From 50e9b77b5df601bdf597fd5ff95f2b03ba726e93 Mon Sep 17 00:00:00 2001 From: johann Date: Wed, 18 Jul 2007 20:56:14 +0000 Subject: [PATCH] Branch b1_6 b=11039 i=adilger i=scjody Remove 2.4 and 2.6.12 kernel patches. --- .../config-linux-2.4.18-p4smp-61chaos | 1035 - .../kernel_configs/config-linux-2.4.20-i386-rh | 1849 - .../kernel-2.4.20-hp_pnnl-2.4-ia64-smp.config | 1047 - .../kernel-2.4.20-hp_pnnl-2.4-ia64.config | 1047 - .../kernel-2.4.20-rh-2.4-i686-smp.config | 1866 - .../kernel-2.4.20-rh-2.4-i686.config | 1866 - .../kernel-2.4.21-rhel-2.4-i686-smp.config | 2139 - .../kernel-2.4.21-rhel-2.4-i686.config | 2139 - .../kernel-2.4.21-rhel-2.4-ia64-smp.config | 1451 - .../kernel-2.4.21-rhel-2.4-ia64.config | 1451 - .../kernel-2.4.21-rhel-2.4-x86_64-smp.config | 1787 - .../kernel-2.4.21-rhel-2.4-x86_64.config | 1787 - .../kernel-2.4.21-sles-2.4-i686-smp.config | 2383 - .../kernel-2.4.21-sles-2.4-i686.config | 2383 - .../kernel-2.4.21-suse-2.4.21-2-x86_64.config | 2042 - .../kernel_configs/uml-vanilla-2.4.24.config | 413 - .../3.5G-address-space-2.4.22-vanilla.patch | 352 - .../kernel_patches/patches/add_page_private.patch | 23 - .../patches/blkdev_tunables-2.4.21-chaos.patch | 52 - .../patches/compile-fixes-2.4.21-rhel.patch | 90 - .../patches/configurable-x86-stack-2.4.20.patch | 318 - .../configurable-x86-stack-2.4.21-chaos.patch | 468 - .../configurable-x86-stack-2.4.21-suse-171.patch | 317 - .../configurable-x86-stack-2.4.21-suse2.patch | 318 - .../patches/configurable-x86_64-2.4.21.patch | 122 - .../patches/dcache_refcount_debug.patch | 24 - .../patches/dev_read_only_2.4.20-rh.patch | 125 - .../patches/dev_read_only_2.4.21-chaos.patch | 122 - .../patches/export-show_task-2.4-cray.patch | 33 - .../patches/export-show_task-2.4-rh.patch | 171 - .../patches/export-show_task-2.4-rhel.patch | 20 - .../patches/export-show_task-2.4-vanilla.patch | 34 - .../kernel_patches/patches/export-truncate.patch | 35 - .../patches/export-zap-page-range.patch | 12 - .../patches/export_num_siblings.patch | 10 - .../patches/exports-2.4.21-chaos.patch | 59 - .../patches/exports_2.4.19-suse.patch | 53 - .../patches/exports_2.4.19-suse2.patch | 59 - .../patches/exports_2.4.20-rh-hp.patch | 53 - .../kernel_patches/patches/ext-2.4-patch-1.patch | 2536 - .../kernel_patches/patches/ext-2.4-patch-2.patch | 34 - .../kernel_patches/patches/ext-2.4-patch-3.patch | 96 - .../kernel_patches/patches/ext-2.4-patch-4.patch | 52 - lustre/kernel_patches/patches/ext3-2.4-ino_t.patch | 144 - .../kernel_patches/patches/ext3-2.4.20-fixes.patch | 118 - .../patches/ext3-delete_thread-2.4.20-hp.patch | 499 - .../patches/ext3-delete_thread-2.4.21-chaos.patch | 449 - .../ext3-delete_thread-2.4.21-suse-171.patch | 496 - .../patches/ext3-delete_thread-2.4.24.patch | 449 - .../patches/ext3-delete_thread-2.4.29.patch | 442 - .../patches/ext3-ea-in-inode-2.4.20.patch | 747 - .../patches/ext3-ea-in-inode-2.4.21-chaos.patch | 758 - .../patches/ext3-ea-in-inode-2.4.21-sles.patch | 758 - .../patches/ext3-ea-in-inode-2.4.21-suse2.patch | 758 - .../patches/ext3-ea-in-inode-2.4.22-rh.patch | 755 - .../patches/ext3-ea-in-inode-2.4.29.patch | 731 - .../kernel_patches/patches/ext3-error-export.patch | 16 - .../patches/ext3-extents-2.4.21-chaos.patch | 2877 - .../patches/ext3-extents-2.4.21-suse2.patch | 2875 - .../patches/ext3-extents-2.4.24.patch | 2863 - .../patches/ext3-extents-2.4.29.patch | 2858 - .../ext3-extents-asyncdel-2.4.21-chaos.patch | 31 - .../patches/ext3-extents-asyncdel-2.4.24.patch | 31 - .../patches/ext3-htree-2.4.21-chaos.patch | 2593 - .../patches/ext3-htree-2.4.21-rhel.patch | 2531 - .../patches/ext3-htree-2.4.22-rh.patch | 2581 - .../kernel_patches/patches/ext3-htree-2.4.29.patch | 2496 - .../patches/ext3-ialloc-2.4.21-suse2.patch | 237 - .../patches/ext3-ialloc-2.4.24.patch | 238 - .../patches/ext3-ino_sb_macro-2.4.21-chaos.patch | 1514 - lustre/kernel_patches/patches/ext3-largefile.patch | 16 - .../patches/ext3-lookup-dotdot-2.4.20.patch | 63 - .../patches/ext3-map_inode_page-2.4.21-suse2.patch | 119 - .../patches/ext3-map_inode_page.patch | 110 - .../patches/ext3-map_inode_page_2.4.18.patch | 110 - .../patches/ext3-nlinks-2.4.20-hp_pnnl.patch | 172 - .../patches/ext3-nlinks-2.4.21-chaos.patch | 172 - .../patches/ext3-nlinks-2.4.24.patch | 172 - .../patches/ext3-no-write-super-chaos.patch | 15 - .../patches/ext3-noread-2.4.20.patch | 218 - .../patches/ext3-noread-2.4.21-chaos.patch | 223 - .../patches/ext3-noread-2.4.21-suse2.patch | 218 - .../patches/ext3-o_direct-2.4.21-chaos.patch | 23 - .../patches/ext3-orphan_lock-2.4.22-rh.patch | 82 - .../kernel_patches/patches/ext3-orphan_lock.patch | 79 - .../kernel_patches/patches/ext3-raw-lookup.patch | 61 - .../kernel_patches/patches/ext3-san-2.4.20.patch | 117 - .../patches/ext3-sector_t-overflow-2.4.patch | 41 - .../patches/ext3-truncate-buffer-head.patch | 10 - .../patches/ext3-truncate_blocks.patch | 92 - .../patches/ext3-trusted_ea-2.4.20.patch | 180 - .../patches/ext3-use-after-free.patch | 53 - .../patches/ext3-xattr-ptr-arith-fix.patch | 18 - .../patches/extN-2.4.18-ino_sb_fixup.patch | 33 - .../kernel_patches/patches/extN-misc-fixup.patch | 20 - .../patches/extN-wantedi-2.4.21-chaos.patch | 213 - .../patches/extN-wantedi-2.4.21-suse2.patch | 226 - lustre/kernel_patches/patches/extN-wantedi.patch | 213 - .../patches/fsprivate-2.4-suse.patch | 10 - lustre/kernel_patches/patches/fsprivate-2.4.patch | 10 - .../patches/gfp_debug-2.4.21-rhel.patch | 77 - .../grab_cache_page_nowait_gfp-2.4.21-suse2.patch | 85 - .../grab_cache_page_nowait_gfp-rh-2.4.patch | 65 - .../patches/inode-max-readahead-2.4.24.patch | 22 - .../patches/invalidate_show-2.4.20-hp.patch | 123 - .../patches/invalidate_show-2.4.20-rh.patch | 114 - .../patches/invalidate_show-2.4.29.patch | 107 - .../kernel_patches/patches/invalidate_show.patch | 112 - .../patches/iod-rmap-exports-2.4.21-chaos.patch | 94 - .../patches/iod-stock-24-exports_hp.patch | 48 - .../patches/iod-stock-exports-2.4.22.patch | 52 - lustre/kernel_patches/patches/iopen-2.4.20.patch | 495 - .../patches/iopen-2.4.21-chaos.patch | 497 - .../patches/jbd-commit-tricks-rhel3.patch | 132 - .../kernel_patches/patches/jbd-commit-tricks.patch | 132 - lustre/kernel_patches/patches/jbd-ctx_switch.patch | 13 - .../patches/jbd-dont-account-blocks-twice.patch | 17 - lustre/kernel_patches/patches/jbd-flushtime.patch | 34 - .../patches/jbd-get_write_access.patch | 56 - .../kernel_patches/patches/kallsyms-2.4.29.patch | 689 - .../patches/linux-2.4.20-xattr-0.8.54-hp.patch | 4875 - .../patches/linux-2.4.21-xattr-0.8.54-chaos.patch | 2172 - .../linux-2.4.21-xattr-0.8.54-suse-171.patch | 276 - .../patches/linux-2.4.21-xattr-0.8.54-suse2.patch | 258 - .../linux-2.4.24-jbd-handle-EIO-rhel3.patch | 23 - .../patches/linux-2.4.24-jbd-handle-EIO.patch | 51 - .../patches/linux-2.4.24-xattr-0.8.54.patch | 5474 -- .../patches/linux-2.4.29-xattr-0.8.54.patch | 5362 -- lustre/kernel_patches/patches/listman-2.4.20.patch | 22 - .../patches/listman-2.4.21-chaos.patch | 26 - .../llnl-frame-pointer-walk-2.4.21-rhel.patch | 120 - .../llnl-frame-pointer-walk-fix-2.4.21-rhel.patch | 249 - .../lookup-stack-symbols-2.4.21-suse-171.patch | 234 - .../patches/loop-sync-2.4.21-suse.patch | 11 - .../patches/netconsole-2.4.24-ppc.patch | 489 - .../patches/nfs-cifs-intent-2.6.12.patch | 128 - .../patches/nfs_export_kernel-2.4.20-hp.patch | 740 - .../patches/nfs_export_kernel-2.4.21-chaos.patch | 756 - .../patches/nfs_export_kernel-2.4.21-suse2.patch | 756 - .../patches/nfs_export_kernel-2.4.22.patch | 745 - .../patches/nfs_export_kernel-2.4.29.patch | 744 - .../patches/nfs_export_kernel-2.4.29.patch-1 | 730 - .../nfs_export_kernel-getattr_on_lookup-2.4.patch | 64 - .../patches/nfs_statfs-toomanyfiles-rhel-2.4.patch | 30 - lustre/kernel_patches/patches/nfsd_iallocsem.patch | 19 - .../patches/pagecache-lock-2.4.21-chaos.patch | 21 - .../patches/procfs-ndynamic-2.4.21-suse2.patch | 16 - .../patches/procfs-ndynamic-2.4.patch | 13 - lustre/kernel_patches/patches/qsnet-rhel-2.4.patch | 93733 ------------------- .../patches/remove-suid-2.4-rhel.patch | 23 - .../kernel_patches/patches/removepage-2.4.20.patch | 28 - .../patches/sd_iostats-2.4.21-chaos.patch | 471 - .../patches/slab-use-after-free-debug-2.4.24.patch | 748 - .../patches/socket-exports-vanilla.patch | 42 - .../patches/statfs64-cast-unsigned-2.4-rhel.patch | 28 - .../patches/uml-2.4.20-do_mmap_pgoff-fix.patch | 16 - .../patches/uml-patch-2.4.24-1.patch | 41972 --------- .../patches/uml-patch-2.4.29-1.patch | 46719 --------- .../patches/uml-sigusr1-2.4-vanilla.patch | 22 - .../patches/vfs_intent-2.4.20-hp.patch | 1948 - .../patches/vfs_intent-2.4.20-vanilla.patch | 1854 - .../patches/vfs_intent-2.4.21-rhel.patch | 1920 - .../patches/vfs_intent-2.4.21-suse-171.patch | 1877 - .../patches/vfs_intent-2.4.21-suse2.patch | 1878 - .../patches/vfs_intent-2.4.29-vanilla.patch | 1833 - .../kernel_patches/patches/vfs_intent-2.6.12.patch | 780 - .../patches/vfs_nointent-2.6.12.patch | 490 - lustre/kernel_patches/series/2.6.12-vanilla.series | 17 - lustre/kernel_patches/series/hp-pnnl-2.4.20 | 49 - lustre/kernel_patches/series/rhel-2.4.21 | 54 - lustre/kernel_patches/series/suse-2.4.21-cray | 43 - lustre/kernel_patches/series/vanilla-2.4.24 | 50 - lustre/kernel_patches/series/vanilla-2.4.29 | 45 - lustre/kernel_patches/series/vanilla-2.4.29-uml | 47 - lustre/kernel_patches/which_patch | 2 - 175 files changed, 290264 deletions(-) delete mode 100644 lustre/kernel_patches/kernel_configs/config-linux-2.4.18-p4smp-61chaos delete mode 100644 lustre/kernel_patches/kernel_configs/config-linux-2.4.20-i386-rh delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64-smp.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686-smp.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686-smp.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64-smp.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64-smp.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686-smp.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686.config delete mode 100644 lustre/kernel_patches/kernel_configs/kernel-2.4.21-suse-2.4.21-2-x86_64.config delete mode 100644 lustre/kernel_patches/kernel_configs/uml-vanilla-2.4.24.config delete mode 100644 lustre/kernel_patches/patches/3.5G-address-space-2.4.22-vanilla.patch delete mode 100644 lustre/kernel_patches/patches/add_page_private.patch delete mode 100644 lustre/kernel_patches/patches/blkdev_tunables-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/compile-fixes-2.4.21-rhel.patch delete mode 100644 lustre/kernel_patches/patches/configurable-x86-stack-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse-171.patch delete mode 100644 lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/configurable-x86_64-2.4.21.patch delete mode 100644 lustre/kernel_patches/patches/dcache_refcount_debug.patch delete mode 100644 lustre/kernel_patches/patches/dev_read_only_2.4.20-rh.patch delete mode 100644 lustre/kernel_patches/patches/dev_read_only_2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/export-show_task-2.4-cray.patch delete mode 100644 lustre/kernel_patches/patches/export-show_task-2.4-rh.patch delete mode 100644 lustre/kernel_patches/patches/export-show_task-2.4-rhel.patch delete mode 100644 lustre/kernel_patches/patches/export-show_task-2.4-vanilla.patch delete mode 100644 lustre/kernel_patches/patches/export-truncate.patch delete mode 100644 lustre/kernel_patches/patches/export-zap-page-range.patch delete mode 100644 lustre/kernel_patches/patches/export_num_siblings.patch delete mode 100644 lustre/kernel_patches/patches/exports-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/exports_2.4.19-suse.patch delete mode 100644 lustre/kernel_patches/patches/exports_2.4.19-suse2.patch delete mode 100644 lustre/kernel_patches/patches/exports_2.4.20-rh-hp.patch delete mode 100644 lustre/kernel_patches/patches/ext-2.4-patch-1.patch delete mode 100644 lustre/kernel_patches/patches/ext-2.4-patch-2.patch delete mode 100644 lustre/kernel_patches/patches/ext-2.4-patch-3.patch delete mode 100644 lustre/kernel_patches/patches/ext-2.4-patch-4.patch delete mode 100644 lustre/kernel_patches/patches/ext3-2.4-ino_t.patch delete mode 100644 lustre/kernel_patches/patches/ext3-2.4.20-fixes.patch delete mode 100644 lustre/kernel_patches/patches/ext3-delete_thread-2.4.20-hp.patch delete mode 100644 lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-suse-171.patch delete mode 100644 lustre/kernel_patches/patches/ext3-delete_thread-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/ext3-delete_thread-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-sles.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.22-rh.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/ext3-error-export.patch delete mode 100644 lustre/kernel_patches/patches/ext3-extents-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-extents-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/ext3-extents-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/ext3-extents-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/ext3-htree-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-htree-2.4.21-rhel.patch delete mode 100644 lustre/kernel_patches/patches/ext3-htree-2.4.22-rh.patch delete mode 100644 lustre/kernel_patches/patches/ext3-htree-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ialloc-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ialloc-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/ext3-ino_sb_macro-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-largefile.patch delete mode 100644 lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/ext3-map_inode_page-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/ext3-map_inode_page.patch delete mode 100644 lustre/kernel_patches/patches/ext3-map_inode_page_2.4.18.patch delete mode 100644 lustre/kernel_patches/patches/ext3-nlinks-2.4.20-hp_pnnl.patch delete mode 100644 lustre/kernel_patches/patches/ext3-nlinks-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-nlinks-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/ext3-no-write-super-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-noread-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/ext3-noread-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-noread-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/ext3-o_direct-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/ext3-orphan_lock-2.4.22-rh.patch delete mode 100644 lustre/kernel_patches/patches/ext3-orphan_lock.patch delete mode 100644 lustre/kernel_patches/patches/ext3-raw-lookup.patch delete mode 100644 lustre/kernel_patches/patches/ext3-san-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch delete mode 100644 lustre/kernel_patches/patches/ext3-truncate-buffer-head.patch delete mode 100644 lustre/kernel_patches/patches/ext3-truncate_blocks.patch delete mode 100644 lustre/kernel_patches/patches/ext3-trusted_ea-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/ext3-use-after-free.patch delete mode 100644 lustre/kernel_patches/patches/ext3-xattr-ptr-arith-fix.patch delete mode 100644 lustre/kernel_patches/patches/extN-2.4.18-ino_sb_fixup.patch delete mode 100644 lustre/kernel_patches/patches/extN-misc-fixup.patch delete mode 100644 lustre/kernel_patches/patches/extN-wantedi-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/extN-wantedi-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/extN-wantedi.patch delete mode 100644 lustre/kernel_patches/patches/fsprivate-2.4-suse.patch delete mode 100644 lustre/kernel_patches/patches/fsprivate-2.4.patch delete mode 100644 lustre/kernel_patches/patches/gfp_debug-2.4.21-rhel.patch delete mode 100644 lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-rh-2.4.patch delete mode 100644 lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/invalidate_show-2.4.20-hp.patch delete mode 100644 lustre/kernel_patches/patches/invalidate_show-2.4.20-rh.patch delete mode 100644 lustre/kernel_patches/patches/invalidate_show-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/invalidate_show.patch delete mode 100644 lustre/kernel_patches/patches/iod-rmap-exports-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/iod-stock-24-exports_hp.patch delete mode 100644 lustre/kernel_patches/patches/iod-stock-exports-2.4.22.patch delete mode 100644 lustre/kernel_patches/patches/iopen-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/jbd-commit-tricks-rhel3.patch delete mode 100644 lustre/kernel_patches/patches/jbd-commit-tricks.patch delete mode 100644 lustre/kernel_patches/patches/jbd-ctx_switch.patch delete mode 100644 lustre/kernel_patches/patches/jbd-dont-account-blocks-twice.patch delete mode 100644 lustre/kernel_patches/patches/jbd-flushtime.patch delete mode 100644 lustre/kernel_patches/patches/jbd-get_write_access.patch delete mode 100644 lustre/kernel_patches/patches/kallsyms-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.20-xattr-0.8.54-hp.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-chaos.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse-171.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse2.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO-rhel3.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.24-xattr-0.8.54.patch delete mode 100644 lustre/kernel_patches/patches/linux-2.4.29-xattr-0.8.54.patch delete mode 100644 lustre/kernel_patches/patches/listman-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/listman-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/llnl-frame-pointer-walk-2.4.21-rhel.patch delete mode 100644 lustre/kernel_patches/patches/llnl-frame-pointer-walk-fix-2.4.21-rhel.patch delete mode 100644 lustre/kernel_patches/patches/lookup-stack-symbols-2.4.21-suse-171.patch delete mode 100644 lustre/kernel_patches/patches/loop-sync-2.4.21-suse.patch delete mode 100644 lustre/kernel_patches/patches/netconsole-2.4.24-ppc.patch delete mode 100644 lustre/kernel_patches/patches/nfs-cifs-intent-2.6.12.patch delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch-1 delete mode 100644 lustre/kernel_patches/patches/nfs_export_kernel-getattr_on_lookup-2.4.patch delete mode 100644 lustre/kernel_patches/patches/nfs_statfs-toomanyfiles-rhel-2.4.patch delete mode 100644 lustre/kernel_patches/patches/nfsd_iallocsem.patch delete mode 100644 lustre/kernel_patches/patches/pagecache-lock-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/procfs-ndynamic-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/procfs-ndynamic-2.4.patch delete mode 100644 lustre/kernel_patches/patches/qsnet-rhel-2.4.patch delete mode 100644 lustre/kernel_patches/patches/remove-suid-2.4-rhel.patch delete mode 100644 lustre/kernel_patches/patches/removepage-2.4.20.patch delete mode 100644 lustre/kernel_patches/patches/sd_iostats-2.4.21-chaos.patch delete mode 100644 lustre/kernel_patches/patches/slab-use-after-free-debug-2.4.24.patch delete mode 100644 lustre/kernel_patches/patches/socket-exports-vanilla.patch delete mode 100644 lustre/kernel_patches/patches/statfs64-cast-unsigned-2.4-rhel.patch delete mode 100644 lustre/kernel_patches/patches/uml-2.4.20-do_mmap_pgoff-fix.patch delete mode 100644 lustre/kernel_patches/patches/uml-patch-2.4.24-1.patch delete mode 100644 lustre/kernel_patches/patches/uml-patch-2.4.29-1.patch delete mode 100644 lustre/kernel_patches/patches/uml-sigusr1-2.4-vanilla.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.4.21-rhel.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.4.21-suse-171.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.4.29-vanilla.patch delete mode 100644 lustre/kernel_patches/patches/vfs_intent-2.6.12.patch delete mode 100644 lustre/kernel_patches/patches/vfs_nointent-2.6.12.patch delete mode 100644 lustre/kernel_patches/series/2.6.12-vanilla.series delete mode 100644 lustre/kernel_patches/series/hp-pnnl-2.4.20 delete mode 100644 lustre/kernel_patches/series/rhel-2.4.21 delete mode 100644 lustre/kernel_patches/series/suse-2.4.21-cray delete mode 100644 lustre/kernel_patches/series/vanilla-2.4.24 delete mode 100644 lustre/kernel_patches/series/vanilla-2.4.29 delete mode 100644 lustre/kernel_patches/series/vanilla-2.4.29-uml diff --git a/lustre/kernel_patches/kernel_configs/config-linux-2.4.18-p4smp-61chaos b/lustre/kernel_patches/kernel_configs/config-linux-2.4.18-p4smp-61chaos deleted file mode 100644 index 0de1146..0000000 --- a/lustre/kernel_patches/kernel_configs/config-linux-2.4.18-p4smp-61chaos +++ /dev/null @@ -1,1035 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86=y -CONFIG_ISA=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -CONFIG_LOLAT=y -# CONFIG_LOLAT_SYSCTL is not set -# 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_MPENTIUMIII is not set -CONFIG_MPENTIUM4=y -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_MCE=y -# CONFIG_CPU_FREQ is not set -# CONFIG_TOSHIBA is not set -# CONFIG_I8K is not set -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_E820_PROC is not set -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -# CONFIG_HIGHMEM64G is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHIO=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -# CONFIG_MULTIQUAD is not set -CONFIG_HAVE_DEC_LOCK=y - -# -# General setup -# -CONFIG_HZ=100 -CONFIG_NET=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_NAMES=y - -# -# Performance-monitoring counters support -# -CONFIG_PERFCTR=m -CONFIG_KPERFCTR=y -# CONFIG_PERFCTR_DEBUG is not set -# CONFIG_PERFCTR_INIT_TESTS is not set -CONFIG_PERFCTR_VIRTUAL=y -CONFIG_PERFCTR_GLOBAL=y -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -# CONFIG_HOTPLUG_PCI is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -# CONFIG_IKCONFIG is not set -CONFIG_PM=y - -# -# Additional device driver support -# -# CONFIG_CIPE is not set -# CONFIG_CRYPTO_AEP is not set -# CONFIG_MEGARAC is not set -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -# CONFIG_SCSI_ISCSI is not set -CONFIG_IBMASM=m -CONFIG_IBMSER=m -# CONFIG_ACPI is not set -CONFIG_APM=y -CONFIG_APM_IGNORE_USER_SUSPEND=y -# CONFIG_APM_DO_ENABLE is not set -# CONFIG_APM_CPU_IDLE is not set -# CONFIG_APM_DISPLAY_BLANK is not set -CONFIG_APM_RTC_IS_GMT=y -# CONFIG_APM_ALLOW_INTS is not set -# CONFIG_APM_REAL_MODE_POWER_OFF is not set - -# -# Binary emulation of other systems -# -# CONFIG_ABI is not set -# CONFIG_ABI_SVR4 is not set -# CONFIG_BINFMT_COFF is not set -# CONFIG_BINFMT_XOUT is not set -# CONFIG_BINFMT_XOUT_X286 is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_CHAR=m -# CONFIG_MTD_BLOCK is not set -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_FTL is not set -# CONFIG_NFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -# CONFIG_MTD_CFI is not set -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -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_CFI_B1=y -# CONFIG_MTD_CFI_B2 is not set -# CONFIG_MTD_CFI_B4 is not set -# CONFIG_MTD_CFI_B8 is not set -CONFIG_MTD_CFI_I1=y -# CONFIG_MTD_CFI_I2 is not set -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_RAM is not set -CONFIG_MTD_ROM=y -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PNC2000 is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_NETSC520 is not set -# CONFIG_MTD_SBC_GXX is not set -# CONFIG_MTD_ELAN_104NC is not set -# CONFIG_MTD_DILNETPC is not set -# CONFIG_MTD_MIXMEM is not set -# CONFIG_MTD_OCTAGON is not set -# CONFIG_MTD_VMAX is not set -# CONFIG_MTD_L440GX is not set -# CONFIG_MTD_AMD766ROM is not set -CONFIG_MTD_ICH2ROM=m -# CONFIG_MTD_PCI is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=y -# CONFIG_PNPBIOS is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_ENBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -CONFIG_BLK_DEV_LVM=m - -# -# Cryptography support (CryptoAPI) -# -# CONFIG_CRYPTO is not set -# CONFIG_CIPHERS is not set -# CONFIG_CRYPTODEV is not set -# CONFIG_CRYPTOLOOP is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_TUX is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -# CONFIG_IP_NF_FTP is not set -# CONFIG_IP_NF_IRC is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -# CONFIG_IPV6 is not set -CONFIG_KHTTPD=m -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -CONFIG_NET_PKTGEN=m - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=m -# CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_IDEFLOPPY=y -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_ISAPNP=y -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -CONFIG_BLK_DEV_ADMA=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_AEC62XX_TUNING=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_CMD680=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_PIIX_TUNING=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_ADMA100 is not set -CONFIG_BLK_DEV_PDC202XX=y -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_FORCE is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -CONFIG_BLK_DEV_CENATEK=y -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_DEV_ELEVATOR_NOOP is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_IDE_MODES=y -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -CONFIG_SCSI_AIC7XXX=y -CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_NEWISP is not set -# CONFIG_SCSI_SEAGATE is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -CONFIG_SCSI_DEBUG=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=y -CONFIG_FUSION_BOOT=y -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -# CONFIG_FUSION_LAN is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set -# CONFIG_NET_SB1000 is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -CONFIG_TULIP=m -# CONFIG_TC35815 is not set -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=m -CONFIG_NET_E100=m -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_NEW_RX_RESET is not set -# CONFIG_SIS900 is not set -# CONFIG_SIS900_OLD is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -CONFIG_NET_BROADCOM=m -CONFIG_TIGON3=m -CONFIG_NET_E1000=m -# CONFIG_FDDI is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Quadrics Supercomputers -# - -# -# QsNet -# -CONFIG_QUADRICS=y -CONFIG_QSNETMOD=m -CONFIG_ELAN3MOD=m -CONFIG_EPMOD=m -CONFIG_EIPMOD=m -CONFIG_RMSMOD=m -CONFIG_JTAG=m - -# -# QsNet II -# - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set -CONFIG_KALLSYMS=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set - -# -# Character devices -# -CONFIG_ECC=m -CONFIG_CHAOSTEST=m -CONFIG_P4THERM=m -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -# CONFIG_SERIAL_MANY_PORTS is not set -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -# CONFIG_SERIAL_MULTIPORT is not set -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -CONFIG_I2C=y -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_MAINBOARD=y -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_HYDRA is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_TSUNAMI is not set -CONFIG_I2C_I801=m -# CONFIG_I2C_I810 is not set -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VOODOO3 is not set -CONFIG_I2C_ISA=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_PROC=y - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -# CONFIG_SENSORS_ADM1024 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_FSCPOS is not set -# CONFIG_SENSORS_FSCSCY is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_MAXILIFE is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_MTP008 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -CONFIG_SENSORS_LM87=m -# CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VIA686A is not set -CONFIG_SENSORS_W83781D=y -# CONFIG_SENSORS_OTHER is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_AMD_RNG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -# CONFIG_AGP_I810 is not set -# CONFIG_AGP_VIA is not set -# CONFIG_AGP_AMD is not set -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_SWORKS is not set -# CONFIG_DRM is not set -# CONFIG_MWAVE is not set -# CONFIG_BATTERY_GERICOM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Crypto Hardware support -# -# CONFIG_CRYPTO is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_AFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_EXTN_FS=m -CONFIG_JBD=y -CONFIG_JBD_DEBUG=y -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_PFS_FS is not set -CONFIG_ZISOFS_FS=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_SMB_NLS is not set -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=m -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=m -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -# CONFIG_VIDEO_IGNORE_BAD_MODE is not set -# CONFIG_MDA_CONSOLE is not set - -# -# Frame-buffer support -# -# CONFIG_FB is not set -# CONFIG_SPEAKUP is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Bluetooth support -# -# CONFIG_BLUEZ is not set - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_FRAME_POINTER=y -CONFIG_STACK_TRACE_SCAN=y -CONFIG_STACK_TRACE_FPTR=y -CONFIG_STACK_TRACE_PARAM_COUNT=4 -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_MCL_COREDUMP=y -CONFIG_BOOTIMG=y -# CONFIG_OPROFILE is not set - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/lustre/kernel_patches/kernel_configs/config-linux-2.4.20-i386-rh b/lustre/kernel_patches/kernel_configs/config-linux-2.4.20-i386-rh deleted file mode 100644 index dec210a..0000000 --- a/lustre/kernel_patches/kernel_configs/config-linux-2.4.20-i386-rh +++ /dev/null @@ -1,1849 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -CONFIG_LOLAT=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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_24_API is not set -CONFIG_X86_POWERNOW_K6=m -# CONFIG_X86_LONGHAUL is not set -CONFIG_X86_SPEEDSTEP=m -# CONFIG_X86_P4_CLOCKMOD is not set -# CONFIG_X86_LONGRUN is not set -CONFIG_TOSHIBA=m -CONFIG_I8K=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_E820_PROC is not set -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -# CONFIG_HIGHMEM64G is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HIGHIO=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -# CONFIG_SMP is not set -CONFIG_X86_UP_APIC=y -CONFIG_X86_UP_IOAPIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_X86_IO_APIC=y -# CONFIG_X86_TSC_DISABLE is not set -CONFIG_X86_TSC=y - -# -# General setup -# -CONFIG_NET=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_IBM is not set -# CONFIG_HOTPLUG_PCI_H2999 is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_PM=y -# CONFIG_ACPI is not set -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -CONFIG_APM_RTC_IS_GMT=y -# CONFIG_APM_ALLOW_INTS is not set -# CONFIG_APM_REAL_MODE_POWER_OFF is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=y - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_XD=m -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=m -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m -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_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Cryptography support (CryptoAPI) -# -CONFIG_CRYPTO=m -CONFIG_CIPHERS=m -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_IDENTITY=m -CONFIG_CRYPTODEV=m -CONFIG_CRYPTOLOOP=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IPV6=m - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_ISAPNP=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_BLK_DEV_NFORCE=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=253 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -CONFIG_AIC79XX_ENABLE_RD_STRM=y -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=m -CONFIG_SCSI_EATA=m -CONFIG_SCSI_EATA_TAGGED_QUEUE=y -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -# CONFIG_SCSI_GENERIC_NCR53C400 is not set -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -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_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_NEWISP=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m -# CONFIG_IEEE1394_PCILYNX is not set -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -CONFIG_EWRK3=m -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -CONFIG_SUNDANCE_MMIO=y -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=m -# CONFIG_HIPPI is not set -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 is not set -# CONFIG_PPPOE is not set -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y -CONFIG_PCMCIA_HERMES_OLD=m - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -CONFIG_TMSISA=m -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -CONFIG_RCPCI=m -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_WVLAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y -CONFIG_AX25=m -# CONFIG_AX25_DAMA_SLAVE is not set -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -# CONFIG_YAM is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y -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 -CONFIG_HISAX_16_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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=y -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_KALLSYMS=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_COMPUTONE=m -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -# CONFIG_RIO is not set -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -# CONFIG_SCx200_I2C is not set -# CONFIG_SCx200_ACB is not set -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -# CONFIG_I2C_TSUNAMI is not set -CONFIG_I2C_I801=m -CONFIG_I2C_I810=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=m -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -CONFIG_AMD7XX_TCO=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set -CONFIG_SONYPI=m - -# -# Ftape, the floppy tape device driver -# -CONFIG_FTAPE=m -CONFIG_ZFTAPE=m -CONFIG_ZFT_DFLT_BLK_SZ=10240 -CONFIG_ZFT_COMPRESSOR=m -CONFIG_FT_NR_BUFFERS=3 -# CONFIG_FT_PROC_FS is not set -CONFIG_FT_NORMAL_DEBUG=y -# CONFIG_FT_FULL_DEBUG is not set -# CONFIG_FT_NO_TRACE is not set -# CONFIG_FT_NO_TRACE_AT_ALL is not set -CONFIG_FT_STD_FDC=y -# CONFIG_FT_MACH2 is not set -# CONFIG_FT_PROBE_FC10 is not set -# CONFIG_FT_ALT_FDC is not set -CONFIG_FT_FDC_THR=8 -CONFIG_FT_FDC_MAX_RATE=2000 -CONFIG_FT_ALPHA_CLOCK=0 -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -CONFIG_DRM_SIS=m - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m -CONFIG_BATTERY_GERICOM=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -CONFIG_VIDEO_MEYE=m - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m - -# -# Crypto Hardware support -# -CONFIG_CRYPTO=m -CONFIG_CRYPTO_BROADCOM=m - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -CONFIG_AFS_FS=m -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_INTERMEZZO_FS=m -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -# CONFIG_VIDEO_IGNORE_BAD_MODE is not set -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G450 is not set -CONFIG_FB_MATROX_G100A=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_SIS=m -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -CONFIG_SOUND_MSNDCLAS=m -# CONFIG_MSNDCLAS_HAVE_BOOT is not set -CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" -CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" -CONFIG_SOUND_MSNDPIN=m -# CONFIG_MSNDPIN_HAVE_BOOT is not set -CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" -CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -CONFIG_SOUND_GUS16=y -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -# CONFIG_PSS_MIXER is not set -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_POWERMATE=m -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -CONFIG_CRYPTO_AEP=m -CONFIG_MEGARAC=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_FRAME_POINTER is not set -CONFIG_MCL_COREDUMP=y -CONFIG_BOOTIMG=y - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64-smp.config deleted file mode 100644 index 4446f20..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64-smp.config +++ /dev/null @@ -1,1047 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_IA64=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y -# CONFIG_IA64_GENERIC is not set -# CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_SIM is not set -CONFIG_IA64_HP_ZX1=y -# CONFIG_IA64_SGI_SN1 is not set -# CONFIG_IA64_SGI_SN2 is not set -# CONFIG_IA64_PAGE_SIZE_4KB is not set -CONFIG_IA64_PAGE_SIZE_8KB=y -# CONFIG_IA64_PAGE_SIZE_16KB is not set -# CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_IA64_L1_CACHE_SHIFT=7 -CONFIG_IA64_MCA=y -CONFIG_PM=y -CONFIG_KCORE_ELF=y -CONFIG_IA64_PAL_IDLE=y -CONFIG_SMP=y -CONFIG_IA32_SUPPORT=y -CONFIG_PERFMON=y -CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m - -# -# Misc devices -# -# CONFIG_BMC is not set -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_KERNEL_CONFIG=y - -# -# ACPI Support -# -CONFIG_ACPI_PCI=y -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_DEBUG is not set -CONFIG_PCI=y -CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -# CONFIG_IP_NF_MATCH_AH_ESP is not set -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -# CONFIG_IP_NF_TARGET_ULOG is not set -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=65536 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_STATS is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=y -CONFIG_MD_RAID0=y -CONFIG_MD_RAID1=y -CONFIG_MD_RAID5=y -CONFIG_MD_MULTIPATH=y -CONFIG_BLK_DEV_LVM=y - -# -# Fusion MPT device support -# -CONFIG_FUSION=y -CONFIG_FUSION_BOOT=y -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=y -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -# CONFIG_BLK_DEV_CMD680 is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set -# CONFIG_BLK_DEV_HPT366 is not set -CONFIG_BLK_DEV_PIIX=y -CONFIG_PIIX_TUNING=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_FORCE is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_IDE_MODES=y -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -CONFIG_CHR_DEV_OSST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=y -CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -CONFIG_SCSI_MEGARAID=y -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -CONFIG_SCSI_SYM53C8XX_2=y -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLOGIC_QLA2XXX=y -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -# CONFIG_TULIP is not set -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=y -# CONFIG_E100 is not set -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_SUNDANCE_MMIO is not set -# CONFIG_TLAN is not set -# CONFIG_TC35815 is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -CONFIG_ACENIC_OMIT_TIGON_I=y -# CONFIG_DL2K is not set -CONFIG_E1000=y -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -CONFIG_TIGON3=y - -# -# Quadrics QsNet -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_EP3=m -CONFIG_EIP=m -CONFIG_ELAN4=m -CONFIG_RMS=m -CONFIG_JTAG=m -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=y -CONFIG_INPUT_KEYBDEV=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_HCDP=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_ACPI=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -# CONFIG_I2C_PHILIPSPAR is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_INPUT_SERIO is not set -# CONFIG_INPUT_SERPORT is not set - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -CONFIG_XFS_FS=y -# CONFIG_XFS_POSIX_ACL is not set -CONFIG_XFS_RT=y -# CONFIG_XFS_QUOTA is not set -CONFIG_XFS_DMAPI=y -# CONFIG_XFS_DEBUG is not set -CONFIG_PAGEBUF_DEBUG=y - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set -CONFIG_FS_MBCACHE=y - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -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 is not set -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=y -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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y - -# -# Frame-buffer support -# -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_UHCI_ALT=y -CONFIG_USB_OHCI=y - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_MIDI is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_BRLVGER is not set -# CONFIG_USB_LCD is not set - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -# CONFIG_ZLIB_DEFLATE is not set - -# -# Bluetooth support -# -# CONFIG_BLUEZ is not set - -# -# Kernel hacking -# -# CONFIG_IA64_GRANULE_16MB is not set -CONFIG_IA64_GRANULE_64MB=y -CONFIG_DUMP=m -CONFIG_DUMP_COMPRESS_RLE=m -CONFIG_DUMP_COMPRESS_GZIP=m -CONFIG_DEBUG_KERNEL=y -# CONFIG_IA64_PRINT_HAZARDS is not set -# CONFIG_DISABLE_VHPT is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_IA64_EARLY_PRINTK=y -CONFIG_IA64_EARLY_PRINTK_UART=y -CONFIG_IA64_EARLY_PRINTK_UART_BASE=0 -# CONFIG_IA64_EARLY_PRINTK_VGA is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_IA64_DEBUG_CMPXCHG is not set -# CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_KALLSYMS=y -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64.config deleted file mode 100644 index 8ba58df..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-hp_pnnl-2.4-ia64.config +++ /dev/null @@ -1,1047 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_IA64=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y -# CONFIG_IA64_GENERIC is not set -# CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_SIM is not set -CONFIG_IA64_HP_ZX1=y -# CONFIG_IA64_SGI_SN1 is not set -# CONFIG_IA64_SGI_SN2 is not set -# CONFIG_IA64_PAGE_SIZE_4KB is not set -CONFIG_IA64_PAGE_SIZE_8KB=y -# CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_IA64_L1_CACHE_SHIFT=7 -CONFIG_IA64_MCA=y -CONFIG_PM=y -CONFIG_KCORE_ELF=y -CONFIG_IA64_PAL_IDLE=y -# CONFIG_SMP is not set -CONFIG_IA32_SUPPORT=y -CONFIG_PERFMON=y -CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m - -# -# Misc devices -# -# CONFIG_BMC is not set -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_KERNEL_CONFIG=y - -# -# ACPI Support -# -CONFIG_ACPI_PCI=y -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_DEBUG is not set -CONFIG_PCI=y -CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -# CONFIG_IP_NF_MATCH_AH_ESP is not set -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -# CONFIG_IP_NF_TARGET_ULOG is not set -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=65536 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_STATS is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=y -CONFIG_MD_RAID0=y -CONFIG_MD_RAID1=y -CONFIG_MD_RAID5=y -CONFIG_MD_MULTIPATH=y -CONFIG_BLK_DEV_LVM=y - -# -# Fusion MPT device support -# -CONFIG_FUSION=y -CONFIG_FUSION_BOOT=y -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set -# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set -# CONFIG_BLK_DEV_IDEDISK_IBM is not set -# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set -# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set -# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set -# CONFIG_BLK_DEV_IDEDISK_WD is not set -# CONFIG_BLK_DEV_COMMERIAL is not set -# CONFIG_BLK_DEV_TIVO is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=y -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -# CONFIG_BLK_DEV_CMD680 is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set -# CONFIG_BLK_DEV_HPT366 is not set -CONFIG_BLK_DEV_PIIX=y -CONFIG_PIIX_TUNING=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_FORCE is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_IDE_MODES=y -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -CONFIG_CHR_DEV_OSST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=y -CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -CONFIG_SCSI_MEGARAID=y -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -CONFIG_SCSI_SYM53C8XX_2=y -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLOGIC_QLA2XXX=y -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -# CONFIG_TULIP is not set -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=y -# CONFIG_E100 is not set -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_SUNDANCE_MMIO is not set -# CONFIG_TLAN is not set -# CONFIG_TC35815 is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -CONFIG_ACENIC_OMIT_TIGON_I=y -# CONFIG_DL2K is not set -CONFIG_E1000=y -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -CONFIG_TIGON3=y - -# -# Quadrics QsNet -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_EP3=m -CONFIG_EIP=m -CONFIG_ELAN4=m -CONFIG_RMS=m -CONFIG_JTAG=m -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=y -CONFIG_INPUT_KEYBDEV=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_HCDP=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_ACPI=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -# CONFIG_I2C_PHILIPSPAR is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_INPUT_SERIO is not set -# CONFIG_INPUT_SERPORT is not set - -# -# Joysticks -# -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -CONFIG_XFS_FS=y -# CONFIG_XFS_POSIX_ACL is not set -CONFIG_XFS_RT=y -# CONFIG_XFS_QUOTA is not set -CONFIG_XFS_DMAPI=y -# CONFIG_XFS_DEBUG is not set -CONFIG_PAGEBUF_DEBUG=y - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set -CONFIG_FS_MBCACHE=y - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -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 is not set -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ISO8859_1=y -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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y - -# -# Frame-buffer support -# -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_LONG_TIMEOUT is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_UHCI_ALT=y -CONFIG_USB_OHCI=y - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_MIDI is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network adaptors -# -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_TIGL is not set -# CONFIG_USB_BRLVGER is not set -# CONFIG_USB_LCD is not set - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -# CONFIG_ZLIB_DEFLATE is not set - -# -# Bluetooth support -# -# CONFIG_BLUEZ is not set - -# -# Kernel hacking -# -# CONFIG_IA64_GRANULE_16MB is not set -CONFIG_IA64_GRANULE_64MB=y -CONFIG_DUMP=m -CONFIG_DUMP_COMPRESS_RLE=m -CONFIG_DUMP_COMPRESS_GZIP=m -CONFIG_DEBUG_KERNEL=y -# CONFIG_IA64_PRINT_HAZARDS is not set -# CONFIG_DISABLE_VHPT is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_IA64_EARLY_PRINTK=y -CONFIG_IA64_EARLY_PRINTK_UART=y -CONFIG_IA64_EARLY_PRINTK_UART_BASE=0 -# CONFIG_IA64_EARLY_PRINTK_VGA is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_IA64_DEBUG_CMPXCHG is not set -# CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_KALLSYMS=y -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686-smp.config deleted file mode 100644 index 1103250..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686-smp.config +++ /dev/null @@ -1,1866 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -CONFIG_LOLAT=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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set -CONFIG_TOSHIBA=m -CONFIG_I8K=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_E820_PROC is not set -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -# CONFIG_HIGHMEM64G is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HIGHIO=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -# CONFIG_X86_NUMA is not set -# CONFIG_X86_TSC_DISABLE is not set -CONFIG_X86_TSC=y -CONFIG_HAVE_DEC_LOCK=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -CONFIG_NET=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=y -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_H2999 is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_PM=y -# CONFIG_ACPI is not set -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -CONFIG_APM_RTC_IS_GMT=y -# CONFIG_APM_ALLOW_INTS is not set -# CONFIG_APM_REAL_MODE_POWER_OFF is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=y - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_XD=m -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=m -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m -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_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Cryptography support (CryptoAPI) -# -CONFIG_CRYPTO=m -CONFIG_CIPHERS=m -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_IDENTITY=m -CONFIG_CRYPTODEV=m -CONFIG_CRYPTOLOOP=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IPV6=m - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_ISAPNP=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=m -CONFIG_SCSI_EATA=m -CONFIG_SCSI_EATA_TAGGED_QUEUE=y -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -# CONFIG_SCSI_GENERIC_NCR53C400 is not set -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -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_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_NEWISP=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -# CONFIG_EWRK3 is not set -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=m -# CONFIG_HIPPI is not set -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 is not set -CONFIG_PPPOE=m -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y -CONFIG_PCMCIA_HERMES_OLD=m - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -CONFIG_TMSISA=m -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -CONFIG_RCPCI=m -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_WVLAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y -CONFIG_AX25=m -# CONFIG_AX25_DAMA_SLAVE is not set -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -# CONFIG_YAM is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y -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 -CONFIG_HISAX_16_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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=y -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_KALLSYMS=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_COMPUTONE=m -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -# CONFIG_RIO is not set -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -# CONFIG_SCx200_I2C is not set -# CONFIG_SCx200_ACB is not set -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -# CONFIG_I2C_TSUNAMI is not set -CONFIG_I2C_I801=m -# CONFIG_I2C_I810 is not set -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=m -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -CONFIG_AMD7XX_TCO=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set -CONFIG_SONYPI=m - -# -# Ftape, the floppy tape device driver -# -CONFIG_FTAPE=m -CONFIG_ZFTAPE=m -CONFIG_ZFT_DFLT_BLK_SZ=10240 -CONFIG_ZFT_COMPRESSOR=m -CONFIG_FT_NR_BUFFERS=3 -# CONFIG_FT_PROC_FS is not set -CONFIG_FT_NORMAL_DEBUG=y -# CONFIG_FT_FULL_DEBUG is not set -# CONFIG_FT_NO_TRACE is not set -# CONFIG_FT_NO_TRACE_AT_ALL is not set -CONFIG_FT_STD_FDC=y -# CONFIG_FT_MACH2 is not set -# CONFIG_FT_PROBE_FC10 is not set -# CONFIG_FT_ALT_FDC is not set -CONFIG_FT_FDC_THR=8 -CONFIG_FT_FDC_MAX_RATE=2000 -CONFIG_FT_ALPHA_CLOCK=0 -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m -CONFIG_BATTERY_GERICOM=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -CONFIG_VIDEO_MEYE=m - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m - -# -# Crypto Hardware support -# -CONFIG_CRYPTO=m -CONFIG_CRYPTO_BROADCOM=m - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -CONFIG_AFS_FS=m -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_INTERMEZZO_FS=m -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -# CONFIG_VIDEO_IGNORE_BAD_MODE is not set -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G450 is not set -CONFIG_FB_MATROX_G100A=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_SIS=m -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -CONFIG_SOUND_MSNDCLAS=m -# CONFIG_MSNDCLAS_HAVE_BOOT is not set -CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" -CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" -CONFIG_SOUND_MSNDPIN=m -# CONFIG_MSNDPIN_HAVE_BOOT is not set -CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" -CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -CONFIG_SOUND_GUS16=y -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -# CONFIG_PSS_MIXER is not set -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -CONFIG_CRYPTO_AEP=m -CONFIG_MEGARAC=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_FRAME_POINTER=y -# CONFIG_MCL_COREDUMP is not set - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686.config deleted file mode 100644 index 1103250..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.20-rh-2.4-i686.config +++ /dev/null @@ -1,1866 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -CONFIG_LOLAT=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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set -CONFIG_TOSHIBA=m -CONFIG_I8K=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_E820_PROC is not set -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -CONFIG_HIGHMEM4G=y -# CONFIG_HIGHMEM64G is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HIGHIO=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -# CONFIG_X86_NUMA is not set -# CONFIG_X86_TSC_DISABLE is not set -CONFIG_X86_TSC=y -CONFIG_HAVE_DEC_LOCK=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -CONFIG_NET=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=y -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_H2999 is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_PM=y -# CONFIG_ACPI is not set -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -CONFIG_APM_RTC_IS_GMT=y -# CONFIG_APM_ALLOW_INTS is not set -# CONFIG_APM_REAL_MODE_POWER_OFF is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=y - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_XD=m -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=m -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m -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_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Cryptography support (CryptoAPI) -# -CONFIG_CRYPTO=m -CONFIG_CIPHERS=m -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_IDENTITY=m -CONFIG_CRYPTODEV=m -CONFIG_CRYPTOLOOP=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IPV6=m - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_ISAPNP=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=m -CONFIG_SCSI_EATA=m -CONFIG_SCSI_EATA_TAGGED_QUEUE=y -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -# CONFIG_SCSI_GENERIC_NCR53C400 is not set -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -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_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_NEWISP=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -# CONFIG_EWRK3 is not set -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=m -# CONFIG_HIPPI is not set -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 is not set -CONFIG_PPPOE=m -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y -CONFIG_PCMCIA_HERMES_OLD=m - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -CONFIG_TMSISA=m -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -CONFIG_RCPCI=m -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_WVLAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y -CONFIG_AX25=m -# CONFIG_AX25_DAMA_SLAVE is not set -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -# CONFIG_YAM is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y -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 -CONFIG_HISAX_16_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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=y -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_KALLSYMS=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_COMPUTONE=m -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -# CONFIG_RIO is not set -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -# CONFIG_SCx200_I2C is not set -# CONFIG_SCx200_ACB is not set -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -# CONFIG_I2C_TSUNAMI is not set -CONFIG_I2C_I801=m -# CONFIG_I2C_I810 is not set -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=m -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -CONFIG_AMD7XX_TCO=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set -CONFIG_SONYPI=m - -# -# Ftape, the floppy tape device driver -# -CONFIG_FTAPE=m -CONFIG_ZFTAPE=m -CONFIG_ZFT_DFLT_BLK_SZ=10240 -CONFIG_ZFT_COMPRESSOR=m -CONFIG_FT_NR_BUFFERS=3 -# CONFIG_FT_PROC_FS is not set -CONFIG_FT_NORMAL_DEBUG=y -# CONFIG_FT_FULL_DEBUG is not set -# CONFIG_FT_NO_TRACE is not set -# CONFIG_FT_NO_TRACE_AT_ALL is not set -CONFIG_FT_STD_FDC=y -# CONFIG_FT_MACH2 is not set -# CONFIG_FT_PROBE_FC10 is not set -# CONFIG_FT_ALT_FDC is not set -CONFIG_FT_FDC_THR=8 -CONFIG_FT_FDC_MAX_RATE=2000 -CONFIG_FT_ALPHA_CLOCK=0 -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m -CONFIG_BATTERY_GERICOM=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -CONFIG_VIDEO_MEYE=m - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m - -# -# Crypto Hardware support -# -CONFIG_CRYPTO=m -CONFIG_CRYPTO_BROADCOM=m - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -CONFIG_AFS_FS=m -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_INTERMEZZO_FS=m -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -# CONFIG_VIDEO_IGNORE_BAD_MODE is not set -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G450 is not set -CONFIG_FB_MATROX_G100A=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_SIS=m -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -CONFIG_SOUND_MSNDCLAS=m -# CONFIG_MSNDCLAS_HAVE_BOOT is not set -CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" -CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" -CONFIG_SOUND_MSNDPIN=m -# CONFIG_MSNDPIN_HAVE_BOOT is not set -CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" -CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -CONFIG_SOUND_GUS16=y -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -# CONFIG_PSS_MIXER is not set -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -CONFIG_CRYPTO_AEP=m -CONFIG_MEGARAC=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_FRAME_POINTER=y -# CONFIG_MCL_COREDUMP is not set - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686-smp.config deleted file mode 100644 index 7d0ceb4..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686-smp.config +++ /dev/null @@ -1,2139 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# 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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set -CONFIG_TOSHIBA=m -CONFIG_I8K=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_E820_PROC is not set -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -# CONFIG_HIGHMEM4G is not set -CONFIG_HIGHMEM64G=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_X86_PAE=y -CONFIG_HIGHIO=y -# CONFIG_X86_4G is not set -CONFIG_3GB=y -# CONFIG_2GB is not set -# CONFIG_1GB is not set -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -# CONFIG_NR_SIBLINGS_0 is not set -CONFIG_NR_SIBLINGS_2=y -CONFIG_SHARE_RUNQUEUE=y -CONFIG_MAX_NR_SIBLINGS=2 -CONFIG_X86_CLUSTERED_APIC=y -CONFIG_X86_NUMA=y -# CONFIG_X86_NUMAQ is not set -CONFIG_X86_SUMMIT=y -CONFIG_X86_CLUSTERED_APIC=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 -CONFIG_HAVE_DEC_LOCK=y - -# -# General setup -# -CONFIG_NET=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -# CONFIG_SCx200 is not set -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -# CONFIG_IKCONFIG is not set -CONFIG_AUDIT=m -CONFIG_PM=y -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -CONFIG_APM_RTC_IS_GMT=y -# CONFIG_APM_ALLOW_INTS is not set -# CONFIG_APM_REAL_MODE_POWER_OFF is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=y -# CONFIG_PNPBIOS is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=m -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=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_CISS_MONITOR_THREAD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y -CONFIG_DISKDUMP=m -CONFIG_BLOCKDUMP=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=16 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -CONFIG_EDP2=m -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_ISAPNP=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=256 -CONFIG_SD_IOSTATS=y -CONFIG_SCSI_DUMP=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_BLK_DEV_3W_9XXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -# CONFIG_SCSI_ADP94XX is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_MEGARAID_SAS=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=m -CONFIG_SCSI_EATA=m -CONFIG_SCSI_EATA_TAGGED_QUEUE=y -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -# CONFIG_SCSI_GENERIC_NCR53C400 is not set -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -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_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m - -# -# Device Drivers -# -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -# CONFIG_EWRK3 is not set -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_B44=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_FORCEDETH=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -CONFIG_E1000_DISABLE_PACKET_SPLIT=y -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Quadrics QsNet device support -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_ELAN4=m -CONFIG_EP=m -CONFIG_EIP=m -CONFIG_RMS=m -CONFIG_JTAG=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=m -# CONFIG_HIPPI is not set -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 is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m - -# -# Wireless Pcmcia cards support -# -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y - -# -# Wireless Pcmcia cards support -# -CONFIG_PCMCIA_HERMES_OLD=m - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -# CONFIG_TMSISA is not set -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_WVLAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y - -# -# Packet Radio protocols -# -CONFIG_AX25=m -# CONFIG_AX25_DAMA_SLAVE is not set -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -# CONFIG_YAM is not set - -# -# IrDA (infrared) support -# -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=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m - -# -# FIR device drivers -# -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# low-level hardware drivers -# - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y - -# -# 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_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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=y -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_KALLSYMS=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ATI_CD1865=m -# CONFIG_COMPUTONE is not set -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -# CONFIG_ICOM is not set -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -# CONFIG_RIO is not set -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -# CONFIG_SCx200_I2C is not set -# CONFIG_SCx200_ACB is not set -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -# CONFIG_I2C_TSUNAMI is not set -CONFIG_I2C_I801=m -CONFIG_I2C_I810=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=m -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_PANIC_STRING is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -CONFIG_AMD7XX_TCO=m -CONFIG_HANGCHECK_TIMER=m -CONFIG_HANGCHECK_DELAY=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -# CONFIG_NVRAM is not set -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set - -# -# Ftape, the floppy tape device driver -# -CONFIG_FTAPE=m -CONFIG_ZFTAPE=m -CONFIG_ZFT_DFLT_BLK_SZ=10240 - -# -# The compressor will be built as a module only! -# -CONFIG_ZFT_COMPRESSOR=m -CONFIG_FT_NR_BUFFERS=3 -# CONFIG_FT_PROC_FS is not set -CONFIG_FT_NORMAL_DEBUG=y -# CONFIG_FT_FULL_DEBUG is not set -# CONFIG_FT_NO_TRACE is not set -# CONFIG_FT_NO_TRACE_AT_ALL is not set - -# -# Hardware configuration -# -CONFIG_FT_STD_FDC=y -# CONFIG_FT_MACH2 is not set -# CONFIG_FT_PROBE_FC10 is not set -# CONFIG_FT_ALT_FDC is not set -CONFIG_FT_FDC_THR=8 -CONFIG_FT_FDC_MAX_RATE=2000 -CONFIG_FT_ALPHA_CLOCK=0 -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_AGP_NVIDIA=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set - -# -# DRM 4.1 drivers -# -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -CONFIG_DRM_SIS=m - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m - -# -# Video Adapters -# -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFS_ACL=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -# CONFIG_VIDEO_IGNORE_BAD_MODE is not set -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_INTEL=m -CONFIG_FB_SIS=m -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -CONFIG_SOUND_MSNDCLAS=m -# CONFIG_MSNDCLAS_HAVE_BOOT is not set -CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" -CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" -CONFIG_SOUND_MSNDPIN=m -# CONFIG_MSNDPIN_HAVE_BOOT is not set -CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" -CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -CONFIG_SOUND_GUS16=y -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -# CONFIG_PSS_MIXER is not set -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m -CONFIG_SOUND_AD1980=m -CONFIG_SOUND_WM97XX=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set - -# -# USB Bluetooth can only be used with disabled Bluetooth subsystem -# -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m - -# -# USB Network adaptors -# -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -# CONFIG_USB_AX8817X is not set -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m - -# -# USB port drivers -# -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -CONFIG_CRYPTO_AEP=m -CONFIG_CRYPTO_BROADCOM=m -CONFIG_MEGARAC=m -CONFIG_FC_QLA2100=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_LPFC=m -CONFIG_FUSION_ISENSE=m -# CONFIG_DCDBAS is not set -CONFIG_DELL_RBU=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_FRAME_POINTER is not set -CONFIG_DEBUG_HIGHMEM=y -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_PANIC_MORSE=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_SMALL is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_QSORT=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686.config deleted file mode 100644 index 2e0d417..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-i686.config +++ /dev/null @@ -1,2139 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# 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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set -CONFIG_TOSHIBA=m -CONFIG_I8K=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_E820_PROC is not set -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -# CONFIG_HIGHMEM4G is not set -CONFIG_HIGHMEM64G=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_X86_PAE=y -CONFIG_HIGHIO=y -# CONFIG_X86_4G is not set -CONFIG_3GB=y -# CONFIG_2GB is not set -# CONFIG_1GB is not set -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -# CONFIG_NR_SIBLINGS_0 is not set -CONFIG_NR_SIBLINGS_2=y -CONFIG_SHARE_RUNQUEUE=y -CONFIG_MAX_NR_SIBLINGS=2 -CONFIG_X86_CLUSTERED_APIC=y -CONFIG_X86_NUMA=y -# CONFIG_X86_NUMAQ is not set -CONFIG_X86_SUMMIT=y -CONFIG_X86_CLUSTERED_APIC=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 -CONFIG_HAVE_DEC_LOCK=y - -# -# General setup -# -CONFIG_NET=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -# CONFIG_SCx200 is not set -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_COMPAQ=m -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_IBM=m -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -# CONFIG_IKCONFIG is not set -CONFIG_AUDIT=m -CONFIG_PM=y -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -# CONFIG_APM_DO_ENABLE is not set -CONFIG_APM_CPU_IDLE=y -# CONFIG_APM_DISPLAY_BLANK is not set -CONFIG_APM_RTC_IS_GMT=y -# CONFIG_APM_ALLOW_INTS is not set -# CONFIG_APM_REAL_MODE_POWER_OFF is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=y -# CONFIG_PNPBIOS is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=m -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=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_CISS_MONITOR_THREAD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y -CONFIG_DISKDUMP=m -CONFIG_BLOCKDUMP=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=16 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -CONFIG_EDP2=m -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -CONFIG_BLK_DEV_ISAPNP=y -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=256 -CONFIG_SD_IOSTATS=y -CONFIG_SCSI_DUMP=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_BLK_DEV_3W_9XXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -# CONFIG_SCSI_ADP94XX is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_MEGARAID_SAS=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=m -CONFIG_SCSI_EATA=m -CONFIG_SCSI_EATA_TAGGED_QUEUE=y -# CONFIG_SCSI_EATA_LINKED_COMMANDS is not set -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -# CONFIG_SCSI_GENERIC_NCR53C400 is not set -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -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_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m - -# -# Device Drivers -# -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -# CONFIG_EWRK3 is not set -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_B44=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_FORCEDETH=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -CONFIG_E1000_DISABLE_PACKET_SPLIT=y -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Quadrics QsNet device support -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_ELAN4=m -CONFIG_EP=m -CONFIG_EIP=m -CONFIG_RMS=m -CONFIG_JTAG=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=m -# CONFIG_HIPPI is not set -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 is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m - -# -# Wireless Pcmcia cards support -# -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y - -# -# Wireless Pcmcia cards support -# -CONFIG_PCMCIA_HERMES_OLD=m - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -# CONFIG_TMSISA is not set -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_ARCNET_COM20020_CS is not set -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_PCMCIA_WVLAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y - -# -# Packet Radio protocols -# -CONFIG_AX25=m -# CONFIG_AX25_DAMA_SLAVE is not set -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -# CONFIG_YAM is not set - -# -# IrDA (infrared) support -# -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=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m - -# -# FIR device drivers -# -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# low-level hardware drivers -# - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y - -# -# 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_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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=y -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_KALLSYMS=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ATI_CD1865=m -# CONFIG_COMPUTONE is not set -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -# CONFIG_ICOM is not set -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -# CONFIG_RIO is not set -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -# CONFIG_SCx200_I2C is not set -# CONFIG_SCx200_ACB is not set -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -# CONFIG_I2C_TSUNAMI is not set -CONFIG_I2C_I801=m -CONFIG_I2C_I810=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=m -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_PANIC_STRING is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -CONFIG_AMD7XX_TCO=m -CONFIG_HANGCHECK_TIMER=m -CONFIG_HANGCHECK_DELAY=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -# CONFIG_NVRAM is not set -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set - -# -# Ftape, the floppy tape device driver -# -CONFIG_FTAPE=m -CONFIG_ZFTAPE=m -CONFIG_ZFT_DFLT_BLK_SZ=10240 - -# -# The compressor will be built as a module only! -# -CONFIG_ZFT_COMPRESSOR=m -CONFIG_FT_NR_BUFFERS=3 -# CONFIG_FT_PROC_FS is not set -CONFIG_FT_NORMAL_DEBUG=y -# CONFIG_FT_FULL_DEBUG is not set -# CONFIG_FT_NO_TRACE is not set -# CONFIG_FT_NO_TRACE_AT_ALL is not set - -# -# Hardware configuration -# -CONFIG_FT_STD_FDC=y -# CONFIG_FT_MACH2 is not set -# CONFIG_FT_PROBE_FC10 is not set -# CONFIG_FT_ALT_FDC is not set -CONFIG_FT_FDC_THR=8 -CONFIG_FT_FDC_MAX_RATE=2000 -CONFIG_FT_ALPHA_CLOCK=0 -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_AGP_NVIDIA=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set - -# -# DRM 4.1 drivers -# -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -CONFIG_DRM_SIS=m - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m - -# -# Video Adapters -# -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFS_ACL=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -# CONFIG_VIDEO_IGNORE_BAD_MODE is not set -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_INTEL=m -CONFIG_FB_SIS=m -CONFIG_FB_SIS_300=y -CONFIG_FB_SIS_315=y -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -CONFIG_SOUND_MSNDCLAS=m -# CONFIG_MSNDCLAS_HAVE_BOOT is not set -CONFIG_MSNDCLAS_INIT_FILE="/etc/sound/msndinit.bin" -CONFIG_MSNDCLAS_PERM_FILE="/etc/sound/msndperm.bin" -CONFIG_SOUND_MSNDPIN=m -# CONFIG_MSNDPIN_HAVE_BOOT is not set -CONFIG_MSNDPIN_INIT_FILE="/etc/sound/pndspini.bin" -CONFIG_MSNDPIN_PERM_FILE="/etc/sound/pndsperm.bin" -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -CONFIG_SOUND_GUS16=y -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -# CONFIG_PSS_MIXER is not set -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m -CONFIG_SOUND_AD1980=m -CONFIG_SOUND_WM97XX=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set - -# -# USB Bluetooth can only be used with disabled Bluetooth subsystem -# -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m - -# -# USB Network adaptors -# -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -# CONFIG_USB_AX8817X is not set -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m - -# -# USB port drivers -# -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -CONFIG_CRYPTO_AEP=m -CONFIG_CRYPTO_BROADCOM=m -CONFIG_MEGARAC=m -CONFIG_FC_QLA2100=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_LPFC=m -# CONFIG_FUSION_ISENSE is not set -# CONFIG_DCDBAS is not set -CONFIG_DELL_RBU=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_FRAME_POINTER is not set -CONFIG_DEBUG_HIGHMEM=y -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_PANIC_MORSE=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_SMALL is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_QSORT=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64-smp.config deleted file mode 100644 index ff4b0d1..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64-smp.config +++ /dev/null @@ -1,1451 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_IA64=y -# CONFIG_HIGHPTE is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHIO=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y -CONFIG_IA64_GENERIC=y -# CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_SIM is not set -# CONFIG_IA64_HP_ZX1 is not set -# CONFIG_IA64_SGI_SN1 is not set -# CONFIG_IA64_SGI_SN2 is not set -# CONFIG_IA64_PAGE_SIZE_4KB is not set -# CONFIG_IA64_PAGE_SIZE_8KB is not set -CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_IA64_L1_CACHE_SHIFT=7 -CONFIG_IA64_MCA=y -CONFIG_PM=y -CONFIG_KCORE_ELF=y -CONFIG_FORCE_MAX_ZONEORDER=15 -# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set -# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set -CONFIG_HUGETLB_PAGE_SIZE_256MB=y -# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set -# CONFIG_IA64_PAL_IDLE is not set -CONFIG_SMP=y -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y -CONFIG_PERFMON=y -CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y -CONFIG_IA64_CYCLONE=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_AUDIT=m -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_KERNEL_CONFIG=y - -# -# ACPI Support -# -CONFIG_ACPI_PCI=y -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -# CONFIG_ACPI_DEBUG is not set -CONFIG_PCI=y -CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=m -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_ACPI=m - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=16 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -CONFIG_EDP2=m -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -CONFIG_BLK_CPQ_CISS_DA=m -CONFIG_CISS_SCSI_TAPE=y -# CONFIG_CISS_MONITOR_THREAD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y -CONFIG_DISKDUMP=m -CONFIG_BLOCKDUMP=m - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m - -# -# Device Drivers -# - -# -# Texas Instruments PCILynx requires I2C bit-banging -# -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=256 -CONFIG_SD_IOSTATS=y -CONFIG_SCSI_DUMP=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_DEBUG_QUEUES=y -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_BLK_DEV_3W_9XXX_RAID=m -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -# CONFIG_SCSI_ADP94XX is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_MEGARAID_SAS=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_GDTH=m -# CONFIG_SCSI_GENERIC_NCR5380 is not set -CONFIG_SCSI_IPS=m -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -CONFIG_SCSI_SYM53C8XX_2=m -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -CONFIG_SCSI_NSP32=m -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -# CONFIG_APRICOT is not set -CONFIG_B44=m -# CONFIG_CS89x0 is not set -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -# CONFIG_LNE390 is not set -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_FORCEDETH=m -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -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_SIS900=m -CONFIG_EPIC100=m -# CONFIG_SUNDANCE is not set -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -CONFIG_E1000_DISABLE_PACKET_SPLIT=y -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Quadrics QsNet device support -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_ELAN4=m -CONFIG_EP=m -CONFIG_EIP=m -CONFIG_RMS=m -CONFIG_JTAG=m -# CONFIG_FDDI is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -# CONFIG_TMS380TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_ECC is not set -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_HCDP=y -CONFIG_SERIAL_ACPI=y -CONFIG_HP_DIVA=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_PANIC_STRING is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_HANGCHECK_TIMER=m -CONFIG_HANGCHECK_DELAY=m -# CONFIG_SCx200_GPIO is not set -CONFIG_INTEL_RNG=m -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -# CONFIG_AGP_I810 is not set -# CONFIG_AGP_VIA is not set -# CONFIG_AGP_AMD is not set -CONFIG_AGP_AMD_8151=y -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_SWORKS is not set -CONFIG_AGP_I460=y -CONFIG_AGP_HP_ZX1=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set - -# -# DRM 4.1 drivers -# -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -# CONFIG_DRM_I810 is not set -# CONFIG_DRM_I810_XFREE_41 is not set -# CONFIG_DRM_I830 is not set -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFS_ACL=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VGA16=m -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -# CONFIG_FB_ATY is not set -# CONFIG_FB_RADEON is not set -CONFIG_FB_ATY128=m -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB8=m -CONFIG_FBCON_CFB16=m -CONFIG_FBCON_CFB24=m -CONFIG_FBCON_CFB32=m -CONFIG_FBCON_VGA_PLANES=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -CONFIG_PCI_CONSOLE=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -# CONFIG_SOUND_BT878 is not set -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -# CONFIG_SOUND_AD1816 is not set -CONFIG_SOUND_AD1889=m -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -CONFIG_SOUND_VMIDI=m -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set -CONFIG_SOUND_AD1980=m -CONFIG_SOUND_WM97XX=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set - -# -# USB Bluetooth can only be used with disabled Bluetooth subsystem -# -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network adaptors -# -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -# CONFIG_USB_AX8817X is not set -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_QSORT=y - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -# CONFIG_BLUEZ_HCIDTL1 is not set -# CONFIG_BLUEZ_HCIBT3C is not set -# CONFIG_BLUEZ_HCIBLUECARD is not set -# CONFIG_BLUEZ_HCIBTUART is not set -CONFIG_BLUEZ_HCIVHCI=m - -# -# Simulated drivers -# -# CONFIG_HP_SIMETH is not set -# CONFIG_HP_SIMSERIAL is not set -# CONFIG_HP_SIMSCSI is not set - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -# CONFIG_CRYPTO_AEP is not set -CONFIG_CRYPTO_BROADCOM=m -# CONFIG_MEGARAC is not set -CONFIG_FC_QLA2100=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_LPFC=m -# CONFIG_FUSION_ISENSE is not set -# CONFIG_DCDBAS is not set -CONFIG_DELL_RBU=m - -# -# Kernel hacking -# -CONFIG_IA64_GRANULE_16MB=y -# CONFIG_IA64_GRANULE_64MB is not set -CONFIG_DEBUG_KERNEL=y -CONFIG_IA64_PRINT_HAZARDS=y -# CONFIG_DISABLE_VHPT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_IA64_EARLY_PRINTK is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_IA64_DEBUG_CMPXCHG is not set -# CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_KALLSYMS=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64.config deleted file mode 100644 index ff4b0d1..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-ia64.config +++ /dev/null @@ -1,1451 +0,0 @@ -# -# Automatically generated make config: don't edit -# - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# General setup -# -CONFIG_IA64=y -# CONFIG_HIGHPTE is not set -CONFIG_HIGHMEM=y -CONFIG_HIGHIO=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_ITANIUM is not set -CONFIG_MCKINLEY=y -CONFIG_IA64_GENERIC=y -# CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_SIM is not set -# CONFIG_IA64_HP_ZX1 is not set -# CONFIG_IA64_SGI_SN1 is not set -# CONFIG_IA64_SGI_SN2 is not set -# CONFIG_IA64_PAGE_SIZE_4KB is not set -# CONFIG_IA64_PAGE_SIZE_8KB is not set -CONFIG_IA64_PAGE_SIZE_16KB=y -# CONFIG_IA64_PAGE_SIZE_64KB is not set -CONFIG_IA64_L1_CACHE_SHIFT=7 -CONFIG_IA64_MCA=y -CONFIG_PM=y -CONFIG_KCORE_ELF=y -CONFIG_FORCE_MAX_ZONEORDER=15 -# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set -# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set -CONFIG_HUGETLB_PAGE_SIZE_256MB=y -# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set -# CONFIG_IA64_PAL_IDLE is not set -CONFIG_SMP=y -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y -CONFIG_PERFMON=y -CONFIG_IA64_PALINFO=y -CONFIG_EFI_VARS=y -CONFIG_IA64_CYCLONE=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_AUDIT=m -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_KERNEL_CONFIG=y - -# -# ACPI Support -# -CONFIG_ACPI_PCI=y -CONFIG_ACPI=y -CONFIG_ACPI_EFI=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -# CONFIG_ACPI_DEBUG is not set -CONFIG_PCI=y -CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=m -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -CONFIG_HOTPLUG_PCI_ACPI=m - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=16 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -CONFIG_EDP2=m -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -CONFIG_BLK_CPQ_CISS_DA=m -CONFIG_CISS_SCSI_TAPE=y -# CONFIG_CISS_MONITOR_THREAD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y -CONFIG_DISKDUMP=m -CONFIG_BLOCKDUMP=m - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m - -# -# Device Drivers -# - -# -# Texas Instruments PCILynx requires I2C bit-banging -# -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=256 -CONFIG_SD_IOSTATS=y -CONFIG_SCSI_DUMP=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_DEBUG_QUEUES=y -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_BLK_DEV_3W_9XXX_RAID=m -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -# CONFIG_SCSI_ADP94XX is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_MEGARAID_SAS=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_GDTH=m -# CONFIG_SCSI_GENERIC_NCR5380 is not set -CONFIG_SCSI_IPS=m -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -CONFIG_SCSI_SYM53C8XX_2=m -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -CONFIG_SCSI_NSP32=m -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -# CONFIG_APRICOT is not set -CONFIG_B44=m -# CONFIG_CS89x0 is not set -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -# CONFIG_LNE390 is not set -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_FORCEDETH=m -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -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_SIS900=m -CONFIG_EPIC100=m -# CONFIG_SUNDANCE is not set -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -CONFIG_E1000_DISABLE_PACKET_SPLIT=y -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Quadrics QsNet device support -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_ELAN4=m -CONFIG_EP=m -CONFIG_EIP=m -CONFIG_RMS=m -CONFIG_JTAG=m -# CONFIG_FDDI is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -# CONFIG_TMS380TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_ECC is not set -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_HCDP=y -CONFIG_SERIAL_ACPI=y -CONFIG_HP_DIVA=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_PANIC_STRING is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_HANGCHECK_TIMER=m -CONFIG_HANGCHECK_DELAY=m -# CONFIG_SCx200_GPIO is not set -CONFIG_INTEL_RNG=m -# CONFIG_AMD_PM768 is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -# CONFIG_AGP_I810 is not set -# CONFIG_AGP_VIA is not set -# CONFIG_AGP_AMD is not set -CONFIG_AGP_AMD_8151=y -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_SWORKS is not set -CONFIG_AGP_I460=y -CONFIG_AGP_HP_ZX1=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set - -# -# DRM 4.1 drivers -# -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -# CONFIG_DRM_I810 is not set -# CONFIG_DRM_I810_XFREE_41 is not set -# CONFIG_DRM_I830 is not set -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFS_ACL=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VGA16=m -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -# CONFIG_FB_ATY is not set -# CONFIG_FB_RADEON is not set -CONFIG_FB_ATY128=m -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB8=m -CONFIG_FBCON_CFB16=m -CONFIG_FBCON_CFB24=m -CONFIG_FBCON_CFB32=m -CONFIG_FBCON_VGA_PLANES=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -CONFIG_PCI_CONSOLE=y - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -# CONFIG_SOUND_BT878 is not set -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -# CONFIG_SOUND_AD1816 is not set -CONFIG_SOUND_AD1889=m -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -CONFIG_SOUND_VMIDI=m -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set -CONFIG_SOUND_AD1980=m -CONFIG_SOUND_WM97XX=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set - -# -# USB Bluetooth can only be used with disabled Bluetooth subsystem -# -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network adaptors -# -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -# CONFIG_USB_AX8817X is not set -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_QSORT=y - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -# CONFIG_BLUEZ_HCIDTL1 is not set -# CONFIG_BLUEZ_HCIBT3C is not set -# CONFIG_BLUEZ_HCIBLUECARD is not set -# CONFIG_BLUEZ_HCIBTUART is not set -CONFIG_BLUEZ_HCIVHCI=m - -# -# Simulated drivers -# -# CONFIG_HP_SIMETH is not set -# CONFIG_HP_SIMSERIAL is not set -# CONFIG_HP_SIMSCSI is not set - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -# CONFIG_CRYPTO_AEP is not set -CONFIG_CRYPTO_BROADCOM=m -# CONFIG_MEGARAC is not set -CONFIG_FC_QLA2100=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_LPFC=m -# CONFIG_FUSION_ISENSE is not set -# CONFIG_DCDBAS is not set -CONFIG_DELL_RBU=m - -# -# Kernel hacking -# -CONFIG_IA64_GRANULE_16MB=y -# CONFIG_IA64_GRANULE_64MB is not set -CONFIG_DEBUG_KERNEL=y -CONFIG_IA64_PRINT_HAZARDS=y -# CONFIG_DISABLE_VHPT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_IA64_EARLY_PRINTK is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_IA64_DEBUG_CMPXCHG is not set -# CONFIG_IA64_DEBUG_IRQ is not set -CONFIG_KALLSYMS=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64-smp.config deleted file mode 100644 index 0d9818a..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64-smp.config +++ /dev/null @@ -1,1787 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_X86_64=y -CONFIG_X86=y -# CONFIG_ISA is not set -# CONFIG_SBUS is not set -# CONFIG_UID16 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_X86_CMPXCHG=y -CONFIG_EARLY_PRINTK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# CONFIG_MK8 is not set -CONFIG_IA32E=y -# CONFIG_GENERIC_CPU is not set -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_TSC=y -CONFIG_X86_GOOD_APIC=y -# CONFIG_MICROCODE is not set -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_MATH_EMULATION is not set -# CONFIG_MCA is not set -# CONFIG_EISA is not set -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_MTRR=y -CONFIG_SMP=y -CONFIG_HPET_TIMER=y -CONFIG_GART_IOMMU=y -CONFIG_SWIOTLB=y -CONFIG_NR_SIBLINGS_0=y -# CONFIG_NR_SIBLINGS_2 is not set -CONFIG_HAVE_DEC_LOCK=y -CONFIG_MCE=y -CONFIG_K8_NUMA=y -CONFIG_DISCONTIGMEM=y -CONFIG_NUMA=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -CONFIG_NET=y -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_IBM is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_AUDIT=m -CONFIG_PM=y -CONFIG_IA32_EMULATION=y -CONFIG_COMPAT=y -CONFIG_ACPI=y - -# -# ACPI Support -# -CONFIG_ACPI=y -# CONFIG_ACPI_HT_ONLY is not set -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -# CONFIG_ACPI_SLEEP is not set -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -# CONFIG_ACPI_NUMA is not set -# CONFIG_ACPI_ASUS is not set -# CONFIG_ACPI_TOSHIBA is not set -# CONFIG_ACPI_DEBUG is not set -# CONFIG_ACPI_PMTMR is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Block devices -# -CONFIG_BLK_DEV_FD=m -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=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_CISS_MONITOR_THREAD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y -CONFIG_DISKDUMP=m -CONFIG_BLOCKDUMP=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=16 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -CONFIG_EDP2=m -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=256 -CONFIG_SD_IOSTATS=y -CONFIG_SCSI_DUMP=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_BLK_DEV_3W_9XXX_RAID=m -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -# CONFIG_SCSI_ADP94XX is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_MEGARAID_SAS=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_GDTH=m -# CONFIG_SCSI_GENERIC_NCR5380 is not set -CONFIG_SCSI_IPS=m -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -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_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_SEAGATE=m -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -# CONFIG_SCSI_DEBUG is not set - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m - -# -# Device Drivers -# - -# -# Texas Instruments PCILynx requires I2C bit-banging -# -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -# CONFIG_LANCE is not set -CONFIG_NET_VENDOR_SMC=y -# CONFIG_WD80x3 is not set -# CONFIG_ULTRAMCA is not set -# CONFIG_ULTRA is not set -# CONFIG_ULTRA32 is not set -# CONFIG_SMC9194 is not set -CONFIG_NET_VENDOR_RACAL=y -# CONFIG_NI5010 is not set -# CONFIG_NI52 is not set -# CONFIG_NI65 is not set -CONFIG_HP100=m -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -# CONFIG_APRICOT is not set -CONFIG_B44=m -# CONFIG_CS89x0 is not set -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -# CONFIG_LNE390 is not set -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_FORCEDETH=m -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -# CONFIG_DE600 is not set -# CONFIG_DE620 is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -CONFIG_E1000_DISABLE_PACKET_SPLIT=y -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Quadrics QsNet device support -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_ELAN4=m -CONFIG_EP=m -CONFIG_EIP=m -CONFIG_RMS=m -CONFIG_JTAG=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -# CONFIG_NETCONSOLE is not set -# CONFIG_HIPPI is not set -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 is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -# CONFIG_TMS380TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -# CONFIG_CYCLADES_SYNC is not set -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -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=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m - -# -# FIR device drivers -# -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# low-level hardware drivers -# - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y - -# -# 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_TELESPCI=y -CONFIG_HISAX_S0BOX=y -CONFIG_HISAX_FRITZPCI=y -# CONFIG_HISAX_AVM_A1_PCMCIA is not set -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=y -# CONFIG_HISAX_SEDLBAUER_CS is not set -# CONFIG_HISAX_ELSA_CS is not set -# CONFIG_HISAX_AVM_A1_CS is not set -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set -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 -# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set -# CONFIG_ISDN_DRV_AVMB1_B1PCI is not set -# CONFIG_ISDN_DRV_AVMB1_B1PCIV4 is not set -# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set -# CONFIG_ISDN_DRV_AVMB1_B1PCMCIA is not set -# CONFIG_ISDN_DRV_AVMB1_AVM_CS is not set -# CONFIG_ISDN_DRV_AVMB1_T1PCI is not set -# CONFIG_ISDN_DRV_AVMB1_C4 is not set -# CONFIG_HYSDN is not set -# CONFIG_HYSDN_CAPI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_ECC is not set -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_ACPI=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ATI_CD1865=m -# CONFIG_COMPUTONE is not set -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -# CONFIG_ESPSERIAL is not set -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -# CONFIG_ICOM is not set -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_PANIC_STRING is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -# CONFIG_AMD7XX_TCO is not set -CONFIG_HANGCHECK_TIMER=m -CONFIG_HANGCHECK_DELAY=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -# CONFIG_AMD_PM768 is not set -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_AGP_NVIDIA=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set - -# -# DRM 4.1 drivers -# -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set -CONFIG_MWAVE=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_BT848 is not set -CONFIG_VIDEO_PMS=m -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_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -CONFIG_VIDEO_STRADIS=m -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -# CONFIG_RADIO_MIROPCM20 is not set - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFS_ACL=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_TEST=m - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -# CONFIG_SOUND_BT878 is not set -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -# CONFIG_SOUND_AD1816 is not set -CONFIG_SOUND_AD1889=m -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -CONFIG_SOUND_VMIDI=m -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set -# CONFIG_SOUND_AD1980 is not set -# CONFIG_SOUND_WM97XX is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set - -# -# USB Bluetooth can only be used with disabled Bluetooth subsystem -# -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m - -# -# USB Network adaptors -# -CONFIG_USB_PEGASUS=m -# CONFIG_USB_RTL8150 is not set -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -# CONFIG_USB_AX8817X is not set -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m - -# -# USB port drivers -# -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -# CONFIG_BLUEZ_HCIDTL1 is not set -# CONFIG_BLUEZ_HCIBT3C is not set -# CONFIG_BLUEZ_HCIBLUECARD is not set -# CONFIG_BLUEZ_HCIBTUART is not set -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -# CONFIG_CRYPTO_AEP is not set -CONFIG_CRYPTO_BROADCOM=m -# CONFIG_MEGARAC is not set -CONFIG_FC_QLA2100=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_LPFC=m -# CONFIG_FUSION_ISENSE is not set -# CONFIG_DCDBAS is not set -CONFIG_DELL_RBU=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_CHECKING=y -CONFIG_INIT_DEBUG=y -# CONFIG_IOMMU_DEBUG is not set -# CONFIG_IOMMU_LEAK is not set -CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_KALLSYMS=y - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_QSORT=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64.config deleted file mode 100644 index 0d9818a..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-rhel-2.4-x86_64.config +++ /dev/null @@ -1,1787 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_X86_64=y -CONFIG_X86=y -# CONFIG_ISA is not set -# CONFIG_SBUS is not set -# CONFIG_UID16 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_X86_CMPXCHG=y -CONFIG_EARLY_PRINTK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# CONFIG_MK8 is not set -CONFIG_IA32E=y -# CONFIG_GENERIC_CPU is not set -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_TSC=y -CONFIG_X86_GOOD_APIC=y -# CONFIG_MICROCODE is not set -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_MATH_EMULATION is not set -# CONFIG_MCA is not set -# CONFIG_EISA is not set -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_MTRR=y -CONFIG_SMP=y -CONFIG_HPET_TIMER=y -CONFIG_GART_IOMMU=y -CONFIG_SWIOTLB=y -CONFIG_NR_SIBLINGS_0=y -# CONFIG_NR_SIBLINGS_2 is not set -CONFIG_HAVE_DEC_LOCK=y -CONFIG_MCE=y -CONFIG_K8_NUMA=y -CONFIG_DISCONTIGMEM=y -CONFIG_NUMA=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -CONFIG_NET=y -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_IBM is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_AUDIT=m -CONFIG_PM=y -CONFIG_IA32_EMULATION=y -CONFIG_COMPAT=y -CONFIG_ACPI=y - -# -# ACPI Support -# -CONFIG_ACPI=y -# CONFIG_ACPI_HT_ONLY is not set -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -# CONFIG_ACPI_SLEEP is not set -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -# CONFIG_ACPI_NUMA is not set -# CONFIG_ACPI_ASUS is not set -# CONFIG_ACPI_TOSHIBA is not set -# CONFIG_ACPI_DEBUG is not set -# CONFIG_ACPI_PMTMR is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -# CONFIG_PARPORT_OTHER is not set -CONFIG_PARPORT_1284=y - -# -# Block devices -# -CONFIG_BLK_DEV_FD=m -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=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_CISS_MONITOR_THREAD is not set -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=8192 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y -CONFIG_DISKDUMP=m -CONFIG_BLOCKDUMP=m - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_NET_KEY=m -CONFIG_INET=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -# CONFIG_TUX_EXTENDED_LOG is not set -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_PNP is not set -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_INET_ECN is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=16 - -# -# 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 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y - -# -# IPv6: Netfilter Configuration -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -# CONFIG_KHTTPD is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -CONFIG_ATM_BR2684_IPFILTER=y -CONFIG_VLAN_8021Q=m - -# -# -# -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -CONFIG_DECNET_ROUTER=y -CONFIG_DECNET_ROUTE_FWMARK=y -CONFIG_BRIDGE=m -# CONFIG_X25 is not set -CONFIG_EDP2=m -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_CMD640=y -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=y -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_SD_EXTRA_DEVS=256 -CONFIG_SD_IOSTATS=y -CONFIG_SCSI_DUMP=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SG=m - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_BLK_DEV_3W_9XXX_RAID=m -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -# CONFIG_SCSI_ADP94XX is not set -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_MEGARAID_SAS=m -CONFIG_SCSI_SATA=y -CONFIG_SCSI_SATA_AHCI=m -CONFIG_SCSI_SATA_SVW=m -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_SATA_NV=m -CONFIG_SCSI_SATA_PROMISE=m -CONFIG_SCSI_SATA_SX4=m -CONFIG_SCSI_SATA_SIL=m -CONFIG_SCSI_SATA_SIS=m -CONFIG_SCSI_SATA_ULI=m -CONFIG_SCSI_SATA_VIA=m -CONFIG_SCSI_SATA_VITESSE=m -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -CONFIG_SCSI_GDTH=m -# CONFIG_SCSI_GENERIC_NCR5380 is not set -CONFIG_SCSI_IPS=m -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -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_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=40 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_SEAGATE=m -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -# CONFIG_SCSI_DEBUG is not set - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -# CONFIG_FUSION_ISENSE is not set -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m - -# -# Device Drivers -# - -# -# Texas Instruments PCILynx requires I2C bit-banging -# -CONFIG_IEEE1394_OHCI1394=m - -# -# Protocol Drivers -# -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -# CONFIG_LANCE is not set -CONFIG_NET_VENDOR_SMC=y -# CONFIG_WD80x3 is not set -# CONFIG_ULTRAMCA is not set -# CONFIG_ULTRA is not set -# CONFIG_ULTRA32 is not set -# CONFIG_SMC9194 is not set -CONFIG_NET_VENDOR_RACAL=y -# CONFIG_NI5010 is not set -# CONFIG_NI52 is not set -# CONFIG_NI65 is not set -CONFIG_HP100=m -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -# CONFIG_APRICOT is not set -CONFIG_B44=m -# CONFIG_CS89x0 is not set -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -# CONFIG_LNE390 is not set -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NE2K_PCI=m -CONFIG_FORCEDETH=m -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -# CONFIG_DE600 is not set -# CONFIG_DE620 is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NAPI=y -CONFIG_E1000_DISABLE_PACKET_SPLIT=y -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_TIGON3=m -CONFIG_BNX2=m - -# -# Quadrics QsNet device support -# -CONFIG_QSNET=m -CONFIG_ELAN3=m -CONFIG_ELAN4=m -CONFIG_EP=m -CONFIG_EIP=m -CONFIG_RMS=m -CONFIG_JTAG=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -# CONFIG_NETCONSOLE is not set -# CONFIG_HIPPI is not set -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 is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -# CONFIG_TMS380TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -# CONFIG_RCPCI is not set -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -# CONFIG_COMX is not set -# CONFIG_DSCC4 is not set -# CONFIG_LANMEDIA is not set -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -# CONFIG_SYNCLINK_SYNCPPP is not set -# CONFIG_HDLC is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -CONFIG_WANPIPE_FR=y -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -# CONFIG_CYCLADES_SYNC is not set -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -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=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m - -# -# Dongle support -# -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m - -# -# FIR device drivers -# -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -# CONFIG_ISDN_DIVERSION is not set - -# -# low-level hardware drivers -# - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y - -# -# 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_TELESPCI=y -CONFIG_HISAX_S0BOX=y -CONFIG_HISAX_FRITZPCI=y -# CONFIG_HISAX_AVM_A1_PCMCIA is not set -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=y -# CONFIG_HISAX_SEDLBAUER_CS is not set -# CONFIG_HISAX_ELSA_CS is not set -# CONFIG_HISAX_AVM_A1_CS is not set -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -# CONFIG_ISDN_DRV_SC is not set -# CONFIG_ISDN_DRV_ACT2000 is not set -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -# CONFIG_ISDN_DRV_EICON_OLD is not set -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set -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 -# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set -# CONFIG_ISDN_DRV_AVMB1_B1PCI is not set -# CONFIG_ISDN_DRV_AVMB1_B1PCIV4 is not set -# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set -# CONFIG_ISDN_DRV_AVMB1_B1PCMCIA is not set -# CONFIG_ISDN_DRV_AVMB1_AVM_CS is not set -# CONFIG_ISDN_DRV_AVMB1_T1PCI is not set -# CONFIG_ISDN_DRV_AVMB1_C4 is not set -# CONFIG_HYSDN is not set -# CONFIG_HYSDN_CAPI is not set - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_ECC is not set -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_ACPI=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -# CONFIG_HUB6 is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ATI_CD1865=m -# CONFIG_COMPUTONE is not set -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -# CONFIG_ESPSERIAL is not set -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -# CONFIG_ICOM is not set -CONFIG_SYNCLINK=m -# CONFIG_SYNCLINKMP is not set -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=2048 -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m - -# -# Joysticks -# -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -# CONFIG_QIC02_TAPE is not set -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_PANIC_STRING is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -# CONFIG_MIXCOMWD is not set -# CONFIG_60XX_WDT is not set -CONFIG_SC1200_WDT=m -# CONFIG_SCx200_WDT is not set -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -# CONFIG_WDT_501 is not set -CONFIG_MACHZ_WDT=m -# CONFIG_AMD7XX_TCO is not set -CONFIG_HANGCHECK_TIMER=m -CONFIG_HANGCHECK_DELAY=m -# CONFIG_SCx200_GPIO is not set -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -# CONFIG_AMD_PM768 is not set -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_AGP_NVIDIA=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set - -# -# DRM 4.1 drivers -# -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_GAMMA=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set -CONFIG_MWAVE=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -# CONFIG_I2C_PARPORT is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_BT848 is not set -CONFIG_VIDEO_PMS=m -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_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -CONFIG_VIDEO_STRADIS=m -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZORAN_BUZ is not set -# CONFIG_VIDEO_ZORAN_DC10 is not set -# CONFIG_VIDEO_ZORAN_LML33 is not set -# CONFIG_VIDEO_ZR36120 is not set -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -# CONFIG_RADIO_MIROPCM20 is not set - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -# CONFIG_QIFACE_COMPAT is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_DEBUG=y -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=m -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XATTR_SHARING is not set -# CONFIG_EXT2_FS_XATTR_USER is not set -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -# CONFIG_INTERMEZZO_FS is not set -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFS_ACL=y -# CONFIG_ROOT_NFS is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FS_MBCACHE=y - -# -# 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 is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -# CONFIG_EFI_PARTITION is not set -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -# CONFIG_FB_PM2_FIFO_DISCONNECT is not set -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_FB_CYBER2000 is not set -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -# CONFIG_FB_MATROX_PROC is not set -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_ATY_CT_VAIO_LCD=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_TEST=m - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -# CONFIG_SOUND_BT878 is not set -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_AUDIGY=m -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -CONFIG_SOUND_DMAP=y -# CONFIG_SOUND_AD1816 is not set -CONFIG_SOUND_AD1889=m -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -CONFIG_SOUND_VMIDI=m -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_TVMIXER is not set -# CONFIG_SOUND_AD1980 is not set -# CONFIG_SOUND_WM97XX is not set - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m - -# -# USB Device Class drivers -# -CONFIG_USB_AUDIO=m -# CONFIG_USB_EMI26 is not set - -# -# USB Bluetooth can only be used with disabled Bluetooth subsystem -# -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# USB Human Interface Devices (HID) -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m - -# -# USB Multimedia devices -# -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m - -# -# USB Network adaptors -# -CONFIG_USB_PEGASUS=m -# CONFIG_USB_RTL8150 is not set -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -# CONFIG_USB_AX8817X is not set -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m - -# -# USB port drivers -# -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -CONFIG_BLUEZ_USB_ZERO_PACKET=y -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -# CONFIG_BLUEZ_HCIDTL1 is not set -# CONFIG_BLUEZ_HCIBT3C is not set -# CONFIG_BLUEZ_HCIBLUECARD is not set -# CONFIG_BLUEZ_HCIBTUART is not set -CONFIG_BLUEZ_HCIVHCI=m - -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=m - -# -# Additional device driver support -# -CONFIG_NET_BROADCOM=m -CONFIG_CIPE=m -# CONFIG_CRYPTO_AEP is not set -CONFIG_CRYPTO_BROADCOM=m -# CONFIG_MEGARAC is not set -CONFIG_FC_QLA2100=m -CONFIG_FC_QLA2200=m -CONFIG_FC_QLA2300=m -CONFIG_SCSI_ISCSI=m -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_LPFC=m -# CONFIG_FUSION_ISENSE is not set -# CONFIG_DCDBAS is not set -CONFIG_DELL_RBU=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_CHECKING=y -CONFIG_INIT_DEBUG=y -# CONFIG_IOMMU_DEBUG is not set -# CONFIG_IOMMU_LEAK is not set -CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_KALLSYMS=y - -# -# Library routines -# -CONFIG_CRC32=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_QSORT=y diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686-smp.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686-smp.config deleted file mode 100644 index c369622..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686-smp.config +++ /dev/null @@ -1,2383 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# 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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set -# CONFIG_M586NOCX8 is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -CONFIG_X86_CMPXCHG8=y -CONFIG_X86_L1_CACHE_SHIFT=5 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set -CONFIG_TOSHIBA=m -# CONFIG_OMNIBOOK is not set -CONFIG_I8K=m -CONFIG_THINKPAD=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -# CONFIG_HIGHMEM4G is not set -CONFIG_HIGHMEM64G=y -CONFIG_HIGHMEM=y -CONFIG_X86_PAE=y -CONFIG_FORCE_MAX_ZONEORDER=10 -CONFIG_1GB=y -# CONFIG_2GB is not set -# CONFIG_3GB is not set -CONFIG_HIGHIO=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -CONFIG_ES7000=y -CONFIG_X86_CLUSTERED_APIC=y -CONFIG_X86_NUMA=y -# CONFIG_X86_NUMAQ is not set -CONFIG_X86_SUMMIT=y -CONFIG_X86_CLUSTERED_APIC=y -CONFIG_HAVE_DEC_LOCK=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -CONFIG_NET=y -CONFIG_EVLOG=y -CONFIG_EVLOG_BUFSIZE=128 -CONFIG_EVLOG_FWPRINTK=y -# CONFIG_EVLOG_PRINTKWLOC is not set -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=m -CONFIG_HOTPLUG_PCI_COMPAQ=m -CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y -CONFIG_HOTPLUG_PCI_IBM=m -CONFIG_HOTPLUG_PCI_ACPI=m -CONFIG_HOTPLUG_PCI_AMD=m -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_MAX_USER_RT_PRIO=100 -CONFIG_MAX_RT_PRIO=0 -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_AUDIT=m -CONFIG_PM=y -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -CONFIG_APM_DO_ENABLE=y -# CONFIG_APM_CPU_IDLE is not set -CONFIG_APM_DISPLAY_BLANK=y -# CONFIG_APM_RTC_IS_GMT is not set -CONFIG_APM_ALLOW_INTS=y -CONFIG_SISBUG=m - -# -# ACPI Support -# -CONFIG_ACPI=y -# CONFIG_ACPI_HT_ONLY is not set -CONFIG_ACPI_INITRD=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -CONFIG_ACPI_ASUS=m -CONFIG_ACPI_TOSHIBA=m -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_RELAXED_AML=y -CONFIG_PROC_MM=y - -# -# Binary emulation of other systems -# -CONFIG_ABI=m -CONFIG_ABI_SVR4=m -CONFIG_ABI_UW7=m -CONFIG_ABI_SOLARIS=m -CONFIG_ABI_IBCS=m -CONFIG_ABI_ISC=m -CONFIG_ABI_SCO=m -CONFIG_ABI_WYSE=m -CONFIG_BINFMT_COFF=m -CONFIG_BINFMT_XOUT=m -CONFIG_BINFMT_XOUT_X286=y -CONFIG_ABI_SPX=y -CONFIG_ABI_XTI=y -CONFIG_ABI_TLI_OPTMGMT=y -# CONFIG_ABI_XTI_OPTMGMT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=m -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=m -CONFIG_MTD_CONCAT=m -CONFIG_MTD_REDBOOT_PARTS=m -CONFIG_MTD_CMDLINE_PARTS=m -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=m -CONFIG_MTD_BLOCK_RO=m -CONFIG_FTL=m -CONFIG_NFTL=m -# CONFIG_NFTL_RW is not set - -# -# 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 is not set -CONFIG_MTD_CFI_INTELEXT=m -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_STAA=m -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -CONFIG_MTD_ABSENT=m -CONFIG_MTD_OBSOLETE_CHIPS=y -CONFIG_MTD_AMDSTD=m -CONFIG_MTD_SHARP=m -CONFIG_MTD_JEDEC=m - -# -# Mapping drivers for chip access -# -CONFIG_MTD_PHYSMAP=m -CONFIG_MTD_PHYSMAP_START=8000000 -CONFIG_MTD_PHYSMAP_LEN=4000000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=2 -CONFIG_MTD_PNC2000=m -CONFIG_MTD_SC520CDP=m -CONFIG_MTD_NETSC520=m -CONFIG_MTD_SBC_GXX=m -CONFIG_MTD_ELAN_104NC=m -CONFIG_MTD_DILNETPC=m -CONFIG_MTD_DILNETPC_BOOTSIZE=80000 -CONFIG_MTD_MIXMEM=m -CONFIG_MTD_OCTAGON=m -CONFIG_MTD_VMAX=m -CONFIG_MTD_SCx200_DOCFLASH=m -CONFIG_MTD_L440GX=m -CONFIG_MTD_AMD76XROM=m -CONFIG_MTD_ICH2ROM=m -CONFIG_MTD_NETtel=m -CONFIG_MTD_SCB2_FLASH=m -CONFIG_MTD_PCI=m -CONFIG_MTD_PCMCIA=m - -# -# Self-contained MTD device drivers -# -CONFIG_MTD_PMC551=m -CONFIG_MTD_PMC551_BUGFIX=y -# CONFIG_MTD_PMC551_DEBUG is not set -CONFIG_MTD_SLRAM=m -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTD_BLKMTD=m -CONFIG_MTD_DOC1000=m -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOCPROBE=m -CONFIG_MTD_DOCPROBE_ADVANCED=y -CONFIG_MTD_DOCPROBE_ADDRESS=0000 -CONFIG_MTD_DOCPROBE_HIGH=y -CONFIG_MTD_DOCPROBE_55AA=y - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_IDS=m - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_PC_SUPERIO=y -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -CONFIG_PARPORT_OTHER=y -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=m - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_XD=m -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=m -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m -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_LOOP=y -CONFIG_CIPHER_TWOFISH=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=64000 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y - -# -# Enterprise Volume Management System -# -CONFIG_EVMS=m -CONFIG_EVMS_LOCAL_DEV_MGR=m -CONFIG_EVMS_DOS_SEGMENT_MGR=m -CONFIG_EVMS_GPT_SEGMENT_MGR=m -CONFIG_EVMS_SNAPSHOT=m -CONFIG_EVMS_DRIVELINK=m -CONFIG_EVMS_BBR=m -CONFIG_EVMS_LVM=m -CONFIG_EVMS_MD=m -CONFIG_EVMS_MD_LINEAR=m -CONFIG_EVMS_MD_RAID0=m -CONFIG_EVMS_MD_RAID1=m -CONFIG_EVMS_MD_RAID5=m -CONFIG_EVMS_AIX=m -CONFIG_EVMS_OS2=m -# CONFIG_EVMS_INFO_CRITICAL is not set -# CONFIG_EVMS_INFO_SERIOUS is not set -# CONFIG_EVMS_INFO_ERROR is not set -# CONFIG_EVMS_INFO_WARNING is not set -CONFIG_EVMS_INFO_DEFAULT=y -# CONFIG_EVMS_INFO_DETAILS is not set -# CONFIG_EVMS_INFO_DEBUG is not set -# CONFIG_EVMS_INFO_EXTRA is not set -# CONFIG_EVMS_INFO_ENTRY_EXIT is not set -# CONFIG_EVMS_INFO_EVERYTHING is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m -CONFIG_BLK_DEV_DM_MIRROR=m - -# -# Cryptography support (CryptoAPI) -# -CONFIG_CRYPTO=y -CONFIG_CIPHERS=y -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_3DES=m -CONFIG_CIPHER_NULL=m -CONFIG_CIPHER_DES=m -CONFIG_DIGESTS=y -CONFIG_DIGEST_MD5=m -CONFIG_DIGEST_SHA1=m -CONFIG_CRYPTODEV=y -CONFIG_CRYPTOLOOP=m -CONFIG_CRYPTOLOOP_ATOMIC=y -# CONFIG_CRYPTOLOOP_IV_HACK is not set -# CONFIG_CRYPTOLOOP_DEBUG is not set - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IPSEC=m -CONFIG_IPSEC_DEBUG=y -CONFIG_IPSEC_DEBUG_DISABLE_DEFAULT=y -CONFIG_IPSEC_TUNNEL=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -CONFIG_TUX_EXTENDED_LOG=y -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=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_INET_ECN=y -CONFIG_SYN_COOKIES=y -CONFIG_IP_IPSEC=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_PSD=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_IPLIMIT=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_STRING=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 -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 -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -# CONFIG_IPV6_DEBUG is not set -CONFIG_IPV6_IM=y -CONFIG_IPV6_MODULE_IP_GRE=y -CONFIG_IPV6_ISATAP=y -CONFIG_IPV6_PREFIXLIST=y -CONFIG_IPV6_6TO4_NEXTHOP=y -CONFIG_IPV6_PRIVACY=y -CONFIG_IPV6_SUBTREES=y -# CONFIG_IPV6_MLD6_ALL_DONE is not set -# CONFIG_IPV6_NODEINFO is not set -CONFIG_IPV6_ZONE=y -# CONFIG_IPV6_ZONE_SITELOCAL is not set -CONFIG_IPV6_DROP_FAKE_V4MAPPED=y - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IPV6_IPSEC=y -CONFIG_IPV6_IPSEC_TUNNEL=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_CN=m -CONFIG_IPV6_MOBILITY_MN=m -CONFIG_IPV6_MOBILITY_HA=m -# CONFIG_IPV6_MOBILITY_DEBUG is not set -# CONFIG_SHARED_IPV6_CARDS is not set -CONFIG_KHTTPD=m -CONFIG_KHTTPD_IPV6=y -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -CONFIG_ATM_CLIP_NO_ICMP=y -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -# CONFIG_ATM_BR2684_IPFILTER is not set -CONFIG_VLAN_8021Q=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -# CONFIG_DECNET_ROUTER is not set -CONFIG_BRIDGE=m -CONFIG_X25=m -CONFIG_LAPB=m -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -CONFIG_ECONET=m -# CONFIG_ECONET_AUNUDP is not set -# CONFIG_ECONET_NATIVE is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_ATM=y -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -CONFIG_IDEDISK_STROKE=y -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_BLK_DEV_CMD640=y -CONFIG_BLK_DEV_CMD640_ENHANCED=y -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_OFFBOARD=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -CONFIG_IDEDMA_ONLYDISK=y -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=m -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_BLK_DEV_NS87415=y -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -CONFIG_PDC202XX_BURST=y -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -CONFIG_BLK_DEV_SC1200=y -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -CONFIG_BLK_DEV_CENATEK=y -CONFIG_IDE_CHIPSETS=y -CONFIG_BLK_DEV_4DRIVES=y -CONFIG_BLK_DEV_ALI14XX=y -CONFIG_BLK_DEV_DTC2278=y -CONFIG_BLK_DEV_HT6560B=y -# CONFIG_BLK_DEV_PDC4030 is not set -CONFIG_BLK_DEV_QD65XX=y -CONFIG_BLK_DEV_UMC8672=y -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_MAX_MAJORS=144 -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=32 -CONFIG_CHR_DEV_SCH=m -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=5000 -CONFIG_AIC7XXX_PROBE_EISA_VL=y -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -CONFIG_AIC7XXX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_AIC79XX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=24 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_ATA=y -# CONFIG_SCSI_ATA_PATA is not set -# CONFIG_SCSI_ATA_ATAPI is not set -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_ATA_VIA=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=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_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_LPFC=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -CONFIG_SCSI_GENERIC_NCR53C400=y -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -CONFIG_SCSI_IPS_OLD=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_PPSCSI=m -CONFIG_PPSCSI_T348=m -CONFIG_PPSCSI_T358=m -CONFIG_PPSCSI_VPI0=m -CONFIG_PPSCSI_VPI2=m -CONFIG_PPSCSI_ONSCSI=m -CONFIG_PPSCSI_SPARCSI=m -CONFIG_PPSCSI_EPSA2=m -CONFIG_PPSCSI_EPST=m -CONFIG_SCSI_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=80 -CONFIG_SCSI_NCR53C8XX_PROFILE=y -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX_PQS_PDS=y -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_QLOGIC_QLA2XXX=y -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m -CONFIG_SCSI_QLA2XXX_60500=y -CONFIG_SCSI_QLA2XXX_QLA2100_60500=m -CONFIG_SCSI_QLA2XXX_QLA2200_60500=m -CONFIG_SCSI_QLA2XXX_QLA2300_60500=m -CONFIG_SCSI_QLA2XXX_60650=y -CONFIG_SCSI_QLA2XXX_QLA2100_60650=m -CONFIG_SCSI_QLA2XXX_QLA2200_60650=m -CONFIG_SCSI_QLA2XXX_QLA2300_60650=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC395x_TRMS1040=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_PDC_ULTRA=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -CONFIG_IEEE1394_OUI_DB=y - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -CONFIG_ARCNET=m -CONFIG_ARCNET_1201=m -CONFIG_ARCNET_1051=m -CONFIG_ARCNET_RAW=m -CONFIG_ARCNET_COM90xx=m -CONFIG_ARCNET_COM90xxIO=m -CONFIG_ARCNET_RIM_I=m -CONFIG_ARCNET_COM20020=m -CONFIG_ARCNET_COM20020_ISA=m -CONFIG_ARCNET_COM20020_PCI=m -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -CONFIG_EWRK3=m -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_PCNET32_OLD=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_NET_BCM4400=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NETGEAR_GA621=m -CONFIG_NETGEAR_GA622=m -CONFIG_NE2K_PCI=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NEW=m -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_SK98LIN_T1=y -CONFIG_SK98LIN_T3=y -CONFIG_SK98LIN_T8=y -CONFIG_SK98LIN_T6=y -CONFIG_SK98LIN_T9=y -CONFIG_SK98LIN_T4=y -CONFIG_SK98LIN_T7=y -CONFIG_SK98LIN_T2=y -CONFIG_SK98LIN_T5=y -CONFIG_SK9DLIN=m -CONFIG_TIGON3=m -CONFIG_NET_BROADCOM=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=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_PPPOE=m -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -CONFIG_TMSISA=m -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -CONFIG_RCPCI=m -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -CONFIG_COMX=m -CONFIG_COMX_HW_COMX=m -CONFIG_COMX_HW_LOCOMX=m -CONFIG_COMX_HW_MIXCOM=m -CONFIG_COMX_HW_MUNICH=m -CONFIG_COMX_PROTO_PPP=m -CONFIG_COMX_PROTO_LAPB=m -CONFIG_COMX_PROTO_FR=m -CONFIG_DSCC4=m -CONFIG_LANMEDIA=m -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -CONFIG_SYNCLINK_SYNCPPP=m -CONFIG_HDLC=m -CONFIG_HDLC_RAW=y -CONFIG_HDLC_CISCO=y -CONFIG_HDLC_FR=y -CONFIG_HDLC_PPP=y -CONFIG_HDLC_X25=y -CONFIG_N2=m -CONFIG_C101=m -CONFIG_FARSYNC=m -# CONFIG_HDLC_DEBUG_PKT is not set -# CONFIG_HDLC_DEBUG_HARD_HEADER is not set -# CONFIG_HDLC_DEBUG_ECN is not set -# CONFIG_HDLC_DEBUG_RINGS is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -# CONFIG_WANPIPE_FR is not set -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -CONFIG_LAPBETHER=m -CONFIG_X25_ASY=m -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_ARCNET_COM20020_CS=m -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y -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_DMASCC=m -CONFIG_SCC=m -CONFIG_SCC_DELAY=y -CONFIG_SCC_TRXECHO=y -CONFIG_BAYCOM_SER_FDX=m -CONFIG_BAYCOM_SER_HDX=m -CONFIG_BAYCOM_PAR=m -CONFIG_BAYCOM_EPP=m -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -CONFIG_YAM=m - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -# CONFIG_IRDA_FAST_RR is not set -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_IPPP_FILTER=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y -CONFIG_ISDN_X25=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -CONFIG_ISDN_DIVERSION=m - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y -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 -CONFIG_HISAX_16_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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 -CONFIG_HISAX_TELES_CS=m -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -CONFIG_ISDN_DRV_SC=m -CONFIG_ISDN_DRV_ACT2000=m -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -CONFIG_ISDN_DRV_EICON_OLD=m -CONFIG_ISDN_DRV_EICON_PCI=y -CONFIG_ISDN_DRV_EICON_ISA=y -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -CONFIG_CD_NO_IDESCSI=y -CONFIG_AZTCD=m -CONFIG_GSCD=m -CONFIG_SBPCD=m -CONFIG_MCD=m -CONFIG_MCD_IRQ=11 -CONFIG_MCD_BASE=300 -CONFIG_MCDX=m -CONFIG_OPTCD=m -CONFIG_CM206=m -CONFIG_SJCD=m -CONFIG_ISP16_CDI=m -CONFIG_CDU31A=m -CONFIG_CDU535=m - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -CONFIG_HUB6=y -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_COMPUTONE=m -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -CONFIG_SYNCLINK=m -CONFIG_SYNCLINKMP=m -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -CONFIG_RIO=m -CONFIG_RIO_OLDPCI=y -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -CONFIG_SCx200_I2C=m -CONFIG_SCx200_I2C_SCL=12 -CONFIG_SCx200_I2C_SDA=13 -CONFIG_SCx200_ACB=m -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -CONFIG_I2C_I810=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m -CONFIG_I2C_SIS645=m -CONFIG_I2C_SAVAGE4=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=y -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_FM801=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -CONFIG_QIC02_TAPE=m -CONFIG_QIC02_DYNCONF=y -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -CONFIG_MIXCOMWD=m -CONFIG_60XX_WDT=m -CONFIG_SC1200_WDT=m -CONFIG_SCx200_WDT=m -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -CONFIG_WDT_501=y -CONFIG_WDT_501_FAN=y -CONFIG_MACHZ_WDT=m -CONFIG_DEADMAN=m -CONFIG_HANGCHECK_TIMER=m -CONFIG_AMD7XX_TCO=m -CONFIG_SCx200_GPIO=m -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -CONFIG_APPLICOM=m -CONFIG_SONYPI=m - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_AGP_NVIDIA=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m -CONFIG_IBMASM=y -CONFIG_IBMASM_ASM=m -CONFIG_IBMASM_SER=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -CONFIG_VIDEO_MEYE=m - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m -CONFIG_DXR3=y -CONFIG_EM8300=m -# CONFIG_EM8300_LOOPBACK is not set -# CONFIG_EM8300_UCODETIMEOUT is not set -# CONFIG_EM8300_DICOMFIX is not set -# CONFIG_EM8300_DICOMCTRL is not set -CONFIG_EM8300_DICOMPAL=y -CONFIG_ADV717X=m -# CONFIG_ADV717X_SWAP is not set -# CONFIG_ADV717X_PIXELPORT16BIT is not set -# CONFIG_ADV717X_PIXELPORTPAL is not set -CONFIG_BT865=m - -# -# File systems -# -CONFIG_QUOTA=y -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_QIFACE_COMPAT=y -# CONFIG_QIFACE_V1 is not set -CONFIG_QIFACE_V2=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=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_XATTR_USER=y -CONFIG_REISERFS_FS_XATTR_TRUSTED=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_ADFS_FS=m -# CONFIG_ADFS_FS_RW is not set -CONFIG_AFFS_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_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -CONFIG_JBD_DEBUG=y -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FATX_FS=m -CONFIG_EFS_FS=m -CONFIG_JFFS_FS=m -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -# CONFIG_JFS_DEBUG is not set -CONFIG_JFS_STATISTICS=y -CONFIG_MINIX_FS=y -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -CONFIG_HPFS_FS=m -CONFIG_PROC_FS=y -CONFIG_PROC_CONFIG=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -CONFIG_QNX4FS_FS=m -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -CONFIG_EXT2_FS_XATTR_TRUSTED=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -CONFIG_XFS_FS=m -CONFIG_XFS_POSIX_ACL=y -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_DMAPI=y -# CONFIG_XFS_DEBUG is not set -# CONFIG_PAGEBUF_DEBUG is not set -CONFIG_OCFS_FS=m - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_INTERMEZZO_FS=m -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_ACL=y -CONFIG_NFS_DIRECTIO=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_NFSD_FHALIAS=y -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_CIFS=m -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y - -# -# 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_XBOX_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 is not set -CONFIG_SGI_PARTITION=y -CONFIG_ULTRIX_PARTITION=y -CONFIG_SUN_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -CONFIG_FB_PM2_FIFO_DISCONNECT=y -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -CONFIG_UNICON=y -CONFIG_UNICON_GB=m -CONFIG_UNICON_GBK=m -CONFIG_UNICON_BIG5=m -CONFIG_UNICON_JIS=m -CONFIG_UNICON_KSCM=m -CONFIG_FB_CYBER2000=m -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -CONFIG_FB_MATROX_PROC=m -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_INTEL=m -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_VMWARE_SVGA=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -CONFIG_FB_TRIDENT=m -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_SPLASHSCREEN=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_ADVANCED=y -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB2=m -CONFIG_FBCON_CFB4=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_AFB=m -CONFIG_FBCON_ILBM=m -CONFIG_FBCON_IPLAN2P2=m -CONFIG_FBCON_IPLAN2P4=m -CONFIG_FBCON_IPLAN2P8=m -CONFIG_FBCON_MAC=m -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_VGA=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -CONFIG_SOUND_TRACEINIT=y -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -# CONFIG_SOUND_GUS16 is not set -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -CONFIG_PSS_MIXER=y -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -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_SEQUENCER_OSS=y -CONFIG_SND_VERBOSE_PRINTK=y -CONFIG_SND_DEBUG=y -CONFIG_SND_DEBUG_MEMORY=y -# CONFIG_SND_DEBUG_DETECT is not set - -# -# Generic devices -# -CONFIG_SND_DUMMY=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -CONFIG_SND_SERIAL_U16550=m -CONFIG_SND_MPU401=m -CONFIG_SND_SERIALMIDI=m - -# -# ISA devices -# -CONFIG_SND_AD1816A=m -CONFIG_SND_AD1848=m -CONFIG_SND_CS4231=m -CONFIG_SND_CS4232=m -CONFIG_SND_CS4236=m -CONFIG_SND_ES968=m -CONFIG_SND_ES1688=m -CONFIG_SND_ES18XX=m -CONFIG_SND_GUSCLASSIC=m -CONFIG_SND_GUSEXTREME=m -CONFIG_SND_GUSMAX=m -CONFIG_SND_INTERWAVE=m -CONFIG_SND_INTERWAVE_STB=m -CONFIG_SND_OPTI92X_AD1848=m -CONFIG_SND_OPTI92X_CS4231=m -CONFIG_SND_OPTI93X=m -CONFIG_SND_SB8=m -CONFIG_SND_SB16=m -CONFIG_SND_SBAWE=m -CONFIG_SND_SB16_CSP=y -CONFIG_SND_WAVEFRONT=m -CONFIG_SND_ALS100=m -CONFIG_SND_AZT2320=m -CONFIG_SND_CMI8330=m -CONFIG_SND_DT019X=m -CONFIG_SND_OPL3SA2=m -CONFIG_SND_SGALAXY=m -CONFIG_SND_SSCAPE=m -CONFIG_SND_MSND_PINNACLE=m - -# -# PCI devices -# -CONFIG_SND_ALI5451=m -CONFIG_SND_CS46XX=m -CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CS4281=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_PDPLUS=m -CONFIG_SND_KORG1212=m -CONFIG_SND_NM256=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_HDSP=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_YMFPCI=m -CONFIG_SND_ALS4000=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_FM801=m -CONFIG_SND_ICE1712=m -CONFIG_SND_ICE1724=m -CONFIG_SND_INTEL8X0=m -CONFIG_SND_SONICVIBES=m -CONFIG_SND_VIA82XX=m -CONFIG_SND_VX222=m -CONFIG_SND_MIXART=m -CONFIG_SND_AZT3328=m - -# -# ALSA USB devices -# -CONFIG_SND_USB_AUDIO=m - -# -# ALSA PCMCIA devices -# -CONFIG_SND_VXPOCKET=m -CONFIG_SND_VXP440=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m -CONFIG_USB_AUDIO=m -CONFIG_USB_EMI26=m -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m -CONFIG_USB_DC2XX=m -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_LOGITECH_CAM=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_AX8817X=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USBDNET=m -CONFIG_USB_USBDNET_VENDOR=0000 -CONFIG_USB_USBDNET_PRODUCT=0000 -CONFIG_USB_USBDNET_CLASS=0000 -CONFIG_USB_USBDNET_SUBCLASS=0000 -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -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_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SAFE_SERIAL_VENDOR=0000 -CONFIG_USB_SAFE_SERIAL_PRODUCT=0000 -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m -CONFIG_USB_SPEEDTOUCH=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y -CONFIG_BLUEZ_CMTP=m - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -# CONFIG_BLUEZ_USB_ZERO_PACKET is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIBFUSB=m -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Kernel hacking -# -CONFIG_DUMP=m -CONFIG_DUMP_COMPRESS_RLE=m -CONFIG_DUMP_COMPRESS_GZIP=m -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_HZ is not set -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_KMSGDUMP is not set -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_FRAME_POINTER=y -# CONFIG_HIGHMEM_EMULATION is not set -# CONFIG_X86_REMOTE_DEBUG is not set -# CONFIG_KDB is not set -# CONFIG_KDB_MODULES is not set -CONFIG_KALLSYMS=y -# CONFIG_HOOK is not set -CONFIG_VTUNE=m - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m -CONFIG_QSORT=y -CONFIG_FW_LOADER=m - -# -# Build options -# -# CONFIG_SUSE_KERNEL is not set -CONFIG_UNITEDLINUX_KERNEL=y -CONFIG_CFGNAME="smp" -CONFIG_RELEASE="273" diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686.config deleted file mode 100644 index c369622..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-sles-2.4-i686.config +++ /dev/null @@ -1,2383 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86=y -# CONFIG_SBUS is not set -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# 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_MPENTIUMIII is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MELAN is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set -# CONFIG_M586NOCX8 is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_CMPXCHG=y -CONFIG_X86_XADD=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -CONFIG_X86_CMPXCHG8=y -CONFIG_X86_L1_CACHE_SHIFT=5 -CONFIG_X86_HAS_TSC=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_PGE=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_F00F_WORKS_OK=y -CONFIG_X86_MCE=y - -# -# CPU Frequency scaling -# -# CONFIG_CPU_FREQ is not set -CONFIG_TOSHIBA=m -# CONFIG_OMNIBOOK is not set -CONFIG_I8K=m -CONFIG_THINKPAD=m -CONFIG_MICROCODE=m -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -CONFIG_EDD=m -# CONFIG_NOHIGHMEM is not set -# CONFIG_HIGHMEM4G is not set -CONFIG_HIGHMEM64G=y -CONFIG_HIGHMEM=y -CONFIG_X86_PAE=y -CONFIG_FORCE_MAX_ZONEORDER=10 -CONFIG_1GB=y -# CONFIG_2GB is not set -# CONFIG_3GB is not set -CONFIG_HIGHIO=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MTRR=y -CONFIG_SMP=y -CONFIG_ES7000=y -CONFIG_X86_CLUSTERED_APIC=y -CONFIG_X86_NUMA=y -# CONFIG_X86_NUMAQ is not set -CONFIG_X86_SUMMIT=y -CONFIG_X86_CLUSTERED_APIC=y -CONFIG_HAVE_DEC_LOCK=y -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -CONFIG_NET=y -CONFIG_EVLOG=y -CONFIG_EVLOG_BUFSIZE=128 -CONFIG_EVLOG_FWPRINTK=y -# CONFIG_EVLOG_PRINTKWLOC is not set -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_ISA=y -CONFIG_PCI_NAMES=y -CONFIG_EISA=y -# CONFIG_MCA is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=m -CONFIG_HOTPLUG_PCI_COMPAQ=m -CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y -CONFIG_HOTPLUG_PCI_IBM=m -CONFIG_HOTPLUG_PCI_ACPI=m -CONFIG_HOTPLUG_PCI_AMD=m -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_MAX_USER_RT_PRIO=100 -CONFIG_MAX_RT_PRIO=0 -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_AUDIT=m -CONFIG_PM=y -CONFIG_APM=y -# CONFIG_APM_IGNORE_USER_SUSPEND is not set -CONFIG_APM_DO_ENABLE=y -# CONFIG_APM_CPU_IDLE is not set -CONFIG_APM_DISPLAY_BLANK=y -# CONFIG_APM_RTC_IS_GMT is not set -CONFIG_APM_ALLOW_INTS=y -CONFIG_SISBUG=m - -# -# ACPI Support -# -CONFIG_ACPI=y -# CONFIG_ACPI_HT_ONLY is not set -CONFIG_ACPI_INITRD=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -CONFIG_ACPI_ASUS=m -CONFIG_ACPI_TOSHIBA=m -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_RELAXED_AML=y -CONFIG_PROC_MM=y - -# -# Binary emulation of other systems -# -CONFIG_ABI=m -CONFIG_ABI_SVR4=m -CONFIG_ABI_UW7=m -CONFIG_ABI_SOLARIS=m -CONFIG_ABI_IBCS=m -CONFIG_ABI_ISC=m -CONFIG_ABI_SCO=m -CONFIG_ABI_WYSE=m -CONFIG_BINFMT_COFF=m -CONFIG_BINFMT_XOUT=m -CONFIG_BINFMT_XOUT_X286=y -CONFIG_ABI_SPX=y -CONFIG_ABI_XTI=y -CONFIG_ABI_TLI_OPTMGMT=y -# CONFIG_ABI_XTI_OPTMGMT is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=m -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=m -CONFIG_MTD_CONCAT=m -CONFIG_MTD_REDBOOT_PARTS=m -CONFIG_MTD_CMDLINE_PARTS=m -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=m -CONFIG_MTD_BLOCK_RO=m -CONFIG_FTL=m -CONFIG_NFTL=m -# CONFIG_NFTL_RW is not set - -# -# 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 is not set -CONFIG_MTD_CFI_INTELEXT=m -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_STAA=m -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -CONFIG_MTD_ABSENT=m -CONFIG_MTD_OBSOLETE_CHIPS=y -CONFIG_MTD_AMDSTD=m -CONFIG_MTD_SHARP=m -CONFIG_MTD_JEDEC=m - -# -# Mapping drivers for chip access -# -CONFIG_MTD_PHYSMAP=m -CONFIG_MTD_PHYSMAP_START=8000000 -CONFIG_MTD_PHYSMAP_LEN=4000000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=2 -CONFIG_MTD_PNC2000=m -CONFIG_MTD_SC520CDP=m -CONFIG_MTD_NETSC520=m -CONFIG_MTD_SBC_GXX=m -CONFIG_MTD_ELAN_104NC=m -CONFIG_MTD_DILNETPC=m -CONFIG_MTD_DILNETPC_BOOTSIZE=80000 -CONFIG_MTD_MIXMEM=m -CONFIG_MTD_OCTAGON=m -CONFIG_MTD_VMAX=m -CONFIG_MTD_SCx200_DOCFLASH=m -CONFIG_MTD_L440GX=m -CONFIG_MTD_AMD76XROM=m -CONFIG_MTD_ICH2ROM=m -CONFIG_MTD_NETtel=m -CONFIG_MTD_SCB2_FLASH=m -CONFIG_MTD_PCI=m -CONFIG_MTD_PCMCIA=m - -# -# Self-contained MTD device drivers -# -CONFIG_MTD_PMC551=m -CONFIG_MTD_PMC551_BUGFIX=y -# CONFIG_MTD_PMC551_DEBUG is not set -CONFIG_MTD_SLRAM=m -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTD_BLKMTD=m -CONFIG_MTD_DOC1000=m -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOCPROBE=m -CONFIG_MTD_DOCPROBE_ADVANCED=y -CONFIG_MTD_DOCPROBE_ADDRESS=0000 -CONFIG_MTD_DOCPROBE_HIGH=y -CONFIG_MTD_DOCPROBE_55AA=y - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_IDS=m - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_PC_SUPERIO=y -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -CONFIG_PARPORT_OTHER=y -CONFIG_PARPORT_1284=y - -# -# Plug and Play configuration -# -CONFIG_PNP=y -CONFIG_ISAPNP=m - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_XD=m -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=m -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m -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_LOOP=y -CONFIG_CIPHER_TWOFISH=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=64000 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y - -# -# Enterprise Volume Management System -# -CONFIG_EVMS=m -CONFIG_EVMS_LOCAL_DEV_MGR=m -CONFIG_EVMS_DOS_SEGMENT_MGR=m -CONFIG_EVMS_GPT_SEGMENT_MGR=m -CONFIG_EVMS_SNAPSHOT=m -CONFIG_EVMS_DRIVELINK=m -CONFIG_EVMS_BBR=m -CONFIG_EVMS_LVM=m -CONFIG_EVMS_MD=m -CONFIG_EVMS_MD_LINEAR=m -CONFIG_EVMS_MD_RAID0=m -CONFIG_EVMS_MD_RAID1=m -CONFIG_EVMS_MD_RAID5=m -CONFIG_EVMS_AIX=m -CONFIG_EVMS_OS2=m -# CONFIG_EVMS_INFO_CRITICAL is not set -# CONFIG_EVMS_INFO_SERIOUS is not set -# CONFIG_EVMS_INFO_ERROR is not set -# CONFIG_EVMS_INFO_WARNING is not set -CONFIG_EVMS_INFO_DEFAULT=y -# CONFIG_EVMS_INFO_DETAILS is not set -# CONFIG_EVMS_INFO_DEBUG is not set -# CONFIG_EVMS_INFO_EXTRA is not set -# CONFIG_EVMS_INFO_ENTRY_EXIT is not set -# CONFIG_EVMS_INFO_EVERYTHING is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m -CONFIG_BLK_DEV_DM_MIRROR=m - -# -# Cryptography support (CryptoAPI) -# -CONFIG_CRYPTO=y -CONFIG_CIPHERS=y -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_3DES=m -CONFIG_CIPHER_NULL=m -CONFIG_CIPHER_DES=m -CONFIG_DIGESTS=y -CONFIG_DIGEST_MD5=m -CONFIG_DIGEST_SHA1=m -CONFIG_CRYPTODEV=y -CONFIG_CRYPTOLOOP=m -CONFIG_CRYPTOLOOP_ATOMIC=y -# CONFIG_CRYPTOLOOP_IV_HACK is not set -# CONFIG_CRYPTOLOOP_DEBUG is not set - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IPSEC=m -CONFIG_IPSEC_DEBUG=y -CONFIG_IPSEC_DEBUG_DISABLE_DEFAULT=y -CONFIG_IPSEC_TUNNEL=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -CONFIG_TUX_EXTENDED_LOG=y -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=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_INET_ECN=y -CONFIG_SYN_COOKIES=y -CONFIG_IP_IPSEC=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_PSD=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_IPLIMIT=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_STRING=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 -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 -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -# CONFIG_IPV6_DEBUG is not set -CONFIG_IPV6_IM=y -CONFIG_IPV6_MODULE_IP_GRE=y -CONFIG_IPV6_ISATAP=y -CONFIG_IPV6_PREFIXLIST=y -CONFIG_IPV6_6TO4_NEXTHOP=y -CONFIG_IPV6_PRIVACY=y -CONFIG_IPV6_SUBTREES=y -# CONFIG_IPV6_MLD6_ALL_DONE is not set -# CONFIG_IPV6_NODEINFO is not set -CONFIG_IPV6_ZONE=y -# CONFIG_IPV6_ZONE_SITELOCAL is not set -CONFIG_IPV6_DROP_FAKE_V4MAPPED=y - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IPV6_IPSEC=y -CONFIG_IPV6_IPSEC_TUNNEL=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_CN=m -CONFIG_IPV6_MOBILITY_MN=m -CONFIG_IPV6_MOBILITY_HA=m -# CONFIG_IPV6_MOBILITY_DEBUG is not set -# CONFIG_SHARED_IPV6_CARDS is not set -CONFIG_KHTTPD=m -CONFIG_KHTTPD_IPV6=y -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -CONFIG_ATM_CLIP_NO_ICMP=y -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -# CONFIG_ATM_BR2684_IPFILTER is not set -CONFIG_VLAN_8021Q=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_LTPC=m -CONFIG_COPS=m -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -# CONFIG_DECNET_ROUTER is not set -CONFIG_BRIDGE=m -CONFIG_X25=m -CONFIG_LAPB=m -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -CONFIG_ECONET=m -# CONFIG_ECONET_AUNUDP is not set -# CONFIG_ECONET_NATIVE is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_ATM=y -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -CONFIG_IDEDISK_STROKE=y -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_BLK_DEV_CMD640=y -CONFIG_BLK_DEV_CMD640_ENHANCED=y -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_OFFBOARD=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -CONFIG_IDEDMA_ONLYDISK=y -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA100=m -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_BLK_DEV_NS87415=y -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -CONFIG_PDC202XX_BURST=y -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -CONFIG_BLK_DEV_RZ1000=y -CONFIG_BLK_DEV_SC1200=y -CONFIG_BLK_DEV_SVWKS=y -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -# CONFIG_BLK_DEV_TRM290 is not set -CONFIG_BLK_DEV_VIA82CXXX=y -CONFIG_BLK_DEV_CENATEK=y -CONFIG_IDE_CHIPSETS=y -CONFIG_BLK_DEV_4DRIVES=y -CONFIG_BLK_DEV_ALI14XX=y -CONFIG_BLK_DEV_DTC2278=y -CONFIG_BLK_DEV_HT6560B=y -# CONFIG_BLK_DEV_PDC4030 is not set -CONFIG_BLK_DEV_QD65XX=y -CONFIG_BLK_DEV_UMC8672=y -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_MAX_MAJORS=144 -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=32 -CONFIG_CHR_DEV_SCH=m -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_7000FASST=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AHA152X=m -CONFIG_SCSI_AHA1542=m -CONFIG_SCSI_AHA1740=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=5000 -CONFIG_AIC7XXX_PROBE_EISA_VL=y -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -CONFIG_AIC7XXX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_AIC79XX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=24 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_ATA=y -# CONFIG_SCSI_ATA_PATA is not set -# CONFIG_SCSI_ATA_ATAPI is not set -CONFIG_SCSI_ATA_PIIX=m -CONFIG_SCSI_ATA_VIA=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -CONFIG_SCSI_DTC3280=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_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_LPFC=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -CONFIG_SCSI_GENERIC_NCR53C400=y -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -CONFIG_SCSI_IPS_OLD=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_PPSCSI=m -CONFIG_PPSCSI_T348=m -CONFIG_PPSCSI_T358=m -CONFIG_PPSCSI_VPI0=m -CONFIG_PPSCSI_VPI2=m -CONFIG_PPSCSI_ONSCSI=m -CONFIG_PPSCSI_SPARCSI=m -CONFIG_PPSCSI_EPSA2=m -CONFIG_PPSCSI_EPST=m -CONFIG_SCSI_NCR53C406A=m -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=80 -CONFIG_SCSI_NCR53C8XX_PROFILE=y -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX_PQS_PDS=y -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -CONFIG_SCSI_PAS16=m -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -CONFIG_SCSI_PSI240I=m -CONFIG_SCSI_QLOGIC_FAS=m -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_QLOGIC_QLA2XXX=y -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m -CONFIG_SCSI_QLA2XXX_60500=y -CONFIG_SCSI_QLA2XXX_QLA2100_60500=m -CONFIG_SCSI_QLA2XXX_QLA2200_60500=m -CONFIG_SCSI_QLA2XXX_QLA2300_60500=m -CONFIG_SCSI_QLA2XXX_60650=y -CONFIG_SCSI_QLA2XXX_QLA2100_60650=m -CONFIG_SCSI_QLA2XXX_QLA2200_60650=m -CONFIG_SCSI_QLA2XXX_QLA2300_60650=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC395x_TRMS1040=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -CONFIG_SCSI_T128=m -CONFIG_SCSI_U14_34F=m -CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_PDC_ULTRA=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -CONFIG_IEEE1394_OUI_DB=y - -# -# I2O device support -# -CONFIG_I2O=m -CONFIG_I2O_PCI=m -CONFIG_I2O_BLOCK=m -CONFIG_I2O_LAN=m -CONFIG_I2O_SCSI=m -CONFIG_I2O_PROC=m - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -CONFIG_ARCNET=m -CONFIG_ARCNET_1201=m -CONFIG_ARCNET_1051=m -CONFIG_ARCNET_RAW=m -CONFIG_ARCNET_COM90xx=m -CONFIG_ARCNET_COM90xxIO=m -CONFIG_ARCNET_RIM_I=m -CONFIG_ARCNET_COM20020=m -CONFIG_ARCNET_COM20020_ISA=m -CONFIG_ARCNET_COM20020_PCI=m -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m -CONFIG_NET_SB1000=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_EL1=m -CONFIG_EL2=m -CONFIG_ELPLUS=m -CONFIG_EL16=m -CONFIG_EL3=m -CONFIG_3C515=m -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_LANCE=m -CONFIG_NET_VENDOR_SMC=y -CONFIG_WD80x3=m -# CONFIG_ULTRAMCA is not set -CONFIG_ULTRA=m -CONFIG_ULTRA32=m -CONFIG_SMC9194=m -CONFIG_NET_VENDOR_RACAL=y -CONFIG_NI5010=m -CONFIG_NI52=m -CONFIG_NI65=m -CONFIG_AT1700=m -CONFIG_DEPCA=m -CONFIG_HP100=m -CONFIG_NET_ISA=y -CONFIG_E2100=m -CONFIG_EWRK3=m -CONFIG_EEXPRESS=m -CONFIG_EEXPRESS_PRO=m -CONFIG_HPLAN_PLUS=m -CONFIG_HPLAN=m -CONFIG_LP486E=m -CONFIG_ETH16I=m -CONFIG_NE2000=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_PCNET32_OLD=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_AC3200=m -CONFIG_APRICOT=m -CONFIG_NET_BCM4400=m -CONFIG_CS89x0=m -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -CONFIG_LNE390=m -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NETGEAR_GA621=m -CONFIG_NETGEAR_GA622=m -CONFIG_NE2K_PCI=m -CONFIG_NE3210=m -CONFIG_ES3210=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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -CONFIG_ATP=m -CONFIG_DE600=m -CONFIG_DE620=m - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -CONFIG_E1000_NEW=m -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_SK98LIN_T1=y -CONFIG_SK98LIN_T3=y -CONFIG_SK98LIN_T8=y -CONFIG_SK98LIN_T6=y -CONFIG_SK98LIN_T9=y -CONFIG_SK98LIN_T4=y -CONFIG_SK98LIN_T7=y -CONFIG_SK98LIN_T2=y -CONFIG_SK98LIN_T5=y -CONFIG_SK9DLIN=m -CONFIG_TIGON3=m -CONFIG_NET_BROADCOM=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=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_PPPOE=m -CONFIG_PPPOATM=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_ARLAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -CONFIG_TR=y -CONFIG_IBMTR=m -CONFIG_IBMOL=m -CONFIG_IBMLS=m -CONFIG_3C359=m -CONFIG_TMS380TR=m -CONFIG_TMSPCI=m -CONFIG_TMSISA=m -CONFIG_ABYSS=m -# CONFIG_MADGEMC is not set -CONFIG_SMCTR=m -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -CONFIG_RCPCI=m -CONFIG_SHAPER=m - -# -# Wan interfaces -# -CONFIG_WAN=y -CONFIG_HOSTESS_SV11=m -CONFIG_COSA=m -CONFIG_COMX=m -CONFIG_COMX_HW_COMX=m -CONFIG_COMX_HW_LOCOMX=m -CONFIG_COMX_HW_MIXCOM=m -CONFIG_COMX_HW_MUNICH=m -CONFIG_COMX_PROTO_PPP=m -CONFIG_COMX_PROTO_LAPB=m -CONFIG_COMX_PROTO_FR=m -CONFIG_DSCC4=m -CONFIG_LANMEDIA=m -CONFIG_ATI_XX20=m -CONFIG_SEALEVEL_4021=m -CONFIG_SYNCLINK_SYNCPPP=m -CONFIG_HDLC=m -CONFIG_HDLC_RAW=y -CONFIG_HDLC_CISCO=y -CONFIG_HDLC_FR=y -CONFIG_HDLC_PPP=y -CONFIG_HDLC_X25=y -CONFIG_N2=m -CONFIG_C101=m -CONFIG_FARSYNC=m -# CONFIG_HDLC_DEBUG_PKT is not set -# CONFIG_HDLC_DEBUG_HARD_HEADER is not set -# CONFIG_HDLC_DEBUG_ECN is not set -# CONFIG_HDLC_DEBUG_RINGS is not set -CONFIG_DLCI=m -CONFIG_DLCI_COUNT=24 -CONFIG_DLCI_MAX=8 -CONFIG_SDLA=m -CONFIG_WAN_ROUTER_DRIVERS=y -CONFIG_VENDOR_SANGOMA=m -CONFIG_WANPIPE_CHDLC=y -# CONFIG_WANPIPE_FR is not set -CONFIG_WANPIPE_X25=y -CONFIG_WANPIPE_PPP=y -CONFIG_WANPIPE_MULTPPP=y -CONFIG_CYCLADES_SYNC=m -CONFIG_CYCLOMX_X25=y -CONFIG_LAPBETHER=m -CONFIG_X25_ASY=m -CONFIG_SBNI=m -CONFIG_SBNI_MULTILINE=y - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_ARCNET_COM20020_CS=m -CONFIG_PCMCIA_IBMTR=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_AIRONET4500_CS=m - -# -# ATM drivers -# -CONFIG_ATM_TCP=m -CONFIG_ATM_LANAI=m -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -CONFIG_ATM_ZATM=m -# CONFIG_ATM_ZATM_DEBUG is not set -CONFIG_ATM_ZATM_EXACT_TS=y -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=y -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_MAYBE=m -CONFIG_ATM_FORE200E_PCA=y -CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y -CONFIG_ATM_FORE200E_TX_RETRY=16 -CONFIG_ATM_FORE200E_DEBUG=0 -CONFIG_ATM_FORE200E=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y -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_DMASCC=m -CONFIG_SCC=m -CONFIG_SCC_DELAY=y -CONFIG_SCC_TRXECHO=y -CONFIG_BAYCOM_SER_FDX=m -CONFIG_BAYCOM_SER_HDX=m -CONFIG_BAYCOM_PAR=m -CONFIG_BAYCOM_EPP=m -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -CONFIG_YAM=m - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -# CONFIG_IRDA_FAST_RR is not set -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -CONFIG_TOSHIBA_OLD=m -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_IPPP_FILTER=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y -CONFIG_ISDN_X25=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -CONFIG_ISDN_DIVERSION=m - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y -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 -CONFIG_HISAX_16_0=y -CONFIG_HISAX_16_3=y -CONFIG_HISAX_AVM_A1=y -CONFIG_HISAX_IX1MICROR2=y -CONFIG_HISAX_ASUSCOM=y -CONFIG_HISAX_TELEINT=y -CONFIG_HISAX_HFCS=y -CONFIG_HISAX_SPORTSTER=y -CONFIG_HISAX_MIC=y -CONFIG_HISAX_ISURF=y -CONFIG_HISAX_HSTSAPHIR=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 -CONFIG_HISAX_TELES_CS=m -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -CONFIG_ISDN_DRV_SC=m -CONFIG_ISDN_DRV_ACT2000=m -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -CONFIG_ISDN_DRV_EICON_OLD=m -CONFIG_ISDN_DRV_EICON_PCI=y -CONFIG_ISDN_DRV_EICON_ISA=y -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -CONFIG_ISDN_DRV_AVMB1_B1ISA=m -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_T1ISA=m -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_HYSDN=m -CONFIG_HYSDN_CAPI=y - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -CONFIG_CD_NO_IDESCSI=y -CONFIG_AZTCD=m -CONFIG_GSCD=m -CONFIG_SBPCD=m -CONFIG_MCD=m -CONFIG_MCD_IRQ=11 -CONFIG_MCD_BASE=300 -CONFIG_MCDX=m -CONFIG_OPTCD=m -CONFIG_CM206=m -CONFIG_SJCD=m -CONFIG_ISP16_CDI=m -CONFIG_CDU31A=m -CONFIG_CDU535=m - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -CONFIG_HUB6=y -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_COMPUTONE=m -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -CONFIG_DIGIEPCA=m -CONFIG_ESPSERIAL=m -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -CONFIG_SYNCLINK=m -CONFIG_SYNCLINKMP=m -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_SPECIALIX=m -CONFIG_SPECIALIX_RTSCTS=y -CONFIG_SX=m -CONFIG_RIO=m -CONFIG_RIO_OLDPCI=y -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -CONFIG_I2C_ELV=m -CONFIG_I2C_VELLEMAN=m -CONFIG_SCx200_I2C=m -CONFIG_SCx200_I2C_SCL=12 -CONFIG_SCx200_I2C_SDA=13 -CONFIG_SCx200_ACB=m -CONFIG_I2C_ALGOPCF=m -CONFIG_I2C_ELEKTOR=m -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -CONFIG_I2C_I810=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m -CONFIG_I2C_SIS645=m -CONFIG_I2C_SAVAGE4=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -CONFIG_SENSORS_PCF8574=m -CONFIG_SENSORS_PCF8591=m - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=y -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_FM801=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -CONFIG_QIC02_TAPE=m -CONFIG_QIC02_DYNCONF=y -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -CONFIG_I810_TCO=m -CONFIG_MIXCOMWD=m -CONFIG_60XX_WDT=m -CONFIG_SC1200_WDT=m -CONFIG_SCx200_WDT=m -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -CONFIG_WDT_501=y -CONFIG_WDT_501_FAN=y -CONFIG_MACHZ_WDT=m -CONFIG_DEADMAN=m -CONFIG_HANGCHECK_TIMER=m -CONFIG_AMD7XX_TCO=m -CONFIG_SCx200_GPIO=m -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -CONFIG_APPLICOM=m -CONFIG_SONYPI=m - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -CONFIG_AGP=m -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_AMD_8151=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -CONFIG_AGP_NVIDIA=y -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m -CONFIG_IBMASM=y -CONFIG_IBMASM_ASM=m -CONFIG_IBMASM_SER=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -CONFIG_VIDEO_MEYE=m - -# -# Radio Adapters -# -CONFIG_RADIO_CADET=m -CONFIG_RADIO_RTRACK=m -CONFIG_RADIO_RTRACK2=m -CONFIG_RADIO_AZTECH=m -CONFIG_RADIO_GEMTEK=m -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -CONFIG_RADIO_MIROPCM20_RDS=m -CONFIG_RADIO_SF16FMI=m -CONFIG_RADIO_SF16FMR2=m -CONFIG_RADIO_TERRATEC=m -CONFIG_RADIO_TRUST=m -CONFIG_RADIO_TYPHOON=m -CONFIG_RADIO_TYPHOON_PROC_FS=y -CONFIG_RADIO_ZOLTRIX=m -CONFIG_DXR3=y -CONFIG_EM8300=m -# CONFIG_EM8300_LOOPBACK is not set -# CONFIG_EM8300_UCODETIMEOUT is not set -# CONFIG_EM8300_DICOMFIX is not set -# CONFIG_EM8300_DICOMCTRL is not set -CONFIG_EM8300_DICOMPAL=y -CONFIG_ADV717X=m -# CONFIG_ADV717X_SWAP is not set -# CONFIG_ADV717X_PIXELPORT16BIT is not set -# CONFIG_ADV717X_PIXELPORTPAL is not set -CONFIG_BT865=m - -# -# File systems -# -CONFIG_QUOTA=y -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_QIFACE_COMPAT=y -# CONFIG_QIFACE_V1 is not set -CONFIG_QIFACE_V2=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=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_XATTR_USER=y -CONFIG_REISERFS_FS_XATTR_TRUSTED=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_ADFS_FS=m -# CONFIG_ADFS_FS_RW is not set -CONFIG_AFFS_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_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=m -CONFIG_JBD_DEBUG=y -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FATX_FS=m -CONFIG_EFS_FS=m -CONFIG_JFFS_FS=m -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -# CONFIG_JFS_DEBUG is not set -CONFIG_JFS_STATISTICS=y -CONFIG_MINIX_FS=y -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -CONFIG_HPFS_FS=m -CONFIG_PROC_FS=y -CONFIG_PROC_CONFIG=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -CONFIG_QNX4FS_FS=m -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -CONFIG_EXT2_FS_XATTR_TRUSTED=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -CONFIG_XFS_FS=m -CONFIG_XFS_POSIX_ACL=y -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_DMAPI=y -# CONFIG_XFS_DEBUG is not set -# CONFIG_PAGEBUF_DEBUG is not set -CONFIG_OCFS_FS=m - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_INTERMEZZO_FS=m -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_ACL=y -CONFIG_NFS_DIRECTIO=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_NFSD_FHALIAS=y -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_CIFS=m -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y - -# -# 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_XBOX_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 is not set -CONFIG_SGI_PARTITION=y -CONFIG_ULTRIX_PARTITION=y -CONFIG_SUN_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -CONFIG_FB_PM2_FIFO_DISCONNECT=y -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -CONFIG_UNICON=y -CONFIG_UNICON_GB=m -CONFIG_UNICON_GBK=m -CONFIG_UNICON_BIG5=m -CONFIG_UNICON_JIS=m -CONFIG_UNICON_KSCM=m -CONFIG_FB_CYBER2000=m -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -CONFIG_FB_MATROX_PROC=m -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -CONFIG_FB_INTEL=m -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_VMWARE_SVGA=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -CONFIG_FB_TRIDENT=m -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_SPLASHSCREEN=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_ADVANCED=y -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB2=m -CONFIG_FBCON_CFB4=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_AFB=m -CONFIG_FBCON_ILBM=m -CONFIG_FBCON_IPLAN2P2=m -CONFIG_FBCON_IPLAN2P4=m -CONFIG_FBCON_IPLAN2P8=m -CONFIG_FBCON_MAC=m -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_VGA=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -CONFIG_SOUND_TRACEINIT=y -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -# CONFIG_SOUND_GUS16 is not set -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -CONFIG_PSS_MIXER=y -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -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_SEQUENCER_OSS=y -CONFIG_SND_VERBOSE_PRINTK=y -CONFIG_SND_DEBUG=y -CONFIG_SND_DEBUG_MEMORY=y -# CONFIG_SND_DEBUG_DETECT is not set - -# -# Generic devices -# -CONFIG_SND_DUMMY=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -CONFIG_SND_SERIAL_U16550=m -CONFIG_SND_MPU401=m -CONFIG_SND_SERIALMIDI=m - -# -# ISA devices -# -CONFIG_SND_AD1816A=m -CONFIG_SND_AD1848=m -CONFIG_SND_CS4231=m -CONFIG_SND_CS4232=m -CONFIG_SND_CS4236=m -CONFIG_SND_ES968=m -CONFIG_SND_ES1688=m -CONFIG_SND_ES18XX=m -CONFIG_SND_GUSCLASSIC=m -CONFIG_SND_GUSEXTREME=m -CONFIG_SND_GUSMAX=m -CONFIG_SND_INTERWAVE=m -CONFIG_SND_INTERWAVE_STB=m -CONFIG_SND_OPTI92X_AD1848=m -CONFIG_SND_OPTI92X_CS4231=m -CONFIG_SND_OPTI93X=m -CONFIG_SND_SB8=m -CONFIG_SND_SB16=m -CONFIG_SND_SBAWE=m -CONFIG_SND_SB16_CSP=y -CONFIG_SND_WAVEFRONT=m -CONFIG_SND_ALS100=m -CONFIG_SND_AZT2320=m -CONFIG_SND_CMI8330=m -CONFIG_SND_DT019X=m -CONFIG_SND_OPL3SA2=m -CONFIG_SND_SGALAXY=m -CONFIG_SND_SSCAPE=m -CONFIG_SND_MSND_PINNACLE=m - -# -# PCI devices -# -CONFIG_SND_ALI5451=m -CONFIG_SND_CS46XX=m -CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CS4281=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_PDPLUS=m -CONFIG_SND_KORG1212=m -CONFIG_SND_NM256=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_HDSP=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_YMFPCI=m -CONFIG_SND_ALS4000=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_FM801=m -CONFIG_SND_ICE1712=m -CONFIG_SND_ICE1724=m -CONFIG_SND_INTEL8X0=m -CONFIG_SND_SONICVIBES=m -CONFIG_SND_VIA82XX=m -CONFIG_SND_VX222=m -CONFIG_SND_MIXART=m -CONFIG_SND_AZT3328=m - -# -# ALSA USB devices -# -CONFIG_SND_USB_AUDIO=m - -# -# ALSA PCMCIA devices -# -CONFIG_SND_VXPOCKET=m -CONFIG_SND_VXP440=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m -CONFIG_USB_AUDIO=m -CONFIG_USB_EMI26=m -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m -CONFIG_USB_DC2XX=m -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -CONFIG_USB_LOGITECH_CAM=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_AX8817X=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USBDNET=m -CONFIG_USB_USBDNET_VENDOR=0000 -CONFIG_USB_USBDNET_PRODUCT=0000 -CONFIG_USB_USBDNET_CLASS=0000 -CONFIG_USB_USBDNET_SUBCLASS=0000 -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -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_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SAFE_SERIAL_VENDOR=0000 -CONFIG_USB_SAFE_SERIAL_PRODUCT=0000 -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m -CONFIG_USB_SPEEDTOUCH=m - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y -CONFIG_BLUEZ_CMTP=m - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -# CONFIG_BLUEZ_USB_ZERO_PACKET is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIBFUSB=m -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Kernel hacking -# -CONFIG_DUMP=m -CONFIG_DUMP_COMPRESS_RLE=m -CONFIG_DUMP_COMPRESS_GZIP=m -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_HZ is not set -CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_HIGHMEM is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_IOVIRT is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_KMSGDUMP is not set -# CONFIG_DEBUG_SPINLOCK is not set -CONFIG_FRAME_POINTER=y -# CONFIG_HIGHMEM_EMULATION is not set -# CONFIG_X86_REMOTE_DEBUG is not set -# CONFIG_KDB is not set -# CONFIG_KDB_MODULES is not set -CONFIG_KALLSYMS=y -# CONFIG_HOOK is not set -CONFIG_VTUNE=m - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m -CONFIG_QSORT=y -CONFIG_FW_LOADER=m - -# -# Build options -# -# CONFIG_SUSE_KERNEL is not set -CONFIG_UNITEDLINUX_KERNEL=y -CONFIG_CFGNAME="smp" -CONFIG_RELEASE="273" diff --git a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-suse-2.4.21-2-x86_64.config b/lustre/kernel_patches/kernel_configs/kernel-2.4.21-suse-2.4.21-2-x86_64.config deleted file mode 100644 index d8c0697..0000000 --- a/lustre/kernel_patches/kernel_configs/kernel-2.4.21-suse-2.4.21-2-x86_64.config +++ /dev/null @@ -1,2042 +0,0 @@ -# -# Automatically generated by make menuconfig: don't edit -# -CONFIG_X86_64=y -CONFIG_X86=y -# CONFIG_ISA is not set -# CONFIG_SBUS is not set -CONFIG_UID16=y -CONFIG_X86_CMPXCHG=y -CONFIG_EARLY_PRINTK=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Processor type and features -# -# CONFIG_MK8 is not set -CONFIG_GENERIC_CPU=y -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_TSC=y -CONFIG_X86_GOOD_APIC=y - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_PROC_INTF=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_24_API=y -CONFIG_X86_POWERNOW_K8=m -# CONFIG_X86_POWERNOW_K8_DBG is not set -CONFIG_X86_MSR=m -CONFIG_X86_CPUID=m -# CONFIG_MATH_EMULATION is not set -# CONFIG_MCA is not set -# CONFIG_EISA is not set -CONFIG_X86_IO_APIC=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_MTRR=y -# CONFIG_SMP is not set -CONFIG_HPET_TIMER=y -CONFIG_GART_IOMMU=y -CONFIG_X86_UP_IOAPIC=y -CONFIG_MCE=y -# CONFIG_K8_NUMA is not set -# CONFIG_NOBIGSTACK is not set -CONFIG_STACK_SIZE_16KB=y -# CONFIG_STACK_SIZE_32KB is not set -# CONFIG_STACK_SIZE_64KB is not set -CONFIG_STACK_SIZE_SHIFT=2 - -# -# General setup -# -# CONFIG_DESKTOP is not set -CONFIG_NET=y -CONFIG_EVLOG=y -CONFIG_EVLOG_BUFSIZE=128 -CONFIG_EVLOG_FWPRINTK=y -# CONFIG_EVLOG_PRINTKWLOC is not set -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y -# CONFIG_PCI_NAMES is not set -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -CONFIG_CARDBUS=y -CONFIG_TCIC=y -CONFIG_I82092=y -CONFIG_I82365=y - -# -# PCI Hotplug Support -# -CONFIG_HOTPLUG_PCI=m -# CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set -# CONFIG_HOTPLUG_PCI_IBM is not set -CONFIG_HOTPLUG_PCI_ACPI=m -CONFIG_HOTPLUG_PCI_AMD=m -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_MAX_USER_RT_PRIO=100 -CONFIG_MAX_RT_PRIO=0 -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_PM=y -CONFIG_IA32_EMULATION=y - -# -# ACPI Support -# -CONFIG_ACPI=y -# CONFIG_ACPI_HT_ONLY is not set -CONFIG_ACPI_INITRD=y -CONFIG_ACPI_BOOT=y -CONFIG_ACPI_BUS=y -CONFIG_ACPI_INTERPRETER=y -CONFIG_ACPI_EC=y -CONFIG_ACPI_POWER=y -CONFIG_ACPI_PCI=y -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_SYSTEM=y -CONFIG_ACPI_AC=m -CONFIG_ACPI_BATTERY=m -CONFIG_ACPI_BUTTON=m -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m -CONFIG_ACPI_ASUS=m -CONFIG_ACPI_TOSHIBA=m -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_RELAXED_AML=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=m -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=m -CONFIG_MTD_CONCAT=m -CONFIG_MTD_REDBOOT_PARTS=m -CONFIG_MTD_CMDLINE_PARTS=m -CONFIG_MTD_CHAR=m -CONFIG_MTD_BLOCK=m -CONFIG_MTD_BLOCK_RO=m -CONFIG_FTL=m -CONFIG_NFTL=m -# CONFIG_NFTL_RW is not set - -# -# 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 is not set -CONFIG_MTD_CFI_INTELEXT=m -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_STAA=m -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -CONFIG_MTD_ABSENT=m -CONFIG_MTD_OBSOLETE_CHIPS=y -CONFIG_MTD_AMDSTD=m -CONFIG_MTD_SHARP=m -CONFIG_MTD_JEDEC=m - -# -# Mapping drivers for chip access -# -CONFIG_MTD_PHYSMAP=m -CONFIG_MTD_PHYSMAP_START=8000000 -CONFIG_MTD_PHYSMAP_LEN=4000000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=2 -CONFIG_MTD_PNC2000=m -CONFIG_MTD_SC520CDP=m -CONFIG_MTD_NETSC520=m -CONFIG_MTD_SBC_GXX=m -CONFIG_MTD_ELAN_104NC=m -CONFIG_MTD_DILNETPC=m -CONFIG_MTD_DILNETPC_BOOTSIZE=80000 -CONFIG_MTD_MIXMEM=m -CONFIG_MTD_OCTAGON=m -CONFIG_MTD_VMAX=m -CONFIG_MTD_SCx200_DOCFLASH=m -CONFIG_MTD_L440GX=m -# CONFIG_MTD_AMD76XROM is not set -CONFIG_MTD_ICH2ROM=m -CONFIG_MTD_NETtel=m -# CONFIG_MTD_SCB2_FLASH is not set -CONFIG_MTD_PCI=m -CONFIG_MTD_PCMCIA=m - -# -# Self-contained MTD device drivers -# -CONFIG_MTD_PMC551=m -CONFIG_MTD_PMC551_BUGFIX=y -# CONFIG_MTD_PMC551_DEBUG is not set -CONFIG_MTD_SLRAM=m -CONFIG_MTD_MTDRAM=m -CONFIG_MTDRAM_TOTAL_SIZE=4096 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTD_BLKMTD=m -CONFIG_MTD_DOC1000=m -CONFIG_MTD_DOC2000=m -CONFIG_MTD_DOC2001=m -CONFIG_MTD_DOCPROBE=m -CONFIG_MTD_DOCPROBE_ADVANCED=y -CONFIG_MTD_DOCPROBE_ADDRESS=0000 -CONFIG_MTD_DOCPROBE_HIGH=y -CONFIG_MTD_DOCPROBE_55AA=y - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=m -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_IDS=m - -# -# Parallel port support -# -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_PC_CML1=m -CONFIG_PARPORT_SERIAL=m -CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_PC_SUPERIO=y -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AMIGA is not set -# CONFIG_PARPORT_MFC3 is not set -# CONFIG_PARPORT_ATARI is not set -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_SUNBPP is not set -CONFIG_PARPORT_OTHER=y -CONFIG_PARPORT_1284=y - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE=m -CONFIG_PARIDE_PARPORT=m -CONFIG_PARIDE_PD=m -CONFIG_PARIDE_PCD=m -CONFIG_PARIDE_PF=m -CONFIG_PARIDE_PT=m -CONFIG_PARIDE_PG=m -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_LOOP=y -CONFIG_CIPHER_TWOFISH=m -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=128000 -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_STATS=y - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID5=m -CONFIG_MD_MULTIPATH=m -CONFIG_BLK_DEV_LVM=m -CONFIG_BLK_DEV_DM=m -CONFIG_BLK_DEV_DM_MIRROR=m - -# -# Cryptography support (CryptoAPI) -# -CONFIG_CRYPTO=y -CONFIG_CIPHERS=y -CONFIG_CIPHER_AES=m -CONFIG_CIPHER_3DES=m -CONFIG_CIPHER_NULL=m -CONFIG_CIPHER_DES=m -CONFIG_DIGESTS=y -CONFIG_DIGEST_MD5=m -CONFIG_DIGEST_SHA1=m -CONFIG_CRYPTODEV=y -CONFIG_CRYPTOLOOP=m -CONFIG_CRYPTOLOOP_ATOMIC=y -# CONFIG_CRYPTOLOOP_IV_HACK is not set -# CONFIG_CRYPTOLOOP_DEBUG is not set - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_FILTER=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IPSEC=m -CONFIG_IPSEC_DEBUG=y -CONFIG_IPSEC_DEBUG_DISABLE_DEFAULT=y -CONFIG_IPSEC_TUNNEL=y -CONFIG_TUX=m -CONFIG_TUX_EXTCGI=y -CONFIG_TUX_EXTENDED_LOG=y -# CONFIG_TUX_DEBUG is not set -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_LARGE_TABLES=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_INET_ECN=y -CONFIG_SYN_COOKIES=y -CONFIG_IP_IPSEC=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_PSD=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_IPLIMIT=m -CONFIG_IP_NF_MATCH_UNCLEAN=m -CONFIG_IP_NF_MATCH_STRING=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m -# CONFIG_IP_NF_NAT_LOCAL is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_NAT_NEEDED=y - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 -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 -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -# CONFIG_IPV6_DEBUG is not set -CONFIG_IPV6_IM=y -CONFIG_IPV6_MODULE_IP_GRE=y -CONFIG_IPV6_ISATAP=y -CONFIG_IPV6_PREFIXLIST=y -CONFIG_IPV6_6TO4_NEXTHOP=y -CONFIG_IPV6_PRIVACY=y -CONFIG_IPV6_SUBTREES=y -# CONFIG_IPV6_MLD6_ALL_DONE is not set -# CONFIG_IPV6_NODEINFO is not set -# CONFIG_IPV6_ZONE is not set -CONFIG_IPV6_DROP_FAKE_V4MAPPED=y - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IPV6_IPSEC=y -CONFIG_IPV6_IPSEC_TUNNEL=y -CONFIG_IPV6_IPV6_TUNNEL=m -CONFIG_IPV6_MOBILITY=m -CONFIG_IPV6_MOBILITY_CN=m -CONFIG_IPV6_MOBILITY_MN=m -CONFIG_IPV6_MOBILITY_HA=m -# CONFIG_IPV6_MOBILITY_DEBUG is not set -# CONFIG_SHARED_IPV6_CARDS is not set -CONFIG_KHTTPD=m -CONFIG_KHTTPD_IPV6=y -# CONFIG_ATM is not set -CONFIG_VLAN_8021Q=m -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m - -# -# Appletalk devices -# -CONFIG_DEV_APPLETALK=y -CONFIG_COPS_DAYNA=y -CONFIG_COPS_TANGENT=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_DECNET=m -CONFIG_DECNET_SIOCGIFCONF=y -# CONFIG_DECNET_ROUTER is not set -CONFIG_BRIDGE=m -CONFIG_X25=m -CONFIG_LAPB=m -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -CONFIG_ECONET=m -# CONFIG_ECONET_AUNUDP is not set -# CONFIG_ECONET_NATIVE is not set -CONFIG_WAN_ROUTER=m -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_CSZ=m -CONFIG_NET_SCH_PRIO=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_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -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_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m - -# -# Telephony Support -# -CONFIG_PHONE=m -CONFIG_PHONE_IXJ=m -CONFIG_PHONE_IXJ_PCMCIA=m - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -CONFIG_IDEDISK_STROKE=y -CONFIG_BLK_DEV_IDECS=m -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_IDETAPE=m -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=m -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_BLK_DEV_CMD640=y -CONFIG_BLK_DEV_CMD640_ENHANCED=y -# CONFIG_BLK_DEV_ISAPNP is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_OFFBOARD=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -CONFIG_IDEDMA_ONLYDISK=y -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_BLK_DEV_ADMA100 is not set -CONFIG_BLK_DEV_AEC62XX=y -CONFIG_BLK_DEV_ALI15X3=y -# CONFIG_WDC_ALI15X3 is not set -CONFIG_BLK_DEV_AMD74XX=y -# CONFIG_AMD74XX_OVERRIDE is not set -CONFIG_BLK_DEV_CMD64X=y -CONFIG_BLK_DEV_TRIFLEX=y -CONFIG_BLK_DEV_CY82C693=y -CONFIG_BLK_DEV_CS5530=y -CONFIG_BLK_DEV_HPT34X=y -# CONFIG_HPT34X_AUTODMA is not set -CONFIG_BLK_DEV_HPT366=y -# CONFIG_BLK_DEV_PIIX is not set -CONFIG_BLK_DEV_NS87415=y -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX_OLD=y -CONFIG_PDC202XX_BURST=y -CONFIG_BLK_DEV_PDC202XX_NEW=y -CONFIG_PDC202XX_FORCE=y -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_SC1200=y -# CONFIG_BLK_DEV_SVWKS is not set -CONFIG_BLK_DEV_SIIMAGE=y -CONFIG_BLK_DEV_SIS5513=y -CONFIG_BLK_DEV_SLC90E66=y -CONFIG_BLK_DEV_TRM290=y -CONFIG_BLK_DEV_VIA82CXXX=y -CONFIG_BLK_DEV_CENATEK=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set -# CONFIG_DMA_NONPCI is not set -CONFIG_BLK_DEV_PDC202XX=y -CONFIG_BLK_DEV_IDE_MODES=y -CONFIG_BLK_DEV_ATARAID=m -CONFIG_BLK_DEV_ATARAID_PDC=m -CONFIG_BLK_DEV_ATARAID_HPT=m -CONFIG_BLK_DEV_ATARAID_SII=m - -# -# SCSI support -# -CONFIG_SCSI=m -CONFIG_BLK_DEV_SD=m -CONFIG_SD_MAX_MAJORS=144 -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=4 -CONFIG_CHR_DEV_SCH=m -CONFIG_CHR_DEV_SG=m -# CONFIG_SCSI_DEBUG_QUEUES is not set -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -CONFIG_BLK_DEV_3W_XXXX_RAID=m -# CONFIG_SCSI_7000FASST is not set -CONFIG_SCSI_ACARD=m -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 -CONFIG_AIC7XXX_RESET_DELAY_MS=5000 -CONFIG_AIC7XXX_PROBE_EISA_VL=y -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -CONFIG_AIC7XXX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=32 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -# CONFIG_AIC79XX_ENABLE_RD_STRM is not set -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -CONFIG_AIC79XX_REG_PRETTY_PRINT=y -CONFIG_SCSI_AIC7XXX_OLD=m -CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=24 -CONFIG_AIC7XXX_OLD_PROC_STATS=y -CONFIG_SCSI_DPT_I2O=m -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_IN2000=m -CONFIG_SCSI_AM53C974=m -CONFIG_SCSI_MEGARAID=m -CONFIG_SCSI_MEGARAID2=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_OMIT_FLASHPOINT is not set -CONFIG_SCSI_CPQFCTS=m -CONFIG_SCSI_DMX3191D=m -# CONFIG_SCSI_DTC3280 is not set -CONFIG_SCSI_EATA=m -CONFIG_SCSI_EATA_TAGGED_QUEUE=y -CONFIG_SCSI_EATA_LINKED_COMMANDS=y -CONFIG_SCSI_EATA_MAX_TAGS=16 -CONFIG_SCSI_EATA_DMA=m -CONFIG_SCSI_EATA_PIO=m -CONFIG_SCSI_LPFC=m -CONFIG_SCSI_FUTURE_DOMAIN=m -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_GENERIC_NCR5380=m -CONFIG_SCSI_GENERIC_NCR53C400=y -CONFIG_SCSI_G_NCR5380_PORT=y -# CONFIG_SCSI_G_NCR5380_MEM is not set -CONFIG_SCSI_IPS_OLD=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_PPSCSI=m -CONFIG_PPSCSI_T348=m -CONFIG_PPSCSI_T358=m -CONFIG_PPSCSI_VPI0=m -CONFIG_PPSCSI_VPI2=m -CONFIG_PPSCSI_ONSCSI=m -CONFIG_PPSCSI_SPARCSI=m -CONFIG_PPSCSI_EPSA2=m -CONFIG_PPSCSI_EPST=m -# CONFIG_SCSI_NCR53C406A is not set -CONFIG_SCSI_NCR53C7xx=m -# CONFIG_SCSI_NCR53C7xx_sync is not set -CONFIG_SCSI_NCR53C7xx_FAST=y -CONFIG_SCSI_NCR53C7xx_DISCONNECT=y -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_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX=m -CONFIG_SCSI_SYM53C8XX=m -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=80 -CONFIG_SCSI_NCR53C8XX_PROFILE=y -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -CONFIG_SCSI_NCR53C8XX_PQS_PDS=y -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PAS16 is not set -CONFIG_SCSI_PCI2000=m -CONFIG_SCSI_PCI2220I=m -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -CONFIG_SCSI_QLOGIC_ISP=m -CONFIG_SCSI_QLOGIC_FC=m -CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_QLOGIC_QLA2XXX=y -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2100=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2200=m -CONFIG_SCSI_QLOGIC_QLA2XXX_QLA2300=m -CONFIG_SCSI_SEAGATE=m -CONFIG_SCSI_SIM710=m -CONFIG_SCSI_SYM53C416=m -CONFIG_SCSI_DC395x_TRMS1040=m -CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -# CONFIG_SCSI_T128 is not set -CONFIG_SCSI_U14_34F=m -CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y -CONFIG_SCSI_U14_34F_MAX_TAGS=8 -CONFIG_SCSI_ULTRASTOR=m -CONFIG_SCSI_NSP32=m -CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_SCSI_PCMCIA=y -CONFIG_PCMCIA_AHA152X=m -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_NINJA_SCSI=m -CONFIG_PCMCIA_QLOGIC=m - -# -# Fusion MPT device support -# -CONFIG_FUSION=m -# CONFIG_FUSION_BOOT is not set -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_ISENSE=m -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_NET_FC=y - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -CONFIG_IEEE1394=m -CONFIG_IEEE1394_PCILYNX=m -CONFIG_IEEE1394_OHCI1394=m -CONFIG_IEEE1394_VIDEO1394=m -CONFIG_IEEE1394_SBP2=m -CONFIG_IEEE1394_SBP2_PHYS_DMA=y -CONFIG_IEEE1394_ETH1394=m -CONFIG_IEEE1394_DV1394=m -CONFIG_IEEE1394_RAWIO=m -CONFIG_IEEE1394_CMP=m -CONFIG_IEEE1394_AMDTP=m -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -# CONFIG_IEEE1394_OUI_DB is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -CONFIG_ARCNET=m -CONFIG_ARCNET_1201=m -CONFIG_ARCNET_1051=m -CONFIG_ARCNET_RAW=m -CONFIG_ARCNET_COM90xx=m -CONFIG_ARCNET_COM90xxIO=m -CONFIG_ARCNET_RIM_I=m -CONFIG_ARCNET_COM20020=m -# CONFIG_ARCNET_COM20020_ISA is not set -CONFIG_ARCNET_COM20020_PCI=m -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -CONFIG_HAPPYMEAL=m -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -CONFIG_SUNGEM=m -CONFIG_NET_VENDOR_3COM=y -# CONFIG_EL1 is not set -# CONFIG_EL2 is not set -# CONFIG_ELPLUS is not set -# CONFIG_EL16 is not set -# CONFIG_ELMC is not set -# CONFIG_ELMC_II is not set -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -# CONFIG_LANCE is not set -CONFIG_NET_VENDOR_SMC=y -# CONFIG_WD80x3 is not set -# CONFIG_ULTRAMCA is not set -# CONFIG_ULTRA is not set -# CONFIG_ULTRA32 is not set -# CONFIG_SMC9194 is not set -CONFIG_NET_VENDOR_RACAL=y -# CONFIG_NI5010 is not set -# CONFIG_NI52 is not set -# CONFIG_NI65 is not set -CONFIG_HP100=m -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=m -CONFIG_PCNET32_OLD=m -CONFIG_AMD8111_ETH=m -CONFIG_ADAPTEC_STARFIRE=m -# CONFIG_APRICOT is not set -CONFIG_NET_BCM4400=m -# CONFIG_CS89x0 is not set -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -CONFIG_DE4X5=m -CONFIG_DGRS=m -CONFIG_DM9102=m -CONFIG_EEPRO100=m -# CONFIG_EEPRO100_PIO is not set -CONFIG_E100=m -# CONFIG_LNE390 is not set -CONFIG_FEALNX=m -CONFIG_NATSEMI=m -CONFIG_NETGEAR_GA621=m -CONFIG_NETGEAR_GA622=m -CONFIG_NE2K_PCI=m -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -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_SIS900=m -CONFIG_EPIC100=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_TLAN=m -CONFIG_TC35815=m -CONFIG_VIA_RHINE=m -# CONFIG_VIA_RHINE_MMIO is not set -CONFIG_WINBOND_840=m -CONFIG_NET_POCKET=y -# CONFIG_DE600 is not set -# CONFIG_DE620 is not set - -# -# Ethernet (1000 Mbit) -# -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_DL2K=m -CONFIG_E1000=m -# CONFIG_MYRI_SBUS is not set -CONFIG_NS83820=m -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_R8169=m -CONFIG_SK98LIN=m -CONFIG_SK98LIN_T1=y -CONFIG_SK98LIN_T3=y -CONFIG_SK98LIN_T8=y -CONFIG_SK98LIN_T6=y -CONFIG_SK98LIN_T9=y -CONFIG_SK98LIN_T4=y -CONFIG_SK98LIN_T7=y -CONFIG_SK98LIN_T2=y -CONFIG_SK98LIN_T5=y -CONFIG_SK9DLIN=m -CONFIG_TIGON3=m -CONFIG_NET_BROADCOM=m -CONFIG_FDDI=y -CONFIG_DEFXX=m -CONFIG_SKFP=m -CONFIG_NETCONSOLE=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_PPPOE=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y -CONFIG_STRIP=m -CONFIG_WAVELAN=m -CONFIG_AIRONET4500=m -CONFIG_AIRONET4500_NONCS=m -CONFIG_AIRONET4500_PNP=y -CONFIG_AIRONET4500_PCI=y -CONFIG_AIRONET4500_ISA=y -CONFIG_AIRONET4500_I365=y -CONFIG_AIRONET4500_PROC=m -CONFIG_AIRO=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_PCI_HERMES=m -CONFIG_PCMCIA_HERMES=m -CONFIG_AIRO_CS=m -CONFIG_NET_WIRELESS=y - -# -# Token Ring devices -# -# CONFIG_TR is not set -CONFIG_NET_FC=y -CONFIG_IPHASE5526=m -CONFIG_RCPCI=m -CONFIG_SHAPER=m - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_FMVJ18X=m -CONFIG_PCMCIA_PCNET=m -CONFIG_PCMCIA_AXNET=m -CONFIG_PCMCIA_NMCLAN=m -CONFIG_PCMCIA_SMC91C92=m -CONFIG_PCMCIA_XIRC2PS=m -CONFIG_ARCNET_COM20020_CS=m -# CONFIG_PCMCIA_IBMTR is not set -CONFIG_PCMCIA_XIRCOM=m -CONFIG_PCMCIA_XIRTULIP=m -CONFIG_NET_PCMCIA_RADIO=y -CONFIG_PCMCIA_RAYCS=m -CONFIG_PCMCIA_NETWAVE=m -CONFIG_PCMCIA_WAVELAN=m -CONFIG_AIRONET4500_CS=m - -# -# Amateur Radio support -# -CONFIG_HAMRADIO=y -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_SCC_DELAY=y -CONFIG_SCC_TRXECHO=y -CONFIG_BAYCOM_SER_FDX=m -CONFIG_BAYCOM_SER_HDX=m -CONFIG_BAYCOM_PAR=m -CONFIG_BAYCOM_EPP=m -CONFIG_SOUNDMODEM=m -CONFIG_SOUNDMODEM_SBC=y -CONFIG_SOUNDMODEM_WSS=y -CONFIG_SOUNDMODEM_AFSK1200=y -CONFIG_SOUNDMODEM_AFSK2400_7=y -CONFIG_SOUNDMODEM_AFSK2400_8=y -CONFIG_SOUNDMODEM_AFSK2666=y -CONFIG_SOUNDMODEM_HAPN4800=y -CONFIG_SOUNDMODEM_PSK4800=y -CONFIG_SOUNDMODEM_FSK9600=y -CONFIG_YAM=m - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_CACHE_LAST_LSAP=y -# CONFIG_IRDA_FAST_RR is not set -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# -CONFIG_IRTTY_SIR=m -CONFIG_IRPORT_SIR=m -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_USB_IRDA=m -CONFIG_NSC_FIR=m -CONFIG_WINBOND_FIR=m -# CONFIG_TOSHIBA_OLD is not set -CONFIG_TOSHIBA_FIR=m -CONFIG_SMC_IRCC_FIR=m -CONFIG_ALI_FIR=m -CONFIG_VLSI_FIR=m - -# -# ISDN subsystem -# -CONFIG_ISDN=m -CONFIG_ISDN_BOOL=y -CONFIG_ISDN_PPP=y -CONFIG_IPPP_FILTER=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_ISDN_PPP_BSDCOMP=m -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y -CONFIG_ISDN_X25=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DRV_LOOP=m -CONFIG_ISDN_DIVERSION=m - -# -# Passive ISDN cards -# -CONFIG_ISDN_DRV_HISAX=m -CONFIG_ISDN_HISAX=y -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 -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 -# CONFIG_HISAX_TELES_CS is not set -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -# CONFIG_HISAX_AVM_A1_CS is not set -CONFIG_HISAX_ST5481=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_USB_AUERISDN=m - -# -# Active ISDN cards -# -CONFIG_ISDN_DRV_ICN=m -CONFIG_ISDN_DRV_PCBIT=m -CONFIG_ISDN_DRV_SC=m -CONFIG_ISDN_DRV_ACT2000=m -CONFIG_ISDN_DRV_EICON=y -CONFIG_ISDN_DRV_EICON_DIVAS=m -CONFIG_ISDN_DRV_EICON_OLD=m -CONFIG_ISDN_DRV_EICON_PCI=y -CONFIG_ISDN_DRV_EICON_ISA=y -CONFIG_ISDN_DRV_TPAM=m -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=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 -# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set -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_HYSDN=m -CONFIG_HYSDN_CAPI=y - -# -# Input core support -# -CONFIG_INPUT=m -CONFIG_INPUT_KEYBDEV=m -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m - -# -# Character devices -# -CONFIG_VT=y -CONFIG_ECC=m -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_SERIAL_EXTENDED=y -CONFIG_SERIAL_MANY_PORTS=y -CONFIG_SERIAL_SHARE_IRQ=y -# CONFIG_SERIAL_DETECT_IRQ is not set -CONFIG_SERIAL_MULTIPORT=y -CONFIG_HUB6=y -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_COMPUTONE=m -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -# CONFIG_ESPSERIAL is not set -CONFIG_MOXA_INTELLIO=m -CONFIG_MOXA_SMARTIO=m -CONFIG_ISI=m -CONFIG_SYNCLINK=m -CONFIG_SYNCLINKMP=m -CONFIG_N_HDLC=m -CONFIG_RISCOM8=m -CONFIG_STALDRV=y -CONFIG_STALLION=m -CONFIG_ISTALLION=m -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -CONFIG_PPDEV=m -CONFIG_TIPAR=m - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_PHILIPSPAR=m -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -CONFIG_SCx200_I2C=m -CONFIG_SCx200_I2C_SCL=12 -CONFIG_SCx200_I2C_SDA=13 -CONFIG_SCx200_ACB=m -CONFIG_I2C_ALGOPCF=m -# CONFIG_I2C_ELEKTOR is not set -CONFIG_I2C_MAINBOARD=y -CONFIG_I2C_ALI1535=m -CONFIG_I2C_ALI15X3=m -CONFIG_I2C_HYDRA=m -CONFIG_I2C_AMD756=m -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -# CONFIG_I2C_I810 is not set -CONFIG_I2C_PIIX4=m -CONFIG_I2C_SIS5595=m -CONFIG_I2C_SIS630=m -CONFIG_I2C_SIS645=m -CONFIG_I2C_SAVAGE4=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m -CONFIG_I2C_VOODOO3=m -CONFIG_I2C_ISA=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m - -# -# Hardware sensors support -# -CONFIG_SENSORS=y -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1024=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_FSCPOS=m -CONFIG_SENSORS_FSCSCY=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_MAXILIFE=m -CONFIG_SENSORS_IT87=m -CONFIG_SENSORS_MTP008=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_LM87=m -# CONFIG_SENSORS_LM92 is not set -CONFIG_SENSORS_SIS5595=m -# CONFIG_SENSORS_SMSC47M1 is not set -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_OTHER=y -CONFIG_SENSORS_BT869=m -CONFIG_SENSORS_DDCMON=m -CONFIG_SENSORS_EEPROM=m -CONFIG_SENSORS_MATORB=m -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set - -# -# Mice -# -CONFIG_BUSMOUSE=m -CONFIG_ATIXL_BUSMOUSE=m -CONFIG_LOGIBUSMOUSE=m -CONFIG_MS_BUSMOUSE=m -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -CONFIG_82C710_MOUSE=y -CONFIG_PC110_PAD=m -CONFIG_MK712_MOUSE=m - -# -# Joysticks -# -CONFIG_INPUT_GAMEPORT=m -CONFIG_INPUT_NS558=m -CONFIG_INPUT_LIGHTNING=m -CONFIG_INPUT_PCIGAME=m -CONFIG_INPUT_CS461X=m -CONFIG_INPUT_EMU10K1=m -CONFIG_INPUT_FM801=m -CONFIG_INPUT_SERIO=m -CONFIG_INPUT_SERPORT=m -CONFIG_INPUT_ANALOG=m -CONFIG_INPUT_A3D=m -CONFIG_INPUT_ADI=m -CONFIG_INPUT_COBRA=m -CONFIG_INPUT_GF2K=m -CONFIG_INPUT_GRIP=m -CONFIG_INPUT_INTERACT=m -CONFIG_INPUT_TMDC=m -CONFIG_INPUT_SIDEWINDER=m -CONFIG_INPUT_IFORCE_USB=m -CONFIG_INPUT_IFORCE_232=m -CONFIG_INPUT_WARRIOR=m -CONFIG_INPUT_MAGELLAN=m -CONFIG_INPUT_SPACEORB=m -CONFIG_INPUT_SPACEBALL=m -CONFIG_INPUT_STINGER=m -CONFIG_INPUT_DB9=m -CONFIG_INPUT_GAMECON=m -CONFIG_INPUT_TURBOGRAFX=m -CONFIG_QIC02_TAPE=m -CONFIG_QIC02_DYNCONF=y -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_PANIC_EVENT=y -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_KCS=m -CONFIG_IPMI_WATCHDOG=m - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_ACQUIRE_WDT=m -CONFIG_ADVANTECH_WDT=m -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -CONFIG_SC520_WDT=m -CONFIG_PCWATCHDOG=m -CONFIG_EUROTECH_WDT=m -CONFIG_IB700_WDT=m -CONFIG_WAFER_WDT=m -# CONFIG_I810_TCO is not set -CONFIG_MIXCOMWD=m -CONFIG_60XX_WDT=m -CONFIG_SC1200_WDT=m -CONFIG_SCx200_WDT=m -CONFIG_SOFT_WATCHDOG=m -CONFIG_W83877F_WDT=m -CONFIG_WDT=m -CONFIG_WDTPCI=m -CONFIG_WDT_501=y -CONFIG_WDT_501_FAN=y -CONFIG_MACHZ_WDT=m -CONFIG_DEADMAN=m -CONFIG_HANGCHECK_TIMER=m -CONFIG_AMD7XX_TCO=m -CONFIG_SCx200_GPIO=m -CONFIG_AMD_RNG=m -CONFIG_INTEL_RNG=m -CONFIG_AMD_PM768=m -CONFIG_NVRAM=m -CONFIG_RTC=y -CONFIG_DTLK=m -CONFIG_R3964=m -CONFIG_APPLICOM=m - -# -# Ftape, the floppy tape device driver -# -CONFIG_FTAPE=m -CONFIG_ZFTAPE=m -CONFIG_ZFT_DFLT_BLK_SZ=10240 -CONFIG_ZFT_COMPRESSOR=m -CONFIG_FT_NR_BUFFERS=3 -CONFIG_FT_PROC_FS=y -CONFIG_FT_NORMAL_DEBUG=y -# CONFIG_FT_FULL_DEBUG is not set -# CONFIG_FT_NO_TRACE is not set -# CONFIG_FT_NO_TRACE_AT_ALL is not set -CONFIG_FT_STD_FDC=y -# CONFIG_FT_MACH2 is not set -# CONFIG_FT_PROBE_FC10 is not set -# CONFIG_FT_ALT_FDC is not set -CONFIG_FT_FDC_THR=8 -CONFIG_FT_FDC_MAX_RATE=2000 -CONFIG_FT_ALPHA_CLOCK=0 -CONFIG_AGP=y -CONFIG_AGP_AMD_8151=y -# CONFIG_AGP_INTEL is not set -# CONFIG_AGP_I810 is not set -# CONFIG_AGP_VIA is not set -# CONFIG_AGP_AMD is not set -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_ALI is not set -# CONFIG_AGP_SWORKS is not set -# CONFIG_AGP_NVIDIA is not set -CONFIG_DRM=y -# CONFIG_DRM_OLD is not set -CONFIG_DRM_NEW=y -CONFIG_DRM_TDFX=m -CONFIG_DRM_R128=m -CONFIG_DRM_RADEON=m -CONFIG_DRM_I810=m -# CONFIG_DRM_I810_XFREE_41 is not set -CONFIG_DRM_I830=m -CONFIG_DRM_MGA=m -# CONFIG_DRM_SIS is not set - -# -# PCMCIA character devices -# -CONFIG_PCMCIA_SERIAL_CS=m -CONFIG_SYNCLINK_CS=m -CONFIG_MWAVE=m - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# -CONFIG_VIDEO_PROC_FS=y -CONFIG_I2C_PARPORT=m -CONFIG_VIDEO_BT848=m -CONFIG_VIDEO_PMS=m -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_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZR36120=m -# CONFIG_VIDEO_MEYE is not set - -# -# Radio Adapters -# -CONFIG_RADIO_GEMTEK_PCI=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_MAESTRO=m -CONFIG_RADIO_MIROPCM20=m -# CONFIG_DXR3 is not set - -# -# File systems -# -CONFIG_QUOTA=y -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_QIFACE_COMPAT=y -# CONFIG_QIFACE_V1 is not set -CONFIG_QIFACE_V2=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_XATTR_USER=y -CONFIG_REISERFS_FS_XATTR_TRUSTED=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_ADFS_FS=m -# CONFIG_ADFS_FS_RW is not set -CONFIG_AFFS_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_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_EXT3_FS_XATTR_TRUSTED=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_JBD=y -CONFIG_JBD_DEBUG=y -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_UMSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FATX_FS=m -CONFIG_EFS_FS=m -CONFIG_JFFS_FS=m -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_CRAMFS=m -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -# CONFIG_JFS_DEBUG is not set -CONFIG_JFS_STATISTICS=y -CONFIG_MINIX_FS=y -CONFIG_VXFS_FS=m -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -CONFIG_HPFS_FS=m -CONFIG_PROC_FS=y -CONFIG_PROC_CONFIG=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -CONFIG_QNX4FS_FS=m -# CONFIG_QNX4FS_RW is not set -CONFIG_ROMFS_FS=m -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -CONFIG_EXT2_FS_XATTR_TRUSTED=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_SYSV_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_RW=y -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -CONFIG_XFS_FS=m -CONFIG_XFS_POSIX_ACL=y -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_DMAPI=y -# CONFIG_XFS_DEBUG is not set -# CONFIG_PAGEBUF_DEBUG is not set -# CONFIG_OCFS_FS is not set - -# -# Network File Systems -# -CONFIG_CODA_FS=m -CONFIG_INTERMEZZO_FS=m -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_ACL=y -CONFIG_NFS_DIRECTIO=y -CONFIG_ROOT_NFS=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -CONFIG_NFSD_ACL=y -CONFIG_NFSD_TCP=y -CONFIG_NFSD_FHALIAS=y -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_CIFS=m -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -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_ZISOFS_FS=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y - -# -# 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_XBOX_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 is not set -CONFIG_SGI_PARTITION=y -CONFIG_ULTRIX_PARTITION=y -CONFIG_SUN_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -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_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 - -# -# Console drivers -# -CONFIG_VGA_CONSOLE=y -CONFIG_VIDEO_SELECT=y -CONFIG_MDA_CONSOLE=m - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_RIVA=m -CONFIG_FB_CLGEN=m -CONFIG_FB_PM2=m -CONFIG_FB_PM2_FIFO_DISCONNECT=y -CONFIG_FB_PM2_PCI=y -CONFIG_FB_PM3=m -# CONFIG_UNICON is not set -# CONFIG_UNICON_GB is not set -# CONFIG_UNICON_GBK is not set -# CONFIG_UNICON_BIG5 is not set -# CONFIG_UNICON_JIS is not set -# CONFIG_UNICON_KSCM is not set -CONFIG_FB_CYBER2000=m -CONFIG_FB_VESA=y -CONFIG_FB_VGA16=m -CONFIG_FB_HGA=m -CONFIG_VIDEO_SELECT=y -CONFIG_FB_MATROX=m -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -CONFIG_FB_MATROX_G450=y -CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_I2C=m -CONFIG_FB_MATROX_MAVEN=m -CONFIG_FB_MATROX_PROC=m -CONFIG_FB_MATROX_MULTIHEAD=y -CONFIG_FB_ATY=m -CONFIG_FB_ATY_GX=y -CONFIG_FB_ATY_CT=y -CONFIG_FB_RADEON=m -CONFIG_FB_ATY128=m -# CONFIG_FB_INTEL is not set -# CONFIG_FB_SIS is not set -CONFIG_FB_NEOMAGIC=m -CONFIG_FB_VMWARE_SVGA=m -CONFIG_FB_3DFX=m -CONFIG_FB_VOODOO1=m -CONFIG_FB_TRIDENT=m -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_SPLASHSCREEN=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_ADVANCED=y -CONFIG_FBCON_MFB=m -CONFIG_FBCON_CFB2=m -CONFIG_FBCON_CFB4=m -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -CONFIG_FBCON_AFB=m -CONFIG_FBCON_ILBM=m -CONFIG_FBCON_IPLAN2P2=m -CONFIG_FBCON_IPLAN2P4=m -CONFIG_FBCON_IPLAN2P8=m -CONFIG_FBCON_MAC=m -CONFIG_FBCON_VGA_PLANES=m -CONFIG_FBCON_VGA=m -CONFIG_FBCON_HGA=m -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Sound -# -CONFIG_SOUND=m -CONFIG_SOUND_ALI5455=m -CONFIG_SOUND_BT878=m -CONFIG_SOUND_CMPCI=m -CONFIG_SOUND_CMPCI_FM=y -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_FMIO=388 -CONFIG_SOUND_CMPCI_MIDI=y -CONFIG_SOUND_CMPCI_MPUIO=330 -CONFIG_SOUND_CMPCI_JOYSTICK=y -CONFIG_SOUND_CMPCI_CM8738=y -# CONFIG_SOUND_CMPCI_SPDIFINVERSE is not set -CONFIG_SOUND_CMPCI_SPDIFLOOP=y -CONFIG_SOUND_CMPCI_SPEAKERS=2 -CONFIG_SOUND_EMU10K1=m -CONFIG_MIDI_EMU10K1=y -CONFIG_SOUND_FUSION=m -CONFIG_SOUND_CS4281=m -CONFIG_SOUND_ES1370=m -CONFIG_SOUND_ES1371=m -CONFIG_SOUND_ESSSOLO1=m -CONFIG_SOUND_MAESTRO=m -CONFIG_SOUND_MAESTRO3=m -CONFIG_SOUND_FORTE=m -CONFIG_SOUND_ICH=m -CONFIG_SOUND_RME96XX=m -CONFIG_SOUND_SONICVIBES=m -CONFIG_SOUND_TRIDENT=m -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -CONFIG_SOUND_VIA82CXXX=m -CONFIG_MIDI_VIA82CXXX=y -CONFIG_SOUND_OSS=m -CONFIG_SOUND_TRACEINIT=y -CONFIG_SOUND_DMAP=y -CONFIG_SOUND_AD1816=m -CONFIG_SOUND_AD1889=m -CONFIG_SOUND_SGALAXY=m -CONFIG_SOUND_ADLIB=m -CONFIG_SOUND_ACI_MIXER=m -CONFIG_SOUND_CS4232=m -CONFIG_SOUND_SSCAPE=m -CONFIG_SOUND_GUS=m -# CONFIG_SOUND_GUS16 is not set -CONFIG_SOUND_GUSMAX=y -CONFIG_SOUND_VMIDI=m -CONFIG_SOUND_TRIX=m -CONFIG_SOUND_MSS=m -CONFIG_SOUND_MPU401=m -CONFIG_SOUND_NM256=m -CONFIG_SOUND_MAD16=m -CONFIG_MAD16_OLDCARD=y -CONFIG_SOUND_PAS=m -# CONFIG_PAS_JOYSTICK is not set -CONFIG_SOUND_PSS=m -CONFIG_PSS_MIXER=y -# CONFIG_PSS_HAVE_BOOT is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_AWE32_SYNTH=m -CONFIG_SOUND_KAHLUA=m -CONFIG_SOUND_WAVEFRONT=m -CONFIG_SOUND_MAUI=m -CONFIG_SOUND_YM3812=m -CONFIG_SOUND_OPL3SA1=m -CONFIG_SOUND_OPL3SA2=m -CONFIG_SOUND_YMFPCI=m -CONFIG_SOUND_YMFPCI_LEGACY=y -CONFIG_SOUND_UART6850=m -CONFIG_SOUND_AEDSP16=m -CONFIG_SC6600=y -CONFIG_SC6600_JOY=y -CONFIG_SC6600_CDROM=4 -CONFIG_SC6600_CDROMBASE=0 -CONFIG_AEDSP16_SBPRO=y -CONFIG_AEDSP16_MPU401=y -CONFIG_SOUND_TVMIXER=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -CONFIG_SND_BIT32_EMUL=m -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_SEQUENCER_OSS=y -CONFIG_SND_VERBOSE_PRINTK=y -CONFIG_SND_DEBUG=y -CONFIG_SND_DEBUG_MEMORY=y -# CONFIG_SND_DEBUG_DETECT is not set - -# -# Generic devices -# -CONFIG_SND_DUMMY=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -CONFIG_SND_SERIAL_U16550=m -CONFIG_SND_MPU401=m -CONFIG_SND_SERIALMIDI=m - -# -# PCI devices -# -CONFIG_SND_ALI5451=m -CONFIG_SND_CS46XX=m -CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CS4281=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_PDPLUS=m -CONFIG_SND_KORG1212=m -CONFIG_SND_NM256=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_HDSP=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_YMFPCI=m -CONFIG_SND_ALS4000=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_FM801=m -CONFIG_SND_ICE1712=m -CONFIG_SND_ICE1724=m -CONFIG_SND_INTEL8X0=m -CONFIG_SND_SONICVIBES=m -CONFIG_SND_VIA82XX=m -CONFIG_SND_VX222=m -CONFIG_SND_MIXART=m -CONFIG_SND_AZT3328=m - -# -# ALSA USB devices -# -CONFIG_SND_USB_AUDIO=m - -# -# ALSA PCMCIA devices -# -CONFIG_SND_VXPOCKET=m -CONFIG_SND_VXP440=m - -# -# USB support -# -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_UHCI=m -CONFIG_USB_UHCI_ALT=m -CONFIG_USB_OHCI=m -CONFIG_USB_AUDIO=m -CONFIG_USB_EMI26=m -CONFIG_USB_MIDI=m -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -CONFIG_USB_HIDDEV=y -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -CONFIG_USB_AIPTEK=m -CONFIG_USB_WACOM=m -CONFIG_USB_KBTAB=m -CONFIG_USB_POWERMATE=m -CONFIG_USB_DC2XX=m -CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m -CONFIG_USB_MICROTEK=m -CONFIG_USB_HPUSBSCSI=m -CONFIG_USB_IBMCAM=m -CONFIG_USB_KONICAWC=m -CONFIG_USB_OV511=m -CONFIG_USB_PWC=m -CONFIG_USB_SE401=m -CONFIG_USB_STV680=m -CONFIG_USB_VICAM=m -CONFIG_USB_DSBR=m -CONFIG_USB_DABUSB=m -# CONFIG_USB_LOGITECH_CAM is not set -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_KAWETH=m -CONFIG_USB_CATC=m -CONFIG_USB_AX8817X=m -CONFIG_USB_CDCETHER=m -CONFIG_USB_USBNET=m -CONFIG_USB_USBDNET=m -CONFIG_USB_USBDNET_VENDOR=0000 -CONFIG_USB_USBDNET_PRODUCT=0000 -CONFIG_USB_USBDNET_CLASS=0000 -CONFIG_USB_USBDNET_SUBCLASS=0000 -CONFIG_USB_USS720=m - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -# CONFIG_USB_SERIAL_DEBUG is not set -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=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_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -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_MPR=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SAFE_SERIAL_VENDOR=0000 -CONFIG_USB_SAFE_SERIAL_PRODUCT=0000 -CONFIG_USB_RIO500=m -CONFIG_USB_AUERSWALD=m -CONFIG_USB_TIGL=m -CONFIG_USB_BRLVGER=m -CONFIG_USB_LCD=m -# CONFIG_USB_SPEEDTOUCH is not set - -# -# Bluetooth support -# -CONFIG_BLUEZ=m -CONFIG_BLUEZ_L2CAP=m -CONFIG_BLUEZ_SCO=m -CONFIG_BLUEZ_RFCOMM=m -CONFIG_BLUEZ_RFCOMM_TTY=y -CONFIG_BLUEZ_BNEP=m -CONFIG_BLUEZ_BNEP_MC_FILTER=y -CONFIG_BLUEZ_BNEP_PROTO_FILTER=y -CONFIG_BLUEZ_CMTP=m - -# -# Bluetooth device drivers -# -CONFIG_BLUEZ_HCIUSB=m -CONFIG_BLUEZ_USB_SCO=y -# CONFIG_BLUEZ_USB_ZERO_PACKET is not set -CONFIG_BLUEZ_HCIUART=m -CONFIG_BLUEZ_HCIUART_H4=y -CONFIG_BLUEZ_HCIUART_BCSP=y -CONFIG_BLUEZ_HCIUART_BCSP_TXCRC=y -CONFIG_BLUEZ_HCIBFUSB=m -CONFIG_BLUEZ_HCIDTL1=m -CONFIG_BLUEZ_HCIBT3C=m -CONFIG_BLUEZ_HCIBLUECARD=m -CONFIG_BLUEZ_HCIBTUART=m -CONFIG_BLUEZ_HCIVHCI=m - -# -# Kernel hacking -# -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SLAB is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_CHECKING is not set -# CONFIG_INIT_DEBUG is not set -# CONFIG_X86_REMOTE_DEBUG is not set -# CONFIG_IOMMU_DEBUG is not set -# CONFIG_IOMMU_LEAK is not set -CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_KALLSYMS=y - -# -# Library routines -# -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m -CONFIG_QSORT=y -CONFIG_FW_LOADER=m - -# -# Build options -# -CONFIG_SUSE_KERNEL=y -CONFIG_CFGNAME="default" -CONFIG_RELEASE=171 -CONFIG_SWIOTLB=y diff --git a/lustre/kernel_patches/kernel_configs/uml-vanilla-2.4.24.config b/lustre/kernel_patches/kernel_configs/uml-vanilla-2.4.24.config deleted file mode 100644 index 2803866..0000000 --- a/lustre/kernel_patches/kernel_configs/uml-vanilla-2.4.24.config +++ /dev/null @@ -1,413 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_USERMODE=y -# CONFIG_ISA is not set -# CONFIG_SBUS is not set -# CONFIG_PCI is not set -CONFIG_UID16=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General Setup -# -CONFIG_MODE_SKAS=y -CONFIG_MODE_TT=y -CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y -CONFIG_HOSTFS=y -CONFIG_HPPFS=y -CONFIG_MCONSOLE=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_HOST_2G_2G is not set -# CONFIG_UML_SMP is not set -# CONFIG_SMP is not set -CONFIG_NEST_LEVEL=0 -CONFIG_KERNEL_HALF_GIGS=1 -# CONFIG_HIGHMEM is not set -CONFIG_PROC_MM=y -CONFIG_KERNEL_STACK_ORDER=4 -CONFIG_UML_REAL_TIME_CLOCK=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_KMOD=y - -# -# Character Devices -# -CONFIG_STDIO_CONSOLE=y -CONFIG_SSL=y -CONFIG_FD_CHAN=y -CONFIG_NULL_CHAN=y -CONFIG_PORT_CHAN=y -CONFIG_PTY_CHAN=y -CONFIG_TTY_CHAN=y -CONFIG_XTERM_CHAN=y -CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -CONFIG_CON_CHAN="xterm" -CONFIG_SSL_CHAN="pty" -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_WATCHDOG is not set -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_UML_WATCHDOG is not set -# CONFIG_UML_SOUND is not set -# CONFIG_SOUND is not set -# CONFIG_HOSTAUDIO is not set -# CONFIG_TTY_LOG is not set - -# -# Block Devices -# -CONFIG_BLK_DEV_UBD=y -# CONFIG_BLK_DEV_UBD_SYNC is not set -CONFIG_COW=y -CONFIG_COW_COMMON=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_MMAPPER is not set -CONFIG_NETDEVICES=y - -# -# Network Devices -# -CONFIG_UML_NET=y -CONFIG_UML_NET_ETHERTAP=y -CONFIG_UML_NET_TUNTAP=y -CONFIG_UML_NET_SLIP=y -CONFIG_UML_NET_SLIRP=y -CONFIG_UML_NET_DAEMON=y -CONFIG_UML_NET_MCAST=y -# CONFIG_UML_NET_PCAP is not set -CONFIG_DUMMY=y -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=y -CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_SLIP=y -# CONFIG_SLIP_COMPRESSED is not set -# CONFIG_SLIP_SMART is not set -# CONFIG_SLIP_MODE_SLIP6 is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_IPV6=m -# CONFIG_KHTTPD is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# Appletalk devices -# -# CONFIG_DEV_APPLETALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set - -# -# File systems -# -CONFIG_QUOTA=y -# CONFIG_QFMT_V2 is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y -CONFIG_REISERFS_FS=y -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_XATTR_SHARING=y -CONFIG_EXT3_FS_XATTR_USER=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_UMSDOS_FS=y -CONFIG_VFAT_FS=y -# CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_MINIX_FS=y -# CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_XATTR_SHARING=y -CONFIG_EXT2_FS_XATTR_USER=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_NFS_FS is not set -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_ROOT_NFS is not set -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set -CONFIG_FS_MBCACHE=y - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -# CONFIG_MTD_CFI is not set -# CONFIG_MTD_JEDECPROBE is not set -# CONFIG_MTD_GEN_PROBE is not set -# CONFIG_MTD_CFI_INTELEXT is not set -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set -# CONFIG_MTD_AMDSTD is not set -# CONFIG_MTD_SHARP is not set -# CONFIG_MTD_JEDEC is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PCMCIA is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=y - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC1000 is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOCPROBE is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y - -# -# Kernel hacking -# -# CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUGSYM=y -CONFIG_PT_PROXY=y -# CONFIG_GPROF is not set -# CONFIG_GCOV is not set diff --git a/lustre/kernel_patches/patches/3.5G-address-space-2.4.22-vanilla.patch b/lustre/kernel_patches/patches/3.5G-address-space-2.4.22-vanilla.patch deleted file mode 100644 index 0276131..0000000 --- a/lustre/kernel_patches/patches/3.5G-address-space-2.4.22-vanilla.patch +++ /dev/null @@ -1,352 +0,0 @@ - Rules.make | 17 +++++++ - arch/i386/Makefile | 4 + - arch/i386/config.in | 10 ++++ - arch/i386/vmlinux.lds | 99 ----------------------------------------- - arch/i386/vmlinux.lds.S | 99 +++++++++++++++++++++++++++++++++++++++++ - include/asm-i386/page.h | 4 + - include/asm-i386/page_offset.h | 10 ++++ - include/asm-i386/processor.h | 4 + - mm/memory.c | 23 +++++++-- - 9 files changed, 165 insertions(+), 105 deletions(-) - -Index: linux-2.4.22-vanilla/arch/i386/config.in -=================================================================== ---- linux-2.4.22-vanilla.orig/arch/i386/config.in 2003-12-02 23:55:28.000000000 +0300 -+++ linux-2.4.22-vanilla/arch/i386/config.in 2003-12-15 23:09:28.000000000 +0300 -@@ -212,6 +212,16 @@ - fi - if [ "$CONFIG_HIGHMEM64G" = "y" ]; then - define_bool CONFIG_X86_PAE y -+ choice 'User address space size' \ -+ "3GB CONFIG_1GB \ -+ 2GB CONFIG_2GB \ -+ 1GB CONFIG_3GB" 3GB -+else -+ choice 'User address space size' \ -+ "3GB CONFIG_1GB \ -+ 2GB CONFIG_2GB \ -+ 1GB CONFIG_3GB \ -+ 3.5GB CONFIG_05GB" 3GB - fi - - if [ "$CONFIG_HIGHMEM" = "y" ]; then -Index: linux-2.4.22-vanilla/arch/i386/Makefile -=================================================================== ---- linux-2.4.22-vanilla.orig/arch/i386/Makefile 2003-11-03 22:50:58.000000000 +0300 -+++ linux-2.4.22-vanilla/arch/i386/Makefile 2003-12-15 23:09:28.000000000 +0300 -@@ -114,6 +114,9 @@ - - MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot - -+arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE -+ $(CPP) -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds -+ - vmlinux: arch/i386/vmlinux.lds - - FORCE: ; -@@ -150,6 +153,7 @@ - @$(MAKEBOOT) clean - - archmrproper: -+ rm -f arch/i386/vmlinux.lds - - archdep: - @$(MAKEBOOT) dep -Index: linux-2.4.22-vanilla/arch/i386/vmlinux.lds.S -=================================================================== ---- linux-2.4.22-vanilla.orig/arch/i386/vmlinux.lds.S 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.22-vanilla/arch/i386/vmlinux.lds.S 2003-12-15 23:10:46.000000000 +0300 -@@ -0,0 +1,83 @@ -+/* ld script to make i386 Linux kernel -+ * Written by Martin Mares ; -+ */ -+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -+OUTPUT_ARCH(i386) -+ENTRY(_start) -+SECTIONS -+{ -+ . = PAGE_OFFSET_RAW + 0x100000; -+ _text = .; /* Text and read-only data */ -+ .text : { -+ *(.text) -+ *(.fixup) -+ *(.gnu.warning) -+ } = 0x9090 -+ -+ _etext = .; /* End of text section */ -+ -+ .rodata : { *(.rodata) *(.rodata.*) } -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ .data : { /* Data */ -+ *(.data) -+ CONSTRUCTORS -+ } -+ -+ _edata = .; /* End of data section */ -+ -+/* chose the biggest of the possible stack sizes here? */ -+ . = ALIGN(65536); /* init_task */ -+ .data.init_task : { *(.data.init_task) } -+ -+ . = ALIGN(4096); /* Init code and data */ -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ .data.init : { *(.data.init) } -+ . = ALIGN(16); -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ . = ALIGN(4096); -+ __init_end = .; -+ -+ . = ALIGN(4096); -+ .data.page_aligned : { *(.data.idt) } -+ -+ . = ALIGN(32); -+ .data.cacheline_aligned : { *(.data.cacheline_aligned) } -+ -+ __bss_start = .; /* BSS */ -+ .bss : { -+ *(.bss) -+ } -+ _end = . ; -+ -+ /* Sections to be discarded */ -+ /DISCARD/ : { -+ *(.text.exit) -+ *(.data.exit) -+ *(.exitcall.exit) -+ } -+ -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+} -Index: linux-2.4.22-vanilla/arch/i386/vmlinux.lds -=================================================================== ---- linux-2.4.22-vanilla.orig/arch/i386/vmlinux.lds 2003-12-15 23:17:09.000000000 +0300 -+++ linux-2.4.22-vanilla/arch/i386/vmlinux.lds 2003-01-30 13:24:37.000000000 +0300 -@@ -1,83 +0,0 @@ --/* ld script to make i386 Linux kernel -- * Written by Martin Mares ; -- */ --OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") --OUTPUT_ARCH(i386) --ENTRY(_start) --SECTIONS --{ -- . = 0xC0000000 + 0x100000; -- _text = .; /* Text and read-only data */ -- .text : { -- *(.text) -- *(.fixup) -- *(.gnu.warning) -- } = 0x9090 -- -- _etext = .; /* End of text section */ -- -- .rodata : { *(.rodata) *(.rodata.*) } -- .kstrtab : { *(.kstrtab) } -- -- . = ALIGN(16); /* Exception table */ -- __start___ex_table = .; -- __ex_table : { *(__ex_table) } -- __stop___ex_table = .; -- -- __start___ksymtab = .; /* Kernel symbol table */ -- __ksymtab : { *(__ksymtab) } -- __stop___ksymtab = .; -- -- .data : { /* Data */ -- *(.data) -- CONSTRUCTORS -- } -- -- _edata = .; /* End of data section */ -- --/* chose the biggest of the possible stack sizes here? */ -- . = ALIGN(65536); /* init_task */ -- .data.init_task : { *(.data.init_task) } -- -- . = ALIGN(4096); /* Init code and data */ -- __init_begin = .; -- .text.init : { *(.text.init) } -- .data.init : { *(.data.init) } -- . = ALIGN(16); -- __setup_start = .; -- .setup.init : { *(.setup.init) } -- __setup_end = .; -- __initcall_start = .; -- .initcall.init : { *(.initcall.init) } -- __initcall_end = .; -- . = ALIGN(4096); -- __init_end = .; -- -- . = ALIGN(4096); -- .data.page_aligned : { *(.data.idt) } -- -- . = ALIGN(32); -- .data.cacheline_aligned : { *(.data.cacheline_aligned) } -- -- __bss_start = .; /* BSS */ -- .bss : { -- *(.bss) -- } -- _end = . ; -- -- /* Sections to be discarded */ -- /DISCARD/ : { -- *(.text.exit) -- *(.data.exit) -- *(.exitcall.exit) -- } -- -- /* Stabs debugging sections. */ -- .stab 0 : { *(.stab) } -- .stabstr 0 : { *(.stabstr) } -- .stab.excl 0 : { *(.stab.excl) } -- .stab.exclstr 0 : { *(.stab.exclstr) } -- .stab.index 0 : { *(.stab.index) } -- .stab.indexstr 0 : { *(.stab.indexstr) } -- .comment 0 : { *(.comment) } --} -Index: linux-2.4.22-vanilla/include/asm-i386/page.h -=================================================================== ---- linux-2.4.22-vanilla.orig/include/asm-i386/page.h 2003-11-03 23:51:46.000000000 +0300 -+++ linux-2.4.22-vanilla/include/asm-i386/page.h 2003-12-15 23:09:28.000000000 +0300 -@@ -78,7 +78,9 @@ - * and CONFIG_HIGHMEM64G options in the kernel configuration. - */ - --#define __PAGE_OFFSET (0xC0000000) -+#include -+ -+#define __PAGE_OFFSET (PAGE_OFFSET_RAW) - - /* - * This much address space is reserved for vmalloc() and iomap() -Index: linux-2.4.22-vanilla/include/asm-i386/page_offset.h -=================================================================== ---- linux-2.4.22-vanilla.orig/include/asm-i386/page_offset.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.22-vanilla/include/asm-i386/page_offset.h 2003-12-15 23:09:28.000000000 +0300 -@@ -0,0 +1,10 @@ -+#include -+#ifdef CONFIG_05GB -+#define PAGE_OFFSET_RAW 0xE0000000 -+#elif defined(CONFIG_1GB) -+#define PAGE_OFFSET_RAW 0xC0000000 -+#elif defined(CONFIG_2GB) -+#define PAGE_OFFSET_RAW 0x80000000 -+#elif defined(CONFIG_3GB) -+#define PAGE_OFFSET_RAW 0x40000000 -+#endif -Index: linux-2.4.22-vanilla/include/asm-i386/processor.h -=================================================================== ---- linux-2.4.22-vanilla.orig/include/asm-i386/processor.h 2003-12-02 23:55:28.000000000 +0300 -+++ linux-2.4.22-vanilla/include/asm-i386/processor.h 2003-12-15 23:09:28.000000000 +0300 -@@ -265,7 +265,11 @@ - /* This decides where the kernel will search for a free chunk of vm - * space during mmap's. - */ -+#ifndef CONFIG_05GB - #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -+#else -+#define TASK_UNMAPPED_BASE (TASK_SIZE / 16) -+#endif - - /* - * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. -Index: linux-2.4.22-vanilla/mm/memory.c -=================================================================== ---- linux-2.4.22-vanilla.orig/mm/memory.c 2003-05-16 05:29:15.000000000 +0400 -+++ linux-2.4.22-vanilla/mm/memory.c 2003-12-15 23:09:28.000000000 +0300 -@@ -108,8 +108,7 @@ - - static inline void free_one_pgd(pgd_t * dir) - { -- int j; -- pmd_t * pmd; -+ pmd_t * pmd, * md, * emd; - - if (pgd_none(*dir)) - return; -@@ -120,9 +119,23 @@ - } - pmd = pmd_offset(dir, 0); - pgd_clear(dir); -- for (j = 0; j < PTRS_PER_PMD ; j++) { -- prefetchw(pmd+j+(PREFETCH_STRIDE/16)); -- free_one_pmd(pmd+j); -+ -+ /* -+ * Beware if changing the loop below. It once used int j, -+ * for (j = 0; j < PTRS_PER_PMD; j++) -+ * free_one_pmd(pmd+j); -+ * but some older i386 compilers (e.g. egcs-2.91.66, gcc-2.95.3) -+ * terminated the loop with a _signed_ address comparison -+ * using "jle", when configured for HIGHMEM64GB (X86_PAE). -+ * If also configured for 3GB of kernel virtual address space, -+ * if page at physical 0x3ffff000 virtual 0x7ffff000 is used as -+ * a pmd, when that mm exits the loop goes on to free "entries" -+ * found at 0x80000000 onwards. The loop below compiles instead -+ * to be terminated by unsigned address comparison using "jb". -+ */ -+ for (md = pmd, emd = pmd + PTRS_PER_PMD; md < emd; md++) { -+ prefetchw(md+(PREFETCH_STRIDE/16)); -+ free_one_pmd(md); - } - pmd_free(pmd); - } -Index: linux-2.4.22-vanilla/Rules.make -=================================================================== ---- linux-2.4.22-vanilla.orig/Rules.make 2003-05-16 05:28:27.000000000 +0400 -+++ linux-2.4.22-vanilla/Rules.make 2003-12-15 23:09:28.000000000 +0300 -@@ -215,6 +215,7 @@ - # - # Added the SMP separator to stop module accidents between uniprocessor - # and SMP Intel boxes - AC - from bits by Michael Chastain -+# Added separator for different PAGE_OFFSET memory models - Ingo. - # - - ifdef CONFIG_SMP -@@ -223,6 +224,22 @@ - genksyms_smp_prefix := - endif - -+ifdef CONFIG_2GB -+ifdef CONFIG_SMP -+ genksyms_smp_prefix := -p smp_2gig_ -+else -+ genksyms_smp_prefix := -p 2gig_ -+endif -+endif -+ -+ifdef CONFIG_3GB -+ifdef CONFIG_SMP -+ genksyms_smp_prefix := -p smp_3gig_ -+else -+ genksyms_smp_prefix := -p 3gig_ -+endif -+endif -+ - $(MODINCL)/%.ver: %.c - @if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \ - echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $<'; \ diff --git a/lustre/kernel_patches/patches/add_page_private.patch b/lustre/kernel_patches/patches/add_page_private.patch deleted file mode 100644 index 93005b66..0000000 --- a/lustre/kernel_patches/patches/add_page_private.patch +++ /dev/null @@ -1,23 +0,0 @@ -Index: linux-ia64/include/linux/mm.h -=================================================================== ---- linux-ia64.orig/include/linux/mm.h 2004-04-27 12:39:16.000000000 -0700 -+++ linux-ia64/include/linux/mm.h 2004-04-27 12:42:10.000000000 -0700 -@@ -205,6 +205,7 @@ typedef struct page { - struct page **pprev_hash; /* Complement to *next_hash. */ - struct buffer_head * buffers; /* Buffer maps us to a disk block. */ -+ unsigned long private; - - /* - * On machines where all RAM is mapped into kernel address space, - -_ -Index: linux-ia64/mm/filemap.c -=================================================================== ---- linux-ia64.orig/mm/filemap.c 2004-04-27 12:35:18.000000000 -0700 -+++ linux-ia64/mm/filemap.c 2004-04-27 12:42:47.000000000 -0700 -@@ -676,6 +676,7 @@ static inline void __add_to_page_cache(s - page_cache_get(page); - page->index = offset; -+ page->private = 0; - add_page_to_inode_queue(mapping, page); - add_page_to_hash_queue(page, hash); diff --git a/lustre/kernel_patches/patches/blkdev_tunables-2.4.21-chaos.patch b/lustre/kernel_patches/patches/blkdev_tunables-2.4.21-chaos.patch deleted file mode 100644 index e863bd6..0000000 --- a/lustre/kernel_patches/patches/blkdev_tunables-2.4.21-chaos.patch +++ /dev/null @@ -1,52 +0,0 @@ -Index: linux-2.4.21/drivers/addon/qla2200/qla2x00.h -=================================================================== ---- linux-2.4.21.orig/drivers/addon/qla2200/qla2x00.h 2005-06-01 22:51:57.000000000 -0400 -+++ linux-2.4.21/drivers/addon/qla2200/qla2x00.h 2005-06-01 23:06:10.592857440 -0400 -@@ -3275,7 +3275,7 @@ - /* Kernel version specific template additions */ - - /* Number of segments 1 - 65535 */ --#define SG_SEGMENTS 32 /* Cmd entry + 6 continuations */ -+#define SG_SEGMENTS 512 /* Cmd entry + 6 continuations */ - - /* - * Scsi_Host_template (see hosts.h) -@@ -3289,7 +3289,7 @@ - * - */ - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,8) --#define TEMPLATE_MAX_SECTORS max_sectors: 512, -+#define TEMPLATE_MAX_SECTORS max_sectors: 2048, - #else - #define TEMPLATE_MAX_SECTORS - #endif -Index: linux-2.4.21/include/linux/blkdev.h -=================================================================== ---- linux-2.4.21.orig/include/linux/blkdev.h 2005-06-01 22:51:55.000000000 -0400 -+++ linux-2.4.21/include/linux/blkdev.h 2005-06-01 23:07:26.186365480 -0400 -@@ -262,10 +262,10 @@ - - extern char * blkdev_varyio[MAX_BLKDEV]; - --#define MAX_SEGMENTS 128 -+#define MAX_SEGMENTS 256 - #define MAX_SECTORS 255 - /* General-case limit for superbh size: */ --#define MAX_SUPERBH 32768 /* must fit info ->b_size right now */ -+#define MAX_SUPERBH (1<<20) /* must fit info ->b_size right now */ - - /* Limit for superbh when we're certain it cannot be bounce-buffered: */ - #define MAX_SUPERBH_NOBOUNCE (1024*1024) /* must fit info ->b_size right now */ -Index: linux-2.4.21/mm/highmem.c -=================================================================== ---- linux-2.4.21.orig/mm/highmem.c 2005-06-01 22:51:50.000000000 -0400 -+++ linux-2.4.21/mm/highmem.c 2005-06-01 23:06:10.594857136 -0400 -@@ -474,7 +474,7 @@ - /* - * FIXME: assuming PAGE_SIZE buffer_heads - */ --#define SUPERBH_MAX_USERS (POOL_SIZE * PAGE_SIZE / MAX_SUPERBH) -+#define SUPERBH_MAX_USERS max(POOL_SIZE * PAGE_SIZE / MAX_SUPERBH, 1) - - static int superbh_users; - static DECLARE_WAIT_QUEUE_HEAD(superbh_wait); diff --git a/lustre/kernel_patches/patches/compile-fixes-2.4.21-rhel.patch b/lustre/kernel_patches/patches/compile-fixes-2.4.21-rhel.patch deleted file mode 100644 index dae8a47..0000000 --- a/lustre/kernel_patches/patches/compile-fixes-2.4.21-rhel.patch +++ /dev/null @@ -1,90 +0,0 @@ -diff -X dontdiff -urp kern_oldest/drivers/i2c/i2c-ali1535.c kern_fix/drivers/i2c/i2c-ali1535.c ---- kern_oldest/drivers/i2c/i2c-ali1535.c 2006-05-01 11:55:43.000000000 -0700 -+++ kern_fix/drivers/i2c/i2c-ali1535.c 2006-05-01 15:25:34.000000000 -0700 -@@ -672,8 +672,8 @@ EXPORT_NO_SYMBOLS; - #ifdef MODULE - - MODULE_AUTHOR -- ("Frodo Looijaard , Philip Edelbrock , -- Mark D. Studebaker and Dan Eaton "); -+ ("Frodo Looijaard , Philip Edelbrock , " -+ "Mark D. Studebaker and Dan Eaton "); - MODULE_DESCRIPTION("ALI1535 SMBus driver"); - - int init_module(void) -diff -X dontdiff -urp kern_oldest/drivers/net/pcmcia/wvlan_cs.c kern_fix/drivers/net/pcmcia/wvlan_cs.c ---- kern_oldest/drivers/net/pcmcia/wvlan_cs.c 2006-05-01 11:55:40.000000000 -0700 -+++ kern_fix/drivers/net/pcmcia/wvlan_cs.c 2006-05-01 15:25:34.000000000 -0700 -@@ -1084,9 +1084,9 @@ static int wvlan_hw_config (struct net_d - /* This is a PrismII card. It is is *very* similar - * to the Lucent, and the driver work 95%, - * therefore, we attempt to support it... */ -- printk(KERN_NOTICE "%s: This is a PrismII card, not a Wavelan IEEE card :-( --You may want report firmare revision (0x%X) and what the card support. --I will try to make it work, but you should look for a better driver.\n", dev_info, firmware); -+ printk(KERN_NOTICE "%s: This is a PrismII card, not a Wavelan IEEE card :-(\n" -+"You may want report firmare revision (0x%X) and what the card support.\n" -+"I will try to make it work, but you should look for a better driver.\n", dev_info, firmware); - local->has_port3 = 1; - local->has_ibssid = 0; - local->has_mwo = 0; -diff -X dontdiff -urp kern_oldest/drivers/net/wan/sbni.c kern_fix/drivers/net/wan/sbni.c ---- kern_oldest/drivers/net/wan/sbni.c 2006-05-01 11:55:40.000000000 -0700 -+++ kern_fix/drivers/net/wan/sbni.c 2006-05-01 15:25:34.000000000 -0700 -@@ -1552,13 +1552,13 @@ __setup( "sbni=", sbni_setup ); - static u32 - calc_crc32( u32 crc, u8 *p, u32 len ) - { -- register u32 _crc __asm ( "ax" ); -+ register u32 _crc; - _crc = crc; - - __asm __volatile ( - "xorl %%ebx, %%ebx\n" -- "movl %1, %%esi\n" -- "movl %2, %%ecx\n" -+ "movl %2, %%esi\n" -+ "movl %3, %%ecx\n" - "movl $crc32tab, %%edi\n" - "shrl $2, %%ecx\n" - "jz 1f\n" -@@ -1594,7 +1594,7 @@ calc_crc32( u32 crc, u8 *p, u32 len - "jnz 0b\n" - - "1:\n" -- "movl %2, %%ecx\n" -+ "movl %3, %%ecx\n" - "andl $3, %%ecx\n" - "jz 2f\n" - -@@ -1619,9 +1619,9 @@ calc_crc32( u32 crc, u8 *p, u32 len - "xorb 2(%%esi), %%bl\n" - "xorl (%%edi,%%ebx,4), %%eax\n" - "2:\n" -- : -- : "a" (_crc), "g" (p), "g" (len) -- : "ax", "bx", "cx", "dx", "si", "di" -+ : "=a" (_crc) -+ : "0" (_crc), "g" (p), "g" (len) -+ : "bx", "cx", "dx", "si", "di" - ); - - return _crc; -diff -X dontdiff -urp kern_oldest/drivers/sensors/lm87.c kern_fix/drivers/sensors/lm87.c ---- kern_oldest/drivers/sensors/lm87.c 2006-05-01 11:55:44.000000000 -0700 -+++ kern_fix/drivers/sensors/lm87.c 2006-05-01 15:25:34.000000000 -0700 -@@ -1060,10 +1060,10 @@ MODULE_LICENSE("GPL"); - #endif - - MODULE_AUTHOR -- ("Frodo Looijaard , -- Philip Edelbrock , -- Mark Studebaker , -- and Stephen Rousset "); -+ ("Frodo Looijaard , " -+ "Philip Edelbrock , " -+ "Mark Studebaker , " -+ "and Stephen Rousset "); - - MODULE_DESCRIPTION("LM87 driver"); - diff --git a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.20.patch b/lustre/kernel_patches/patches/configurable-x86-stack-2.4.20.patch deleted file mode 100644 index 38bafff..0000000 --- a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.20.patch +++ /dev/null @@ -1,318 +0,0 @@ -Index: kernel-2.4.21/arch/i386/kernel/entry.S -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/entry.S 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/kernel/entry.S 2003-12-04 11:57:01.000000000 -0800 -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - EBX = 0x00 - ECX = 0x04 -@@ -130,10 +131,6 @@ - .long 3b,6b; \ - .previous - --#define GET_CURRENT(reg) \ -- movl $-8192, reg; \ -- andl %esp, reg -- - ENTRY(lcall7) - pushfl # We get a different stack layout with call gates, - pushl %eax # which has to be cleaned up later.. -@@ -149,7 +146,7 @@ - movl %ecx,CS(%esp) # - movl %esp,%ebx - pushl %ebx -- andl $-8192,%ebx # GET_CURRENT -+ andl $-THREAD_SIZE,%ebx # GET_CURRENT - movl exec_domain(%ebx),%edx # Get the execution domain - movl 4(%edx),%edx # Get the lcall7 handler for the domain - pushl $0x7 -@@ -173,7 +170,7 @@ - movl %ecx,CS(%esp) # - movl %esp,%ebx - pushl %ebx -- andl $-8192,%ebx # GET_CURRENT -+ andl $-THREAD_SIZE,%ebx # GET_CURRENT - movl exec_domain(%ebx),%edx # Get the execution domain - movl 4(%edx),%edx # Get the lcall7 handler for the domain - pushl $0x27 -Index: kernel-2.4.21/arch/i386/kernel/smpboot.c -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/smpboot.c 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/kernel/smpboot.c 2003-12-04 11:57:01.000000000 -0800 -@@ -819,7 +819,7 @@ - - /* So we see what's up */ - printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); -- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); -+ stack_start.esp = (void *)idle->thread.esp; - - /* - * This grunge runs the startup process for -@@ -892,7 +892,7 @@ - Dprintk("CPU has booted.\n"); - } else { - boot_error= 1; -- if (*((volatile unsigned char *)phys_to_virt(8192)) -+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE)) - == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); -@@ -915,7 +915,7 @@ - } - - /* mark "stuck" area as not stuck */ -- *((volatile unsigned long *)phys_to_virt(8192)) = 0; -+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0; - - if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) { - printk("Restoring NMI vector\n"); -Index: kernel-2.4.21/arch/i386/kernel/traps.c -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/traps.c 2002-11-28 15:53:09.000000000 -0800 -+++ kernel-2.4.21/arch/i386/kernel/traps.c 2003-12-04 11:57:01.000000000 -0800 -@@ -158,7 +158,7 @@ - unsigned long esp = tsk->thread.esp; - - /* User space on another CPU? */ -- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1)) - return; - show_trace((unsigned long *)esp); - } -Index: kernel-2.4.21/arch/i386/kernel/head.S -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/head.S 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/kernel/head.S 2003-12-04 11:57:01.000000000 -0800 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #define OLD_CL_MAGIC_ADDR 0x90020 - #define OLD_CL_MAGIC 0xA33F -@@ -320,7 +321,7 @@ - ret - - ENTRY(stack_start) -- .long SYMBOL_NAME(init_task_union)+8192 -+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE - .long __KERNEL_DS - - /* This is the default interrupt "handler" :-) */ -Index: kernel-2.4.21/arch/i386/kernel/irq.c -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/irq.c 2002-11-28 15:53:09.000000000 -0800 -+++ kernel-2.4.21/arch/i386/kernel/irq.c 2003-12-04 11:57:01.000000000 -0800 -@@ -581,7 +581,10 @@ - long esp; - - /* Debugging check for stack overflow: is there less than 1KB free? */ -- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191)); -+ __asm__ __volatile__( -+ "andl %%esp,%0" -+ : "=r" (esp) : "0" (THREAD_SIZE-1)); -+ - if (unlikely(esp < (sizeof(struct task_struct) + 1024))) { - extern void show_stack(unsigned long *); - -Index: kernel-2.4.21/arch/i386/lib/getuser.S -=================================================================== ---- kernel-2.4.21.orig/arch/i386/lib/getuser.S 1998-01-12 13:42:52.000000000 -0800 -+++ kernel-2.4.21/arch/i386/lib/getuser.S 2003-12-04 11:57:01.000000000 -0800 -@@ -21,6 +21,10 @@ - * as they get called from within inline assembly. - */ - -+/* Duplicated from asm/processor.h */ -+#include -+#include -+ - addr_limit = 12 - - .text -@@ -28,7 +32,7 @@ - .globl __get_user_1 - __get_user_1: - movl %esp,%edx -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 1: movzbl (%eax),%edx -@@ -41,7 +45,7 @@ - addl $1,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 2: movzwl -1(%eax),%edx -@@ -54,7 +58,7 @@ - addl $3,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 3: movl -3(%eax),%edx -Index: kernel-2.4.21/arch/i386/config.in -=================================================================== ---- kernel-2.4.21.orig/arch/i386/config.in 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/config.in 2003-12-04 11:57:01.000000000 -0800 -@@ -256,6 +256,29 @@ - if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then - define_bool CONFIG_HAVE_DEC_LOCK y - fi -+ -+choice 'Bigger Stack Size Support' \ -+ "off CONFIG_NOBIGSTACK \ -+ 16KB CONFIG_STACK_SIZE_16KB \ -+ 32KB CONFIG_STACK_SIZE_32KB \ -+ 64KB CONFIG_STACK_SIZE_64KB" off -+ -+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 1 -+else -+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 2 -+ else -+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 3 -+ else -+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 4 -+ fi -+ fi -+ fi -+fi -+ - endmenu - - mainmenu_option next_comment -Index: kernel-2.4.21/arch/i386/vmlinux.lds -=================================================================== ---- kernel-2.4.21.orig/arch/i386/vmlinux.lds 2002-02-25 11:37:53.000000000 -0800 -+++ kernel-2.4.21/arch/i386/vmlinux.lds 2003-12-04 11:57:01.000000000 -0800 -@@ -35,7 +35,8 @@ - - _edata = .; /* End of data section */ - -- . = ALIGN(8192); /* init_task */ -+/* chose the biggest of the possible stack sizes here? */ -+ . = ALIGN(65536); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); /* Init code and data */ -Index: kernel-2.4.21/include/asm-i386/current.h -=================================================================== ---- kernel-2.4.21.orig/include/asm-i386/current.h 1998-08-14 16:35:22.000000000 -0700 -+++ kernel-2.4.21/include/asm-i386/current.h 2003-12-04 11:57:01.000000000 -0800 -@@ -1,15 +1,43 @@ - #ifndef _I386_CURRENT_H - #define _I386_CURRENT_H -+#include -+ -+/* -+ * Configurable page sizes on i386, mainly for debugging purposes. -+ * (c) Balbir Singh -+ */ -+ -+#ifdef __ASSEMBLY__ -+ -+#define PAGE_SIZE 4096 /* as cannot handle 1UL << 12 */ -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) -+ -+#define GET_CURRENT(reg) \ -+ movl $-THREAD_SIZE, reg; \ -+ andl %esp, reg -+ -+#else /* __ASSEMBLY__ */ -+ -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) -+#define alloc_task_struct() \ -+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,CONFIG_STACK_SIZE_SHIFT)) -+ -+#define free_task_struct(p) \ -+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT) -+ -+#define INIT_TASK_SIZE THREAD_SIZE - - struct task_struct; - - static inline struct task_struct * get_current(void) - { - struct task_struct *current; -- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); -+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1))); - return current; - } - - #define current get_current() - -+#endif /* __ASSEMBLY__ */ -+ - #endif /* !(_I386_CURRENT_H) */ -Index: kernel-2.4.21/include/asm-i386/hw_irq.h -=================================================================== ---- kernel-2.4.21.orig/include/asm-i386/hw_irq.h 2001-11-22 11:46:18.000000000 -0800 -+++ kernel-2.4.21/include/asm-i386/hw_irq.h 2003-12-04 11:57:01.000000000 -0800 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - /* - * IDT vectors usable for external interrupt sources start -@@ -113,10 +114,6 @@ - #define IRQ_NAME2(nr) nr##_interrupt(void) - #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) - --#define GET_CURRENT \ -- "movl %esp, %ebx\n\t" \ -- "andl $-8192, %ebx\n\t" -- - /* - * SMP has a few special interrupts for IPI messages - */ -Index: kernel-2.4.21/include/asm-i386/processor.h -=================================================================== ---- kernel-2.4.21.orig/include/asm-i386/processor.h 2003-06-13 07:51:38.000000000 -0700 -+++ kernel-2.4.21/include/asm-i386/processor.h 2003-12-04 11:57:01.000000000 -0800 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -453,9 +454,6 @@ - #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) - #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) - --#define THREAD_SIZE (2*PAGE_SIZE) --#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) --#define free_task_struct(p) free_pages((unsigned long) (p), 1) - #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) - - #define init_task (init_task_union.task) -Index: kernel-2.4.21/include/linux/sched.h -=================================================================== ---- kernel-2.4.21.orig/include/linux/sched.h 2003-06-13 15:26:52.000000000 -0700 -+++ kernel-2.4.21/include/linux/sched.h 2003-12-04 12:00:14.000000000 -0800 -@@ -2,6 +2,7 @@ - #define _LINUX_SCHED_H - - #include /* for HZ */ -+#include /* maybe for INIT_TASK_SIZE */ - - extern unsigned long event; - diff --git a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-chaos.patch b/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-chaos.patch deleted file mode 100644 index 271ee19..0000000 --- a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-chaos.patch +++ /dev/null @@ -1,468 +0,0 @@ -Index: linux-2.4.21-27.EL/include/asm-i386/hw_irq.h -=================================================================== ---- linux-2.4.21-27.EL.orig/include/asm-i386/hw_irq.h 2004-12-21 13:51:09.000000000 -0500 -+++ linux-2.4.21-27.EL/include/asm-i386/hw_irq.h 2005-01-07 10:55:45.367690072 -0500 -@@ -135,21 +135,17 @@ - " \ - /* load the real stack - keep the offset */ \ - \ -- movl $-8192, %ebx; \ -+ movl $- " STR(THREAD_SIZE) ", %ebx; \ - andl %esp, %ebx; \ - movl 36(%ebx), %edx; \ - movl %esp, %ebx; \ -- andl $0x1fff, %ebx; \ -+ andl $( " STR(THREAD_SIZE) "-1), %ebx; \ - orl %ebx, %edx; \ - movl %edx, %esp;" - - #define IRQ_NAME2(nr) nr##_interrupt(void) - #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) - --#define GET_CURRENT \ -- "movl %esp, %ebx\n\t" \ -- "andl $-8192, %ebx\n\t" -- - /* - * SMP has a few special interrupts for IPI messages - */ -Index: linux-2.4.21-27.EL/include/asm-i386/processor.h -=================================================================== ---- linux-2.4.21-27.EL.orig/include/asm-i386/processor.h 2004-12-21 13:51:31.000000000 -0500 -+++ linux-2.4.21-27.EL/include/asm-i386/processor.h 2005-01-07 10:55:45.376688704 -0500 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -490,10 +491,6 @@ - #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) - #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) - --#define THREAD_SIZE (2*PAGE_SIZE) --#define __alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) --#define __free_task_struct(p) do { BUG_ON((p)->state < TASK_ZOMBIE); free_pages((unsigned long) (p), 1); } while (0) -- - #define init_task (init_task_union.task) - #define init_stack (init_task_union.stack) - -Index: linux-2.4.21-27.EL/include/asm-i386/current.h -=================================================================== ---- linux-2.4.21-27.EL.orig/include/asm-i386/current.h 1998-08-14 19:35:22.000000000 -0400 -+++ linux-2.4.21-27.EL/include/asm-i386/current.h 2005-01-07 10:55:45.356691744 -0500 -@@ -1,15 +1,64 @@ - #ifndef _I386_CURRENT_H - #define _I386_CURRENT_H -+#include -+ -+/* -+ * Configurable page sizes on i386, mainly for debugging purposes. -+ * (c) Balbir Singh -+ */ -+ -+/* enumerate the values, include/asm-i386/hw_irq.h in particular needs this */ -+#if (PAGE_SIZE != 4096) -+#error PAGE_SIZE != 4096 unsupported -+#endif -+ -+#if (CONFIG_STACK_SIZE_SHIFT == 0) -+#define THREAD_SIZE 4096 -+#elif (CONFIG_STACK_SIZE_SHIFT == 1) -+#define THREAD_SIZE 8192 -+#elif (CONFIG_STACK_SIZE_SHIFT == 2) -+#define THREAD_SIZE 16384 -+#elif (CONFIG_STACK_SIZE_SHIFT == 3) -+#define THREAD_SIZE 32768 -+#elif (CONFIG_STACK_SIZE_SHIFT == 4) -+#define THREAD_SIZE 65536 -+#else -+#error CONFIG_STACK_SIZE_SHIFT > 4 unsupported -+#endif -+ -+#if (CONFIG_STACK_SIZE_SHIFT != 1) && defined(CONFIG_X86_4G) -+#error Large stacks with 4G/4G split unsupported -+#endif -+ -+#ifdef __ASSEMBLY__ -+ -+#define GET_CURRENT(reg) \ -+ movl $-THREAD_SIZE, reg; \ -+ andl %esp, reg -+ -+#else /* __ASSEMBLY__ */ -+ -+#define __alloc_task_struct() \ -+ ((struct task_struct *) __get_free_pages(GFP_KERNEL, CONFIG_STACK_SIZE_SHIFT)) -+ -+#define __free_task_struct(p) do { \ -+ BUG_ON((p)->state < TASK_ZOMBIE); \ -+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT); \ -+} while(0) -+ -+#define INIT_TASK_SIZE THREAD_SIZE - - struct task_struct; - - static inline struct task_struct * get_current(void) - { - struct task_struct *current; -- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); -+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1))); - return current; - } - - #define current get_current() - -+#endif /* __ASSEMBLY__ */ -+ - #endif /* !(_I386_CURRENT_H) */ -Index: linux-2.4.21-27.EL/include/asm-x86_64/processor.h -=================================================================== ---- linux-2.4.21-27.EL.orig/include/asm-x86_64/processor.h 2004-12-21 13:51:31.000000000 -0500 -+++ linux-2.4.21-27.EL/include/asm-x86_64/processor.h 2005-01-07 10:58:24.167548824 -0500 -@@ -407,8 +407,8 @@ - /* Note: most of the infrastructure to separate stack and task_struct - are already there. When you run out of stack try this first. */ - --#define __alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) --#define __free_task_struct(p) free_pages((unsigned long) (p), 1) -+#define __alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL, THREAD_ORDER)) -+#define __free_task_struct(p) free_pages((unsigned long) (p), THREAD_ORDER) - - #define init_task (init_task_union.task) - #define init_stack (init_task_union.stack) -Index: linux-2.4.21-27.EL/include/asm-x86_64/page.h -=================================================================== ---- linux-2.4.21-27.EL.orig/include/asm-x86_64/page.h 2004-12-21 13:51:10.000000000 -0500 -+++ linux-2.4.21-27.EL/include/asm-x86_64/page.h 2005-01-07 10:55:45.404684448 -0500 -@@ -27,8 +27,8 @@ - /* We still hope 8K is enough, but ... */ - /* Currently it is actually ~6k. This would change when task_struct moves into - an own slab. */ --#define THREAD_ORDER 1 --#define THREAD_SIZE (2*PAGE_SIZE) -+#define THREAD_ORDER CONFIG_STACK_SIZE_SHIFT -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) - - #define INIT_TASK_SIZE THREAD_SIZE - #define CURRENT_MASK (~(THREAD_SIZE-1)) -Index: linux-2.4.21-27.EL/include/asm-x86_64/current.h -=================================================================== ---- linux-2.4.21-27.EL.orig/include/asm-x86_64/current.h 2002-11-28 18:53:15.000000000 -0500 -+++ linux-2.4.21-27.EL/include/asm-x86_64/current.h 2005-01-07 10:55:45.394685968 -0500 -@@ -5,6 +5,7 @@ - struct task_struct; - - #include -+#include - - static inline struct task_struct *get_current(void) - { -Index: linux-2.4.21-27.EL/arch/x86_64/config.in -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/x86_64/config.in 2004-12-21 13:51:30.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/x86_64/config.in 2005-01-07 10:55:45.324696608 -0500 -@@ -90,6 +90,28 @@ - define_bool CONFIG_NUMA y - fi - -+choice 'Bigger Stack Size Support' \ -+ "off CONFIG_NOBIGSTACK \ -+ 16KB CONFIG_STACK_SIZE_16KB \ -+ 32KB CONFIG_STACK_SIZE_32KB \ -+ 64KB CONFIG_STACK_SIZE_64KB" off -+ -+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 1 -+else -+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 2 -+ else -+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 3 -+ else -+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 4 -+ fi -+ fi -+ fi -+fi -+ - endmenu - - mainmenu_option next_comment -Index: linux-2.4.21-27.EL/arch/x86_64/kernel/smpboot.c -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/x86_64/kernel/smpboot.c 2004-12-21 13:51:01.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/x86_64/kernel/smpboot.c 2005-01-07 10:55:45.325696456 -0500 -@@ -753,7 +753,7 @@ - Dprintk("CPU has booted.\n"); - } else { - boot_status = 1; -- if (*((volatile unsigned char *)phys_to_virt(8192)) -+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE)) - == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); -@@ -771,7 +771,7 @@ - } - - /* mark "stuck" area as not stuck */ -- *((volatile unsigned int *)phys_to_virt(8192)) = 0; -+ *((volatile unsigned int *)phys_to_virt(THREAD_SIZE)) = 0; - - return cpu; - } -Index: linux-2.4.21-27.EL/arch/x86_64/kernel/traps.c -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/x86_64/kernel/traps.c 2004-12-21 13:51:15.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/x86_64/kernel/traps.c 2005-01-07 10:55:45.326696304 -0500 -@@ -240,7 +240,7 @@ - unsigned long rsp = tsk->thread.rsp; - - /* User space on another CPU? */ -- if ((rsp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ if ((rsp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1)) - return; - show_trace((unsigned long *)rsp); - } -Index: linux-2.4.21-27.EL/arch/x86_64/vmlinux.lds -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/x86_64/vmlinux.lds 2003-06-13 10:51:32.000000000 -0400 -+++ linux-2.4.21-27.EL/arch/x86_64/vmlinux.lds 2005-01-07 10:55:45.327696152 -0500 -@@ -72,7 +72,8 @@ - .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) } - . = LOADADDR(.vsyscall_0) + 4096; - -- . = ALIGN(8192); /* init_task */ -+/* chose the biggest of the possible stack sizes here? */ -+ . = ALIGN(65536); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); -Index: linux-2.4.21-27.EL/arch/i386/config.in -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/config.in 2004-12-21 13:51:31.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/config.in 2005-01-07 10:55:45.324696608 -0500 -@@ -306,6 +306,28 @@ - fi - fi - -+choice 'Bigger Stack Size Support' \ -+ "off CONFIG_NOBIGSTACK \ -+ 16KB CONFIG_STACK_SIZE_16KB \ -+ 32KB CONFIG_STACK_SIZE_32KB \ -+ 64KB CONFIG_STACK_SIZE_64KB" off -+ -+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 1 -+else -+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 2 -+ else -+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 3 -+ else -+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 4 -+ fi -+ fi -+ fi -+fi -+ - if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then - define_bool CONFIG_HAVE_DEC_LOCK y - fi -Index: linux-2.4.21-27.EL/arch/i386/kernel/entry.S -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/kernel/entry.S 2004-12-21 13:51:31.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/kernel/entry.S 2005-01-07 10:55:45.271704664 -0500 -@@ -46,6 +46,7 @@ - #include - #include - #include -+#include - #include - - EBX = 0x00 -@@ -94,10 +95,6 @@ - - ENOSYS = 38 - --#define GET_CURRENT(reg) \ -- movl $-8192, reg; \ -- andl %esp, reg -- - #if CONFIG_X86_HIGH_ENTRY - - #define call_SYMBOL_NAME_ABS(X) movl $X, %ebp; call *%ebp -@@ -193,7 +190,7 @@ - GET_CURRENT(%ebx); \ - movl real_stack(%ebx), %edx; \ - movl %esp, %ebx; \ -- andl $0x1fff, %ebx; \ -+ andl $(THREAD_SIZE-1), %ebx; \ - orl %ebx, %edx; \ - movl %edx, %esp; - -@@ -228,7 +225,7 @@ - return_path_start_marker: \ - nop; \ - movl %esp, %ebx; \ -- andl $0x1fff, %ebx; \ -+ andl $(THREAD_SIZE-1), %ebx; \ - orl %ebx, %edx; \ - movl %esp, %eax; \ - movl %edx, %esp; \ -Index: linux-2.4.21-27.EL/arch/i386/kernel/irq.c -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/kernel/irq.c 2004-12-21 13:51:22.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/kernel/irq.c 2005-01-07 10:55:45.307699192 -0500 -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - - -@@ -585,7 +586,7 @@ - long esp; - - /* Debugging check for stack overflow: is there less than 1KB free? */ -- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191)); -+ __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (THREAD_SIZE-1)); - if (unlikely(esp < (sizeof(struct task_struct) + 1024))) { - extern void show_stack(unsigned long *); - -Index: linux-2.4.21-27.EL/arch/i386/kernel/smpboot.c -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/kernel/smpboot.c 2004-12-21 13:51:01.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/kernel/smpboot.c 2005-01-07 10:55:45.305699496 -0500 -@@ -814,7 +814,7 @@ - - /* So we see what's up */ - printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); -- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); -+ stack_start.esp = (void *)idle->thread.esp; - - /* - * This grunge runs the startup process for -@@ -887,7 +887,7 @@ - Dprintk("CPU has booted.\n"); - } else { - boot_error= 1; -- if (*((volatile unsigned char *)phys_to_virt(8192)) -+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE)) - == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); -@@ -910,7 +910,7 @@ - } - - /* mark "stuck" area as not stuck */ -- *((volatile unsigned long *)phys_to_virt(8192)) = 0; -+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0; - - if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) { - printk("Restoring NMI vector\n"); -Index: linux-2.4.21-27.EL/arch/i386/kernel/traps.c -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/kernel/traps.c 2004-12-21 13:51:15.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/kernel/traps.c 2005-01-07 10:55:45.306699344 -0500 -@@ -180,7 +180,7 @@ - unsigned long esp = tsk->thread.esp; - - /* User space on another CPU? */ -- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1)) - return; - show_trace((unsigned long *)esp); - } -Index: linux-2.4.21-27.EL/arch/i386/kernel/head.S -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/kernel/head.S 2004-12-21 13:51:07.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/kernel/head.S 2005-01-07 10:55:45.307699192 -0500 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #define OLD_CL_MAGIC_ADDR 0x90020 - #define OLD_CL_MAGIC 0xA33F -@@ -343,7 +344,7 @@ - ret - - ENTRY(stack_start) -- .long SYMBOL_NAME(init_task_union)+8192 -+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE - .long __KERNEL_DS - - /* This is the default interrupt "handler" :-) */ -Index: linux-2.4.21-27.EL/arch/i386/lib/getuser.S -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/lib/getuser.S 1998-01-12 16:42:52.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/lib/getuser.S 2005-01-07 10:55:45.323696760 -0500 -@@ -21,6 +21,10 @@ - * as they get called from within inline assembly. - */ - -+/* Duplicated from asm/processor.h */ -+#include -+#include -+ - addr_limit = 12 - - .text -@@ -28,7 +32,7 @@ - .globl __get_user_1 - __get_user_1: - movl %esp,%edx -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 1: movzbl (%eax),%edx -@@ -41,7 +45,7 @@ - addl $1,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 2: movzwl -1(%eax),%edx -@@ -54,7 +58,7 @@ - addl $3,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 3: movl -3(%eax),%edx -Index: linux-2.4.21-27.EL/arch/i386/vmlinux.lds.in -=================================================================== ---- linux-2.4.21-27.EL.orig/arch/i386/vmlinux.lds.in 2004-12-21 13:51:08.000000000 -0500 -+++ linux-2.4.21-27.EL/arch/i386/vmlinux.lds.in 2005-01-07 10:55:45.324696608 -0500 -@@ -1,6 +1,7 @@ - - #define __ASSEMBLY__ - #include -+#include - - /* ld script to make i386 Linux kernel - * Written by Martin Mares ; -@@ -51,7 +52,7 @@ - - _edata = .; /* End of data section */ - -- . = ALIGN(8192); /* init_task */ -+ . = ALIGN(THREAD_SIZE); /* init_task */ - .data.init_task : { *(.data.init_task) } - - entry_tramp_start = .; diff --git a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse-171.patch b/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse-171.patch deleted file mode 100644 index 6e708bf..0000000 --- a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse-171.patch +++ /dev/null @@ -1,317 +0,0 @@ -Index: linux-2.4.21-171/arch/i386/kernel/entry.S -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/kernel/entry.S 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/kernel/entry.S 2004-04-03 16:02:32.000000000 -0500 -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - EBX = 0x00 - ECX = 0x04 -@@ -130,10 +131,6 @@ - .long 3b,6b; \ - .previous - --#define GET_CURRENT(reg) \ -- movl $-8192, reg; \ -- andl %esp, reg -- - ENTRY(lcall7) - pushfl # We get a different stack layout with call gates, - pushl %eax # which has to be cleaned up later.. -@@ -149,7 +146,7 @@ - movl %ecx,CS(%esp) # - movl %esp,%ebx - pushl %ebx -- andl $-8192,%ebx # GET_CURRENT -+ andl $-THREAD_SIZE,%ebx # GET_CURRENT - movl exec_domain(%ebx),%edx # Get the execution domain - movl 4(%edx),%edx # Get the lcall7 handler for the domain - pushl $0x7 -@@ -173,7 +170,7 @@ - movl %ecx,CS(%esp) # - movl %esp,%ebx - pushl %ebx -- andl $-8192,%ebx # GET_CURRENT -+ andl $-THREAD_SIZE,%ebx # GET_CURRENT - movl exec_domain(%ebx),%edx # Get the execution domain - movl 4(%edx),%edx # Get the lcall7 handler for the domain - pushl $0x27 -Index: linux-2.4.21-171/arch/i386/kernel/smpboot.c -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/kernel/smpboot.c 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/kernel/smpboot.c 2004-04-03 16:02:32.000000000 -0500 -@@ -833,7 +833,7 @@ - - /* So we see what's up */ - printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); -- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); -+ stack_start.esp = (void *)idle->thread.esp; - - /* - * This grunge runs the startup process for -@@ -914,7 +914,7 @@ - Dprintk("CPU has booted.\n"); - } else { - boot_error= 1; -- if (*((volatile unsigned char *)phys_to_virt(8192)) -+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE)) - == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); -@@ -937,7 +937,7 @@ - } - - /* mark "stuck" area as not stuck */ -- *((volatile unsigned long *)phys_to_virt(8192)) = 0; -+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0; - - #ifdef CONFIG_ES7000 - if (!es7000_plat) -Index: linux-2.4.21-171/arch/i386/kernel/traps.c -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/kernel/traps.c 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/kernel/traps.c 2004-04-03 16:02:32.000000000 -0500 -@@ -193,7 +193,7 @@ - unsigned long esp = tsk->thread.esp; - - /* User space on another CPU? */ -- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1)) - return; - show_trace((unsigned long *)esp); - } -Index: linux-2.4.21-171/arch/i386/kernel/head.S -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/kernel/head.S 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/kernel/head.S 2004-04-03 16:02:32.000000000 -0500 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #define OLD_CL_MAGIC_ADDR 0x90020 - #define OLD_CL_MAGIC 0xA33F -@@ -326,7 +327,7 @@ - ret - - ENTRY(stack_start) -- .long SYMBOL_NAME(init_task_union)+8192 -+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE - .long __KERNEL_DS - - /* This is the default interrupt "handler" :-) */ -Index: linux-2.4.21-171/arch/i386/kernel/irq.c -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/kernel/irq.c 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/kernel/irq.c 2004-04-03 16:05:17.000000000 -0500 -@@ -597,7 +597,9 @@ - long esp; - - /* Debugging check for stack overflow: is there less than 1KB free? */ -- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191)); -+ __asm__ __volatile__( -+ "andl %%esp,%0" -+ : "=r" (esp) : "0" (THREAD_SIZE-1)); - if (unlikely(esp < (sizeof(struct task_struct) + sysctl_stackwarn))) { - static unsigned long next_jiffies; /* ratelimiting */ - static long least_esp = THREAD_SIZE; -Index: linux-2.4.21-171/arch/i386/lib/getuser.S -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/lib/getuser.S 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/lib/getuser.S 2004-04-03 16:02:32.000000000 -0500 -@@ -21,6 +21,10 @@ - * as they get called from within inline assembly. - */ - -+/* Duplicated from asm/processor.h */ -+#include -+#include -+ - addr_limit = 12 - - .text -@@ -28,7 +32,7 @@ - .globl __get_user_1 - __get_user_1: - movl %esp,%edx -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 1: movzbl (%eax),%edx -@@ -41,7 +45,7 @@ - addl $1,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 2: movzwl -1(%eax),%edx -@@ -54,7 +58,7 @@ - addl $3,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 3: movl -3(%eax),%edx -Index: linux-2.4.21-171/arch/i386/config.in -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/config.in 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/config.in 2004-04-03 16:02:32.000000000 -0500 -@@ -325,6 +325,29 @@ - if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then - define_bool CONFIG_HAVE_DEC_LOCK y - fi -+ -+choice 'Bigger Stack Size Support' \ -+ "off CONFIG_NOBIGSTACK \ -+ 16KB CONFIG_STACK_SIZE_16KB \ -+ 32KB CONFIG_STACK_SIZE_32KB \ -+ 64KB CONFIG_STACK_SIZE_64KB" off -+ -+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 1 -+else -+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 2 -+ else -+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 3 -+ else -+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 4 -+ fi -+ fi -+ fi -+fi -+ - endmenu - - mainmenu_option next_comment -Index: linux-2.4.21-171/arch/i386/vmlinux.lds.S -=================================================================== ---- linux-2.4.21-171.orig/arch/i386/vmlinux.lds.S 2004-02-24 13:43:40.000000000 -0500 -+++ linux-2.4.21-171/arch/i386/vmlinux.lds.S 2004-04-03 16:02:32.000000000 -0500 -@@ -39,7 +39,8 @@ - - _edata = .; /* End of data section */ - -- . = ALIGN(8192); /* init_task */ -+/* chose the biggest of the possible stack sizes here? */ -+ . = ALIGN(65536); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); /* Init code and data */ -Index: linux-2.4.21-171/include/asm-i386/current.h -=================================================================== ---- linux-2.4.21-171.orig/include/asm-i386/current.h 2004-02-24 13:42:29.000000000 -0500 -+++ linux-2.4.21-171/include/asm-i386/current.h 2004-04-03 16:02:32.000000000 -0500 -@@ -1,15 +1,43 @@ - #ifndef _I386_CURRENT_H - #define _I386_CURRENT_H -+#include -+ -+/* -+ * Configurable page sizes on i386, mainly for debugging purposes. -+ * (c) Balbir Singh -+ */ -+ -+#ifdef __ASSEMBLY__ -+ -+#define PAGE_SIZE 4096 /* as cannot handle 1UL << 12 */ -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) -+ -+#define GET_CURRENT(reg) \ -+ movl $-THREAD_SIZE, reg; \ -+ andl %esp, reg -+ -+#else /* __ASSEMBLY__ */ -+ -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) -+#define alloc_task_struct() \ -+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,CONFIG_STACK_SIZE_SHIFT)) -+ -+#define free_task_struct(p) \ -+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT) -+ -+#define INIT_TASK_SIZE THREAD_SIZE - - struct task_struct; - - static inline struct task_struct * get_current(void) - { - struct task_struct *current; -- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); -+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1))); - return current; - } - - #define current get_current() - -+#endif /* __ASSEMBLY__ */ -+ - #endif /* !(_I386_CURRENT_H) */ -Index: linux-2.4.21-171/include/asm-i386/hw_irq.h -=================================================================== ---- linux-2.4.21-171.orig/include/asm-i386/hw_irq.h 2004-02-24 13:42:29.000000000 -0500 -+++ linux-2.4.21-171/include/asm-i386/hw_irq.h 2004-04-03 16:02:32.000000000 -0500 -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - - /* - * IDT vectors usable for external interrupt sources start -@@ -116,10 +117,6 @@ - #define IRQ_NAME2(nr) nr##_interrupt(void) - #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) - --#define GET_CURRENT \ -- "movl %esp, %ebx\n\t" \ -- "andl $-8192, %ebx\n\t" -- - /* - * SMP has a few special interrupts for IPI messages - */ -Index: linux-2.4.21-171/include/asm-i386/processor.h -=================================================================== ---- linux-2.4.21-171.orig/include/asm-i386/processor.h 2004-02-24 13:42:29.000000000 -0500 -+++ linux-2.4.21-171/include/asm-i386/processor.h 2004-04-03 16:02:32.000000000 -0500 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -464,9 +465,6 @@ - #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) - #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) - --#define THREAD_SIZE (2*PAGE_SIZE) --#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) --#define free_task_struct(p) free_pages((unsigned long) (p), 1) - #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) - - #define init_task (init_task_union.task) -Index: linux-2.4.21-171/include/linux/sched.h -=================================================================== ---- linux-2.4.21-171.orig/include/linux/sched.h 2004-03-31 14:58:26.000000000 -0500 -+++ linux-2.4.21-171/include/linux/sched.h 2004-04-03 16:02:32.000000000 -0500 -@@ -2,6 +2,7 @@ - #define _LINUX_SCHED_H - - #include /* for HZ */ -+#include /* maybe for INIT_TASK_SIZE */ - - extern unsigned long event; - diff --git a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse2.patch b/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse2.patch deleted file mode 100644 index dc68b3e..0000000 --- a/lustre/kernel_patches/patches/configurable-x86-stack-2.4.21-suse2.patch +++ /dev/null @@ -1,318 +0,0 @@ -Index: kernel-2.4.21/arch/i386/kernel/entry.S -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/entry.S 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/kernel/entry.S 2003-12-04 11:57:01.000000000 -0800 -@@ -45,6 +45,7 @@ - #include - #include - #include -+#include - - EBX = 0x00 - ECX = 0x04 -@@ -130,10 +131,6 @@ - .long 3b,6b; \ - .previous - --#define GET_CURRENT(reg) \ -- movl $-8192, reg; \ -- andl %esp, reg -- - ENTRY(lcall7) - pushfl # We get a different stack layout with call gates, - pushl %eax # which has to be cleaned up later.. -@@ -149,7 +146,7 @@ - movl %ecx,CS(%esp) # - movl %esp,%ebx - pushl %ebx -- andl $-8192,%ebx # GET_CURRENT -+ andl $-THREAD_SIZE,%ebx # GET_CURRENT - movl exec_domain(%ebx),%edx # Get the execution domain - movl 4(%edx),%edx # Get the lcall7 handler for the domain - pushl $0x7 -@@ -173,7 +170,7 @@ - movl %ecx,CS(%esp) # - movl %esp,%ebx - pushl %ebx -- andl $-8192,%ebx # GET_CURRENT -+ andl $-THREAD_SIZE,%ebx # GET_CURRENT - movl exec_domain(%ebx),%edx # Get the execution domain - movl 4(%edx),%edx # Get the lcall7 handler for the domain - pushl $0x27 -Index: kernel-2.4.21/arch/i386/kernel/smpboot.c -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/smpboot.c 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/kernel/smpboot.c 2003-12-04 11:57:01.000000000 -0800 -@@ -819,7 +819,7 @@ - - /* So we see what's up */ - printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); -- stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); -+ stack_start.esp = (void *)idle->thread.esp; - - /* - * This grunge runs the startup process for -@@ -892,7 +892,7 @@ - Dprintk("CPU has booted.\n"); - } else { - boot_error= 1; -- if (*((volatile unsigned char *)phys_to_virt(8192)) -+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE)) - == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); -@@ -915,7 +915,7 @@ - } - - /* mark "stuck" area as not stuck */ -- *((volatile unsigned long *)phys_to_virt(8192)) = 0; -+ *((volatile unsigned long *)phys_to_virt(THREAD_SIZE)) = 0; - - if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) { - printk("Restoring NMI vector\n"); -Index: kernel-2.4.21/arch/i386/kernel/traps.c -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/traps.c 2002-11-28 15:53:09.000000000 -0800 -+++ kernel-2.4.21/arch/i386/kernel/traps.c 2003-12-04 11:57:01.000000000 -0800 -@@ -158,7 +158,7 @@ - unsigned long esp = tsk->thread.esp; - - /* User space on another CPU? */ -- if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ if ((esp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1)) - return; - show_trace((unsigned long *)esp); - } -Index: kernel-2.4.21/arch/i386/kernel/head.S -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/head.S 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/kernel/head.S 2003-12-04 11:57:01.000000000 -0800 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #define OLD_CL_MAGIC_ADDR 0x90020 - #define OLD_CL_MAGIC 0xA33F -@@ -320,7 +321,7 @@ - ret - - ENTRY(stack_start) -- .long SYMBOL_NAME(init_task_union)+8192 -+ .long SYMBOL_NAME(init_task_union)+THREAD_SIZE - .long __KERNEL_DS - - /* This is the default interrupt "handler" :-) */ -Index: kernel-2.4.21/arch/i386/kernel/irq.c -=================================================================== ---- kernel-2.4.21.orig/arch/i386/kernel/irq.c 2002-11-28 15:53:09.000000000 -0800 -+++ kernel-2.4.21/arch/i386/kernel/irq.c 2003-12-04 11:57:01.000000000 -0800 -@@ -581,7 +581,10 @@ - long esp; - - /* Debugging check for stack overflow: is there less than 1KB free? */ -- __asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191)); -+ __asm__ __volatile__( -+ "andl %%esp,%0" -+ : "=r" (esp) : "0" (THREAD_SIZE-1)); -+ - if (unlikely(esp < (sizeof(struct task_struct) + 1024))) { - extern void show_stack(unsigned long *); - -Index: kernel-2.4.21/arch/i386/lib/getuser.S -=================================================================== ---- kernel-2.4.21.orig/arch/i386/lib/getuser.S 1998-01-12 13:42:52.000000000 -0800 -+++ kernel-2.4.21/arch/i386/lib/getuser.S 2003-12-04 11:57:01.000000000 -0800 -@@ -21,6 +21,10 @@ - * as they get called from within inline assembly. - */ - -+/* Duplicated from asm/processor.h */ -+#include -+#include -+ - addr_limit = 12 - - .text -@@ -28,7 +32,7 @@ - .globl __get_user_1 - __get_user_1: - movl %esp,%edx -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 1: movzbl (%eax),%edx -@@ -41,7 +45,7 @@ - addl $1,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 2: movzwl -1(%eax),%edx -@@ -54,7 +58,7 @@ - addl $3,%eax - movl %esp,%edx - jc bad_get_user -- andl $0xffffe000,%edx -+ andl $~(THREAD_SIZE - 1),%edx - cmpl addr_limit(%edx),%eax - jae bad_get_user - 3: movl -3(%eax),%edx -Index: kernel-2.4.21/arch/i386/config.in -=================================================================== ---- kernel-2.4.21.orig/arch/i386/config.in 2003-06-13 07:51:29.000000000 -0700 -+++ kernel-2.4.21/arch/i386/config.in 2003-12-04 11:57:01.000000000 -0800 -@@ -256,6 +256,29 @@ - if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then - define_bool CONFIG_HAVE_DEC_LOCK y - fi -+ -+choice 'Bigger Stack Size Support' \ -+ "off CONFIG_NOBIGSTACK \ -+ 16KB CONFIG_STACK_SIZE_16KB \ -+ 32KB CONFIG_STACK_SIZE_32KB \ -+ 64KB CONFIG_STACK_SIZE_64KB" off -+ -+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 1 -+else -+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 2 -+ else -+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 3 -+ else -+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 4 -+ fi -+ fi -+ fi -+fi -+ - endmenu - - mainmenu_option next_comment -Index: kernel-2.4.21/arch/i386/vmlinux.lds -=================================================================== ---- kernel-2.4.21.orig/arch/i386/vmlinux.lds.S 2002-02-25 11:37:53.000000000 -0800 -+++ kernel-2.4.21/arch/i386/vmlinux.lds.S 2003-12-04 11:57:01.000000000 -0800 -@@ -35,7 +35,8 @@ - - _edata = .; /* End of data section */ - -- . = ALIGN(8192); /* init_task */ -+/* chose the biggest of the possible stack sizes here? */ -+ . = ALIGN(65536); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); /* Init code and data */ -Index: kernel-2.4.21/include/asm-i386/current.h -=================================================================== ---- kernel-2.4.21.orig/include/asm-i386/current.h 1998-08-14 16:35:22.000000000 -0700 -+++ kernel-2.4.21/include/asm-i386/current.h 2003-12-04 11:57:01.000000000 -0800 -@@ -1,15 +1,43 @@ - #ifndef _I386_CURRENT_H - #define _I386_CURRENT_H -+#include -+ -+/* -+ * Configurable page sizes on i386, mainly for debugging purposes. -+ * (c) Balbir Singh -+ */ -+ -+#ifdef __ASSEMBLY__ -+ -+#define PAGE_SIZE 4096 /* as cannot handle 1UL << 12 */ -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) -+ -+#define GET_CURRENT(reg) \ -+ movl $-THREAD_SIZE, reg; \ -+ andl %esp, reg -+ -+#else /* __ASSEMBLY__ */ -+ -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) -+#define alloc_task_struct() \ -+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,CONFIG_STACK_SIZE_SHIFT)) -+ -+#define free_task_struct(p) \ -+ free_pages((unsigned long) (p), CONFIG_STACK_SIZE_SHIFT) -+ -+#define INIT_TASK_SIZE THREAD_SIZE - - struct task_struct; - - static inline struct task_struct * get_current(void) - { - struct task_struct *current; -- __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); -+ __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~(THREAD_SIZE - 1))); - return current; - } - - #define current get_current() - -+#endif /* __ASSEMBLY__ */ -+ - #endif /* !(_I386_CURRENT_H) */ -Index: kernel-2.4.21/include/asm-i386/hw_irq.h -=================================================================== ---- kernel-2.4.21.orig/include/asm-i386/hw_irq.h 2001-11-22 11:46:18.000000000 -0800 -+++ kernel-2.4.21/include/asm-i386/hw_irq.h 2003-12-04 11:57:01.000000000 -0800 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - /* - * IDT vectors usable for external interrupt sources start -@@ -113,10 +114,6 @@ - #define IRQ_NAME2(nr) nr##_interrupt(void) - #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) - --#define GET_CURRENT \ -- "movl %esp, %ebx\n\t" \ -- "andl $-8192, %ebx\n\t" -- - /* - * SMP has a few special interrupts for IPI messages - */ -Index: kernel-2.4.21/include/asm-i386/processor.h -=================================================================== ---- kernel-2.4.21.orig/include/asm-i386/processor.h 2003-06-13 07:51:38.000000000 -0700 -+++ kernel-2.4.21/include/asm-i386/processor.h 2003-12-04 11:57:01.000000000 -0800 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -453,9 +454,6 @@ - #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) - #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) - --#define THREAD_SIZE (2*PAGE_SIZE) --#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) --#define free_task_struct(p) free_pages((unsigned long) (p), 1) - #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) - - #define init_task (init_task_union.task) -Index: kernel-2.4.21/include/linux/sched.h -=================================================================== ---- kernel-2.4.21.orig/include/linux/sched.h 2003-06-13 15:26:52.000000000 -0700 -+++ kernel-2.4.21/include/linux/sched.h 2003-12-04 12:00:14.000000000 -0800 -@@ -2,6 +2,7 @@ - #define _LINUX_SCHED_H - - #include /* for HZ */ -+#include /* maybe for INIT_TASK_SIZE */ - - extern unsigned long event; - diff --git a/lustre/kernel_patches/patches/configurable-x86_64-2.4.21.patch b/lustre/kernel_patches/patches/configurable-x86_64-2.4.21.patch deleted file mode 100644 index 757ee71..0000000 --- a/lustre/kernel_patches/patches/configurable-x86_64-2.4.21.patch +++ /dev/null @@ -1,122 +0,0 @@ -Index: linux-2.4.21-drop2/arch/x86_64/kernel/smpboot.c -=================================================================== ---- linux-2.4.21-drop2.orig/arch/x86_64/kernel/smpboot.c 2003-10-28 10:34:20.000000000 -0800 -+++ linux-2.4.21-drop2/arch/x86_64/kernel/smpboot.c 2004-08-06 06:18:39.000000000 -0700 -@@ -751,7 +751,7 @@ - Dprintk("CPU has booted.\n"); - } else { - boot_status = 1; -- if (*((volatile unsigned char *)phys_to_virt(8192)) -+ if (*((volatile unsigned char *)phys_to_virt(THREAD_SIZE)) - == 0xA5) - /* trampoline started but...? */ - printk("Stuck ??\n"); -@@ -770,7 +770,7 @@ - } - - /* mark "stuck" area as not stuck */ -- *((volatile unsigned int *)phys_to_virt(8192)) = 0; -+ *((volatile unsigned int *)phys_to_virt(THREAD_SIZE)) = 0; - - return cpu; - } -Index: linux-2.4.21-drop2/arch/x86_64/kernel/traps.c -=================================================================== ---- linux-2.4.21-drop2.orig/arch/x86_64/kernel/traps.c 2003-11-06 15:52:41.000000000 -0800 -+++ linux-2.4.21-drop2/arch/x86_64/kernel/traps.c 2004-08-06 06:18:39.000000000 -0700 -@@ -239,7 +239,7 @@ - unsigned long rsp = tsk->thread.rsp; - - /* User space on another CPU? */ -- if ((rsp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ if ((rsp ^ (unsigned long)tsk) & ~(THREAD_SIZE - 1)) - return; - show_trace((unsigned long *)rsp); - } -Index: linux-2.4.21-drop2/arch/x86_64/config.in -=================================================================== ---- linux-2.4.21-drop2.orig/arch/x86_64/config.in 2003-10-28 10:34:25.000000000 -0800 -+++ linux-2.4.21-drop2/arch/x86_64/config.in 2004-08-06 06:20:20.000000000 -0700 -@@ -91,6 +91,28 @@ - define_bool CONFIG_NUMA y - fi - -+choice 'Bigger Stack Size Support' \ -+ "off CONFIG_NOBIGSTACK \ -+ 16KB CONFIG_STACK_SIZE_16KB \ -+ 32KB CONFIG_STACK_SIZE_32KB \ -+ 64KB CONFIG_STACK_SIZE_64KB" off -+ -+if [ "$CONFIG_NOBIGSTACK" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 1 -+else -+ if [ "$CONFIG_STACK_SIZE_16KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 2 -+ else -+ if [ "$CONFIG_STACK_SIZE_32KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 3 -+ else -+ if [ "$CONFIG_STACK_SIZE_64KB" = "y" ]; then -+ define_int CONFIG_STACK_SIZE_SHIFT 4 -+ fi -+ fi -+ fi -+fi -+ - endmenu - - mainmenu_option next_comment -Index: linux-2.4.21-drop2/arch/x86_64/vmlinux.lds -=================================================================== ---- linux-2.4.21-drop2.orig/arch/x86_64/vmlinux.lds 2003-06-13 07:51:32.000000000 -0700 -+++ linux-2.4.21-drop2/arch/x86_64/vmlinux.lds 2004-08-06 06:18:39.000000000 -0700 -@@ -72,7 +72,8 @@ - .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) } - . = LOADADDR(.vsyscall_0) + 4096; - -- . = ALIGN(8192); /* init_task */ -+/* chose the biggest of the possible stack sizes here? */ -+ . = ALIGN(65536); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); -Index: linux-2.4.21-drop2/include/asm-x86_64/current.h -=================================================================== ---- linux-2.4.21-drop2.orig/include/asm-x86_64/current.h 2003-11-10 16:44:28.000000000 -0800 -+++ linux-2.4.21-drop2/include/asm-x86_64/current.h 2004-08-06 06:24:33.000000000 -0700 -@@ -5,6 +5,7 @@ - struct task_struct; - - #include -+#include - - static inline struct task_struct *get_current(void) - { -Index: linux-2.4.21-drop2/include/asm-x86_64/page.h -=================================================================== ---- linux-2.4.21-drop2.orig/include/asm-x86_64/page.h 2003-10-28 10:34:00.000000000 -0800 -+++ linux-2.4.21-drop2/include/asm-x86_64/page.h 2004-08-06 06:24:33.000000000 -0700 -@@ -27,8 +27,8 @@ - /* We still hope 8K is enough, but ... */ - /* Currently it is actually ~6k. This would change when task_struct moves into - an own slab. */ --#define THREAD_ORDER 1 --#define THREAD_SIZE (2*PAGE_SIZE) -+#define THREAD_ORDER CONFIG_STACK_SIZE_SHIFT -+#define THREAD_SIZE ((1 << CONFIG_STACK_SIZE_SHIFT) * PAGE_SIZE) - - #define INIT_TASK_SIZE THREAD_SIZE - #define CURRENT_MASK (~(THREAD_SIZE-1)) -Index: linux-2.4.21-drop2/include/asm-x86_64/processor.h -=================================================================== ---- linux-2.4.21-drop2.orig/include/asm-x86_64/processor.h 2003-11-10 16:44:28.000000000 -0800 -+++ linux-2.4.21-drop2/include/asm-x86_64/processor.h 2004-08-06 06:24:33.000000000 -0700 -@@ -385,7 +385,7 @@ - are already there. When you run out of stack try this first. */ - #define alloc_task_struct() \ - ((struct task_struct *) __get_free_pages(GFP_KERNEL,THREAD_ORDER)) --#define free_task_struct(p) free_pages((unsigned long) (p), 1) -+#define free_task_struct(p) free_pages((unsigned long) (p), THREAD_ORDER) - #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) - - #define init_task (init_task_union.task) diff --git a/lustre/kernel_patches/patches/dcache_refcount_debug.patch b/lustre/kernel_patches/patches/dcache_refcount_debug.patch deleted file mode 100644 index 0eddc23..0000000 --- a/lustre/kernel_patches/patches/dcache_refcount_debug.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- ./fs/dcache.c.orig 2004-01-30 14:54:45.000000000 -0700 -+++ ./fs/dcache.c 2004-02-20 14:49:18.000000000 -0700 -@@ -348,8 +348,20 @@ - dentry_stat.nr_unused--; - - /* Unused dentry with a count? */ -- if (atomic_read(&dentry->d_count)) -+ if (atomic_read(&dentry->d_count)) { -+ struct inode *inode = dentry->d_inode; -+ printk(KERN_CRIT "dentry %*s %p->%lu/%u(%p/%s) ct %d\n", -+ dentry->d_name.len, dentry->d_name.name, dentry, -+ inode ? inode->i_ino : 0, -+ inode ? inode->i_generation : 0, inode, -+ inode ? inode->i_sb ? -+ inode->i_sb->s_type->name : "" : "", -+ atomic_read(&dentry->d_count)); -+ spin_unlock(&dcache_lock); -+ set_task_state(current, TASK_UNINTERRUPTIBLE); -+ schedule(); - BUG(); -+ } - - prune_one_dentry(dentry); - if (!--count) diff --git a/lustre/kernel_patches/patches/dev_read_only_2.4.20-rh.patch b/lustre/kernel_patches/patches/dev_read_only_2.4.20-rh.patch deleted file mode 100644 index c7650fd..0000000 --- a/lustre/kernel_patches/patches/dev_read_only_2.4.20-rh.patch +++ /dev/null @@ -1,125 +0,0 @@ -diff -ur linux-2.4.20-rh.orig/drivers/block/ll_rw_blk.c linux-2.4.20-rh/drivers/block/ll_rw_blk.c ---- linux-2.4.20-rh.orig/drivers/block/ll_rw_blk.c 2004-05-27 11:25:09.000000000 -0700 -+++ linux-2.4.20-rh/drivers/block/ll_rw_blk.c 2005-04-08 09:02:14.734804881 -0700 -@@ -645,6 +645,84 @@ void set_device_ro(kdev_t dev,int flag) - else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); - } - -+/* -+ * Debug code for turning block devices read-only *silently* (will -+ * discard writes silently). This is only for filesystem crash/recovery -+ * testing. -+ */ -+struct deventry { -+ kdev_t dev; -+ struct deventry *next; -+}; -+ -+static struct deventry *devlist = NULL; -+static spinlock_t devlock = SPIN_LOCK_UNLOCKED; -+ -+int dev_check_rdonly(kdev_t dev) { -+ struct deventry *cur; -+ spin_lock(&devlock); -+ cur = devlist; -+ while(cur) { -+ if (dev == cur->dev) { -+ spin_unlock(&devlock); -+ return 1; -+ } -+ cur = cur->next; -+ } -+ spin_unlock(&devlock); -+ return 0; -+} -+ -+void dev_set_rdonly(kdev_t dev) -+{ -+ struct deventry *newdev, *cur; -+ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL); -+ if (!newdev) return; -+ -+ spin_lock(&devlock); -+ cur = devlist; -+ while(cur) { -+ if (dev == cur->dev) { -+ spin_unlock(&devlock); -+ kfree(newdev); -+ return; -+ } -+ cur = cur->next; -+ } -+ newdev->dev = dev; -+ newdev->next = devlist; -+ devlist = newdev; -+ spin_unlock(&devlock); -+ printk(KERN_WARNING "Turning device %s read-only\n", bdevname(dev)); -+} -+ -+void dev_clear_rdonly(kdev_t dev) { -+ struct deventry *cur, *last = NULL; -+ -+ spin_lock(&devlock); -+ cur = devlist; -+ while(cur) { -+ if (dev == cur->dev) { -+ if (last) -+ last->next = cur->next; -+ else -+ devlist = cur->next; -+ spin_unlock(&devlock); -+ kfree(cur); -+ printk(KERN_WARNING "Removing read-only on %s\n", -+ bdevname(dev)); -+ return; -+ } -+ last = cur; -+ cur = cur->next; -+ } -+ spin_unlock(&devlock); -+} -+ -+EXPORT_SYMBOL(dev_set_rdonly); -+EXPORT_SYMBOL(dev_check_rdonly); -+EXPORT_SYMBOL(dev_clear_rdonly); -+ - inline void drive_stat_acct (kdev_t dev, int rw, - unsigned long nr_sectors, int new_io) - { -@@ -1183,6 +1263,10 @@ void generic_make_request (int rw, struc - buffer_IO_error(bh); - break; - } -+ if ((rw & WRITE)&&(dev_check_rdonly(bh->b_rdev))) { -+ bh->b_end_io(bh, 0); -+ break; -+ } - } while (q->make_request_fn(q, rw, bh)); - } - -diff -ur linux-2.4.20-rh.orig/fs/block_dev.c linux-2.4.20-rh/fs/block_dev.c ---- linux-2.4.20-rh.orig/fs/block_dev.c 2002-08-02 17:39:45.000000000 -0700 -+++ linux-2.4.20-rh/fs/block_dev.c 2005-04-08 09:02:15.005789333 -0700 -@@ -645,6 +645,7 @@ int blkdev_put(struct block_device *bdev - bdev->bd_op = NULL; - unlock_kernel(); - up(&bdev->bd_sem); -+ dev_clear_rdonly(to_kdev_t(bdev->bd_dev)); - bdput(bdev); - return ret; - } -diff -ur linux-2.4.20-rh.orig/include/linux/fs.h linux-2.4.20-rh/include/linux/fs.h ---- linux-2.4.20-rh.orig/include/linux/fs.h 2004-05-27 11:25:09.000000000 -0700 -+++ linux-2.4.20-rh/include/linux/fs.h 2005-04-08 09:02:14.915794496 -0700 -@@ -1425,6 +1425,10 @@ extern struct buffer_head * getblk(kdev_ - extern void ll_rw_block(int, int, struct buffer_head * bh[]); - extern void submit_bh(int, struct buffer_head *); - extern int is_read_only(kdev_t); -+#define HAVE_CLEAR_RDONLY_ON_PUT -+void dev_set_rdonly(kdev_t dev); -+int dev_check_rdonly(kdev_t dev); -+void dev_clear_rdonly(kdev_t dev); - extern void __brelse(struct buffer_head *); - static inline void brelse(struct buffer_head *buf) - { - diff --git a/lustre/kernel_patches/patches/dev_read_only_2.4.21-chaos.patch b/lustre/kernel_patches/patches/dev_read_only_2.4.21-chaos.patch deleted file mode 100644 index 3902db5..0000000 --- a/lustre/kernel_patches/patches/dev_read_only_2.4.21-chaos.patch +++ /dev/null @@ -1,122 +0,0 @@ ---- linux-2.4.24.orig/drivers/block/ll_rw_blk.c 2005-04-07 17:30:58.978035892 -0700 -+++ linux-2.4.24/drivers/block/ll_rw_blk.c 2005-04-07 17:22:04.354867801 -0700 -@@ -691,6 +691,85 @@ void set_device_ro(kdev_t dev,int flag) - else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); - } - -+ -+/* -+ * Debug code for turning block devices read-only *silently* (will -+ * discard writes silently). This is only for filesystem crash/recovery -+ * testing. -+ */ -+struct deventry { -+ kdev_t dev; -+ struct deventry *next; -+}; -+ -+static struct deventry *devlist = NULL; -+static spinlock_t devlock = SPIN_LOCK_UNLOCKED; -+ -+int dev_check_rdonly(kdev_t dev) { -+ struct deventry *cur; -+ spin_lock(&devlock); -+ cur = devlist; -+ while(cur) { -+ if (dev == cur->dev) { -+ spin_unlock(&devlock); -+ return 1; -+ } -+ cur = cur->next; -+ } -+ spin_unlock(&devlock); -+ return 0; -+} -+ -+void dev_set_rdonly(kdev_t dev) -+{ -+ struct deventry *newdev, *cur; -+ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL); -+ if (!newdev) return; -+ -+ spin_lock(&devlock); -+ cur = devlist; -+ while(cur) { -+ if (dev == cur->dev) { -+ spin_unlock(&devlock); -+ kfree(newdev); -+ return; -+ } -+ cur = cur->next; -+ } -+ newdev->dev = dev; -+ newdev->next = devlist; -+ devlist = newdev; -+ spin_unlock(&devlock); -+ printk(KERN_WARNING "Turning device %s read-only\n", bdevname(dev)); -+} -+ -+void dev_clear_rdonly(kdev_t dev) { -+ struct deventry *cur, *last = NULL; -+ spin_lock(&devlock); -+ cur = devlist; -+ while(cur) { -+ if (dev == cur->dev) { -+ if (last) -+ last->next = cur->next; -+ else -+ devlist = cur->next; -+ spin_unlock(&devlock); -+ kfree(cur); -+ printk(KERN_WARNING "Removing read-only on %s\n", -+ bdevname(dev)); -+ return; -+ } -+ last = cur; -+ cur = cur->next; -+ } -+ spin_unlock(&devlock); -+} -+ -+EXPORT_SYMBOL(dev_set_rdonly); -+EXPORT_SYMBOL(dev_check_rdonly); -+EXPORT_SYMBOL(dev_clear_rdonly); -+ -+ - inline void drive_stat_acct (kdev_t dev, int rw, - unsigned long nr_sectors, int new_io) - { -@@ -1256,6 +1336,10 @@ void generic_make_request (int rw, struc - break; - } - -+ if ((rw & WRITE)&&(dev_check_rdonly(bh->b_rdev))) { -+ bh->b_end_io(bh, 0); -+ break; -+ } - } while (q->make_request_fn(q, rw, bh)); - } - ---- linux-2.4.24.orig/include/linux/fs.h 2003-11-28 10:26:21.000000000 -0800 -+++ linux-2.4.24/include/linux/fs.h 2005-04-07 17:03:36.810595409 -0700 -@@ -1418,6 +1418,10 @@ extern struct buffer_head * getblk(kdev_ - extern void ll_rw_block(int, int, struct buffer_head * bh[]); - extern void submit_bh(int, struct buffer_head *); - extern int is_read_only(kdev_t); -+#define HAVE_CLEAR_RDONLY_ON_PUT -+void dev_set_rdonly(kdev_t dev); -+int dev_check_rdonly(kdev_t dev); -+void dev_clear_rdonly(kdev_t dev); - extern void __brelse(struct buffer_head *); - static inline void brelse(struct buffer_head *buf) - { ---- linux-2.4.24.orig/fs/block_dev.c 2003-06-13 07:51:37.000000000 -0700 -+++ linux-2.4.24/fs/block_dev.c 2005-04-07 14:01:49.000000000 -0700 -@@ -645,6 +645,7 @@ int blkdev_put(struct block_device *bdev - bdev->bd_op = NULL; - unlock_kernel(); - up(&bdev->bd_sem); -+ dev_clear_rdonly(to_kdev_t(bdev->bd_dev)); - bdput(bdev); - return ret; - } diff --git a/lustre/kernel_patches/patches/export-show_task-2.4-cray.patch b/lustre/kernel_patches/patches/export-show_task-2.4-cray.patch deleted file mode 100644 index 8211401..0000000 --- a/lustre/kernel_patches/patches/export-show_task-2.4-cray.patch +++ /dev/null @@ -1,33 +0,0 @@ -Index: kernel-l0405/kernel/sched.c -=================================================================== ---- kernel-l0405.orig/kernel/sched.c 2003-11-06 16:15:20.000000000 -0800 -+++ kernel-l0405/kernel/sched.c 2005-04-05 14:44:27.000000000 -0700 -@@ -1627,7 +1627,7 @@ - return retval; - } - --static void show_task(task_t * p) -+void show_task(task_t * p) - { - unsigned long free = 0; - int state; -Index: kernel-l0405/kernel/ksyms.c -=================================================================== ---- kernel-l0405.orig/kernel/ksyms.c 2005-04-05 14:44:15.000000000 -0700 -+++ kernel-l0405/kernel/ksyms.c 2005-04-05 14:44:50.000000000 -0700 -@@ -55,6 +55,7 @@ - #include - #include - -+extern void show_task(task_t *); - - #if defined(CONFIG_PROC_FS) - #include -@@ -684,6 +685,7 @@ - - /* debug */ - EXPORT_SYMBOL(dump_stack); -+EXPORT_SYMBOL(show_task); - - #if defined(CONFIG_KDB_USB) - #include diff --git a/lustre/kernel_patches/patches/export-show_task-2.4-rh.patch b/lustre/kernel_patches/patches/export-show_task-2.4-rh.patch deleted file mode 100644 index 3799348..0000000 --- a/lustre/kernel_patches/patches/export-show_task-2.4-rh.patch +++ /dev/null @@ -1,171 +0,0 @@ -Index: linux-2.4.20/kernel/ksyms.c -=================================================================== ---- linux-2.4.20.orig/kernel/ksyms.c 2004-10-21 21:30:14.000000000 -0400 -+++ linux-2.4.20/kernel/ksyms.c 2004-10-21 21:32:00.000000000 -0400 -@@ -75,6 +75,7 @@ - extern spinlock_t dma_spin_lock; - extern int panic_timeout; - -+extern void show_task(task_t *); - - #ifdef CONFIG_MODVERSIONS - const struct module_symbol __export_Using_Versions -@@ -636,3 +637,4 @@ - extern void check_tasklist_locked(void); - EXPORT_SYMBOL_GPL(check_tasklist_locked); - EXPORT_SYMBOL(dump_stack); -+EXPORT_SYMBOL(show_task); -Index: linux-2.4.20/arch/i386/kernel/traps.c -=================================================================== ---- linux-2.4.20.orig/arch/i386/kernel/traps.c 2004-10-21 21:30:15.000000000 -0400 -+++ linux-2.4.20/arch/i386/kernel/traps.c 2004-10-25 14:34:41.000000000 -0400 -@@ -137,29 +137,141 @@ - - #endif - --void show_trace(unsigned long * stack) -+void scan_stack (unsigned long *stack) - { - int i; - unsigned long addr; -- /* static to not take up stackspace; if we race here too bad */ -- static char buffer[512]; -+ /* static to not take up stackspace */ -+ static char buffer[NR_CPUS][512], *bufp; - -- if (!stack) -- stack = (unsigned long*)&stack; -+ bufp = buffer[smp_processor_id()]; - -- printk("Call Trace: "); -+ /* -+ * If we have frame pointers then use them to get -+ * a 100% exact backtrace, up until the entry frame: -+ */ - i = 1; - while (((long) stack & (THREAD_SIZE-1)) != 0) { - addr = *stack++; - if (kernel_text_address(addr)) { -- lookup_symbol(addr, buffer, 512); -- printk("[<%08lx>] %s (0x%x))\n", addr,buffer,stack-1); -+ lookup_symbol(addr, bufp, 512); -+ printk("[<%08lx>] %s (0x%p)\n", addr,bufp,stack-1); - i++; - } - } -+} -+ -+#if CONFIG_FRAME_POINTER -+void show_stack_frame_params (int param_count, unsigned long params[]) -+{ -+ int i; -+ unsigned long *p, task_addr, stack_base; -+ -+ if (param_count <= 0) -+ return; -+ -+ task_addr = (unsigned long) current; -+ stack_base = task_addr + THREAD_SIZE - 1; -+ -+ printk(" ("); -+ -+ for (i = 0, p = params; -+ ((param_count - i) > 1) && (p >= task_addr) && (p <= stack_base); -+ i++, p++) { -+ printk("0x%x, ", *p); -+ -+ if ((i % 4) == 3) -+ printk("\n "); -+ } -+ -+ if ((p >= task_addr) && (p <= stack_base)) -+ printk("0x%x)\n", *p); -+} -+ -+/* Display a stack trace for the currently executing task. The 'dummy' -+ * parameter serves a purpose although its value is unused. We use the -+ * address of 'dummy' as a reference point for finding the saved %ebp register -+ * value on the stack. -+ */ -+void frame_pointer_walk (void *dummy) -+{ -+ int i; -+ unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr, -+ eip, stack_base; -+ /* static to not take up stackspace */ -+ static char buffer[NR_CPUS][512], *bufp; -+ -+ bufp = buffer[smp_processor_id()]; -+ task_addr = (unsigned long) current; -+ stack_base = task_addr + THREAD_SIZE - 1; -+ frame_ptr = (unsigned long *) (&dummy - 2); -+ -+ for (; ; ) { -+ next_frame_ptr = (unsigned long *) (*frame_ptr); -+ addr = (unsigned long) next_frame_ptr; -+ -+ /* Stop when we reach a frame pointer that points to a -+ * location clearly outside our own kernel stack. -+ */ -+ if ((addr < task_addr) || (addr > stack_base)) -+ break; -+ -+ eip_ptr = frame_ptr + 1; -+ eip = *eip_ptr; -+ -+ if (kernel_text_address(eip)) { -+ lookup_symbol(eip, bufp, 512); -+ show_stack_frame_params(4, frame_ptr + 2); -+ printk("[<%08lx>] %s (0x%x)\n", eip, bufp, -+ eip_ptr); -+ } -+ -+ frame_ptr = next_frame_ptr; -+ } -+} -+ -+typedef void (*stack_trace_fn_t) (unsigned long *stack); -+ -+void show_trace(unsigned long * stack) -+{ -+ static const stack_trace_fn_t trace_fn_vector[] = -+ { scan_stack, frame_pointer_walk }; -+ unsigned long addr, task_addr, stack_base; -+ int task_is_current; -+ -+ if (!stack) -+ stack = (unsigned long*)&stack; -+ -+ printk("Call Trace:\n"); -+ addr = (unsigned long) stack; -+ task_addr = (unsigned long) current; -+ stack_base = task_addr + THREAD_SIZE - 1; -+ task_is_current = (addr >= task_addr) && (addr <= stack_base); -+ -+ /* We may use frame pointers to do a stack trace only if the current -+ * task is being traced. Tracing some other task in this manner -+ * would require a saved %ebp register value. Perhaps in the future -+ * I'll consider providing a means of obtaining this. -+ */ -+ trace_fn_vector[task_is_current](stack); -+ - printk("\n"); - } - -+#else /* CONFIG_FRAME_POINTER */ -+ -+void show_trace(unsigned long * stack) -+{ -+ if (!stack) -+ stack = (unsigned long*)&stack; -+ -+ printk("Call Trace:\n"); -+ scan_stack(stack); -+ printk("\n"); -+} -+ -+#endif /* CONFIG_FRAME_POINTER */ -+ - void show_trace_task(struct task_struct *tsk) - { - unsigned long esp = tsk->thread.esp; diff --git a/lustre/kernel_patches/patches/export-show_task-2.4-rhel.patch b/lustre/kernel_patches/patches/export-show_task-2.4-rhel.patch deleted file mode 100644 index a1937d3..0000000 --- a/lustre/kernel_patches/patches/export-show_task-2.4-rhel.patch +++ /dev/null @@ -1,20 +0,0 @@ -Index: linux-2.4.21/kernel/ksyms.c -=================================================================== ---- linux-2.4.21.orig/kernel/ksyms.c 2004-11-01 22:00:03.000000000 -0500 -+++ linux-2.4.21/kernel/ksyms.c 2004-11-01 22:07:07.000000000 -0500 -@@ -86,6 +86,7 @@ - }; - #endif - -+extern void show_task(task_t *); - - EXPORT_SYMBOL(inter_module_register); - EXPORT_SYMBOL(inter_module_unregister); -@@ -670,6 +671,7 @@ - extern void check_tasklist_locked(void); - EXPORT_SYMBOL_GPL(check_tasklist_locked); - EXPORT_SYMBOL(dump_stack); -+EXPORT_SYMBOL(show_task); - - EXPORT_SYMBOL_GPL(netdump_func); - EXPORT_SYMBOL_GPL(netdump_mode); diff --git a/lustre/kernel_patches/patches/export-show_task-2.4-vanilla.patch b/lustre/kernel_patches/patches/export-show_task-2.4-vanilla.patch deleted file mode 100644 index 4e05709..0000000 --- a/lustre/kernel_patches/patches/export-show_task-2.4-vanilla.patch +++ /dev/null @@ -1,34 +0,0 @@ -Index: linux-2.4.24/kernel/ksyms.c -=================================================================== ---- linux-2.4.24.orig/kernel/ksyms.c 2004-10-22 14:00:00.000000000 -0400 -+++ linux-2.4.24/kernel/ksyms.c 2004-10-22 14:03:54.000000000 -0400 -@@ -70,6 +70,8 @@ - extern spinlock_t dma_spin_lock; - extern int panic_timeout; - -+extern void show_task(struct task_struct *); -+ - #ifdef CONFIG_MODVERSIONS - const struct module_symbol __export_Using_Versions - __attribute__((section("__ksymtab"))) = { -@@ -619,6 +621,7 @@ - - /* debug */ - EXPORT_SYMBOL(dump_stack); -+EXPORT_SYMBOL(show_task); - - /* To match ksyms with System.map */ - extern const char _end[]; -Index: linux-2.4.24/kernel/sched.c -=================================================================== ---- linux-2.4.24.orig/kernel/sched.c 2003-11-28 13:26:21.000000000 -0500 -+++ linux-2.4.24/kernel/sched.c 2004-10-22 14:10:10.000000000 -0400 -@@ -1177,7 +1177,7 @@ - return retval; - } - --static void show_task(struct task_struct * p) -+void show_task(struct task_struct * p) - { - unsigned long free = 0; - int state; diff --git a/lustre/kernel_patches/patches/export-truncate.patch b/lustre/kernel_patches/patches/export-truncate.patch deleted file mode 100644 index 2cd96b9..0000000 --- a/lustre/kernel_patches/patches/export-truncate.patch +++ /dev/null @@ -1,35 +0,0 @@ - include/linux/mm.h | 1 + - mm/filemap.c | 3 ++- - 2 files changed, 3 insertions(+), 1 deletion(-) - ---- linux-2.4.18-18/include/linux/mm.h~export-truncate 2003-04-05 02:54:55.000000000 -0700 -+++ linux-2.4.18-18-braam/include/linux/mm.h 2003-04-09 17:37:46.000000000 -0600 -@@ -650,6 +650,7 @@ struct zone_t; - /* filemap.c */ - extern void remove_inode_page(struct page *); - extern unsigned long page_unuse(struct page *); -+extern void truncate_complete_page(struct page *); - extern void truncate_inode_pages(struct address_space *, loff_t); - - /* generic vm_area_ops exported for stackable file systems */ ---- linux-2.4.18-18/mm/filemap.c~export-truncate 2003-04-05 02:54:55.000000000 -0700 -+++ linux-2.4.18-18-braam/mm/filemap.c 2003-04-09 17:37:46.000000000 -0600 -@@ -245,7 +245,7 @@ static inline void truncate_partial_page - do_flushpage(page, partial); - } - --static void truncate_complete_page(struct page *page) -+void truncate_complete_page(struct page *page) - { - /* - * Leave it on the LRU if it gets converted into anonymous buffers -@@ -266,6 +266,7 @@ static void truncate_complete_page(struc - remove_inode_page(page); - page_cache_release(page); - } -+EXPORT_SYMBOL_GPL(truncate_complete_page); - - static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *)); - static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial) - -_ diff --git a/lustre/kernel_patches/patches/export-zap-page-range.patch b/lustre/kernel_patches/patches/export-zap-page-range.patch deleted file mode 100644 index 9b9d48f..0000000 --- a/lustre/kernel_patches/patches/export-zap-page-range.patch +++ /dev/null @@ -1,12 +0,0 @@ -Index: linux-2.4.24-l36mmap/mm/memory.c -=================================================================== ---- linux-2.4.24-l36mmap.orig/mm/memory.c 2004-05-27 17:44:13.000000000 -0700 -+++ linux-2.4.24-l36mmap/mm/memory.c 2004-05-27 17:45:07.000000000 -0700 -@@ -411,6 +411,7 @@ - mm->rss = 0; - spin_unlock(&mm->page_table_lock); - } -+EXPORT_SYMBOL_GPL(zap_page_range); - - /* - * Do a quick page-table lookup for a single page. diff --git a/lustre/kernel_patches/patches/export_num_siblings.patch b/lustre/kernel_patches/patches/export_num_siblings.patch deleted file mode 100644 index 0fdefb5..0000000 --- a/lustre/kernel_patches/patches/export_num_siblings.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- linux/arch/i386/kernel/i386_ksyms.c.orig 2003-11-28 11:26:19.000000000 -0700 -+++ linux/arch/i386/kernel/i386_ksyms.c 2004-08-13 11:31:33.000000000 -0600 -@@ -131,6 +131,7 @@ - EXPORT_SYMBOL(cpu_data); - EXPORT_SYMBOL(kernel_flag_cacheline); - EXPORT_SYMBOL(smp_num_cpus); -+EXPORT_SYMBOL(smp_num_siblings); - EXPORT_SYMBOL(cpu_online_map); - EXPORT_SYMBOL_NOVERS(__write_lock_failed); - EXPORT_SYMBOL_NOVERS(__read_lock_failed); diff --git a/lustre/kernel_patches/patches/exports-2.4.21-chaos.patch b/lustre/kernel_patches/patches/exports-2.4.21-chaos.patch deleted file mode 100644 index 61a3f5c..0000000 --- a/lustre/kernel_patches/patches/exports-2.4.21-chaos.patch +++ /dev/null @@ -1,59 +0,0 @@ - fs/ext3/Makefile | 2 ++ - fs/ext3/super.c | 2 +- - include/linux/fs.h | 1 + - kernel/ksyms.c | 4 ++++ - 4 files changed, 8 insertions(+), 1 deletion(-) - -Index: 57chaos/fs/ext3/Makefile -=================================================================== ---- 57chaos.orig/fs/ext3/Makefile 2004-06-21 13:39:47.000000000 -0700 -+++ 57chaos/fs/ext3/Makefile 2004-06-21 13:59:16.000000000 -0700 -@@ -9,6 +9,8 @@ - - O_TARGET := ext3.o - -+export-objs := super.o inode.o -+ - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) -Index: 57chaos/fs/ext3/super.c -=================================================================== ---- 57chaos.orig/fs/ext3/super.c 2004-06-21 13:39:47.000000000 -0700 -+++ 57chaos/fs/ext3/super.c 2004-06-21 13:59:16.000000000 -0700 -@@ -1938,7 +1938,7 @@ static void __exit exit_ext3_fs(void) - unregister_filesystem(&ext3_fs_type); - } - --EXPORT_NO_SYMBOLS; -+EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); -Index: 57chaos/include/linux/fs.h -=================================================================== ---- 57chaos.orig/include/linux/fs.h 2004-06-21 13:39:47.000000000 -0700 -+++ 57chaos/include/linux/fs.h 2004-06-21 13:59:57.000000000 -0700 -@@ -1073,6 +1073,7 @@ extern int unregister_filesystem(struct - extern struct vfsmount *kern_mount(struct file_system_type *); - extern int may_umount(struct vfsmount *); - extern long do_mount(char *, char *, char *, unsigned long, void *); -+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); - - #define kern_umount mntput - -Index: 57chaos/kernel/ksyms.c -=================================================================== ---- 57chaos.orig/kernel/ksyms.c 2004-06-21 13:39:47.000000000 -0700 -+++ 57chaos/kernel/ksyms.c 2004-06-21 13:59:16.000000000 -0700 -@@ -336,6 +336,10 @@ EXPORT_SYMBOL(dcache_dir_fsync); - EXPORT_SYMBOL(dcache_readdir); - EXPORT_SYMBOL(dcache_dir_ops); - -+/* lustre */ -+EXPORT_SYMBOL(pagecache_lock_cacheline); -+EXPORT_SYMBOL(do_kern_mount); -+ - /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ - EXPORT_SYMBOL(default_llseek); - EXPORT_SYMBOL(dentry_open); diff --git a/lustre/kernel_patches/patches/exports_2.4.19-suse.patch b/lustre/kernel_patches/patches/exports_2.4.19-suse.patch deleted file mode 100644 index feaeec6..0000000 --- a/lustre/kernel_patches/patches/exports_2.4.19-suse.patch +++ /dev/null @@ -1,53 +0,0 @@ - fs/ext3/Makefile | 2 ++ - fs/ext3/super.c | 2 +- - include/linux/fs.h | 1 + - kernel/ksyms.c | 4 ++++ - 4 files changed, 8 insertions(+), 1 deletion(-) - ---- linux/fs/ext3/Makefile~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/fs/ext3/Makefile Wed Apr 9 10:19:53 2003 -@@ -9,6 +9,8 @@ - - O_TARGET := ext3.o - -+export-objs := super.o inode.o -+ - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) ---- linux/fs/ext3/super.c~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/fs/ext3/super.c Wed Apr 9 10:19:53 2003 -@@ -1769,7 +1769,7 @@ static void __exit exit_ext3_fs(void) - unregister_filesystem(&ext3_fs_type); - } - --EXPORT_NO_SYMBOLS; -+EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); ---- linux/include/linux/fs.h~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/include/linux/fs.h Wed Apr 9 10:19:53 2003 -@@ -1020,6 +1020,7 @@ extern int unregister_filesystem(struct - extern struct vfsmount *kern_mount(struct file_system_type *); - extern int may_umount(struct vfsmount *); - extern long do_mount(char *, char *, char *, unsigned long, void *); -+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); - - #define kern_umount mntput - ---- linux/kernel/ksyms.c~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/kernel/ksyms.c Wed Apr 9 10:19:53 2003 -@@ -308,6 +308,10 @@ EXPORT_SYMBOL(dcache_dir_fsync); - EXPORT_SYMBOL(dcache_readdir); - EXPORT_SYMBOL(dcache_dir_ops); - -+/* lustre */ -+EXPORT_SYMBOL(pagecache_lock_cacheline); -+EXPORT_SYMBOL(do_kern_mount); -+ - /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ - EXPORT_SYMBOL(default_llseek); - EXPORT_SYMBOL(dentry_open); - -_ diff --git a/lustre/kernel_patches/patches/exports_2.4.19-suse2.patch b/lustre/kernel_patches/patches/exports_2.4.19-suse2.patch deleted file mode 100644 index 41744b9..0000000 --- a/lustre/kernel_patches/patches/exports_2.4.19-suse2.patch +++ /dev/null @@ -1,59 +0,0 @@ - fs/ext3/Makefile | 2 ++ - fs/ext3/super.c | 2 +- - include/linux/fs.h | 1 + - kernel/ksyms.c | 4 ++++ - 4 files changed, 8 insertions(+), 1 deletion(-) - -Index: linux-2.4.19.SuSE/fs/ext3/Makefile -=================================================================== ---- linux-2.4.19.SuSE.orig/fs/ext3/Makefile 2004-04-29 16:18:08.000000000 -0700 -+++ linux-2.4.19.SuSE/fs/ext3/Makefile 2004-04-29 16:36:09.000000000 -0700 -@@ -9,6 +9,8 @@ - - O_TARGET := ext3.o - -+export-objs := super.o inode.o -+ - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) -Index: linux-2.4.19.SuSE/fs/ext3/super.c -=================================================================== ---- linux-2.4.19.SuSE.orig/fs/ext3/super.c 2004-04-29 16:18:08.000000000 -0700 -+++ linux-2.4.19.SuSE/fs/ext3/super.c 2004-04-29 16:36:09.000000000 -0700 -@@ -1821,7 +1821,7 @@ - exit_ext3_xattr(); - } - --EXPORT_NO_SYMBOLS; -+EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); -Index: linux-2.4.19.SuSE/include/linux/fs.h -=================================================================== ---- linux-2.4.19.SuSE.orig/include/linux/fs.h 2004-04-29 16:19:41.000000000 -0700 -+++ linux-2.4.19.SuSE/include/linux/fs.h 2004-04-29 16:36:52.000000000 -0700 -@@ -1174,6 +1174,7 @@ - extern struct vfsmount *kern_mount(struct file_system_type *); - extern int may_umount(struct vfsmount *); - extern long do_mount(char *, char *, char *, unsigned long, void *); -+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); - extern void umount_tree(struct vfsmount *); - - #define kern_umount mntput -Index: linux-2.4.19.SuSE/kernel/ksyms.c -=================================================================== ---- linux-2.4.19.SuSE.orig/kernel/ksyms.c 2004-04-29 16:19:35.000000000 -0700 -+++ linux-2.4.19.SuSE/kernel/ksyms.c 2004-04-29 16:36:09.000000000 -0700 -@@ -330,6 +330,10 @@ - EXPORT_SYMBOL(dcache_readdir); - EXPORT_SYMBOL(dcache_dir_ops); - -+/* lustre */ -+EXPORT_SYMBOL(pagecache_lock_cacheline); -+EXPORT_SYMBOL(do_kern_mount); -+ - /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ - EXPORT_SYMBOL(default_llseek); - EXPORT_SYMBOL(dentry_open); diff --git a/lustre/kernel_patches/patches/exports_2.4.20-rh-hp.patch b/lustre/kernel_patches/patches/exports_2.4.20-rh-hp.patch deleted file mode 100644 index feaeec6..0000000 --- a/lustre/kernel_patches/patches/exports_2.4.20-rh-hp.patch +++ /dev/null @@ -1,53 +0,0 @@ - fs/ext3/Makefile | 2 ++ - fs/ext3/super.c | 2 +- - include/linux/fs.h | 1 + - kernel/ksyms.c | 4 ++++ - 4 files changed, 8 insertions(+), 1 deletion(-) - ---- linux/fs/ext3/Makefile~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/fs/ext3/Makefile Wed Apr 9 10:19:53 2003 -@@ -9,6 +9,8 @@ - - O_TARGET := ext3.o - -+export-objs := super.o inode.o -+ - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) ---- linux/fs/ext3/super.c~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/fs/ext3/super.c Wed Apr 9 10:19:53 2003 -@@ -1769,7 +1769,7 @@ static void __exit exit_ext3_fs(void) - unregister_filesystem(&ext3_fs_type); - } - --EXPORT_NO_SYMBOLS; -+EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); ---- linux/include/linux/fs.h~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/include/linux/fs.h Wed Apr 9 10:19:53 2003 -@@ -1020,6 +1020,7 @@ extern int unregister_filesystem(struct - extern struct vfsmount *kern_mount(struct file_system_type *); - extern int may_umount(struct vfsmount *); - extern long do_mount(char *, char *, char *, unsigned long, void *); -+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); - - #define kern_umount mntput - ---- linux/kernel/ksyms.c~exports_2.4.20 Wed Apr 9 10:07:14 2003 -+++ linux-mmonroe/kernel/ksyms.c Wed Apr 9 10:19:53 2003 -@@ -308,6 +308,10 @@ EXPORT_SYMBOL(dcache_dir_fsync); - EXPORT_SYMBOL(dcache_readdir); - EXPORT_SYMBOL(dcache_dir_ops); - -+/* lustre */ -+EXPORT_SYMBOL(pagecache_lock_cacheline); -+EXPORT_SYMBOL(do_kern_mount); -+ - /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ - EXPORT_SYMBOL(default_llseek); - EXPORT_SYMBOL(dentry_open); - -_ diff --git a/lustre/kernel_patches/patches/ext-2.4-patch-1.patch b/lustre/kernel_patches/patches/ext-2.4-patch-1.patch deleted file mode 100644 index c5e1ee0..0000000 --- a/lustre/kernel_patches/patches/ext-2.4-patch-1.patch +++ /dev/null @@ -1,2536 +0,0 @@ - fs/ext3/Makefile | 2 - fs/ext3/dir.c | 299 +++++++++ - fs/ext3/file.c | 3 - fs/ext3/hash.c | 215 ++++++ - fs/ext3/namei.c | 1387 ++++++++++++++++++++++++++++++++++++++++----- - fs/ext3/super.c | 7 - include/linux/ext3_fs.h | 85 ++ - include/linux/ext3_fs_sb.h | 2 - include/linux/ext3_jbd.h | 2 - include/linux/rbtree.h | 2 - lib/rbtree.c | 42 + - 11 files changed, 1886 insertions(+), 160 deletions(-) - ---- linux-2.4.20/fs/ext3/Makefile~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/fs/ext3/Makefile Sat Apr 5 03:57:05 2003 -@@ -12,7 +12,7 @@ O_TARGET := ext3.o - export-objs := super.o inode.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o -+ ioctl.o namei.o super.o symlink.o hash.o - obj-m := $(O_TARGET) - - include $(TOPDIR)/Rules.make ---- linux-2.4.20/fs/ext3/dir.c~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/fs/ext3/dir.c Sat Apr 5 03:56:31 2003 -@@ -21,12 +21,16 @@ - #include - #include - #include -+#include -+#include - - static unsigned char ext3_filetype_table[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK - }; - - static int ext3_readdir(struct file *, void *, filldir_t); -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir); - - struct file_operations ext3_dir_operations = { - read: generic_read_dir, -@@ -35,6 +39,17 @@ struct file_operations ext3_dir_operatio - fsync: ext3_sync_file, /* BKL held */ - }; - -+ -+static unsigned char get_dtype(struct super_block *sb, int filetype) -+{ -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) || -+ (filetype >= EXT3_FT_MAX)) -+ return DT_UNKNOWN; -+ -+ return (ext3_filetype_table[filetype]); -+} -+ -+ - int ext3_check_dir_entry (const char * function, struct inode * dir, - struct ext3_dir_entry_2 * de, - struct buffer_head * bh, -@@ -79,6 +94,16 @@ static int ext3_readdir(struct file * fi - - sb = inode->i_sb; - -+ if (is_dx(inode)) { -+ err = ext3_dx_readdir(filp, dirent, filldir); -+ if (err != ERR_BAD_DX_DIR) -+ return err; -+ /* -+ * We don't set the inode dirty flag since it's not -+ * critical that it get flushed back to the disk. -+ */ -+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; -+ } - stored = 0; - bh = NULL; - offset = filp->f_pos & (sb->s_blocksize - 1); -@@ -162,18 +187,12 @@ revalidate: - * during the copy operation. - */ - unsigned long version = filp->f_version; -- unsigned char d_type = DT_UNKNOWN; - -- if (EXT3_HAS_INCOMPAT_FEATURE(sb, -- EXT3_FEATURE_INCOMPAT_FILETYPE) -- && de->file_type < EXT3_FT_MAX) -- d_type = -- ext3_filetype_table[de->file_type]; - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, - le32_to_cpu(de->inode), -- d_type); -+ get_dtype(sb, de->file_type)); - if (error) - break; - if (version != filp->f_version) -@@ -188,3 +207,269 @@ revalidate: - UPDATE_ATIME(inode); - return 0; - } -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * These functions convert from the major/minor hash to an f_pos -+ * value. -+ * -+ * Currently we only use major hash numer. This is unfortunate, but -+ * on 32-bit machines, the same VFS interface is used for lseek and -+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of -+ * lseek/telldir/seekdir will blow out spectacularly, and from within -+ * the ext2 low-level routine, we don't know if we're being called by -+ * a 64-bit version of the system call or the 32-bit version of the -+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir -+ * cookie. Sigh. -+ */ -+#define hash2pos(major, minor) (major >> 1) -+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) -+#define pos2min_hash(pos) (0) -+ -+/* -+ * This structure holds the nodes of the red-black tree used to store -+ * the directory entry in hash order. -+ */ -+struct fname { -+ __u32 hash; -+ __u32 minor_hash; -+ rb_node_t rb_hash; -+ struct fname *next; -+ __u32 inode; -+ __u8 name_len; -+ __u8 file_type; -+ char name[0]; -+}; -+ -+/* -+ * This functoin implements a non-recursive way of freeing all of the -+ * nodes in the red-black tree. -+ */ -+static void free_rb_tree_fname(rb_root_t *root) -+{ -+ rb_node_t *n = root->rb_node; -+ rb_node_t *parent; -+ struct fname *fname; -+ -+ while (n) { -+ /* Do the node's children first */ -+ if ((n)->rb_left) { -+ n = n->rb_left; -+ continue; -+ } -+ if (n->rb_right) { -+ n = n->rb_right; -+ continue; -+ } -+ /* -+ * The node has no children; free it, and then zero -+ * out parent's link to it. Finally go to the -+ * beginning of the loop and try to free the parent -+ * node. -+ */ -+ parent = n->rb_parent; -+ fname = rb_entry(n, struct fname, rb_hash); -+ kfree(fname); -+ if (!parent) -+ root->rb_node = 0; -+ else if (parent->rb_left == n) -+ parent->rb_left = 0; -+ else if (parent->rb_right == n) -+ parent->rb_right = 0; -+ n = parent; -+ } -+ root->rb_node = 0; -+} -+ -+ -+struct dir_private_info *create_dir_info(loff_t pos) -+{ -+ struct dir_private_info *p; -+ -+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL); -+ if (!p) -+ return NULL; -+ p->root.rb_node = 0; -+ p->curr_node = 0; -+ p->extra_fname = 0; -+ p->last_pos = 0; -+ p->curr_hash = pos2maj_hash(pos); -+ p->curr_minor_hash = pos2min_hash(pos); -+ p->next_hash = 0; -+ return p; -+} -+ -+void ext3_htree_free_dir_info(struct dir_private_info *p) -+{ -+ free_rb_tree_fname(&p->root); -+ kfree(p); -+} -+ -+/* -+ * Given a directory entry, enter it into the fname rb tree. -+ */ -+void ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent) -+{ -+ rb_node_t **p, *parent = NULL; -+ struct fname * fname, *new_fn; -+ struct dir_private_info *info; -+ int len; -+ -+ info = (struct dir_private_info *) dir_file->private_data; -+ p = &info->root.rb_node; -+ -+ /* Create and allocate the fname structure */ -+ len = sizeof(struct fname) + dirent->name_len + 1; -+ new_fn = kmalloc(len, GFP_KERNEL); -+ memset(new_fn, 0, len); -+ new_fn->hash = hash; -+ new_fn->minor_hash = minor_hash; -+ new_fn->inode = le32_to_cpu(dirent->inode); -+ new_fn->name_len = dirent->name_len; -+ new_fn->file_type = dirent->file_type; -+ memcpy(new_fn->name, dirent->name, dirent->name_len); -+ new_fn->name[dirent->name_len] = 0; -+ -+ while (*p) { -+ parent = *p; -+ fname = rb_entry(parent, struct fname, rb_hash); -+ -+ /* -+ * If the hash and minor hash match up, then we put -+ * them on a linked list. This rarely happens... -+ */ -+ if ((new_fn->hash == fname->hash) && -+ (new_fn->minor_hash == fname->minor_hash)) { -+ new_fn->next = fname->next; -+ fname->next = new_fn; -+ return; -+ } -+ -+ if (new_fn->hash < fname->hash) -+ p = &(*p)->rb_left; -+ else if (new_fn->hash > fname->hash) -+ p = &(*p)->rb_right; -+ else if (new_fn->minor_hash < fname->minor_hash) -+ p = &(*p)->rb_left; -+ else /* if (new_fn->minor_hash > fname->minor_hash) */ -+ p = &(*p)->rb_right; -+ } -+ -+ rb_link_node(&new_fn->rb_hash, parent, p); -+ rb_insert_color(&new_fn->rb_hash, &info->root); -+} -+ -+ -+ -+/* -+ * This is a helper function for ext3_dx_readdir. It calls filldir -+ * for all entres on the fname linked list. (Normally there is only -+ * one entry on the linked list, unless there are 62 bit hash collisions.) -+ */ -+static int call_filldir(struct file * filp, void * dirent, -+ filldir_t filldir, struct fname *fname) -+{ -+ struct dir_private_info *info = filp->private_data; -+ loff_t curr_pos; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct super_block * sb; -+ int error; -+ -+ sb = inode->i_sb; -+ -+ if (!fname) { -+ printk("call_filldir: called with null fname?!?\n"); -+ return 0; -+ } -+ curr_pos = hash2pos(fname->hash, fname->minor_hash); -+ while (fname) { -+ error = filldir(dirent, fname->name, -+ fname->name_len, curr_pos, -+ fname->inode, -+ get_dtype(sb, fname->file_type)); -+ if (error) { -+ filp->f_pos = curr_pos; -+ info->extra_fname = fname->next; -+ return error; -+ } -+ fname = fname->next; -+ } -+ return 0; -+} -+ -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir) -+{ -+ struct dir_private_info *info = filp->private_data; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct fname *fname; -+ int ret; -+ -+ if (!info) { -+ info = create_dir_info(filp->f_pos); -+ if (!info) -+ return -ENOMEM; -+ filp->private_data = info; -+ } -+ -+ /* Some one has messed with f_pos; reset the world */ -+ if (info->last_pos != filp->f_pos) { -+ free_rb_tree_fname(&info->root); -+ info->curr_node = 0; -+ info->extra_fname = 0; -+ info->curr_hash = pos2maj_hash(filp->f_pos); -+ info->curr_minor_hash = pos2min_hash(filp->f_pos); -+ } -+ -+ /* -+ * If there are any leftover names on the hash collision -+ * chain, return them first. -+ */ -+ if (info->extra_fname && -+ call_filldir(filp, dirent, filldir, info->extra_fname)) -+ goto finished; -+ -+ if (!info->curr_node) -+ info->curr_node = rb_get_first(&info->root); -+ -+ while (1) { -+ /* -+ * Fill the rbtree if we have no more entries, -+ * or the inode has changed since we last read in the -+ * cached entries. -+ */ -+ if ((!info->curr_node) || -+ (filp->f_version != inode->i_version)) { -+ info->curr_node = 0; -+ free_rb_tree_fname(&info->root); -+ filp->f_version = inode->i_version; -+ ret = ext3_htree_fill_tree(filp, info->curr_hash, -+ info->curr_minor_hash, -+ &info->next_hash); -+ if (ret < 0) -+ return ret; -+ if (ret == 0) -+ break; -+ info->curr_node = rb_get_first(&info->root); -+ } -+ -+ fname = rb_entry(info->curr_node, struct fname, rb_hash); -+ info->curr_hash = fname->hash; -+ info->curr_minor_hash = fname->minor_hash; -+ if (call_filldir(filp, dirent, filldir, fname)) -+ break; -+ -+ info->curr_node = rb_get_next(info->curr_node); -+ if (!info->curr_node) { -+ info->curr_hash = info->next_hash; -+ info->curr_minor_hash = 0; -+ } -+ } -+finished: -+ info->last_pos = filp->f_pos; -+ UPDATE_ATIME(inode); -+ return 0; -+} -+#endif ---- linux-2.4.20/fs/ext3/file.c~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/fs/ext3/file.c Sat Apr 5 03:56:31 2003 -@@ -35,6 +35,9 @@ static int ext3_release_file (struct ino - { - if (filp->f_mode & FMODE_WRITE) - ext3_discard_prealloc (inode); -+ if (is_dx(inode) && filp->private_data) -+ ext3_htree_free_dir_info(filp->private_data); -+ - return 0; - } - ---- /dev/null Fri Aug 30 17:31:37 2002 -+++ linux-2.4.20-braam/fs/ext3/hash.c Sat Apr 5 03:56:31 2003 -@@ -0,0 +1,215 @@ -+/* -+ * linux/fs/ext3/hash.c -+ * -+ * Copyright (C) 2002 by Theodore Ts'o -+ * -+ * This file is released under the GPL v2. -+ * -+ * This file may be redistributed under the terms of the GNU Public -+ * License. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define DELTA 0x9E3779B9 -+ -+static void TEA_transform(__u32 buf[4], __u32 const in[]) -+{ -+ __u32 sum = 0; -+ __u32 b0 = buf[0], b1 = buf[1]; -+ __u32 a = in[0], b = in[1], c = in[2], d = in[3]; -+ int n = 16; -+ -+ do { -+ sum += DELTA; -+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); -+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); -+ } while(--n); -+ -+ buf[0] += b0; -+ buf[1] += b1; -+} -+ -+/* F, G and H are basic MD4 functions: selection, majority, parity */ -+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+ -+/* -+ * The generic round function. The application is so specific that -+ * we don't bother protecting all the arguments with parens, as is generally -+ * good macro practice, in favor of extra legibility. -+ * Rotation is separate from addition to prevent recomputation -+ */ -+#define ROUND(f, a, b, c, d, x, s) \ -+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) -+#define K1 0 -+#define K2 013240474631UL -+#define K3 015666365641UL -+ -+/* -+ * Basic cut-down MD4 transform. Returns only 32 bits of result. -+ */ -+static void halfMD4Transform (__u32 buf[4], __u32 const in[]) -+{ -+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; -+ -+ /* Round 1 */ -+ ROUND(F, a, b, c, d, in[0] + K1, 3); -+ ROUND(F, d, a, b, c, in[1] + K1, 7); -+ ROUND(F, c, d, a, b, in[2] + K1, 11); -+ ROUND(F, b, c, d, a, in[3] + K1, 19); -+ ROUND(F, a, b, c, d, in[4] + K1, 3); -+ ROUND(F, d, a, b, c, in[5] + K1, 7); -+ ROUND(F, c, d, a, b, in[6] + K1, 11); -+ ROUND(F, b, c, d, a, in[7] + K1, 19); -+ -+ /* Round 2 */ -+ ROUND(G, a, b, c, d, in[1] + K2, 3); -+ ROUND(G, d, a, b, c, in[3] + K2, 5); -+ ROUND(G, c, d, a, b, in[5] + K2, 9); -+ ROUND(G, b, c, d, a, in[7] + K2, 13); -+ ROUND(G, a, b, c, d, in[0] + K2, 3); -+ ROUND(G, d, a, b, c, in[2] + K2, 5); -+ ROUND(G, c, d, a, b, in[4] + K2, 9); -+ ROUND(G, b, c, d, a, in[6] + K2, 13); -+ -+ /* Round 3 */ -+ ROUND(H, a, b, c, d, in[3] + K3, 3); -+ ROUND(H, d, a, b, c, in[7] + K3, 9); -+ ROUND(H, c, d, a, b, in[2] + K3, 11); -+ ROUND(H, b, c, d, a, in[6] + K3, 15); -+ ROUND(H, a, b, c, d, in[1] + K3, 3); -+ ROUND(H, d, a, b, c, in[5] + K3, 9); -+ ROUND(H, c, d, a, b, in[0] + K3, 11); -+ ROUND(H, b, c, d, a, in[4] + K3, 15); -+ -+ buf[0] += a; -+ buf[1] += b; -+ buf[2] += c; -+ buf[3] += d; -+} -+ -+#undef ROUND -+#undef F -+#undef G -+#undef H -+#undef K1 -+#undef K2 -+#undef K3 -+ -+/* The old legacy hash */ -+static __u32 dx_hack_hash (const char *name, int len) -+{ -+ __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; -+ while (len--) { -+ __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); -+ -+ if (hash & 0x80000000) hash -= 0x7fffffff; -+ hash1 = hash0; -+ hash0 = hash; -+ } -+ return (hash0 << 1); -+} -+ -+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) -+{ -+ __u32 pad, val; -+ int i; -+ -+ pad = (__u32)len | ((__u32)len << 8); -+ pad |= pad << 16; -+ -+ val = pad; -+ if (len > num*4) -+ len = num * 4; -+ for (i=0; i < len; i++) { -+ if ((i % 4) == 0) -+ val = pad; -+ val = msg[i] + (val << 8); -+ if ((i % 4) == 3) { -+ *buf++ = val; -+ val = pad; -+ num--; -+ } -+ } -+ if (--num >= 0) -+ *buf++ = val; -+ while (--num >= 0) -+ *buf++ = pad; -+} -+ -+/* -+ * Returns the hash of a filename. If len is 0 and name is NULL, then -+ * this function can be used to test whether or not a hash version is -+ * supported. -+ * -+ * The seed is an 4 longword (32 bits) "secret" which can be used to -+ * uniquify a hash. If the seed is all zero's, then some default seed -+ * may be used. -+ * -+ * A particular hash version specifies whether or not the seed is -+ * represented, and whether or not the returned hash is 32 bits or 64 -+ * bits. 32 bit hashes will return 0 for the minor hash. -+ */ -+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) -+{ -+ __u32 hash; -+ __u32 minor_hash = 0; -+ const char *p; -+ int i; -+ __u32 in[8], buf[4]; -+ -+ /* Initialize the default seed for the hash checksum functions */ -+ buf[0] = 0x67452301; -+ buf[1] = 0xefcdab89; -+ buf[2] = 0x98badcfe; -+ buf[3] = 0x10325476; -+ -+ /* Check to see if the seed is all zero's */ -+ if (hinfo->seed) { -+ for (i=0; i < 4; i++) { -+ if (hinfo->seed[i]) -+ break; -+ } -+ if (i < 4) -+ memcpy(buf, hinfo->seed, sizeof(buf)); -+ } -+ -+ switch (hinfo->hash_version) { -+ case DX_HASH_LEGACY: -+ hash = dx_hack_hash(name, len); -+ break; -+ case DX_HASH_HALF_MD4: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 8); -+ halfMD4Transform(buf, in); -+ len -= 32; -+ p += 32; -+ } -+ minor_hash = buf[2]; -+ hash = buf[1]; -+ break; -+ case DX_HASH_TEA: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 4); -+ TEA_transform(buf, in); -+ len -= 16; -+ p += 16; -+ } -+ hash = buf[0]; -+ minor_hash = buf[1]; -+ break; -+ default: -+ hinfo->hash = 0; -+ return -1; -+ } -+ hinfo->hash = hash & ~1; -+ hinfo->minor_hash = minor_hash; -+ return 0; -+} ---- linux-2.4.20/fs/ext3/namei.c~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/fs/ext3/namei.c Sat Apr 5 03:56:31 2003 -@@ -16,6 +16,12 @@ - * David S. Miller (davem@caip.rutgers.edu), 1995 - * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 -+ * Hash Tree Directory indexing (c) -+ * Daniel Phillips, 2001 -+ * Hash Tree Directory indexing porting -+ * Christopher Li, 2002 -+ * Hash Tree Directory indexing cleanup -+ * Theodore Ts'o, 2002 - */ - - #include -@@ -38,6 +44,630 @@ - #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) - #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) - -+static struct buffer_head *ext3_append(handle_t *handle, -+ struct inode *inode, -+ u32 *block, int *err) -+{ -+ struct buffer_head *bh; -+ -+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits; -+ -+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) { -+ inode->i_size += inode->i_sb->s_blocksize; -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_journal_get_write_access(handle,bh); -+ } -+ return bh; -+} -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#ifndef swap -+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) -+#endif -+ -+typedef struct { u32 v; } le_u32; -+typedef struct { u16 v; } le_u16; -+ -+#ifdef DX_DEBUG -+#define dxtrace(command) command -+#else -+#define dxtrace(command) -+#endif -+ -+struct fake_dirent -+{ -+ /*le*/u32 inode; -+ /*le*/u16 rec_len; -+ u8 name_len; -+ u8 file_type; -+}; -+ -+struct dx_countlimit -+{ -+ le_u16 limit; -+ le_u16 count; -+}; -+ -+struct dx_entry -+{ -+ le_u32 hash; -+ le_u32 block; -+}; -+ -+/* -+ * dx_root_info is laid out so that if it should somehow get overlaid by a -+ * dirent the two low bits of the hash version will be zero. Therefore, the -+ * hash version mod 4 should never be 0. Sincerely, the paranoia department. -+ */ -+ -+struct dx_root -+{ -+ struct fake_dirent dot; -+ char dot_name[4]; -+ struct fake_dirent dotdot; -+ char dotdot_name[4]; -+ struct dx_root_info -+ { -+ le_u32 reserved_zero; -+ u8 hash_version; -+ u8 info_length; /* 8 */ -+ u8 indirect_levels; -+ u8 unused_flags; -+ } -+ info; -+ struct dx_entry entries[0]; -+}; -+ -+struct dx_node -+{ -+ struct fake_dirent fake; -+ struct dx_entry entries[0]; -+}; -+ -+ -+struct dx_frame -+{ -+ struct buffer_head *bh; -+ struct dx_entry *entries; -+ struct dx_entry *at; -+}; -+ -+struct dx_map_entry -+{ -+ u32 hash; -+ u32 offs; -+}; -+ -+#ifdef CONFIG_EXT3_INDEX -+static inline unsigned dx_get_block (struct dx_entry *entry); -+static void dx_set_block (struct dx_entry *entry, unsigned value); -+static inline unsigned dx_get_hash (struct dx_entry *entry); -+static void dx_set_hash (struct dx_entry *entry, unsigned value); -+static unsigned dx_get_count (struct dx_entry *entries); -+static unsigned dx_get_limit (struct dx_entry *entries); -+static void dx_set_count (struct dx_entry *entries, unsigned value); -+static void dx_set_limit (struct dx_entry *entries, unsigned value); -+static unsigned dx_root_limit (struct inode *dir, unsigned infosize); -+static unsigned dx_node_limit (struct inode *dir); -+static struct dx_frame *dx_probe(struct dentry *dentry, -+ struct inode *dir, -+ struct dx_hash_info *hinfo, -+ struct dx_frame *frame, -+ int *err); -+static void dx_release (struct dx_frame *frames); -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry map[]); -+static void dx_sort_map(struct dx_map_entry *map, unsigned count); -+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, -+ struct dx_map_entry *offsets, int count); -+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); -+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash); -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err); -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Future: use high four bits of block for coalesce-on-delete flags -+ * Mask them off for now. -+ */ -+ -+static inline unsigned dx_get_block (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->block.v) & 0x00ffffff; -+} -+ -+static inline void dx_set_block (struct dx_entry *entry, unsigned value) -+{ -+ entry->block.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_hash (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->hash.v); -+} -+ -+static inline void dx_set_hash (struct dx_entry *entry, unsigned value) -+{ -+ entry->hash.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_count (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v); -+} -+ -+static inline unsigned dx_get_limit (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v); -+} -+ -+static inline void dx_set_count (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value); -+} -+ -+static inline void dx_set_limit (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value); -+} -+ -+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - -+ EXT3_DIR_REC_LEN(2) - infosize; -+ return 0? 20: entry_space / sizeof(struct dx_entry); -+} -+ -+static inline unsigned dx_node_limit (struct inode *dir) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); -+ return 0? 22: entry_space / sizeof(struct dx_entry); -+} -+ -+/* -+ * Debug -+ */ -+#ifdef DX_DEBUG -+struct stats -+{ -+ unsigned names; -+ unsigned space; -+ unsigned bcount; -+}; -+ -+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de, -+ int size, int show_names) -+{ -+ unsigned names = 0, space = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ printk("names: "); -+ while ((char *) de < base + size) -+ { -+ if (de->inode) -+ { -+ if (show_names) -+ { -+ int len = de->name_len; -+ char *name = de->name; -+ while (len--) printk("%c", *name++); -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ printk(":%x.%u ", h.hash, -+ ((char *) de - base)); -+ } -+ space += EXT3_DIR_REC_LEN(de->name_len); -+ names++; -+ } -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ printk("(%i)\n", names); -+ return (struct stats) { names, space, 1 }; -+} -+ -+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, -+ struct dx_entry *entries, int levels) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count = dx_get_count (entries), names = 0, space = 0, i; -+ unsigned bcount = 0; -+ struct buffer_head *bh; -+ int err; -+ printk("%i indexed blocks...\n", count); -+ for (i = 0; i < count; i++, entries++) -+ { -+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0; -+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; -+ struct stats stats; -+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); -+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue; -+ stats = levels? -+ dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): -+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) bh->b_data, blocksize, 0); -+ names += stats.names; -+ space += stats.space; -+ bcount += stats.bcount; -+ brelse (bh); -+ } -+ if (bcount) -+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ", -+ names, space/bcount,(space/bcount)*100/blocksize); -+ return (struct stats) { names, space, bcount}; -+} -+#endif /* DX_DEBUG */ -+ -+/* -+ * Probe for a directory leaf block to search. -+ * -+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format -+ * error in the directory index, and the caller should fall back to -+ * searching the directory normally. The callers of dx_probe **MUST** -+ * check for this error code, and make sure it never gets reflected -+ * back to userspace. -+ */ -+static struct dx_frame * -+dx_probe(struct dentry *dentry, struct inode *dir, -+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) -+{ -+ unsigned count, indirect; -+ struct dx_entry *at, *entries, *p, *q, *m; -+ struct dx_root *root; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+ -+ frame->bh = NULL; -+ if (dentry) -+ dir = dentry->d_parent->d_inode; -+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) -+ goto fail; -+ root = (struct dx_root *) bh->b_data; -+ if (root->info.hash_version != DX_HASH_TEA && -+ root->info.hash_version != DX_HASH_HALF_MD4 && -+ root->info.hash_version != DX_HASH_LEGACY) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unrecognised inode hash code %d", -+ root->info.hash_version); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ hinfo->hash_version = root->info.hash_version; -+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ if (dentry) -+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); -+ hash = hinfo->hash; -+ -+ if (root->info.unused_flags & 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash flags: %#06x", -+ root->info.unused_flags); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ if ((indirect = root->info.indirect_levels) > 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash depth: %#06x", -+ root->info.indirect_levels); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ entries = (struct dx_entry *) (((char *)&root->info) + -+ root->info.info_length); -+ assert(dx_get_limit(entries) == dx_root_limit(dir, -+ root->info.info_length)); -+ dxtrace (printk("Look up %x", hash)); -+ while (1) -+ { -+ count = dx_get_count(entries); -+ assert (count && count <= dx_get_limit(entries)); -+ p = entries + 1; -+ q = entries + count - 1; -+ while (p <= q) -+ { -+ m = p + (q - p)/2; -+ dxtrace(printk(".")); -+ if (dx_get_hash(m) > hash) -+ q = m - 1; -+ else -+ p = m + 1; -+ } -+ -+ if (0) // linear search cross check -+ { -+ unsigned n = count - 1; -+ at = entries; -+ while (n--) -+ { -+ dxtrace(printk(",")); -+ if (dx_get_hash(++at) > hash) -+ { -+ at--; -+ break; -+ } -+ } -+ assert (at == p - 1); -+ } -+ -+ at = p - 1; -+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); -+ frame->bh = bh; -+ frame->entries = entries; -+ frame->at = at; -+ if (!indirect--) return frame; -+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) -+ goto fail2; -+ at = entries = ((struct dx_node *) bh->b_data)->entries; -+ assert (dx_get_limit(entries) == dx_node_limit (dir)); -+ frame++; -+ } -+fail2: -+ while (frame >= frame_in) { -+ brelse(frame->bh); -+ frame--; -+ } -+fail: -+ return NULL; -+} -+ -+static void dx_release (struct dx_frame *frames) -+{ -+ if (frames[0].bh == NULL) -+ return; -+ -+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) -+ brelse(frames[1].bh); -+ brelse(frames[0].bh); -+} -+ -+/* -+ * This function increments the frame pointer to search the next leaf -+ * block, and reads in the necessary intervening nodes if the search -+ * should be necessary. Whether or not the search is necessary is -+ * controlled by the hash parameter. If the hash value is even, then -+ * the search is only continued if the next block starts with that -+ * hash value. This is used if we are searching for a specific file. -+ * -+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block. -+ * -+ * This function returns 1 if the caller should continue to search, -+ * or 0 if it should not. If there is an error reading one of the -+ * index blocks, it will return -1. -+ * -+ * If start_hash is non-null, it will be filled in with the starting -+ * hash of the next page. -+ */ -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash) -+{ -+ struct dx_frame *p; -+ struct buffer_head *bh; -+ int num_frames = 0; -+ __u32 bhash; -+ -+ *err = ENOENT; -+ p = frame; -+ /* -+ * Find the next leaf page by incrementing the frame pointer. -+ * If we run out of entries in the interior node, loop around and -+ * increment pointer in the parent node. When we break out of -+ * this loop, num_frames indicates the number of interior -+ * nodes need to be read. -+ */ -+ while (1) { -+ if (++(p->at) < p->entries + dx_get_count(p->entries)) -+ break; -+ if (p == frames) -+ return 0; -+ num_frames++; -+ p--; -+ } -+ -+ /* -+ * If the hash is 1, then continue only if the next page has a -+ * continuation hash of any value. This is used for readdir -+ * handling. Otherwise, check to see if the hash matches the -+ * desired contiuation hash. If it doesn't, return since -+ * there's no point to read in the successive index pages. -+ */ -+ bhash = dx_get_hash(p->at); -+ if (start_hash) -+ *start_hash = bhash; -+ if ((hash & 1) == 0) { -+ if ((bhash & ~1) != hash) -+ return 0; -+ } -+ /* -+ * If the hash is HASH_NB_ALWAYS, we always go to the next -+ * block so no check is necessary -+ */ -+ while (num_frames--) { -+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), -+ 0, err))) -+ return -1; /* Failure */ -+ p++; -+ brelse (p->bh); -+ p->bh = bh; -+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; -+ } -+ return 1; -+} -+ -+ -+/* -+ * p is at least 6 bytes before the end of page -+ */ -+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) -+{ -+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); -+} -+ -+/* -+ * This function fills a red-black tree with information from a -+ * directory. We start scanning the directory in hash order, starting -+ * at start_hash and start_minor_hash. -+ * -+ * This function returns the number of entries inserted into the tree, -+ * or a negative error code. -+ */ -+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash) -+{ -+ struct dx_hash_info hinfo; -+ struct buffer_head *bh; -+ struct ext3_dir_entry_2 *de, *top; -+ static struct dx_frame frames[2], *frame; -+ struct inode *dir; -+ int block, err; -+ int count = 0; -+ int ret; -+ __u32 hashval; -+ -+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, -+ start_minor_hash)); -+ dir = dir_file->f_dentry->d_inode; -+ hinfo.hash = start_hash; -+ hinfo.minor_hash = 0; -+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ -+ while (1) { -+ block = dx_get_block(frame->at); -+ dxtrace(printk("Reading block %d\n", block)); -+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) -+ goto errout; -+ -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) { -+ ext3fs_dirhash(de->name, de->name_len, &hinfo); -+ if ((hinfo.hash < start_hash) || -+ ((hinfo.hash == start_hash) && -+ (hinfo.minor_hash < start_minor_hash))) -+ continue; -+ ext3_htree_store_dirent(dir_file, hinfo.hash, -+ hinfo.minor_hash, de); -+ count++; -+ } -+ brelse (bh); -+ hashval = ~1; -+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, -+ frame, frames, &err, &hashval); -+ if (next_hash) -+ *next_hash = hashval; -+ if (ret == -1) -+ goto errout; -+ /* -+ * Stop if: (a) there are no more entries, or -+ * (b) we have inserted at least one entry and the -+ * next hash value is not a continuation -+ */ -+ if ((ret == 0) || -+ (count && ((hashval & 1) == 0))) -+ break; -+ } -+ dx_release(frames); -+ dxtrace(printk("Fill tree: returned %d entries\n", count)); -+ return count; -+errout: -+ dx_release(frames); -+ return (err); -+} -+ -+ -+/* -+ * Directory block splitting, compacting -+ */ -+ -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) -+{ -+ int count = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ while ((char *) de < base + size) -+ { -+ if (de->name_len && de->inode) { -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ map_tail--; -+ map_tail->hash = h.hash; -+ map_tail->offs = (u32) ((char *) de - base); -+ count++; -+ } -+ /* XXX: do we need to check rec_len == 0 case? -Chris */ -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ return count; -+} -+ -+static void dx_sort_map (struct dx_map_entry *map, unsigned count) -+{ -+ struct dx_map_entry *p, *q, *top = map + count - 1; -+ int more; -+ /* Combsort until bubble sort doesn't suck */ -+ while (count > 2) -+ { -+ count = count*10/13; -+ if (count - 9 < 2) /* 9, 10 -> 11 */ -+ count = 11; -+ for (p = top, q = p - count; q >= map; p--, q--) -+ if (p->hash < q->hash) -+ swap(*p, *q); -+ } -+ /* Garden variety bubble sort */ -+ do { -+ more = 0; -+ q = top; -+ while (q-- > map) -+ { -+ if (q[1].hash >= q[0].hash) -+ continue; -+ swap(*(q+1), *q); -+ more = 1; -+ } -+ } while(more); -+} -+ -+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) -+{ -+ struct dx_entry *entries = frame->entries; -+ struct dx_entry *old = frame->at, *new = old + 1; -+ int count = dx_get_count(entries); -+ -+ assert(count < dx_get_limit(entries)); -+ assert(old < entries + count); -+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new)); -+ dx_set_hash(new, hash); -+ dx_set_block(new, block); -+ dx_set_count(entries, count + 1); -+} -+#endif -+ -+ -+static void ext3_update_dx_flag(struct inode *inode) -+{ -+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb, -+ EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL; -+} -+ - /* - * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure. - * -@@ -94,6 +724,7 @@ static int inline search_dirblock(struct - return 0; - } - -+ - /* - * ext3_find_entry() - * -@@ -105,6 +736,8 @@ static int inline search_dirblock(struct - * The returned buffer_head has ->b_count elevated. The caller is expected - * to brelse() it when appropriate. - */ -+ -+ - static struct buffer_head * ext3_find_entry (struct dentry *dentry, - struct ext3_dir_entry_2 ** res_dir) - { -@@ -119,12 +752,32 @@ static struct buffer_head * ext3_find_en - int num = 0; - int nblocks, i, err; - struct inode *dir = dentry->d_parent->d_inode; -+ int namelen; -+ const u8 *name; -+ unsigned blocksize; - - *res_dir = NULL; - sb = dir->i_sb; -- -+ blocksize = sb->s_blocksize; -+ namelen = dentry->d_name.len; -+ name = dentry->d_name.name; -+ if (namelen > EXT3_NAME_LEN) -+ return NULL; -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ bh = ext3_dx_find_entry(dentry, res_dir, &err); -+ /* -+ * On success, or if the error was file not found, -+ * return. Otherwise, fall back to doing a search the -+ * old fashioned way. -+ */ -+ if (bh || (err != ERR_BAD_DX_DIR)) -+ return bh; -+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n")); -+ } -+#endif - nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb); -- start = dir->u.ext3_i.i_dir_start_lookup; -+ start = EXT3_I(dir)->i_dir_start_lookup; - if (start >= nblocks) - start = 0; - block = start; -@@ -165,7 +818,7 @@ restart: - i = search_dirblock(bh, dir, dentry, - block << EXT3_BLOCK_SIZE_BITS(sb), res_dir); - if (i == 1) { -- dir->u.ext3_i.i_dir_start_lookup = block; -+ EXT3_I(dir)->i_dir_start_lookup = block; - ret = bh; - goto cleanup_and_exit; - } else { -@@ -196,6 +849,74 @@ cleanup_and_exit: - return ret; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err) -+{ -+ struct super_block * sb; -+ struct dx_hash_info hinfo; -+ u32 hash; -+ struct dx_frame frames[2], *frame; -+ struct ext3_dir_entry_2 *de, *top; -+ struct buffer_head *bh; -+ unsigned long block; -+ int retval; -+ int namelen = dentry->d_name.len; -+ const u8 *name = dentry->d_name.name; -+ struct inode *dir = dentry->d_parent->d_inode; -+ -+ sb = dir->i_sb; -+ /* NFS may look up ".." - look at dx_root directory block */ -+ if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){ -+ if (!(frame = dx_probe(dentry, 0, &hinfo, frames, err))) -+ return NULL; -+ } else { -+ frame = frames; -+ frame->bh = NULL; /* for dx_release() */ -+ frame->at = (struct dx_entry *)frames; /* hack for zero entry*/ -+ dx_set_block(frame->at, 0); /* dx_root block is 0 */ -+ } -+ hash = hinfo.hash; -+ do { -+ block = dx_get_block(frame->at); -+ if (!(bh = ext3_bread (NULL,dir, block, 0, err))) -+ goto errout; -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *)((char *)de + sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) -+ if (ext3_match (namelen, name, de)) { -+ if (!ext3_check_dir_entry("ext3_find_entry", -+ dir, de, bh, -+ (block<b_data))) { -+ brelse (bh); -+ goto errout; -+ } -+ *res_dir = de; -+ dx_release (frames); -+ return bh; -+ } -+ brelse (bh); -+ /* Check to see if we should continue to search */ -+ retval = ext3_htree_next_block(dir, hash, frame, -+ frames, err, 0); -+ if (retval == -1) { -+ ext3_warning(sb, __FUNCTION__, -+ "error reading index page in directory #%lu", -+ dir->i_ino); -+ goto errout; -+ } -+ } while (retval == 1); -+ -+ *err = -ENOENT; -+errout: -+ dxtrace(printk("%s not found\n", name)); -+ dx_release (frames); -+ return NULL; -+} -+#endif -+ - static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) - { - struct inode * inode; -@@ -212,8 +925,9 @@ static struct dentry *ext3_lookup(struct - brelse (bh); - inode = iget(dir->i_sb, ino); - -- if (!inode) -+ if (!inode) { - return ERR_PTR(-EACCES); -+ } - } - d_add(dentry, inode); - return NULL; -@@ -237,6 +951,301 @@ static inline void ext3_set_de_type(stru - de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct ext3_dir_entry_2 * -+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) -+{ -+ unsigned rec_len = 0; -+ -+ while (count--) { -+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ memcpy (to, de, rec_len); -+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len); -+ de->inode = 0; -+ map++; -+ to += rec_len; -+ } -+ return (struct ext3_dir_entry_2 *) (to - rec_len); -+} -+ -+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) -+{ -+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; -+ unsigned rec_len = 0; -+ -+ prev = to = de; -+ while ((char*)de < base + size) { -+ next = (struct ext3_dir_entry_2 *) ((char *) de + -+ le16_to_cpu(de->rec_len)); -+ if (de->inode && de->name_len) { -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ if (de > to) -+ memmove(to, de, rec_len); -+ to->rec_len = cpu_to_le16(rec_len); -+ prev = to; -+ to = (struct ext3_dir_entry_2 *)((char *)to + rec_len); -+ } -+ de = next; -+ } -+ return prev; -+} -+ -+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, -+ struct buffer_head **bh,struct dx_frame *frame, -+ struct dx_hash_info *hinfo, int *error) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count, continued; -+ struct buffer_head *bh2; -+ u32 newblock; -+ u32 hash2; -+ struct dx_map_entry *map; -+ char *data1 = (*bh)->b_data, *data2; -+ unsigned split; -+ struct ext3_dir_entry_2 *de = NULL, *de2; -+ int err; -+ -+ bh2 = ext3_append (handle, dir, &newblock, error); -+ if (!(bh2)) { -+ brelse(*bh); -+ *bh = NULL; -+ goto errout; -+ } -+ -+ BUFFER_TRACE(*bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, *bh); -+ if (err) { -+ journal_error: -+ brelse(*bh); -+ brelse(bh2); -+ *bh = NULL; -+ ext3_std_error(dir->i_sb, err); -+ goto errout; -+ } -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ -+ data2 = bh2->b_data; -+ -+ /* create map in the end of data2 block */ -+ map = (struct dx_map_entry *) (data2 + blocksize); -+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1, -+ blocksize, hinfo, map); -+ map -= count; -+ split = count/2; // need to adjust to actual middle -+ dx_sort_map (map, count); -+ hash2 = map[split].hash; -+ continued = hash2 == map[split - 1].hash; -+ dxtrace(printk("Split block %i at %x, %i/%i\n", -+ dx_get_block(frame->at), hash2, split, count-split)); -+ -+ /* Fancy dance to stay within two buffers */ -+ de2 = dx_move_dirents(data1, data2, map + split, count - split); -+ de = dx_pack_dirents(data1,blocksize); -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); -+ -+ /* Which block gets the new entry? */ -+ if (hinfo->hash >= hash2) -+ { -+ swap(*bh, bh2); -+ de = de2; -+ } -+ dx_insert_block (frame, hash2 + continued, newblock); -+ err = ext3_journal_dirty_metadata (handle, bh2); -+ if (err) -+ goto journal_error; -+ err = ext3_journal_dirty_metadata (handle, frame->bh); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ dxtrace(dx_show_index ("frame", frame->entries)); -+errout: -+ return de; -+} -+#endif -+ -+ -+/* -+ * Add a new entry into a directory (leaf) block. If de is non-NULL, -+ * it points to a directory entry which is guaranteed to be large -+ * enough for new directory entry. If de is NULL, then -+ * add_dirent_to_buf will attempt search the directory block for -+ * space. It will return -ENOSPC if no space is available, and -EIO -+ * and -EEXIST if directory entry already exists. -+ * -+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In -+ * all other cases bh is released. -+ */ -+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct ext3_dir_entry_2 *de, -+ struct buffer_head * bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned long offset = 0; -+ unsigned short reclen; -+ int nlen, rlen, err; -+ char *top; -+ -+ reclen = EXT3_DIR_REC_LEN(namelen); -+ if (!de) { -+ de = (struct ext3_dir_entry_2 *)bh->b_data; -+ top = bh->b_data + dir->i_sb->s_blocksize - reclen; -+ while ((char *) de <= top) { -+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de, -+ bh, offset)) { -+ brelse (bh); -+ return -EIO; -+ } -+ if (ext3_match (namelen, name, de)) { -+ brelse (bh); -+ return -EEXIST; -+ } -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if ((de->inode? rlen - nlen: rlen) >= reclen) -+ break; -+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen); -+ offset += rlen; -+ } -+ if ((char *) de > top) -+ return -ENOSPC; -+ } -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) { -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return err; -+ } -+ -+ /* By now the buffer is marked for journaling */ -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if (de->inode) { -+ struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); -+ de1->rec_len = cpu_to_le16(rlen - nlen); -+ de->rec_len = cpu_to_le16(nlen); -+ de = de1; -+ } -+ de->file_type = EXT3_FT_UNKNOWN; -+ if (inode) { -+ de->inode = cpu_to_le32(inode->i_ino); -+ ext3_set_de_type(dir->i_sb, de, inode->i_mode); -+ } else -+ de->inode = 0; -+ de->name_len = namelen; -+ memcpy (de->name, name, namelen); -+ /* -+ * XXX shouldn't update any times until successful -+ * completion of syscall, but too many callers depend -+ * on this. -+ * -+ * XXX similarly, too many callers depend on -+ * ext3_new_inode() setting the times, but error -+ * recovery deletes the inode, so the worst that can -+ * happen is that the times are slightly out of date -+ * and/or different from the directory change time. -+ */ -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME; -+ ext3_update_dx_flag(dir); -+ dir->i_version = ++event; -+ ext3_mark_inode_dirty(handle, dir); -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return 0; -+} -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * This converts a one block unindexed directory to a 3 block indexed -+ * directory, and adds the dentry to the indexed directory. -+ */ -+static int make_indexed_dir(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct buffer_head *bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+ struct dx_root *root; -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries; -+ struct ext3_dir_entry_2 *de, *de2; -+ char *data1, *top; -+ unsigned len; -+ int retval; -+ unsigned blocksize; -+ struct dx_hash_info hinfo; -+ u32 block; -+ -+ blocksize = dir->i_sb->s_blocksize; -+ dxtrace(printk("Creating index\n")); -+ retval = ext3_journal_get_write_access(handle, bh); -+ if (retval) { -+ ext3_std_error(dir->i_sb, retval); -+ brelse(bh); -+ return retval; -+ } -+ root = (struct dx_root *) bh->b_data; -+ -+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; -+ bh2 = ext3_append (handle, dir, &block, &retval); -+ if (!(bh2)) { -+ brelse(bh); -+ return retval; -+ } -+ data1 = bh2->b_data; -+ -+ /* The 0th block becomes the root, move the dirents out */ -+ de = (struct ext3_dir_entry_2 *)&root->dotdot; -+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len)); -+ len = ((char *) root) + blocksize - (char *) de; -+ memcpy (data1, de, len); -+ de = (struct ext3_dir_entry_2 *) data1; -+ top = data1 + len; -+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top) -+ de = de2; -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ /* Initialize the root; the dot dirents already exist */ -+ de = (struct ext3_dir_entry_2 *) (&root->dotdot); -+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); -+ memset (&root->info, 0, sizeof(root->info)); -+ root->info.info_length = sizeof(root->info); -+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version; -+ entries = root->entries; -+ dx_set_block (entries, 1); -+ dx_set_count (entries, 1); -+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info))); -+ -+ /* Initialize as for dx_probe */ -+ hinfo.hash_version = root->info.hash_version; -+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ ext3fs_dirhash(name, namelen, &hinfo); -+ frame = frames; -+ frame->entries = entries; -+ frame->at = entries; -+ frame->bh = bh; -+ bh = bh2; -+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval); -+ dx_release (frames); -+ if (!(de)) -+ return retval; -+ -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} -+#endif -+ - /* - * ext3_add_entry() - * -@@ -247,127 +1255,198 @@ static inline void ext3_set_de_type(stru - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -- --/* -- * AKPM: the journalling code here looks wrong on the error paths -- */ - static int ext3_add_entry (handle_t *handle, struct dentry *dentry, - struct inode *inode) - { - struct inode *dir = dentry->d_parent->d_inode; -- const char *name = dentry->d_name.name; -- int namelen = dentry->d_name.len; - unsigned long offset; -- unsigned short rec_len; - struct buffer_head * bh; -- struct ext3_dir_entry_2 * de, * de1; -+ struct ext3_dir_entry_2 *de; - struct super_block * sb; - int retval; -+#ifdef CONFIG_EXT3_INDEX -+ int dx_fallback=0; -+#endif -+ unsigned blocksize; -+ unsigned nlen, rlen; -+ u32 block, blocks; - - sb = dir->i_sb; -- -- if (!namelen) -+ blocksize = sb->s_blocksize; -+ if (!dentry->d_name.len) - return -EINVAL; -- bh = ext3_bread (handle, dir, 0, 0, &retval); -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ retval = ext3_dx_add_entry(handle, dentry, inode); -+ if (!retval || (retval != ERR_BAD_DX_DIR)) -+ return retval; -+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; -+ dx_fallback++; -+ ext3_mark_inode_dirty(handle, dir); -+ } -+#endif -+ blocks = dir->i_size >> sb->s_blocksize_bits; -+ for (block = 0, offset = 0; block < blocks; block++) { -+ bh = ext3_bread(handle, dir, block, 0, &retval); -+ if(!bh) -+ return retval; -+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (retval != -ENOSPC) -+ return retval; -+ -+#ifdef CONFIG_EXT3_INDEX -+ if (blocks == 1 && !dx_fallback && -+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ return make_indexed_dir(handle, dentry, inode, bh); -+#endif -+ brelse(bh); -+ } -+ bh = ext3_append(handle, dir, &block, &retval); - if (!bh) - return retval; -- rec_len = EXT3_DIR_REC_LEN(namelen); -- offset = 0; - de = (struct ext3_dir_entry_2 *) bh->b_data; -- while (1) { -- if ((char *)de >= sb->s_blocksize + bh->b_data) { -- brelse (bh); -- bh = NULL; -- bh = ext3_bread (handle, dir, -- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval); -- if (!bh) -- return retval; -- if (dir->i_size <= offset) { -- if (dir->i_size == 0) { -- brelse(bh); -- return -ENOENT; -- } -+ de->inode = 0; -+ de->rec_len = cpu_to_le16(rlen = blocksize); -+ nlen = 0; -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} - -- ext3_debug ("creating next block\n"); -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * Returns 0 for success, or a negative error value -+ */ -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries, *at; -+ struct dx_hash_info hinfo; -+ struct buffer_head * bh; -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct super_block * sb = dir->i_sb; -+ struct ext3_dir_entry_2 *de; -+ int err; - -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- de->inode = 0; -- de->rec_len = le16_to_cpu(sb->s_blocksize); -- dir->u.ext3_i.i_disksize = -- dir->i_size = offset + sb->s_blocksize; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- ext3_mark_inode_dirty(handle, dir); -- } else { -+ frame = dx_probe(dentry, 0, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ entries = frame->entries; -+ at = frame->at; - -- ext3_debug ("skipping to next block\n"); -+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) -+ goto cleanup; - -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- } -- } -- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh, -- offset)) { -- brelse (bh); -- return -ENOENT; -- } -- if (ext3_match (namelen, name, de)) { -- brelse (bh); -- return -EEXIST; -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) -+ goto journal_error; -+ -+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (err != -ENOSPC) { -+ bh = 0; -+ goto cleanup; -+ } -+ -+ /* Block full, should compress but for now just split */ -+ dxtrace(printk("using %u of %u node entries\n", -+ dx_get_count(entries), dx_get_limit(entries))); -+ /* Need to split index? */ -+ if (dx_get_count(entries) == dx_get_limit(entries)) { -+ u32 newblock; -+ unsigned icount = dx_get_count(entries); -+ int levels = frame - frames; -+ struct dx_entry *entries2; -+ struct dx_node *node2; -+ struct buffer_head *bh2; -+ -+ if (levels && (dx_get_count(frames->entries) == -+ dx_get_limit(frames->entries))) { -+ ext3_warning(sb, __FUNCTION__, -+ "Directory index full!\n"); -+ err = -ENOSPC; -+ goto cleanup; - } -- if ((le32_to_cpu(de->inode) == 0 && -- le16_to_cpu(de->rec_len) >= rec_len) || -- (le16_to_cpu(de->rec_len) >= -- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) { -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- /* By now the buffer is marked for journaling */ -- offset += le16_to_cpu(de->rec_len); -- if (le32_to_cpu(de->inode)) { -- de1 = (struct ext3_dir_entry_2 *) ((char *) de + -- EXT3_DIR_REC_LEN(de->name_len)); -- de1->rec_len = -- cpu_to_le16(le16_to_cpu(de->rec_len) - -- EXT3_DIR_REC_LEN(de->name_len)); -- de->rec_len = cpu_to_le16( -- EXT3_DIR_REC_LEN(de->name_len)); -- de = de1; -+ bh2 = ext3_append (handle, dir, &newblock, &err); -+ if (!(bh2)) -+ goto cleanup; -+ node2 = (struct dx_node *)(bh2->b_data); -+ entries2 = node2->entries; -+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); -+ node2->fake.inode = 0; -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ if (levels) { -+ unsigned icount1 = icount/2, icount2 = icount - icount1; -+ unsigned hash2 = dx_get_hash(entries + icount1); -+ dxtrace(printk("Split index %i/%i\n", icount1, icount2)); -+ -+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ -+ err = ext3_journal_get_write_access(handle, -+ frames[0].bh); -+ if (err) -+ goto journal_error; -+ -+ memcpy ((char *) entries2, (char *) (entries + icount1), -+ icount2 * sizeof(struct dx_entry)); -+ dx_set_count (entries, icount1); -+ dx_set_count (entries2, icount2); -+ dx_set_limit (entries2, dx_node_limit(dir)); -+ -+ /* Which index block gets the new entry? */ -+ if (at - entries >= icount1) { -+ frame->at = at = at - entries - icount1 + entries2; -+ frame->entries = entries = entries2; -+ swap(frame->bh, bh2); - } -- de->file_type = EXT3_FT_UNKNOWN; -- if (inode) { -- de->inode = cpu_to_le32(inode->i_ino); -- ext3_set_de_type(dir->i_sb, de, inode->i_mode); -- } else -- de->inode = 0; -- de->name_len = namelen; -- memcpy (de->name, name, namelen); -- /* -- * XXX shouldn't update any times until successful -- * completion of syscall, but too many callers depend -- * on this. -- * -- * XXX similarly, too many callers depend on -- * ext3_new_inode() setting the times, but error -- * recovery deletes the inode, so the worst that can -- * happen is that the times are slightly out of date -- * and/or different from the directory change time. -- */ -- dir->i_mtime = dir->i_ctime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- dir->i_version = ++event; -- ext3_mark_inode_dirty(handle, dir); -- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -- ext3_journal_dirty_metadata(handle, bh); -- brelse(bh); -- return 0; -+ dx_insert_block (frames + 0, hash2, newblock); -+ dxtrace(dx_show_index ("node", frames[1].entries)); -+ dxtrace(dx_show_index ("node", -+ ((struct dx_node *) bh2->b_data)->entries)); -+ err = ext3_journal_dirty_metadata(handle, bh2); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ } else { -+ dxtrace(printk("Creating second level index...\n")); -+ memcpy((char *) entries2, (char *) entries, -+ icount * sizeof(struct dx_entry)); -+ dx_set_limit(entries2, dx_node_limit(dir)); -+ -+ /* Set up root */ -+ dx_set_count(entries, 1); -+ dx_set_block(entries + 0, newblock); -+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; -+ -+ /* Add new access path frame */ -+ frame = frames + 1; -+ frame->at = at = at - entries + entries2; -+ frame->entries = entries = entries2; -+ frame->bh = bh2; -+ err = ext3_journal_get_write_access(handle, -+ frame->bh); -+ if (err) -+ goto journal_error; - } -- offset += le16_to_cpu(de->rec_len); -- de = (struct ext3_dir_entry_2 *) -- ((char *) de + le16_to_cpu(de->rec_len)); -+ ext3_journal_dirty_metadata(handle, frames[0].bh); - } -- brelse (bh); -- return -ENOSPC; -+ de = do_split(handle, dir, &bh, frame, &hinfo, &err); -+ if (!de) -+ goto cleanup; -+ err = add_dirent_to_buf(handle, dentry, inode, de, bh); -+ bh = 0; -+ goto cleanup; -+ -+journal_error: -+ ext3_std_error(dir->i_sb, err); -+cleanup: -+ if (bh) -+ brelse(bh); -+ dx_release(frames); -+ return err; - } -+#endif - - /* - * ext3_delete_entry deletes a directory entry by merging it with the -@@ -451,9 +1530,11 @@ static int ext3_create (struct inode * d - struct inode * inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -478,9 +1559,11 @@ static int ext3_mknod (struct inode * di - struct inode *inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -507,9 +1590,11 @@ static int ext3_mkdir(struct inode * dir - if (dir->i_nlink >= EXT3_LINK_MAX) - return -EMLINK; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -521,7 +1606,7 @@ static int ext3_mkdir(struct inode * dir - - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; -- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize; -+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - inode->i_blocks = 0; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { -@@ -554,21 +1639,19 @@ static int ext3_mkdir(struct inode * dir - inode->i_mode |= S_ISGID; - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); -- if (err) -- goto out_no_entry; -+ if (err) { -+ inode->i_nlink = 0; -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - dir->i_nlink++; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- inode->i_nlink = 0; -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - /* -@@ -655,7 +1738,7 @@ int ext3_orphan_add(handle_t *handle, st - int err = 0, rc; - - lock_super(sb); -- if (!list_empty(&inode->u.ext3_i.i_orphan)) -+ if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - - /* Orphan handling is only valid for files with data blocks -@@ -696,7 +1779,7 @@ int ext3_orphan_add(handle_t *handle, st - * This is safe: on error we're going to ignore the orphan list - * anyway on the next recovery. */ - if (!err) -- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan); -+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", -@@ -714,25 +1797,26 @@ out_unlock: - int ext3_orphan_del(handle_t *handle, struct inode *inode) - { - struct list_head *prev; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_sb_info *sbi; - ino_t ino_next; - struct ext3_iloc iloc; - int err = 0; - - lock_super(inode->i_sb); -- if (list_empty(&inode->u.ext3_i.i_orphan)) { -+ if (list_empty(&ei->i_orphan)) { - unlock_super(inode->i_sb); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); -- prev = inode->u.ext3_i.i_orphan.prev; -+ prev = ei->i_orphan.prev; - sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino); - -- list_del(&inode->u.ext3_i.i_orphan); -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ list_del(&ei->i_orphan); -+ INIT_LIST_HEAD(&ei->i_orphan); - - /* If we're on an error path, we may not have a valid - * transaction handle with which to update the orphan list on -@@ -793,8 +1877,9 @@ static int ext3_rmdir (struct inode * di - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - retval = -ENOENT; - bh = ext3_find_entry (dentry, &de); -@@ -832,7 +1917,7 @@ static int ext3_rmdir (struct inode * di - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - - end_rmdir: -@@ -850,8 +1935,9 @@ static int ext3_unlink(struct inode * di - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -878,7 +1964,7 @@ static int ext3_unlink(struct inode * di - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; - if (!inode->i_nlink) -@@ -904,9 +1990,11 @@ static int ext3_symlink (struct inode * - if (l > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -916,7 +2004,7 @@ static int ext3_symlink (struct inode * - if (IS_ERR(inode)) - goto out_stop; - -- if (l > sizeof (inode->u.ext3_i.i_data)) { -+ if (l > sizeof (EXT3_I(inode)->i_data)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* -@@ -925,25 +2013,23 @@ static int ext3_symlink (struct inode * - * i_size in generic_commit_write(). - */ - err = block_symlink(inode, symname, l); -- if (err) -- goto out_no_entry; -+ if (err) { -+ ext3_dec_count(handle, inode); -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - } else { - inode->i_op = &ext3_fast_symlink_inode_operations; -- memcpy((char*)&inode->u.ext3_i.i_data,symname,l); -+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l); - inode->i_size = l-1; - } -- inode->u.ext3_i.i_disksize = inode->i_size; -+ EXT3_I(inode)->i_disksize = inode->i_size; - err = ext3_add_nondir(handle, dentry, inode); - ext3_mark_inode_dirty(handle, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- ext3_dec_count(handle, inode); -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - static int ext3_link (struct dentry * old_dentry, -@@ -956,12 +2042,15 @@ static int ext3_link (struct dentry * ol - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) -+ if (inode->i_nlink >= EXT3_LINK_MAX) { - return -EMLINK; -+ } - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -995,9 +2084,11 @@ static int ext3_rename (struct inode * o - - old_bh = new_bh = dir_bh = NULL; - -- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(old_dir) || IS_SYNC(new_dir)) - handle->h_sync = 1; -@@ -1077,7 +2168,7 @@ static int ext3_rename (struct inode * o - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(old_dir); - if (dir_bh) { - BUFFER_TRACE(dir_bh, "get_write_access"); - ext3_journal_get_write_access(handle, dir_bh); -@@ -1089,7 +2180,7 @@ static int ext3_rename (struct inode * o - new_inode->i_nlink--; - } else { - new_dir->i_nlink++; -- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } - } ---- linux-2.4.20/fs/ext3/super.c~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/fs/ext3/super.c Sat Apr 5 03:56:31 2003 -@@ -707,6 +707,7 @@ static int ext3_setup_super(struct super - es->s_mtime = cpu_to_le32(CURRENT_TIME); - ext3_update_dynamic_rev(sb); - EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -+ - ext3_commit_super (sb, es, 1); - if (test_opt (sb, DEBUG)) - printk (KERN_INFO -@@ -717,6 +718,7 @@ static int ext3_setup_super(struct super - EXT3_BLOCKS_PER_GROUP(sb), - EXT3_INODES_PER_GROUP(sb), - sbi->s_mount_opt); -+ - printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ", - bdevname(sb->s_dev)); - if (EXT3_SB(sb)->s_journal->j_inode == NULL) { -@@ -890,6 +892,7 @@ static loff_t ext3_max_size(int bits) - return res; - } - -+ - struct super_block * ext3_read_super (struct super_block * sb, void * data, - int silent) - { -@@ -1066,6 +1069,9 @@ struct super_block * ext3_read_super (st - sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); -+ for (i=0; i < 4; i++) -+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); -+ sbi->s_def_hash_version = es->s_def_hash_version; - - if (sbi->s_blocks_per_group > blocksize * 8) { - printk (KERN_ERR -@@ -1769,6 +1775,7 @@ static void __exit exit_ext3_fs(void) - unregister_filesystem(&ext3_fs_type); - } - -+EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); ---- linux-2.4.20/include/linux/ext3_fs.h~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/include/linux/ext3_fs.h Sat Apr 5 03:56:31 2003 -@@ -40,6 +40,11 @@ - #define EXT3FS_VERSION "2.4-0.9.19" - - /* -+ * Always enable hashed directories -+ */ -+#define CONFIG_EXT3_INDEX -+ -+/* - * Debug code - */ - #ifdef EXT3FS_DEBUG -@@ -437,8 +442,11 @@ struct ext3_super_block { - /*E0*/ __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ -- --/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */ -+ __u32 s_hash_seed[4]; /* HTREE hash seed */ -+ __u8 s_def_hash_version; /* Default hash version to use */ -+ __u8 s_reserved_char_pad; -+ __u16 s_reserved_word_pad; -+ __u32 s_reserved[192]; /* Padding to the end of the block */ - }; - - #ifdef __KERNEL__ -@@ -575,9 +583,46 @@ struct ext3_dir_entry_2 { - #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) - #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ - ~EXT3_DIR_ROUND) -+/* -+ * Hash Tree Directory indexing -+ * (c) Daniel Phillips, 2001 -+ */ -+ -+#ifdef CONFIG_EXT3_INDEX -+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \ -+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \ -+ (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) -+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) -+#else -+ #define is_dx(dir) 0 -+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2) -+#endif -+ -+/* Legal values for the dx_root hash_version field: */ -+ -+#define DX_HASH_LEGACY 0 -+#define DX_HASH_HALF_MD4 1 -+#define DX_HASH_TEA 2 -+ -+/* hash info structure used by the directory hash */ -+struct dx_hash_info -+{ -+ u32 hash; -+ u32 minor_hash; -+ int hash_version; -+ u32 *seed; -+}; - - #ifdef __KERNEL__ - /* -+ * Control parameters used by ext3_htree_next_block -+ */ -+#define HASH_NB_ALWAYS 1 -+ -+ -+/* - * Describe an inode's exact location on disk and in memory - */ - struct ext3_iloc -@@ -587,6 +632,27 @@ struct ext3_iloc - unsigned long block_group; - }; - -+ -+/* -+ * This structure is stuffed into the struct file's private_data field -+ * for directories. It is where we put information so that we can do -+ * readdir operations in hash tree order. -+ */ -+struct dir_private_info { -+ rb_root_t root; -+ rb_node_t *curr_node; -+ struct fname *extra_fname; -+ loff_t last_pos; -+ __u32 curr_hash; -+ __u32 curr_minor_hash; -+ __u32 next_hash; -+}; -+ -+/* -+ * Special error return code only used by dx_probe() and its callers. -+ */ -+#define ERR_BAD_DX_DIR -75000 -+ - /* - * Function prototypes - */ -@@ -614,11 +680,20 @@ extern struct ext3_group_desc * ext3_get - - /* dir.c */ - extern int ext3_check_dir_entry(const char *, struct inode *, -- struct ext3_dir_entry_2 *, struct buffer_head *, -- unsigned long); -+ struct ext3_dir_entry_2 *, -+ struct buffer_head *, unsigned long); -+extern void ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent); -+extern void ext3_htree_free_dir_info(struct dir_private_info *p); -+ - /* fsync.c */ - extern int ext3_sync_file (struct file *, struct dentry *, int); - -+/* hash.c */ -+extern int ext3fs_dirhash(const char *name, int len, struct -+ dx_hash_info *hinfo); -+ - /* ialloc.c */ - extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int); - extern void ext3_free_inode (handle_t *, struct inode *); -@@ -650,6 +725,8 @@ extern int ext3_ioctl (struct inode *, s - /* namei.c */ - extern int ext3_orphan_add(handle_t *, struct inode *); - extern int ext3_orphan_del(handle_t *, struct inode *); -+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash); - - /* super.c */ - extern void ext3_error (struct super_block *, const char *, const char *, ...) ---- linux-2.4.20/include/linux/ext3_fs_sb.h~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/include/linux/ext3_fs_sb.h Sat Apr 5 03:56:31 2003 -@@ -62,6 +62,8 @@ struct ext3_sb_info { - int s_inode_size; - int s_first_ino; - u32 s_next_generation; -+ u32 s_hash_seed[4]; -+ int s_def_hash_version; - - /* Journaling */ - struct inode * s_journal_inode; ---- linux-2.4.20/include/linux/ext3_jbd.h~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/include/linux/ext3_jbd.h Sat Apr 5 03:56:31 2003 -@@ -63,6 +63,8 @@ extern int ext3_writepage_trans_blocks(s - - #define EXT3_RESERVE_TRANS_BLOCKS 12 - -+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 -+ - int - ext3_mark_iloc_dirty(handle_t *handle, - struct inode *inode, ---- linux-2.4.20/include/linux/rbtree.h~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/include/linux/rbtree.h Sat Apr 5 03:56:31 2003 -@@ -120,6 +120,8 @@ rb_root_t; - - extern void rb_insert_color(rb_node_t *, rb_root_t *); - extern void rb_erase(rb_node_t *, rb_root_t *); -+extern rb_node_t *rb_get_first(rb_root_t *root); -+extern rb_node_t *rb_get_next(rb_node_t *n); - - static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) - { ---- linux-2.4.20/lib/rbtree.c~ext-2.4-patch-1 Sat Apr 5 03:56:31 2003 -+++ linux-2.4.20-braam/lib/rbtree.c Sat Apr 5 03:56:31 2003 -@@ -17,6 +17,8 @@ - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -+ -+ rb_get_first and rb_get_next written by Theodore Ts'o, 9/8/2002 - */ - - #include -@@ -294,3 +296,43 @@ void rb_erase(rb_node_t * node, rb_root_ - __rb_erase_color(child, parent, root); - } - EXPORT_SYMBOL(rb_erase); -+ -+/* -+ * This function returns the first node (in sort order) of the tree. -+ */ -+rb_node_t *rb_get_first(rb_root_t *root) -+{ -+ rb_node_t *n; -+ -+ n = root->rb_node; -+ if (!n) -+ return 0; -+ while (n->rb_left) -+ n = n->rb_left; -+ return n; -+} -+EXPORT_SYMBOL(rb_get_first); -+ -+/* -+ * Given a node, this function will return the next node in the tree. -+ */ -+rb_node_t *rb_get_next(rb_node_t *n) -+{ -+ rb_node_t *parent; -+ -+ if (n->rb_right) { -+ n = n->rb_right; -+ while (n->rb_left) -+ n = n->rb_left; -+ return n; -+ } else { -+ while ((parent = n->rb_parent)) { -+ if (n == parent->rb_left) -+ return parent; -+ n = parent; -+ } -+ return 0; -+ } -+} -+EXPORT_SYMBOL(rb_get_next); -+ - -_ diff --git a/lustre/kernel_patches/patches/ext-2.4-patch-2.patch b/lustre/kernel_patches/patches/ext-2.4-patch-2.patch deleted file mode 100644 index 689d33b..0000000 --- a/lustre/kernel_patches/patches/ext-2.4-patch-2.patch +++ /dev/null @@ -1,34 +0,0 @@ -# This is a BitKeeper generated patch for the following project: -# Project Name: Linux kernel tree -# -# namei.c | 9 +++++++++ -# 1 files changed, 9 insertions(+) -# -# The following is the BitKeeper ChangeSet Log -# -------------------------------------------- -# 02/11/07 tytso@snap.thunk.org 1.777 -# Add '.' and '..' entries to be returned by readdir of htree directories -# -# This patch from Chris Li adds '.' and '..' to the rbtree so that they -# are properly returned by readdir. -# -------------------------------------------- -# -diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c ---- a/fs/ext3/namei.c Thu Nov 7 10:57:30 2002 -+++ b/fs/ext3/namei.c Thu Nov 7 10:57:30 2002 -@@ -546,6 +546,15 @@ - if (!frame) - return err; - -+ /* Add '.' and '..' from the htree header */ -+ if (!start_hash && !start_minor_hash) { -+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; -+ ext3_htree_store_dirent(dir_file, 0, 0, de); -+ de = ext3_next_entry(de); -+ ext3_htree_store_dirent(dir_file, 0, 0, de); -+ count += 2; -+ } -+ - while (1) { - block = dx_get_block(frame->at); - dxtrace(printk("Reading block %d\n", block)); diff --git a/lustre/kernel_patches/patches/ext-2.4-patch-3.patch b/lustre/kernel_patches/patches/ext-2.4-patch-3.patch deleted file mode 100644 index 2600b02..0000000 --- a/lustre/kernel_patches/patches/ext-2.4-patch-3.patch +++ /dev/null @@ -1,96 +0,0 @@ -# This is a BitKeeper generated patch for the following project: -# Project Name: Linux kernel tree -# -# fs/ext3/dir.c | 7 +++++-- -# fs/ext3/namei.c | 11 +++++++---- -# include/linux/ext3_fs.h | 2 +- -# 3 files changed, 13 insertions(+), 7 deletions(-) -# -# The following is the BitKeeper ChangeSet Log -# -------------------------------------------- -# 02/11/07 tytso@snap.thunk.org 1.778 -# Check for failed kmalloc() in ext3_htree_store_dirent() -# -# This patch checks for a failed kmalloc() in ext3_htree_store_dirent(), -# and passes the error up to its caller, ext3_htree_fill_tree(). -# -------------------------------------------- -# -diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c ---- a/fs/ext3/dir.c Thu Nov 7 10:57:34 2002 -+++ b/fs/ext3/dir.c Thu Nov 7 10:57:34 2002 -@@ -308,7 +308,7 @@ - /* - * Given a directory entry, enter it into the fname rb tree. - */ --void ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, - __u32 minor_hash, - struct ext3_dir_entry_2 *dirent) - { -@@ -323,6 +323,8 @@ - /* Create and allocate the fname structure */ - len = sizeof(struct fname) + dirent->name_len + 1; - new_fn = kmalloc(len, GFP_KERNEL); -+ if (!new_fn) -+ return -ENOMEM; - memset(new_fn, 0, len); - new_fn->hash = hash; - new_fn->minor_hash = minor_hash; -@@ -344,7 +346,7 @@ - (new_fn->minor_hash == fname->minor_hash)) { - new_fn->next = fname->next; - fname->next = new_fn; -- return; -+ return 0; - } - - if (new_fn->hash < fname->hash) -@@ -359,6 +361,7 @@ - - rb_link_node(&new_fn->rb_hash, parent, p); - rb_insert_color(&new_fn->rb_hash, &info->root); -+ return 0; - } - - -diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c ---- a/fs/ext3/namei.c Thu Nov 7 10:57:34 2002 -+++ b/fs/ext3/namei.c Thu Nov 7 10:57:34 2002 -@@ -549,9 +549,11 @@ - /* Add '.' and '..' from the htree header */ - if (!start_hash && !start_minor_hash) { - de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; -- ext3_htree_store_dirent(dir_file, 0, 0, de); -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; - de = ext3_next_entry(de); -- ext3_htree_store_dirent(dir_file, 0, 0, de); -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; - count += 2; - } - -@@ -570,8 +572,9 @@ - ((hinfo.hash == start_hash) && - (hinfo.minor_hash < start_minor_hash))) - continue; -- ext3_htree_store_dirent(dir_file, hinfo.hash, -- hinfo.minor_hash, de); -+ if ((err = ext3_htree_store_dirent(dir_file, -+ hinfo.hash, hinfo.minor_hash, de)) != 0) -+ goto errout; - count++; - } - brelse (bh); -diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h ---- a/include/linux/ext3_fs.h Thu Nov 7 10:57:34 2002 -+++ b/include/linux/ext3_fs.h Thu Nov 7 10:57:34 2002 -@@ -682,7 +682,7 @@ - extern int ext3_check_dir_entry(const char *, struct inode *, - struct ext3_dir_entry_2 *, - struct buffer_head *, unsigned long); --extern void ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, - __u32 minor_hash, - struct ext3_dir_entry_2 *dirent); - extern void ext3_htree_free_dir_info(struct dir_private_info *p); diff --git a/lustre/kernel_patches/patches/ext-2.4-patch-4.patch b/lustre/kernel_patches/patches/ext-2.4-patch-4.patch deleted file mode 100644 index 4c8d4fa..0000000 --- a/lustre/kernel_patches/patches/ext-2.4-patch-4.patch +++ /dev/null @@ -1,52 +0,0 @@ -# This is a BitKeeper generated patch for the following project: -# Project Name: Linux kernel tree -# -# namei.c | 21 ++++++++++++++++++++- -# 1 files changed, 20 insertions(+), 1 deletion(-) -# -# The following is the BitKeeper ChangeSet Log -# -------------------------------------------- -# 02/11/07 tytso@snap.thunk.org 1.779 -# Fix ext3 htree rename bug. -# -# This fixes an ext3 htree bug pointed out by Christopher Li; if -# adding the new name to the directory causes a split, this can cause -# the directory entry containing the old name to move to another -# block, and then the removal of the old name will fail. -# -------------------------------------------- -# -diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c ---- a/fs/ext3/namei.c Thu Nov 7 10:57:49 2002 -+++ b/fs/ext3/namei.c Thu Nov 7 10:57:49 2002 -@@ -2173,7 +2173,30 @@ - /* - * ok, that's it - */ -- ext3_delete_entry(handle, old_dir, old_de, old_bh); -+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino || -+ old_de->name_len != old_dentry->d_name.len || -+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || -+ (retval = ext3_delete_entry(handle, old_dir, -+ old_de, old_bh)) == -ENOENT) { -+ /* old_de could have moved from under us during htree split, so -+ * make sure that we are deleting the right entry. We might -+ * also be pointing to a stale entry in the unused part of -+ * old_bh so just checking inum and the name isn't enough. */ -+ struct buffer_head *old_bh2; -+ struct ext3_dir_entry_2 *old_de2; -+ -+ old_bh2 = ext3_find_entry(old_dentry, &old_de2); -+ if (old_bh2) { -+ retval = ext3_delete_entry(handle, old_dir, -+ old_de2, old_bh2); -+ brelse(old_bh2); -+ } -+ } -+ if (retval) { -+ ext3_warning(old_dir->i_sb, "ext3_rename", -+ "Deleting old file (%lu), %d, error=%d", -+ old_dir->i_ino, old_dir->i_nlink, retval); -+ } - - if (new_inode) { - new_inode->i_nlink--; diff --git a/lustre/kernel_patches/patches/ext3-2.4-ino_t.patch b/lustre/kernel_patches/patches/ext3-2.4-ino_t.patch deleted file mode 100644 index 1786d0f..0000000 --- a/lustre/kernel_patches/patches/ext3-2.4-ino_t.patch +++ /dev/null @@ -1,144 +0,0 @@ - fs/ext3/ialloc.c | 20 ++++++++++---------- - fs/ext3/namei.c | 16 ++++++++-------- - include/linux/ext3_fs.h | 2 +- - 3 files changed, 19 insertions(+), 19 deletions(-) - ---- linux-2.4.20/fs/ext3/ialloc.c~ext3-2.4-ino_t 2003-04-08 23:35:24.000000000 -0600 -+++ linux-2.4.20-braam/fs/ext3/ialloc.c 2003-04-08 23:35:24.000000000 -0600 -@@ -65,8 +65,8 @@ static int read_inode_bitmap (struct sup - if (!bh) { - ext3_error (sb, "read_inode_bitmap", - "Cannot read inode bitmap - " -- "block_group = %lu, inode_bitmap = %lu", -- block_group, (unsigned long) gdp->bg_inode_bitmap); -+ "block_group = %lu, inode_bitmap = %u", -+ block_group, gdp->bg_inode_bitmap); - retval = -EIO; - } - /* -@@ -533,19 +533,19 @@ out: - } - - /* Verify that we are loading a valid orphan from disk */ --struct inode *ext3_orphan_get (struct super_block * sb, ino_t ino) -+struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) - { -- ino_t max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count); -+ unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count); - unsigned long block_group; - int bit; - int bitmap_nr; - struct buffer_head *bh; - struct inode *inode = NULL; -- -+ - /* Error cases - e2fsck has already cleaned up for us */ - if (ino > max_ino) { - ext3_warning(sb, __FUNCTION__, -- "bad orphan ino %ld! e2fsck was run?\n", ino); -+ "bad orphan ino %lu! e2fsck was run?\n", ino); - return NULL; - } - -@@ -554,7 +554,7 @@ struct inode *ext3_orphan_get (struct su - if ((bitmap_nr = load_inode_bitmap(sb, block_group)) < 0 || - !(bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr])) { - ext3_warning(sb, __FUNCTION__, -- "inode bitmap error for orphan %ld\n", ino); -+ "inode bitmap error for orphan %lu\n", ino); - return NULL; - } - -@@ -565,16 +565,16 @@ struct inode *ext3_orphan_get (struct su - if (!ext3_test_bit(bit, bh->b_data) || !(inode = iget(sb, ino)) || - is_bad_inode(inode) || NEXT_ORPHAN(inode) > max_ino) { - ext3_warning(sb, __FUNCTION__, -- "bad orphan inode %ld! e2fsck was run?\n", ino); -+ "bad orphan inode %lu! e2fsck was run?\n", ino); - printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%ld) = %d\n", - bit, bh->b_blocknr, ext3_test_bit(bit, bh->b_data)); - printk(KERN_NOTICE "inode=%p\n", inode); - if (inode) { - printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", - is_bad_inode(inode)); -- printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%d\n", -+ printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", - NEXT_ORPHAN(inode)); -- printk(KERN_NOTICE "max_ino=%ld\n", max_ino); -+ printk(KERN_NOTICE "max_ino=%lu\n", max_ino); - } - /* Avoid freeing blocks if we got a bad deleted inode */ - if (inode && inode->i_nlink == 0) ---- linux-2.4.20/fs/ext3/namei.c~ext3-2.4-ino_t 2003-04-08 23:35:24.000000000 -0600 -+++ linux-2.4.20-braam/fs/ext3/namei.c 2003-04-08 23:35:24.000000000 -0600 -@@ -1808,10 +1808,10 @@ int ext3_orphan_del(handle_t *handle, st - struct list_head *prev; - struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_sb_info *sbi; -- ino_t ino_next; -+ unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; -- -+ - lock_super(inode->i_sb); - if (list_empty(&ei->i_orphan)) { - unlock_super(inode->i_sb); -@@ -1822,7 +1822,7 @@ int ext3_orphan_del(handle_t *handle, st - prev = ei->i_orphan.prev; - sbi = EXT3_SB(inode->i_sb); - -- jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino); -+ jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - - list_del(&ei->i_orphan); - INIT_LIST_HEAD(&ei->i_orphan); -@@ -1833,13 +1833,13 @@ int ext3_orphan_del(handle_t *handle, st - * list in memory. */ - if (!handle) - goto out; -- -+ - err = ext3_reserve_inode_write(handle, inode, &iloc); - if (err) - goto out_err; - - if (prev == &sbi->s_orphan) { -- jbd_debug(4, "superblock will point to %ld\n", ino_next); -+ jbd_debug(4, "superblock will point to %lu\n", ino_next); - BUFFER_TRACE(sbi->s_sbh, "get_write_access"); - err = ext3_journal_get_write_access(handle, sbi->s_sbh); - if (err) -@@ -1850,8 +1850,8 @@ int ext3_orphan_del(handle_t *handle, st - struct ext3_iloc iloc2; - struct inode *i_prev = - list_entry(prev, struct inode, u.ext3_i.i_orphan); -- -- jbd_debug(4, "orphan inode %ld will point to %ld\n", -+ -+ jbd_debug(4, "orphan inode %lu will point to %lu\n", - i_prev->i_ino, ino_next); - err = ext3_reserve_inode_write(handle, i_prev, &iloc2); - if (err) -@@ -1866,7 +1866,7 @@ int ext3_orphan_del(handle_t *handle, st - if (err) - goto out_brelse; - --out_err: -+out_err: - ext3_std_error(inode->i_sb, err); - out: - unlock_super(inode->i_sb); ---- linux-2.4.20/include/linux/ext3_fs.h~ext3-2.4-ino_t 2003-04-08 23:35:24.000000000 -0600 -+++ linux-2.4.20-braam/include/linux/ext3_fs.h 2003-04-08 23:35:24.000000000 -0600 -@@ -673,7 +673,7 @@ extern int ext3fs_dirhash(const char *na - /* ialloc.c */ - extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int); - extern void ext3_free_inode (handle_t *, struct inode *); --extern struct inode * ext3_orphan_get (struct super_block *, ino_t); -+extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); - extern unsigned long ext3_count_free_inodes (struct super_block *); - extern void ext3_check_inodes_bitmap (struct super_block *); - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - -_ diff --git a/lustre/kernel_patches/patches/ext3-2.4.20-fixes.patch b/lustre/kernel_patches/patches/ext3-2.4.20-fixes.patch deleted file mode 100644 index 5f566de..0000000 --- a/lustre/kernel_patches/patches/ext3-2.4.20-fixes.patch +++ /dev/null @@ -1,118 +0,0 @@ - - - - fs/ext3/balloc.c | 53 +++++++++++++++++++++++++++++++---------------------- - 1 files changed, 31 insertions(+), 22 deletions(-) - ---- linux-2.4.20/fs/ext3/balloc.c~ext3-2.4.20-fixes 2003-04-08 23:35:17.000000000 -0600 -+++ linux-2.4.20-braam/fs/ext3/balloc.c 2003-04-08 23:35:17.000000000 -0600 -@@ -276,7 +276,8 @@ void ext3_free_blocks (handle_t *handle, - } - lock_super (sb); - es = sb->u.ext3_sb.s_es; -- if (block < le32_to_cpu(es->s_first_data_block) || -+ if (block < le32_to_cpu(es->s_first_data_block) || -+ block + count < block || - (block + count) > le32_to_cpu(es->s_blocks_count)) { - ext3_error (sb, "ext3_free_blocks", - "Freeing blocks not in datazone - " -@@ -309,17 +310,6 @@ do_more: - if (!gdp) - goto error_return; - -- if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) || -- in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) || -- in_range (block, le32_to_cpu(gdp->bg_inode_table), -- sb->u.ext3_sb.s_itb_per_group) || -- in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table), -- sb->u.ext3_sb.s_itb_per_group)) -- ext3_error (sb, "ext3_free_blocks", -- "Freeing blocks in system zones - " -- "Block = %lu, count = %lu", -- block, count); -- - /* - * We are about to start releasing blocks in the bitmap, - * so we need undo access. -@@ -345,14 +335,24 @@ do_more: - if (err) - goto error_return; - -- for (i = 0; i < count; i++) { -+ for (i = 0; i < count; i++, block++) { -+ if (block == le32_to_cpu(gdp->bg_block_bitmap) || -+ block == le32_to_cpu(gdp->bg_inode_bitmap) || -+ in_range(block, le32_to_cpu(gdp->bg_inode_table), -+ EXT3_SB(sb)->s_itb_per_group)) { -+ ext3_error(sb, __FUNCTION__, -+ "Freeing block in system zone - block = %lu", -+ block); -+ continue; -+ } -+ - /* - * An HJ special. This is expensive... - */ - #ifdef CONFIG_JBD_DEBUG - { - struct buffer_head *debug_bh; -- debug_bh = sb_get_hash_table(sb, block + i); -+ debug_bh = sb_get_hash_table(sb, block); - if (debug_bh) { - BUFFER_TRACE(debug_bh, "Deleted!"); - if (!bh2jh(bitmap_bh)->b_committed_data) -@@ -365,9 +365,8 @@ do_more: - #endif - BUFFER_TRACE(bitmap_bh, "clear bit"); - if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) { -- ext3_error (sb, __FUNCTION__, -- "bit already cleared for block %lu", -- block + i); -+ ext3_error(sb, __FUNCTION__, -+ "bit already cleared for block %lu", block); - BUFFER_TRACE(bitmap_bh, "bit already cleared"); - } else { - dquot_freed_blocks++; -@@ -415,7 +414,6 @@ do_more: - if (!err) err = ret; - - if (overflow && !err) { -- block += count; - count = overflow; - goto do_more; - } -@@ -576,6 +574,7 @@ int ext3_new_block (handle_t *handle, st - - ext3_debug ("goal=%lu.\n", goal); - -+repeat: - /* - * First, test whether the goal block is free. - */ -@@ -684,10 +683,20 @@ got_block: - if (tmp == le32_to_cpu(gdp->bg_block_bitmap) || - tmp == le32_to_cpu(gdp->bg_inode_bitmap) || - in_range (tmp, le32_to_cpu(gdp->bg_inode_table), -- sb->u.ext3_sb.s_itb_per_group)) -- ext3_error (sb, "ext3_new_block", -- "Allocating block in system zone - " -- "block = %u", tmp); -+ EXT3_SB(sb)->s_itb_per_group)) { -+ ext3_error(sb, __FUNCTION__, -+ "Allocating block in system zone - block = %u", tmp); -+ -+ /* Note: This will potentially use up one of the handle's -+ * buffer credits. Normally we have way too many credits, -+ * so that is OK. In _very_ rare cases it might not be OK. -+ * We will trigger an assertion if we run out of credits, -+ * and we will have to do a full fsck of the filesystem - -+ * better than randomly corrupting filesystem metadata. -+ */ -+ ext3_set_bit(j, bh->b_data); -+ goto repeat; -+ } - - /* The superblock lock should guard against anybody else beating - * us to this point! */ - -_ diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20-hp.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20-hp.patch deleted file mode 100644 index 619b845..0000000 --- a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.20-hp.patch +++ /dev/null @@ -1,499 +0,0 @@ - fs/ext3/file.c | 4 - fs/ext3/inode.c | 116 ++++++++++++++++++++++ - fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/ext3_fs.h | 5 - include/linux/ext3_fs_sb.h | 10 + - 5 files changed, 365 insertions(+) - -Index: linux-2.4.20-hp_pnnl39/fs/ext3/super.c -=================================================================== ---- linux-2.4.20-hp_pnnl39.orig/fs/ext3/super.c 2004-11-02 22:16:42.000000000 +0300 -+++ linux-2.4.20-hp_pnnl39/fs/ext3/super.c 2004-11-02 23:47:18.513035128 +0300 -@@ -400,6 +400,221 @@ - } - } - -+#ifdef EXT3_DELETE_THREAD -+/* -+ * Delete inodes in a loop until there are no more to be deleted. -+ * Normally, we run in the background doing the deletes and sleeping again, -+ * and clients just add new inodes to be deleted onto the end of the list. -+ * If someone is concerned about free space (e.g. block allocation or similar) -+ * then they can sleep on s_delete_waiter_queue and be woken up when space -+ * has been freed. -+ */ -+int ext3_delete_thread(void *data) -+{ -+ struct super_block *sb = data; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ struct task_struct *tsk = current; -+ -+ /* Almost like daemonize, but not quite */ -+ exit_mm(current); -+ tsk->session = 1; -+ tsk->pgrp = 1; -+ tsk->tty = NULL; -+ exit_files(current); -+ reparent_to_init(); -+ -+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev)); -+ sigfillset(&tsk->blocked); -+ -+ /*tsk->flags |= PF_KERNTHREAD;*/ -+ -+ INIT_LIST_HEAD(&sbi->s_delete_list); -+ wake_up(&sbi->s_delete_waiter_queue); -+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev)); -+ -+ /* main loop */ -+ for (;;) { -+ wait_event_interruptible(sbi->s_delete_thread_queue, -+ !list_empty(&sbi->s_delete_list) || -+ !test_opt(sb, ASYNCDEL)); -+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n", -+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks); -+ -+ spin_lock(&sbi->s_delete_lock); -+ if (list_empty(&sbi->s_delete_list)) { -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ memset(&sbi->s_delete_list, 0, -+ sizeof(sbi->s_delete_list)); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("delete thread on %s exiting\n", -+ kdevname(sb->s_dev)); -+ wake_up(&sbi->s_delete_waiter_queue); -+ break; -+ } -+ -+ while (!list_empty(&sbi->s_delete_list)) { -+ struct inode *inode=list_entry(sbi->s_delete_list.next, -+ struct inode, i_dentry); -+ unsigned long blocks = inode->i_blocks >> -+ (inode->i_blkbits - 9); -+ -+ list_del_init(&inode->i_dentry); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("%s delete ino %lu blk %lu\n", -+ tsk->comm, inode->i_ino, blocks); -+ -+ iput(inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ sbi->s_delete_blocks -= blocks; -+ sbi->s_delete_inodes--; -+ } -+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) { -+ ext3_warning(sb, __FUNCTION__, -+ "%lu blocks, %lu inodes on list?\n", -+ sbi->s_delete_blocks,sbi->s_delete_inodes); -+ sbi->s_delete_blocks = 0; -+ sbi->s_delete_inodes = 0; -+ } -+ spin_unlock(&sbi->s_delete_lock); -+ wake_up(&sbi->s_delete_waiter_queue); -+ } -+ -+ return 0; -+} -+ -+static void ext3_start_delete_thread(struct super_block *sb) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int rc; -+ -+ spin_lock_init(&sbi->s_delete_lock); -+ init_waitqueue_head(&sbi->s_delete_thread_queue); -+ init_waitqueue_head(&sbi->s_delete_waiter_queue); -+ -+ if (!test_opt(sb, ASYNCDEL)) -+ return; -+ -+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES); -+ if (rc < 0) -+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n", -+ rc); -+ else -+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next); -+} -+ -+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi) -+{ -+ if (sbi->s_delete_list.next == 0) /* thread never started */ -+ return; -+ -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ wake_up(&sbi->s_delete_thread_queue); -+ wait_event(sbi->s_delete_waiter_queue, -+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0); -+} -+ -+/* Instead of playing games with the inode flags, destruction, etc we just -+ * create a new inode locally and put it on a list for the truncate thread. -+ * We need large parts of the inode struct in order to complete the -+ * truncate and unlink, so we may as well just have a real inode to do it. -+ * -+ * If we have any problem deferring the delete, just delete it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+static void ext3_delete_inode_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (is_bad_inode(old_inode)) { -+ clear_inode(old_inode); -+ return; -+ } -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_delete; -+ -+ /* We may want to delete the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS) -+ goto out_delete; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_delete; -+ } -+ -+ /* We can iget this inode again here, because our caller has unhashed -+ * old_inode, so new_inode will be in a different inode struct. -+ * -+ * We need to ensure that the i_orphan pointers in the other inodes -+ * point at the new inode copy instead of the old one so the orphan -+ * list doesn't get corrupted when the old orphan inode is freed. -+ */ -+ down(&sbi->s_orphan_lock); -+ -+ sbi->s_mount_state |= EXT3_ORPHAN_FS; -+ new_inode = iget(old_inode->i_sb, old_inode->i_ino); -+ sbi->s_mount_state &= ~EXT3_ORPHAN_FS; -+ if (is_bad_inode(new_inode)) { -+ printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino); -+ iput(new_inode); -+ new_inode = NULL; -+ } -+ if (!new_inode) { -+ up(&sbi->s_orphan_lock); -+ ext3_debug("delete inode %lu directly (bad read)\n", -+ old_inode->i_ino); -+ goto out_delete; -+ } -+ J_ASSERT(new_inode != old_inode); -+ -+ J_ASSERT(!list_empty(&oei->i_orphan)); -+ -+ nei = EXT3_I(new_inode); -+ /* Ugh. We need to insert new_inode into the same spot on the list -+ * as old_inode was, to ensure the in-memory orphan list is still -+ * in the same order as the on-disk orphan list (badness otherwise). -+ */ -+ nei->i_orphan = oei->i_orphan; -+ nei->i_orphan.next->prev = &nei->i_orphan; -+ nei->i_orphan.prev->next = &nei->i_orphan; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up(&sbi->s_orphan_lock); -+ -+ clear_inode(old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_dentry)); -+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_delete: -+ ext3_delete_inode(old_inode); -+} -+#else -+#define ext3_start_delete_thread(sbi) do {} while(0) -+#define ext3_stop_delete_thread(sbi) do {} while(0) -+#endif /* EXT3_DELETE_THREAD */ -+ - void ext3_put_super (struct super_block * sb) - { - struct ext3_sb_info *sbi = EXT3_SB(sb); -@@ -407,6 +622,9 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+#ifdef EXT3_DELETE_THREAD -+ J_ASSERT(sbi->s_delete_inodes == 0); -+#endif - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -455,7 +673,11 @@ - write_inode: ext3_write_inode, /* BKL not held. Don't need */ - dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */ - put_inode: ext3_put_inode, /* BKL not held. Don't need */ -- delete_inode: ext3_delete_inode, /* BKL not held. We take it */ -+#ifdef EXT3_DELETE_THREAD -+ delete_inode: ext3_delete_inode_thread,/* BKL not held. We take it */ -+#else -+ delete_inode: ext3_delete_inode, /* BKL not held. We take it */ -+#endif - put_super: ext3_put_super, /* BKL held */ - write_super: ext3_write_super, /* BKL held */ - sync_fs: ext3_sync_fs, -@@ -524,6 +746,13 @@ - clear_opt (*mount_options, XATTR_USER); - else - #endif -+#ifdef EXT3_DELETE_THREAD -+ if (!strcmp(this_char, "asyncdel")) -+ set_opt(*mount_options, ASYNCDEL); -+ else if (!strcmp(this_char, "noasyncdel")) -+ clear_opt(*mount_options, ASYNCDEL); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -1223,6 +1452,7 @@ - } - - ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); -+ ext3_start_delete_thread(sb); - /* - * akpm: core read_super() calls in here with the superblock locked. - * That deadlocks, because orphan cleanup needs to lock the superblock -@@ -1614,7 +1844,12 @@ - static int ext3_sync_fs(struct super_block *sb) - { - tid_t target; -- -+ -+ if (atomic_read(&sb->s_active) == 0) { -+ /* fs is being umounted: time to stop delete thread */ -+ ext3_stop_delete_thread(EXT3_SB(sb)); -+ } -+ - sb->s_dirt = 0; - target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); - log_wait_commit(EXT3_SB(sb)->s_journal, target); -@@ -1678,6 +1913,9 @@ - if (!parse_options(data, &tmp, sbi, &tmp, 1)) - return -EINVAL; - -+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY)) -+ ext3_stop_delete_thread(sbi); -+ - if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) - ext3_abort(sb, __FUNCTION__, "Abort forced by user"); - -Index: linux-2.4.20-hp_pnnl39/fs/ext3/inode.c -=================================================================== ---- linux-2.4.20-hp_pnnl39.orig/fs/ext3/inode.c 2004-11-02 22:16:41.000000000 +0300 -+++ linux-2.4.20-hp_pnnl39/fs/ext3/inode.c 2004-11-02 22:16:42.000000000 +0300 -@@ -2500,6 +2500,118 @@ - return err; - } - -+#ifdef EXT3_DELETE_THREAD -+/* Move blocks from to-be-truncated inode over to a new inode, and delete -+ * that one from the delete thread instead. This avoids a lot of latency -+ * when truncating large files. -+ * -+ * If we have any problem deferring the truncate, just truncate it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+void ext3_truncate_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ handle_t *handle; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_truncate; -+ -+ /* XXX This is a temporary limitation for code simplicity. -+ * We could truncate to arbitrary sizes at some later time. -+ */ -+ if (old_inode->i_size != 0) -+ goto out_truncate; -+ -+ /* We may want to truncate the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS || -+ old_inode->i_size > oei->i_disksize) -+ goto out_truncate; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_truncate; -+ } -+ -+ ext3_discard_prealloc(old_inode); -+ -+ /* old_inode = 1 -+ * new_inode = sb + GDT + ibitmap -+ * orphan list = 1 inode/superblock for add, 2 inodes for del -+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS -+ */ -+ handle = ext3_journal_start(old_inode, 7); -+ if (IS_ERR(handle)) -+ goto out_truncate; -+ -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ if (IS_ERR(new_inode)) { -+ ext3_debug("truncate inode %lu directly (no new inodes)\n", -+ old_inode->i_ino); -+ goto out_journal; -+ } -+ -+ nei = EXT3_I(new_inode); -+ -+ down_write(&oei->truncate_sem); -+ new_inode->i_size = old_inode->i_size; -+ new_inode->i_blocks = old_inode->i_blocks; -+ new_inode->i_uid = old_inode->i_uid; -+ new_inode->i_gid = old_inode->i_gid; -+ new_inode->i_nlink = 0; -+ -+ /* FIXME when we do arbitrary truncates */ -+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0; -+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME; -+ -+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); -+ memset(oei->i_data, 0, sizeof(oei->i_data)); -+ -+ nei->i_disksize = oei->i_disksize; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up_write(&oei->truncate_sem); -+ -+ if (ext3_orphan_add(handle, new_inode) < 0) -+ goto out_journal; -+ -+ if (ext3_orphan_del(handle, old_inode) < 0) { -+ ext3_orphan_del(handle, new_inode); -+ iput(new_inode); -+ goto out_journal; -+ } -+ -+ ext3_journal_stop(handle, old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_dentry)); -+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_journal: -+ ext3_journal_stop(handle, old_inode); -+out_truncate: -+ ext3_truncate(old_inode); -+} -+#endif /* EXT3_DELETE_THREAD */ -+ - /* - * On success, We end up with an outstanding reference count against - * iloc->bh. This _must_ be cleaned up later. -Index: linux-2.4.20-hp_pnnl39/fs/ext3/file.c -=================================================================== ---- linux-2.4.20-hp_pnnl39.orig/fs/ext3/file.c 2004-11-02 22:16:41.000000000 +0300 -+++ linux-2.4.20-hp_pnnl39/fs/ext3/file.c 2004-11-02 22:16:42.132490592 +0300 -@@ -125,7 +125,11 @@ - }; - - struct inode_operations ext3_file_inode_operations = { -+#ifdef EXT3_DELETE_THREAD -+ truncate: ext3_truncate_thread, /* BKL held */ -+#else - truncate: ext3_truncate, /* BKL held */ -+#endif - setattr: ext3_setattr, /* BKL held */ - setxattr: ext3_setxattr, /* BKL held */ - getxattr: ext3_getxattr, /* BKL held */ -Index: linux-2.4.20-hp_pnnl39/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.20-hp_pnnl39.orig/include/linux/ext3_fs.h 2004-11-02 22:16:41.000000000 +0300 -+++ linux-2.4.20-hp_pnnl39/include/linux/ext3_fs.h 2004-11-02 22:16:42.000000000 +0300 -@@ -193,6 +193,7 @@ - */ - #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */ - #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */ -+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */ - - /* - * ioctl commands -@@ -320,6 +321,7 @@ - #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ -+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -694,6 +696,9 @@ - extern void ext3_dirty_inode(struct inode *); - extern int ext3_change_inode_journal_flag(struct inode *, int); - extern void ext3_truncate (struct inode *); -+#ifdef EXT3_DELETE_THREAD -+extern void ext3_truncate_thread(struct inode *inode); -+#endif - - /* ioctl.c */ - extern int ext3_ioctl (struct inode *, struct file *, unsigned int, -Index: linux-2.4.20-hp_pnnl39/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.20-hp_pnnl39.orig/include/linux/ext3_fs_sb.h 2004-11-02 22:16:42.000000000 +0300 -+++ linux-2.4.20-hp_pnnl39/include/linux/ext3_fs_sb.h 2004-11-02 23:43:11.521583536 +0300 -@@ -29,6 +29,8 @@ - - #define EXT3_MAX_GROUP_LOADED 8 - -+#define EXT3_DELETE_THREAD -+ - /* - * third extended-fs super-block data in memory - */ -@@ -76,6 +78,14 @@ - struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */ - wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */ - #endif -+#ifdef EXT3_DELETE_THREAD -+ spinlock_t s_delete_lock; -+ struct list_head s_delete_list; -+ unsigned long s_delete_blocks; -+ unsigned long s_delete_inodes; -+ wait_queue_head_t s_delete_thread_queue; -+ wait_queue_head_t s_delete_waiter_queue; -+#endif - }; - - #endif /* _LINUX_EXT3_FS_SB */ diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-chaos.patch deleted file mode 100644 index 6d6720d..0000000 --- a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-chaos.patch +++ /dev/null @@ -1,449 +0,0 @@ - fs/ext3/file.c | 4 - fs/ext3/inode.c | 116 ++++++++++++++++++++++ - fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/ext3_fs.h | 5 - include/linux/ext3_fs_sb.h | 10 + - 5 files changed, 365 insertions(+) - -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2004-01-12 19:20:07.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2004-01-13 17:25:49.000000000 +0300 -@@ -425,6 +425,127 @@ - } - } - -+#ifdef EXT3_DELETE_THREAD -+/* -+ * Delete inodes in a loop until there are no more to be deleted. -+ * Normally, we run in the background doing the deletes and sleeping again, -+ * and clients just add new inodes to be deleted onto the end of the list. -+ * If someone is concerned about free space (e.g. block allocation or similar) -+ * then they can sleep on s_delete_waiter_queue and be woken up when space -+ * has been freed. -+ */ -+int ext3_delete_thread(void *data) -+{ -+ struct super_block *sb = data; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ struct task_struct *tsk = current; -+ -+ /* Almost like daemonize, but not quite */ -+ exit_mm(current); -+ tsk->session = 1; -+ tsk->pgrp = 1; -+ tsk->tty = NULL; -+ exit_files(current); -+ reparent_to_init(); -+ -+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev)); -+ sigfillset(&tsk->blocked); -+ -+ /*tsk->flags |= PF_KERNTHREAD;*/ -+ -+ INIT_LIST_HEAD(&sbi->s_delete_list); -+ wake_up(&sbi->s_delete_waiter_queue); -+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev)); -+ -+ /* main loop */ -+ for (;;) { -+ wait_event_interruptible(sbi->s_delete_thread_queue, -+ !list_empty(&sbi->s_delete_list) || -+ !test_opt(sb, ASYNCDEL)); -+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n", -+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks); -+ -+ spin_lock(&sbi->s_delete_lock); -+ if (list_empty(&sbi->s_delete_list)) { -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ memset(&sbi->s_delete_list, 0, -+ sizeof(sbi->s_delete_list)); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("delete thread on %s exiting\n", -+ kdevname(sb->s_dev)); -+ wake_up(&sbi->s_delete_waiter_queue); -+ break; -+ } -+ -+ while (!list_empty(&sbi->s_delete_list)) { -+ struct inode *inode=list_entry(sbi->s_delete_list.next, -+ struct inode, i_devices); -+ unsigned long blocks = inode->i_blocks >> -+ (inode->i_blkbits - 9); -+ -+ list_del_init(&inode->i_devices); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("%s delete ino %lu blk %lu\n", -+ tsk->comm, inode->i_ino, blocks); -+ -+ J_ASSERT(EXT3_I(inode)->i_state & EXT3_STATE_DELETE); -+ J_ASSERT(inode->i_nlink == 1); -+ inode->i_nlink = 0; -+ iput(inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ sbi->s_delete_blocks -= blocks; -+ sbi->s_delete_inodes--; -+ } -+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) { -+ ext3_warning(sb, __FUNCTION__, -+ "%lu blocks, %lu inodes on list?\n", -+ sbi->s_delete_blocks,sbi->s_delete_inodes); -+ sbi->s_delete_blocks = 0; -+ sbi->s_delete_inodes = 0; -+ } -+ spin_unlock(&sbi->s_delete_lock); -+ wake_up(&sbi->s_delete_waiter_queue); -+ } -+ -+ return 0; -+} -+ -+static void ext3_start_delete_thread(struct super_block *sb) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int rc; -+ -+ spin_lock_init(&sbi->s_delete_lock); -+ init_waitqueue_head(&sbi->s_delete_thread_queue); -+ init_waitqueue_head(&sbi->s_delete_waiter_queue); -+ -+ if (!test_opt(sb, ASYNCDEL)) -+ return; -+ -+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES); -+ if (rc < 0) -+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n", -+ rc); -+ else -+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next); -+} -+ -+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi) -+{ -+ if (sbi->s_delete_list.next == 0) /* thread never started */ -+ return; -+ -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ wake_up(&sbi->s_delete_thread_queue); -+ wait_event(sbi->s_delete_waiter_queue, -+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0); -+} -+#else -+#define ext3_start_delete_thread(sbi) do {} while(0) -+#define ext3_stop_delete_thread(sbi) do {} while(0) -+#endif /* EXT3_DELETE_THREAD */ -+ - void ext3_put_super (struct super_block * sb) - { - struct ext3_sb_info *sbi = EXT3_SB(sb); -@@ -432,6 +647,9 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+#ifdef EXT3_DELETE_THREAD -+ J_ASSERT(sbi->s_delete_inodes == 0); -+#endif - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -579,6 +799,13 @@ - *mount_flags &= ~MS_POSIXACL; - else - #endif -+#ifdef EXT3_DELETE_THREAD -+ if (!strcmp(this_char, "asyncdel")) -+ set_opt(*mount_options, ASYNCDEL); -+ else if (!strcmp(this_char, "noasyncdel")) -+ clear_opt(*mount_options, ASYNCDEL); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -1283,6 +1510,7 @@ - } - - ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); -+ ext3_start_delete_thread(sb); - /* - * akpm: core read_super() calls in here with the superblock locked. - * That deadlocks, because orphan cleanup needs to lock the superblock -@@ -1676,7 +1904,12 @@ - static int ext3_sync_fs(struct super_block *sb) - { - tid_t target; -- -+ -+ if (atomic_read(&sb->s_active) == 0) { -+ /* fs is being umounted: time to stop delete thread */ -+ ext3_stop_delete_thread(EXT3_SB(sb)); -+ } -+ - sb->s_dirt = 0; - target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); - log_wait_commit(EXT3_SB(sb)->s_journal, target); -@@ -1746,6 +1979,9 @@ - if (!parse_options(data, &tmp, sbi, &mount_flags, &tmp, 1)) - return -EINVAL; - -+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY)) -+ ext3_stop_delete_thread(sbi); -+ - if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) - ext3_abort(sb, __FUNCTION__, "Abort forced by user"); - -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2004-01-12 19:20:06.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2004-01-12 19:20:07.000000000 +0300 -@@ -2179,6 +2179,118 @@ - return; /* AKPM: return what? */ - } - -+#ifdef EXT3_DELETE_THREAD -+/* Move blocks from to-be-truncated inode over to a new inode, and delete -+ * that one from the delete thread instead. This avoids a lot of latency -+ * when truncating large files. -+ * -+ * If we have any problem deferring the truncate, just truncate it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+void ext3_truncate_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ handle_t *handle; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_truncate; -+ -+ /* XXX This is a temporary limitation for code simplicity. -+ * We could truncate to arbitrary sizes at some later time. -+ */ -+ if (old_inode->i_size != 0) -+ goto out_truncate; -+ -+ /* We may want to truncate the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS || -+ old_inode->i_size > oei->i_disksize) -+ goto out_truncate; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_truncate; -+ } -+ -+ ext3_discard_prealloc(old_inode); -+ -+ /* old_inode = 1 -+ * new_inode = sb + GDT + ibitmap -+ * orphan list = 1 inode/superblock for add, 2 inodes for del -+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS -+ */ -+ handle = ext3_journal_start(old_inode, 7); -+ if (IS_ERR(handle)) -+ goto out_truncate; -+ -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ if (IS_ERR(new_inode)) { -+ ext3_debug("truncate inode %lu directly (no new inodes)\n", -+ old_inode->i_ino); -+ goto out_journal; -+ } -+ -+ nei = EXT3_I(new_inode); -+ -+ down_write(&oei->truncate_sem); -+ new_inode->i_size = old_inode->i_size; -+ new_inode->i_blocks = old_inode->i_blocks; -+ new_inode->i_uid = old_inode->i_uid; -+ new_inode->i_gid = old_inode->i_gid; -+ new_inode->i_nlink = 1; -+ -+ /* FIXME when we do arbitrary truncates */ -+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0; -+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME; -+ -+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); -+ memset(oei->i_data, 0, sizeof(oei->i_data)); -+ -+ nei->i_disksize = oei->i_disksize; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up_write(&oei->truncate_sem); -+ -+ if (ext3_orphan_add(handle, new_inode) < 0) -+ goto out_journal; -+ -+ if (ext3_orphan_del(handle, old_inode) < 0) { -+ ext3_orphan_del(handle, new_inode); -+ iput(new_inode); -+ goto out_journal; -+ } -+ -+ ext3_journal_stop(handle, old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_devices)); -+ list_add_tail(&new_inode->i_devices, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_journal: -+ ext3_journal_stop(handle, old_inode); -+out_truncate: -+ ext3_truncate(old_inode); -+} -+#endif /* EXT3_DELETE_THREAD */ -+ - /* - * ext3_get_inode_loc returns with an extra refcount against the - * inode's underlying buffer_head on success. -Index: linux-2.4.21-chaos/fs/ext3/file.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/file.c 2004-01-12 19:20:06.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/file.c 2004-01-12 19:20:07.000000000 +0300 -@@ -132,7 +132,11 @@ - }; - - struct inode_operations ext3_file_inode_operations = { -+#ifdef EXT3_DELETE_THREAD -+ truncate: ext3_truncate_thread, /* BKL held */ -+#else - truncate: ext3_truncate, /* BKL held */ -+#endif - setattr: ext3_setattr, /* BKL held */ - setxattr: ext3_setxattr, /* BKL held */ - getxattr: ext3_getxattr, /* BKL held */ -Index: linux-2.4.21-chaos/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/namei.c 2004-01-12 20:36:31.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/namei.c 2004-01-12 20:36:32.000000000 +0300 -@@ -1936,6 +1936,40 @@ - return retval; - } - -+#ifdef EXT3_DELETE_THREAD -+static int ext3_try_to_delay_deletion(struct inode *inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb); -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long blocks; -+ -+ if (!test_opt(inode->i_sb, ASYNCDEL)) -+ return 0; -+ -+ /* We may want to delete the inode immediately and not defer it */ -+ blocks = inode->i_blocks >> (inode->i_blkbits - 9); -+ if (IS_SYNC(inode) || blocks <= EXT3_NDIR_BLOCKS) -+ return 0; -+ -+ inode->i_nlink = 1; -+ atomic_inc(&inode->i_count); -+ ei->i_state |= EXT3_STATE_DELETE; -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&inode->i_devices)); -+ list_add_tail(&inode->i_devices, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ -+ return 0; -+} -+#else -+#define ext3_try_to_delay_deletion(inode) do {} while (0) -+#endif -+ - static int ext3_unlink(struct inode * dir, struct dentry *dentry) - { - int retval; -@@ -1977,8 +2007,10 @@ - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; -- if (!inode->i_nlink) -+ if (!inode->i_nlink) { -+ ext3_try_to_delay_deletion(inode); - ext3_orphan_add(handle, inode); -+ } - inode->i_ctime = dir->i_ctime; - ext3_mark_inode_dirty(handle, inode); - retval = 0; -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2004-01-12 19:20:06.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2004-01-12 19:20:07.000000000 +0300 -@@ -195,6 +195,7 @@ - */ - #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */ - #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */ -+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */ - - /* - * ioctl commands -@@ -323,6 +324,7 @@ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - #define EXT3_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ -+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -697,6 +699,9 @@ - extern void ext3_dirty_inode(struct inode *); - extern int ext3_change_inode_journal_flag(struct inode *, int); - extern void ext3_truncate (struct inode *); -+#ifdef EXT3_DELETE_THREAD -+extern void ext3_truncate_thread(struct inode *inode); -+#endif - extern void ext3_set_inode_flags(struct inode *); - - /* ioctl.c */ -Index: linux-2.4.21-chaos/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs_sb.h 2004-01-12 19:20:07.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs_sb.h 2004-01-12 20:53:51.000000000 +0300 -@@ -29,6 +29,8 @@ - - #define EXT3_MAX_GROUP_LOADED 32 - -+#define EXT3_DELETE_THREAD -+ - /* - * third extended-fs super-block data in memory - */ -@@ -76,6 +78,14 @@ - struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */ - wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */ - #endif -+#ifdef EXT3_DELETE_THREAD -+ spinlock_t s_delete_lock; -+ struct list_head s_delete_list; -+ unsigned long s_delete_blocks; -+ unsigned long s_delete_inodes; -+ wait_queue_head_t s_delete_thread_queue; -+ wait_queue_head_t s_delete_waiter_queue; -+#endif - }; - - #endif /* _LINUX_EXT3_FS_SB */ diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-suse-171.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-suse-171.patch deleted file mode 100644 index 7eb6442..0000000 --- a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.21-suse-171.patch +++ /dev/null @@ -1,496 +0,0 @@ - fs/ext3/file.c | 4 - fs/ext3/inode.c | 116 ++++++++++++++++++++++ - fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/ext3_fs.h | 5 - include/linux/ext3_fs_sb.h | 10 + - 5 files changed, 365 insertions(+) - -Index: linux-2.4.21-241/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/super.c 2004-10-04 02:48:16.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/super.c 2004-10-04 02:48:18.000000000 -0400 -@@ -401,6 +401,221 @@ - } - } - -+#ifdef EXT3_DELETE_THREAD -+/* -+ * Delete inodes in a loop until there are no more to be deleted. -+ * Normally, we run in the background doing the deletes and sleeping again, -+ * and clients just add new inodes to be deleted onto the end of the list. -+ * If someone is concerned about free space (e.g. block allocation or similar) -+ * then they can sleep on s_delete_waiter_queue and be woken up when space -+ * has been freed. -+ */ -+int ext3_delete_thread(void *data) -+{ -+ struct super_block *sb = data; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ struct task_struct *tsk = current; -+ -+ /* Almost like daemonize, but not quite */ -+ exit_mm(current); -+ tsk->session = 1; -+ tsk->pgrp = 1; -+ tsk->tty = NULL; -+ exit_files(current); -+ reparent_to_init(); -+ -+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev)); -+ sigfillset(&tsk->blocked); -+ -+ /*tsk->flags |= PF_KERNTHREAD;*/ -+ -+ INIT_LIST_HEAD(&sbi->s_delete_list); -+ wake_up(&sbi->s_delete_waiter_queue); -+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev)); -+ -+ /* main loop */ -+ for (;;) { -+ wait_event_interruptible(sbi->s_delete_thread_queue, -+ !list_empty(&sbi->s_delete_list) || -+ !test_opt(sb, ASYNCDEL)); -+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n", -+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks); -+ -+ spin_lock(&sbi->s_delete_lock); -+ if (list_empty(&sbi->s_delete_list)) { -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ memset(&sbi->s_delete_list, 0, -+ sizeof(sbi->s_delete_list)); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("delete thread on %s exiting\n", -+ kdevname(sb->s_dev)); -+ wake_up(&sbi->s_delete_waiter_queue); -+ break; -+ } -+ -+ while (!list_empty(&sbi->s_delete_list)) { -+ struct inode *inode=list_entry(sbi->s_delete_list.next, -+ struct inode, i_dentry); -+ unsigned long blocks = inode->i_blocks >> -+ (inode->i_blkbits - 9); -+ -+ list_del_init(&inode->i_dentry); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("%s delete ino %lu blk %lu\n", -+ tsk->comm, inode->i_ino, blocks); -+ -+ iput(inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ sbi->s_delete_blocks -= blocks; -+ sbi->s_delete_inodes--; -+ } -+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) { -+ ext3_warning(sb, __FUNCTION__, -+ "%lu blocks, %lu inodes on list?\n", -+ sbi->s_delete_blocks,sbi->s_delete_inodes); -+ sbi->s_delete_blocks = 0; -+ sbi->s_delete_inodes = 0; -+ } -+ spin_unlock(&sbi->s_delete_lock); -+ wake_up(&sbi->s_delete_waiter_queue); -+ } -+ -+ return 0; -+} -+ -+static void ext3_start_delete_thread(struct super_block *sb) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int rc; -+ -+ spin_lock_init(&sbi->s_delete_lock); -+ init_waitqueue_head(&sbi->s_delete_thread_queue); -+ init_waitqueue_head(&sbi->s_delete_waiter_queue); -+ -+ if (!test_opt(sb, ASYNCDEL)) -+ return; -+ -+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES); -+ if (rc < 0) -+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n", -+ rc); -+ else -+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next); -+} -+ -+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi) -+{ -+ if (sbi->s_delete_list.next == 0) /* thread never started */ -+ return; -+ -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ wake_up(&sbi->s_delete_thread_queue); -+ wait_event(sbi->s_delete_waiter_queue, -+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0); -+} -+ -+/* Instead of playing games with the inode flags, destruction, etc we just -+ * create a new inode locally and put it on a list for the truncate thread. -+ * We need large parts of the inode struct in order to complete the -+ * truncate and unlink, so we may as well just have a real inode to do it. -+ * -+ * If we have any problem deferring the delete, just delete it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+static void ext3_delete_inode_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (is_bad_inode(old_inode)) { -+ clear_inode(old_inode); -+ return; -+ } -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_delete; -+ -+ /* We may want to delete the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS) -+ goto out_delete; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_delete; -+ } -+ -+ /* We can iget this inode again here, because our caller has unhashed -+ * old_inode, so new_inode will be in a different inode struct. -+ * -+ * We need to ensure that the i_orphan pointers in the other inodes -+ * point at the new inode copy instead of the old one so the orphan -+ * list doesn't get corrupted when the old orphan inode is freed. -+ */ -+ down(&sbi->s_orphan_lock); -+ -+ sbi->s_mount_state |= EXT3_ORPHAN_FS; -+ new_inode = iget(old_inode->i_sb, old_inode->i_ino); -+ sbi->s_mount_state &= ~EXT3_ORPHAN_FS; -+ if (is_bad_inode(new_inode)) { -+ printk(KERN_WARNING "read bad inode %lu\n", old_inode->i_ino); -+ iput(new_inode); -+ new_inode = NULL; -+ } -+ if (!new_inode) { -+ up(&sbi->s_orphan_lock); -+ ext3_debug("delete inode %lu directly (bad read)\n", -+ old_inode->i_ino); -+ goto out_delete; -+ } -+ J_ASSERT(new_inode != old_inode); -+ -+ J_ASSERT(!list_empty(&oei->i_orphan)); -+ -+ nei = EXT3_I(new_inode); -+ /* Ugh. We need to insert new_inode into the same spot on the list -+ * as old_inode was, to ensure the in-memory orphan list is still -+ * in the same order as the on-disk orphan list (badness otherwise). -+ */ -+ nei->i_orphan = oei->i_orphan; -+ nei->i_orphan.next->prev = &nei->i_orphan; -+ nei->i_orphan.prev->next = &nei->i_orphan; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up(&sbi->s_orphan_lock); -+ -+ clear_inode(old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_dentry)); -+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_delete: -+ ext3_delete_inode(old_inode); -+} -+#else -+#define ext3_start_delete_thread(sbi) do {} while(0) -+#define ext3_stop_delete_thread(sbi) do {} while(0) -+#endif /* EXT3_DELETE_THREAD */ -+ - void ext3_put_super (struct super_block * sb) - { - struct ext3_sb_info *sbi = EXT3_SB(sb); -@@ -408,6 +623,7 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+ J_ASSERT(sbi->s_delete_inodes == 0); - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -479,7 +695,11 @@ - write_inode: ext3_write_inode, /* BKL not held. Don't need */ - dirty_inode: ext3_dirty_inode, /* BKL not held. We take it */ - put_inode: ext3_put_inode, /* BKL not held. Don't need */ -+#ifdef EXT3_DELETE_THREAD -+ delete_inode: ext3_delete_inode_thread,/* BKL not held. We take it */ -+#else - delete_inode: ext3_delete_inode, /* BKL not held. We take it */ -+#endif - put_super: ext3_put_super, /* BKL held */ - write_super: ext3_write_super, /* BKL held */ - sync_fs: ext3_sync_fs, -@@ -557,6 +777,13 @@ - *mount_flags &= ~MS_POSIXACL; - else - #endif -+#ifdef EXT3_DELETE_THREAD -+ if (!strcmp(this_char, "asyncdel")) -+ set_opt(*mount_options, ASYNCDEL); -+ else if (!strcmp(this_char, "noasyncdel")) -+ clear_opt(*mount_options, ASYNCDEL); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -1261,6 +1488,7 @@ - } - - ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); -+ ext3_start_delete_thread(sb); - /* - * akpm: core read_super() calls in here with the superblock locked. - * That deadlocks, because orphan cleanup needs to lock the superblock -@@ -1652,7 +1880,12 @@ - static int ext3_sync_fs(struct super_block *sb) - { - tid_t target; -- -+ -+ if (atomic_read(&sb->s_active) == 0) { -+ /* fs is being umounted: time to stop delete thread */ -+ ext3_stop_delete_thread(EXT3_SB(sb)); -+ } -+ - sb->s_dirt = 0; - target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); - log_wait_commit(EXT3_SB(sb)->s_journal, target); -@@ -1716,6 +1949,9 @@ - if (!parse_options(data, &tmp, sbi, &mount_flags, &tmp, 1)) - return -EINVAL; - -+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY)) -+ ext3_stop_delete_thread(sbi); -+ - if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) - ext3_abort(sb, __FUNCTION__, "Abort forced by user"); - -Index: linux-2.4.21-241/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/inode.c 2004-10-04 02:48:17.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/inode.c 2004-10-04 02:48:18.000000000 -0400 -@@ -2694,6 +2694,118 @@ - return err; - } - -+#ifdef EXT3_DELETE_THREAD -+/* Move blocks from to-be-truncated inode over to a new inode, and delete -+ * that one from the delete thread instead. This avoids a lot of latency -+ * when truncating large files. -+ * -+ * If we have any problem deferring the truncate, just truncate it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+void ext3_truncate_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ handle_t *handle; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_truncate; -+ -+ /* XXX This is a temporary limitation for code simplicity. -+ * We could truncate to arbitrary sizes at some later time. -+ */ -+ if (old_inode->i_size != 0) -+ goto out_truncate; -+ -+ /* We may want to truncate the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS || -+ old_inode->i_size > oei->i_disksize) -+ goto out_truncate; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_truncate; -+ } -+ -+ ext3_discard_prealloc(old_inode); -+ -+ /* old_inode = 1 -+ * new_inode = sb + GDT + ibitmap -+ * orphan list = 1 inode/superblock for add, 2 inodes for del -+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS -+ */ -+ handle = ext3_journal_start(old_inode, 7); -+ if (IS_ERR(handle)) -+ goto out_truncate; -+ -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ if (IS_ERR(new_inode)) { -+ ext3_debug("truncate inode %lu directly (no new inodes)\n", -+ old_inode->i_ino); -+ goto out_journal; -+ } -+ -+ nei = EXT3_I(new_inode); -+ -+ down_write(&oei->truncate_sem); -+ new_inode->i_size = old_inode->i_size; -+ new_inode->i_blocks = old_inode->i_blocks; -+ new_inode->i_uid = old_inode->i_uid; -+ new_inode->i_gid = old_inode->i_gid; -+ new_inode->i_nlink = 0; -+ -+ /* FIXME when we do arbitrary truncates */ -+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0; -+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME; -+ -+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); -+ memset(oei->i_data, 0, sizeof(oei->i_data)); -+ -+ nei->i_disksize = oei->i_disksize; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up_write(&oei->truncate_sem); -+ -+ if (ext3_orphan_add(handle, new_inode) < 0) -+ goto out_journal; -+ -+ if (ext3_orphan_del(handle, old_inode) < 0) { -+ ext3_orphan_del(handle, new_inode); -+ iput(new_inode); -+ goto out_journal; -+ } -+ -+ ext3_journal_stop(handle, old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_dentry)); -+ list_add_tail(&new_inode->i_dentry, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_journal: -+ ext3_journal_stop(handle, old_inode); -+out_truncate: -+ ext3_truncate(old_inode); -+} -+#endif /* EXT3_DELETE_THREAD */ -+ - /* - * On success, We end up with an outstanding reference count against - * iloc->bh. This _must_ be cleaned up later. -Index: linux-2.4.21-241/fs/ext3/file.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/file.c 2004-10-04 02:48:13.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/file.c 2004-10-04 02:48:18.000000000 -0400 -@@ -132,7 +132,11 @@ - }; - - struct inode_operations ext3_file_inode_operations = { -+#ifdef EXT3_DELETE_THREAD -+ truncate: ext3_truncate_thread, /* BKL held */ -+#else - truncate: ext3_truncate, /* BKL held */ -+#endif - setattr: ext3_setattr, /* BKL held */ - setxattr: ext3_setxattr, /* BKL held */ - getxattr: ext3_getxattr, /* BKL held */ -Index: linux-2.4.21-241/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-241.orig/include/linux/ext3_fs.h 2004-10-04 02:48:17.000000000 -0400 -+++ linux-2.4.21-241/include/linux/ext3_fs.h 2004-10-04 02:48:18.000000000 -0400 -@@ -193,6 +193,7 @@ - */ - #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */ - #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */ -+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */ - - /* - * ioctl commands -@@ -321,6 +322,7 @@ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - #define EXT3_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ -+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -699,6 +701,9 @@ - extern int ext3_change_inode_journal_flag(struct inode *, int); - extern void ext3_truncate (struct inode *); - extern void ext3_set_inode_flags(struct inode *); -+#ifdef EXT3_DELETE_THREAD -+extern void ext3_truncate_thread(struct inode *inode); -+#endif - - /* ioctl.c */ - extern int ext3_ioctl (struct inode *, struct file *, unsigned int, -Index: linux-2.4.21-241/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.21-241.orig/include/linux/ext3_fs_sb.h 2004-10-04 02:48:16.000000000 -0400 -+++ linux-2.4.21-241/include/linux/ext3_fs_sb.h 2004-10-04 02:48:18.000000000 -0400 -@@ -29,6 +29,8 @@ - - #define EXT3_MAX_GROUP_LOADED 8 - -+#define EXT3_DELETE_THREAD -+ - /* - * third extended-fs super-block data in memory - */ -@@ -76,6 +78,14 @@ - struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */ - wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */ - #endif -+#ifdef EXT3_DELETE_THREAD -+ spinlock_t s_delete_lock; -+ struct list_head s_delete_list; -+ unsigned long s_delete_blocks; -+ unsigned long s_delete_inodes; -+ wait_queue_head_t s_delete_thread_queue; -+ wait_queue_head_t s_delete_waiter_queue; -+#endif - }; - - #endif /* _LINUX_EXT3_FS_SB */ diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.24.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.24.patch deleted file mode 100644 index 61bad1b..0000000 --- a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.24.patch +++ /dev/null @@ -1,449 +0,0 @@ - fs/ext3/file.c | 4 - fs/ext3/inode.c | 116 ++++++++++++++++++++++ - fs/ext3/super.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/ext3_fs.h | 5 - include/linux/ext3_fs_sb.h | 10 + - 5 files changed, 365 insertions(+) - -Index: linux-2.4.24/fs/ext3/super.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/super.c 2004-01-12 20:36:31.000000000 +0300 -+++ linux-2.4.24/fs/ext3/super.c 2004-01-13 16:27:43.000000000 +0300 -@@ -400,6 +400,127 @@ - } - } - -+#ifdef EXT3_DELETE_THREAD -+/* -+ * Delete inodes in a loop until there are no more to be deleted. -+ * Normally, we run in the background doing the deletes and sleeping again, -+ * and clients just add new inodes to be deleted onto the end of the list. -+ * If someone is concerned about free space (e.g. block allocation or similar) -+ * then they can sleep on s_delete_waiter_queue and be woken up when space -+ * has been freed. -+ */ -+int ext3_delete_thread(void *data) -+{ -+ struct super_block *sb = data; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ struct task_struct *tsk = current; -+ -+ /* Almost like daemonize, but not quite */ -+ exit_mm(current); -+ tsk->session = 1; -+ tsk->pgrp = 1; -+ tsk->tty = NULL; -+ exit_files(current); -+ reparent_to_init(); -+ -+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev)); -+ sigfillset(&tsk->blocked); -+ -+ /*tsk->flags |= PF_KERNTHREAD;*/ -+ -+ INIT_LIST_HEAD(&sbi->s_delete_list); -+ wake_up(&sbi->s_delete_waiter_queue); -+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev)); -+ -+ /* main loop */ -+ for (;;) { -+ wait_event_interruptible(sbi->s_delete_thread_queue, -+ !list_empty(&sbi->s_delete_list) || -+ !test_opt(sb, ASYNCDEL)); -+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n", -+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks); -+ -+ spin_lock(&sbi->s_delete_lock); -+ if (list_empty(&sbi->s_delete_list)) { -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ memset(&sbi->s_delete_list, 0, -+ sizeof(sbi->s_delete_list)); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("delete thread on %s exiting\n", -+ kdevname(sb->s_dev)); -+ wake_up(&sbi->s_delete_waiter_queue); -+ break; -+ } -+ -+ while (!list_empty(&sbi->s_delete_list)) { -+ struct inode *inode=list_entry(sbi->s_delete_list.next, -+ struct inode, i_devices); -+ unsigned long blocks = inode->i_blocks >> -+ (inode->i_blkbits - 9); -+ -+ list_del_init(&inode->i_devices); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("%s delete ino %lu blk %lu\n", -+ tsk->comm, inode->i_ino, blocks); -+ -+ J_ASSERT(EXT3_I(inode)->i_state & EXT3_STATE_DELETE); -+ J_ASSERT(inode->i_nlink == 1); -+ inode->i_nlink = 0; -+ iput(inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ sbi->s_delete_blocks -= blocks; -+ sbi->s_delete_inodes--; -+ } -+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) { -+ ext3_warning(sb, __FUNCTION__, -+ "%lu blocks, %lu inodes on list?\n", -+ sbi->s_delete_blocks,sbi->s_delete_inodes); -+ sbi->s_delete_blocks = 0; -+ sbi->s_delete_inodes = 0; -+ } -+ spin_unlock(&sbi->s_delete_lock); -+ wake_up(&sbi->s_delete_waiter_queue); -+ } -+ -+ return 0; -+} -+ -+static void ext3_start_delete_thread(struct super_block *sb) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int rc; -+ -+ spin_lock_init(&sbi->s_delete_lock); -+ init_waitqueue_head(&sbi->s_delete_thread_queue); -+ init_waitqueue_head(&sbi->s_delete_waiter_queue); -+ -+ if (!test_opt(sb, ASYNCDEL)) -+ return; -+ -+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES); -+ if (rc < 0) -+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n", -+ rc); -+ else -+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next); -+} -+ -+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi) -+{ -+ if (sbi->s_delete_list.next == 0) /* thread never started */ -+ return; -+ -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ wake_up(&sbi->s_delete_thread_queue); -+ wait_event(sbi->s_delete_waiter_queue, -+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0); -+} -+#else -+#define ext3_start_delete_thread(sbi) do {} while(0) -+#define ext3_stop_delete_thread(sbi) do {} while(0) -+#endif /* EXT3_DELETE_THREAD */ -+ - void ext3_put_super (struct super_block * sb) - { - struct ext3_sb_info *sbi = EXT3_SB(sb); -@@ -407,6 +529,9 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+#ifdef EXT3_DELETE_THREAD -+ J_ASSERT(sbi->s_delete_inodes == 0); -+#endif - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -527,6 +650,13 @@ - clear_opt (*mount_options, XATTR_USER); - else - #endif -+#ifdef EXT3_DELETE_THREAD -+ if (!strcmp(this_char, "asyncdel")) -+ set_opt(*mount_options, ASYNCDEL); -+ else if (!strcmp(this_char, "noasyncdel")) -+ clear_opt(*mount_options, ASYNCDEL); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -1227,6 +1357,7 @@ - } - - ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); -+ ext3_start_delete_thread(sb); - /* - * akpm: core read_super() calls in here with the superblock locked. - * That deadlocks, because orphan cleanup needs to lock the superblock -@@ -1618,7 +1749,12 @@ - static int ext3_sync_fs(struct super_block *sb) - { - tid_t target; -- -+ -+ if (atomic_read(&sb->s_active) == 0) { -+ /* fs is being umounted: time to stop delete thread */ -+ ext3_stop_delete_thread(EXT3_SB(sb)); -+ } -+ - sb->s_dirt = 0; - target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); - log_wait_commit(EXT3_SB(sb)->s_journal, target); -@@ -1682,6 +1818,9 @@ - if (!parse_options(data, &tmp, sbi, &tmp, 1)) - return -EINVAL; - -+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY)) -+ ext3_stop_delete_thread(sbi); -+ - if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) - ext3_abort(sb, __FUNCTION__, "Abort forced by user"); - -Index: linux-2.4.24/fs/ext3/inode.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/inode.c 2004-01-12 20:36:31.000000000 +0300 -+++ linux-2.4.24/fs/ext3/inode.c 2004-01-12 20:36:32.000000000 +0300 -@@ -2551,6 +2551,118 @@ - return err; - } - -+#ifdef EXT3_DELETE_THREAD -+/* Move blocks from to-be-truncated inode over to a new inode, and delete -+ * that one from the delete thread instead. This avoids a lot of latency -+ * when truncating large files. -+ * -+ * If we have any problem deferring the truncate, just truncate it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+void ext3_truncate_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ handle_t *handle; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_truncate; -+ -+ /* XXX This is a temporary limitation for code simplicity. -+ * We could truncate to arbitrary sizes at some later time. -+ */ -+ if (old_inode->i_size != 0) -+ goto out_truncate; -+ -+ /* We may want to truncate the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS || -+ old_inode->i_size > oei->i_disksize) -+ goto out_truncate; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_truncate; -+ } -+ -+ ext3_discard_prealloc(old_inode); -+ -+ /* old_inode = 1 -+ * new_inode = sb + GDT + ibitmap -+ * orphan list = 1 inode/superblock for add, 2 inodes for del -+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS -+ */ -+ handle = ext3_journal_start(old_inode, 7); -+ if (IS_ERR(handle)) -+ goto out_truncate; -+ -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ if (IS_ERR(new_inode)) { -+ ext3_debug("truncate inode %lu directly (no new inodes)\n", -+ old_inode->i_ino); -+ goto out_journal; -+ } -+ -+ nei = EXT3_I(new_inode); -+ -+ down_write(&oei->truncate_sem); -+ new_inode->i_size = old_inode->i_size; -+ new_inode->i_blocks = old_inode->i_blocks; -+ new_inode->i_uid = old_inode->i_uid; -+ new_inode->i_gid = old_inode->i_gid; -+ new_inode->i_nlink = 1; -+ -+ /* FIXME when we do arbitrary truncates */ -+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0; -+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME; -+ -+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); -+ memset(oei->i_data, 0, sizeof(oei->i_data)); -+ -+ nei->i_disksize = oei->i_disksize; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up_write(&oei->truncate_sem); -+ -+ if (ext3_orphan_add(handle, new_inode) < 0) -+ goto out_journal; -+ -+ if (ext3_orphan_del(handle, old_inode) < 0) { -+ ext3_orphan_del(handle, new_inode); -+ iput(new_inode); -+ goto out_journal; -+ } -+ -+ ext3_journal_stop(handle, old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_devices)); -+ list_add_tail(&new_inode->i_devices, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_journal: -+ ext3_journal_stop(handle, old_inode); -+out_truncate: -+ ext3_truncate(old_inode); -+} -+#endif /* EXT3_DELETE_THREAD */ -+ - /* - * On success, We end up with an outstanding reference count against - * iloc->bh. This _must_ be cleaned up later. -Index: linux-2.4.24/fs/ext3/file.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/file.c 2004-01-12 20:36:29.000000000 +0300 -+++ linux-2.4.24/fs/ext3/file.c 2004-01-12 20:36:32.000000000 +0300 -@@ -126,7 +126,11 @@ - }; - - struct inode_operations ext3_file_inode_operations = { -+#ifdef EXT3_DELETE_THREAD -+ truncate: ext3_truncate_thread, /* BKL held */ -+#else - truncate: ext3_truncate, /* BKL held */ -+#endif - setattr: ext3_setattr, /* BKL held */ - setxattr: ext3_setxattr, /* BKL held */ - getxattr: ext3_getxattr, /* BKL held */ -Index: linux-2.4.24/fs/ext3/namei.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/namei.c 2004-01-12 20:36:31.000000000 +0300 -+++ linux-2.4.24/fs/ext3/namei.c 2004-01-12 20:36:32.000000000 +0300 -@@ -1936,6 +1936,40 @@ - return retval; - } - -+#ifdef EXT3_DELETE_THREAD -+static int ext3_try_to_delay_deletion(struct inode *inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb); -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long blocks; -+ -+ if (!test_opt(inode->i_sb, ASYNCDEL)) -+ return 0; -+ -+ /* We may want to delete the inode immediately and not defer it */ -+ blocks = inode->i_blocks >> (inode->i_blkbits - 9); -+ if (IS_SYNC(inode) || blocks <= EXT3_NDIR_BLOCKS) -+ return 0; -+ -+ inode->i_nlink = 1; -+ atomic_inc(&inode->i_count); -+ ei->i_state |= EXT3_STATE_DELETE; -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&inode->i_devices)); -+ list_add_tail(&inode->i_devices, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ -+ return 0; -+} -+#else -+#define ext3_try_to_delay_deletion(inode) do {} while (0) -+#endif -+ - static int ext3_unlink(struct inode * dir, struct dentry *dentry) - { - int retval; -@@ -1977,8 +2007,10 @@ - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; -- if (!inode->i_nlink) -+ if (!inode->i_nlink) { -+ ext3_try_to_delay_deletion(inode); - ext3_orphan_add(handle, inode); -+ } - inode->i_ctime = dir->i_ctime; - ext3_mark_inode_dirty(handle, inode); - retval = 0; -Index: linux-2.4.24/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-01-12 20:36:31.000000000 +0300 -+++ linux-2.4.24/include/linux/ext3_fs.h 2004-01-12 20:36:32.000000000 +0300 -@@ -193,6 +193,7 @@ - */ - #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */ - #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */ -+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */ - - /* - * ioctl commands -@@ -320,6 +321,7 @@ - #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ -+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -697,6 +699,9 @@ - extern void ext3_dirty_inode(struct inode *); - extern int ext3_change_inode_journal_flag(struct inode *, int); - extern void ext3_truncate (struct inode *); -+#ifdef EXT3_DELETE_THREAD -+extern void ext3_truncate_thread(struct inode *inode); -+#endif - extern void ext3_set_inode_flags(struct inode *); - - /* ioctl.c */ -Index: linux-2.4.24/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.24.orig/include/linux/ext3_fs_sb.h 2004-01-12 20:36:31.000000000 +0300 -+++ linux-2.4.24/include/linux/ext3_fs_sb.h 2004-01-12 20:36:32.000000000 +0300 -@@ -29,6 +29,8 @@ - - #define EXT3_MAX_GROUP_LOADED 8 - -+#define EXT3_DELETE_THREAD -+ - /* - * third extended-fs super-block data in memory - */ -@@ -76,6 +78,14 @@ - struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */ - wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */ - #endif -+#ifdef EXT3_DELETE_THREAD -+ spinlock_t s_delete_lock; -+ struct list_head s_delete_list; -+ unsigned long s_delete_blocks; -+ unsigned long s_delete_inodes; -+ wait_queue_head_t s_delete_thread_queue; -+ wait_queue_head_t s_delete_waiter_queue; -+#endif - }; - - #endif /* _LINUX_EXT3_FS_SB */ diff --git a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.29.patch b/lustre/kernel_patches/patches/ext3-delete_thread-2.4.29.patch deleted file mode 100644 index 39c47a7..0000000 --- a/lustre/kernel_patches/patches/ext3-delete_thread-2.4.29.patch +++ /dev/null @@ -1,442 +0,0 @@ -Index: linux-2.4.29/fs/ext3/super.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/super.c 2005-05-03 15:53:33.047533872 +0300 -+++ linux-2.4.29/fs/ext3/super.c 2005-05-03 15:54:47.192262160 +0300 -@@ -400,6 +400,127 @@ - } - } - -+#ifdef EXT3_DELETE_THREAD -+/* -+ * Delete inodes in a loop until there are no more to be deleted. -+ * Normally, we run in the background doing the deletes and sleeping again, -+ * and clients just add new inodes to be deleted onto the end of the list. -+ * If someone is concerned about free space (e.g. block allocation or similar) -+ * then they can sleep on s_delete_waiter_queue and be woken up when space -+ * has been freed. -+ */ -+int ext3_delete_thread(void *data) -+{ -+ struct super_block *sb = data; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ struct task_struct *tsk = current; -+ -+ /* Almost like daemonize, but not quite */ -+ exit_mm(current); -+ tsk->session = 1; -+ tsk->pgrp = 1; -+ tsk->tty = NULL; -+ exit_files(current); -+ reparent_to_init(); -+ -+ sprintf(tsk->comm, "kdelext3-%s", kdevname(sb->s_dev)); -+ sigfillset(&tsk->blocked); -+ -+ /*tsk->flags |= PF_KERNTHREAD;*/ -+ -+ INIT_LIST_HEAD(&sbi->s_delete_list); -+ wake_up(&sbi->s_delete_waiter_queue); -+ ext3_debug("delete thread on %s started\n", kdevname(sb->s_dev)); -+ -+ /* main loop */ -+ for (;;) { -+ wait_event_interruptible(sbi->s_delete_thread_queue, -+ !list_empty(&sbi->s_delete_list) || -+ !test_opt(sb, ASYNCDEL)); -+ ext3_debug("%s woken up: %lu inodes, %lu blocks\n", -+ tsk->comm,sbi->s_delete_inodes,sbi->s_delete_blocks); -+ -+ spin_lock(&sbi->s_delete_lock); -+ if (list_empty(&sbi->s_delete_list)) { -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ memset(&sbi->s_delete_list, 0, -+ sizeof(sbi->s_delete_list)); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("delete thread on %s exiting\n", -+ kdevname(sb->s_dev)); -+ wake_up(&sbi->s_delete_waiter_queue); -+ break; -+ } -+ -+ while (!list_empty(&sbi->s_delete_list)) { -+ struct inode *inode=list_entry(sbi->s_delete_list.next, -+ struct inode, i_devices); -+ unsigned long blocks = inode->i_blocks >> -+ (inode->i_blkbits - 9); -+ -+ list_del_init(&inode->i_devices); -+ spin_unlock(&sbi->s_delete_lock); -+ ext3_debug("%s delete ino %lu blk %lu\n", -+ tsk->comm, inode->i_ino, blocks); -+ -+ J_ASSERT(EXT3_I(inode)->i_state & EXT3_STATE_DELETE); -+ J_ASSERT(inode->i_nlink == 1); -+ inode->i_nlink = 0; -+ iput(inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ sbi->s_delete_blocks -= blocks; -+ sbi->s_delete_inodes--; -+ } -+ if (sbi->s_delete_blocks != 0 || sbi->s_delete_inodes != 0) { -+ ext3_warning(sb, __FUNCTION__, -+ "%lu blocks, %lu inodes on list?\n", -+ sbi->s_delete_blocks,sbi->s_delete_inodes); -+ sbi->s_delete_blocks = 0; -+ sbi->s_delete_inodes = 0; -+ } -+ spin_unlock(&sbi->s_delete_lock); -+ wake_up(&sbi->s_delete_waiter_queue); -+ } -+ -+ return 0; -+} -+ -+static void ext3_start_delete_thread(struct super_block *sb) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int rc; -+ -+ spin_lock_init(&sbi->s_delete_lock); -+ init_waitqueue_head(&sbi->s_delete_thread_queue); -+ init_waitqueue_head(&sbi->s_delete_waiter_queue); -+ -+ if (!test_opt(sb, ASYNCDEL)) -+ return; -+ -+ rc = kernel_thread(ext3_delete_thread, sb, CLONE_VM | CLONE_FILES); -+ if (rc < 0) -+ printk(KERN_ERR "EXT3-fs: cannot start delete thread: rc %d\n", -+ rc); -+ else -+ wait_event(sbi->s_delete_waiter_queue, sbi->s_delete_list.next); -+} -+ -+static void ext3_stop_delete_thread(struct ext3_sb_info *sbi) -+{ -+ if (sbi->s_delete_list.next == 0) /* thread never started */ -+ return; -+ -+ clear_opt(sbi->s_mount_opt, ASYNCDEL); -+ wake_up(&sbi->s_delete_thread_queue); -+ wait_event(sbi->s_delete_waiter_queue, -+ sbi->s_delete_list.next == 0 && sbi->s_delete_inodes == 0); -+} -+#else -+#define ext3_start_delete_thread(sbi) do {} while(0) -+#define ext3_stop_delete_thread(sbi) do {} while(0) -+#endif /* EXT3_DELETE_THREAD */ -+ - void ext3_put_super (struct super_block * sb) - { - struct ext3_sb_info *sbi = EXT3_SB(sb); -@@ -407,6 +528,9 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+#ifdef EXT3_DELETE_THREAD -+ J_ASSERT(sbi->s_delete_inodes == 0); -+#endif - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -526,6 +650,13 @@ - clear_opt (*mount_options, XATTR_USER); - else - #endif -+#ifdef EXT3_DELETE_THREAD -+ if (!strcmp(this_char, "asyncdel")) -+ set_opt(*mount_options, ASYNCDEL); -+ else if (!strcmp(this_char, "noasyncdel")) -+ clear_opt(*mount_options, ASYNCDEL); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -1244,6 +1375,7 @@ - } - - ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); -+ ext3_start_delete_thread(sb); - EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS; - ext3_orphan_cleanup(sb, es); - EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS; -@@ -1626,7 +1758,12 @@ - static int ext3_sync_fs(struct super_block *sb) - { - tid_t target; -- -+ -+ if (atomic_read(&sb->s_active) == 0) { -+ /* fs is being umounted: time to stop delete thread */ -+ ext3_stop_delete_thread(EXT3_SB(sb)); -+ } -+ - sb->s_dirt = 0; - target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); - log_wait_commit(EXT3_SB(sb)->s_journal, target); -@@ -1690,6 +1827,9 @@ - if (!parse_options(data, &tmp, sbi, &tmp, 1)) - return -EINVAL; - -+ if (!test_opt(sb, ASYNCDEL) || (*flags & MS_RDONLY)) -+ ext3_stop_delete_thread(sbi); -+ - if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) - ext3_abort(sb, __FUNCTION__, "Abort forced by user"); - -Index: linux-2.4.29/fs/ext3/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/inode.c 2005-05-03 15:53:36.555000656 +0300 -+++ linux-2.4.29/fs/ext3/inode.c 2005-05-03 15:53:56.901907456 +0300 -@@ -2562,6 +2562,118 @@ - return err; - } - -+#ifdef EXT3_DELETE_THREAD -+/* Move blocks from to-be-truncated inode over to a new inode, and delete -+ * that one from the delete thread instead. This avoids a lot of latency -+ * when truncating large files. -+ * -+ * If we have any problem deferring the truncate, just truncate it right away. -+ * If we defer it, we also mark how many blocks it would free, so that we -+ * can keep the statfs data correct, and we know if we should sleep on the -+ * delete thread when we run out of space. -+ */ -+void ext3_truncate_thread(struct inode *old_inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(old_inode->i_sb); -+ struct ext3_inode_info *nei, *oei = EXT3_I(old_inode); -+ struct inode *new_inode; -+ handle_t *handle; -+ unsigned long blocks = old_inode->i_blocks >> (old_inode->i_blkbits-9); -+ -+ if (!test_opt(old_inode->i_sb, ASYNCDEL) || !sbi->s_delete_list.next) -+ goto out_truncate; -+ -+ /* XXX This is a temporary limitation for code simplicity. -+ * We could truncate to arbitrary sizes at some later time. -+ */ -+ if (old_inode->i_size != 0) -+ goto out_truncate; -+ -+ /* We may want to truncate the inode immediately and not defer it */ -+ if (IS_SYNC(old_inode) || blocks <= EXT3_NDIR_BLOCKS || -+ old_inode->i_size > oei->i_disksize) -+ goto out_truncate; -+ -+ /* We can't use the delete thread as-is during real orphan recovery, -+ * as we add to the orphan list here, causing ext3_orphan_cleanup() -+ * to loop endlessly. It would be nice to do so, but needs work. -+ */ -+ if (oei->i_state & EXT3_STATE_DELETE || -+ sbi->s_mount_state & EXT3_ORPHAN_FS) { -+ ext3_debug("doing deferred inode %lu delete (%lu blocks)\n", -+ old_inode->i_ino, blocks); -+ goto out_truncate; -+ } -+ -+ ext3_discard_prealloc(old_inode); -+ -+ /* old_inode = 1 -+ * new_inode = sb + GDT + ibitmap -+ * orphan list = 1 inode/superblock for add, 2 inodes for del -+ * quota files = 2 * EXT3_SINGLEDATA_TRANS_BLOCKS -+ */ -+ handle = ext3_journal_start(old_inode, 7); -+ if (IS_ERR(handle)) -+ goto out_truncate; -+ -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ if (IS_ERR(new_inode)) { -+ ext3_debug("truncate inode %lu directly (no new inodes)\n", -+ old_inode->i_ino); -+ goto out_journal; -+ } -+ -+ nei = EXT3_I(new_inode); -+ -+ down_write(&oei->truncate_sem); -+ new_inode->i_size = old_inode->i_size; -+ new_inode->i_blocks = old_inode->i_blocks; -+ new_inode->i_uid = old_inode->i_uid; -+ new_inode->i_gid = old_inode->i_gid; -+ new_inode->i_nlink = 1; -+ -+ /* FIXME when we do arbitrary truncates */ -+ old_inode->i_blocks = oei->i_file_acl ? old_inode->i_blksize / 512 : 0; -+ old_inode->i_mtime = old_inode->i_ctime = CURRENT_TIME; -+ -+ memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); -+ memset(oei->i_data, 0, sizeof(oei->i_data)); -+ -+ nei->i_disksize = oei->i_disksize; -+ nei->i_state |= EXT3_STATE_DELETE; -+ up_write(&oei->truncate_sem); -+ -+ if (ext3_orphan_add(handle, new_inode) < 0) -+ goto out_journal; -+ -+ if (ext3_orphan_del(handle, old_inode) < 0) { -+ ext3_orphan_del(handle, new_inode); -+ iput(new_inode); -+ goto out_journal; -+ } -+ -+ ext3_journal_stop(handle, old_inode); -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&new_inode->i_devices)); -+ list_add_tail(&new_inode->i_devices, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ ext3_debug("delete inode %lu (%lu blocks) by thread\n", -+ new_inode->i_ino, blocks); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ return; -+ -+out_journal: -+ ext3_journal_stop(handle, old_inode); -+out_truncate: -+ ext3_truncate(old_inode); -+} -+#endif /* EXT3_DELETE_THREAD */ -+ - /* - * On success, We end up with an outstanding reference count against - * iloc->bh. This _must_ be cleaned up later. -Index: linux-2.4.29/fs/ext3/file.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/file.c 2005-04-07 19:31:00.000000000 +0300 -+++ linux-2.4.29/fs/ext3/file.c 2005-05-03 15:53:56.902907304 +0300 -@@ -123,7 +123,11 @@ - }; - - struct inode_operations ext3_file_inode_operations = { -+#ifdef EXT3_DELETE_THREAD -+ truncate: ext3_truncate_thread, /* BKL held */ -+#else - truncate: ext3_truncate, /* BKL held */ -+#endif - setattr: ext3_setattr, /* BKL held */ - setxattr: ext3_setxattr, /* BKL held */ - getxattr: ext3_getxattr, /* BKL held */ -Index: linux-2.4.29/fs/ext3/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/namei.c 2005-05-03 15:53:33.044534328 +0300 -+++ linux-2.4.29/fs/ext3/namei.c 2005-05-03 15:53:56.905906848 +0300 -@@ -838,6 +838,40 @@ - return retval; - } - -+#ifdef EXT3_DELETE_THREAD -+static int ext3_try_to_delay_deletion(struct inode *inode) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb); -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long blocks; -+ -+ if (!test_opt(inode->i_sb, ASYNCDEL)) -+ return 0; -+ -+ /* We may want to delete the inode immediately and not defer it */ -+ blocks = inode->i_blocks >> (inode->i_blkbits - 9); -+ if (IS_SYNC(inode) || blocks <= EXT3_NDIR_BLOCKS) -+ return 0; -+ -+ inode->i_nlink = 1; -+ atomic_inc(&inode->i_count); -+ ei->i_state |= EXT3_STATE_DELETE; -+ -+ spin_lock(&sbi->s_delete_lock); -+ J_ASSERT(list_empty(&inode->i_devices)); -+ list_add_tail(&inode->i_devices, &sbi->s_delete_list); -+ sbi->s_delete_blocks += blocks; -+ sbi->s_delete_inodes++; -+ spin_unlock(&sbi->s_delete_lock); -+ -+ wake_up(&sbi->s_delete_thread_queue); -+ -+ return 0; -+} -+#else -+#define ext3_try_to_delay_deletion(inode) do {} while (0) -+#endif -+ - static int ext3_unlink(struct inode * dir, struct dentry *dentry) - { - int retval; -@@ -878,8 +912,10 @@ - dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; -- if (!inode->i_nlink) -+ if (!inode->i_nlink) { -+ ext3_try_to_delay_deletion(inode); - ext3_orphan_add(handle, inode); -+ } - inode->i_ctime = dir->i_ctime; - ext3_mark_inode_dirty(handle, inode); - retval = 0; -Index: linux-2.4.29/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-05-03 15:53:37.124914016 +0300 -+++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 15:53:56.907906544 +0300 -@@ -188,6 +188,7 @@ - */ - #define EXT3_STATE_JDATA 0x00000001 /* journaled data exists */ - #define EXT3_STATE_NEW 0x00000002 /* inode is newly created */ -+#define EXT3_STATE_DELETE 0x00000010 /* deferred delete inode */ - - /* - * ioctl commands -@@ -315,6 +316,7 @@ - #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ -+#define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -639,6 +641,9 @@ - extern void ext3_dirty_inode(struct inode *); - extern int ext3_change_inode_journal_flag(struct inode *, int); - extern void ext3_truncate (struct inode *); -+#ifdef EXT3_DELETE_THREAD -+extern void ext3_truncate_thread(struct inode *inode); -+#endif - extern void ext3_set_inode_flags(struct inode *); - - /* ioctl.c */ -Index: linux-2.4.29/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs_sb.h 2005-05-03 15:53:33.048533720 +0300 -+++ linux-2.4.29/include/linux/ext3_fs_sb.h 2005-05-03 15:53:56.909906240 +0300 -@@ -29,6 +29,8 @@ - - #define EXT3_MAX_GROUP_LOADED 8 - -+#define EXT3_DELETE_THREAD -+ - /* - * third extended-fs super-block data in memory - */ -@@ -74,6 +76,14 @@ - struct timer_list turn_ro_timer; /* For turning read-only (crash simulation) */ - wait_queue_head_t ro_wait_queue; /* For people waiting for the fs to go read-only */ - #endif -+#ifdef EXT3_DELETE_THREAD -+ spinlock_t s_delete_lock; -+ struct list_head s_delete_list; -+ unsigned long s_delete_blocks; -+ unsigned long s_delete_inodes; -+ wait_queue_head_t s_delete_thread_queue; -+ wait_queue_head_t s_delete_waiter_queue; -+#endif - }; - - #endif /* _LINUX_EXT3_FS_SB */ diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.20.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.20.patch deleted file mode 100644 index 0e93ced..0000000 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.20.patch +++ /dev/null @@ -1,747 +0,0 @@ - fs/ext3/ialloc.c | 6 - fs/ext3/inode.c | 12 - fs/ext3/super.c | 6 - fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++- - include/linux/ext3_fs.h | 2 - include/linux/ext3_fs_i.h | 3 - 6 files changed, 615 insertions(+), 11 deletions(-) - ---- linux-2.4.20/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:08.000000000 +0400 -+++ linux-2.4.20-alexey/fs/ext3/ialloc.c 2003-10-12 16:25:21.000000000 +0400 -@@ -577,6 +577,10 @@ repeat: - inode->i_generation = sb->u.ext3_sb.s_next_generation++; - - inode->u.ext3_i.i_state = EXT3_STATE_NEW; -+ inode->u.ext3_i.i_extra_isize = -+ (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ? -+ sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; -+ - err = ext3_get_inode_loc_new(inode, &iloc, 1); - if (err) goto fail; - BUFFER_TRACE(iloc->bh, "get_write_access"); ---- linux-2.4.20/fs/ext3/inode.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:08.000000000 +0400 -+++ linux-2.4.20-alexey/fs/ext3/inode.c 2003-10-12 16:25:21.000000000 +0400 -@@ -2209,6 +2209,12 @@ void ext3_read_inode(struct inode * inod - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ inode->u.ext3_i.i_extra_isize = -+ le16_to_cpu(raw_inode->i_extra_isize); -+ else -+ inode->u.ext3_i.i_extra_isize = 0; -+ - brelse (iloc.bh); - - if (S_ISREG(inode->i_mode)) { -@@ -2274,6 +2280,8 @@ static int ext3_do_update_inode(handle_t - if (err) - goto out_brelse; - } -+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) -+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb)); - raw_inode->i_mode = cpu_to_le16(inode->i_mode); - if(!(test_opt(inode->i_sb, NO_UID32))) { - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); -@@ -2357,6 +2365,10 @@ static int ext3_do_update_inode(handle_t - else for (block = 0; block < EXT3_N_BLOCKS; block++) - raw_inode->i_block[block] = inode->u.ext3_i.i_data[block]; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ raw_inode->i_extra_isize = -+ cpu_to_le16(EXT3_I(inode)->i_extra_isize); -+ - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) ---- linux-2.4.20/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:06.000000000 +0400 -+++ linux-2.4.20-alexey/fs/ext3/xattr.c 2003-10-12 16:26:31.000000000 +0400 -@@ -100,6 +100,9 @@ - static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *, - struct ext3_xattr_header *); - -+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); -+ - #ifdef CONFIG_EXT3_FS_XATTR_SHARING - - static int ext3_xattr_cache_insert(struct buffer_head *); -@@ -348,17 +351,12 @@ ext3_removexattr(struct dentry *dentry, - } - - /* -- * ext3_xattr_get() -- * -- * Copy an extended attribute into the buffer -- * provided, or compute the buffer size required. -- * Buffer is NULL to compute the size of the buffer required. -+ * ext3_xattr_block_get() - * -- * Returns a negative error number on failure, or the number of bytes -- * used / required on success. -+ * routine looks for attribute in EA block and returns it's value and size - */ - int --ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; -@@ -447,6 +445,94 @@ cleanup: - } - - /* -+ * ext3_xattr_ibody_get() -+ * -+ * routine looks for attribute in inode body and returns it's value and size -+ */ -+int -+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int size, name_len = strlen(name), storage_size; -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOENT; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ goto found; -+ last = next; -+ } -+ -+ /* can't find EA */ -+ brelse(iloc.bh); -+ return -ENOENT; -+ -+found: -+ size = le32_to_cpu(last->e_value_size); -+ if (buffer) { -+ ret = -ERANGE; -+ if (buffer_size >= size) { -+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs), -+ size); -+ ret = size; -+ } -+ } else -+ ret = size; -+ brelse(iloc.bh); -+ return ret; -+} -+ -+int ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int err; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_get(inode, name_index, name, -+ buffer, buffer_size); -+ if (err < 0) -+ /* search was unsuccessful, try to find EA in dedicated block */ -+ err = ext3_xattr_block_get(inode, name_index, name, -+ buffer, buffer_size); -+ return err; -+} -+ -+/* - * ext3_xattr_list() - * - * Copy a list of attribute names into the buffer -@@ -457,7 +543,7 @@ cleanup: - * used / required on success. - */ - int --ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; - struct ext3_xattr_entry *entry; -@@ -530,6 +616,131 @@ cleanup: - return error; - } - -+/* ext3_xattr_ibody_list() -+ * -+ * generate list of attributes stored in inode body -+ */ -+int -+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ char *start, *end, *buf; -+ struct ext3_iloc iloc; -+ int storage_size; -+ int ret; -+ int size = 0; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return 0; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return 0; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ -+ if (!buffer) { -+ ret = size; -+ goto cleanup; -+ } else { -+ ret = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ last = (struct ext3_xattr_entry *) start; -+ buf = buffer; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ ret = size; -+cleanup: -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ int error; -+ int size = buffer_size; -+ -+ /* get list of attributes stored in inode body */ -+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size); -+ if (error < 0) { -+ /* some error occured while collecting -+ * attributes in inode body */ -+ size = 0; -+ goto cleanup; -+ } -+ size = error; -+ -+ /* get list of attributes stored in dedicated block */ -+ if (buffer) { -+ buffer_size -= error; -+ if (buffer_size <= 0) { -+ buffer = NULL; -+ buffer_size = 0; -+ } else -+ buffer += error; -+ } -+ -+ error = ext3_xattr_block_list(inode, buffer, buffer_size); -+ if (error < 0) -+ /* listing was successful, so we return len */ -+ size = 0; -+ -+cleanup: -+ return error + size; -+} -+ - /* - * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is - * not set, set it. -@@ -553,6 +764,279 @@ static void ext3_xattr_update_super_bloc - } - - /* -+ * ext3_xattr_ibody_find() -+ * -+ * search attribute and calculate free space in inode body -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_ibody_find(struct inode *inode, int name_index, -+ const char *name, struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return ret; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return -EIO; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ *free = storage_size - sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) { -+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry)); -+ ret = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(last->e_name_len); -+ *free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_block_find() -+ * -+ * search attribute and calculate free space in EA block (if it allocated) -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, -+ struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ char *end; -+ int name_len, error = -ENOENT; -+ -+ if (!EXT3_I(inode)->i_file_acl) { -+ *free = inode->i_sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - -+ sizeof(__u32); -+ return -ENOENT; -+ } -+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl); -+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, -+ EXT3_I(inode)->i_file_acl); -+ brelse(bh); -+ return -EIO; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ *free = bh->b_size - sizeof(__u32); -+ -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) { -+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry)); -+ error = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(entry->e_name_len); -+ *free -= le32_to_cpu(entry->e_value_size); -+ } -+ entry = next; -+ } -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_inode_set() -+ * -+ * this routine add/remove/replace attribute in inode body -+ */ -+int -+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry *last, *next, *here = NULL; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int esize = EXT3_XATTR_LEN(name_len); -+ struct buffer_head *bh; -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ int free, min_offs; -+ char *start, *end; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOSPC; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return err; -+ raw_inode = iloc.raw_inode; -+ bh = iloc.bh; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) { -+ /* inode had no attributes before */ -+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC); -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ min_offs = storage_size; -+ free = storage_size - sizeof(__u32); -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set", -+ "inode %ld", inode->i_ino); -+ brelse(bh); -+ return -EIO; -+ } -+ -+ if (last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ here = last; -+ else { -+ /* we calculate all but our attribute -+ * because it will be removed before changing */ -+ free -= EXT3_XATTR_LEN(last->e_name_len); -+ free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ if (value && (esize + value_len > free)) { -+ brelse(bh); -+ return -ENOSPC; -+ } -+ -+ err = ext3_reserve_inode_write(handle, inode, &iloc); -+ if (err) { -+ brelse(bh); -+ return err; -+ } -+ -+ if (here) { -+ /* time to remove old value */ -+ struct ext3_xattr_entry *e; -+ int size = le32_to_cpu(here->e_value_size); -+ int border = le16_to_cpu(here->e_value_offs); -+ char *src; -+ -+ /* move tail */ -+ memmove(start + min_offs + size, start + min_offs, -+ border - min_offs); -+ -+ /* recalculate offsets */ -+ e = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(e)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e); -+ int offs = le16_to_cpu(e->e_value_offs); -+ if (offs < border) -+ e->e_value_offs = -+ cpu_to_le16(offs + size); -+ e = next; -+ } -+ min_offs += size; -+ -+ /* remove entry */ -+ border = EXT3_XATTR_LEN(here->e_name_len); -+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len); -+ size = (char *) last - src; -+ if ((char *) here + size > end) -+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n", -+ __FILE__, __LINE__, here, size, end); -+ memmove(here, src, size); -+ last = (struct ext3_xattr_entry *) ((char *) last - border); -+ *((__u32 *) last) = 0; -+ } -+ -+ if (value) { -+ int offs = min_offs - value_len; -+ /* use last to create new entry */ -+ last->e_name_len = strlen(name); -+ last->e_name_index = name_index; -+ last->e_value_offs = cpu_to_le16(offs); -+ last->e_value_size = cpu_to_le32(value_len); -+ last->e_hash = last->e_value_block = 0; -+ memset(last->e_name, 0, esize); -+ memcpy(last->e_name, name, last->e_name_len); -+ if (start + offs + value_len > end) -+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n", -+ __FILE__, __LINE__, start, offs, -+ value_len, end); -+ memcpy(start + offs, value, value_len); -+ last = EXT3_XATTR_NEXT(last); -+ *((__u32 *) last) = 0; -+ } -+ -+ ext3_mark_iloc_dirty(handle, inode, &iloc); -+ brelse(bh); -+ -+ return 0; -+} -+ -+/* - * ext3_xattr_set() - * - * Create, replace or remove an extended attribute for this inode. Buffer -@@ -566,6 +1050,101 @@ static void ext3_xattr_update_super_bloc - */ - int - ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, int flags) -+{ -+ struct ext3_xattr_entry entry; -+ int err, where = 0, found = 0, total; -+ int free1 = -1, free2 = -1; -+ int name_len; -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize) -+ return -ERANGE; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1); -+ if (err == 0) { -+ /* found EA in inode */ -+ found = 1; -+ where = 0; -+ } else if (err == -ENOENT) { -+ /* there is no such attribute in inode body */ -+ /* try to find attribute in dedicated block */ -+ err = ext3_xattr_block_find(inode, name_index, name, -+ &entry, &free2); -+ if (err != 0 && err != -ENOENT) { -+ /* not found EA in block */ -+ goto finish; -+ } else if (err == 0) { -+ /* found EA in block */ -+ where = 1; -+ found = 1; -+ } -+ } else -+ goto finish; -+ -+ /* check flags: may replace? may create ? */ -+ if (found && (flags & XATTR_CREATE)) { -+ err = -EEXIST; -+ goto finish; -+ } else if (!found && (flags & XATTR_REPLACE)) { -+ err = -ENODATA; -+ goto finish; -+ } -+ -+ /* check if we have enough space to store attribute */ -+ total = EXT3_XATTR_LEN(strlen(name)) + value_len; -+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) { -+ /* have no enough space */ -+ err = -ENOSPC; -+ goto finish; -+ } -+ -+ /* time to remove attribute */ -+ if (found) { -+ if (where == 0) { -+ /* EA is stored in inode body */ -+ ext3_xattr_ibody_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } else { -+ /* EA is stored in separated block */ -+ ext3_xattr_block_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } -+ } -+ -+ /* try to store EA in inode body */ -+ err = ext3_xattr_ibody_set(handle, inode, name_index, name, -+ value, value_len, flags); -+ if (err) { -+ /* can't store EA in inode body */ -+ /* try to store in block */ -+ err = ext3_xattr_block_set(handle, inode, name_index, -+ name, value, value_len, flags); -+ } -+ -+finish: -+ return err; -+} -+ -+/* -+ * ext3_xattr_block_set() -+ * -+ * this routine add/remove/replace attribute in EA block -+ */ -+int -+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, int flags) - { - struct super_block *sb = inode->i_sb; ---- linux-2.4.20/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:08.000000000 +0400 -+++ linux-2.4.20-alexey/include/linux/ext3_fs.h 2003-10-12 16:35:46.000000000 +0400 -@@ -264,6 +264,8 @@ struct ext3_inode { - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -+ __u16 i_extra_isize; -+ __u16 i_pad1; - }; - - #define i_size_high i_dir_acl ---- linux-2.4.20/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.20 2001-11-22 22:46:19.000000000 +0300 -+++ linux-2.4.20-alexey/include/linux/ext3_fs_i.h 2003-10-12 16:34:14.000000000 +0400 -@@ -62,6 +62,9 @@ struct ext3_inode_info { - */ - loff_t i_disksize; - -+ /* on-disk additional length */ -+ __u16 i_extra_isize; -+ - /* - * truncate_sem is for serialising ext3_truncate() against - * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's ---- linux-2.4.20/fs/ext3/super.c~ext3-ea-in-inode-2.4.20 2003-10-08 23:18:09.000000000 +0400 -+++ linux-2.4.20-alexey/fs/ext3/super.c 2003-10-12 16:25:21.000000000 +0400 -@@ -1292,8 +1292,10 @@ struct super_block * ext3_read_super (st - } else { - sbi->s_inode_size = le16_to_cpu(es->s_inode_size); - sbi->s_first_ino = le32_to_cpu(es->s_first_ino); -- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) { -- printk (KERN_ERR -+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || -+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) || -+ (sbi->s_inode_size > blocksize)) { -+ printk (KERN_ERR - "EXT3-fs: unsupported inode size: %d\n", - sbi->s_inode_size); - goto failed_mount; - -_ diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-chaos.patch deleted file mode 100644 index 491a2df..0000000 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-chaos.patch +++ /dev/null @@ -1,758 +0,0 @@ - fs/ext3/ialloc.c | 6 - fs/ext3/inode.c | 12 - fs/ext3/super.c | 6 - fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++- - include/linux/ext3_fs.h | 2 - include/linux/ext3_fs_i.h | 3 - 6 files changed, 615 insertions(+), 11 deletions(-) - -Index: linux-2.4.21-chaos/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c 2003-12-12 17:39:10.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ialloc.c 2003-12-12 17:39:55.000000000 +0300 -@@ -580,6 +580,10 @@ - inode->i_generation = sbi->s_next_generation++; - - ei->i_state = EXT3_STATE_NEW; -+ ei->i_extra_isize = -+ (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ? -+ sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; -+ - err = ext3_get_inode_loc_new(inode, &iloc, 1); - if (err) goto fail; - BUFFER_TRACE(iloc->bh, "get_write_access"); -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 17:39:11.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 17:39:55.000000000 +0300 -@@ -2502,6 +2502,12 @@ - ei->i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&ei->i_orphan); - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ EXT3_I(inode)->i_extra_isize = -+ le16_to_cpu(raw_inode->i_extra_isize); -+ else -+ EXT3_I(inode)->i_extra_isize = 0; -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; -@@ -2564,6 +2570,8 @@ - if (err) - goto out_brelse; - } -+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) -+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb)); - raw_inode->i_mode = cpu_to_le16(inode->i_mode); - if(!(test_opt(inode->i_sb, NO_UID32))) { - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); -@@ -2646,6 +2654,10 @@ - else for (block = 0; block < EXT3_N_BLOCKS; block++) - raw_inode->i_block[block] = ei->i_data[block]; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ raw_inode->i_extra_isize = -+ cpu_to_le16(EXT3_I(inode)->i_extra_isize); -+ - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) -Index: linux-2.4.21-chaos/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr.c 2003-12-12 17:38:44.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/xattr.c 2003-12-12 17:42:58.000000000 +0300 -@@ -88,6 +88,9 @@ - struct buffer_head *, - struct ext3_xattr_header *); - -+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); -+ - #ifdef CONFIG_EXT3_FS_XATTR_SHARING - - static int ext3_xattr_cache_insert(struct buffer_head *); -@@ -256,17 +259,12 @@ - } - - /* -- * ext3_xattr_get() -- * -- * Copy an extended attribute into the buffer -- * provided, or compute the buffer size required. -- * Buffer is NULL to compute the size of the buffer required. -+ * ext3_xattr_block_get() - * -- * Returns a negative error number on failure, or the number of bytes -- * used / required on success. -+ * routine looks for attribute in EA block and returns it's value and size - */ - int --ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; -@@ -359,6 +357,94 @@ - } - - /* -+ * ext3_xattr_ibody_get() -+ * -+ * routine looks for attribute in inode body and returns it's value and size -+ */ -+int -+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int size, name_len = strlen(name), storage_size; -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOENT; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ goto found; -+ last = next; -+ } -+ -+ /* can't find EA */ -+ brelse(iloc.bh); -+ return -ENOENT; -+ -+found: -+ size = le32_to_cpu(last->e_value_size); -+ if (buffer) { -+ ret = -ERANGE; -+ if (buffer_size >= size) { -+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs), -+ size); -+ ret = size; -+ } -+ } else -+ ret = size; -+ brelse(iloc.bh); -+ return ret; -+} -+ -+int ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int err; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_get(inode, name_index, name, -+ buffer, buffer_size); -+ if (err < 0) -+ /* search was unsuccessful, try to find EA in dedicated block */ -+ err = ext3_xattr_block_get(inode, name_index, name, -+ buffer, buffer_size); -+ return err; -+} -+ -+/* - * ext3_xattr_list() - * - * Copy a list of attribute names into the buffer -@@ -369,7 +455,7 @@ - * used / required on success. - */ - int --ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; - struct ext3_xattr_entry *entry; -@@ -446,6 +532,131 @@ - return error; - } - -+/* ext3_xattr_ibody_list() -+ * -+ * generate list of attributes stored in inode body -+ */ -+int -+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ char *start, *end, *buf; -+ struct ext3_iloc iloc; -+ int storage_size; -+ int ret; -+ int size = 0; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return 0; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return 0; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ -+ if (!buffer) { -+ ret = size; -+ goto cleanup; -+ } else { -+ ret = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ last = (struct ext3_xattr_entry *) start; -+ buf = buffer; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ ret = size; -+cleanup: -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ int error; -+ int size = buffer_size; -+ -+ /* get list of attributes stored in inode body */ -+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size); -+ if (error < 0) { -+ /* some error occured while collecting -+ * attributes in inode body */ -+ size = 0; -+ goto cleanup; -+ } -+ size = error; -+ -+ /* get list of attributes stored in dedicated block */ -+ if (buffer) { -+ buffer_size -= error; -+ if (buffer_size <= 0) { -+ buffer = NULL; -+ buffer_size = 0; -+ } else -+ buffer += error; -+ } -+ -+ error = ext3_xattr_block_list(inode, buffer, buffer_size); -+ if (error < 0) -+ /* listing was successful, so we return len */ -+ size = 0; -+ -+cleanup: -+ return error + size; -+} -+ - /* - * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is - * not set, set it. -@@ -480,6 +691,102 @@ - */ - int - ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry entry; -+ int err, where = 0, found = 0, total; -+ int free1 = -1, free2 = -1; -+ int name_len; -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize) -+ return -ERANGE; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1); -+ if (err == 0) { -+ /* found EA in inode */ -+ found = 1; -+ where = 0; -+ } else if (err == -ENOENT) { -+ /* there is no such attribute in inode body */ -+ /* try to find attribute in dedicated block */ -+ err = ext3_xattr_block_find(inode, name_index, name, -+ &entry, &free2); -+ if (err != 0 && err != -ENOENT) { -+ /* not found EA in block */ -+ goto finish; -+ } else if (err == 0) { -+ /* found EA in block */ -+ where = 1; -+ found = 1; -+ } -+ } else -+ goto finish; -+ -+ /* check flags: may replace? may create ? */ -+ if (found && (flags & XATTR_CREATE)) { -+ err = -EEXIST; -+ goto finish; -+ } else if (!found && (flags & XATTR_REPLACE)) { -+ err = -ENODATA; -+ goto finish; -+ } -+ -+ /* check if we have enough space to store attribute */ -+ total = EXT3_XATTR_LEN(strlen(name)) + value_len; -+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) { -+ /* have no enough space */ -+ err = -ENOSPC; -+ goto finish; -+ } -+ -+ /* time to remove attribute */ -+ if (found) { -+ if (where == 0) { -+ /* EA is stored in inode body */ -+ ext3_xattr_ibody_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } else { -+ /* EA is stored in separated block */ -+ ext3_xattr_block_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } -+ } -+ -+ /* try to store EA in inode body */ -+ err = ext3_xattr_ibody_set(handle, inode, name_index, name, -+ value, value_len, flags); -+ if (err) { -+ /* can't store EA in inode body */ -+ /* try to store in block */ -+ err = ext3_xattr_block_set(handle, inode, name_index, -+ name, value, value_len, flags); -+ } -+ -+finish: -+ return err; -+} -+ -+/* -+ * ext3_xattr_block_set() -+ * -+ * this routine add/remove/replace attribute in EA block -+ */ -+int -+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, - int flags) - { -@@ -868,6 +1174,279 @@ - } - - /* -+ * ext3_xattr_ibody_find() -+ * -+ * search attribute and calculate free space in inode body -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_ibody_find(struct inode *inode, int name_index, -+ const char *name, struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return ret; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return -EIO; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ *free = storage_size - sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) { -+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry)); -+ ret = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(last->e_name_len); -+ *free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_block_find() -+ * -+ * search attribute and calculate free space in EA block (if it allocated) -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, -+ struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ char *end; -+ int name_len, error = -ENOENT; -+ -+ if (!EXT3_I(inode)->i_file_acl) { -+ *free = inode->i_sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - -+ sizeof(__u32); -+ return -ENOENT; -+ } -+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl); -+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, -+ EXT3_I(inode)->i_file_acl); -+ brelse(bh); -+ return -EIO; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ *free = bh->b_size - sizeof(__u32); -+ -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) { -+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry)); -+ error = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(entry->e_name_len); -+ *free -= le32_to_cpu(entry->e_value_size); -+ } -+ entry = next; -+ } -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_inode_set() -+ * -+ * this routine add/remove/replace attribute in inode body -+ */ -+int -+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry *last, *next, *here = NULL; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int esize = EXT3_XATTR_LEN(name_len); -+ struct buffer_head *bh; -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ int free, min_offs; -+ char *start, *end; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOSPC; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return err; -+ raw_inode = iloc.raw_inode; -+ bh = iloc.bh; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) { -+ /* inode had no attributes before */ -+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC); -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ min_offs = storage_size; -+ free = storage_size - sizeof(__u32); -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set", -+ "inode %ld", inode->i_ino); -+ brelse(bh); -+ return -EIO; -+ } -+ -+ if (last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ here = last; -+ else { -+ /* we calculate all but our attribute -+ * because it will be removed before changing */ -+ free -= EXT3_XATTR_LEN(last->e_name_len); -+ free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ if (value && (esize + value_len > free)) { -+ brelse(bh); -+ return -ENOSPC; -+ } -+ -+ err = ext3_reserve_inode_write(handle, inode, &iloc); -+ if (err) { -+ brelse(bh); -+ return err; -+ } -+ -+ if (here) { -+ /* time to remove old value */ -+ struct ext3_xattr_entry *e; -+ int size = le32_to_cpu(here->e_value_size); -+ int border = le16_to_cpu(here->e_value_offs); -+ char *src; -+ -+ /* move tail */ -+ memmove(start + min_offs + size, start + min_offs, -+ border - min_offs); -+ -+ /* recalculate offsets */ -+ e = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(e)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e); -+ int offs = le16_to_cpu(e->e_value_offs); -+ if (offs < border) -+ e->e_value_offs = -+ cpu_to_le16(offs + size); -+ e = next; -+ } -+ min_offs += size; -+ -+ /* remove entry */ -+ border = EXT3_XATTR_LEN(here->e_name_len); -+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len); -+ size = (char *) last - src; -+ if ((char *) here + size > end) -+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n", -+ __FILE__, __LINE__, here, size, end); -+ memmove(here, src, size); -+ last = (struct ext3_xattr_entry *) ((char *) last - border); -+ *((__u32 *) last) = 0; -+ } -+ -+ if (value) { -+ int offs = min_offs - value_len; -+ /* use last to create new entry */ -+ last->e_name_len = strlen(name); -+ last->e_name_index = name_index; -+ last->e_value_offs = cpu_to_le16(offs); -+ last->e_value_size = cpu_to_le32(value_len); -+ last->e_hash = last->e_value_block = 0; -+ memset(last->e_name, 0, esize); -+ memcpy(last->e_name, name, last->e_name_len); -+ if (start + offs + value_len > end) -+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n", -+ __FILE__, __LINE__, start, offs, -+ value_len, end); -+ memcpy(start + offs, value, value_len); -+ last = EXT3_XATTR_NEXT(last); -+ *((__u32 *) last) = 0; -+ } -+ -+ ext3_mark_iloc_dirty(handle, inode, &iloc); -+ brelse(bh); -+ -+ return 0; -+} -+ -+/* - * ext3_xattr_set_trans() - * - * Like ext3_xattr_set_handle, but start from an inode. This extended -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 17:39:11.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 17:39:55.000000000 +0300 -@@ -1354,8 +1354,10 @@ - } else { - sbi->s_inode_size = le16_to_cpu(es->s_inode_size); - sbi->s_first_ino = le32_to_cpu(es->s_first_ino); -- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) { -- printk (KERN_ERR -+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || -+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) || -+ (sbi->s_inode_size > blocksize)) { -+ printk (KERN_ERR - "EXT3-fs: unsupported inode size: %d\n", - sbi->s_inode_size); - goto failed_mount; -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 17:39:10.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 17:39:55.000000000 +0300 -@@ -268,6 +268,8 @@ - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -+ __u16 i_extra_isize; -+ __u16 i_pad1; - }; - - #define i_size_high i_dir_acl -Index: linux-2.4.21-chaos/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs_i.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs_i.h 2003-12-12 17:39:55.000000000 +0300 -@@ -76,6 +76,9 @@ - */ - loff_t i_disksize; - -+ /* on-disk additional length */ -+ __u16 i_extra_isize; -+ - /* - * truncate_sem is for serialising ext3_truncate() against - * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-sles.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-sles.patch deleted file mode 100644 index 5cc683f..0000000 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-sles.patch +++ /dev/null @@ -1,758 +0,0 @@ - fs/ext3/ialloc.c | 6 - fs/ext3/inode.c | 12 - fs/ext3/super.c | 6 - fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++- - include/linux/ext3_fs.h | 2 - include/linux/ext3_fs_i.h | 3 - 6 files changed, 615 insertions(+), 11 deletions(-) - -Index: linux-2.4.21-273/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-273.orig/fs/ext3/ialloc.c 2005-04-05 20:00:00.732329548 -0400 -+++ linux-2.4.21-273/fs/ext3/ialloc.c 2005-04-05 20:01:09.836317838 -0400 -@@ -576,6 +576,12 @@ - insert_inode_hash(inode); - inode->i_generation = sb->u.ext3_sb.s_next_generation++; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) { -+ EXT3_I(inode)->i_extra_isize = sizeof(__u16) /* i_extra_isize */ -+ + sizeof(__u16); /* i_pad1 */ -+ } else -+ EXT3_I(inode)->i_extra_isize = 0; -+ - inode->u.ext3_i.i_state = EXT3_STATE_NEW; - err = ext3_get_inode_loc_new(inode, &iloc, 1); - if (err) goto fail; -Index: linux-2.4.21-273/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-273.orig/fs/ext3/inode.c 2005-04-05 20:00:02.455079957 -0400 -+++ linux-2.4.21-273/fs/ext3/inode.c 2005-04-05 20:00:11.012840119 -0400 -@@ -2341,6 +2341,12 @@ - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ EXT3_I(inode)->i_extra_isize = -+ le16_to_cpu(raw_inode->i_extra_isize); -+ else -+ EXT3_I(inode)->i_extra_isize = 0; -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; -@@ -2401,6 +2407,8 @@ - if (err) - goto out_brelse; - } -+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) -+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb)); - raw_inode->i_mode = cpu_to_le16(inode->i_mode); - if(!(test_opt(inode->i_sb, NO_UID32))) { - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); -@@ -2484,6 +2492,10 @@ - else for (block = 0; block < EXT3_N_BLOCKS; block++) - raw_inode->i_block[block] = inode->u.ext3_i.i_data[block]; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ raw_inode->i_extra_isize = -+ cpu_to_le16(EXT3_I(inode)->i_extra_isize); -+ - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) -Index: linux-2.4.21-273/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.21-273.orig/fs/ext3/xattr.c 2005-04-05 19:59:59.134561031 -0400 -+++ linux-2.4.21-273/fs/ext3/xattr.c 2005-04-05 20:00:11.014839829 -0400 -@@ -88,6 +88,9 @@ - struct buffer_head *, - struct ext3_xattr_header *); - -+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); -+ - #ifdef CONFIG_EXT3_FS_XATTR_SHARING - - static int ext3_xattr_cache_insert(struct buffer_head *); -@@ -256,17 +259,12 @@ - } - - /* -- * ext3_xattr_get() -- * -- * Copy an extended attribute into the buffer -- * provided, or compute the buffer size required. -- * Buffer is NULL to compute the size of the buffer required. -+ * ext3_xattr_block_get() - * -- * Returns a negative error number on failure, or the number of bytes -- * used / required on success. -+ * routine looks for attribute in EA block and returns it's value and size - */ - int --ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; -@@ -359,6 +357,94 @@ - } - - /* -+ * ext3_xattr_ibody_get() -+ * -+ * routine looks for attribute in inode body and returns it's value and size -+ */ -+int -+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int size, name_len = strlen(name), storage_size; -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOENT; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ goto found; -+ last = next; -+ } -+ -+ /* can't find EA */ -+ brelse(iloc.bh); -+ return -ENOENT; -+ -+found: -+ size = le32_to_cpu(last->e_value_size); -+ if (buffer) { -+ ret = -ERANGE; -+ if (buffer_size >= size) { -+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs), -+ size); -+ ret = size; -+ } -+ } else -+ ret = size; -+ brelse(iloc.bh); -+ return ret; -+} -+ -+int ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int err; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_get(inode, name_index, name, -+ buffer, buffer_size); -+ if (err < 0) -+ /* search was unsuccessful, try to find EA in dedicated block */ -+ err = ext3_xattr_block_get(inode, name_index, name, -+ buffer, buffer_size); -+ return err; -+} -+ -+/* - * ext3_xattr_list() - * - * Copy a list of attribute names into the buffer -@@ -369,7 +455,7 @@ - * used / required on success. - */ - int --ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; - struct ext3_xattr_entry *entry; -@@ -446,6 +532,131 @@ - return error; - } - -+/* ext3_xattr_ibody_list() -+ * -+ * generate list of attributes stored in inode body -+ */ -+int -+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ char *start, *end, *buf; -+ struct ext3_iloc iloc; -+ int storage_size; -+ int ret; -+ int size = 0; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return 0; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return 0; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ -+ if (!buffer) { -+ ret = size; -+ goto cleanup; -+ } else { -+ ret = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ last = (struct ext3_xattr_entry *) start; -+ buf = buffer; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ ret = size; -+cleanup: -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ int error; -+ int size = buffer_size; -+ -+ /* get list of attributes stored in inode body */ -+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size); -+ if (error < 0) { -+ /* some error occured while collecting -+ * attributes in inode body */ -+ size = 0; -+ goto cleanup; -+ } -+ size = error; -+ -+ /* get list of attributes stored in dedicated block */ -+ if (buffer) { -+ buffer_size -= error; -+ if (buffer_size <= 0) { -+ buffer = NULL; -+ buffer_size = 0; -+ } else -+ buffer += error; -+ } -+ -+ error = ext3_xattr_block_list(inode, buffer, buffer_size); -+ if (error < 0) -+ /* listing was successful, so we return len */ -+ size = 0; -+ -+cleanup: -+ return error + size; -+} -+ - /* - * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is - * not set, set it. -@@ -480,6 +691,102 @@ - */ - int - ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry entry; -+ int err, where = 0, found = 0, total; -+ int free1 = -1, free2 = -1; -+ int name_len; -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize) -+ return -ERANGE; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1); -+ if (err == 0) { -+ /* found EA in inode */ -+ found = 1; -+ where = 0; -+ } else if (err == -ENOENT) { -+ /* there is no such attribute in inode body */ -+ /* try to find attribute in dedicated block */ -+ err = ext3_xattr_block_find(inode, name_index, name, -+ &entry, &free2); -+ if (err != 0 && err != -ENOENT) { -+ /* not found EA in block */ -+ goto finish; -+ } else if (err == 0) { -+ /* found EA in block */ -+ where = 1; -+ found = 1; -+ } -+ } else -+ goto finish; -+ -+ /* check flags: may replace? may create ? */ -+ if (found && (flags & XATTR_CREATE)) { -+ err = -EEXIST; -+ goto finish; -+ } else if (!found && (flags & XATTR_REPLACE)) { -+ err = -ENODATA; -+ goto finish; -+ } -+ -+ /* check if we have enough space to store attribute */ -+ total = EXT3_XATTR_LEN(strlen(name)) + value_len; -+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) { -+ /* have no enough space */ -+ err = -ENOSPC; -+ goto finish; -+ } -+ -+ /* time to remove attribute */ -+ if (found) { -+ if (where == 0) { -+ /* EA is stored in inode body */ -+ ext3_xattr_ibody_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } else { -+ /* EA is stored in separated block */ -+ ext3_xattr_block_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } -+ } -+ -+ /* try to store EA in inode body */ -+ err = ext3_xattr_ibody_set(handle, inode, name_index, name, -+ value, value_len, flags); -+ if (err) { -+ /* can't store EA in inode body */ -+ /* try to store in block */ -+ err = ext3_xattr_block_set(handle, inode, name_index, -+ name, value, value_len, flags); -+ } -+ -+finish: -+ return err; -+} -+ -+/* -+ * ext3_xattr_block_set() -+ * -+ * this routine add/remove/replace attribute in EA block -+ */ -+int -+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, - int flags) - { -@@ -870,6 +1177,279 @@ - } - - /* -+ * ext3_xattr_ibody_find() -+ * -+ * search attribute and calculate free space in inode body -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_ibody_find(struct inode *inode, int name_index, -+ const char *name, struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return ret; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return -EIO; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ *free = storage_size - sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) { -+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry)); -+ ret = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(last->e_name_len); -+ *free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_block_find() -+ * -+ * search attribute and calculate free space in EA block (if it allocated) -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, -+ struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ char *end; -+ int name_len, error = -ENOENT; -+ -+ if (!EXT3_I(inode)->i_file_acl) { -+ *free = inode->i_sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - -+ sizeof(__u32); -+ return -ENOENT; -+ } -+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl); -+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, -+ EXT3_I(inode)->i_file_acl); -+ brelse(bh); -+ return -EIO; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ *free = bh->b_size - sizeof(__u32); -+ -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) { -+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry)); -+ error = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(entry->e_name_len); -+ *free -= le32_to_cpu(entry->e_value_size); -+ } -+ entry = next; -+ } -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_inode_set() -+ * -+ * this routine add/remove/replace attribute in inode body -+ */ -+int -+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry *last, *next, *here = NULL; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int esize = EXT3_XATTR_LEN(name_len); -+ struct buffer_head *bh; -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ int free, min_offs; -+ char *start, *end; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOSPC; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return err; -+ raw_inode = iloc.raw_inode; -+ bh = iloc.bh; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) { -+ /* inode had no attributes before */ -+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC); -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ min_offs = storage_size; -+ free = storage_size - sizeof(__u32); -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set", -+ "inode %ld", inode->i_ino); -+ brelse(bh); -+ return -EIO; -+ } -+ -+ if (last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ here = last; -+ else { -+ /* we calculate all but our attribute -+ * because it will be removed before changing */ -+ free -= EXT3_XATTR_LEN(last->e_name_len); -+ free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ if (value && (esize + value_len > free)) { -+ brelse(bh); -+ return -ENOSPC; -+ } -+ -+ err = ext3_reserve_inode_write(handle, inode, &iloc); -+ if (err) { -+ brelse(bh); -+ return err; -+ } -+ -+ if (here) { -+ /* time to remove old value */ -+ struct ext3_xattr_entry *e; -+ int size = le32_to_cpu(here->e_value_size); -+ int border = le16_to_cpu(here->e_value_offs); -+ char *src; -+ -+ /* move tail */ -+ memmove(start + min_offs + size, start + min_offs, -+ border - min_offs); -+ -+ /* recalculate offsets */ -+ e = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(e)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e); -+ int offs = le16_to_cpu(e->e_value_offs); -+ if (offs < border) -+ e->e_value_offs = -+ cpu_to_le16(offs + size); -+ e = next; -+ } -+ min_offs += size; -+ -+ /* remove entry */ -+ border = EXT3_XATTR_LEN(here->e_name_len); -+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len); -+ size = (char *) last - src; -+ if ((char *) here + size > end) -+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n", -+ __FILE__, __LINE__, here, size, end); -+ memmove(here, src, size); -+ last = (struct ext3_xattr_entry *) ((char *) last - border); -+ *((__u32 *) last) = 0; -+ } -+ -+ if (value) { -+ int offs = min_offs - value_len; -+ /* use last to create new entry */ -+ last->e_name_len = strlen(name); -+ last->e_name_index = name_index; -+ last->e_value_offs = cpu_to_le16(offs); -+ last->e_value_size = cpu_to_le32(value_len); -+ last->e_hash = last->e_value_block = 0; -+ memset(last->e_name, 0, esize); -+ memcpy(last->e_name, name, last->e_name_len); -+ if (start + offs + value_len > end) -+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n", -+ __FILE__, __LINE__, start, offs, -+ value_len, end); -+ memcpy(start + offs, value, value_len); -+ last = EXT3_XATTR_NEXT(last); -+ *((__u32 *) last) = 0; -+ } -+ -+ ext3_mark_iloc_dirty(handle, inode, &iloc); -+ brelse(bh); -+ -+ return 0; -+} -+ -+/* - * ext3_xattr_set_trans() - * - * Like ext3_xattr_set_handle, but start from an inode. This extended -Index: linux-2.4.21-273/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-273.orig/fs/ext3/super.c 2005-04-05 20:00:04.146834858 -0400 -+++ linux-2.4.21-273/fs/ext3/super.c 2005-04-05 20:00:11.016839539 -0400 -@@ -1334,7 +1334,9 @@ - } else { - sbi->s_inode_size = le16_to_cpu(es->s_inode_size); - sbi->s_first_ino = le32_to_cpu(es->s_first_ino); -- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) { -+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || -+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) || -+ (sbi->s_inode_size > blocksize)) { - printk (KERN_ERR - "EXT3-fs: unsupported inode size: %d\n", - sbi->s_inode_size); -Index: linux-2.4.21-273/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-273.orig/include/linux/ext3_fs.h 2005-04-05 20:00:02.461079088 -0400 -+++ linux-2.4.21-273/include/linux/ext3_fs.h 2005-04-05 20:00:11.017839394 -0400 -@@ -264,6 +264,8 @@ - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -+ __u16 i_extra_isize; -+ __u16 i_pad1; - }; - - #define i_size_high i_dir_acl -Index: linux-2.4.21-273/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.21-273.orig/include/linux/ext3_fs_i.h 2005-01-17 07:09:09.000000000 -0500 -+++ linux-2.4.21-273/include/linux/ext3_fs_i.h 2005-04-05 20:00:11.017839394 -0400 -@@ -76,6 +76,9 @@ - */ - loff_t i_disksize; - -+ /* on-disk additional length */ -+ __u16 i_extra_isize; -+ - /* - * truncate_sem is for serialising ext3_truncate() against - * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-suse2.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-suse2.patch deleted file mode 100644 index 90ff24a..0000000 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.21-suse2.patch +++ /dev/null @@ -1,758 +0,0 @@ - fs/ext3/ialloc.c | 6 - fs/ext3/inode.c | 12 - fs/ext3/super.c | 6 - fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++- - include/linux/ext3_fs.h | 2 - include/linux/ext3_fs_i.h | 3 - 6 files changed, 615 insertions(+), 11 deletions(-) - -Index: linux-2.4.21-chaos/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c 2003-12-12 17:39:10.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ialloc.c 2003-12-12 17:39:55.000000000 +0300 -@@ -580,6 +580,10 @@ - inode->i_generation = sbi->s_next_generation++; - - inode->u.ext3_i.i_state = EXT3_STATE_NEW; -+ inode->u.ext3_i.i_extra_isize = -+ (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ? -+ sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; -+ - err = ext3_get_inode_loc_new(inode, &iloc, 1); - if (err) goto fail; - BUFFER_TRACE(iloc->bh, "get_write_access"); -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 17:39:11.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 17:39:55.000000000 +0300 -@@ -2502,6 +2502,12 @@ - ei->i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&ei->i_orphan); - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ EXT3_I(inode)->i_extra_isize = -+ le16_to_cpu(raw_inode->i_extra_isize); -+ else -+ EXT3_I(inode)->i_extra_isize = 0; -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; -@@ -2564,6 +2570,8 @@ - if (err) - goto out_brelse; - } -+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) -+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb)); - raw_inode->i_mode = cpu_to_le16(inode->i_mode); - if(!(test_opt(inode->i_sb, NO_UID32))) { - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); -@@ -2646,6 +2654,10 @@ - else for (block = 0; block < EXT3_N_BLOCKS; block++) - raw_inode->i_block[block] = ei->i_data[block]; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ raw_inode->i_extra_isize = -+ cpu_to_le16(EXT3_I(inode)->i_extra_isize); -+ - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) -Index: linux-2.4.21-chaos/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr.c 2003-12-12 17:38:44.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/xattr.c 2003-12-12 17:42:58.000000000 +0300 -@@ -88,6 +88,9 @@ - struct buffer_head *, - struct ext3_xattr_header *); - -+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); -+ - #ifdef CONFIG_EXT3_FS_XATTR_SHARING - - static int ext3_xattr_cache_insert(struct buffer_head *); -@@ -256,17 +259,12 @@ - } - - /* -- * ext3_xattr_get() -- * -- * Copy an extended attribute into the buffer -- * provided, or compute the buffer size required. -- * Buffer is NULL to compute the size of the buffer required. -+ * ext3_xattr_block_get() - * -- * Returns a negative error number on failure, or the number of bytes -- * used / required on success. -+ * routine looks for attribute in EA block and returns it's value and size - */ - int --ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; -@@ -359,6 +357,94 @@ - } - - /* -+ * ext3_xattr_ibody_get() -+ * -+ * routine looks for attribute in inode body and returns it's value and size -+ */ -+int -+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int size, name_len = strlen(name), storage_size; -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOENT; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ goto found; -+ last = next; -+ } -+ -+ /* can't find EA */ -+ brelse(iloc.bh); -+ return -ENOENT; -+ -+found: -+ size = le32_to_cpu(last->e_value_size); -+ if (buffer) { -+ ret = -ERANGE; -+ if (buffer_size >= size) { -+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs), -+ size); -+ ret = size; -+ } -+ } else -+ ret = size; -+ brelse(iloc.bh); -+ return ret; -+} -+ -+int ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int err; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_get(inode, name_index, name, -+ buffer, buffer_size); -+ if (err < 0) -+ /* search was unsuccessful, try to find EA in dedicated block */ -+ err = ext3_xattr_block_get(inode, name_index, name, -+ buffer, buffer_size); -+ return err; -+} -+ -+/* - * ext3_xattr_list() - * - * Copy a list of attribute names into the buffer -@@ -369,7 +455,7 @@ - * used / required on success. - */ - int --ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; - struct ext3_xattr_entry *entry; -@@ -446,6 +532,131 @@ - return error; - } - -+/* ext3_xattr_ibody_list() -+ * -+ * generate list of attributes stored in inode body -+ */ -+int -+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ char *start, *end, *buf; -+ struct ext3_iloc iloc; -+ int storage_size; -+ int ret; -+ int size = 0; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return 0; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return 0; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ -+ if (!buffer) { -+ ret = size; -+ goto cleanup; -+ } else { -+ ret = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ last = (struct ext3_xattr_entry *) start; -+ buf = buffer; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ ret = size; -+cleanup: -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ int error; -+ int size = buffer_size; -+ -+ /* get list of attributes stored in inode body */ -+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size); -+ if (error < 0) { -+ /* some error occured while collecting -+ * attributes in inode body */ -+ size = 0; -+ goto cleanup; -+ } -+ size = error; -+ -+ /* get list of attributes stored in dedicated block */ -+ if (buffer) { -+ buffer_size -= error; -+ if (buffer_size <= 0) { -+ buffer = NULL; -+ buffer_size = 0; -+ } else -+ buffer += error; -+ } -+ -+ error = ext3_xattr_block_list(inode, buffer, buffer_size); -+ if (error < 0) -+ /* listing was successful, so we return len */ -+ size = 0; -+ -+cleanup: -+ return error + size; -+} -+ - /* - * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is - * not set, set it. -@@ -480,6 +691,102 @@ - */ - int - ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry entry; -+ int err, where = 0, found = 0, total; -+ int free1 = -1, free2 = -1; -+ int name_len; -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize) -+ return -ERANGE; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1); -+ if (err == 0) { -+ /* found EA in inode */ -+ found = 1; -+ where = 0; -+ } else if (err == -ENOENT) { -+ /* there is no such attribute in inode body */ -+ /* try to find attribute in dedicated block */ -+ err = ext3_xattr_block_find(inode, name_index, name, -+ &entry, &free2); -+ if (err != 0 && err != -ENOENT) { -+ /* not found EA in block */ -+ goto finish; -+ } else if (err == 0) { -+ /* found EA in block */ -+ where = 1; -+ found = 1; -+ } -+ } else -+ goto finish; -+ -+ /* check flags: may replace? may create ? */ -+ if (found && (flags & XATTR_CREATE)) { -+ err = -EEXIST; -+ goto finish; -+ } else if (!found && (flags & XATTR_REPLACE)) { -+ err = -ENODATA; -+ goto finish; -+ } -+ -+ /* check if we have enough space to store attribute */ -+ total = EXT3_XATTR_LEN(strlen(name)) + value_len; -+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) { -+ /* have no enough space */ -+ err = -ENOSPC; -+ goto finish; -+ } -+ -+ /* time to remove attribute */ -+ if (found) { -+ if (where == 0) { -+ /* EA is stored in inode body */ -+ ext3_xattr_ibody_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } else { -+ /* EA is stored in separated block */ -+ ext3_xattr_block_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } -+ } -+ -+ /* try to store EA in inode body */ -+ err = ext3_xattr_ibody_set(handle, inode, name_index, name, -+ value, value_len, flags); -+ if (err) { -+ /* can't store EA in inode body */ -+ /* try to store in block */ -+ err = ext3_xattr_block_set(handle, inode, name_index, -+ name, value, value_len, flags); -+ } -+ -+finish: -+ return err; -+} -+ -+/* -+ * ext3_xattr_block_set() -+ * -+ * this routine add/remove/replace attribute in EA block -+ */ -+int -+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, - int flags) - { -@@ -868,6 +1174,279 @@ - } - - /* -+ * ext3_xattr_ibody_find() -+ * -+ * search attribute and calculate free space in inode body -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_ibody_find(struct inode *inode, int name_index, -+ const char *name, struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return ret; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return -EIO; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ *free = storage_size - sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) { -+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry)); -+ ret = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(last->e_name_len); -+ *free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_block_find() -+ * -+ * search attribute and calculate free space in EA block (if it allocated) -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, -+ struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ char *end; -+ int name_len, error = -ENOENT; -+ -+ if (!EXT3_I(inode)->i_file_acl) { -+ *free = inode->i_sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - -+ sizeof(__u32); -+ return -ENOENT; -+ } -+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl); -+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, -+ EXT3_I(inode)->i_file_acl); -+ brelse(bh); -+ return -EIO; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ *free = bh->b_size - sizeof(__u32); -+ -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) { -+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry)); -+ error = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(entry->e_name_len); -+ *free -= le32_to_cpu(entry->e_value_size); -+ } -+ entry = next; -+ } -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_inode_set() -+ * -+ * this routine add/remove/replace attribute in inode body -+ */ -+int -+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry *last, *next, *here = NULL; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int esize = EXT3_XATTR_LEN(name_len); -+ struct buffer_head *bh; -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ int free, min_offs; -+ char *start, *end; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOSPC; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return err; -+ raw_inode = iloc.raw_inode; -+ bh = iloc.bh; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) { -+ /* inode had no attributes before */ -+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC); -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ min_offs = storage_size; -+ free = storage_size - sizeof(__u32); -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set", -+ "inode %ld", inode->i_ino); -+ brelse(bh); -+ return -EIO; -+ } -+ -+ if (last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ here = last; -+ else { -+ /* we calculate all but our attribute -+ * because it will be removed before changing */ -+ free -= EXT3_XATTR_LEN(last->e_name_len); -+ free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ if (value && (esize + value_len > free)) { -+ brelse(bh); -+ return -ENOSPC; -+ } -+ -+ err = ext3_reserve_inode_write(handle, inode, &iloc); -+ if (err) { -+ brelse(bh); -+ return err; -+ } -+ -+ if (here) { -+ /* time to remove old value */ -+ struct ext3_xattr_entry *e; -+ int size = le32_to_cpu(here->e_value_size); -+ int border = le16_to_cpu(here->e_value_offs); -+ char *src; -+ -+ /* move tail */ -+ memmove(start + min_offs + size, start + min_offs, -+ border - min_offs); -+ -+ /* recalculate offsets */ -+ e = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(e)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e); -+ int offs = le16_to_cpu(e->e_value_offs); -+ if (offs < border) -+ e->e_value_offs = -+ cpu_to_le16(offs + size); -+ e = next; -+ } -+ min_offs += size; -+ -+ /* remove entry */ -+ border = EXT3_XATTR_LEN(here->e_name_len); -+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len); -+ size = (char *) last - src; -+ if ((char *) here + size > end) -+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n", -+ __FILE__, __LINE__, here, size, end); -+ memmove(here, src, size); -+ last = (struct ext3_xattr_entry *) ((char *) last - border); -+ *((__u32 *) last) = 0; -+ } -+ -+ if (value) { -+ int offs = min_offs - value_len; -+ /* use last to create new entry */ -+ last->e_name_len = strlen(name); -+ last->e_name_index = name_index; -+ last->e_value_offs = cpu_to_le16(offs); -+ last->e_value_size = cpu_to_le32(value_len); -+ last->e_hash = last->e_value_block = 0; -+ memset(last->e_name, 0, esize); -+ memcpy(last->e_name, name, last->e_name_len); -+ if (start + offs + value_len > end) -+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n", -+ __FILE__, __LINE__, start, offs, -+ value_len, end); -+ memcpy(start + offs, value, value_len); -+ last = EXT3_XATTR_NEXT(last); -+ *((__u32 *) last) = 0; -+ } -+ -+ ext3_mark_iloc_dirty(handle, inode, &iloc); -+ brelse(bh); -+ -+ return 0; -+} -+ -+/* - * ext3_xattr_set_trans() - * - * Like ext3_xattr_set_handle, but start from an inode. This extended -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 17:39:11.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 17:39:55.000000000 +0300 -@@ -1354,8 +1354,10 @@ - } else { - sbi->s_inode_size = le16_to_cpu(es->s_inode_size); - sbi->s_first_ino = le32_to_cpu(es->s_first_ino); -- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) { -- printk (KERN_ERR -+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || -+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) || -+ (sbi->s_inode_size > blocksize)) { -+ printk (KERN_ERR - "EXT3-fs: unsupported inode size: %d\n", - sbi->s_inode_size); - goto failed_mount; -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 17:39:10.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 17:39:55.000000000 +0300 -@@ -268,6 +268,8 @@ - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -+ __u16 i_extra_isize; -+ __u16 i_pad1; - }; - - #define i_size_high i_dir_acl -Index: linux-2.4.21-chaos/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs_i.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs_i.h 2003-12-12 17:39:55.000000000 +0300 -@@ -76,6 +76,9 @@ - */ - loff_t i_disksize; - -+ /* on-disk additional length */ -+ __u16 i_extra_isize; -+ - /* - * truncate_sem is for serialising ext3_truncate() against - * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.22-rh.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.22-rh.patch deleted file mode 100644 index 6b22a71..0000000 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.22-rh.patch +++ /dev/null @@ -1,755 +0,0 @@ - fs/ext3/ialloc.c | 6 - fs/ext3/inode.c | 12 - fs/ext3/super.c | 6 - fs/ext3/xattr.c | 597 +++++++++++++++++++++++++++++++++++++++++++++- - include/linux/ext3_fs.h | 2 - include/linux/ext3_fs_i.h | 3 - 6 files changed, 615 insertions(+), 11 deletions(-) - ---- linux-2.4.22-ac1/fs/ext3/ialloc.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:56.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/ialloc.c 2003-10-08 15:13:31.000000000 +0400 -@@ -715,6 +715,10 @@ have_bit_and_group: - inode->i_generation = sb->u.ext3_sb.s_next_generation++; - - inode->u.ext3_i.i_state = EXT3_STATE_NEW; -+ inode->u.ext3_i.i_extra_isize = -+ (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ? -+ sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; -+ - err = ext3_get_inode_loc_new(inode, &iloc, 1); - if (err) goto fail; - BUFFER_TRACE(iloc->bh, "get_write_access"); ---- linux-2.4.22-ac1/fs/ext3/inode.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/inode.c 2003-10-08 15:14:57.000000000 +0400 -@@ -2229,6 +2229,12 @@ void ext3_read_inode(struct inode * inod - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ inode->u.ext3_i.i_extra_isize = -+ le16_to_cpu(raw_inode->i_extra_isize); -+ else -+ inode->u.ext3_i.i_extra_isize = 0; -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; -@@ -2277,6 +2283,8 @@ static int ext3_do_update_inode(handle_t - if (err) - goto out_brelse; - } -+ if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) -+ memset(raw_inode, 0, EXT3_INODE_SIZE(inode->i_sb)); - raw_inode->i_mode = cpu_to_le16(inode->i_mode); - if(!(test_opt(inode->i_sb, NO_UID32))) { - raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid)); -@@ -2360,6 +2368,10 @@ static int ext3_do_update_inode(handle_t - else for (block = 0; block < EXT3_N_BLOCKS; block++) - raw_inode->i_block[block] = inode->u.ext3_i.i_data[block]; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ raw_inode->i_extra_isize = -+ cpu_to_le16(EXT3_I(inode)->i_extra_isize); -+ - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) ---- linux-2.4.22-ac1/fs/ext3/super.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-10-08 15:13:31.000000000 +0400 -@@ -1299,8 +1299,10 @@ struct super_block * ext3_read_super (st - } else { - sbi->s_inode_size = le16_to_cpu(es->s_inode_size); - sbi->s_first_ino = le32_to_cpu(es->s_first_ino); -- if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) { -- printk (KERN_ERR -+ if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || -+ (sbi->s_inode_size & (sbi->s_inode_size - 1)) || -+ (sbi->s_inode_size > blocksize)) { -+ printk (KERN_ERR - "EXT3-fs: unsupported inode size: %d\n", - sbi->s_inode_size); - goto failed_mount; ---- linux-2.4.22-ac1/fs/ext3/xattr.c~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:56.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/xattr.c 2003-10-12 16:36:07.000000000 +0400 -@@ -100,6 +100,9 @@ - static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *, - struct ext3_xattr_header *); - -+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); -+ - #ifdef CONFIG_EXT3_FS_XATTR_SHARING - - static int ext3_xattr_cache_insert(struct buffer_head *); -@@ -348,17 +351,12 @@ ext3_removexattr(struct dentry *dentry, - } - - /* -- * ext3_xattr_get() -- * -- * Copy an extended attribute into the buffer -- * provided, or compute the buffer size required. -- * Buffer is NULL to compute the size of the buffer required. -+ * ext3_xattr_block_get() - * -- * Returns a negative error number on failure, or the number of bytes -- * used / required on success. -+ * routine looks for attribute in EA block and returns it's value and size - */ - int --ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; -@@ -447,6 +445,94 @@ cleanup: - } - - /* -+ * ext3_xattr_ibody_get() -+ * -+ * routine looks for attribute in inode body and returns it's value and size -+ */ -+int -+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int size, name_len = strlen(name), storage_size; -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOENT; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ goto found; -+ last = next; -+ } -+ -+ /* can't find EA */ -+ brelse(iloc.bh); -+ return -ENOENT; -+ -+found: -+ size = le32_to_cpu(last->e_value_size); -+ if (buffer) { -+ ret = -ERANGE; -+ if (buffer_size >= size) { -+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs), -+ size); -+ ret = size; -+ } -+ } else -+ ret = size; -+ brelse(iloc.bh); -+ return ret; -+} -+ -+int ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int err; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_get(inode, name_index, name, -+ buffer, buffer_size); -+ if (err < 0) -+ /* search was unsuccessful, try to find EA in dedicated block */ -+ err = ext3_xattr_block_get(inode, name_index, name, -+ buffer, buffer_size); -+ return err; -+} -+ -+/* - * ext3_xattr_list() - * - * Copy a list of attribute names into the buffer -@@ -457,7 +543,7 @@ cleanup: - * used / required on success. - */ - int --ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; - struct ext3_xattr_entry *entry; -@@ -530,6 +616,131 @@ cleanup: - return error; - } - -+/* ext3_xattr_ibody_list() -+ * -+ * generate list of attributes stored in inode body -+ */ -+int -+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ char *start, *end, *buf; -+ struct ext3_iloc iloc; -+ int storage_size; -+ int ret; -+ int size = 0; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return 0; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return 0; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ -+ if (!buffer) { -+ ret = size; -+ goto cleanup; -+ } else { -+ ret = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ last = (struct ext3_xattr_entry *) start; -+ buf = buffer; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ ret = size; -+cleanup: -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ int error; -+ int size = buffer_size; -+ -+ /* get list of attributes stored in inode body */ -+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size); -+ if (error < 0) { -+ /* some error occured while collecting -+ * attributes in inode body */ -+ size = 0; -+ goto cleanup; -+ } -+ size = error; -+ -+ /* get list of attributes stored in dedicated block */ -+ if (buffer) { -+ buffer_size -= error; -+ if (buffer_size <= 0) { -+ buffer = NULL; -+ buffer_size = 0; -+ } else -+ buffer += error; -+ } -+ -+ error = ext3_xattr_block_list(inode, buffer, buffer_size); -+ if (error < 0) -+ /* listing was successful, so we return len */ -+ size = 0; -+ -+cleanup: -+ return error + size; -+} -+ - /* - * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is - * not set, set it. -@@ -553,6 +764,279 @@ static void ext3_xattr_update_super_bloc - } - - /* -+ * ext3_xattr_ibody_find() -+ * -+ * search attribute and calculate free space in inode body -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_ibody_find(struct inode *inode, int name_index, -+ const char *name, struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return ret; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return -EIO; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ *free = storage_size - sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) { -+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry)); -+ ret = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(last->e_name_len); -+ *free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_block_find() -+ * -+ * search attribute and calculate free space in EA block (if it allocated) -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, -+ struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ char *end; -+ int name_len, error = -ENOENT; -+ -+ if (!EXT3_I(inode)->i_file_acl) { -+ *free = inode->i_sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - -+ sizeof(__u32); -+ return -ENOENT; -+ } -+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl); -+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, -+ EXT3_I(inode)->i_file_acl); -+ brelse(bh); -+ return -EIO; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ *free = bh->b_size - sizeof(__u32); -+ -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) { -+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry)); -+ error = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(entry->e_name_len); -+ *free -= le32_to_cpu(entry->e_value_size); -+ } -+ entry = next; -+ } -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_inode_set() -+ * -+ * this routine add/remove/replace attribute in inode body -+ */ -+int -+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry *last, *next, *here = NULL; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int esize = EXT3_XATTR_LEN(name_len); -+ struct buffer_head *bh; -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ int free, min_offs; -+ char *start, *end; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOSPC; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return err; -+ raw_inode = iloc.raw_inode; -+ bh = iloc.bh; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) { -+ /* inode had no attributes before */ -+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC); -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ min_offs = storage_size; -+ free = storage_size - sizeof(__u32); -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set", -+ "inode %ld", inode->i_ino); -+ brelse(bh); -+ return -EIO; -+ } -+ -+ if (last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ here = last; -+ else { -+ /* we calculate all but our attribute -+ * because it will be removed before changing */ -+ free -= EXT3_XATTR_LEN(last->e_name_len); -+ free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ if (value && (esize + value_len > free)) { -+ brelse(bh); -+ return -ENOSPC; -+ } -+ -+ err = ext3_reserve_inode_write(handle, inode, &iloc); -+ if (err) { -+ brelse(bh); -+ return err; -+ } -+ -+ if (here) { -+ /* time to remove old value */ -+ struct ext3_xattr_entry *e; -+ int size = le32_to_cpu(here->e_value_size); -+ int border = le16_to_cpu(here->e_value_offs); -+ char *src; -+ -+ /* move tail */ -+ memmove(start + min_offs + size, start + min_offs, -+ border - min_offs); -+ -+ /* recalculate offsets */ -+ e = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(e)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e); -+ int offs = le16_to_cpu(e->e_value_offs); -+ if (offs < border) -+ e->e_value_offs = -+ cpu_to_le16(offs + size); -+ e = next; -+ } -+ min_offs += size; -+ -+ /* remove entry */ -+ border = EXT3_XATTR_LEN(here->e_name_len); -+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len); -+ size = (char *) last - src; -+ if ((char *) here + size > end) -+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n", -+ __FILE__, __LINE__, here, size, end); -+ memmove(here, src, size); -+ last = (struct ext3_xattr_entry *) ((char *) last - border); -+ *((__u32 *) last) = 0; -+ } -+ -+ if (value) { -+ int offs = min_offs - value_len; -+ /* use last to create new entry */ -+ last->e_name_len = strlen(name); -+ last->e_name_index = name_index; -+ last->e_value_offs = cpu_to_le16(offs); -+ last->e_value_size = cpu_to_le32(value_len); -+ last->e_hash = last->e_value_block = 0; -+ memset(last->e_name, 0, esize); -+ memcpy(last->e_name, name, last->e_name_len); -+ if (start + offs + value_len > end) -+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n", -+ __FILE__, __LINE__, start, offs, -+ value_len, end); -+ memcpy(start + offs, value, value_len); -+ last = EXT3_XATTR_NEXT(last); -+ *((__u32 *) last) = 0; -+ } -+ -+ ext3_mark_iloc_dirty(handle, inode, &iloc); -+ brelse(bh); -+ -+ return 0; -+} -+ -+/* - * ext3_xattr_set() - * - * Create, replace or remove an extended attribute for this inode. Buffer -@@ -566,6 +1050,101 @@ static void ext3_xattr_update_super_bloc - */ - int - ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, int flags) -+{ -+ struct ext3_xattr_entry entry; -+ int err, where = 0, found = 0, total; -+ int free1 = -1, free2 = -1; -+ int name_len; -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize) -+ return -ERANGE; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1); -+ if (err == 0) { -+ /* found EA in inode */ -+ found = 1; -+ where = 0; -+ } else if (err == -ENOENT) { -+ /* there is no such attribute in inode body */ -+ /* try to find attribute in dedicated block */ -+ err = ext3_xattr_block_find(inode, name_index, name, -+ &entry, &free2); -+ if (err != 0 && err != -ENOENT) { -+ /* not found EA in block */ -+ goto finish; -+ } else if (err == 0) { -+ /* found EA in block */ -+ where = 1; -+ found = 1; -+ } -+ } else -+ goto finish; -+ -+ /* check flags: may replace? may create ? */ -+ if (found && (flags & XATTR_CREATE)) { -+ err = -EEXIST; -+ goto finish; -+ } else if (!found && (flags & XATTR_REPLACE)) { -+ err = -ENODATA; -+ goto finish; -+ } -+ -+ /* check if we have enough space to store attribute */ -+ total = EXT3_XATTR_LEN(strlen(name)) + value_len; -+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) { -+ /* have no enough space */ -+ err = -ENOSPC; -+ goto finish; -+ } -+ -+ /* time to remove attribute */ -+ if (found) { -+ if (where == 0) { -+ /* EA is stored in inode body */ -+ ext3_xattr_ibody_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } else { -+ /* EA is stored in separated block */ -+ ext3_xattr_block_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } -+ } -+ -+ /* try to store EA in inode body */ -+ err = ext3_xattr_ibody_set(handle, inode, name_index, name, -+ value, value_len, flags); -+ if (err) { -+ /* can't store EA in inode body */ -+ /* try to store in block */ -+ err = ext3_xattr_block_set(handle, inode, name_index, -+ name, value, value_len, flags); -+ } -+ -+finish: -+ return err; -+} -+ -+/* -+ * ext3_xattr_block_set() -+ * -+ * this routine add/remove/replace attribute in EA block -+ */ -+int -+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, int flags) - { - struct super_block *sb = inode->i_sb; -@@ -603,6 +1181,7 @@ ext3_xattr_set(handle_t *handle, struct - name_len = strlen(name); - if (name_len > 255 || value_len > sb->s_blocksize) - return -ERANGE; -+ - down(&ext3_xattr_sem); - - if (block) { ---- linux-2.4.22-ac1/include/linux/ext3_fs.h~ext3-ea-in-inode-2.4.22-rh 2003-10-08 13:57:57.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h 2003-10-08 15:13:31.000000000 +0400 -@@ -265,6 +265,8 @@ struct ext3_inode { - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -+ __u16 i_extra_isize; -+ __u16 i_pad1; - }; - - #define i_size_high i_dir_acl ---- linux-2.4.22-ac1/include/linux/ext3_fs_i.h~ext3-ea-in-inode-2.4.22-rh 2003-09-26 00:54:44.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_i.h 2003-10-08 15:13:31.000000000 +0400 -@@ -62,6 +62,9 @@ struct ext3_inode_info { - */ - loff_t i_disksize; - -+ /* on-disk additional length */ -+ __u16 i_extra_isize; -+ - /* - * truncate_sem is for serialising ext3_truncate() against - * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's - -_ diff --git a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.29.patch b/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.29.patch deleted file mode 100644 index 2376ffa..0000000 --- a/lustre/kernel_patches/patches/ext3-ea-in-inode-2.4.29.patch +++ /dev/null @@ -1,731 +0,0 @@ -Index: linux-2.4.29/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/ialloc.c 2005-05-03 15:56:43.831530296 +0300 -+++ linux-2.4.29/fs/ext3/ialloc.c 2005-05-03 16:07:32.990843080 +0300 -@@ -576,6 +576,10 @@ - inode->i_generation = sb->u.ext3_sb.s_next_generation++; - - inode->u.ext3_i.i_state = EXT3_STATE_NEW; -+ inode->u.ext3_i.i_extra_isize = -+ (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) ? -+ sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0; -+ - err = ext3_get_inode_loc_new(inode, &iloc, 1); - if (err) goto fail; - BUFFER_TRACE(iloc->bh, "get_write_access"); -Index: linux-2.4.29/fs/ext3/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/inode.c 2005-05-03 15:58:30.758274960 +0300 -+++ linux-2.4.29/fs/ext3/inode.c 2005-05-03 16:07:32.995842320 +0300 -@@ -2240,6 +2240,12 @@ - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ inode->u.ext3_i.i_extra_isize = -+ le16_to_cpu(raw_inode->i_extra_isize); -+ else -+ inode->u.ext3_i.i_extra_isize = 0; -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; -@@ -2367,6 +2373,10 @@ - else for (block = 0; block < EXT3_N_BLOCKS; block++) - raw_inode->i_block[block] = inode->u.ext3_i.i_data[block]; - -+ if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) -+ raw_inode->i_extra_isize = -+ cpu_to_le16(EXT3_I(inode)->i_extra_isize); -+ - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) -Index: linux-2.4.29/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/xattr.c 2005-04-07 19:31:00.000000000 +0300 -+++ linux-2.4.29/fs/ext3/xattr.c 2005-05-03 16:07:33.007840496 +0300 -@@ -100,6 +100,9 @@ - static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *, - struct ext3_xattr_header *); - -+int ext3_xattr_block_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); -+ - #ifdef CONFIG_EXT3_FS_XATTR_SHARING - - static int ext3_xattr_cache_insert(struct buffer_head *); -@@ -348,17 +351,12 @@ - } - - /* -- * ext3_xattr_get() -- * -- * Copy an extended attribute into the buffer -- * provided, or compute the buffer size required. -- * Buffer is NULL to compute the size of the buffer required. -+ * ext3_xattr_block_get() - * -- * Returns a negative error number on failure, or the number of bytes -- * used / required on success. -+ * routine looks for attribute in EA block and returns it's value and size - */ - int --ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, - void *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; -@@ -447,6 +445,94 @@ - } - - /* -+ * ext3_xattr_ibody_get() -+ * -+ * routine looks for attribute in inode body and returns it's value and size -+ */ -+int -+ext3_xattr_ibody_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int size, name_len = strlen(name), storage_size; -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOENT; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_get", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ goto found; -+ last = next; -+ } -+ -+ /* can't find EA */ -+ brelse(iloc.bh); -+ return -ENOENT; -+ -+found: -+ size = le32_to_cpu(last->e_value_size); -+ if (buffer) { -+ ret = -ERANGE; -+ if (buffer_size >= size) { -+ memcpy(buffer, start + le16_to_cpu(last->e_value_offs), -+ size); -+ ret = size; -+ } -+ } else -+ ret = size; -+ brelse(iloc.bh); -+ return ret; -+} -+ -+int ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ int err; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_get(inode, name_index, name, -+ buffer, buffer_size); -+ if (err < 0) -+ /* search was unsuccessful, try to find EA in dedicated block */ -+ err = ext3_xattr_block_get(inode, name_index, name, -+ buffer, buffer_size); -+ return err; -+} -+ -+/* - * ext3_xattr_list() - * - * Copy a list of attribute names into the buffer -@@ -457,7 +543,7 @@ - * used / required on success. - */ - int --ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) - { - struct buffer_head *bh = NULL; - struct ext3_xattr_entry *entry; -@@ -530,6 +616,131 @@ - return error; - } - -+/* ext3_xattr_ibody_list() -+ * -+ * generate list of attributes stored in inode body -+ */ -+int -+ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ char *start, *end, *buf; -+ struct ext3_iloc iloc; -+ int storage_size; -+ int ret; -+ int size = 0; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return 0; -+ -+ ret = ext3_get_inode_loc(inode, &iloc); -+ if (ret) -+ return ret; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return 0; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_list", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ -+ if (!buffer) { -+ ret = size; -+ goto cleanup; -+ } else { -+ ret = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ last = (struct ext3_xattr_entry *) start; -+ buf = buffer; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ struct ext3_xattr_handler *handler; -+ handler = ext3_xattr_handler(last->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, last->e_name, -+ last->e_name_len); -+ last = next; -+ } -+ ret = size; -+cleanup: -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ int error; -+ int size = buffer_size; -+ -+ /* get list of attributes stored in inode body */ -+ error = ext3_xattr_ibody_list(inode, buffer, buffer_size); -+ if (error < 0) { -+ /* some error occured while collecting -+ * attributes in inode body */ -+ size = 0; -+ goto cleanup; -+ } -+ size = error; -+ -+ /* get list of attributes stored in dedicated block */ -+ if (buffer) { -+ buffer_size -= error; -+ if (buffer_size <= 0) { -+ buffer = NULL; -+ buffer_size = 0; -+ } else -+ buffer += error; -+ } -+ -+ error = ext3_xattr_block_list(inode, buffer, buffer_size); -+ if (error < 0) -+ /* listing was successful, so we return len */ -+ size = 0; -+ -+cleanup: -+ return error + size; -+} -+ - /* - * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is - * not set, set it. -@@ -553,6 +764,279 @@ - } - - /* -+ * ext3_xattr_ibody_find() -+ * -+ * search attribute and calculate free space in inode body -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_ibody_find(struct inode *inode, int name_index, -+ const char *name, struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct ext3_xattr_entry *last; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ char *start, *end; -+ int ret = -ENOENT; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return ret; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return -EIO; -+ raw_inode = iloc.raw_inode; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ *free = storage_size - sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if (le32_to_cpu((*(__u32*) start)) != EXT3_XATTR_MAGIC) { -+ brelse(iloc.bh); -+ return -ENOENT; -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_find", -+ "inode %ld", inode->i_ino); -+ brelse(iloc.bh); -+ return -EIO; -+ } -+ -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) { -+ memcpy(rentry, last, sizeof(struct ext3_xattr_entry)); -+ ret = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(last->e_name_len); -+ *free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ brelse(iloc.bh); -+ return ret; -+} -+ -+/* -+ * ext3_xattr_block_find() -+ * -+ * search attribute and calculate free space in EA block (if it allocated) -+ * NOTE: free space includes space our attribute hold -+ */ -+int -+ext3_xattr_block_find(struct inode *inode, int name_index, const char *name, -+ struct ext3_xattr_entry *rentry, int *free) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ char *end; -+ int name_len, error = -ENOENT; -+ -+ if (!EXT3_I(inode)->i_file_acl) { -+ *free = inode->i_sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - -+ sizeof(__u32); -+ return -ENOENT; -+ } -+ ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl); -+ bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, -+ EXT3_I(inode)->i_file_acl); -+ brelse(bh); -+ return -EIO; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ *free = bh->b_size - sizeof(__u32); -+ -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) { -+ memcpy(rentry, entry, sizeof(struct ext3_xattr_entry)); -+ error = 0; -+ } else { -+ *free -= EXT3_XATTR_LEN(entry->e_name_len); -+ *free -= le32_to_cpu(entry->e_value_size); -+ } -+ entry = next; -+ } -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_inode_set() -+ * -+ * this routine add/remove/replace attribute in inode body -+ */ -+int -+ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ struct ext3_xattr_entry *last, *next, *here = NULL; -+ struct ext3_inode *raw_inode; -+ int name_len = strlen(name); -+ int esize = EXT3_XATTR_LEN(name_len); -+ struct buffer_head *bh; -+ int err, storage_size; -+ struct ext3_iloc iloc; -+ int free, min_offs; -+ char *start, *end; -+ -+ if (EXT3_SB(inode->i_sb)->s_inode_size <= EXT3_GOOD_OLD_INODE_SIZE) -+ return -ENOSPC; -+ -+ err = ext3_get_inode_loc(inode, &iloc); -+ if (err) -+ return err; -+ raw_inode = iloc.raw_inode; -+ bh = iloc.bh; -+ -+ storage_size = EXT3_SB(inode->i_sb)->s_inode_size - -+ EXT3_GOOD_OLD_INODE_SIZE - -+ EXT3_I(inode)->i_extra_isize - -+ sizeof(__u32); -+ start = (char *) raw_inode + EXT3_GOOD_OLD_INODE_SIZE + -+ EXT3_I(inode)->i_extra_isize; -+ if ((*(__u32*) start) != EXT3_XATTR_MAGIC) { -+ /* inode had no attributes before */ -+ *((__u32*) start) = cpu_to_le32(EXT3_XATTR_MAGIC); -+ } -+ start += sizeof(__u32); -+ end = (char *) raw_inode + EXT3_SB(inode->i_sb)->s_inode_size; -+ min_offs = storage_size; -+ free = storage_size - sizeof(__u32); -+ -+ last = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(last)) { -+ next = EXT3_XATTR_NEXT(last); -+ if (le32_to_cpu(last->e_value_size) > storage_size || -+ (char *) next >= end) { -+ ext3_error(inode->i_sb, "ext3_xattr_ibody_set", -+ "inode %ld", inode->i_ino); -+ brelse(bh); -+ return -EIO; -+ } -+ -+ if (last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ if (name_index == last->e_name_index && -+ name_len == last->e_name_len && -+ !memcmp(name, last->e_name, name_len)) -+ here = last; -+ else { -+ /* we calculate all but our attribute -+ * because it will be removed before changing */ -+ free -= EXT3_XATTR_LEN(last->e_name_len); -+ free -= le32_to_cpu(last->e_value_size); -+ } -+ last = next; -+ } -+ -+ if (value && (esize + value_len > free)) { -+ brelse(bh); -+ return -ENOSPC; -+ } -+ -+ err = ext3_reserve_inode_write(handle, inode, &iloc); -+ if (err) { -+ brelse(bh); -+ return err; -+ } -+ -+ if (here) { -+ /* time to remove old value */ -+ struct ext3_xattr_entry *e; -+ int size = le32_to_cpu(here->e_value_size); -+ int border = le16_to_cpu(here->e_value_offs); -+ char *src; -+ -+ /* move tail */ -+ memmove(start + min_offs + size, start + min_offs, -+ border - min_offs); -+ -+ /* recalculate offsets */ -+ e = (struct ext3_xattr_entry *) start; -+ while (!IS_LAST_ENTRY(e)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(e); -+ int offs = le16_to_cpu(e->e_value_offs); -+ if (offs < border) -+ e->e_value_offs = -+ cpu_to_le16(offs + size); -+ e = next; -+ } -+ min_offs += size; -+ -+ /* remove entry */ -+ border = EXT3_XATTR_LEN(here->e_name_len); -+ src = (char *) here + EXT3_XATTR_LEN(here->e_name_len); -+ size = (char *) last - src; -+ if ((char *) here + size > end) -+ printk("ALERT at %s:%d: 0x%p + %d > 0x%p\n", -+ __FILE__, __LINE__, here, size, end); -+ memmove(here, src, size); -+ last = (struct ext3_xattr_entry *) ((char *) last - border); -+ *((__u32 *) last) = 0; -+ } -+ -+ if (value) { -+ int offs = min_offs - value_len; -+ /* use last to create new entry */ -+ last->e_name_len = strlen(name); -+ last->e_name_index = name_index; -+ last->e_value_offs = cpu_to_le16(offs); -+ last->e_value_size = cpu_to_le32(value_len); -+ last->e_hash = last->e_value_block = 0; -+ memset(last->e_name, 0, esize); -+ memcpy(last->e_name, name, last->e_name_len); -+ if (start + offs + value_len > end) -+ printk("ALERT at %s:%d: 0x%p + %d + %d > 0x%p\n", -+ __FILE__, __LINE__, start, offs, -+ value_len, end); -+ memcpy(start + offs, value, value_len); -+ last = EXT3_XATTR_NEXT(last); -+ *((__u32 *) last) = 0; -+ } -+ -+ ext3_mark_iloc_dirty(handle, inode, &iloc); -+ brelse(bh); -+ -+ return 0; -+} -+ -+/* - * ext3_xattr_set() - * - * Create, replace or remove an extended attribute for this inode. Buffer -@@ -566,6 +1050,101 @@ - */ - int - ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, int flags) -+{ -+ struct ext3_xattr_entry entry; -+ int err, where = 0, found = 0, total; -+ int free1 = -1, free2 = -1; -+ int name_len; -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > inode->i_sb->s_blocksize) -+ return -ERANGE; -+ -+ /* try to find attribute in inode body */ -+ err = ext3_xattr_ibody_find(inode, name_index, name, &entry, &free1); -+ if (err == 0) { -+ /* found EA in inode */ -+ found = 1; -+ where = 0; -+ } else if (err == -ENOENT) { -+ /* there is no such attribute in inode body */ -+ /* try to find attribute in dedicated block */ -+ err = ext3_xattr_block_find(inode, name_index, name, -+ &entry, &free2); -+ if (err != 0 && err != -ENOENT) { -+ /* not found EA in block */ -+ goto finish; -+ } else if (err == 0) { -+ /* found EA in block */ -+ where = 1; -+ found = 1; -+ } -+ } else -+ goto finish; -+ -+ /* check flags: may replace? may create ? */ -+ if (found && (flags & XATTR_CREATE)) { -+ err = -EEXIST; -+ goto finish; -+ } else if (!found && (flags & XATTR_REPLACE)) { -+ err = -ENODATA; -+ goto finish; -+ } -+ -+ /* check if we have enough space to store attribute */ -+ total = EXT3_XATTR_LEN(strlen(name)) + value_len; -+ if (free1 >= 0 && total > free1 && free2 >= 0 && total > free2) { -+ /* have no enough space */ -+ err = -ENOSPC; -+ goto finish; -+ } -+ -+ /* time to remove attribute */ -+ if (found) { -+ if (where == 0) { -+ /* EA is stored in inode body */ -+ ext3_xattr_ibody_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } else { -+ /* EA is stored in separated block */ -+ ext3_xattr_block_set(handle, inode, name_index, name, -+ NULL, 0, flags); -+ } -+ } -+ -+ /* try to store EA in inode body */ -+ err = ext3_xattr_ibody_set(handle, inode, name_index, name, -+ value, value_len, flags); -+ if (err) { -+ /* can't store EA in inode body */ -+ /* try to store in block */ -+ err = ext3_xattr_block_set(handle, inode, name_index, -+ name, value, value_len, flags); -+ } -+ -+finish: -+ return err; -+} -+ -+/* -+ * ext3_xattr_block_set() -+ * -+ * this routine add/remove/replace attribute in EA block -+ */ -+int -+ext3_xattr_block_set(handle_t *handle, struct inode *inode, int name_index, - const char *name, const void *value, size_t value_len, int flags) - { - struct super_block *sb = inode->i_sb; -@@ -603,6 +1182,7 @@ - name_len = strlen(name); - if (name_len > 255 || value_len > sb->s_blocksize) - return -ERANGE; -+ - down(&ext3_xattr_sem); - - if (block) { -Index: linux-2.4.29/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-05-03 15:58:30.767273592 +0300 -+++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 16:07:33.009840192 +0300 -@@ -259,6 +259,8 @@ - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -+ __u16 i_extra_isize; -+ __u16 i_pad1; - }; - - #define i_size_high i_dir_acl -Index: linux-2.4.29/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs_i.h 2005-04-07 18:52:18.000000000 +0300 -+++ linux-2.4.29/include/linux/ext3_fs_i.h 2005-05-03 16:07:33.010840040 +0300 -@@ -62,6 +62,9 @@ - */ - loff_t i_disksize; - -+ /* on-disk additional length */ -+ __u16 i_extra_isize; -+ - /* - * truncate_sem is for serialising ext3_truncate() against - * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's diff --git a/lustre/kernel_patches/patches/ext3-error-export.patch b/lustre/kernel_patches/patches/ext3-error-export.patch deleted file mode 100644 index c52fc18..0000000 --- a/lustre/kernel_patches/patches/ext3-error-export.patch +++ /dev/null @@ -1,16 +0,0 @@ - fs/ext3/ext3-exports.c | 5 +++++ - 1 files changed, 5 insertions(+) - ---- linux/fs/ext3/ext3-exports.c~ext3-error-export Mon Jul 14 19:30:50 2003 -+++ linux-mmonroe/fs/ext3/ext3-exports.c Mon Jul 14 19:32:37 2003 -@@ -21,3 +21,8 @@ EXPORT_SYMBOL(ext3_xattr_list); - EXPORT_SYMBOL(ext3_xattr_set); - EXPORT_SYMBOL(ext3_prep_san_write); - EXPORT_SYMBOL(ext3_map_inode_page); -+ -+EXPORT_SYMBOL(ext3_abort); -+EXPORT_SYMBOL(ext3_decode_error); -+EXPORT_SYMBOL(__ext3_std_error); -+ - -_ diff --git a/lustre/kernel_patches/patches/ext3-extents-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-extents-2.4.21-chaos.patch deleted file mode 100644 index e1bb92c..0000000 --- a/lustre/kernel_patches/patches/ext3-extents-2.4.21-chaos.patch +++ /dev/null @@ -1,2877 +0,0 @@ -Index: linux-2.4.21-rhel/fs/ext3/extents.c -=================================================================== ---- linux-2.4.21-rhel.orig/fs/ext3/extents.c 2005-03-02 22:42:20.659360368 +0300 -+++ linux-2.4.21-rhel/fs/ext3/extents.c 2005-03-04 02:34:52.000000000 +0300 -@@ -0,0 +1,2324 @@ -+/* -+ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+/* -+ * Extents support for EXT3 -+ * -+ * TODO: -+ * - ext3_ext_walk_space() sould not use ext3_ext_find_extent() -+ * - ext3_ext_calc_credits() could take 'mergable' into account -+ * - ext3*_error() should be used in some situations -+ * - find_goal() [to be tested and improved] -+ * - smart tree reduction -+ * - arch-independence -+ * common on-disk format for big/little-endian arch -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+static inline int ext3_ext_check_header(struct ext3_extent_header *eh) -+{ -+ if (eh->eh_magic != EXT3_EXT_MAGIC) { -+ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n", -+ (unsigned)eh->eh_magic); -+ return -EIO; -+ } -+ if (eh->eh_max == 0) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n", -+ (unsigned)eh->eh_max); -+ return -EIO; -+ } -+ if (eh->eh_entries > eh->eh_max) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n", -+ (unsigned)eh->eh_entries); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed) -+{ -+ int err; -+ -+ if (handle->h_buffer_credits > needed) -+ return handle; -+ if (!ext3_journal_extend(handle, needed)) -+ return handle; -+ err = ext3_journal_restart(handle, needed); -+ -+ return handle; -+} -+ -+static int inline -+ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->get_write_access) -+ return tree->ops->get_write_access(h,tree->buffer); -+ else -+ return 0; -+} -+ -+static int inline -+ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->mark_buffer_dirty) -+ return tree->ops->mark_buffer_dirty(h,tree->buffer); -+ else -+ return 0; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ */ -+static int ext3_ext_get_access(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ -+ if (path->p_bh) { -+ /* path points to block */ -+ err = ext3_journal_get_write_access(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_get_access_for_root(handle, tree); -+ } -+ return err; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ * - EIO -+ */ -+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ if (path->p_bh) { -+ /* path points to block */ -+ err =ext3_journal_dirty_metadata(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_mark_root_dirty(handle, tree); -+ } -+ return err; -+} -+ -+static int inline -+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, struct ext3_extent *ex, -+ int *err) -+{ -+ int goal, depth, newblock; -+ struct inode *inode; -+ -+ EXT_ASSERT(tree); -+ if (tree->ops->new_block) -+ return tree->ops->new_block(handle, tree, path, ex, err); -+ -+ inode = tree->inode; -+ depth = EXT_DEPTH(tree); -+ if (path && depth > 0) { -+ goal = path[depth-1].p_block; -+ } else { -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ -+ bg_start = (ei->i_block_group * -+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ goal = bg_start + colour; -+ } -+ -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, err); -+ unlock_kernel(); -+ return newblock; -+} -+ -+static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *neh = EXT_ROOT_HDR(tree); -+ neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) | -+ (EXT_HDR_GEN(neh) + 1); -+} -+ -+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 6; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 5; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 3; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 4; -+#endif -+ return size; -+} -+ -+static void ext3_ext_show_path(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int k, l = path->p_depth; -+ -+ ext_debug(tree, "path:"); -+ for (k = 0; k <= l; k++, path++) { -+ if (path->p_idx) { -+ ext_debug(tree, " %d->%d", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ } else if (path->p_ext) { -+ ext_debug(tree, " %d:%d:%d", -+ path->p_ext->ee_block, -+ path->p_ext->ee_len, -+ path->p_ext->ee_start); -+ } else -+ ext_debug(tree, " []"); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *eh; -+ struct ext3_extent *ex; -+ int i; -+ -+ if (!path) -+ return; -+ -+ eh = path[depth].p_hdr; -+ ex = EXT_FIRST_EXTENT(eh); -+ -+ for (i = 0; i < eh->eh_entries; i++, ex++) { -+ ext_debug(tree, "%d:%d:%d ", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_drop_refs(struct ext3_ext_path *path) -+{ -+ int depth = path->p_depth; -+ int i; -+ -+ for (i = 0; i <= depth; i++, path++) { -+ if (path->p_bh) { -+ brelse(path->p_bh); -+ path->p_bh = NULL; -+ } -+ } -+} -+ -+/* -+ * binary search for closest index by given block -+ */ -+static inline void -+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent_idx *ix; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_entries > 0); -+ -+ ext_debug(tree, "binsearch for %d(idx): ", block); -+ -+ path->p_idx = ix = EXT_FIRST_INDEX(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ix[l + k].ei_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ix += l; -+ path->p_idx = ix; -+ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf); -+ -+ while (l++ < r) { -+ if (block < ix->ei_block) -+ break; -+ path->p_idx = ix++; -+ } -+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent_idx *chix; -+ -+ chix = ix = EXT_FIRST_INDEX(eh); -+ for (k = 0; k < eh->eh_entries; k++, ix++) { -+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) { -+ printk("k=%d, ix=0x%p, first=0x%p\n", k, -+ ix, EXT_FIRST_INDEX(eh)); -+ printk("%u <= %u\n", -+ ix->ei_block,ix[-1].ei_block); -+ } -+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block); -+ if (block < ix->ei_block) -+ break; -+ chix = ix; -+ } -+ EXT_ASSERT(chix == path->p_idx); -+ } -+#endif -+} -+ -+/* -+ * binary search for closest extent by given block -+ */ -+static inline void -+ext3_ext_binsearch(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent *ex; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ -+ if (eh->eh_entries == 0) { -+ /* -+ * this leaf is empty yet: -+ * we get such a leaf in split/add case -+ */ -+ return; -+ } -+ -+ ext_debug(tree, "binsearch for %d: ", block); -+ -+ path->p_ext = ex = EXT_FIRST_EXTENT(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ex[l + k].ee_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ex += l; -+ path->p_ext = ex; -+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+ while (l++ < r) { -+ if (block < ex->ee_block) -+ break; -+ path->p_ext = ex++; -+ } -+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent *chex; -+ -+ chex = ex = EXT_FIRST_EXTENT(eh); -+ for (k = 0; k < eh->eh_entries; k++, ex++) { -+ EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block); -+ if (block < ex->ee_block) -+ break; -+ chex = ex; -+ } -+ EXT_ASSERT(chex == path->p_ext); -+ } -+#endif -+} -+ -+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *eh; -+ -+ BUG_ON(tree->buffer_len == 0); -+ ext3_ext_get_access_for_root(handle, tree); -+ eh = EXT_ROOT_HDR(tree); -+ eh->eh_depth = 0; -+ eh->eh_entries = 0; -+ eh->eh_magic = EXT3_EXT_MAGIC; -+ eh->eh_max = ext3_ext_space_root(tree); -+ ext3_ext_mark_root_dirty(handle, tree); -+ ext3_ext_invalidate_cache(tree); -+ return 0; -+} -+ -+struct ext3_ext_path * -+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ struct buffer_head *bh; -+ int depth, i, ppos = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ eh = EXT_ROOT_HDR(tree); -+ EXT_ASSERT(eh); -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ i = depth = EXT_DEPTH(tree); -+ EXT_ASSERT(eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* account possible depth increase */ -+ if (!path) { -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2), -+ GFP_NOFS); -+ if (!path) -+ return ERR_PTR(-ENOMEM); -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[0].p_hdr = eh; -+ -+ /* walk through the tree */ -+ while (i) { -+ ext_debug(tree, "depth %d: num %d, max %d\n", -+ ppos, eh->eh_entries, eh->eh_max); -+ ext3_ext_binsearch_idx(tree, path + ppos, block); -+ path[ppos].p_block = path[ppos].p_idx->ei_leaf; -+ path[ppos].p_depth = i; -+ path[ppos].p_ext = NULL; -+ -+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block); -+ if (!bh) -+ goto err; -+ -+ eh = EXT_BLOCK_HDR(bh); -+ ppos++; -+ EXT_ASSERT(ppos <= depth); -+ path[ppos].p_bh = bh; -+ path[ppos].p_hdr = eh; -+ i--; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ } -+ -+ path[ppos].p_depth = i; -+ path[ppos].p_hdr = eh; -+ path[ppos].p_ext = NULL; -+ path[ppos].p_idx = NULL; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ /* find extent */ -+ ext3_ext_binsearch(tree, path + ppos, block); -+ -+ ext3_ext_show_path(tree, path); -+ -+ return path; -+ -+err: -+ printk(KERN_ERR "EXT3-fs: header is corrupted!\n"); -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ return ERR_PTR(-EIO); -+} -+ -+/* -+ * insert new index [logical;ptr] into the block at cupr -+ * it check where to insert: before curp or after curp -+ */ -+static int ext3_ext_insert_index(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *curp, -+ int logical, int ptr) -+{ -+ struct ext3_extent_idx *ix; -+ int len, err; -+ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ return err; -+ -+ EXT_ASSERT(logical != curp->p_idx->ei_block); -+ len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx; -+ if (logical > curp->p_idx->ei_block) { -+ /* insert after */ -+ if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) { -+ len = (len - 1) * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d after: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ (curp->p_idx + 1), (curp->p_idx + 2)); -+ memmove(curp->p_idx + 2, curp->p_idx + 1, len); -+ } -+ ix = curp->p_idx + 1; -+ } else { -+ /* insert before */ -+ len = len * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d before: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ curp->p_idx, (curp->p_idx + 1)); -+ memmove(curp->p_idx + 1, curp->p_idx, len); -+ ix = curp->p_idx; -+ } -+ -+ ix->ei_block = logical; -+ ix->ei_leaf = ptr; -+ ix->ei_leaf_hi = ix->ei_unused = 0; -+ curp->p_hdr->eh_entries++; -+ -+ EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max); -+ EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr)); -+ -+ err = ext3_ext_dirty(handle, tree, curp); -+ ext3_std_error(tree->inode->i_sb, err); -+ -+ return err; -+} -+ -+/* -+ * routine inserts new subtree into the path, using free index entry -+ * at depth 'at: -+ * - allocates all needed blocks (new leaf and all intermediate index blocks) -+ * - makes decision where to split -+ * - moves remaining extens and index entries (right to the split point) -+ * into the newly allocated blocks -+ * - initialize subtree -+ */ -+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext, int at) -+{ -+ struct buffer_head *bh = NULL; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct ext3_extent *ex; -+ int i = at, k, m, a; -+ unsigned long newblock, oldblock, border; -+ int *ablocks = NULL; /* array of allocated blocks */ -+ int err = 0; -+ -+ /* make decision: where to split? */ -+ /* FIXME: now desicion is simplest: at current extent */ -+ -+ /* if current leaf will be splitted, then we should use -+ * border from split point */ -+ EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr)); -+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ border = path[depth].p_ext[1].ee_block; -+ ext_debug(tree, "leaf will be splitted." -+ " next leaf starts at %d\n", -+ (int)border); -+ } else { -+ border = newext->ee_block; -+ ext_debug(tree, "leaf will be added." -+ " next leaf starts at %d\n", -+ (int)border); -+ } -+ -+ /* -+ * if error occurs, then we break processing -+ * and turn filesystem read-only. so, index won't -+ * be inserted and tree will be in consistent -+ * state. next mount will repair buffers too -+ */ -+ -+ /* -+ * get array to track all allocated blocks -+ * we need this to handle errors and free blocks -+ * upon them -+ */ -+ ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS); -+ if (!ablocks) -+ return -ENOMEM; -+ memset(ablocks, 0, sizeof(unsigned long) * depth); -+ -+ /* allocate all needed blocks */ -+ ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at); -+ for (a = 0; a < depth - at; a++) { -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ goto cleanup; -+ ablocks[a] = newblock; -+ } -+ -+ /* initialize new leaf */ -+ newblock = ablocks[--a]; -+ EXT_ASSERT(newblock); -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 0; -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_depth = 0; -+ ex = EXT_FIRST_EXTENT(neh); -+ -+ /* move remain of path[depth] to the new leaf */ -+ EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max); -+ /* start copy from next extent */ -+ /* TODO: we could do it by single memmove */ -+ m = 0; -+ path[depth].p_ext++; -+ while (path[depth].p_ext <= -+ EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n", -+ path[depth].p_ext->ee_block, -+ path[depth].p_ext->ee_start, -+ path[depth].p_ext->ee_len, -+ newblock); -+ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent)); -+ neh->eh_entries++; -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old leaf */ -+ if (m) { -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ path[depth].p_hdr->eh_entries -= m; -+ if ((err = ext3_ext_dirty(handle, tree, path + depth))) -+ goto cleanup; -+ -+ } -+ -+ /* create intermediate indexes */ -+ k = depth - at - 1; -+ EXT_ASSERT(k >= 0); -+ if (k) -+ ext_debug(tree, "create %d intermediate indices\n", k); -+ /* insert new index into current index block */ -+ /* current depth stored in i var */ -+ i = depth - 1; -+ while (k--) { -+ oldblock = newblock; -+ newblock = ablocks[--a]; -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 1; -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ neh->eh_depth = depth - i; -+ fidx = EXT_FIRST_INDEX(neh); -+ fidx->ei_block = border; -+ fidx->ei_leaf = oldblock; -+ fidx->ei_leaf_hi = fidx->ei_unused = 0; -+ -+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n", -+ i, newblock, border, oldblock); -+ /* copy indexes */ -+ m = 0; -+ path[i].p_idx++; -+ -+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx, -+ EXT_MAX_INDEX(path[i].p_hdr)); -+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) == -+ EXT_LAST_INDEX(path[i].p_hdr)); -+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { -+ ext_debug(tree, "%d: move %d:%d in new index %lu\n", -+ i, path[i].p_idx->ei_block, -+ path[i].p_idx->ei_leaf, newblock); -+ memmove(++fidx, path[i].p_idx++, -+ sizeof(struct ext3_extent_idx)); -+ neh->eh_entries++; -+ EXT_ASSERT(neh->eh_entries <= neh->eh_max); -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old index */ -+ if (m) { -+ err = ext3_ext_get_access(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ path[i].p_hdr->eh_entries -= m; -+ err = ext3_ext_dirty(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ } -+ -+ i--; -+ } -+ -+ /* insert new index */ -+ if (!err) -+ err = ext3_ext_insert_index(handle, tree, path + at, -+ border, newblock); -+ -+cleanup: -+ if (bh) { -+ if (buffer_locked(bh)) -+ unlock_buffer(bh); -+ brelse(bh); -+ } -+ -+ if (err) { -+ /* free all allocated blocks in error case */ -+ for (i = 0; i < depth; i++) { -+ if (!ablocks[i]) -+ continue; -+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1); -+ } -+ } -+ kfree(ablocks); -+ -+ return err; -+} -+ -+/* -+ * routine implements tree growing procedure: -+ * - allocates new block -+ * - moves top-level data (index block or leaf) into the new block -+ * - initialize new top-level, creating index that points to the -+ * just created block -+ */ -+static int ext3_ext_grow_indepth(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp = path; -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct buffer_head *bh; -+ unsigned long newblock; -+ int err = 0; -+ -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ return err; -+ -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ ext3_std_error(tree->inode->i_sb, err); -+ return err; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) { -+ unlock_buffer(bh); -+ goto out; -+ } -+ -+ /* move top-level index/leaf into new block */ -+ memmove(bh->b_data, curp->p_hdr, tree->buffer_len); -+ -+ /* set size of new block */ -+ neh = EXT_BLOCK_HDR(bh); -+ /* old root could have indexes or leaves -+ * so calculate eh_max right way */ -+ if (EXT_DEPTH(tree)) -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ else -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto out; -+ -+ /* create index in new top-level index: num,max,pointer */ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ goto out; -+ -+ curp->p_hdr->eh_magic = EXT3_EXT_MAGIC; -+ curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree); -+ curp->p_hdr->eh_entries = 1; -+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); -+ /* FIXME: it works, but actually path[0] can be index */ -+ curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; -+ curp->p_idx->ei_leaf = newblock; -+ curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0; -+ -+ neh = EXT_ROOT_HDR(tree); -+ fidx = EXT_FIRST_INDEX(neh); -+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n", -+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); -+ -+ neh->eh_depth = path->p_depth + 1; -+ err = ext3_ext_dirty(handle, tree, curp); -+out: -+ brelse(bh); -+ -+ return err; -+} -+ -+/* -+ * routine finds empty index and adds new leaf. if no free index found -+ * then it requests in-depth growing -+ */ -+static int ext3_ext_create_new_leaf(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp; -+ int depth, i, err = 0; -+ -+repeat: -+ i = depth = EXT_DEPTH(tree); -+ -+ /* walk up to the tree and look for free index entry */ -+ curp = path + depth; -+ while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) { -+ i--; -+ curp--; -+ } -+ -+ /* we use already allocated block for index block -+ * so, subsequent data blocks should be contigoues */ -+ if (EXT_HAS_FREE_INDEX(curp)) { -+ /* if we found index with free entry, then use that -+ * entry: create all needed subtree and add new leaf */ -+ err = ext3_ext_split(handle, tree, path, newext, i); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ } else { -+ /* tree is full, time to grow in depth */ -+ err = ext3_ext_grow_indepth(handle, tree, path, newext); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ -+ /* -+ * only first (depth 0 -> 1) produces free space -+ * in all other cases we have to split growed tree -+ */ -+ depth = EXT_DEPTH(tree); -+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) { -+ /* now we need split */ -+ goto repeat; -+ } -+ } -+ -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+/* -+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK -+ * NOTE: it consider block number from index entry as -+ * allocated block. thus, index entries have to be consistent -+ * with leafs -+ */ -+static unsigned long -+ext3_ext_next_allocated_block(struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ if (depth == 0 && path->p_ext == NULL) -+ return EXT_MAX_BLOCK; -+ -+ /* FIXME: what if index isn't full ?! */ -+ while (depth >= 0) { -+ if (depth == path->p_depth) { -+ /* leaf */ -+ if (path[depth].p_ext != -+ EXT_LAST_EXTENT(path[depth].p_hdr)) -+ return path[depth].p_ext[1].ee_block; -+ } else { -+ /* index */ -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ } -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * returns first allocated block from next leaf or EXT_MAX_BLOCK -+ */ -+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ /* zero-tree has no leaf blocks at all */ -+ if (depth == 0) -+ return EXT_MAX_BLOCK; -+ -+ /* go to index block */ -+ depth--; -+ -+ while (depth >= 0) { -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * if leaf gets modified and modified extent is first in the leaf -+ * then we have to correct all indexes above -+ * TODO: do we need to correct tree in all cases? -+ */ -+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent *ex; -+ unsigned long border; -+ int k, err = 0; -+ -+ eh = path[depth].p_hdr; -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(eh); -+ -+ if (depth == 0) { -+ /* there is no tree at all */ -+ return 0; -+ } -+ -+ if (ex != EXT_FIRST_EXTENT(eh)) { -+ /* we correct tree if first leaf got modified only */ -+ return 0; -+ } -+ -+ /* -+ * TODO: we need correction if border is smaller then current one -+ */ -+ k = depth - 1; -+ border = path[depth].p_ext->ee_block; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ return err; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ return err; -+ -+ while (k--) { -+ /* change all left-side indexes */ -+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr)) -+ break; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ break; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ break; -+ } -+ -+ return err; -+} -+ -+static int inline -+ext3_can_extents_be_merged(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block) -+ return 0; -+ -+#ifdef AGRESSIVE_TEST -+ if (ex1->ee_len >= 4) -+ return 0; -+#endif -+ -+ if (!tree->ops->mergable) -+ return 1; -+ -+ return tree->ops->mergable(ex1, ex2); -+} -+ -+/* -+ * this routine tries to merge requsted extent into the existing -+ * extent or inserts requested extent as new one into the tree, -+ * creating new leaf in no-space case -+ */ -+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_extent_header * eh; -+ struct ext3_extent *ex, *fex; -+ struct ext3_extent *nearex; /* nearest extent */ -+ struct ext3_ext_path *npath = NULL; -+ int depth, len, err, next; -+ -+ EXT_ASSERT(newext->ee_len > 0); -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(path[depth].p_hdr); -+ -+ /* try to insert block into found extent and return */ -+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) { -+ ext_debug(tree, "append %d block to %d:%d (from %d)\n", -+ newext->ee_len, ex->ee_block, ex->ee_len, -+ ex->ee_start); -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ return err; -+ ex->ee_len += newext->ee_len; -+ eh = path[depth].p_hdr; -+ nearex = ex; -+ goto merge; -+ } -+ -+repeat: -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) -+ goto has_space; -+ -+ /* probably next leaf has space for us? */ -+ fex = EXT_LAST_EXTENT(eh); -+ next = ext3_ext_next_leaf_block(tree, path); -+ if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) { -+ ext_debug(tree, "next leaf block - %d\n", next); -+ EXT_ASSERT(!npath); -+ npath = ext3_ext_find_extent(tree, next, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ EXT_ASSERT(npath->p_depth == path->p_depth); -+ eh = npath[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) { -+ ext_debug(tree, "next leaf isnt full(%d)\n", -+ eh->eh_entries); -+ path = npath; -+ goto repeat; -+ } -+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n", -+ eh->eh_entries, eh->eh_max); -+ } -+ -+ /* -+ * there is no free space in found leaf -+ * we're gonna add new leaf in the tree -+ */ -+ err = ext3_ext_create_new_leaf(handle, tree, path, newext); -+ if (err) -+ goto cleanup; -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ -+has_space: -+ nearex = path[depth].p_ext; -+ -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ -+ if (!nearex) { -+ /* there is no extent in this leaf, create first one */ -+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len); -+ path[depth].p_ext = EXT_FIRST_EXTENT(eh); -+ } else if (newext->ee_block > nearex->ee_block) { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ if (nearex != EXT_LAST_EXTENT(eh)) { -+ len = EXT_MAX_EXTENT(eh) - nearex; -+ len = (len - 1) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 2, nearex + 1, len); -+ } -+ path[depth].p_ext = nearex + 1; -+ } else { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 1, nearex, len); -+ path[depth].p_ext = nearex; -+ } -+ -+ eh->eh_entries++; -+ nearex = path[depth].p_ext; -+ nearex->ee_block = newext->ee_block; -+ nearex->ee_start = newext->ee_start; -+ nearex->ee_len = newext->ee_len; -+ /* FIXME: support for large fs */ -+ nearex->ee_start_hi = 0; -+ -+merge: -+ /* try to merge extents to the right */ -+ while (nearex < EXT_LAST_EXTENT(eh)) { -+ if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1)) -+ break; -+ /* merge with next extent! */ -+ nearex->ee_len += nearex[1].ee_len; -+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) { -+ len = (EXT_LAST_EXTENT(eh) - nearex - 1) * -+ sizeof(struct ext3_extent); -+ memmove(nearex + 1, nearex + 2, len); -+ } -+ eh->eh_entries--; -+ EXT_ASSERT(eh->eh_entries > 0); -+ } -+ -+ /* try to merge extents to the left */ -+ -+ /* time to correct all indexes above */ -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ if (err) -+ goto cleanup; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ -+cleanup: -+ if (npath) { -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ } -+ ext3_ext_tree_changed(tree); -+ ext3_ext_invalidate_cache(tree); -+ return err; -+} -+ -+int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block, -+ unsigned long num, ext_prepare_callback func) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_ext_cache cbex; -+ struct ext3_extent *ex; -+ unsigned long next, start = 0, end = 0; -+ unsigned long last = block + num; -+ int depth, exists, err = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(func); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ while (block < last && block != EXT_MAX_BLOCK) { -+ num = last - block; -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(tree, block, path); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ break; -+ } -+ -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(path[depth].p_hdr); -+ ex = path[depth].p_ext; -+ next = ext3_ext_next_allocated_block(path); -+ -+ exists = 0; -+ if (!ex) { -+ /* there is no extent yet, so try to allocate -+ * all requested space */ -+ start = block; -+ end = block + num; -+ } else if (ex->ee_block > block) { -+ /* need to allocate space before found extent */ -+ start = block; -+ end = ex->ee_block; -+ if (block + num < end) -+ end = block + num; -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ /* need to allocate space after found extent */ -+ start = block; -+ end = block + num; -+ if (end >= next) -+ end = next; -+ } else if (block >= ex->ee_block) { -+ /* -+ * some part of requested space is covered -+ * by found extent -+ */ -+ start = block; -+ end = ex->ee_block + ex->ee_len; -+ if (block + num < end) -+ end = block + num; -+ exists = 1; -+ } else { -+ BUG(); -+ } -+ EXT_ASSERT(end > start); -+ -+ if (!exists) { -+ cbex.ec_block = start; -+ cbex.ec_len = end - start; -+ cbex.ec_start = 0; -+ cbex.ec_type = EXT3_EXT_CACHE_GAP; -+ } else { -+ cbex.ec_block = ex->ee_block; -+ cbex.ec_len = ex->ee_len; -+ cbex.ec_start = ex->ee_start; -+ cbex.ec_type = EXT3_EXT_CACHE_EXTENT; -+ } -+ -+ EXT_ASSERT(cbex.ec_len > 0); -+ EXT_ASSERT(path[depth].p_hdr); -+ err = func(tree, path, &cbex); -+ ext3_ext_drop_refs(path); -+ -+ if (err < 0) -+ break; -+ if (err == EXT_REPEAT) -+ continue; -+ else if (err == EXT_BREAK) { -+ err = 0; -+ break; -+ } -+ -+ if (EXT_DEPTH(tree) != depth) { -+ /* depth was changed. we have to realloc path */ -+ kfree(path); -+ path = NULL; -+ } -+ -+ block = cbex.ec_block + cbex.ec_len; -+ } -+ -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ -+ return err; -+} -+ -+static inline void -+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block, -+ __u32 len, __u32 start, int type) -+{ -+ EXT_ASSERT(len > 0); -+ if (tree->cex) { -+ tree->cex->ec_type = type; -+ tree->cex->ec_block = block; -+ tree->cex->ec_len = len; -+ tree->cex->ec_start = start; -+ } -+} -+ -+/* -+ * this routine calculate boundaries of the gap requested block fits into -+ * and cache this gap -+ */ -+static inline void -+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ int depth = EXT_DEPTH(tree); -+ unsigned long lblock, len; -+ struct ext3_extent *ex; -+ -+ if (!tree->cex) -+ return; -+ -+ ex = path[depth].p_ext; -+ if (ex == NULL) { -+ /* there is no extent yet, so gap is [0;-] */ -+ lblock = 0; -+ len = EXT_MAX_BLOCK; -+ ext_debug(tree, "cache gap(whole file):"); -+ } else if (block < ex->ee_block) { -+ lblock = block; -+ len = ex->ee_block - block; -+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len); -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ lblock = ex->ee_block + ex->ee_len; -+ len = ext3_ext_next_allocated_block(path); -+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu", -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) block); -+ EXT_ASSERT(len > lblock); -+ len = len - lblock; -+ } else { -+ lblock = len = 0; -+ BUG(); -+ } -+ -+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len); -+ ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP); -+} -+ -+static inline int -+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block, -+ struct ext3_extent *ex) -+{ -+ struct ext3_ext_cache *cex = tree->cex; -+ -+ /* is there cache storage at all? */ -+ if (!cex) -+ return EXT3_EXT_CACHE_NO; -+ -+ /* has cache valid data? */ -+ if (cex->ec_type == EXT3_EXT_CACHE_NO) -+ return EXT3_EXT_CACHE_NO; -+ -+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP || -+ cex->ec_type == EXT3_EXT_CACHE_EXTENT); -+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { -+ ex->ee_block = cex->ec_block; -+ ex->ee_start = cex->ec_start; -+ ex->ee_start_hi = 0; -+ ex->ee_len = cex->ec_len; -+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) ex->ee_start); -+ return cex->ec_type; -+ } -+ -+ /* not in cache */ -+ return EXT3_EXT_CACHE_NO; -+} -+ -+/* -+ * routine removes index from the index block -+ * it's used in truncate case only. thus all requests are for -+ * last index in the block only -+ */ -+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct buffer_head *bh; -+ int err; -+ -+ /* free index block */ -+ path--; -+ EXT_ASSERT(path->p_hdr->eh_entries); -+ if ((err = ext3_ext_get_access(handle, tree, path))) -+ return err; -+ path->p_hdr->eh_entries--; -+ if ((err = ext3_ext_dirty(handle, tree, path))) -+ return err; -+ ext_debug(tree, "index is empty, remove it, free block %d\n", -+ path->p_idx->ei_leaf); -+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf); -+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf); -+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1); -+ return err; -+} -+ -+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth = EXT_DEPTH(tree); -+ int needed; -+ -+ if (path) { -+ /* probably there is space in leaf? */ -+ if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max) -+ return 1; -+ } -+ -+ /* -+ * the worste case we're expecting is creation of the -+ * new root (growing in depth) with index splitting -+ * for splitting we have to consider depth + 1 because -+ * previous growing could increase it -+ */ -+ depth = depth + 1; -+ -+ /* -+ * growing in depth: -+ * block allocation + new root + old root -+ */ -+ needed = EXT3_ALLOC_NEEDED + 2; -+ -+ /* index split. we may need: -+ * allocate intermediate indexes and new leaf -+ * change two blocks at each level, but root -+ * modify root block (inode) -+ */ -+ needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1; -+ -+ return needed; -+} -+ -+static int -+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, tex; -+ struct ext3_ext_path *npath; -+ int depth, creds, err; -+ -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1); -+ EXT_ASSERT(ex->ee_block < start); -+ -+ /* calculate tail extent */ -+ tex.ee_block = end + 1; -+ EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len); -+ tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block; -+ -+ creds = ext3_ext_calc_credits_for_insert(tree, path); -+ handle = ext3_ext_journal_restart(handle, creds); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ /* calculate head extent. use primary extent */ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ return err; -+ ex->ee_len = start - ex->ee_block; -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ return err; -+ -+ /* FIXME: some callback to free underlying resource -+ * and correct ee_start? */ -+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n", -+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len); -+ -+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block); -+ EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len); -+ -+ err = ext3_ext_insert_extent(handle, tree, npath, &tex); -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ -+ return err; -+} -+ -+static int -+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, *fu = NULL, *lu, *le; -+ int err = 0, correct_index = 0; -+ int depth = EXT_DEPTH(tree), credits; -+ struct ext3_extent_header *eh; -+ unsigned a, b, block, num; -+ -+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end); -+ if (!path[depth].p_hdr) -+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh); -+ eh = path[depth].p_hdr; -+ EXT_ASSERT(eh); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* find where to start removing */ -+ le = ex = EXT_LAST_EXTENT(eh); -+ while (ex != EXT_FIRST_EXTENT(eh)) { -+ if (ex->ee_block <= end) -+ break; -+ ex--; -+ } -+ -+ if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) { -+ /* removal of internal part of the extent requested -+ * tail and head must be placed in different extent -+ * so, we have to insert one more extent */ -+ path[depth].p_ext = ex; -+ return ext3_ext_split_for_rm(handle, tree, path, start, end); -+ } -+ -+ lu = ex; -+ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) { -+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len); -+ path[depth].p_ext = ex; -+ -+ a = ex->ee_block > start ? ex->ee_block : start; -+ b = ex->ee_block + ex->ee_len - 1 < end ? -+ ex->ee_block + ex->ee_len - 1 : end; -+ -+ ext_debug(tree, " border %u:%u\n", a, b); -+ -+ if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) { -+ block = 0; -+ num = 0; -+ BUG(); -+ } else if (a != ex->ee_block) { -+ /* remove tail of the extent */ -+ block = ex->ee_block; -+ num = a - block; -+ } else if (b != ex->ee_block + ex->ee_len - 1) { -+ /* remove head of the extent */ -+ block = a; -+ num = b - a; -+ } else { -+ /* remove whole extent: excelent! */ -+ block = ex->ee_block; -+ num = 0; -+ EXT_ASSERT(a == ex->ee_block && -+ b == ex->ee_block + ex->ee_len - 1); -+ } -+ -+ if (ex == EXT_FIRST_EXTENT(eh)) -+ correct_index = 1; -+ -+ credits = 1; -+ if (correct_index) -+ credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1; -+ if (tree->ops->remove_extent_credits) -+ credits+=tree->ops->remove_extent_credits(tree,ex,a,b); -+ -+ handle = ext3_ext_journal_restart(handle, credits); -+ if (IS_ERR(handle)) { -+ err = PTR_ERR(handle); -+ goto out; -+ } -+ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ if (tree->ops->remove_extent) -+ err = tree->ops->remove_extent(tree, ex, a, b); -+ if (err) -+ goto out; -+ -+ if (num == 0) { -+ /* this extent is removed entirely mark slot unused */ -+ ex->ee_start = ex->ee_start_hi = 0; -+ eh->eh_entries--; -+ fu = ex; -+ } -+ -+ ex->ee_block = block; -+ ex->ee_len = num; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ ext_debug(tree, "new extent: %u:%u:%u\n", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ ex--; -+ } -+ -+ if (fu) { -+ /* reuse unused slots */ -+ while (lu < le) { -+ if (lu->ee_start) { -+ *fu = *lu; -+ lu->ee_start = lu->ee_start_hi = 0; -+ fu++; -+ } -+ lu++; -+ } -+ } -+ -+ if (correct_index && eh->eh_entries) -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ -+ /* if this leaf is free, then we should -+ * remove it from index block above */ -+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) -+ err = ext3_ext_rm_idx(handle, tree, path + depth); -+ -+out: -+ return err; -+} -+ -+ -+static struct ext3_extent_idx * -+ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block) -+{ -+ struct ext3_extent_idx *ix; -+ -+ ix = EXT_LAST_INDEX(hdr); -+ while (ix != EXT_FIRST_INDEX(hdr)) { -+ if (ix->ei_block <= block) -+ break; -+ ix--; -+ } -+ return ix; -+} -+ -+/* -+ * returns 1 if current index have to be freed (even partial) -+ */ -+static int inline -+ext3_ext_more_to_rm(struct ext3_ext_path *path) -+{ -+ EXT_ASSERT(path->p_idx); -+ -+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr)) -+ return 0; -+ -+ /* -+ * if truncate on deeper level happened it it wasn't partial -+ * so we have to consider current index for truncation -+ */ -+ if (path->p_hdr->eh_entries == path->p_block) -+ return 0; -+ return 1; -+} -+ -+int ext3_ext_remove_space(struct ext3_extents_tree *tree, -+ unsigned long start, unsigned long end) -+{ -+ struct inode *inode = tree->inode; -+ struct super_block *sb = inode->i_sb; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_ext_path *path; -+ handle_t *handle; -+ int i = 0, err = 0; -+ -+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end); -+ -+ /* probably first extent we're gonna free will be last in block */ -+ handle = ext3_journal_start(inode, depth + 1); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ ext3_ext_invalidate_cache(tree); -+ -+ /* -+ * we start scanning from right side freeing all the blocks -+ * after i_size and walking into the deep -+ */ -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL); -+ if (IS_ERR(path)) { -+ ext3_error(sb, __FUNCTION__, "Can't allocate path array"); -+ ext3_journal_stop(handle, inode); -+ return -ENOMEM; -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[i].p_hdr = EXT_ROOT_HDR(tree); -+ -+ while (i >= 0 && err == 0) { -+ if (i == depth) { -+ /* this is leaf block */ -+ err = ext3_ext_rm_leaf(handle, tree, path, start, end); -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ continue; -+ } -+ -+ /* this is index block */ -+ if (!path[i].p_hdr) { -+ ext_debug(tree, "initialize header\n"); -+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh); -+ } -+ -+ EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max); -+ EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC); -+ -+ if (!path[i].p_idx) { -+ /* this level hasn't touched yet */ -+ path[i].p_idx = -+ ext3_ext_last_covered(path[i].p_hdr, end); -+ path[i].p_block = path[i].p_hdr->eh_entries + 1; -+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n", -+ path[i].p_hdr, path[i].p_hdr->eh_entries); -+ } else { -+ /* we've already was here, see at next index */ -+ path[i].p_idx--; -+ } -+ -+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n", -+ i, EXT_FIRST_INDEX(path[i].p_hdr), -+ path[i].p_idx); -+ if (ext3_ext_more_to_rm(path + i)) { -+ /* go to the next level */ -+ ext_debug(tree, "move to level %d (block %d)\n", -+ i + 1, path[i].p_idx->ei_leaf); -+ memset(path + i + 1, 0, sizeof(*path)); -+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf); -+ if (!path[i+1].p_bh) { -+ /* should we reset i_size? */ -+ err = -EIO; -+ break; -+ } -+ /* put actual number of indexes to know is this -+ * number got changed at the next iteration */ -+ path[i].p_block = path[i].p_hdr->eh_entries; -+ i++; -+ } else { -+ /* we finish processing this index, go up */ -+ if (path[i].p_hdr->eh_entries == 0 && i > 0) { -+ /* index is empty, remove it -+ * handle must be already prepared by the -+ * truncatei_leaf() */ -+ err = ext3_ext_rm_idx(handle, tree, path + i); -+ } -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ ext_debug(tree, "return to level %d\n", i); -+ } -+ } -+ -+ /* TODO: flexible tree reduction should be here */ -+ if (path->p_hdr->eh_entries == 0) { -+ /* -+ * truncate to zero freed all the tree -+ * so, we need to correct eh_depth -+ */ -+ err = ext3_ext_get_access(handle, tree, path); -+ if (err == 0) { -+ EXT_ROOT_HDR(tree)->eh_depth = 0; -+ EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree); -+ err = ext3_ext_dirty(handle, tree, path); -+ } -+ } -+ ext3_ext_tree_changed(tree); -+ -+ kfree(path); -+ ext3_journal_stop(handle, inode); -+ -+ return err; -+} -+ -+/* -+ * called at mount time -+ */ -+void ext3_ext_init(struct super_block *sb) -+{ -+ /* -+ * possible initialization would be here -+ */ -+ -+ if (test_opt(sb, EXTENTS)) { -+ printk("EXT3-fs: file extents enabled"); -+#ifdef AGRESSIVE_TEST -+ printk(", agressive tests"); -+#endif -+#ifdef CHECK_BINSEARCH -+ printk(", check binsearch"); -+#endif -+ printk("\n"); -+ } -+} -+ -+/* -+ * called at umount time -+ */ -+void ext3_ext_release(struct super_block *sb) -+{ -+} -+ -+/************************************************************************ -+ * VFS related routines -+ ************************************************************************/ -+ -+static int ext3_get_inode_write_access(handle_t *handle, void *buffer) -+{ -+ /* we use in-core data, not bh */ -+ return 0; -+} -+ -+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer) -+{ -+ struct inode *inode = buffer; -+ return ext3_mark_inode_dirty(handle, inode); -+} -+ -+static int ext3_ext_mergable(struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ /* FIXME: support for large fs */ -+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start) -+ return 1; -+ return 0; -+} -+ -+static int -+ext3_remove_blocks_credits(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed; -+ -+ /* at present, extent can't cross block group */; -+ needed = 4; /* bitmap + group desc + sb + inode */ -+ -+#ifdef CONFIG_QUOTA -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ return needed; -+} -+ -+static int -+ext3_remove_blocks(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed = ext3_remove_blocks_credits(tree, ex, from, to); -+ handle_t *handle = ext3_journal_start(tree->inode, needed); -+ struct buffer_head *bh; -+ int i; -+ -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) { -+ /* tail removal */ -+ unsigned long num, start; -+ num = ex->ee_block + ex->ee_len - from; -+ start = ex->ee_start + ex->ee_len - num; -+ ext_debug(tree, "free last %lu blocks starting %lu\n", -+ num, start); -+ for (i = 0; i < num; i++) { -+ bh = sb_get_hash_table(tree->inode->i_sb, start + i); -+ ext3_forget(handle, 0, tree->inode, bh, start + i); -+ } -+ ext3_free_blocks(handle, tree->inode, start, num); -+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) { -+ printk("strange request: removal %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } else { -+ printk("strange request: removal(2) %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } -+ ext3_journal_stop(handle, tree->inode); -+ return 0; -+} -+ -+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ int depth; -+ -+ if (path) { -+ struct ext3_extent *ex; -+ depth = path->p_depth; -+ -+ /* try to predict block placement */ -+ if ((ex = path[depth].p_ext)) -+ return ex->ee_start + (block - ex->ee_block); -+ -+ /* it looks index is empty -+ * try to find starting from index itself */ -+ if (path[depth].p_bh) -+ return path[depth].p_bh->b_blocknr; -+ } -+ -+ /* OK. use inode's group */ -+ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ return bg_start + colour + block; -+} -+ -+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *ex, int *err) -+{ -+ struct inode *inode = tree->inode; -+ int newblock, goal; -+ -+ EXT_ASSERT(path); -+ EXT_ASSERT(ex); -+ EXT_ASSERT(ex->ee_start); -+ EXT_ASSERT(ex->ee_len); -+ -+ /* reuse block from the extent to order data/metadata */ -+ newblock = ex->ee_start++; -+ ex->ee_len--; -+ if (ex->ee_len == 0) { -+ ex->ee_len = 1; -+ /* allocate new block for the extent */ -+ goal = ext3_ext_find_goal(inode, path, ex->ee_block); -+ lock_kernel(); -+ ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err); -+ ex->ee_start_hi = 0; -+ unlock_kernel(); -+ if (ex->ee_start == 0) { -+ /* error occured: restore old extent */ -+ ex->ee_start = newblock; -+ return 0; -+ } -+ } -+ return newblock; -+} -+ -+static struct ext3_extents_helpers ext3_blockmap_helpers = { -+ .get_write_access = ext3_get_inode_write_access, -+ .mark_buffer_dirty = ext3_mark_buffer_dirty, -+ .mergable = ext3_ext_mergable, -+ .new_block = ext3_new_block_cb, -+ .remove_extent = ext3_remove_blocks, -+ .remove_extent_credits = ext3_remove_blocks_credits, -+}; -+ -+void ext3_init_tree_desc(struct ext3_extents_tree *tree, -+ struct inode *inode) -+{ -+ tree->inode = inode; -+ tree->root = (void *) EXT3_I(inode)->i_data; -+ tree->buffer = (void *) inode; -+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data); -+ tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent; -+ tree->ops = &ext3_blockmap_helpers; -+} -+ -+int ext3_ext_get_block(handle_t *handle, struct inode *inode, -+ long iblock, struct buffer_head *bh_result, int create) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_extent newex; -+ struct ext3_extent *ex; -+ int goal, newblock, err = 0, depth; -+ struct ext3_extents_tree tree; -+ -+ clear_bit(BH_New, &bh_result->b_state); -+ ext3_init_tree_desc(&tree, inode); -+ ext_debug(&tree, "block %d requested for inode %u\n", -+ (int) iblock, (unsigned) inode->i_ino); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ -+ /* check in cache */ -+ if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) { -+ if (goal == EXT3_EXT_CACHE_GAP) { -+ if (!create) { -+ /* block isn't allocated yet and -+ * user don't want to allocate it */ -+ goto out2; -+ } -+ /* we should allocate requested block */ -+ } else if (goal == EXT3_EXT_CACHE_EXTENT) { -+ /* block is already allocated */ -+ newblock = iblock - newex.ee_block + newex.ee_start; -+ goto out; -+ } else { -+ EXT_ASSERT(0); -+ } -+ } -+ -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(&tree, iblock, NULL); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ goto out2; -+ } -+ -+ depth = EXT_DEPTH(&tree); -+ -+ /* -+ * consistent leaf must not be empty -+ * this situations is possible, though, _during_ tree modification -+ * this is why assert can't be put in ext3_ext_find_extent() -+ */ -+ EXT_ASSERT(path[depth].p_ext != NULL || depth == 0); -+ -+ if ((ex = path[depth].p_ext)) { -+ /* if found exent covers block, simple return it */ -+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) { -+ newblock = iblock - ex->ee_block + ex->ee_start; -+ ext_debug(&tree, "%d fit into %d:%d -> %d\n", -+ (int) iblock, ex->ee_block, ex->ee_len, -+ newblock); -+ ext3_ext_put_in_cache(&tree, ex->ee_block, -+ ex->ee_len, ex->ee_start, -+ EXT3_EXT_CACHE_EXTENT); -+ goto out; -+ } -+ } -+ -+ /* -+ * requested block isn't allocated yet -+ * we couldn't try to create block if create flag is zero -+ */ -+ if (!create) { -+ /* put just found gap into cache to speedup subsequest reqs */ -+ ext3_ext_put_gap_in_cache(&tree, path, iblock); -+ goto out2; -+ } -+ -+ /* allocate new block */ -+ goal = ext3_ext_find_goal(inode, path, iblock); -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err); -+ unlock_kernel(); -+ if (!newblock) -+ goto out2; -+ ext_debug(&tree, "allocate new block: goal %d, found %d\n", -+ goal, newblock); -+ -+ /* try to insert new extent into found leaf and return */ -+ newex.ee_block = iblock; -+ newex.ee_start = newblock; -+ newex.ee_start_hi = 0; -+ newex.ee_len = 1; -+ err = ext3_ext_insert_extent(handle, &tree, path, &newex); -+ if (err) -+ goto out2; -+ -+ if (inode->i_size > EXT3_I(inode)->i_disksize) -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ -+ /* previous routine could use block we allocated */ -+ newblock = newex.ee_start; -+ set_bit(BH_New, &bh_result->b_state); -+ -+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len, -+ newex.ee_start, EXT3_EXT_CACHE_EXTENT); -+out: -+ ext3_ext_show_leaf(&tree, path); -+ set_bit(BH_Mapped, &bh_result->b_state); -+ bh_result->b_dev = inode->i_sb->s_dev; -+ bh_result->b_blocknr = newblock; -+out2: -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ up_write(&EXT3_I(inode)->truncate_sem); -+ -+ return err; -+} -+ -+void ext3_ext_truncate(struct inode * inode, struct page *page) -+{ -+ struct address_space *mapping = inode->i_mapping; -+ struct super_block *sb = inode->i_sb; -+ struct ext3_extents_tree tree; -+ unsigned long last_block; -+ handle_t *handle; -+ int err = 0; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ /* -+ * probably first extent we're gonna free will be last in block -+ */ -+ err = ext3_writepage_trans_blocks(inode) + 3; -+ handle = ext3_journal_start(inode, err); -+ if (IS_ERR(handle)) -+ goto out_unlock; -+ -+ if (page) -+ ext3_block_truncate_page(handle, mapping, inode->i_size, page, -+ inode->i_sb->s_blocksize); -+ -+ down_write(&EXT3_I(inode)->truncate_sem); -+ ext3_ext_invalidate_cache(&tree); -+ -+ /* -+ * TODO: optimization is possible here -+ * probably we need not scaning at all, -+ * because page truncation is enough -+ */ -+ if (ext3_orphan_add(handle, inode)) -+ goto out_stop; -+ -+ /* we have to know where to truncate from in crash case */ -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_mark_inode_dirty(handle, inode); -+ -+ last_block = (inode->i_size + sb->s_blocksize - 1) >> -+ EXT3_BLOCK_SIZE_BITS(sb); -+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK); -+ -+ /* In a multi-transaction truncate, we only make the final -+ * transaction synchronous */ -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+out_stop: -+ /* -+ * If this was a simple ftruncate(), and the file will remain alive -+ * then we need to clear up the orphan record which we created above. -+ * However, if this was a real unlink then we were called by -+ * ext3_delete_inode(), and we allow that function to clean up the -+ * orphan info for us. -+ */ -+ if (inode->i_nlink) -+ ext3_orphan_del(handle, inode); -+ -+ up_write(&EXT3_I(inode)->truncate_sem); -+ ext3_journal_stop(handle, inode); -+ return; -+ -+out_unlock: -+ if (page) { -+ UnlockPage(page); -+ page_cache_release(page); -+ } -+} -+ -+/* -+ * this routine calculate max number of blocks we could modify -+ * in order to allocate new block for an inode -+ */ -+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num) -+{ -+ struct ext3_extents_tree tree; -+ int needed; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ needed = ext3_ext_calc_credits_for_insert(&tree, NULL); -+ -+ /* caller want to allocate num blocks */ -+ needed *= num; -+ -+#ifdef CONFIG_QUOTA -+ /* -+ * FIXME: real calculation should be here -+ * it depends on blockmap format of qouta file -+ */ -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ -+ return needed; -+} -+ -+void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode) -+{ -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ ext3_extent_tree_init(handle, &tree); -+} -+ -+static int -+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *newex) -+{ -+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private; -+ -+ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ if (buf->err < 0) -+ return EXT_BREAK; -+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen) -+ return EXT_BREAK; -+ -+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) { -+ buf->err++; -+ buf->cur += sizeof(*newex); -+ } else { -+ buf->err = -EFAULT; -+ return EXT_BREAK; -+ } -+ return EXT_CONTINUE; -+} -+ -+static int -+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *ex) -+{ -+ struct ext3_extent_tree_stats *buf = -+ (struct ext3_extent_tree_stats *) tree->private; -+ int depth; -+ -+ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ depth = EXT_DEPTH(tree); -+ buf->extents_num++; -+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr)) -+ buf->leaf_num++; -+ return EXT_CONTINUE; -+} -+ -+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, -+ unsigned long arg) -+{ -+ int err = 0; -+ -+ if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)) -+ return -EINVAL; -+ -+ if (cmd == EXT3_IOC_GET_EXTENTS) { -+ struct ext3_extent_buf buf; -+ struct ext3_extents_tree tree; -+ -+ if (copy_from_user(&buf, (void *) arg, sizeof(buf))) -+ return -EFAULT; -+ -+ ext3_init_tree_desc(&tree, inode); -+ buf.cur = buf.buffer; -+ buf.err = 0; -+ tree.private = &buf; -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK, -+ ext3_ext_store_extent_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (err == 0) -+ err = buf.err; -+ } else if (cmd == EXT3_IOC_GET_TREE_STATS) { -+ struct ext3_extent_tree_stats buf; -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ buf.depth = EXT_DEPTH(&tree); -+ buf.extents_num = 0; -+ buf.leaf_num = 0; -+ tree.private = &buf; -+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK, -+ ext3_ext_collect_stats_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (!err) -+ err = copy_to_user((void *) arg, &buf, sizeof(buf)); -+ } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) { -+ struct ext3_extents_tree tree; -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = EXT_DEPTH(&tree); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ } -+ -+ return err; -+} -+ -+EXPORT_SYMBOL(ext3_init_tree_desc); -+EXPORT_SYMBOL(ext3_mark_inode_dirty); -+EXPORT_SYMBOL(ext3_ext_invalidate_cache); -+EXPORT_SYMBOL(ext3_ext_insert_extent); -+EXPORT_SYMBOL(ext3_ext_walk_space); -+EXPORT_SYMBOL(ext3_ext_find_goal); -+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert); -Index: linux-2.4.21-rhel/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-rhel.orig/fs/ext3/ialloc.c 2005-03-04 00:44:34.000000000 +0300 -+++ linux-2.4.21-rhel/fs/ext3/ialloc.c 2005-03-04 00:44:35.000000000 +0300 -@@ -553,7 +553,7 @@ repeat: - inode->i_blksize = PAGE_SIZE; - inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; -- ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL; -+ ei->i_flags = EXT3_I(dir)->i_flags & ~(EXT3_INDEX_FL|EXT3_EXTENTS_FL); - if (S_ISLNK(mode)) - ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); - #ifdef EXT3_FRAGMENTS -@@ -596,6 +596,19 @@ - iloc.bh = NULL; - goto fail; - } -+ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) { -+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL; -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); -+ ext3_extents_initialize_blockmap(handle, inode); -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) { -+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+ if (err) goto fail; -+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ } -+ } -+ - err = ext3_mark_iloc_dirty(handle, inode, &iloc); - if (err) goto fail; - -Index: linux-2.4.21-rhel/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-rhel.orig/fs/ext3/inode.c 2005-03-04 00:44:34.000000000 +0300 -+++ linux-2.4.21-rhel/fs/ext3/inode.c 2005-03-04 00:44:35.000000000 +0300 -@@ -859,6 +859,16 @@ - goto reread; - } - -+static inline int -+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block, -+ struct buffer_head *bh, int create, int extend_disksize) -+{ -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_get_block(handle, inode, block, bh, create); -+ return ext3_get_block_handle(handle, inode, block, bh, create, -+ extend_disksize); -+} -+ - /* - * The BKL is not held on entry here. - */ -@@ -872,7 +882,7 @@ - handle = ext3_journal_current_handle(); - J_ASSERT(handle != 0); - } -- ret = ext3_get_block_handle(handle, inode, iblock, -+ ret = ext3_get_block_wrap(handle, inode, iblock, - bh_result, create, 1); - return ret; - } -@@ -921,7 +931,7 @@ - dummy.b_state = 0; - dummy.b_blocknr = -1000; - buffer_trace_init(&dummy.b_history); -- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1); -+ *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1); - if (!*errp && buffer_mapped(&dummy)) { - struct buffer_head *bh; - bh = sb_getblk(inode->i_sb, dummy.b_blocknr); -@@ -1564,7 +1574,7 @@ - * This required during truncate. We need to physically zero the tail end - * of that block so it doesn't yield old data if the file is later grown. - */ --static int ext3_block_truncate_page(handle_t *handle, -+int ext3_block_truncate_page(handle_t *handle, - struct address_space *mapping, loff_t from, - struct page *page, unsigned blocksize) - { -@@ -2049,6 +2059,9 @@ - (inode->i_mapping, inode->i_size, blocksize); - if (IS_ERR(page)) - return; -+ -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_truncate(inode, page); - - handle = start_transaction(inode); - if (IS_ERR(handle)) -@@ -2502,6 +2515,7 @@ - for (block = 0; block < EXT3_N_BLOCKS; block++) - ei->i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&ei->i_orphan); -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); - - if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) - EXT3_I(inode)->i_extra_isize = -@@ -2842,6 +2856,9 @@ - int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3; - int ret; - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_writepage_trans_blocks(inode, bpp); -+ - if (ext3_should_journal_data(inode)) - ret = 3 * (bpp + indirects) + 2; - else -@@ -3166,7 +3183,7 @@ - - /* alloc blocks one by one */ - for (i = 0; i < nblocks; i++) { -- ret = ext3_get_block_handle(handle, inode, blocks[i], -+ ret = ext3_get_block_wrap(handle, inode, blocks[i], - &bh_tmp, 1, 1); - if (ret) - break; -@@ -3242,7 +3259,7 @@ - if (blocks[i] != 0) - continue; - -- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1); -+ rc = ext3_get_block_wrap(handle, inode, iblock, &bh, 1, 1); - if (rc) { - printk(KERN_INFO "ext3_map_inode_page: error %d " - "allocating block %ld\n", rc, iblock); -Index: linux-2.4.21-rhel/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21-rhel.orig/fs/ext3/Makefile 2005-03-04 00:44:33.000000000 +0300 -+++ linux-2.4.21-rhel/fs/ext3/Makefile 2005-03-04 00:44:35.000000000 +0300 -@@ -9,10 +9,11 @@ - - O_TARGET := ext3.o - --export-objs := ext3-exports.o -+export-objs := ext3-exports.o extents.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ -- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \ -+ extents.o - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21-rhel/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-rhel.orig/fs/ext3/super.c 2005-03-04 00:44:34.000000000 +0300 -+++ linux-2.4.21-rhel/fs/ext3/super.c 2005-03-04 00:44:35.000000000 +0300 -@@ -556,6 +556,7 @@ - #ifdef EXT3_DELETE_THREAD - J_ASSERT(sbi->s_delete_inodes == 0); - #endif -+ ext3_ext_release(sb); - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -755,6 +756,12 @@ - return 0; - } - } -+ else if (!strcmp (this_char, "extents")) -+ set_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "noextents")) -+ clear_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "extdebug")) -+ set_opt (*mount_options, EXTDEBUG); - else if (!strcmp (this_char, "grpid") || - !strcmp (this_char, "bsdgroups")) - set_opt (*mount_options, GRPID); -@@ -1450,6 +1455,8 @@ - test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": - "writeback"); - -+ ext3_ext_init(sb); -+ - return sb; - - failed_mount3: -Index: linux-2.4.21-rhel/fs/ext3/ioctl.c -=================================================================== ---- linux-2.4.21-rhel.orig/fs/ext3/ioctl.c 2005-03-04 00:44:32.000000000 +0300 -+++ linux-2.4.21-rhel/fs/ext3/ioctl.c 2005-03-04 00:44:35.000000000 +0300 -@@ -173,6 +173,10 @@ - return ret; - } - #endif -+ case EXT3_IOC_GET_EXTENTS: -+ case EXT3_IOC_GET_TREE_STATS: -+ case EXT3_IOC_GET_TREE_DEPTH: -+ return ext3_ext_ioctl(inode, filp, cmd, arg); - default: - return -ENOTTY; - } -Index: linux-2.4.21-rhel/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-rhel.orig/include/linux/ext3_fs.h 2005-03-04 00:44:34.000000000 +0300 -+++ linux-2.4.21-rhel/include/linux/ext3_fs.h 2005-03-04 00:44:35.000000000 +0300 -@@ -188,8 +188,9 @@ - #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ - #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ - #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ -+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ - --#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */ -+#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */ - #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ - - /* -@@ -212,6 +213,9 @@ - #ifdef CONFIG_JBD_DEBUG - #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long) - #endif -+#define EXT3_IOC_GET_EXTENTS _IOR('f', 7, long) -+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 8, long) -+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 9, long) - - /* - * Structure of an inode on the disk -@@ -332,6 +336,8 @@ - #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - #define EXT3_MOUNT_IOPEN 0x80000 /* Allow access via iopen */ - #define EXT3_MOUNT_IOPEN_NOPRIV 0x100000/* Make iopen world-readable */ -+#define EXT3_MOUNT_EXTENTS 0x200000/* Extents support */ -+#define EXT3_MOUNT_EXTDEBUG 0x400000/* Extents debug */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -504,10 +510,12 @@ - #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ -+#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ - - #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ -- EXT3_FEATURE_INCOMPAT_RECOVER) -+ EXT3_FEATURE_INCOMPAT_RECOVER| \ -+ EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) -@@ -689,6 +697,9 @@ - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t, -+ struct page *, unsigned); -+extern int ext3_writepage_trans_blocks(struct inode *inode); - extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); -@@ -770,6 +780,16 @@ - extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - -+/* extents.c */ -+extern int ext3_ext_writepage_trans_blocks(struct inode *, int); -+extern int ext3_ext_get_block(handle_t *, struct inode *, long, -+ struct buffer_head *, int); -+extern void ext3_ext_truncate(struct inode *, struct page *); -+extern void ext3_ext_init(struct super_block *); -+extern void ext3_ext_release(struct super_block *); -+extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *); -+extern int ext3_ext_ioctl(struct inode *inode, struct file *filp, -+ unsigned int cmd, unsigned long arg); - - #endif /* __KERNEL__ */ - -Index: linux-2.4.21-rhel/include/linux/ext3_extents.h -=================================================================== ---- linux-2.4.21-rhel.orig/include/linux/ext3_extents.h 2005-03-02 22:42:20.659360368 +0300 -+++ linux-2.4.21-rhel/include/linux/ext3_extents.h 2005-03-04 02:34:52.000000000 +0300 -@@ -0,0 +1,261 @@ -+/* -+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+#ifndef _LINUX_EXT3_EXTENTS -+#define _LINUX_EXT3_EXTENTS -+ -+/* -+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks -+ * become very little, so index split, in-depth growing and -+ * other hard changes happens much more often -+ * this is for debug purposes only -+ */ -+#define AGRESSIVE_TEST_ -+ -+/* -+ * if CHECK_BINSEARCH defined, then results of binary search -+ * will be checked by linear search -+ */ -+#define CHECK_BINSEARCH_ -+ -+/* -+ * if EXT_DEBUG is defined you can use 'extdebug' mount option -+ * to get lots of info what's going on -+ */ -+#define EXT_DEBUG_ -+#ifdef EXT_DEBUG -+#define ext_debug(tree,fmt,a...) \ -+do { \ -+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \ -+ printk(fmt, ##a); \ -+} while (0); -+#else -+#define ext_debug(tree,fmt,a...) -+#endif -+ -+/* -+ * if EXT_STATS is defined then stats numbers are collected -+ * these number will be displayed at umount time -+ */ -+#define EXT_STATS_ -+ -+ -+#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */ -+ -+/* -+ * ext3_inode has i_block array (total 60 bytes) -+ * first 4 bytes are used to store: -+ * - tree depth (0 mean there is no tree yet. all extents in the inode) -+ * - number of alive extents in the inode -+ */ -+ -+/* -+ * this is extent on-disk structure -+ * it's used at the bottom of the tree -+ */ -+struct ext3_extent { -+ __u32 ee_block; /* first logical block extent covers */ -+ __u16 ee_len; /* number of blocks covered by extent */ -+ __u16 ee_start_hi; /* high 16 bits of physical block */ -+ __u32 ee_start; /* low 32 bigs of physical block */ -+}; -+ -+/* -+ * this is index on-disk structure -+ * it's used at all the levels, but the bottom -+ */ -+struct ext3_extent_idx { -+ __u32 ei_block; /* index covers logical blocks from 'block' */ -+ __u32 ei_leaf; /* pointer to the physical block of the next * -+ * level. leaf or next index could bet here */ -+ __u16 ei_leaf_hi; /* high 16 bits of physical block */ -+ __u16 ei_unused; -+}; -+ -+/* -+ * each block (leaves and indexes), even inode-stored has header -+ */ -+struct ext3_extent_header { -+ __u16 eh_magic; /* probably will support different formats */ -+ __u16 eh_entries; /* number of valid entries */ -+ __u16 eh_max; /* capacity of store in entries */ -+ __u16 eh_depth; /* has tree real underlaying blocks? */ -+ __u32 eh_generation; /* flags(8 bits) | generation of the tree */ -+}; -+ -+#define EXT3_EXT_MAGIC 0xf30a -+ -+/* -+ * array of ext3_ext_path contains path to some extent -+ * creation/lookup routines use it for traversal/splitting/etc -+ * truncate uses it to simulate recursive walking -+ */ -+struct ext3_ext_path { -+ __u32 p_block; -+ __u16 p_depth; -+ struct ext3_extent *p_ext; -+ struct ext3_extent_idx *p_idx; -+ struct ext3_extent_header *p_hdr; -+ struct buffer_head *p_bh; -+}; -+ -+/* -+ * structure for external API -+ */ -+ -+/* -+ * storage for cached extent -+ */ -+struct ext3_ext_cache { -+ __u32 ec_start; -+ __u32 ec_block; -+ __u32 ec_len; -+ __u32 ec_type; -+}; -+ -+#define EXT3_EXT_CACHE_NO 0 -+#define EXT3_EXT_CACHE_GAP 1 -+#define EXT3_EXT_CACHE_EXTENT 2 -+ -+/* -+ * ext3_extents_tree is used to pass initial information -+ * to top-level extents API -+ */ -+struct ext3_extents_helpers; -+struct ext3_extents_tree { -+ struct inode *inode; /* inode which tree belongs to */ -+ void *root; /* ptr to data top of tree resides at */ -+ void *buffer; /* will be passed as arg to ^^ routines */ -+ int buffer_len; -+ void *private; -+ struct ext3_ext_cache *cex;/* last found extent */ -+ struct ext3_extents_helpers *ops; -+}; -+ -+struct ext3_extents_helpers { -+ int (*get_write_access)(handle_t *h, void *buffer); -+ int (*mark_buffer_dirty)(handle_t *h, void *buffer); -+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2); -+ int (*remove_extent_credits)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*remove_extent)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*new_block)(handle_t *, struct ext3_extents_tree *, -+ struct ext3_ext_path *, struct ext3_extent *, -+ int *); -+}; -+ -+/* -+ * to be called by ext3_ext_walk_space() -+ * negative retcode - error -+ * positive retcode - signal for ext3_ext_walk_space(), see below -+ * callback must return valid extent (passed or newly created) -+ */ -+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *, -+ struct ext3_ext_path *, -+ struct ext3_ext_cache *); -+ -+#define EXT_CONTINUE 0 -+#define EXT_BREAK 1 -+#define EXT_REPEAT 2 -+ -+ -+#define EXT_MAX_BLOCK 0xffffffff -+ -+ -+#define EXT_FIRST_EXTENT(__hdr__) \ -+ ((struct ext3_extent *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_FIRST_INDEX(__hdr__) \ -+ ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_HAS_FREE_INDEX(__path__) \ -+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) -+#define EXT_LAST_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_LAST_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_MAX_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_MAX_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_HDR_GEN(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff) -+#define EXT_FLAGS(__hdr__) ((__hdr__)->eh_generation >> 24) -+#define EXT_FLAGS_CLR_UNKNOWN 0x7 /* Flags cleared on modification */ -+ -+#define EXT_BLOCK_HDR(__bh__) ((struct ext3_extent_header *)(__bh__)->b_data) -+#define EXT_ROOT_HDR(__tree__) ((struct ext3_extent_header *)(__tree__)->root) -+#define EXT_DEPTH(__tree__) (EXT_ROOT_HDR(__tree__)->eh_depth) -+#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__)) -+ -+#define EXT_ASSERT(__x__) if (!(__x__)) BUG(); -+ -+#define EXT_CHECK_PATH(tree,path) \ -+{ \ -+ int depth = EXT_DEPTH(tree); \ -+ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_idx < \ -+ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_ext < \ -+ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \ -+ && depth != 0); \ -+ BUG_ON((path)[0].p_depth != depth); \ -+} -+ -+ -+/* -+ * this structure is used to gather extents from the tree via ioctl -+ */ -+struct ext3_extent_buf { -+ unsigned long start; -+ int buflen; -+ void *buffer; -+ void *cur; -+ int err; -+}; -+ -+/* -+ * this structure is used to collect stats info about the tree -+ */ -+struct ext3_extent_tree_stats { -+ int depth; -+ int extents_num; -+ int leaf_num; -+}; -+ -+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *); -+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *); -+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *); -+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *); -+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback); -+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long); -+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *); -+ -+static inline void -+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree) -+{ -+ if (tree->cex) -+ tree->cex->ec_type = EXT3_EXT_CACHE_NO; -+} -+ -+ -+#endif /* _LINUX_EXT3_EXTENTS */ -Index: linux-2.4.21-rhel/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.21-rhel.orig/include/linux/ext3_fs_i.h 2005-03-04 00:44:34.000000000 +0300 -+++ linux-2.4.21-rhel/include/linux/ext3_fs_i.h 2005-03-04 01:56:36.000000000 +0300 -@@ -90,6 +90,8 @@ - * by other means, so we have truncate_sem. - */ - struct rw_semaphore truncate_sem; -+ -+ __u32 i_cached_extent[4]; - }; - - #endif /* _LINUX_EXT3_FS_I */ diff --git a/lustre/kernel_patches/patches/ext3-extents-2.4.21-suse2.patch b/lustre/kernel_patches/patches/ext3-extents-2.4.21-suse2.patch deleted file mode 100644 index 34a0b9d..0000000 --- a/lustre/kernel_patches/patches/ext3-extents-2.4.21-suse2.patch +++ /dev/null @@ -1,2875 +0,0 @@ -Index: linux-2.4.21-suse2/fs/ext3/extents.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/extents.c 2004-11-03 00:34:45.404241880 +0300 -@@ -0,0 +1,2315 @@ -+/* -+ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+/* -+ * Extents support for EXT3 -+ * -+ * TODO: -+ * - ext3_ext_walk_space() sould not use ext3_ext_find_extent() -+ * - ext3_ext_calc_credits() could take 'mergable' into account -+ * - ext3*_error() should be used in some situations -+ * - find_goal() [to be tested and improved] -+ * - smart tree reduction -+ * - arch-independence -+ * common on-disk format for big/little-endian arch -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+static inline int ext3_ext_check_header(struct ext3_extent_header *eh) -+{ -+ if (eh->eh_magic != EXT3_EXT_MAGIC) { -+ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n", -+ (unsigned)eh->eh_magic); -+ return -EIO; -+ } -+ if (eh->eh_max == 0) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n", -+ (unsigned)eh->eh_max); -+ return -EIO; -+ } -+ if (eh->eh_entries > eh->eh_max) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n", -+ (unsigned)eh->eh_entries); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed) -+{ -+ int err; -+ -+ if (handle->h_buffer_credits > needed) -+ return handle; -+ if (!ext3_journal_extend(handle, needed)) -+ return handle; -+ err = ext3_journal_restart(handle, needed); -+ -+ return handle; -+} -+ -+static int inline -+ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->get_write_access) -+ return tree->ops->get_write_access(h,tree->buffer); -+ else -+ return 0; -+} -+ -+static int inline -+ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->mark_buffer_dirty) -+ return tree->ops->mark_buffer_dirty(h,tree->buffer); -+ else -+ return 0; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ */ -+static int ext3_ext_get_access(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ -+ if (path->p_bh) { -+ /* path points to block */ -+ err = ext3_journal_get_write_access(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_get_access_for_root(handle, tree); -+ } -+ return err; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ * - EIO -+ */ -+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ if (path->p_bh) { -+ /* path points to block */ -+ err =ext3_journal_dirty_metadata(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_mark_root_dirty(handle, tree); -+ } -+ return err; -+} -+ -+static int inline -+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, struct ext3_extent *ex, -+ int *err) -+{ -+ int goal, depth, newblock; -+ struct inode *inode; -+ -+ EXT_ASSERT(tree); -+ if (tree->ops->new_block) -+ return tree->ops->new_block(handle, tree, path, ex, err); -+ -+ inode = tree->inode; -+ depth = EXT_DEPTH(tree); -+ if (path && depth > 0) { -+ goal = path[depth-1].p_block; -+ } else { -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ -+ bg_start = (ei->i_block_group * -+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ goal = bg_start + colour; -+ } -+ -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, err); -+ unlock_kernel(); -+ return newblock; -+} -+ -+static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *neh = EXT_ROOT_HDR(tree); -+ neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) | -+ (EXT_HDR_GEN(neh) + 1); -+} -+ -+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 6; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 5; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 3; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 4; -+#endif -+ return size; -+} -+ -+static void ext3_ext_show_path(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int k, l = path->p_depth; -+ -+ ext_debug(tree, "path:"); -+ for (k = 0; k <= l; k++, path++) { -+ if (path->p_idx) { -+ ext_debug(tree, " %d->%d", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ } else if (path->p_ext) { -+ ext_debug(tree, " %d:%d:%d", -+ path->p_ext->ee_block, -+ path->p_ext->ee_len, -+ path->p_ext->ee_start); -+ } else -+ ext_debug(tree, " []"); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *eh; -+ struct ext3_extent *ex; -+ int i; -+ -+ if (!path) -+ return; -+ -+ eh = path[depth].p_hdr; -+ ex = EXT_FIRST_EXTENT(eh); -+ -+ for (i = 0; i < eh->eh_entries; i++, ex++) { -+ ext_debug(tree, "%d:%d:%d ", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_drop_refs(struct ext3_ext_path *path) -+{ -+ int depth = path->p_depth; -+ int i; -+ -+ for (i = 0; i <= depth; i++, path++) { -+ if (path->p_bh) { -+ brelse(path->p_bh); -+ path->p_bh = NULL; -+ } -+ } -+} -+ -+/* -+ * binary search for closest index by given block -+ */ -+static inline void -+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent_idx *ix; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_entries > 0); -+ -+ ext_debug(tree, "binsearch for %d(idx): ", block); -+ -+ path->p_idx = ix = EXT_FIRST_INDEX(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ix[l + k].ei_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ix += l; -+ path->p_idx = ix; -+ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf); -+ -+ while (l++ < r) { -+ if (block < ix->ei_block) -+ break; -+ path->p_idx = ix++; -+ } -+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent_idx *chix; -+ -+ chix = ix = EXT_FIRST_INDEX(eh); -+ for (k = 0; k < eh->eh_entries; k++, ix++) { -+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) { -+ printk("k=%d, ix=0x%p, first=0x%p\n", k, -+ ix, EXT_FIRST_INDEX(eh)); -+ printk("%u <= %u\n", -+ ix->ei_block,ix[-1].ei_block); -+ } -+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block); -+ if (block < ix->ei_block) -+ break; -+ chix = ix; -+ } -+ EXT_ASSERT(chix == path->p_idx); -+ } -+#endif -+} -+ -+/* -+ * binary search for closest extent by given block -+ */ -+static inline void -+ext3_ext_binsearch(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent *ex; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ -+ if (eh->eh_entries == 0) { -+ /* -+ * this leaf is empty yet: -+ * we get such a leaf in split/add case -+ */ -+ return; -+ } -+ -+ ext_debug(tree, "binsearch for %d: ", block); -+ -+ path->p_ext = ex = EXT_FIRST_EXTENT(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ex[l + k].ee_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ex += l; -+ path->p_ext = ex; -+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+ while (l++ < r) { -+ if (block < ex->ee_block) -+ break; -+ path->p_ext = ex++; -+ } -+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent *chex; -+ -+ chex = ex = EXT_FIRST_EXTENT(eh); -+ for (k = 0; k < eh->eh_entries; k++, ex++) { -+ EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block); -+ if (block < ex->ee_block) -+ break; -+ chex = ex; -+ } -+ EXT_ASSERT(chex == path->p_ext); -+ } -+#endif -+} -+ -+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *eh; -+ -+ BUG_ON(tree->buffer_len == 0); -+ ext3_ext_get_access_for_root(handle, tree); -+ eh = EXT_ROOT_HDR(tree); -+ eh->eh_depth = 0; -+ eh->eh_entries = 0; -+ eh->eh_magic = EXT3_EXT_MAGIC; -+ eh->eh_max = ext3_ext_space_root(tree); -+ ext3_ext_mark_root_dirty(handle, tree); -+ ext3_ext_invalidate_cache(tree); -+ return 0; -+} -+ -+struct ext3_ext_path * -+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ struct buffer_head *bh; -+ int depth, i, ppos = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ eh = EXT_ROOT_HDR(tree); -+ EXT_ASSERT(eh); -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ i = depth = EXT_DEPTH(tree); -+ EXT_ASSERT(eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* account possible depth increase */ -+ if (!path) { -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2), -+ GFP_NOFS); -+ if (!path) -+ return ERR_PTR(-ENOMEM); -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[0].p_hdr = eh; -+ -+ /* walk through the tree */ -+ while (i) { -+ ext_debug(tree, "depth %d: num %d, max %d\n", -+ ppos, eh->eh_entries, eh->eh_max); -+ ext3_ext_binsearch_idx(tree, path + ppos, block); -+ path[ppos].p_block = path[ppos].p_idx->ei_leaf; -+ path[ppos].p_depth = i; -+ path[ppos].p_ext = NULL; -+ -+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block); -+ if (!bh) -+ goto err; -+ -+ eh = EXT_BLOCK_HDR(bh); -+ ppos++; -+ EXT_ASSERT(ppos <= depth); -+ path[ppos].p_bh = bh; -+ path[ppos].p_hdr = eh; -+ i--; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ } -+ -+ path[ppos].p_depth = i; -+ path[ppos].p_hdr = eh; -+ path[ppos].p_ext = NULL; -+ path[ppos].p_idx = NULL; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ /* find extent */ -+ ext3_ext_binsearch(tree, path + ppos, block); -+ -+ ext3_ext_show_path(tree, path); -+ -+ return path; -+ -+err: -+ printk(KERN_ERR "EXT3-fs: header is corrupted!\n"); -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ return ERR_PTR(-EIO); -+} -+ -+/* -+ * insert new index [logical;ptr] into the block at cupr -+ * it check where to insert: before curp or after curp -+ */ -+static int ext3_ext_insert_index(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *curp, -+ int logical, int ptr) -+{ -+ struct ext3_extent_idx *ix; -+ int len, err; -+ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ return err; -+ -+ EXT_ASSERT(logical != curp->p_idx->ei_block); -+ len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx; -+ if (logical > curp->p_idx->ei_block) { -+ /* insert after */ -+ if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) { -+ len = (len - 1) * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d after: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ (curp->p_idx + 1), (curp->p_idx + 2)); -+ memmove(curp->p_idx + 2, curp->p_idx + 1, len); -+ } -+ ix = curp->p_idx + 1; -+ } else { -+ /* insert before */ -+ len = len * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d before: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ curp->p_idx, (curp->p_idx + 1)); -+ memmove(curp->p_idx + 1, curp->p_idx, len); -+ ix = curp->p_idx; -+ } -+ -+ ix->ei_block = logical; -+ ix->ei_leaf = ptr; -+ ix->ei_leaf_hi = ix->ei_unused = 0; -+ curp->p_hdr->eh_entries++; -+ -+ EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max); -+ EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr)); -+ -+ err = ext3_ext_dirty(handle, tree, curp); -+ ext3_std_error(tree->inode->i_sb, err); -+ -+ return err; -+} -+ -+/* -+ * routine inserts new subtree into the path, using free index entry -+ * at depth 'at: -+ * - allocates all needed blocks (new leaf and all intermediate index blocks) -+ * - makes decision where to split -+ * - moves remaining extens and index entries (right to the split point) -+ * into the newly allocated blocks -+ * - initialize subtree -+ */ -+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext, int at) -+{ -+ struct buffer_head *bh = NULL; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct ext3_extent *ex; -+ int i = at, k, m, a; -+ unsigned long newblock, oldblock, border; -+ int *ablocks = NULL; /* array of allocated blocks */ -+ int err = 0; -+ -+ /* make decision: where to split? */ -+ /* FIXME: now desicion is simplest: at current extent */ -+ -+ /* if current leaf will be splitted, then we should use -+ * border from split point */ -+ EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr)); -+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ border = path[depth].p_ext[1].ee_block; -+ ext_debug(tree, "leaf will be splitted." -+ " next leaf starts at %d\n", -+ (int)border); -+ } else { -+ border = newext->ee_block; -+ ext_debug(tree, "leaf will be added." -+ " next leaf starts at %d\n", -+ (int)border); -+ } -+ -+ /* -+ * if error occurs, then we break processing -+ * and turn filesystem read-only. so, index won't -+ * be inserted and tree will be in consistent -+ * state. next mount will repair buffers too -+ */ -+ -+ /* -+ * get array to track all allocated blocks -+ * we need this to handle errors and free blocks -+ * upon them -+ */ -+ ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS); -+ if (!ablocks) -+ return -ENOMEM; -+ memset(ablocks, 0, sizeof(unsigned long) * depth); -+ -+ /* allocate all needed blocks */ -+ ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at); -+ for (a = 0; a < depth - at; a++) { -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ goto cleanup; -+ ablocks[a] = newblock; -+ } -+ -+ /* initialize new leaf */ -+ newblock = ablocks[--a]; -+ EXT_ASSERT(newblock); -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 0; -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_depth = 0; -+ ex = EXT_FIRST_EXTENT(neh); -+ -+ /* move remain of path[depth] to the new leaf */ -+ EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max); -+ /* start copy from next extent */ -+ /* TODO: we could do it by single memmove */ -+ m = 0; -+ path[depth].p_ext++; -+ while (path[depth].p_ext <= -+ EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n", -+ path[depth].p_ext->ee_block, -+ path[depth].p_ext->ee_start, -+ path[depth].p_ext->ee_len, -+ newblock); -+ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent)); -+ neh->eh_entries++; -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old leaf */ -+ if (m) { -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ path[depth].p_hdr->eh_entries -= m; -+ if ((err = ext3_ext_dirty(handle, tree, path + depth))) -+ goto cleanup; -+ -+ } -+ -+ /* create intermediate indexes */ -+ k = depth - at - 1; -+ EXT_ASSERT(k >= 0); -+ if (k) -+ ext_debug(tree, "create %d intermediate indices\n", k); -+ /* insert new index into current index block */ -+ /* current depth stored in i var */ -+ i = depth - 1; -+ while (k--) { -+ oldblock = newblock; -+ newblock = ablocks[--a]; -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 1; -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ neh->eh_depth = depth - i; -+ fidx = EXT_FIRST_INDEX(neh); -+ fidx->ei_block = border; -+ fidx->ei_leaf = oldblock; -+ fidx->ei_leaf_hi = fidx->ei_unused = 0; -+ -+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n", -+ i, newblock, border, oldblock); -+ /* copy indexes */ -+ m = 0; -+ path[i].p_idx++; -+ -+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx, -+ EXT_MAX_INDEX(path[i].p_hdr)); -+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) == -+ EXT_LAST_INDEX(path[i].p_hdr)); -+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { -+ ext_debug(tree, "%d: move %d:%d in new index %lu\n", -+ i, path[i].p_idx->ei_block, -+ path[i].p_idx->ei_leaf, newblock); -+ memmove(++fidx, path[i].p_idx++, -+ sizeof(struct ext3_extent_idx)); -+ neh->eh_entries++; -+ EXT_ASSERT(neh->eh_entries <= neh->eh_max); -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old index */ -+ if (m) { -+ err = ext3_ext_get_access(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ path[i].p_hdr->eh_entries -= m; -+ err = ext3_ext_dirty(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ } -+ -+ i--; -+ } -+ -+ /* insert new index */ -+ if (!err) -+ err = ext3_ext_insert_index(handle, tree, path + at, -+ border, newblock); -+ -+cleanup: -+ if (bh) { -+ if (buffer_locked(bh)) -+ unlock_buffer(bh); -+ brelse(bh); -+ } -+ -+ if (err) { -+ /* free all allocated blocks in error case */ -+ for (i = 0; i < depth; i++) { -+ if (!ablocks[i]) -+ continue; -+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1); -+ } -+ } -+ kfree(ablocks); -+ -+ return err; -+} -+ -+/* -+ * routine implements tree growing procedure: -+ * - allocates new block -+ * - moves top-level data (index block or leaf) into the new block -+ * - initialize new top-level, creating index that points to the -+ * just created block -+ */ -+static int ext3_ext_grow_indepth(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp = path; -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct buffer_head *bh; -+ unsigned long newblock; -+ int err = 0; -+ -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ return err; -+ -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ ext3_std_error(tree->inode->i_sb, err); -+ return err; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) { -+ unlock_buffer(bh); -+ goto out; -+ } -+ -+ /* move top-level index/leaf into new block */ -+ memmove(bh->b_data, curp->p_hdr, tree->buffer_len); -+ -+ /* set size of new block */ -+ neh = EXT_BLOCK_HDR(bh); -+ /* old root could have indexes or leaves -+ * so calculate eh_max right way */ -+ if (EXT_DEPTH(tree)) -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ else -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto out; -+ -+ /* create index in new top-level index: num,max,pointer */ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ goto out; -+ -+ curp->p_hdr->eh_magic = EXT3_EXT_MAGIC; -+ curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree); -+ curp->p_hdr->eh_entries = 1; -+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); -+ /* FIXME: it works, but actually path[0] can be index */ -+ curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; -+ curp->p_idx->ei_leaf = newblock; -+ curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0; -+ -+ neh = EXT_ROOT_HDR(tree); -+ fidx = EXT_FIRST_INDEX(neh); -+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n", -+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); -+ -+ neh->eh_depth = path->p_depth + 1; -+ err = ext3_ext_dirty(handle, tree, curp); -+out: -+ brelse(bh); -+ -+ return err; -+} -+ -+/* -+ * routine finds empty index and adds new leaf. if no free index found -+ * then it requests in-depth growing -+ */ -+static int ext3_ext_create_new_leaf(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp; -+ int depth, i, err = 0; -+ -+repeat: -+ i = depth = EXT_DEPTH(tree); -+ -+ /* walk up to the tree and look for free index entry */ -+ curp = path + depth; -+ while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) { -+ i--; -+ curp--; -+ } -+ -+ /* we use already allocated block for index block -+ * so, subsequent data blocks should be contigoues */ -+ if (EXT_HAS_FREE_INDEX(curp)) { -+ /* if we found index with free entry, then use that -+ * entry: create all needed subtree and add new leaf */ -+ err = ext3_ext_split(handle, tree, path, newext, i); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ } else { -+ /* tree is full, time to grow in depth */ -+ err = ext3_ext_grow_indepth(handle, tree, path, newext); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ -+ /* -+ * only first (depth 0 -> 1) produces free space -+ * in all other cases we have to split growed tree -+ */ -+ depth = EXT_DEPTH(tree); -+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) { -+ /* now we need split */ -+ goto repeat; -+ } -+ } -+ -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+/* -+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK -+ * NOTE: it consider block number from index entry as -+ * allocated block. thus, index entries have to be consistent -+ * with leafs -+ */ -+static unsigned long -+ext3_ext_next_allocated_block(struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ if (depth == 0 && path->p_ext == NULL) -+ return EXT_MAX_BLOCK; -+ -+ /* FIXME: what if index isn't full ?! */ -+ while (depth >= 0) { -+ if (depth == path->p_depth) { -+ /* leaf */ -+ if (path[depth].p_ext != -+ EXT_LAST_EXTENT(path[depth].p_hdr)) -+ return path[depth].p_ext[1].ee_block; -+ } else { -+ /* index */ -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ } -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * returns first allocated block from next leaf or EXT_MAX_BLOCK -+ */ -+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ /* zero-tree has no leaf blocks at all */ -+ if (depth == 0) -+ return EXT_MAX_BLOCK; -+ -+ /* go to index block */ -+ depth--; -+ -+ while (depth >= 0) { -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * if leaf gets modified and modified extent is first in the leaf -+ * then we have to correct all indexes above -+ * TODO: do we need to correct tree in all cases? -+ */ -+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent *ex; -+ unsigned long border; -+ int k, err = 0; -+ -+ eh = path[depth].p_hdr; -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(eh); -+ -+ if (depth == 0) { -+ /* there is no tree at all */ -+ return 0; -+ } -+ -+ if (ex != EXT_FIRST_EXTENT(eh)) { -+ /* we correct tree if first leaf got modified only */ -+ return 0; -+ } -+ -+ /* -+ * TODO: we need correction if border is smaller then current one -+ */ -+ k = depth - 1; -+ border = path[depth].p_ext->ee_block; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ return err; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ return err; -+ -+ while (k--) { -+ /* change all left-side indexes */ -+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr)) -+ break; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ break; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ break; -+ } -+ -+ return err; -+} -+ -+static int inline -+ext3_can_extents_be_merged(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block) -+ return 0; -+ -+#ifdef AGRESSIVE_TEST -+ if (ex1->ee_len >= 4) -+ return 0; -+#endif -+ -+ if (!tree->ops->mergable) -+ return 1; -+ -+ return tree->ops->mergable(ex1, ex2); -+} -+ -+/* -+ * this routine tries to merge requsted extent into the existing -+ * extent or inserts requested extent as new one into the tree, -+ * creating new leaf in no-space case -+ */ -+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_extent_header * eh; -+ struct ext3_extent *ex, *fex; -+ struct ext3_extent *nearex; /* nearest extent */ -+ struct ext3_ext_path *npath = NULL; -+ int depth, len, err, next; -+ -+ EXT_ASSERT(newext->ee_len > 0); -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(path[depth].p_hdr); -+ -+ /* try to insert block into found extent and return */ -+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) { -+ ext_debug(tree, "append %d block to %d:%d (from %d)\n", -+ newext->ee_len, ex->ee_block, ex->ee_len, -+ ex->ee_start); -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ return err; -+ ex->ee_len += newext->ee_len; -+ eh = path[depth].p_hdr; -+ nearex = ex; -+ goto merge; -+ } -+ -+repeat: -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) -+ goto has_space; -+ -+ /* probably next leaf has space for us? */ -+ fex = EXT_LAST_EXTENT(eh); -+ next = ext3_ext_next_leaf_block(tree, path); -+ if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) { -+ ext_debug(tree, "next leaf block - %d\n", next); -+ EXT_ASSERT(!npath); -+ npath = ext3_ext_find_extent(tree, next, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ EXT_ASSERT(npath->p_depth == path->p_depth); -+ eh = npath[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) { -+ ext_debug(tree, "next leaf isnt full(%d)\n", -+ eh->eh_entries); -+ path = npath; -+ goto repeat; -+ } -+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n", -+ eh->eh_entries, eh->eh_max); -+ } -+ -+ /* -+ * there is no free space in found leaf -+ * we're gonna add new leaf in the tree -+ */ -+ err = ext3_ext_create_new_leaf(handle, tree, path, newext); -+ if (err) -+ goto cleanup; -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ -+has_space: -+ nearex = path[depth].p_ext; -+ -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ -+ if (!nearex) { -+ /* there is no extent in this leaf, create first one */ -+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len); -+ path[depth].p_ext = EXT_FIRST_EXTENT(eh); -+ } else if (newext->ee_block > nearex->ee_block) { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ if (nearex != EXT_LAST_EXTENT(eh)) { -+ len = EXT_MAX_EXTENT(eh) - nearex; -+ len = (len - 1) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 2, nearex + 1, len); -+ } -+ path[depth].p_ext = nearex + 1; -+ } else { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 1, nearex, len); -+ path[depth].p_ext = nearex; -+ } -+ -+ eh->eh_entries++; -+ nearex = path[depth].p_ext; -+ nearex->ee_block = newext->ee_block; -+ nearex->ee_start = newext->ee_start; -+ nearex->ee_len = newext->ee_len; -+ /* FIXME: support for large fs */ -+ nearex->ee_start_hi = 0; -+ -+merge: -+ /* try to merge extents to the right */ -+ while (nearex < EXT_LAST_EXTENT(eh)) { -+ if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1)) -+ break; -+ /* merge with next extent! */ -+ nearex->ee_len += nearex[1].ee_len; -+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) { -+ len = (EXT_LAST_EXTENT(eh) - nearex - 1) * -+ sizeof(struct ext3_extent); -+ memmove(nearex + 1, nearex + 2, len); -+ } -+ eh->eh_entries--; -+ EXT_ASSERT(eh->eh_entries > 0); -+ } -+ -+ /* try to merge extents to the left */ -+ -+ /* time to correct all indexes above */ -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ if (err) -+ goto cleanup; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ -+cleanup: -+ if (npath) { -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ } -+ ext3_ext_tree_changed(tree); -+ ext3_ext_invalidate_cache(tree); -+ return err; -+} -+ -+int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block, -+ unsigned long num, ext_prepare_callback func) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_ext_cache cbex; -+ struct ext3_extent *ex; -+ unsigned long next, start = 0, end = 0; -+ unsigned long last = block + num; -+ int depth, exists, err = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(func); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ while (block < last && block != EXT_MAX_BLOCK) { -+ num = last - block; -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(tree, block, path); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ break; -+ } -+ -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(path[depth].p_hdr); -+ ex = path[depth].p_ext; -+ next = ext3_ext_next_allocated_block(path); -+ -+ exists = 0; -+ if (!ex) { -+ /* there is no extent yet, so try to allocate -+ * all requested space */ -+ start = block; -+ end = block + num; -+ } else if (ex->ee_block > block) { -+ /* need to allocate space before found extent */ -+ start = block; -+ end = ex->ee_block; -+ if (block + num < end) -+ end = block + num; -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ /* need to allocate space after found extent */ -+ start = block; -+ end = block + num; -+ if (end >= next) -+ end = next; -+ } else if (block >= ex->ee_block) { -+ /* -+ * some part of requested space is covered -+ * by found extent -+ */ -+ start = block; -+ end = ex->ee_block + ex->ee_len; -+ if (block + num < end) -+ end = block + num; -+ exists = 1; -+ } else { -+ BUG(); -+ } -+ EXT_ASSERT(end > start); -+ -+ if (!exists) { -+ cbex.ec_block = start; -+ cbex.ec_len = end - start; -+ cbex.ec_start = 0; -+ cbex.ec_type = EXT3_EXT_CACHE_GAP; -+ } else { -+ cbex.ec_block = ex->ee_block; -+ cbex.ec_len = ex->ee_len; -+ cbex.ec_start = ex->ee_start; -+ cbex.ec_type = EXT3_EXT_CACHE_EXTENT; -+ } -+ -+ EXT_ASSERT(cbex.ec_len > 0); -+ EXT_ASSERT(path[depth].p_hdr); -+ err = func(tree, path, &cbex); -+ ext3_ext_drop_refs(path); -+ -+ if (err < 0) -+ break; -+ if (err == EXT_REPEAT) -+ continue; -+ else if (err == EXT_BREAK) { -+ err = 0; -+ break; -+ } -+ -+ if (EXT_DEPTH(tree) != depth) { -+ /* depth was changed. we have to realloc path */ -+ kfree(path); -+ path = NULL; -+ } -+ -+ block = cbex.ec_block + cbex.ec_len; -+ } -+ -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ -+ return err; -+} -+ -+static inline void -+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block, -+ __u32 len, __u32 start, int type) -+{ -+ EXT_ASSERT(len > 0); -+ if (tree->cex) { -+ tree->cex->ec_type = type; -+ tree->cex->ec_block = block; -+ tree->cex->ec_len = len; -+ tree->cex->ec_start = start; -+ } -+} -+ -+/* -+ * this routine calculate boundaries of the gap requested block fits into -+ * and cache this gap -+ */ -+static inline void -+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ int depth = EXT_DEPTH(tree); -+ unsigned long lblock, len; -+ struct ext3_extent *ex; -+ -+ if (!tree->cex) -+ return; -+ -+ ex = path[depth].p_ext; -+ if (ex == NULL) { -+ /* there is no extent yet, so gap is [0;-] */ -+ lblock = 0; -+ len = EXT_MAX_BLOCK; -+ ext_debug(tree, "cache gap(whole file):"); -+ } else if (block < ex->ee_block) { -+ lblock = block; -+ len = ex->ee_block - block; -+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len); -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ lblock = ex->ee_block + ex->ee_len; -+ len = ext3_ext_next_allocated_block(path); -+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu", -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) block); -+ EXT_ASSERT(len > lblock); -+ len = len - lblock; -+ } else { -+ lblock = len = 0; -+ BUG(); -+ } -+ -+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len); -+ ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP); -+} -+ -+static inline int -+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block, -+ struct ext3_extent *ex) -+{ -+ struct ext3_ext_cache *cex = tree->cex; -+ -+ /* is there cache storage at all? */ -+ if (!cex) -+ return EXT3_EXT_CACHE_NO; -+ -+ /* has cache valid data? */ -+ if (cex->ec_type == EXT3_EXT_CACHE_NO) -+ return EXT3_EXT_CACHE_NO; -+ -+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP || -+ cex->ec_type == EXT3_EXT_CACHE_EXTENT); -+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { -+ ex->ee_block = cex->ec_block; -+ ex->ee_start = cex->ec_start; -+ ex->ee_start_hi = 0; -+ ex->ee_len = cex->ec_len; -+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) ex->ee_start); -+ return cex->ec_type; -+ } -+ -+ /* not in cache */ -+ return EXT3_EXT_CACHE_NO; -+} -+ -+/* -+ * routine removes index from the index block -+ * it's used in truncate case only. thus all requests are for -+ * last index in the block only -+ */ -+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct buffer_head *bh; -+ int err; -+ -+ /* free index block */ -+ path--; -+ EXT_ASSERT(path->p_hdr->eh_entries); -+ if ((err = ext3_ext_get_access(handle, tree, path))) -+ return err; -+ path->p_hdr->eh_entries--; -+ if ((err = ext3_ext_dirty(handle, tree, path))) -+ return err; -+ ext_debug(tree, "index is empty, remove it, free block %d\n", -+ path->p_idx->ei_leaf); -+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf); -+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf); -+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1); -+ return err; -+} -+ -+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth = EXT_DEPTH(tree); -+ int needed; -+ -+ if (path) { -+ /* probably there is space in leaf? */ -+ if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max) -+ return 1; -+ } -+ -+ /* -+ * the worste case we're expecting is creation of the -+ * new root (growing in depth) with index splitting -+ * for splitting we have to consider depth + 1 because -+ * previous growing could increase it -+ */ -+ depth = depth + 1; -+ -+ /* -+ * growing in depth: -+ * block allocation + new root + old root -+ */ -+ needed = EXT3_ALLOC_NEEDED + 2; -+ -+ /* index split. we may need: -+ * allocate intermediate indexes and new leaf -+ * change two blocks at each level, but root -+ * modify root block (inode) -+ */ -+ needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1; -+ -+ return needed; -+} -+ -+static int -+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, tex; -+ struct ext3_ext_path *npath; -+ int depth, creds, err; -+ -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1); -+ EXT_ASSERT(ex->ee_block < start); -+ -+ /* calculate tail extent */ -+ tex.ee_block = end + 1; -+ EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len); -+ tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block; -+ -+ creds = ext3_ext_calc_credits_for_insert(tree, path); -+ handle = ext3_ext_journal_restart(handle, creds); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ /* calculate head extent. use primary extent */ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ return err; -+ ex->ee_len = start - ex->ee_block; -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ return err; -+ -+ /* FIXME: some callback to free underlying resource -+ * and correct ee_start? */ -+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n", -+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len); -+ -+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block); -+ EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len); -+ -+ err = ext3_ext_insert_extent(handle, tree, npath, &tex); -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ -+ return err; -+} -+ -+static int -+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, *fu = NULL, *lu, *le; -+ int err = 0, correct_index = 0; -+ int depth = EXT_DEPTH(tree), credits; -+ struct ext3_extent_header *eh; -+ unsigned a, b, block, num; -+ -+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end); -+ if (!path[depth].p_hdr) -+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh); -+ eh = path[depth].p_hdr; -+ EXT_ASSERT(eh); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* find where to start removing */ -+ le = ex = EXT_LAST_EXTENT(eh); -+ while (ex != EXT_FIRST_EXTENT(eh)) { -+ if (ex->ee_block <= end) -+ break; -+ ex--; -+ } -+ -+ if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) { -+ /* removal of internal part of the extent requested -+ * tail and head must be placed in different extent -+ * so, we have to insert one more extent */ -+ path[depth].p_ext = ex; -+ return ext3_ext_split_for_rm(handle, tree, path, start, end); -+ } -+ -+ lu = ex; -+ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) { -+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len); -+ path[depth].p_ext = ex; -+ -+ a = ex->ee_block > start ? ex->ee_block : start; -+ b = ex->ee_block + ex->ee_len - 1 < end ? -+ ex->ee_block + ex->ee_len - 1 : end; -+ -+ ext_debug(tree, " border %u:%u\n", a, b); -+ -+ if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) { -+ block = 0; -+ num = 0; -+ BUG(); -+ } else if (a != ex->ee_block) { -+ /* remove tail of the extent */ -+ block = ex->ee_block; -+ num = a - block; -+ } else if (b != ex->ee_block + ex->ee_len - 1) { -+ /* remove head of the extent */ -+ block = a; -+ num = b - a; -+ } else { -+ /* remove whole extent: excelent! */ -+ block = ex->ee_block; -+ num = 0; -+ EXT_ASSERT(a == ex->ee_block && -+ b == ex->ee_block + ex->ee_len - 1); -+ } -+ -+ if (ex == EXT_FIRST_EXTENT(eh)) -+ correct_index = 1; -+ -+ credits = 1; -+ if (correct_index) -+ credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1; -+ if (tree->ops->remove_extent_credits) -+ credits+=tree->ops->remove_extent_credits(tree,ex,a,b); -+ -+ handle = ext3_ext_journal_restart(handle, credits); -+ if (IS_ERR(handle)) { -+ err = PTR_ERR(handle); -+ goto out; -+ } -+ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ if (tree->ops->remove_extent) -+ err = tree->ops->remove_extent(tree, ex, a, b); -+ if (err) -+ goto out; -+ -+ if (num == 0) { -+ /* this extent is removed entirely mark slot unused */ -+ ex->ee_start = ex->ee_start_hi = 0; -+ eh->eh_entries--; -+ fu = ex; -+ } -+ -+ ex->ee_block = block; -+ ex->ee_len = num; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ ext_debug(tree, "new extent: %u:%u:%u\n", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ ex--; -+ } -+ -+ if (fu) { -+ /* reuse unused slots */ -+ while (lu < le) { -+ if (lu->ee_start) { -+ *fu = *lu; -+ lu->ee_start = lu->ee_start_hi = 0; -+ fu++; -+ } -+ lu++; -+ } -+ } -+ -+ if (correct_index && eh->eh_entries) -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ -+ /* if this leaf is free, then we should -+ * remove it from index block above */ -+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) -+ err = ext3_ext_rm_idx(handle, tree, path + depth); -+ -+out: -+ return err; -+} -+ -+ -+static struct ext3_extent_idx * -+ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block) -+{ -+ struct ext3_extent_idx *ix; -+ -+ ix = EXT_LAST_INDEX(hdr); -+ while (ix != EXT_FIRST_INDEX(hdr)) { -+ if (ix->ei_block <= block) -+ break; -+ ix--; -+ } -+ return ix; -+} -+ -+/* -+ * returns 1 if current index have to be freed (even partial) -+ */ -+static int inline -+ext3_ext_more_to_rm(struct ext3_ext_path *path) -+{ -+ EXT_ASSERT(path->p_idx); -+ -+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr)) -+ return 0; -+ -+ /* -+ * if truncate on deeper level happened it it wasn't partial -+ * so we have to consider current index for truncation -+ */ -+ if (path->p_hdr->eh_entries == path->p_block) -+ return 0; -+ return 1; -+} -+ -+int ext3_ext_remove_space(struct ext3_extents_tree *tree, -+ unsigned long start, unsigned long end) -+{ -+ struct inode *inode = tree->inode; -+ struct super_block *sb = inode->i_sb; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_ext_path *path; -+ handle_t *handle; -+ int i = 0, err = 0; -+ -+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end); -+ -+ /* probably first extent we're gonna free will be last in block */ -+ handle = ext3_journal_start(inode, depth + 1); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ ext3_ext_invalidate_cache(tree); -+ -+ /* -+ * we start scanning from right side freeing all the blocks -+ * after i_size and walking into the deep -+ */ -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL); -+ if (IS_ERR(path)) { -+ ext3_error(sb, __FUNCTION__, "Can't allocate path array"); -+ ext3_journal_stop(handle, inode); -+ return -ENOMEM; -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[i].p_hdr = EXT_ROOT_HDR(tree); -+ -+ while (i >= 0 && err == 0) { -+ if (i == depth) { -+ /* this is leaf block */ -+ err = ext3_ext_rm_leaf(handle, tree, path, start, end); -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ continue; -+ } -+ -+ /* this is index block */ -+ if (!path[i].p_hdr) { -+ ext_debug(tree, "initialize header\n"); -+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh); -+ } -+ -+ EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max); -+ EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC); -+ -+ if (!path[i].p_idx) { -+ /* this level hasn't touched yet */ -+ path[i].p_idx = -+ ext3_ext_last_covered(path[i].p_hdr, end); -+ path[i].p_block = path[i].p_hdr->eh_entries + 1; -+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n", -+ path[i].p_hdr, path[i].p_hdr->eh_entries); -+ } else { -+ /* we've already was here, see at next index */ -+ path[i].p_idx--; -+ } -+ -+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n", -+ i, EXT_FIRST_INDEX(path[i].p_hdr), -+ path[i].p_idx); -+ if (ext3_ext_more_to_rm(path + i)) { -+ /* go to the next level */ -+ ext_debug(tree, "move to level %d (block %d)\n", -+ i + 1, path[i].p_idx->ei_leaf); -+ memset(path + i + 1, 0, sizeof(*path)); -+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf); -+ if (!path[i+1].p_bh) { -+ /* should we reset i_size? */ -+ err = -EIO; -+ break; -+ } -+ /* put actual number of indexes to know is this -+ * number got changed at the next iteration */ -+ path[i].p_block = path[i].p_hdr->eh_entries; -+ i++; -+ } else { -+ /* we finish processing this index, go up */ -+ if (path[i].p_hdr->eh_entries == 0 && i > 0) { -+ /* index is empty, remove it -+ * handle must be already prepared by the -+ * truncatei_leaf() */ -+ err = ext3_ext_rm_idx(handle, tree, path + i); -+ } -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ ext_debug(tree, "return to level %d\n", i); -+ } -+ } -+ -+ /* TODO: flexible tree reduction should be here */ -+ if (path->p_hdr->eh_entries == 0) { -+ /* -+ * truncate to zero freed all the tree -+ * so, we need to correct eh_depth -+ */ -+ err = ext3_ext_get_access(handle, tree, path); -+ if (err == 0) { -+ EXT_ROOT_HDR(tree)->eh_depth = 0; -+ EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree); -+ err = ext3_ext_dirty(handle, tree, path); -+ } -+ } -+ ext3_ext_tree_changed(tree); -+ -+ kfree(path); -+ ext3_journal_stop(handle, inode); -+ -+ return err; -+} -+ -+/* -+ * called at mount time -+ */ -+void ext3_ext_init(struct super_block *sb) -+{ -+ /* -+ * possible initialization would be here -+ */ -+ -+ if (test_opt(sb, EXTENTS)) { -+ printk("EXT3-fs: file extents enabled"); -+#ifdef AGRESSIVE_TEST -+ printk(", agressive tests"); -+#endif -+#ifdef CHECK_BINSEARCH -+ printk(", check binsearch"); -+#endif -+ printk("\n"); -+ } -+} -+ -+/* -+ * called at umount time -+ */ -+void ext3_ext_release(struct super_block *sb) -+{ -+} -+ -+/************************************************************************ -+ * VFS related routines -+ ************************************************************************/ -+ -+static int ext3_get_inode_write_access(handle_t *handle, void *buffer) -+{ -+ /* we use in-core data, not bh */ -+ return 0; -+} -+ -+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer) -+{ -+ struct inode *inode = buffer; -+ return ext3_mark_inode_dirty(handle, inode); -+} -+ -+static int ext3_ext_mergable(struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ /* FIXME: support for large fs */ -+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start) -+ return 1; -+ return 0; -+} -+ -+static int -+ext3_remove_blocks_credits(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed; -+ -+ /* at present, extent can't cross block group */; -+ needed = 4; /* bitmap + group desc + sb + inode */ -+ -+#ifdef CONFIG_QUOTA -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ return needed; -+} -+ -+static int -+ext3_remove_blocks(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed = ext3_remove_blocks_credits(tree, ex, from, to); -+ handle_t *handle = ext3_journal_start(tree->inode, needed); -+ struct buffer_head *bh; -+ int i; -+ -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) { -+ /* tail removal */ -+ unsigned long num, start; -+ num = ex->ee_block + ex->ee_len - from; -+ start = ex->ee_start + ex->ee_len - num; -+ ext_debug(tree, "free last %lu blocks starting %lu\n", -+ num, start); -+ for (i = 0; i < num; i++) { -+ bh = sb_get_hash_table(tree->inode->i_sb, start + i); -+ ext3_forget(handle, 0, tree->inode, bh, start + i); -+ } -+ ext3_free_blocks(handle, tree->inode, start, num); -+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) { -+ printk("strange request: removal %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } else { -+ printk("strange request: removal(2) %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } -+ ext3_journal_stop(handle, tree->inode); -+ return 0; -+} -+ -+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ int depth; -+ -+ if (path) { -+ struct ext3_extent *ex; -+ depth = path->p_depth; -+ -+ /* try to predict block placement */ -+ if ((ex = path[depth].p_ext)) -+ return ex->ee_start + (block - ex->ee_block); -+ -+ /* it looks index is empty -+ * try to find starting from index itself */ -+ if (path[depth].p_bh) -+ return path[depth].p_bh->b_blocknr; -+ } -+ -+ /* OK. use inode's group */ -+ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ return bg_start + colour + block; -+} -+ -+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *ex, int *err) -+{ -+ struct inode *inode = tree->inode; -+ int newblock, goal; -+ -+ EXT_ASSERT(path); -+ EXT_ASSERT(ex); -+ EXT_ASSERT(ex->ee_start); -+ EXT_ASSERT(ex->ee_len); -+ -+ /* reuse block from the extent to order data/metadata */ -+ newblock = ex->ee_start++; -+ ex->ee_len--; -+ if (ex->ee_len == 0) { -+ ex->ee_len = 1; -+ /* allocate new block for the extent */ -+ goal = ext3_ext_find_goal(inode, path, ex->ee_block); -+ lock_kernel(); -+ ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err); -+ ex->ee_start_hi = 0; -+ unlock_kernel(); -+ if (ex->ee_start == 0) { -+ /* error occured: restore old extent */ -+ ex->ee_start = newblock; -+ return 0; -+ } -+ } -+ return newblock; -+} -+ -+static struct ext3_extents_helpers ext3_blockmap_helpers = { -+ .get_write_access = ext3_get_inode_write_access, -+ .mark_buffer_dirty = ext3_mark_buffer_dirty, -+ .mergable = ext3_ext_mergable, -+ .new_block = ext3_new_block_cb, -+ .remove_extent = ext3_remove_blocks, -+ .remove_extent_credits = ext3_remove_blocks_credits, -+}; -+ -+void ext3_init_tree_desc(struct ext3_extents_tree *tree, -+ struct inode *inode) -+{ -+ tree->inode = inode; -+ tree->root = (void *) EXT3_I(inode)->i_data; -+ tree->buffer = (void *) inode; -+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data); -+ tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent; -+ tree->ops = &ext3_blockmap_helpers; -+} -+ -+int ext3_ext_get_block(handle_t *handle, struct inode *inode, -+ long iblock, struct buffer_head *bh_result, int create) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_extent newex; -+ struct ext3_extent *ex; -+ int goal, newblock, err = 0, depth; -+ struct ext3_extents_tree tree; -+ -+ clear_bit(BH_New, &bh_result->b_state); -+ ext3_init_tree_desc(&tree, inode); -+ ext_debug(&tree, "block %d requested for inode %u\n", -+ (int) iblock, (unsigned) inode->i_ino); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ -+ /* check in cache */ -+ if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) { -+ if (goal == EXT3_EXT_CACHE_GAP) { -+ if (!create) { -+ /* block isn't allocated yet and -+ * user don't want to allocate it */ -+ goto out2; -+ } -+ /* we should allocate requested block */ -+ } else if (goal == EXT3_EXT_CACHE_EXTENT) { -+ /* block is already allocated */ -+ newblock = iblock - newex.ee_block + newex.ee_start; -+ goto out; -+ } else { -+ EXT_ASSERT(0); -+ } -+ } -+ -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(&tree, iblock, NULL); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ goto out2; -+ } -+ -+ depth = EXT_DEPTH(&tree); -+ -+ /* -+ * consistent leaf must not be empty -+ * this situations is possible, though, _during_ tree modification -+ * this is why assert can't be put in ext3_ext_find_extent() -+ */ -+ EXT_ASSERT(path[depth].p_ext != NULL || depth == 0); -+ -+ if ((ex = path[depth].p_ext)) { -+ /* if found exent covers block, simple return it */ -+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) { -+ newblock = iblock - ex->ee_block + ex->ee_start; -+ ext_debug(&tree, "%d fit into %d:%d -> %d\n", -+ (int) iblock, ex->ee_block, ex->ee_len, -+ newblock); -+ ext3_ext_put_in_cache(&tree, ex->ee_block, -+ ex->ee_len, ex->ee_start, -+ EXT3_EXT_CACHE_EXTENT); -+ goto out; -+ } -+ } -+ -+ /* -+ * requested block isn't allocated yet -+ * we couldn't try to create block if create flag is zero -+ */ -+ if (!create) { -+ /* put just found gap into cache to speedup subsequest reqs */ -+ ext3_ext_put_gap_in_cache(&tree, path, iblock); -+ goto out2; -+ } -+ -+ /* allocate new block */ -+ goal = ext3_ext_find_goal(inode, path, iblock); -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err); -+ unlock_kernel(); -+ if (!newblock) -+ goto out2; -+ ext_debug(&tree, "allocate new block: goal %d, found %d\n", -+ goal, newblock); -+ -+ /* try to insert new extent into found leaf and return */ -+ newex.ee_block = iblock; -+ newex.ee_start = newblock; -+ newex.ee_start_hi = 0; -+ newex.ee_len = 1; -+ err = ext3_ext_insert_extent(handle, &tree, path, &newex); -+ if (err) -+ goto out2; -+ -+ if (inode->i_size > EXT3_I(inode)->i_disksize) -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ -+ /* previous routine could use block we allocated */ -+ newblock = newex.ee_start; -+ set_bit(BH_New, &bh_result->b_state); -+ -+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len, -+ newex.ee_start, EXT3_EXT_CACHE_EXTENT); -+out: -+ ext3_ext_show_leaf(&tree, path); -+ set_bit(BH_Mapped, &bh_result->b_state); -+ bh_result->b_dev = inode->i_sb->s_dev; -+ bh_result->b_blocknr = newblock; -+out2: -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ up_write(&EXT3_I(inode)->truncate_sem); -+ -+ return err; -+} -+ -+void ext3_ext_truncate(struct inode * inode) -+{ -+ struct address_space *mapping = inode->i_mapping; -+ struct super_block *sb = inode->i_sb; -+ struct ext3_extents_tree tree; -+ unsigned long last_block; -+ handle_t *handle; -+ int err = 0; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ /* -+ * probably first extent we're gonna free will be last in block -+ */ -+ err = ext3_writepage_trans_blocks(inode) + 3; -+ handle = ext3_journal_start(inode, err); -+ if (IS_ERR(handle)) -+ return; -+ -+ ext3_block_truncate_page(handle, mapping, inode->i_size); -+ -+ down_write(&EXT3_I(inode)->truncate_sem); -+ ext3_ext_invalidate_cache(&tree); -+ -+ /* -+ * TODO: optimization is possible here -+ * probably we need not scaning at all, -+ * because page truncation is enough -+ */ -+ if (ext3_orphan_add(handle, inode)) -+ goto out_stop; -+ -+ /* we have to know where to truncate from in crash case */ -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_mark_inode_dirty(handle, inode); -+ -+ last_block = (inode->i_size + sb->s_blocksize - 1) >> -+ EXT3_BLOCK_SIZE_BITS(sb); -+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK); -+ -+ /* In a multi-transaction truncate, we only make the final -+ * transaction synchronous */ -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+out_stop: -+ /* -+ * If this was a simple ftruncate(), and the file will remain alive -+ * then we need to clear up the orphan record which we created above. -+ * However, if this was a real unlink then we were called by -+ * ext3_delete_inode(), and we allow that function to clean up the -+ * orphan info for us. -+ */ -+ if (inode->i_nlink) -+ ext3_orphan_del(handle, inode); -+ -+ up_write(&EXT3_I(inode)->truncate_sem); -+ ext3_journal_stop(handle, inode); -+} -+ -+/* -+ * this routine calculate max number of blocks we could modify -+ * in order to allocate new block for an inode -+ */ -+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num) -+{ -+ struct ext3_extents_tree tree; -+ int needed; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ needed = ext3_ext_calc_credits_for_insert(&tree, NULL); -+ -+ /* caller want to allocate num blocks */ -+ needed *= num; -+ -+#ifdef CONFIG_QUOTA -+ /* -+ * FIXME: real calculation should be here -+ * it depends on blockmap format of qouta file -+ */ -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ -+ return needed; -+} -+ -+void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode) -+{ -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ ext3_extent_tree_init(handle, &tree); -+} -+ -+static int -+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *newex) -+{ -+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private; -+ -+ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ if (buf->err < 0) -+ return EXT_BREAK; -+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen) -+ return EXT_BREAK; -+ -+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) { -+ buf->err++; -+ buf->cur += sizeof(*newex); -+ } else { -+ buf->err = -EFAULT; -+ return EXT_BREAK; -+ } -+ return EXT_CONTINUE; -+} -+ -+static int -+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *ex) -+{ -+ struct ext3_extent_tree_stats *buf = -+ (struct ext3_extent_tree_stats *) tree->private; -+ int depth; -+ -+ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ depth = EXT_DEPTH(tree); -+ buf->extents_num++; -+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr)) -+ buf->leaf_num++; -+ return EXT_CONTINUE; -+} -+ -+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, -+ unsigned long arg) -+{ -+ int err = 0; -+ -+ if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)) -+ return -EINVAL; -+ -+ if (cmd == EXT3_IOC_GET_EXTENTS) { -+ struct ext3_extent_buf buf; -+ struct ext3_extents_tree tree; -+ -+ if (copy_from_user(&buf, (void *) arg, sizeof(buf))) -+ return -EFAULT; -+ -+ ext3_init_tree_desc(&tree, inode); -+ buf.cur = buf.buffer; -+ buf.err = 0; -+ tree.private = &buf; -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK, -+ ext3_ext_store_extent_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (err == 0) -+ err = buf.err; -+ } else if (cmd == EXT3_IOC_GET_TREE_STATS) { -+ struct ext3_extent_tree_stats buf; -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ buf.depth = EXT_DEPTH(&tree); -+ buf.extents_num = 0; -+ buf.leaf_num = 0; -+ tree.private = &buf; -+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK, -+ ext3_ext_collect_stats_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (!err) -+ err = copy_to_user((void *) arg, &buf, sizeof(buf)); -+ } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) { -+ struct ext3_extents_tree tree; -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = EXT_DEPTH(&tree); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ } -+ -+ return err; -+} -+ -+EXPORT_SYMBOL(ext3_init_tree_desc); -+EXPORT_SYMBOL(ext3_mark_inode_dirty); -+EXPORT_SYMBOL(ext3_ext_invalidate_cache); -+EXPORT_SYMBOL(ext3_ext_insert_extent); -+EXPORT_SYMBOL(ext3_ext_walk_space); -+EXPORT_SYMBOL(ext3_ext_find_goal); -+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert); -Index: linux-2.4.21-suse2/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/ialloc.c 2004-11-02 20:31:37.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/ialloc.c 2004-11-02 20:34:00.000000000 +0300 -@@ -553,7 +553,8 @@ repeat: - inode->i_blksize = PAGE_SIZE; - inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; -- inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; -+ inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & -+ ~(EXT3_INDEX_FL | EXT3_EXTENTS_FL); - if (S_ISLNK(mode)) - inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); - #ifdef EXT3_FRAGMENTS -@@ -592,6 +592,19 @@ - iloc.bh = NULL; - goto fail; - } -+ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) { -+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL; -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); -+ ext3_extents_initialize_blockmap(handle, inode); -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) { -+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+ if (err) goto fail; -+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ } -+ } -+ - err = ext3_mark_iloc_dirty(handle, inode, &iloc); - if (err) goto fail; - -Index: linux-2.4.21-suse2/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/inode.c 2004-11-02 20:31:38.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/inode.c 2004-11-02 20:34:00.000000000 +0300 -@@ -853,6 +853,16 @@ - goto reread; - } - -+static inline int -+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block, -+ struct buffer_head *bh, int create, int extend_disksize) -+{ -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_get_block(handle, inode, block, bh, create); -+ return ext3_get_block_handle(handle, inode, block, bh, create, -+ extend_disksize); -+} -+ - /* - * The BKL is not held on entry here. - */ -@@ -866,7 +876,7 @@ - handle = ext3_journal_current_handle(); - J_ASSERT(handle != 0); - } -- ret = ext3_get_block_handle(handle, inode, iblock, -+ ret = ext3_get_block_wrap(handle, inode, iblock, - bh_result, create, 1); - return ret; - } -@@ -893,7 +903,7 @@ - } - } - if (ret == 0) -- ret = ext3_get_block_handle(handle, inode, iblock, -+ ret = ext3_get_block_wrap(handle, inode, iblock, - bh_result, create, 0); - if (ret == 0) - bh_result->b_size = (1 << inode->i_blkbits); -@@ -915,7 +925,7 @@ - dummy.b_state = 0; - dummy.b_blocknr = -1000; - buffer_trace_init(&dummy.b_history); -- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1); -+ *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1); - if (!*errp && buffer_mapped(&dummy)) { - struct buffer_head *bh; - bh = sb_getblk(inode->i_sb, dummy.b_blocknr); -@@ -1502,7 +1512,7 @@ - * This required during truncate. We need to physically zero the tail end - * of that block so it doesn't yield old data if the file is later grown. - */ --static int ext3_block_truncate_page(handle_t *handle, -+int ext3_block_truncate_page(handle_t *handle, - struct address_space *mapping, loff_t from) - { - unsigned long index = from >> PAGE_CACHE_SHIFT; -@@ -1988,6 +1998,9 @@ - - ext3_discard_prealloc(inode); - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_truncate(inode); -+ - handle = start_transaction(inode); - if (IS_ERR(handle)) - return; /* AKPM: return what? */ -@@ -2324,6 +2337,7 @@ - for (block = 0; block < EXT3_N_BLOCKS; block++) - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); - - brelse (iloc.bh); - -@@ -2664,6 +2678,9 @@ - int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3; - int ret; - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_writepage_trans_blocks(inode, bpp); -+ - if (ext3_should_journal_data(inode)) - ret = 3 * (bpp + indirects) + 2; - else -@@ -3100,7 +3117,7 @@ - - /* alloc blocks one by one */ - for (i = 0; i < nblocks; i++) { -- ret = ext3_get_block_handle(handle, inode, blocks[i], -+ ret = ext3_get_block_wrap(handle, inode, blocks[i], - &bh_tmp, 1, 1); - if (ret) - break; -@@ -3176,7 +3193,7 @@ - if (blocks[i] != 0) - continue; - -- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1); -+ rc = ext3_get_block_wrap(handle, inode, iblock, &bh, 1, 1); - if (rc) { - printk(KERN_INFO "ext3_map_inode_page: error %d " - "allocating block %ld\n", rc, iblock); -Index: linux-2.4.21-suse2/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/Makefile 2004-11-02 20:31:33.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/Makefile 2004-11-02 20:31:39.000000000 +0300 -@@ -12,7 +12,10 @@ - export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ -- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \ -+ extents.o -+export-objs += extents.o -+ - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21-suse2/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/super.c 2005-04-04 05:44:58.000000000 -0600 -+++ linux-2.4.21-suse2/fs/ext3/super.c 2005-04-04 05:45:43.000000000 -0600 -@@ -532,6 +532,7 @@ - #ifdef EXT3_DELETE_THREAD - J_ASSERT(sbi->s_delete_inodes == 0); - #endif -+ ext3_ext_release(sb); - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -733,6 +734,12 @@ - return 0; - } - } -+ else if (!strcmp (this_char, "extents")) -+ set_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "noextents")) -+ clear_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "extdebug")) -+ set_opt (*mount_options, EXTDEBUG); - else if (!strcmp (this_char, "grpid") || - !strcmp (this_char, "bsdgroups")) - set_opt (*mount_options, GRPID); -@@ -1428,6 +1433,8 @@ - test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": - "writeback"); - -+ ext3_ext_init(sb); -+ - return sb; - - failed_mount3: -Index: linux-2.4.21-suse2/fs/ext3/ioctl.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/ioctl.c 2004-11-02 20:31:32.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/ioctl.c 2004-11-02 20:31:39.000000000 +0300 -@@ -174,6 +174,10 @@ - return ret; - } - #endif -+ case EXT3_IOC_GET_EXTENTS: -+ case EXT3_IOC_GET_TREE_STATS: -+ case EXT3_IOC_GET_TREE_DEPTH: -+ return ext3_ext_ioctl(inode, filp, cmd, arg); - default: - return -ENOTTY; - } -Index: linux-2.4.21-suse2/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/ext3_fs.h 2004-11-02 20:31:37.000000000 +0300 -+++ linux-2.4.21-suse2/include/linux/ext3_fs.h 2004-11-02 20:31:39.000000000 +0300 -@@ -184,8 +184,9 @@ - #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ - #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ - #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ -+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ - --#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */ -+#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */ - #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ - - /* -@@ -208,6 +209,9 @@ - #ifdef CONFIG_JBD_DEBUG - #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long) - #endif -+#define EXT3_IOC_GET_EXTENTS _IOR('f', 7, long) -+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 8, long) -+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 9, long) - - /* - * Structure of an inode on the disk -@@ -328,6 +332,8 @@ - #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - #define EXT3_MOUNT_IOPEN 0x80000 /* Allow access via iopen */ - #define EXT3_MOUNT_IOPEN_NOPRIV 0x100000/* Make iopen world-readable */ -+#define EXT3_MOUNT_EXTENTS 0x200000/* Extents support */ -+#define EXT3_MOUNT_EXTDEBUG 0x400000/* Extents debug */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -504,10 +510,12 @@ - #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ -+#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ - - #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ -- EXT3_FEATURE_INCOMPAT_RECOVER) -+ EXT3_FEATURE_INCOMPAT_RECOVER| \ -+ EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) -@@ -689,6 +697,8 @@ - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t); -+extern int ext3_writepage_trans_blocks(struct inode *inode); - extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); -@@ -770,6 +779,16 @@ - extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - -+/* extents.c */ -+extern int ext3_ext_writepage_trans_blocks(struct inode *, int); -+extern int ext3_ext_get_block(handle_t *, struct inode *, long, -+ struct buffer_head *, int); -+extern void ext3_ext_truncate(struct inode *); -+extern void ext3_ext_init(struct super_block *); -+extern void ext3_ext_release(struct super_block *); -+extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *); -+extern int ext3_ext_ioctl(struct inode *inode, struct file *filp, -+ unsigned int cmd, unsigned long arg); - - #endif /* __KERNEL__ */ - -Index: linux-2.4.21-suse2/include/linux/ext3_extents.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-suse2/include/linux/ext3_extents.h 2004-11-02 20:34:00.000000000 +0300 -@@ -0,0 +1,261 @@ -+/* -+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+#ifndef _LINUX_EXT3_EXTENTS -+#define _LINUX_EXT3_EXTENTS -+ -+/* -+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks -+ * become very little, so index split, in-depth growing and -+ * other hard changes happens much more often -+ * this is for debug purposes only -+ */ -+#define AGRESSIVE_TEST_ -+ -+/* -+ * if CHECK_BINSEARCH defined, then results of binary search -+ * will be checked by linear search -+ */ -+#define CHECK_BINSEARCH_ -+ -+/* -+ * if EXT_DEBUG is defined you can use 'extdebug' mount option -+ * to get lots of info what's going on -+ */ -+#define EXT_DEBUG_ -+#ifdef EXT_DEBUG -+#define ext_debug(tree,fmt,a...) \ -+do { \ -+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \ -+ printk(fmt, ##a); \ -+} while (0); -+#else -+#define ext_debug(tree,fmt,a...) -+#endif -+ -+/* -+ * if EXT_STATS is defined then stats numbers are collected -+ * these number will be displayed at umount time -+ */ -+#define EXT_STATS_ -+ -+ -+#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */ -+ -+/* -+ * ext3_inode has i_block array (total 60 bytes) -+ * first 4 bytes are used to store: -+ * - tree depth (0 mean there is no tree yet. all extents in the inode) -+ * - number of alive extents in the inode -+ */ -+ -+/* -+ * this is extent on-disk structure -+ * it's used at the bottom of the tree -+ */ -+struct ext3_extent { -+ __u32 ee_block; /* first logical block extent covers */ -+ __u16 ee_len; /* number of blocks covered by extent */ -+ __u16 ee_start_hi; /* high 16 bits of physical block */ -+ __u32 ee_start; /* low 32 bigs of physical block */ -+}; -+ -+/* -+ * this is index on-disk structure -+ * it's used at all the levels, but the bottom -+ */ -+struct ext3_extent_idx { -+ __u32 ei_block; /* index covers logical blocks from 'block' */ -+ __u32 ei_leaf; /* pointer to the physical block of the next * -+ * level. leaf or next index could bet here */ -+ __u16 ei_leaf_hi; /* high 16 bits of physical block */ -+ __u16 ei_unused; -+}; -+ -+/* -+ * each block (leaves and indexes), even inode-stored has header -+ */ -+struct ext3_extent_header { -+ __u16 eh_magic; /* probably will support different formats */ -+ __u16 eh_entries; /* number of valid entries */ -+ __u16 eh_max; /* capacity of store in entries */ -+ __u16 eh_depth; /* has tree real underlaying blocks? */ -+ __u32 eh_generation; /* flags(8 bits) | generation of the tree */ -+}; -+ -+#define EXT3_EXT_MAGIC 0xf30a -+ -+/* -+ * array of ext3_ext_path contains path to some extent -+ * creation/lookup routines use it for traversal/splitting/etc -+ * truncate uses it to simulate recursive walking -+ */ -+struct ext3_ext_path { -+ __u32 p_block; -+ __u16 p_depth; -+ struct ext3_extent *p_ext; -+ struct ext3_extent_idx *p_idx; -+ struct ext3_extent_header *p_hdr; -+ struct buffer_head *p_bh; -+}; -+ -+/* -+ * structure for external API -+ */ -+ -+/* -+ * storage for cached extent -+ */ -+struct ext3_ext_cache { -+ __u32 ec_start; -+ __u32 ec_block; -+ __u32 ec_len; -+ __u32 ec_type; -+}; -+ -+#define EXT3_EXT_CACHE_NO 0 -+#define EXT3_EXT_CACHE_GAP 1 -+#define EXT3_EXT_CACHE_EXTENT 2 -+ -+/* -+ * ext3_extents_tree is used to pass initial information -+ * to top-level extents API -+ */ -+struct ext3_extents_helpers; -+struct ext3_extents_tree { -+ struct inode *inode; /* inode which tree belongs to */ -+ void *root; /* ptr to data top of tree resides at */ -+ void *buffer; /* will be passed as arg to ^^ routines */ -+ int buffer_len; -+ void *private; -+ struct ext3_ext_cache *cex;/* last found extent */ -+ struct ext3_extents_helpers *ops; -+}; -+ -+struct ext3_extents_helpers { -+ int (*get_write_access)(handle_t *h, void *buffer); -+ int (*mark_buffer_dirty)(handle_t *h, void *buffer); -+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2); -+ int (*remove_extent_credits)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*remove_extent)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*new_block)(handle_t *, struct ext3_extents_tree *, -+ struct ext3_ext_path *, struct ext3_extent *, -+ int *); -+}; -+ -+/* -+ * to be called by ext3_ext_walk_space() -+ * negative retcode - error -+ * positive retcode - signal for ext3_ext_walk_space(), see below -+ * callback must return valid extent (passed or newly created) -+ */ -+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *, -+ struct ext3_ext_path *, -+ struct ext3_ext_cache *); -+ -+#define EXT_CONTINUE 0 -+#define EXT_BREAK 1 -+#define EXT_REPEAT 2 -+ -+ -+#define EXT_MAX_BLOCK 0xffffffff -+ -+ -+#define EXT_FIRST_EXTENT(__hdr__) \ -+ ((struct ext3_extent *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_FIRST_INDEX(__hdr__) \ -+ ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_HAS_FREE_INDEX(__path__) \ -+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) -+#define EXT_LAST_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_LAST_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_MAX_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_MAX_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_HDR_GEN(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff) -+#define EXT_FLAGS(__hdr__) ((__hdr__)->eh_generation >> 24) -+#define EXT_FLAGS_CLR_UNKNOWN 0x7 /* Flags cleared on modification */ -+ -+#define EXT_BLOCK_HDR(__bh__) ((struct ext3_extent_header *)(__bh__)->b_data) -+#define EXT_ROOT_HDR(__tree__) ((struct ext3_extent_header *)(__tree__)->root) -+#define EXT_DEPTH(__tree__) (EXT_ROOT_HDR(__tree__)->eh_depth) -+#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__)) -+ -+#define EXT_ASSERT(__x__) if (!(__x__)) BUG(); -+ -+#define EXT_CHECK_PATH(tree,path) \ -+{ \ -+ int depth = EXT_DEPTH(tree); \ -+ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_idx < \ -+ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_ext < \ -+ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \ -+ && depth != 0); \ -+ BUG_ON((path)[0].p_depth != depth); \ -+} -+ -+ -+/* -+ * this structure is used to gather extents from the tree via ioctl -+ */ -+struct ext3_extent_buf { -+ unsigned long start; -+ int buflen; -+ void *buffer; -+ void *cur; -+ int err; -+}; -+ -+/* -+ * this structure is used to collect stats info about the tree -+ */ -+struct ext3_extent_tree_stats { -+ int depth; -+ int extents_num; -+ int leaf_num; -+}; -+ -+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *); -+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *); -+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *); -+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *); -+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback); -+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long); -+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *); -+ -+static inline void -+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree) -+{ -+ if (tree->cex) -+ tree->cex->ec_type = EXT3_EXT_CACHE_NO; -+} -+ -+ -+#endif /* _LINUX_EXT3_EXTENTS */ -Index: linux-2.4.21-suse2/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/ext3_fs_i.h 2004-11-02 20:31:37.000000000 +0300 -+++ linux-2.4.21-suse2/include/linux/ext3_fs_i.h 2004-11-02 20:45:16.000000000 +0300 -@@ -90,6 +90,8 @@ - * by other means, so we have truncate_sem. - */ - struct rw_semaphore truncate_sem; -+ -+ __u32 i_cached_extent[4]; - }; - - #endif /* _LINUX_EXT3_FS_I */ diff --git a/lustre/kernel_patches/patches/ext3-extents-2.4.24.patch b/lustre/kernel_patches/patches/ext3-extents-2.4.24.patch deleted file mode 100644 index 067e6df..0000000 --- a/lustre/kernel_patches/patches/ext3-extents-2.4.24.patch +++ /dev/null @@ -1,2863 +0,0 @@ -Index: linux-2.4.24/fs/ext3/extents.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/extents.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24/fs/ext3/extents.c 2004-11-03 00:36:44.894076664 +0300 -@@ -0,0 +1,2314 @@ -+/* -+ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+/* -+ * Extents support for EXT3 -+ * -+ * TODO: -+ * - ext3_ext_walk_space() sould not use ext3_ext_find_extent() -+ * - ext3_ext_calc_credits() could take 'mergable' into account -+ * - ext3*_error() should be used in some situations -+ * - find_goal() [to be tested and improved] -+ * - smart tree reduction -+ * - arch-independence -+ * common on-disk format for big/little-endian arch -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+static inline int ext3_ext_check_header(struct ext3_extent_header *eh) -+{ -+ if (eh->eh_magic != EXT3_EXT_MAGIC) { -+ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n", -+ (unsigned)eh->eh_magic); -+ return -EIO; -+ } -+ if (eh->eh_max == 0) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n", -+ (unsigned)eh->eh_max); -+ return -EIO; -+ } -+ if (eh->eh_entries > eh->eh_max) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n", -+ (unsigned)eh->eh_entries); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed) -+{ -+ int err; -+ -+ if (handle->h_buffer_credits > needed) -+ return handle; -+ if (!ext3_journal_extend(handle, needed)) -+ return handle; -+ err = ext3_journal_restart(handle, needed); -+ -+ return handle; -+} -+ -+static int inline -+ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->get_write_access) -+ return tree->ops->get_write_access(h,tree->buffer); -+ else -+ return 0; -+} -+ -+static int inline -+ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->mark_buffer_dirty) -+ return tree->ops->mark_buffer_dirty(h,tree->buffer); -+ else -+ return 0; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ */ -+static int ext3_ext_get_access(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ -+ if (path->p_bh) { -+ /* path points to block */ -+ err = ext3_journal_get_write_access(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_get_access_for_root(handle, tree); -+ } -+ return err; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ * - EIO -+ */ -+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ if (path->p_bh) { -+ /* path points to block */ -+ err =ext3_journal_dirty_metadata(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_mark_root_dirty(handle, tree); -+ } -+ return err; -+} -+ -+static int inline -+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, struct ext3_extent *ex, -+ int *err) -+{ -+ int goal, depth, newblock; -+ struct inode *inode; -+ -+ EXT_ASSERT(tree); -+ if (tree->ops->new_block) -+ return tree->ops->new_block(handle, tree, path, ex, err); -+ -+ inode = tree->inode; -+ depth = EXT_DEPTH(tree); -+ if (path && depth > 0) { -+ goal = path[depth-1].p_block; -+ } else { -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ -+ bg_start = (ei->i_block_group * -+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ goal = bg_start + colour; -+ } -+ -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, err); -+ unlock_kernel(); -+ return newblock; -+} -+ -+static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *neh = EXT_ROOT_HDR(tree); -+ neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) | -+ (EXT_HDR_GEN(neh) + 1); -+} -+ -+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 6; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 5; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 3; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 4; -+#endif -+ return size; -+} -+ -+static void ext3_ext_show_path(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int k, l = path->p_depth; -+ -+ ext_debug(tree, "path:"); -+ for (k = 0; k <= l; k++, path++) { -+ if (path->p_idx) { -+ ext_debug(tree, " %d->%d", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ } else if (path->p_ext) { -+ ext_debug(tree, " %d:%d:%d", -+ path->p_ext->ee_block, -+ path->p_ext->ee_len, -+ path->p_ext->ee_start); -+ } else -+ ext_debug(tree, " []"); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *eh; -+ struct ext3_extent *ex; -+ int i; -+ -+ if (!path) -+ return; -+ -+ eh = path[depth].p_hdr; -+ ex = EXT_FIRST_EXTENT(eh); -+ -+ for (i = 0; i < eh->eh_entries; i++, ex++) { -+ ext_debug(tree, "%d:%d:%d ", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_drop_refs(struct ext3_ext_path *path) -+{ -+ int depth = path->p_depth; -+ int i; -+ -+ for (i = 0; i <= depth; i++, path++) { -+ if (path->p_bh) { -+ brelse(path->p_bh); -+ path->p_bh = NULL; -+ } -+ } -+} -+ -+/* -+ * binary search for closest index by given block -+ */ -+static inline void -+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent_idx *ix; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_entries > 0); -+ -+ ext_debug(tree, "binsearch for %d(idx): ", block); -+ -+ path->p_idx = ix = EXT_FIRST_INDEX(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ix[l + k].ei_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ix += l; -+ path->p_idx = ix; -+ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf); -+ -+ while (l++ < r) { -+ if (block < ix->ei_block) -+ break; -+ path->p_idx = ix++; -+ } -+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent_idx *chix; -+ -+ chix = ix = EXT_FIRST_INDEX(eh); -+ for (k = 0; k < eh->eh_entries; k++, ix++) { -+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) { -+ printk("k=%d, ix=0x%p, first=0x%p\n", k, -+ ix, EXT_FIRST_INDEX(eh)); -+ printk("%u <= %u\n", -+ ix->ei_block,ix[-1].ei_block); -+ } -+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block); -+ if (block < ix->ei_block) -+ break; -+ chix = ix; -+ } -+ EXT_ASSERT(chix == path->p_idx); -+ } -+#endif -+} -+ -+/* -+ * binary search for closest extent by given block -+ */ -+static inline void -+ext3_ext_binsearch(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent *ex; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ -+ if (eh->eh_entries == 0) { -+ /* -+ * this leaf is empty yet: -+ * we get such a leaf in split/add case -+ */ -+ return; -+ } -+ -+ ext_debug(tree, "binsearch for %d: ", block); -+ -+ path->p_ext = ex = EXT_FIRST_EXTENT(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ex[l + k].ee_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ex += l; -+ path->p_ext = ex; -+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+ while (l++ < r) { -+ if (block < ex->ee_block) -+ break; -+ path->p_ext = ex++; -+ } -+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent *chex; -+ -+ chex = ex = EXT_FIRST_EXTENT(eh); -+ for (k = 0; k < eh->eh_entries; k++, ex++) { -+ EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block); -+ if (block < ex->ee_block) -+ break; -+ chex = ex; -+ } -+ EXT_ASSERT(chex == path->p_ext); -+ } -+#endif -+} -+ -+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *eh; -+ -+ BUG_ON(tree->buffer_len == 0); -+ ext3_ext_get_access_for_root(handle, tree); -+ eh = EXT_ROOT_HDR(tree); -+ eh->eh_depth = 0; -+ eh->eh_entries = 0; -+ eh->eh_magic = EXT3_EXT_MAGIC; -+ eh->eh_max = ext3_ext_space_root(tree); -+ ext3_ext_mark_root_dirty(handle, tree); -+ ext3_ext_invalidate_cache(tree); -+ return 0; -+} -+ -+struct ext3_ext_path * -+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ struct buffer_head *bh; -+ int depth, i, ppos = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ eh = EXT_ROOT_HDR(tree); -+ EXT_ASSERT(eh); -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ i = depth = EXT_DEPTH(tree); -+ EXT_ASSERT(eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* account possible depth increase */ -+ if (!path) { -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2), -+ GFP_NOFS); -+ if (!path) -+ return ERR_PTR(-ENOMEM); -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[0].p_hdr = eh; -+ -+ /* walk through the tree */ -+ while (i) { -+ ext_debug(tree, "depth %d: num %d, max %d\n", -+ ppos, eh->eh_entries, eh->eh_max); -+ ext3_ext_binsearch_idx(tree, path + ppos, block); -+ path[ppos].p_block = path[ppos].p_idx->ei_leaf; -+ path[ppos].p_depth = i; -+ path[ppos].p_ext = NULL; -+ -+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block); -+ if (!bh) -+ goto err; -+ eh = EXT_BLOCK_HDR(bh); -+ ppos++; -+ EXT_ASSERT(ppos <= depth); -+ path[ppos].p_bh = bh; -+ path[ppos].p_hdr = eh; -+ i--; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ } -+ -+ path[ppos].p_depth = i; -+ path[ppos].p_hdr = eh; -+ path[ppos].p_ext = NULL; -+ path[ppos].p_idx = NULL; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ /* find extent */ -+ ext3_ext_binsearch(tree, path + ppos, block); -+ -+ ext3_ext_show_path(tree, path); -+ -+ return path; -+ -+err: -+ printk(KERN_ERR "EXT3-fs: header is corrupted!\n"); -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ return ERR_PTR(-EIO); -+} -+ -+/* -+ * insert new index [logical;ptr] into the block at cupr -+ * it check where to insert: before curp or after curp -+ */ -+static int ext3_ext_insert_index(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *curp, -+ int logical, int ptr) -+{ -+ struct ext3_extent_idx *ix; -+ int len, err; -+ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ return err; -+ -+ EXT_ASSERT(logical != curp->p_idx->ei_block); -+ len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx; -+ if (logical > curp->p_idx->ei_block) { -+ /* insert after */ -+ if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) { -+ len = (len - 1) * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d after: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ (curp->p_idx + 1), (curp->p_idx + 2)); -+ memmove(curp->p_idx + 2, curp->p_idx + 1, len); -+ } -+ ix = curp->p_idx + 1; -+ } else { -+ /* insert before */ -+ len = len * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d before: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ curp->p_idx, (curp->p_idx + 1)); -+ memmove(curp->p_idx + 1, curp->p_idx, len); -+ ix = curp->p_idx; -+ } -+ -+ ix->ei_block = logical; -+ ix->ei_leaf = ptr; -+ ix->ei_leaf_hi = ix->ei_unused = 0; -+ curp->p_hdr->eh_entries++; -+ -+ EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max); -+ EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr)); -+ -+ err = ext3_ext_dirty(handle, tree, curp); -+ ext3_std_error(tree->inode->i_sb, err); -+ -+ return err; -+} -+ -+/* -+ * routine inserts new subtree into the path, using free index entry -+ * at depth 'at: -+ * - allocates all needed blocks (new leaf and all intermediate index blocks) -+ * - makes decision where to split -+ * - moves remaining extens and index entries (right to the split point) -+ * into the newly allocated blocks -+ * - initialize subtree -+ */ -+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext, int at) -+{ -+ struct buffer_head *bh = NULL; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct ext3_extent *ex; -+ int i = at, k, m, a; -+ unsigned long newblock, oldblock, border; -+ int *ablocks = NULL; /* array of allocated blocks */ -+ int err = 0; -+ -+ /* make decision: where to split? */ -+ /* FIXME: now desicion is simplest: at current extent */ -+ -+ /* if current leaf will be splitted, then we should use -+ * border from split point */ -+ EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr)); -+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ border = path[depth].p_ext[1].ee_block; -+ ext_debug(tree, "leaf will be splitted." -+ " next leaf starts at %d\n", -+ (int)border); -+ } else { -+ border = newext->ee_block; -+ ext_debug(tree, "leaf will be added." -+ " next leaf starts at %d\n", -+ (int)border); -+ } -+ -+ /* -+ * if error occurs, then we break processing -+ * and turn filesystem read-only. so, index won't -+ * be inserted and tree will be in consistent -+ * state. next mount will repair buffers too -+ */ -+ -+ /* -+ * get array to track all allocated blocks -+ * we need this to handle errors and free blocks -+ * upon them -+ */ -+ ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS); -+ if (!ablocks) -+ return -ENOMEM; -+ memset(ablocks, 0, sizeof(unsigned long) * depth); -+ -+ /* allocate all needed blocks */ -+ ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at); -+ for (a = 0; a < depth - at; a++) { -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ goto cleanup; -+ ablocks[a] = newblock; -+ } -+ -+ /* initialize new leaf */ -+ newblock = ablocks[--a]; -+ EXT_ASSERT(newblock); -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 0; -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_depth = 0; -+ ex = EXT_FIRST_EXTENT(neh); -+ -+ /* move remain of path[depth] to the new leaf */ -+ EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max); -+ /* start copy from next extent */ -+ /* TODO: we could do it by single memmove */ -+ m = 0; -+ path[depth].p_ext++; -+ while (path[depth].p_ext <= -+ EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n", -+ path[depth].p_ext->ee_block, -+ path[depth].p_ext->ee_start, -+ path[depth].p_ext->ee_len, -+ newblock); -+ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent)); -+ neh->eh_entries++; -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old leaf */ -+ if (m) { -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ path[depth].p_hdr->eh_entries -= m; -+ if ((err = ext3_ext_dirty(handle, tree, path + depth))) -+ goto cleanup; -+ -+ } -+ -+ /* create intermediate indexes */ -+ k = depth - at - 1; -+ EXT_ASSERT(k >= 0); -+ if (k) -+ ext_debug(tree, "create %d intermediate indices\n", k); -+ /* insert new index into current index block */ -+ /* current depth stored in i var */ -+ i = depth - 1; -+ while (k--) { -+ oldblock = newblock; -+ newblock = ablocks[--a]; -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 1; -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ neh->eh_depth = depth - i; -+ fidx = EXT_FIRST_INDEX(neh); -+ fidx->ei_block = border; -+ fidx->ei_leaf = oldblock; -+ fidx->ei_leaf_hi = fidx->ei_unused = 0; -+ -+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n", -+ i, newblock, border, oldblock); -+ /* copy indexes */ -+ m = 0; -+ path[i].p_idx++; -+ -+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx, -+ EXT_MAX_INDEX(path[i].p_hdr)); -+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) == -+ EXT_LAST_INDEX(path[i].p_hdr)); -+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { -+ ext_debug(tree, "%d: move %d:%d in new index %lu\n", -+ i, path[i].p_idx->ei_block, -+ path[i].p_idx->ei_leaf, newblock); -+ memmove(++fidx, path[i].p_idx++, -+ sizeof(struct ext3_extent_idx)); -+ neh->eh_entries++; -+ EXT_ASSERT(neh->eh_entries <= neh->eh_max); -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old index */ -+ if (m) { -+ err = ext3_ext_get_access(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ path[i].p_hdr->eh_entries -= m; -+ err = ext3_ext_dirty(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ } -+ -+ i--; -+ } -+ -+ /* insert new index */ -+ if (!err) -+ err = ext3_ext_insert_index(handle, tree, path + at, -+ border, newblock); -+ -+cleanup: -+ if (bh) { -+ if (buffer_locked(bh)) -+ unlock_buffer(bh); -+ brelse(bh); -+ } -+ -+ if (err) { -+ /* free all allocated blocks in error case */ -+ for (i = 0; i < depth; i++) { -+ if (!ablocks[i]) -+ continue; -+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1); -+ } -+ } -+ kfree(ablocks); -+ -+ return err; -+} -+ -+/* -+ * routine implements tree growing procedure: -+ * - allocates new block -+ * - moves top-level data (index block or leaf) into the new block -+ * - initialize new top-level, creating index that points to the -+ * just created block -+ */ -+static int ext3_ext_grow_indepth(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp = path; -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct buffer_head *bh; -+ unsigned long newblock; -+ int err = 0; -+ -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ return err; -+ -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ ext3_std_error(tree->inode->i_sb, err); -+ return err; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) { -+ unlock_buffer(bh); -+ goto out; -+ } -+ -+ /* move top-level index/leaf into new block */ -+ memmove(bh->b_data, curp->p_hdr, tree->buffer_len); -+ -+ /* set size of new block */ -+ neh = EXT_BLOCK_HDR(bh); -+ /* old root could have indexes or leaves -+ * so calculate eh_max right way */ -+ if (EXT_DEPTH(tree)) -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ else -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto out; -+ -+ /* create index in new top-level index: num,max,pointer */ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ goto out; -+ -+ curp->p_hdr->eh_magic = EXT3_EXT_MAGIC; -+ curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree); -+ curp->p_hdr->eh_entries = 1; -+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); -+ /* FIXME: it works, but actually path[0] can be index */ -+ curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; -+ curp->p_idx->ei_leaf = newblock; -+ curp->p_idx->ei_leaf_hi = curp->p_idx->ei_unused = 0; -+ -+ neh = EXT_ROOT_HDR(tree); -+ fidx = EXT_FIRST_INDEX(neh); -+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n", -+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); -+ -+ neh->eh_depth = path->p_depth + 1; -+ err = ext3_ext_dirty(handle, tree, curp); -+out: -+ brelse(bh); -+ -+ return err; -+} -+ -+/* -+ * routine finds empty index and adds new leaf. if no free index found -+ * then it requests in-depth growing -+ */ -+static int ext3_ext_create_new_leaf(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp; -+ int depth, i, err = 0; -+ -+repeat: -+ i = depth = EXT_DEPTH(tree); -+ -+ /* walk up to the tree and look for free index entry */ -+ curp = path + depth; -+ while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) { -+ i--; -+ curp--; -+ } -+ -+ /* we use already allocated block for index block -+ * so, subsequent data blocks should be contigoues */ -+ if (EXT_HAS_FREE_INDEX(curp)) { -+ /* if we found index with free entry, then use that -+ * entry: create all needed subtree and add new leaf */ -+ err = ext3_ext_split(handle, tree, path, newext, i); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ } else { -+ /* tree is full, time to grow in depth */ -+ err = ext3_ext_grow_indepth(handle, tree, path, newext); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ -+ /* -+ * only first (depth 0 -> 1) produces free space -+ * in all other cases we have to split growed tree -+ */ -+ depth = EXT_DEPTH(tree); -+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) { -+ /* now we need split */ -+ goto repeat; -+ } -+ } -+ -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+/* -+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK -+ * NOTE: it consider block number from index entry as -+ * allocated block. thus, index entries have to be consistent -+ * with leafs -+ */ -+static unsigned long -+ext3_ext_next_allocated_block(struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ if (depth == 0 && path->p_ext == NULL) -+ return EXT_MAX_BLOCK; -+ -+ /* FIXME: what if index isn't full ?! */ -+ while (depth >= 0) { -+ if (depth == path->p_depth) { -+ /* leaf */ -+ if (path[depth].p_ext != -+ EXT_LAST_EXTENT(path[depth].p_hdr)) -+ return path[depth].p_ext[1].ee_block; -+ } else { -+ /* index */ -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ } -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * returns first allocated block from next leaf or EXT_MAX_BLOCK -+ */ -+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ /* zero-tree has no leaf blocks at all */ -+ if (depth == 0) -+ return EXT_MAX_BLOCK; -+ -+ /* go to index block */ -+ depth--; -+ -+ while (depth >= 0) { -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * if leaf gets modified and modified extent is first in the leaf -+ * then we have to correct all indexes above -+ * TODO: do we need to correct tree in all cases? -+ */ -+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent *ex; -+ unsigned long border; -+ int k, err = 0; -+ -+ eh = path[depth].p_hdr; -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(eh); -+ -+ if (depth == 0) { -+ /* there is no tree at all */ -+ return 0; -+ } -+ -+ if (ex != EXT_FIRST_EXTENT(eh)) { -+ /* we correct tree if first leaf got modified only */ -+ return 0; -+ } -+ -+ /* -+ * TODO: we need correction if border is smaller then current one -+ */ -+ k = depth - 1; -+ border = path[depth].p_ext->ee_block; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ return err; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ return err; -+ -+ while (k--) { -+ /* change all left-side indexes */ -+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr)) -+ break; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ break; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ break; -+ } -+ -+ return err; -+} -+ -+static int inline -+ext3_can_extents_be_merged(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block) -+ return 0; -+ -+#ifdef AGRESSIVE_TEST -+ if (ex1->ee_len >= 4) -+ return 0; -+#endif -+ -+ if (!tree->ops->mergable) -+ return 1; -+ -+ return tree->ops->mergable(ex1, ex2); -+} -+ -+/* -+ * this routine tries to merge requsted extent into the existing -+ * extent or inserts requested extent as new one into the tree, -+ * creating new leaf in no-space case -+ */ -+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_extent_header * eh; -+ struct ext3_extent *ex, *fex; -+ struct ext3_extent *nearex; /* nearest extent */ -+ struct ext3_ext_path *npath = NULL; -+ int depth, len, err, next; -+ -+ EXT_ASSERT(newext->ee_len > 0); -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(path[depth].p_hdr); -+ -+ /* try to insert block into found extent and return */ -+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) { -+ ext_debug(tree, "append %d block to %d:%d (from %d)\n", -+ newext->ee_len, ex->ee_block, ex->ee_len, -+ ex->ee_start); -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ return err; -+ ex->ee_len += newext->ee_len; -+ eh = path[depth].p_hdr; -+ nearex = ex; -+ goto merge; -+ } -+ -+repeat: -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) -+ goto has_space; -+ -+ /* probably next leaf has space for us? */ -+ fex = EXT_LAST_EXTENT(eh); -+ next = ext3_ext_next_leaf_block(tree, path); -+ if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) { -+ ext_debug(tree, "next leaf block - %d\n", next); -+ EXT_ASSERT(!npath); -+ npath = ext3_ext_find_extent(tree, next, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ EXT_ASSERT(npath->p_depth == path->p_depth); -+ eh = npath[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) { -+ ext_debug(tree, "next leaf isnt full(%d)\n", -+ eh->eh_entries); -+ path = npath; -+ goto repeat; -+ } -+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n", -+ eh->eh_entries, eh->eh_max); -+ } -+ -+ /* -+ * there is no free space in found leaf -+ * we're gonna add new leaf in the tree -+ */ -+ err = ext3_ext_create_new_leaf(handle, tree, path, newext); -+ if (err) -+ goto cleanup; -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ -+has_space: -+ nearex = path[depth].p_ext; -+ -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ -+ if (!nearex) { -+ /* there is no extent in this leaf, create first one */ -+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len); -+ path[depth].p_ext = EXT_FIRST_EXTENT(eh); -+ } else if (newext->ee_block > nearex->ee_block) { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ if (nearex != EXT_LAST_EXTENT(eh)) { -+ len = EXT_MAX_EXTENT(eh) - nearex; -+ len = (len - 1) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 2, nearex + 1, len); -+ } -+ path[depth].p_ext = nearex + 1; -+ } else { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 1, nearex, len); -+ path[depth].p_ext = nearex; -+ } -+ -+ eh->eh_entries++; -+ nearex = path[depth].p_ext; -+ nearex->ee_block = newext->ee_block; -+ nearex->ee_start = newext->ee_start; -+ nearex->ee_len = newext->ee_len; -+ /* FIXME: support for large fs */ -+ nearex->ee_start_hi = 0; -+ -+merge: -+ /* try to merge extents to the right */ -+ while (nearex < EXT_LAST_EXTENT(eh)) { -+ if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1)) -+ break; -+ /* merge with next extent! */ -+ nearex->ee_len += nearex[1].ee_len; -+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) { -+ len = (EXT_LAST_EXTENT(eh) - nearex - 1) * -+ sizeof(struct ext3_extent); -+ memmove(nearex + 1, nearex + 2, len); -+ } -+ eh->eh_entries--; -+ EXT_ASSERT(eh->eh_entries > 0); -+ } -+ -+ /* try to merge extents to the left */ -+ -+ /* time to correct all indexes above */ -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ if (err) -+ goto cleanup; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ -+cleanup: -+ if (npath) { -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ } -+ ext3_ext_tree_changed(tree); -+ ext3_ext_invalidate_cache(tree); -+ return err; -+} -+ -+int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block, -+ unsigned long num, ext_prepare_callback func) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_ext_cache cbex; -+ struct ext3_extent *ex; -+ unsigned long next, start = 0, end = 0; -+ unsigned long last = block + num; -+ int depth, exists, err = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(func); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ while (block < last && block != EXT_MAX_BLOCK) { -+ num = last - block; -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(tree, block, path); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ break; -+ } -+ -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(path[depth].p_hdr); -+ ex = path[depth].p_ext; -+ next = ext3_ext_next_allocated_block(path); -+ -+ exists = 0; -+ if (!ex) { -+ /* there is no extent yet, so try to allocate -+ * all requested space */ -+ start = block; -+ end = block + num; -+ } else if (ex->ee_block > block) { -+ /* need to allocate space before found extent */ -+ start = block; -+ end = ex->ee_block; -+ if (block + num < end) -+ end = block + num; -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ /* need to allocate space after found extent */ -+ start = block; -+ end = block + num; -+ if (end >= next) -+ end = next; -+ } else if (block >= ex->ee_block) { -+ /* -+ * some part of requested space is covered -+ * by found extent -+ */ -+ start = block; -+ end = ex->ee_block + ex->ee_len; -+ if (block + num < end) -+ end = block + num; -+ exists = 1; -+ } else { -+ BUG(); -+ } -+ EXT_ASSERT(end > start); -+ -+ if (!exists) { -+ cbex.ec_block = start; -+ cbex.ec_len = end - start; -+ cbex.ec_start = 0; -+ cbex.ec_type = EXT3_EXT_CACHE_GAP; -+ } else { -+ cbex.ec_block = ex->ee_block; -+ cbex.ec_len = ex->ee_len; -+ cbex.ec_start = ex->ee_start; -+ cbex.ec_type = EXT3_EXT_CACHE_EXTENT; -+ } -+ -+ EXT_ASSERT(cbex.ec_len > 0); -+ EXT_ASSERT(path[depth].p_hdr); -+ err = func(tree, path, &cbex); -+ ext3_ext_drop_refs(path); -+ -+ if (err < 0) -+ break; -+ if (err == EXT_REPEAT) -+ continue; -+ else if (err == EXT_BREAK) { -+ err = 0; -+ break; -+ } -+ -+ if (EXT_DEPTH(tree) != depth) { -+ /* depth was changed. we have to realloc path */ -+ kfree(path); -+ path = NULL; -+ } -+ -+ block = cbex.ec_block + cbex.ec_len; -+ } -+ -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ -+ return err; -+} -+ -+static inline void -+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block, -+ __u32 len, __u32 start, int type) -+{ -+ EXT_ASSERT(len > 0); -+ if (tree->cex) { -+ tree->cex->ec_type = type; -+ tree->cex->ec_block = block; -+ tree->cex->ec_len = len; -+ tree->cex->ec_start = start; -+ } -+} -+ -+/* -+ * this routine calculate boundaries of the gap requested block fits into -+ * and cache this gap -+ */ -+static inline void -+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ int depth = EXT_DEPTH(tree); -+ unsigned long lblock, len; -+ struct ext3_extent *ex; -+ -+ if (!tree->cex) -+ return; -+ -+ ex = path[depth].p_ext; -+ if (ex == NULL) { -+ /* there is no extent yet, so gap is [0;-] */ -+ lblock = 0; -+ len = EXT_MAX_BLOCK; -+ ext_debug(tree, "cache gap(whole file):"); -+ } else if (block < ex->ee_block) { -+ lblock = block; -+ len = ex->ee_block - block; -+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len); -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ lblock = ex->ee_block + ex->ee_len; -+ len = ext3_ext_next_allocated_block(path); -+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu", -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) block); -+ EXT_ASSERT(len > lblock); -+ len = len - lblock; -+ } else { -+ lblock = len = 0; -+ BUG(); -+ } -+ -+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len); -+ ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP); -+} -+ -+static inline int -+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block, -+ struct ext3_extent *ex) -+{ -+ struct ext3_ext_cache *cex = tree->cex; -+ -+ /* is there cache storage at all? */ -+ if (!cex) -+ return EXT3_EXT_CACHE_NO; -+ -+ /* has cache valid data? */ -+ if (cex->ec_type == EXT3_EXT_CACHE_NO) -+ return EXT3_EXT_CACHE_NO; -+ -+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP || -+ cex->ec_type == EXT3_EXT_CACHE_EXTENT); -+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { -+ ex->ee_block = cex->ec_block; -+ ex->ee_start = cex->ec_start; -+ ex->ee_start_hi = 0; -+ ex->ee_len = cex->ec_len; -+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) ex->ee_start); -+ return cex->ec_type; -+ } -+ -+ /* not in cache */ -+ return EXT3_EXT_CACHE_NO; -+} -+ -+/* -+ * routine removes index from the index block -+ * it's used in truncate case only. thus all requests are for -+ * last index in the block only -+ */ -+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct buffer_head *bh; -+ int err; -+ -+ /* free index block */ -+ path--; -+ EXT_ASSERT(path->p_hdr->eh_entries); -+ if ((err = ext3_ext_get_access(handle, tree, path))) -+ return err; -+ path->p_hdr->eh_entries--; -+ if ((err = ext3_ext_dirty(handle, tree, path))) -+ return err; -+ ext_debug(tree, "index is empty, remove it, free block %d\n", -+ path->p_idx->ei_leaf); -+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf); -+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf); -+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1); -+ return err; -+} -+ -+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth = EXT_DEPTH(tree); -+ int needed; -+ -+ if (path) { -+ /* probably there is space in leaf? */ -+ if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max) -+ return 1; -+ } -+ -+ /* -+ * the worste case we're expecting is creation of the -+ * new root (growing in depth) with index splitting -+ * for splitting we have to consider depth + 1 because -+ * previous growing could increase it -+ */ -+ depth = depth + 1; -+ -+ /* -+ * growing in depth: -+ * block allocation + new root + old root -+ */ -+ needed = EXT3_ALLOC_NEEDED + 2; -+ -+ /* index split. we may need: -+ * allocate intermediate indexes and new leaf -+ * change two blocks at each level, but root -+ * modify root block (inode) -+ */ -+ needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1; -+ -+ return needed; -+} -+ -+static int -+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, tex; -+ struct ext3_ext_path *npath; -+ int depth, creds, err; -+ -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1); -+ EXT_ASSERT(ex->ee_block < start); -+ -+ /* calculate tail extent */ -+ tex.ee_block = end + 1; -+ EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len); -+ tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block; -+ -+ creds = ext3_ext_calc_credits_for_insert(tree, path); -+ handle = ext3_ext_journal_restart(handle, creds); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ /* calculate head extent. use primary extent */ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ return err; -+ ex->ee_len = start - ex->ee_block; -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ return err; -+ -+ /* FIXME: some callback to free underlying resource -+ * and correct ee_start? */ -+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n", -+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len); -+ -+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block); -+ EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len); -+ -+ err = ext3_ext_insert_extent(handle, tree, npath, &tex); -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ -+ return err; -+} -+ -+static int -+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, *fu = NULL, *lu, *le; -+ int err = 0, correct_index = 0; -+ int depth = EXT_DEPTH(tree), credits; -+ struct ext3_extent_header *eh; -+ unsigned a, b, block, num; -+ -+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end); -+ if (!path[depth].p_hdr) -+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh); -+ eh = path[depth].p_hdr; -+ EXT_ASSERT(eh); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* find where to start removing */ -+ le = ex = EXT_LAST_EXTENT(eh); -+ while (ex != EXT_FIRST_EXTENT(eh)) { -+ if (ex->ee_block <= end) -+ break; -+ ex--; -+ } -+ -+ if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) { -+ /* removal of internal part of the extent requested -+ * tail and head must be placed in different extent -+ * so, we have to insert one more extent */ -+ path[depth].p_ext = ex; -+ return ext3_ext_split_for_rm(handle, tree, path, start, end); -+ } -+ -+ lu = ex; -+ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) { -+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len); -+ path[depth].p_ext = ex; -+ -+ a = ex->ee_block > start ? ex->ee_block : start; -+ b = ex->ee_block + ex->ee_len - 1 < end ? -+ ex->ee_block + ex->ee_len - 1 : end; -+ -+ ext_debug(tree, " border %u:%u\n", a, b); -+ -+ if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) { -+ block = 0; -+ num = 0; -+ BUG(); -+ } else if (a != ex->ee_block) { -+ /* remove tail of the extent */ -+ block = ex->ee_block; -+ num = a - block; -+ } else if (b != ex->ee_block + ex->ee_len - 1) { -+ /* remove head of the extent */ -+ block = a; -+ num = b - a; -+ } else { -+ /* remove whole extent: excelent! */ -+ block = ex->ee_block; -+ num = 0; -+ EXT_ASSERT(a == ex->ee_block && -+ b == ex->ee_block + ex->ee_len - 1); -+ } -+ -+ if (ex == EXT_FIRST_EXTENT(eh)) -+ correct_index = 1; -+ -+ credits = 1; -+ if (correct_index) -+ credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1; -+ if (tree->ops->remove_extent_credits) -+ credits+=tree->ops->remove_extent_credits(tree,ex,a,b); -+ -+ handle = ext3_ext_journal_restart(handle, credits); -+ if (IS_ERR(handle)) { -+ err = PTR_ERR(handle); -+ goto out; -+ } -+ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ if (tree->ops->remove_extent) -+ err = tree->ops->remove_extent(tree, ex, a, b); -+ if (err) -+ goto out; -+ -+ if (num == 0) { -+ /* this extent is removed entirely mark slot unused */ -+ ex->ee_start = ex->ee_start_hi = 0; -+ eh->eh_entries--; -+ fu = ex; -+ } -+ -+ ex->ee_block = block; -+ ex->ee_len = num; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ ext_debug(tree, "new extent: %u:%u:%u\n", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ ex--; -+ } -+ -+ if (fu) { -+ /* reuse unused slots */ -+ while (lu < le) { -+ if (lu->ee_start) { -+ *fu = *lu; -+ lu->ee_start = lu->ee_start_hi = 0; -+ fu++; -+ } -+ lu++; -+ } -+ } -+ -+ if (correct_index && eh->eh_entries) -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ -+ /* if this leaf is free, then we should -+ * remove it from index block above */ -+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) -+ err = ext3_ext_rm_idx(handle, tree, path + depth); -+ -+out: -+ return err; -+} -+ -+ -+static struct ext3_extent_idx * -+ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block) -+{ -+ struct ext3_extent_idx *ix; -+ -+ ix = EXT_LAST_INDEX(hdr); -+ while (ix != EXT_FIRST_INDEX(hdr)) { -+ if (ix->ei_block <= block) -+ break; -+ ix--; -+ } -+ return ix; -+} -+ -+/* -+ * returns 1 if current index have to be freed (even partial) -+ */ -+static int inline -+ext3_ext_more_to_rm(struct ext3_ext_path *path) -+{ -+ EXT_ASSERT(path->p_idx); -+ -+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr)) -+ return 0; -+ -+ /* -+ * if truncate on deeper level happened it it wasn't partial -+ * so we have to consider current index for truncation -+ */ -+ if (path->p_hdr->eh_entries == path->p_block) -+ return 0; -+ return 1; -+} -+ -+int ext3_ext_remove_space(struct ext3_extents_tree *tree, -+ unsigned long start, unsigned long end) -+{ -+ struct inode *inode = tree->inode; -+ struct super_block *sb = inode->i_sb; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_ext_path *path; -+ handle_t *handle; -+ int i = 0, err = 0; -+ -+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end); -+ -+ /* probably first extent we're gonna free will be last in block */ -+ handle = ext3_journal_start(inode, depth + 1); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ ext3_ext_invalidate_cache(tree); -+ -+ /* -+ * we start scanning from right side freeing all the blocks -+ * after i_size and walking into the deep -+ */ -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL); -+ if (IS_ERR(path)) { -+ ext3_error(sb, __FUNCTION__, "Can't allocate path array"); -+ ext3_journal_stop(handle, inode); -+ return -ENOMEM; -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[i].p_hdr = EXT_ROOT_HDR(tree); -+ -+ while (i >= 0 && err == 0) { -+ if (i == depth) { -+ /* this is leaf block */ -+ err = ext3_ext_rm_leaf(handle, tree, path, start, end); -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ continue; -+ } -+ -+ /* this is index block */ -+ if (!path[i].p_hdr) { -+ ext_debug(tree, "initialize header\n"); -+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh); -+ } -+ -+ EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max); -+ EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC); -+ -+ if (!path[i].p_idx) { -+ /* this level hasn't touched yet */ -+ path[i].p_idx = -+ ext3_ext_last_covered(path[i].p_hdr, end); -+ path[i].p_block = path[i].p_hdr->eh_entries + 1; -+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n", -+ path[i].p_hdr, path[i].p_hdr->eh_entries); -+ } else { -+ /* we've already was here, see at next index */ -+ path[i].p_idx--; -+ } -+ -+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n", -+ i, EXT_FIRST_INDEX(path[i].p_hdr), -+ path[i].p_idx); -+ if (ext3_ext_more_to_rm(path + i)) { -+ /* go to the next level */ -+ ext_debug(tree, "move to level %d (block %d)\n", -+ i + 1, path[i].p_idx->ei_leaf); -+ memset(path + i + 1, 0, sizeof(*path)); -+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf); -+ if (!path[i+1].p_bh) { -+ /* should we reset i_size? */ -+ err = -EIO; -+ break; -+ } -+ /* put actual number of indexes to know is this -+ * number got changed at the next iteration */ -+ path[i].p_block = path[i].p_hdr->eh_entries; -+ i++; -+ } else { -+ /* we finish processing this index, go up */ -+ if (path[i].p_hdr->eh_entries == 0 && i > 0) { -+ /* index is empty, remove it -+ * handle must be already prepared by the -+ * truncatei_leaf() */ -+ err = ext3_ext_rm_idx(handle, tree, path + i); -+ } -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ ext_debug(tree, "return to level %d\n", i); -+ } -+ } -+ -+ /* TODO: flexible tree reduction should be here */ -+ if (path->p_hdr->eh_entries == 0) { -+ /* -+ * truncate to zero freed all the tree -+ * so, we need to correct eh_depth -+ */ -+ err = ext3_ext_get_access(handle, tree, path); -+ if (err == 0) { -+ EXT_ROOT_HDR(tree)->eh_depth = 0; -+ EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree); -+ err = ext3_ext_dirty(handle, tree, path); -+ } -+ } -+ ext3_ext_tree_changed(tree); -+ -+ kfree(path); -+ ext3_journal_stop(handle, inode); -+ -+ return err; -+} -+ -+/* -+ * called at mount time -+ */ -+void ext3_ext_init(struct super_block *sb) -+{ -+ /* -+ * possible initialization would be here -+ */ -+ -+ if (test_opt(sb, EXTENTS)) { -+ printk("EXT3-fs: file extents enabled"); -+#ifdef AGRESSIVE_TEST -+ printk(", agressive tests"); -+#endif -+#ifdef CHECK_BINSEARCH -+ printk(", check binsearch"); -+#endif -+ printk("\n"); -+ } -+} -+ -+/* -+ * called at umount time -+ */ -+void ext3_ext_release(struct super_block *sb) -+{ -+} -+ -+/************************************************************************ -+ * VFS related routines -+ ************************************************************************/ -+ -+static int ext3_get_inode_write_access(handle_t *handle, void *buffer) -+{ -+ /* we use in-core data, not bh */ -+ return 0; -+} -+ -+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer) -+{ -+ struct inode *inode = buffer; -+ return ext3_mark_inode_dirty(handle, inode); -+} -+ -+static int ext3_ext_mergable(struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ /* FIXME: support for large fs */ -+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start) -+ return 1; -+ return 0; -+} -+ -+static int -+ext3_remove_blocks_credits(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed; -+ -+ /* at present, extent can't cross block group */; -+ needed = 4; /* bitmap + group desc + sb + inode */ -+ -+#ifdef CONFIG_QUOTA -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ return needed; -+} -+ -+static int -+ext3_remove_blocks(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed = ext3_remove_blocks_credits(tree, ex, from, to); -+ handle_t *handle = ext3_journal_start(tree->inode, needed); -+ struct buffer_head *bh; -+ int i; -+ -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) { -+ /* tail removal */ -+ unsigned long num, start; -+ num = ex->ee_block + ex->ee_len - from; -+ start = ex->ee_start + ex->ee_len - num; -+ ext_debug(tree, "free last %lu blocks starting %lu\n", -+ num, start); -+ for (i = 0; i < num; i++) { -+ bh = sb_get_hash_table(tree->inode->i_sb, start + i); -+ ext3_forget(handle, 0, tree->inode, bh, start + i); -+ } -+ ext3_free_blocks(handle, tree->inode, start, num); -+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) { -+ printk("strange request: removal %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } else { -+ printk("strange request: removal(2) %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } -+ ext3_journal_stop(handle, tree->inode); -+ return 0; -+} -+ -+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ int depth; -+ -+ if (path) { -+ struct ext3_extent *ex; -+ depth = path->p_depth; -+ -+ /* try to predict block placement */ -+ if ((ex = path[depth].p_ext)) -+ return ex->ee_start + (block - ex->ee_block); -+ -+ /* it looks index is empty -+ * try to find starting from index itself */ -+ if (path[depth].p_bh) -+ return path[depth].p_bh->b_blocknr; -+ } -+ -+ /* OK. use inode's group */ -+ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ return bg_start + colour + block; -+} -+ -+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *ex, int *err) -+{ -+ struct inode *inode = tree->inode; -+ int newblock, goal; -+ -+ EXT_ASSERT(path); -+ EXT_ASSERT(ex); -+ EXT_ASSERT(ex->ee_start); -+ EXT_ASSERT(ex->ee_len); -+ -+ /* reuse block from the extent to order data/metadata */ -+ newblock = ex->ee_start++; -+ ex->ee_len--; -+ if (ex->ee_len == 0) { -+ ex->ee_len = 1; -+ /* allocate new block for the extent */ -+ goal = ext3_ext_find_goal(inode, path, ex->ee_block); -+ lock_kernel(); -+ ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err); -+ ex->ee_start_hi = 0; -+ unlock_kernel(); -+ if (ex->ee_start == 0) { -+ /* error occured: restore old extent */ -+ ex->ee_start = newblock; -+ return 0; -+ } -+ } -+ return newblock; -+} -+ -+static struct ext3_extents_helpers ext3_blockmap_helpers = { -+ .get_write_access = ext3_get_inode_write_access, -+ .mark_buffer_dirty = ext3_mark_buffer_dirty, -+ .mergable = ext3_ext_mergable, -+ .new_block = ext3_new_block_cb, -+ .remove_extent = ext3_remove_blocks, -+ .remove_extent_credits = ext3_remove_blocks_credits, -+}; -+ -+void ext3_init_tree_desc(struct ext3_extents_tree *tree, -+ struct inode *inode) -+{ -+ tree->inode = inode; -+ tree->root = (void *) EXT3_I(inode)->i_data; -+ tree->buffer = (void *) inode; -+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data); -+ tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent; -+ tree->ops = &ext3_blockmap_helpers; -+} -+ -+int ext3_ext_get_block(handle_t *handle, struct inode *inode, -+ long iblock, struct buffer_head *bh_result, int create) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_extent newex; -+ struct ext3_extent *ex; -+ int goal, newblock, err = 0, depth; -+ struct ext3_extents_tree tree; -+ -+ clear_bit(BH_New, &bh_result->b_state); -+ ext3_init_tree_desc(&tree, inode); -+ ext_debug(&tree, "block %d requested for inode %u\n", -+ (int) iblock, (unsigned) inode->i_ino); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ -+ /* check in cache */ -+ if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) { -+ if (goal == EXT3_EXT_CACHE_GAP) { -+ if (!create) { -+ /* block isn't allocated yet and -+ * user don't want to allocate it */ -+ goto out2; -+ } -+ /* we should allocate requested block */ -+ } else if (goal == EXT3_EXT_CACHE_EXTENT) { -+ /* block is already allocated */ -+ newblock = iblock - newex.ee_block + newex.ee_start; -+ goto out; -+ } else { -+ EXT_ASSERT(0); -+ } -+ } -+ -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(&tree, iblock, NULL); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ goto out2; -+ } -+ -+ depth = EXT_DEPTH(&tree); -+ -+ /* -+ * consistent leaf must not be empty -+ * this situations is possible, though, _during_ tree modification -+ * this is why assert can't be put in ext3_ext_find_extent() -+ */ -+ EXT_ASSERT(path[depth].p_ext != NULL || depth == 0); -+ -+ if ((ex = path[depth].p_ext)) { -+ /* if found exent covers block, simple return it */ -+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) { -+ newblock = iblock - ex->ee_block + ex->ee_start; -+ ext_debug(&tree, "%d fit into %d:%d -> %d\n", -+ (int) iblock, ex->ee_block, ex->ee_len, -+ newblock); -+ ext3_ext_put_in_cache(&tree, ex->ee_block, -+ ex->ee_len, ex->ee_start, -+ EXT3_EXT_CACHE_EXTENT); -+ goto out; -+ } -+ } -+ -+ /* -+ * requested block isn't allocated yet -+ * we couldn't try to create block if create flag is zero -+ */ -+ if (!create) { -+ /* put just found gap into cache to speedup subsequest reqs */ -+ ext3_ext_put_gap_in_cache(&tree, path, iblock); -+ goto out2; -+ } -+ -+ /* allocate new block */ -+ goal = ext3_ext_find_goal(inode, path, iblock); -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err); -+ unlock_kernel(); -+ if (!newblock) -+ goto out2; -+ ext_debug(&tree, "allocate new block: goal %d, found %d\n", -+ goal, newblock); -+ -+ /* try to insert new extent into found leaf and return */ -+ newex.ee_block = iblock; -+ newex.ee_start = newblock; -+ newex.ee_start_hi = 0; -+ newex.ee_len = 1; -+ err = ext3_ext_insert_extent(handle, &tree, path, &newex); -+ if (err) -+ goto out2; -+ -+ if (inode->i_size > EXT3_I(inode)->i_disksize) -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ -+ /* previous routine could use block we allocated */ -+ newblock = newex.ee_start; -+ set_bit(BH_New, &bh_result->b_state); -+ -+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len, -+ newex.ee_start, EXT3_EXT_CACHE_EXTENT); -+out: -+ ext3_ext_show_leaf(&tree, path); -+ set_bit(BH_Mapped, &bh_result->b_state); -+ bh_result->b_dev = inode->i_sb->s_dev; -+ bh_result->b_blocknr = newblock; -+out2: -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ up_write(&EXT3_I(inode)->truncate_sem); -+ -+ return err; -+} -+ -+void ext3_ext_truncate(struct inode * inode) -+{ -+ struct address_space *mapping = inode->i_mapping; -+ struct super_block *sb = inode->i_sb; -+ struct ext3_extents_tree tree; -+ unsigned long last_block; -+ handle_t *handle; -+ int err = 0; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ /* -+ * probably first extent we're gonna free will be last in block -+ */ -+ err = ext3_writepage_trans_blocks(inode) + 3; -+ handle = ext3_journal_start(inode, err); -+ if (IS_ERR(handle)) -+ return; -+ -+ ext3_block_truncate_page(handle, mapping, inode->i_size); -+ -+ down_write(&EXT3_I(inode)->truncate_sem); -+ ext3_ext_invalidate_cache(&tree); -+ -+ /* -+ * TODO: optimization is possible here -+ * probably we need not scaning at all, -+ * because page truncation is enough -+ */ -+ if (ext3_orphan_add(handle, inode)) -+ goto out_stop; -+ -+ /* we have to know where to truncate from in crash case */ -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_mark_inode_dirty(handle, inode); -+ -+ last_block = (inode->i_size + sb->s_blocksize - 1) >> -+ EXT3_BLOCK_SIZE_BITS(sb); -+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK); -+ -+ /* In a multi-transaction truncate, we only make the final -+ * transaction synchronous */ -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+out_stop: -+ /* -+ * If this was a simple ftruncate(), and the file will remain alive -+ * then we need to clear up the orphan record which we created above. -+ * However, if this was a real unlink then we were called by -+ * ext3_delete_inode(), and we allow that function to clean up the -+ * orphan info for us. -+ */ -+ if (inode->i_nlink) -+ ext3_orphan_del(handle, inode); -+ -+ up_write(&EXT3_I(inode)->truncate_sem); -+ ext3_journal_stop(handle, inode); -+} -+ -+/* -+ * this routine calculate max number of blocks we could modify -+ * in order to allocate new block for an inode -+ */ -+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num) -+{ -+ struct ext3_extents_tree tree; -+ int needed; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ needed = ext3_ext_calc_credits_for_insert(&tree, NULL); -+ -+ /* caller want to allocate num blocks */ -+ needed *= num; -+ -+#ifdef CONFIG_QUOTA -+ /* -+ * FIXME: real calculation should be here -+ * it depends on blockmap format of qouta file -+ */ -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ -+ return needed; -+} -+ -+void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode) -+{ -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ ext3_extent_tree_init(handle, &tree); -+} -+ -+static int -+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *newex) -+{ -+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private; -+ -+ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ if (buf->err < 0) -+ return EXT_BREAK; -+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen) -+ return EXT_BREAK; -+ -+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) { -+ buf->err++; -+ buf->cur += sizeof(*newex); -+ } else { -+ buf->err = -EFAULT; -+ return EXT_BREAK; -+ } -+ return EXT_CONTINUE; -+} -+ -+static int -+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *ex) -+{ -+ struct ext3_extent_tree_stats *buf = -+ (struct ext3_extent_tree_stats *) tree->private; -+ int depth; -+ -+ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ depth = EXT_DEPTH(tree); -+ buf->extents_num++; -+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr)) -+ buf->leaf_num++; -+ return EXT_CONTINUE; -+} -+ -+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, -+ unsigned long arg) -+{ -+ int err = 0; -+ -+ if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)) -+ return -EINVAL; -+ -+ if (cmd == EXT3_IOC_GET_EXTENTS) { -+ struct ext3_extent_buf buf; -+ struct ext3_extents_tree tree; -+ -+ if (copy_from_user(&buf, (void *) arg, sizeof(buf))) -+ return -EFAULT; -+ -+ ext3_init_tree_desc(&tree, inode); -+ buf.cur = buf.buffer; -+ buf.err = 0; -+ tree.private = &buf; -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK, -+ ext3_ext_store_extent_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (err == 0) -+ err = buf.err; -+ } else if (cmd == EXT3_IOC_GET_TREE_STATS) { -+ struct ext3_extent_tree_stats buf; -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ buf.depth = EXT_DEPTH(&tree); -+ buf.extents_num = 0; -+ buf.leaf_num = 0; -+ tree.private = &buf; -+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK, -+ ext3_ext_collect_stats_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (!err) -+ err = copy_to_user((void *) arg, &buf, sizeof(buf)); -+ } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) { -+ struct ext3_extents_tree tree; -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = EXT_DEPTH(&tree); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ } -+ -+ return err; -+} -+ -+EXPORT_SYMBOL(ext3_init_tree_desc); -+EXPORT_SYMBOL(ext3_mark_inode_dirty); -+EXPORT_SYMBOL(ext3_ext_invalidate_cache); -+EXPORT_SYMBOL(ext3_ext_insert_extent); -+EXPORT_SYMBOL(ext3_ext_walk_space); -+EXPORT_SYMBOL(ext3_ext_find_goal); -+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert); -Index: linux-2.4.24/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/ialloc.c 2004-11-02 20:28:32.000000000 +0300 -+++ linux-2.4.24/fs/ext3/ialloc.c 2004-11-02 20:32:17.000000000 +0300 -@@ -553,7 +553,8 @@ repeat: - inode->i_blksize = PAGE_SIZE; - inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; -- inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; -+ inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & -+ ~(EXT3_INDEX_FL | EXT3_EXTENTS_FL); - if (S_ISLNK(mode)) - inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); - #ifdef EXT3_FRAGMENTS -@@ -592,6 +592,19 @@ - iloc.bh = NULL; - goto fail; - } -+ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) { -+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL; -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); -+ ext3_extents_initialize_blockmap(handle, inode); -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) { -+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+ if (err) goto fail; -+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ } -+ } -+ - err = ext3_mark_iloc_dirty(handle, inode, &iloc); - if (err) goto fail; - -Index: linux-2.4.24/fs/ext3/inode.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/inode.c 2004-11-02 20:28:33.000000000 +0300 -+++ linux-2.4.24/fs/ext3/inode.c 2004-11-02 20:32:17.000000000 +0300 -@@ -848,6 +848,15 @@ - goto reread; - } - -+static inline int -+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block, -+ struct buffer_head *bh, int create) -+{ -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_get_block(handle, inode, block, bh, create); -+ return ext3_get_block_handle(handle, inode, block, bh, create); -+} -+ - /* - * The BKL is not held on entry here. - */ -@@ -861,7 +870,7 @@ - handle = ext3_journal_current_handle(); - J_ASSERT(handle != 0); - } -- ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create); -+ ret = ext3_get_block_wrap(handle, inode, iblock, bh_result, create); - return ret; - } - -@@ -879,7 +888,7 @@ - dummy.b_state = 0; - dummy.b_blocknr = -1000; - buffer_trace_init(&dummy.b_history); -- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create); -+ *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create); - if (!*errp && buffer_mapped(&dummy)) { - struct buffer_head *bh; - bh = sb_getblk(inode->i_sb, dummy.b_blocknr); -@@ -1403,7 +1412,7 @@ - * This required during truncate. We need to physically zero the tail end - * of that block so it doesn't yield old data if the file is later grown. - */ --static int ext3_block_truncate_page(handle_t *handle, -+int ext3_block_truncate_page(handle_t *handle, - struct address_space *mapping, loff_t from) - { - unsigned long index = from >> PAGE_CACHE_SHIFT; -@@ -1889,6 +1898,9 @@ - - ext3_discard_prealloc(inode); - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_truncate(inode); -+ - handle = start_transaction(inode); - if (IS_ERR(handle)) - return; /* AKPM: return what? */ -@@ -2225,6 +2237,7 @@ - for (block = 0; block < EXT3_N_BLOCKS; block++) - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); - - if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) - inode->u.ext3_i.i_extra_isize = -@@ -2537,6 +2550,9 @@ - int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3; - int ret; - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_writepage_trans_blocks(inode, bpp); -+ - if (ext3_should_journal_data(inode)) - ret = 3 * (bpp + indirects) + 2; - else -@@ -2973,7 +2989,7 @@ - - /* alloc blocks one by one */ - for (i = 0; i < nblocks; i++) { -- ret = ext3_get_block_handle(handle, inode, blocks[i], -+ ret = ext3_get_block_wrap(handle, inode, blocks[i], - &bh_tmp, 1); - if (ret) - break; -@@ -3049,7 +3065,7 @@ - if (blocks[i] != 0) - continue; - -- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1); -+ rc = ext3_get_block_wrap(handle, inode, iblock, &bh, 1); - if (rc) { - printk(KERN_INFO "ext3_map_inode_page: error %d " - "allocating block %ld\n", rc, iblock); -Index: linux-2.4.24/fs/ext3/Makefile -=================================================================== ---- linux-2.4.24.orig/fs/ext3/Makefile 2004-11-02 20:28:32.000000000 +0300 -+++ linux-2.4.24/fs/ext3/Makefile 2004-11-02 20:32:17.000000000 +0300 -@@ -13,7 +13,9 @@ - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ - ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \ -- xattr_trusted.o -+ xattr_trusted.o extents.o -+export-objs += extents.o -+ - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.24/fs/ext3/super.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/super.c 2004-11-02 20:28:32.000000000 +0300 -+++ linux-2.4.24/fs/ext3/super.c 2004-11-02 20:32:17.000000000 +0300 -@@ -532,6 +532,7 @@ - #ifdef EXT3_DELETE_THREAD - J_ASSERT(sbi->s_delete_inodes == 0); - #endif -+ ext3_ext_release(sb); - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -704,6 +705,12 @@ - return 0; - } - } -+ else if (!strcmp (this_char, "extents")) -+ set_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "noextents")) -+ clear_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "extdebug")) -+ set_opt (*mount_options, EXTDEBUG); - else if (!strcmp (this_char, "grpid") || - !strcmp (this_char, "bsdgroups")) - set_opt (*mount_options, GRPID); -@@ -1395,6 +1400,8 @@ - test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": - "writeback"); - -+ ext3_ext_init(sb); -+ - return sb; - - failed_mount3: -Index: linux-2.4.24/fs/ext3/ioctl.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/ioctl.c 2004-11-02 20:28:29.000000000 +0300 -+++ linux-2.4.24/fs/ext3/ioctl.c 2004-11-02 20:32:17.000000000 +0300 -@@ -174,6 +174,10 @@ - return ret; - } - #endif -+ case EXT3_IOC_GET_EXTENTS: -+ case EXT3_IOC_GET_TREE_STATS: -+ case EXT3_IOC_GET_TREE_DEPTH: -+ return ext3_ext_ioctl(inode, filp, cmd, arg); - default: - return -ENOTTY; - } -Index: linux-2.4.24/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-11-02 20:28:32.000000000 +0300 -+++ linux-2.4.24/include/linux/ext3_fs.h 2004-11-02 20:32:17.000000000 +0300 -@@ -184,8 +184,9 @@ - #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ - #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ - #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ -+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ - --#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */ -+#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */ - #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ - - /* -@@ -208,6 +209,9 @@ - #ifdef CONFIG_JBD_DEBUG - #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long) - #endif -+#define EXT3_IOC_GET_EXTENTS _IOR('f', 7, long) -+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 8, long) -+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 9, long) - - /* - * Structure of an inode on the disk -@@ -327,6 +331,8 @@ - #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - #define EXT3_MOUNT_IOPEN 0x80000 /* Allow access via iopen */ - #define EXT3_MOUNT_IOPEN_NOPRIV 0x100000/* Make iopen world-readable */ -+#define EXT3_MOUNT_EXTENTS 0x200000/* Extents support */ -+#define EXT3_MOUNT_EXTDEBUG 0x400000/* Extents debug */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -503,10 +509,12 @@ - #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ -+#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ - - #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ -- EXT3_FEATURE_INCOMPAT_RECOVER) -+ EXT3_FEATURE_INCOMPAT_RECOVER| \ -+ EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) -@@ -688,6 +696,8 @@ - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t); -+extern int ext3_writepage_trans_blocks(struct inode *inode); - extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); -@@ -769,6 +778,16 @@ - extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - -+/* extents.c */ -+extern int ext3_ext_writepage_trans_blocks(struct inode *, int); -+extern int ext3_ext_get_block(handle_t *, struct inode *, long, -+ struct buffer_head *, int); -+extern void ext3_ext_truncate(struct inode *); -+extern void ext3_ext_init(struct super_block *); -+extern void ext3_ext_release(struct super_block *); -+extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *); -+extern int ext3_ext_ioctl(struct inode *inode, struct file *filp, -+ unsigned int cmd, unsigned long arg); - - #endif /* __KERNEL__ */ - -Index: linux-2.4.24/include/linux/ext3_extents.h -=================================================================== ---- linux-2.4.24.orig/include/linux/ext3_extents.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24/include/linux/ext3_extents.h 2004-11-02 20:32:17.000000000 +0300 -@@ -0,0 +1,261 @@ -+/* -+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+#ifndef _LINUX_EXT3_EXTENTS -+#define _LINUX_EXT3_EXTENTS -+ -+/* -+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks -+ * become very little, so index split, in-depth growing and -+ * other hard changes happens much more often -+ * this is for debug purposes only -+ */ -+#define AGRESSIVE_TEST_ -+ -+/* -+ * if CHECK_BINSEARCH defined, then results of binary search -+ * will be checked by linear search -+ */ -+#define CHECK_BINSEARCH_ -+ -+/* -+ * if EXT_DEBUG is defined you can use 'extdebug' mount option -+ * to get lots of info what's going on -+ */ -+#define EXT_DEBUG_ -+#ifdef EXT_DEBUG -+#define ext_debug(tree,fmt,a...) \ -+do { \ -+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \ -+ printk(fmt, ##a); \ -+} while (0); -+#else -+#define ext_debug(tree,fmt,a...) -+#endif -+ -+/* -+ * if EXT_STATS is defined then stats numbers are collected -+ * these number will be displayed at umount time -+ */ -+#define EXT_STATS_ -+ -+ -+#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */ -+ -+/* -+ * ext3_inode has i_block array (total 60 bytes) -+ * first 4 bytes are used to store: -+ * - tree depth (0 mean there is no tree yet. all extents in the inode) -+ * - number of alive extents in the inode -+ */ -+ -+/* -+ * this is extent on-disk structure -+ * it's used at the bottom of the tree -+ */ -+struct ext3_extent { -+ __u32 ee_block; /* first logical block extent covers */ -+ __u16 ee_len; /* number of blocks covered by extent */ -+ __u16 ee_start_hi; /* high 16 bits of physical block */ -+ __u32 ee_start; /* low 32 bigs of physical block */ -+}; -+ -+/* -+ * this is index on-disk structure -+ * it's used at all the levels, but the bottom -+ */ -+struct ext3_extent_idx { -+ __u32 ei_block; /* index covers logical blocks from 'block' */ -+ __u32 ei_leaf; /* pointer to the physical block of the next * -+ * level. leaf or next index could bet here */ -+ __u16 ei_leaf_hi; /* high 16 bits of physical block */ -+ __u16 ei_unused; -+}; -+ -+/* -+ * each block (leaves and indexes), even inode-stored has header -+ */ -+struct ext3_extent_header { -+ __u16 eh_magic; /* probably will support different formats */ -+ __u16 eh_entries; /* number of valid entries */ -+ __u16 eh_max; /* capacity of store in entries */ -+ __u16 eh_depth; /* has tree real underlaying blocks? */ -+ __u32 eh_generation; /* flags(8 bits) | generation of the tree */ -+}; -+ -+#define EXT3_EXT_MAGIC 0xf30a -+ -+/* -+ * array of ext3_ext_path contains path to some extent -+ * creation/lookup routines use it for traversal/splitting/etc -+ * truncate uses it to simulate recursive walking -+ */ -+struct ext3_ext_path { -+ __u32 p_block; -+ __u16 p_depth; -+ struct ext3_extent *p_ext; -+ struct ext3_extent_idx *p_idx; -+ struct ext3_extent_header *p_hdr; -+ struct buffer_head *p_bh; -+}; -+ -+/* -+ * structure for external API -+ */ -+ -+/* -+ * storage for cached extent -+ */ -+struct ext3_ext_cache { -+ __u32 ec_start; -+ __u32 ec_block; -+ __u32 ec_len; -+ __u32 ec_type; -+}; -+ -+#define EXT3_EXT_CACHE_NO 0 -+#define EXT3_EXT_CACHE_GAP 1 -+#define EXT3_EXT_CACHE_EXTENT 2 -+ -+/* -+ * ext3_extents_tree is used to pass initial information -+ * to top-level extents API -+ */ -+struct ext3_extents_helpers; -+struct ext3_extents_tree { -+ struct inode *inode; /* inode which tree belongs to */ -+ void *root; /* ptr to data top of tree resides at */ -+ void *buffer; /* will be passed as arg to ^^ routines */ -+ int buffer_len; -+ void *private; -+ struct ext3_ext_cache *cex;/* last found extent */ -+ struct ext3_extents_helpers *ops; -+}; -+ -+struct ext3_extents_helpers { -+ int (*get_write_access)(handle_t *h, void *buffer); -+ int (*mark_buffer_dirty)(handle_t *h, void *buffer); -+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2); -+ int (*remove_extent_credits)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*remove_extent)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*new_block)(handle_t *, struct ext3_extents_tree *, -+ struct ext3_ext_path *, struct ext3_extent *, -+ int *); -+}; -+ -+/* -+ * to be called by ext3_ext_walk_space() -+ * negative retcode - error -+ * positive retcode - signal for ext3_ext_walk_space(), see below -+ * callback must return valid extent (passed or newly created) -+ */ -+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *, -+ struct ext3_ext_path *, -+ struct ext3_ext_cache *); -+ -+#define EXT_CONTINUE 0 -+#define EXT_BREAK 1 -+#define EXT_REPEAT 2 -+ -+ -+#define EXT_MAX_BLOCK 0xffffffff -+ -+ -+#define EXT_FIRST_EXTENT(__hdr__) \ -+ ((struct ext3_extent *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_FIRST_INDEX(__hdr__) \ -+ ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_HAS_FREE_INDEX(__path__) \ -+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) -+#define EXT_LAST_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_LAST_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_MAX_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_MAX_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_HDR_GEN(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff) -+#define EXT_FLAGS(__hdr__) ((__hdr__)->eh_generation >> 24) -+#define EXT_FLAGS_CLR_UNKNOWN 0x7 /* Flags cleared on modification */ -+ -+#define EXT_BLOCK_HDR(__bh__) ((struct ext3_extent_header *)(__bh__)->b_data) -+#define EXT_ROOT_HDR(__tree__) ((struct ext3_extent_header *)(__tree__)->root) -+#define EXT_DEPTH(__tree__) (EXT_ROOT_HDR(__tree__)->eh_depth) -+#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__)) -+ -+#define EXT_ASSERT(__x__) if (!(__x__)) BUG(); -+ -+#define EXT_CHECK_PATH(tree,path) \ -+{ \ -+ int depth = EXT_DEPTH(tree); \ -+ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_idx < \ -+ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_ext < \ -+ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \ -+ && depth != 0); \ -+ BUG_ON((path)[0].p_depth != depth); \ -+} -+ -+ -+/* -+ * this structure is used to gather extents from the tree via ioctl -+ */ -+struct ext3_extent_buf { -+ unsigned long start; -+ int buflen; -+ void *buffer; -+ void *cur; -+ int err; -+}; -+ -+/* -+ * this structure is used to collect stats info about the tree -+ */ -+struct ext3_extent_tree_stats { -+ int depth; -+ int extents_num; -+ int leaf_num; -+}; -+ -+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *); -+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *); -+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *); -+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *); -+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback); -+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long); -+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *); -+ -+static inline void -+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree) -+{ -+ if (tree->cex) -+ tree->cex->ec_type = EXT3_EXT_CACHE_NO; -+} -+ -+ -+#endif /* _LINUX_EXT3_EXTENTS */ -Index: linux-2.4.24/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.24.orig/include/linux/ext3_fs_i.h 2004-11-02 20:28:32.000000000 +0300 -+++ linux-2.4.24/include/linux/ext3_fs_i.h 2004-11-02 20:43:45.000000000 +0300 -@@ -76,6 +76,8 @@ - * by other means, so we have truncate_sem. - */ - struct rw_semaphore truncate_sem; -+ -+ __u32 i_cached_extent[4]; - }; - - #endif /* _LINUX_EXT3_FS_I */ diff --git a/lustre/kernel_patches/patches/ext3-extents-2.4.29.patch b/lustre/kernel_patches/patches/ext3-extents-2.4.29.patch deleted file mode 100644 index f3b1fb5..0000000 --- a/lustre/kernel_patches/patches/ext3-extents-2.4.29.patch +++ /dev/null @@ -1,2858 +0,0 @@ -Index: linux-2.4.29/fs/ext3/extents.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/extents.c 2005-05-03 16:52:08.723069952 +0300 -+++ linux-2.4.29/fs/ext3/extents.c 2005-05-03 16:52:08.802057944 +0300 -@@ -0,0 +1,2308 @@ -+/* -+ * Copyright(c) 2003, 2004, 2005, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+/* -+ * Extents support for EXT3 -+ * -+ * TODO: -+ * - ext3_ext_walk_space() sould not use ext3_ext_find_extent() -+ * - ext3_ext_calc_credits() could take 'mergable' into account -+ * - ext3*_error() should be used in some situations -+ * - find_goal() [to be tested and improved] -+ * - smart tree reduction -+ * - arch-independence -+ * common on-disk format for big/little-endian arch -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+static inline int ext3_ext_check_header(struct ext3_extent_header *eh) -+{ -+ if (eh->eh_magic != EXT3_EXT_MAGIC) { -+ printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n", -+ (unsigned)eh->eh_magic); -+ return -EIO; -+ } -+ if (eh->eh_max == 0) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n", -+ (unsigned)eh->eh_max); -+ return -EIO; -+ } -+ if (eh->eh_entries > eh->eh_max) { -+ printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n", -+ (unsigned)eh->eh_entries); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed) -+{ -+ int err; -+ -+ if (handle->h_buffer_credits > needed) -+ return handle; -+ if (!ext3_journal_extend(handle, needed)) -+ return handle; -+ err = ext3_journal_restart(handle, needed); -+ -+ return handle; -+} -+ -+static int inline -+ext3_ext_get_access_for_root(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->get_write_access) -+ return tree->ops->get_write_access(h,tree->buffer); -+ else -+ return 0; -+} -+ -+static int inline -+ext3_ext_mark_root_dirty(handle_t *h, struct ext3_extents_tree *tree) -+{ -+ if (tree->ops->mark_buffer_dirty) -+ return tree->ops->mark_buffer_dirty(h,tree->buffer); -+ else -+ return 0; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ */ -+static int ext3_ext_get_access(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ -+ if (path->p_bh) { -+ /* path points to block */ -+ err = ext3_journal_get_write_access(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_get_access_for_root(handle, tree); -+ } -+ return err; -+} -+ -+/* -+ * could return: -+ * - EROFS -+ * - ENOMEM -+ * - EIO -+ */ -+static int ext3_ext_dirty(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int err; -+ if (path->p_bh) { -+ /* path points to block */ -+ err =ext3_journal_dirty_metadata(handle, path->p_bh); -+ } else { -+ /* path points to leaf/index in inode body */ -+ err = ext3_ext_mark_root_dirty(handle, tree); -+ } -+ return err; -+} -+ -+static int inline -+ext3_ext_new_block(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, struct ext3_extent *ex, -+ int *err) -+{ -+ int goal, depth, newblock; -+ struct inode *inode; -+ -+ EXT_ASSERT(tree); -+ if (tree->ops->new_block) -+ return tree->ops->new_block(handle, tree, path, ex, err); -+ -+ inode = tree->inode; -+ depth = EXT_DEPTH(tree); -+ if (path && depth > 0) { -+ goal = path[depth-1].p_block; -+ } else { -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ -+ bg_start = (ei->i_block_group * -+ EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ goal = bg_start + colour; -+ } -+ -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, err); -+ unlock_kernel(); -+ return newblock; -+} -+ -+static inline void ext3_ext_tree_changed(struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *neh = EXT_ROOT_HDR(tree); -+ neh->eh_generation = ((EXT_FLAGS(neh) & ~EXT_FLAGS_CLR_UNKNOWN) << 24) | -+ (EXT_HDR_GEN(neh) + 1); -+} -+ -+static inline int ext3_ext_space_block(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 6; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_block_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->inode->i_sb->s_blocksize - -+ sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 5; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent); -+#ifdef AGRESSIVE_TEST -+ size = 3; -+#endif -+ return size; -+} -+ -+static inline int ext3_ext_space_root_idx(struct ext3_extents_tree *tree) -+{ -+ int size; -+ -+ size = (tree->buffer_len - sizeof(struct ext3_extent_header)) / -+ sizeof(struct ext3_extent_idx); -+#ifdef AGRESSIVE_TEST -+ size = 4; -+#endif -+ return size; -+} -+ -+static void ext3_ext_show_path(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int k, l = path->p_depth; -+ -+ ext_debug(tree, "path:"); -+ for (k = 0; k <= l; k++, path++) { -+ if (path->p_idx) { -+ ext_debug(tree, " %d->%d", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ } else if (path->p_ext) { -+ ext_debug(tree, " %d:%d:%d", -+ path->p_ext->ee_block, -+ path->p_ext->ee_len, -+ path->p_ext->ee_start); -+ } else -+ ext_debug(tree, " []"); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_show_leaf(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+#ifdef EXT_DEBUG -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *eh; -+ struct ext3_extent *ex; -+ int i; -+ -+ if (!path) -+ return; -+ -+ eh = path[depth].p_hdr; -+ ex = EXT_FIRST_EXTENT(eh); -+ -+ for (i = 0; i < eh->eh_entries; i++, ex++) { -+ ext_debug(tree, "%d:%d:%d ", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ } -+ ext_debug(tree, "\n"); -+#endif -+} -+ -+static void ext3_ext_drop_refs(struct ext3_ext_path *path) -+{ -+ int depth = path->p_depth; -+ int i; -+ -+ for (i = 0; i <= depth; i++, path++) { -+ if (path->p_bh) { -+ brelse(path->p_bh); -+ path->p_bh = NULL; -+ } -+ } -+} -+ -+/* -+ * binary search for closest index by given block -+ */ -+static inline void -+ext3_ext_binsearch_idx(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent_idx *ix; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_entries > 0); -+ -+ ext_debug(tree, "binsearch for %d(idx): ", block); -+ -+ path->p_idx = ix = EXT_FIRST_INDEX(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ix[l + k].ei_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ix += l; -+ path->p_idx = ix; -+ ext_debug(tree," -> %d->%d ",path->p_idx->ei_block,path->p_idx->ei_leaf); -+ -+ while (l++ < r) { -+ if (block < ix->ei_block) -+ break; -+ path->p_idx = ix++; -+ } -+ ext_debug(tree, " -> %d->%d\n", path->p_idx->ei_block, -+ path->p_idx->ei_leaf); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent_idx *chix; -+ -+ chix = ix = EXT_FIRST_INDEX(eh); -+ for (k = 0; k < eh->eh_entries; k++, ix++) { -+ if (k != 0 && ix->ei_block <= ix[-1].ei_block) { -+ printk("k=%d, ix=0x%p, first=0x%p\n", k, -+ ix, EXT_FIRST_INDEX(eh)); -+ printk("%u <= %u\n", -+ ix->ei_block,ix[-1].ei_block); -+ } -+ EXT_ASSERT(k == 0 || ix->ei_block > ix[-1].ei_block); -+ if (block < ix->ei_block) -+ break; -+ chix = ix; -+ } -+ EXT_ASSERT(chix == path->p_idx); -+ } -+#endif -+} -+ -+/* -+ * binary search for closest extent by given block -+ */ -+static inline void -+ext3_ext_binsearch(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, int block) -+{ -+ struct ext3_extent_header *eh = path->p_hdr; -+ struct ext3_extent *ex; -+ int l = 0, k, r; -+ -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ -+ if (eh->eh_entries == 0) { -+ /* -+ * this leaf is empty yet: -+ * we get such a leaf in split/add case -+ */ -+ return; -+ } -+ -+ ext_debug(tree, "binsearch for %d: ", block); -+ -+ path->p_ext = ex = EXT_FIRST_EXTENT(eh); -+ -+ r = k = eh->eh_entries; -+ while (k > 1) { -+ k = (r - l) / 2; -+ if (block < ex[l + k].ee_block) -+ r -= k; -+ else -+ l += k; -+ ext_debug(tree, "%d:%d:%d ", k, l, r); -+ } -+ -+ ex += l; -+ path->p_ext = ex; -+ ext_debug(tree, " -> %d:%d:%d ", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+ while (l++ < r) { -+ if (block < ex->ee_block) -+ break; -+ path->p_ext = ex++; -+ } -+ ext_debug(tree, " -> %d:%d:%d\n", path->p_ext->ee_block, -+ path->p_ext->ee_start, path->p_ext->ee_len); -+ -+#ifdef CHECK_BINSEARCH -+ { -+ struct ext3_extent *chex; -+ -+ chex = ex = EXT_FIRST_EXTENT(eh); -+ for (k = 0; k < eh->eh_entries; k++, ex++) { -+ EXT_ASSERT(k == 0 || ex->ee_block > ex[-1].ee_block); -+ if (block < ex->ee_block) -+ break; -+ chex = ex; -+ } -+ EXT_ASSERT(chex == path->p_ext); -+ } -+#endif -+} -+ -+int ext3_extent_tree_init(handle_t *handle, struct ext3_extents_tree *tree) -+{ -+ struct ext3_extent_header *eh; -+ -+ BUG_ON(tree->buffer_len == 0); -+ ext3_ext_get_access_for_root(handle, tree); -+ eh = EXT_ROOT_HDR(tree); -+ eh->eh_depth = 0; -+ eh->eh_entries = 0; -+ eh->eh_magic = EXT3_EXT_MAGIC; -+ eh->eh_max = ext3_ext_space_root(tree); -+ ext3_ext_mark_root_dirty(handle, tree); -+ ext3_ext_invalidate_cache(tree); -+ return 0; -+} -+ -+struct ext3_ext_path * -+ext3_ext_find_extent(struct ext3_extents_tree *tree, int block, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ struct buffer_head *bh; -+ int depth, i, ppos = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ eh = EXT_ROOT_HDR(tree); -+ EXT_ASSERT(eh); -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ i = depth = EXT_DEPTH(tree); -+ EXT_ASSERT(eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* account possible depth increase */ -+ if (!path) { -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2), -+ GFP_NOFS); -+ if (!path) -+ return ERR_PTR(-ENOMEM); -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[0].p_hdr = eh; -+ -+ /* walk through the tree */ -+ while (i) { -+ ext_debug(tree, "depth %d: num %d, max %d\n", -+ ppos, eh->eh_entries, eh->eh_max); -+ ext3_ext_binsearch_idx(tree, path + ppos, block); -+ path[ppos].p_block = path[ppos].p_idx->ei_leaf; -+ path[ppos].p_depth = i; -+ path[ppos].p_ext = NULL; -+ -+ bh = sb_bread(tree->inode->i_sb, path[ppos].p_block); -+ if (!bh) -+ goto err; -+ eh = EXT_BLOCK_HDR(bh); -+ ppos++; -+ EXT_ASSERT(ppos <= depth); -+ path[ppos].p_bh = bh; -+ path[ppos].p_hdr = eh; -+ i--; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ } -+ -+ path[ppos].p_depth = i; -+ path[ppos].p_hdr = eh; -+ path[ppos].p_ext = NULL; -+ path[ppos].p_idx = NULL; -+ -+ if (ext3_ext_check_header(eh)) -+ goto err; -+ -+ /* find extent */ -+ ext3_ext_binsearch(tree, path + ppos, block); -+ -+ ext3_ext_show_path(tree, path); -+ -+ return path; -+ -+err: -+ printk(KERN_ERR "EXT3-fs: header is corrupted!\n"); -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ return ERR_PTR(-EIO); -+} -+ -+/* -+ * insert new index [logical;ptr] into the block at cupr -+ * it check where to insert: before curp or after curp -+ */ -+static int ext3_ext_insert_index(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *curp, -+ int logical, int ptr) -+{ -+ struct ext3_extent_idx *ix; -+ int len, err; -+ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ return err; -+ -+ EXT_ASSERT(logical != curp->p_idx->ei_block); -+ len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx; -+ if (logical > curp->p_idx->ei_block) { -+ /* insert after */ -+ if (curp->p_idx != EXT_LAST_INDEX(curp->p_hdr)) { -+ len = (len - 1) * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d after: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ (curp->p_idx + 1), (curp->p_idx + 2)); -+ memmove(curp->p_idx + 2, curp->p_idx + 1, len); -+ } -+ ix = curp->p_idx + 1; -+ } else { -+ /* insert before */ -+ len = len * sizeof(struct ext3_extent_idx); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert new index %d before: %d. " -+ "move %d from 0x%p to 0x%p\n", -+ logical, ptr, len, -+ curp->p_idx, (curp->p_idx + 1)); -+ memmove(curp->p_idx + 1, curp->p_idx, len); -+ ix = curp->p_idx; -+ } -+ -+ ix->ei_block = logical; -+ ix->ei_leaf = ptr; -+ curp->p_hdr->eh_entries++; -+ -+ EXT_ASSERT(curp->p_hdr->eh_entries <= curp->p_hdr->eh_max); -+ EXT_ASSERT(ix <= EXT_LAST_INDEX(curp->p_hdr)); -+ -+ err = ext3_ext_dirty(handle, tree, curp); -+ ext3_std_error(tree->inode->i_sb, err); -+ -+ return err; -+} -+ -+/* -+ * routine inserts new subtree into the path, using free index entry -+ * at depth 'at: -+ * - allocates all needed blocks (new leaf and all intermediate index blocks) -+ * - makes decision where to split -+ * - moves remaining extens and index entries (right to the split point) -+ * into the newly allocated blocks -+ * - initialize subtree -+ */ -+static int ext3_ext_split(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext, int at) -+{ -+ struct buffer_head *bh = NULL; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct ext3_extent *ex; -+ int i = at, k, m, a; -+ unsigned long newblock, oldblock, border; -+ int *ablocks = NULL; /* array of allocated blocks */ -+ int err = 0; -+ -+ /* make decision: where to split? */ -+ /* FIXME: now desicion is simplest: at current extent */ -+ -+ /* if current leaf will be splitted, then we should use -+ * border from split point */ -+ EXT_ASSERT(path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr)); -+ if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ border = path[depth].p_ext[1].ee_block; -+ ext_debug(tree, "leaf will be splitted." -+ " next leaf starts at %d\n", -+ (int)border); -+ } else { -+ border = newext->ee_block; -+ ext_debug(tree, "leaf will be added." -+ " next leaf starts at %d\n", -+ (int)border); -+ } -+ -+ /* -+ * if error occurs, then we break processing -+ * and turn filesystem read-only. so, index won't -+ * be inserted and tree will be in consistent -+ * state. next mount will repair buffers too -+ */ -+ -+ /* -+ * get array to track all allocated blocks -+ * we need this to handle errors and free blocks -+ * upon them -+ */ -+ ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS); -+ if (!ablocks) -+ return -ENOMEM; -+ memset(ablocks, 0, sizeof(unsigned long) * depth); -+ -+ /* allocate all needed blocks */ -+ ext_debug(tree, "allocate %d blocks for indexes/leaf\n", depth - at); -+ for (a = 0; a < depth - at; a++) { -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ goto cleanup; -+ ablocks[a] = newblock; -+ } -+ -+ /* initialize new leaf */ -+ newblock = ablocks[--a]; -+ EXT_ASSERT(newblock); -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 0; -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_depth = 0; -+ ex = EXT_FIRST_EXTENT(neh); -+ -+ /* move remain of path[depth] to the new leaf */ -+ EXT_ASSERT(path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max); -+ /* start copy from next extent */ -+ /* TODO: we could do it by single memmove */ -+ m = 0; -+ path[depth].p_ext++; -+ while (path[depth].p_ext <= -+ EXT_MAX_EXTENT(path[depth].p_hdr)) { -+ ext_debug(tree, "move %d:%d:%d in new leaf %lu\n", -+ path[depth].p_ext->ee_block, -+ path[depth].p_ext->ee_start, -+ path[depth].p_ext->ee_len, -+ newblock); -+ memmove(ex++, path[depth].p_ext++, sizeof(struct ext3_extent)); -+ neh->eh_entries++; -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old leaf */ -+ if (m) { -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ path[depth].p_hdr->eh_entries -= m; -+ if ((err = ext3_ext_dirty(handle, tree, path + depth))) -+ goto cleanup; -+ -+ } -+ -+ /* create intermediate indexes */ -+ k = depth - at - 1; -+ EXT_ASSERT(k >= 0); -+ if (k) -+ ext_debug(tree, "create %d intermediate indices\n", k); -+ /* insert new index into current index block */ -+ /* current depth stored in i var */ -+ i = depth - 1; -+ while (k--) { -+ oldblock = newblock; -+ newblock = ablocks[--a]; -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) -+ goto cleanup; -+ -+ neh = EXT_BLOCK_HDR(bh); -+ neh->eh_entries = 1; -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ neh->eh_depth = depth - i; -+ fidx = EXT_FIRST_INDEX(neh); -+ fidx->ei_block = border; -+ fidx->ei_leaf = oldblock; -+ -+ ext_debug(tree, "int.index at %d (block %lu): %lu -> %lu\n", -+ i, newblock, border, oldblock); -+ /* copy indexes */ -+ m = 0; -+ path[i].p_idx++; -+ -+ ext_debug(tree, "cur 0x%p, last 0x%p\n", path[i].p_idx, -+ EXT_MAX_INDEX(path[i].p_hdr)); -+ EXT_ASSERT(EXT_MAX_INDEX(path[i].p_hdr) == -+ EXT_LAST_INDEX(path[i].p_hdr)); -+ while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { -+ ext_debug(tree, "%d: move %d:%d in new index %lu\n", -+ i, path[i].p_idx->ei_block, -+ path[i].p_idx->ei_leaf, newblock); -+ memmove(++fidx, path[i].p_idx++, -+ sizeof(struct ext3_extent_idx)); -+ neh->eh_entries++; -+ EXT_ASSERT(neh->eh_entries <= neh->eh_max); -+ m++; -+ } -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto cleanup; -+ brelse(bh); -+ bh = NULL; -+ -+ /* correct old index */ -+ if (m) { -+ err = ext3_ext_get_access(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ path[i].p_hdr->eh_entries -= m; -+ err = ext3_ext_dirty(handle, tree, path + i); -+ if (err) -+ goto cleanup; -+ } -+ -+ i--; -+ } -+ -+ /* insert new index */ -+ if (!err) -+ err = ext3_ext_insert_index(handle, tree, path + at, -+ border, newblock); -+ -+cleanup: -+ if (bh) { -+ if (buffer_locked(bh)) -+ unlock_buffer(bh); -+ brelse(bh); -+ } -+ -+ if (err) { -+ /* free all allocated blocks in error case */ -+ for (i = 0; i < depth; i++) { -+ if (!ablocks[i]) -+ continue; -+ ext3_free_blocks(handle, tree->inode, ablocks[i], 1); -+ } -+ } -+ kfree(ablocks); -+ -+ return err; -+} -+ -+/* -+ * routine implements tree growing procedure: -+ * - allocates new block -+ * - moves top-level data (index block or leaf) into the new block -+ * - initialize new top-level, creating index that points to the -+ * just created block -+ */ -+static int ext3_ext_grow_indepth(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp = path; -+ struct ext3_extent_header *neh; -+ struct ext3_extent_idx *fidx; -+ struct buffer_head *bh; -+ unsigned long newblock; -+ int err = 0; -+ -+ newblock = ext3_ext_new_block(handle, tree, path, newext, &err); -+ if (newblock == 0) -+ return err; -+ -+ bh = sb_getblk(tree->inode->i_sb, newblock); -+ if (!bh) { -+ err = -EIO; -+ ext3_std_error(tree->inode->i_sb, err); -+ return err; -+ } -+ lock_buffer(bh); -+ -+ if ((err = ext3_journal_get_create_access(handle, bh))) { -+ unlock_buffer(bh); -+ goto out; -+ } -+ -+ /* move top-level index/leaf into new block */ -+ memmove(bh->b_data, curp->p_hdr, tree->buffer_len); -+ -+ /* set size of new block */ -+ neh = EXT_BLOCK_HDR(bh); -+ /* old root could have indexes or leaves -+ * so calculate eh_max right way */ -+ if (EXT_DEPTH(tree)) -+ neh->eh_max = ext3_ext_space_block_idx(tree); -+ else -+ neh->eh_max = ext3_ext_space_block(tree); -+ neh->eh_magic = EXT3_EXT_MAGIC; -+ mark_buffer_uptodate(bh, 1); -+ unlock_buffer(bh); -+ -+ if ((err = ext3_journal_dirty_metadata(handle, bh))) -+ goto out; -+ -+ /* create index in new top-level index: num,max,pointer */ -+ if ((err = ext3_ext_get_access(handle, tree, curp))) -+ goto out; -+ -+ curp->p_hdr->eh_magic = EXT3_EXT_MAGIC; -+ curp->p_hdr->eh_max = ext3_ext_space_root_idx(tree); -+ curp->p_hdr->eh_entries = 1; -+ curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); -+ /* FIXME: it works, but actually path[0] can be index */ -+ curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; -+ curp->p_idx->ei_leaf = newblock; -+ -+ neh = EXT_ROOT_HDR(tree); -+ fidx = EXT_FIRST_INDEX(neh); -+ ext_debug(tree, "new root: num %d(%d), lblock %d, ptr %d\n", -+ neh->eh_entries, neh->eh_max, fidx->ei_block, fidx->ei_leaf); -+ -+ neh->eh_depth = path->p_depth + 1; -+ err = ext3_ext_dirty(handle, tree, curp); -+out: -+ brelse(bh); -+ -+ return err; -+} -+ -+/* -+ * routine finds empty index and adds new leaf. if no free index found -+ * then it requests in-depth growing -+ */ -+static int ext3_ext_create_new_leaf(handle_t *handle, -+ struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_ext_path *curp; -+ int depth, i, err = 0; -+ -+repeat: -+ i = depth = EXT_DEPTH(tree); -+ -+ /* walk up to the tree and look for free index entry */ -+ curp = path + depth; -+ while (i > 0 && !EXT_HAS_FREE_INDEX(curp)) { -+ i--; -+ curp--; -+ } -+ -+ /* we use already allocated block for index block -+ * so, subsequent data blocks should be contigoues */ -+ if (EXT_HAS_FREE_INDEX(curp)) { -+ /* if we found index with free entry, then use that -+ * entry: create all needed subtree and add new leaf */ -+ err = ext3_ext_split(handle, tree, path, newext, i); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ } else { -+ /* tree is full, time to grow in depth */ -+ err = ext3_ext_grow_indepth(handle, tree, path, newext); -+ -+ /* refill path */ -+ ext3_ext_drop_refs(path); -+ path = ext3_ext_find_extent(tree, newext->ee_block, path); -+ if (IS_ERR(path)) -+ err = PTR_ERR(path); -+ -+ /* -+ * only first (depth 0 -> 1) produces free space -+ * in all other cases we have to split growed tree -+ */ -+ depth = EXT_DEPTH(tree); -+ if (path[depth].p_hdr->eh_entries == path[depth].p_hdr->eh_max) { -+ /* now we need split */ -+ goto repeat; -+ } -+ } -+ -+ if (err) -+ return err; -+ -+ return 0; -+} -+ -+/* -+ * returns allocated block in subsequent extent or EXT_MAX_BLOCK -+ * NOTE: it consider block number from index entry as -+ * allocated block. thus, index entries have to be consistent -+ * with leafs -+ */ -+static unsigned long -+ext3_ext_next_allocated_block(struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ if (depth == 0 && path->p_ext == NULL) -+ return EXT_MAX_BLOCK; -+ -+ /* FIXME: what if index isn't full ?! */ -+ while (depth >= 0) { -+ if (depth == path->p_depth) { -+ /* leaf */ -+ if (path[depth].p_ext != -+ EXT_LAST_EXTENT(path[depth].p_hdr)) -+ return path[depth].p_ext[1].ee_block; -+ } else { -+ /* index */ -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ } -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * returns first allocated block from next leaf or EXT_MAX_BLOCK -+ */ -+static unsigned ext3_ext_next_leaf_block(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth; -+ -+ EXT_ASSERT(path != NULL); -+ depth = path->p_depth; -+ -+ /* zero-tree has no leaf blocks at all */ -+ if (depth == 0) -+ return EXT_MAX_BLOCK; -+ -+ /* go to index block */ -+ depth--; -+ -+ while (depth >= 0) { -+ if (path[depth].p_idx != -+ EXT_LAST_INDEX(path[depth].p_hdr)) -+ return path[depth].p_idx[1].ei_block; -+ depth--; -+ } -+ -+ return EXT_MAX_BLOCK; -+} -+ -+/* -+ * if leaf gets modified and modified extent is first in the leaf -+ * then we have to correct all indexes above -+ * TODO: do we need to correct tree in all cases? -+ */ -+int ext3_ext_correct_indexes(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct ext3_extent_header *eh; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_extent *ex; -+ unsigned long border; -+ int k, err = 0; -+ -+ eh = path[depth].p_hdr; -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(eh); -+ -+ if (depth == 0) { -+ /* there is no tree at all */ -+ return 0; -+ } -+ -+ if (ex != EXT_FIRST_EXTENT(eh)) { -+ /* we correct tree if first leaf got modified only */ -+ return 0; -+ } -+ -+ /* -+ * TODO: we need correction if border is smaller then current one -+ */ -+ k = depth - 1; -+ border = path[depth].p_ext->ee_block; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ return err; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ return err; -+ -+ while (k--) { -+ /* change all left-side indexes */ -+ if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr)) -+ break; -+ if ((err = ext3_ext_get_access(handle, tree, path + k))) -+ break; -+ path[k].p_idx->ei_block = border; -+ if ((err = ext3_ext_dirty(handle, tree, path + k))) -+ break; -+ } -+ -+ return err; -+} -+ -+static int inline -+ext3_can_extents_be_merged(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ if (ex1->ee_block + ex1->ee_len != ex2->ee_block) -+ return 0; -+ -+#ifdef AGRESSIVE_TEST -+ if (ex1->ee_len >= 4) -+ return 0; -+#endif -+ -+ if (!tree->ops->mergable) -+ return 1; -+ -+ return tree->ops->mergable(ex1, ex2); -+} -+ -+/* -+ * this routine tries to merge requsted extent into the existing -+ * extent or inserts requested extent as new one into the tree, -+ * creating new leaf in no-space case -+ */ -+int ext3_ext_insert_extent(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *newext) -+{ -+ struct ext3_extent_header * eh; -+ struct ext3_extent *ex, *fex; -+ struct ext3_extent *nearex; /* nearest extent */ -+ struct ext3_ext_path *npath = NULL; -+ int depth, len, err, next; -+ -+ EXT_ASSERT(newext->ee_len > 0); -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(path[depth].p_hdr); -+ -+ /* try to insert block into found extent and return */ -+ if (ex && ext3_can_extents_be_merged(tree, ex, newext)) { -+ ext_debug(tree, "append %d block to %d:%d (from %d)\n", -+ newext->ee_len, ex->ee_block, ex->ee_len, -+ ex->ee_start); -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ return err; -+ ex->ee_len += newext->ee_len; -+ eh = path[depth].p_hdr; -+ nearex = ex; -+ goto merge; -+ } -+ -+repeat: -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) -+ goto has_space; -+ -+ /* probably next leaf has space for us? */ -+ fex = EXT_LAST_EXTENT(eh); -+ next = ext3_ext_next_leaf_block(tree, path); -+ if (newext->ee_block > fex->ee_block && next != EXT_MAX_BLOCK) { -+ ext_debug(tree, "next leaf block - %d\n", next); -+ EXT_ASSERT(!npath); -+ npath = ext3_ext_find_extent(tree, next, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ EXT_ASSERT(npath->p_depth == path->p_depth); -+ eh = npath[depth].p_hdr; -+ if (eh->eh_entries < eh->eh_max) { -+ ext_debug(tree, "next leaf isnt full(%d)\n", -+ eh->eh_entries); -+ path = npath; -+ goto repeat; -+ } -+ ext_debug(tree, "next leaf hasno free space(%d,%d)\n", -+ eh->eh_entries, eh->eh_max); -+ } -+ -+ /* -+ * there is no free space in found leaf -+ * we're gonna add new leaf in the tree -+ */ -+ err = ext3_ext_create_new_leaf(handle, tree, path, newext); -+ if (err) -+ goto cleanup; -+ depth = EXT_DEPTH(tree); -+ eh = path[depth].p_hdr; -+ -+has_space: -+ nearex = path[depth].p_ext; -+ -+ if ((err = ext3_ext_get_access(handle, tree, path + depth))) -+ goto cleanup; -+ -+ if (!nearex) { -+ /* there is no extent in this leaf, create first one */ -+ ext_debug(tree, "first extent in the leaf: %d:%d:%d\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len); -+ path[depth].p_ext = EXT_FIRST_EXTENT(eh); -+ } else if (newext->ee_block > nearex->ee_block) { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ if (nearex != EXT_LAST_EXTENT(eh)) { -+ len = EXT_MAX_EXTENT(eh) - nearex; -+ len = (len - 1) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d after: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, -+ newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 2, nearex + 1, len); -+ } -+ path[depth].p_ext = nearex + 1; -+ } else { -+ EXT_ASSERT(newext->ee_block != nearex->ee_block); -+ len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext3_extent); -+ len = len < 0 ? 0 : len; -+ ext_debug(tree, "insert %d:%d:%d before: nearest 0x%p, " -+ "move %d from 0x%p to 0x%p\n", -+ newext->ee_block, newext->ee_start, newext->ee_len, -+ nearex, len, nearex + 1, nearex + 2); -+ memmove(nearex + 1, nearex, len); -+ path[depth].p_ext = nearex; -+ } -+ -+ eh->eh_entries++; -+ nearex = path[depth].p_ext; -+ nearex->ee_block = newext->ee_block; -+ nearex->ee_start = newext->ee_start; -+ nearex->ee_len = newext->ee_len; -+ /* FIXME: support for large fs */ -+ nearex->ee_start_hi = 0; -+ -+merge: -+ /* try to merge extents to the right */ -+ while (nearex < EXT_LAST_EXTENT(eh)) { -+ if (!ext3_can_extents_be_merged(tree, nearex, nearex + 1)) -+ break; -+ /* merge with next extent! */ -+ nearex->ee_len += nearex[1].ee_len; -+ if (nearex + 1 < EXT_LAST_EXTENT(eh)) { -+ len = (EXT_LAST_EXTENT(eh) - nearex - 1) * -+ sizeof(struct ext3_extent); -+ memmove(nearex + 1, nearex + 2, len); -+ } -+ eh->eh_entries--; -+ EXT_ASSERT(eh->eh_entries > 0); -+ } -+ -+ /* try to merge extents to the left */ -+ -+ /* time to correct all indexes above */ -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ if (err) -+ goto cleanup; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ -+cleanup: -+ if (npath) { -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ } -+ ext3_ext_tree_changed(tree); -+ ext3_ext_invalidate_cache(tree); -+ return err; -+} -+ -+int ext3_ext_walk_space(struct ext3_extents_tree *tree, unsigned long block, -+ unsigned long num, ext_prepare_callback func) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_ext_cache cbex; -+ struct ext3_extent *ex; -+ unsigned long next, start = 0, end = 0; -+ unsigned long last = block + num; -+ int depth, exists, err = 0; -+ -+ EXT_ASSERT(tree); -+ EXT_ASSERT(func); -+ EXT_ASSERT(tree->inode); -+ EXT_ASSERT(tree->root); -+ -+ while (block < last && block != EXT_MAX_BLOCK) { -+ num = last - block; -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(tree, block, path); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ break; -+ } -+ -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(path[depth].p_hdr); -+ ex = path[depth].p_ext; -+ next = ext3_ext_next_allocated_block(path); -+ -+ exists = 0; -+ if (!ex) { -+ /* there is no extent yet, so try to allocate -+ * all requested space */ -+ start = block; -+ end = block + num; -+ } else if (ex->ee_block > block) { -+ /* need to allocate space before found extent */ -+ start = block; -+ end = ex->ee_block; -+ if (block + num < end) -+ end = block + num; -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ /* need to allocate space after found extent */ -+ start = block; -+ end = block + num; -+ if (end >= next) -+ end = next; -+ } else if (block >= ex->ee_block) { -+ /* -+ * some part of requested space is covered -+ * by found extent -+ */ -+ start = block; -+ end = ex->ee_block + ex->ee_len; -+ if (block + num < end) -+ end = block + num; -+ exists = 1; -+ } else { -+ BUG(); -+ } -+ EXT_ASSERT(end > start); -+ -+ if (!exists) { -+ cbex.ec_block = start; -+ cbex.ec_len = end - start; -+ cbex.ec_start = 0; -+ cbex.ec_type = EXT3_EXT_CACHE_GAP; -+ } else { -+ cbex.ec_block = ex->ee_block; -+ cbex.ec_len = ex->ee_len; -+ cbex.ec_start = ex->ee_start; -+ cbex.ec_type = EXT3_EXT_CACHE_EXTENT; -+ } -+ -+ EXT_ASSERT(cbex.ec_len > 0); -+ EXT_ASSERT(path[depth].p_hdr); -+ err = func(tree, path, &cbex); -+ ext3_ext_drop_refs(path); -+ -+ if (err < 0) -+ break; -+ if (err == EXT_REPEAT) -+ continue; -+ else if (err == EXT_BREAK) { -+ err = 0; -+ break; -+ } -+ -+ if (EXT_DEPTH(tree) != depth) { -+ /* depth was changed. we have to realloc path */ -+ kfree(path); -+ path = NULL; -+ } -+ -+ block = cbex.ec_block + cbex.ec_len; -+ } -+ -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ -+ return err; -+} -+ -+static inline void -+ext3_ext_put_in_cache(struct ext3_extents_tree *tree, __u32 block, -+ __u32 len, __u32 start, int type) -+{ -+ EXT_ASSERT(len > 0); -+ if (tree->cex) { -+ tree->cex->ec_type = type; -+ tree->cex->ec_block = block; -+ tree->cex->ec_len = len; -+ tree->cex->ec_start = start; -+ } -+} -+ -+/* -+ * this routine calculate boundaries of the gap requested block fits into -+ * and cache this gap -+ */ -+static inline void -+ext3_ext_put_gap_in_cache(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ int depth = EXT_DEPTH(tree); -+ unsigned long lblock, len; -+ struct ext3_extent *ex; -+ -+ if (!tree->cex) -+ return; -+ -+ ex = path[depth].p_ext; -+ if (ex == NULL) { -+ /* there is no extent yet, so gap is [0;-] */ -+ lblock = 0; -+ len = EXT_MAX_BLOCK; -+ ext_debug(tree, "cache gap(whole file):"); -+ } else if (block < ex->ee_block) { -+ lblock = block; -+ len = ex->ee_block - block; -+ ext_debug(tree, "cache gap(before): %lu [%lu:%lu]", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len); -+ } else if (block >= ex->ee_block + ex->ee_len) { -+ lblock = ex->ee_block + ex->ee_len; -+ len = ext3_ext_next_allocated_block(path); -+ ext_debug(tree, "cache gap(after): [%lu:%lu] %lu", -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) block); -+ EXT_ASSERT(len > lblock); -+ len = len - lblock; -+ } else { -+ lblock = len = 0; -+ BUG(); -+ } -+ -+ ext_debug(tree, " -> %lu:%lu\n", (unsigned long) lblock, len); -+ ext3_ext_put_in_cache(tree, lblock, len, 0, EXT3_EXT_CACHE_GAP); -+} -+ -+static inline int -+ext3_ext_in_cache(struct ext3_extents_tree *tree, unsigned long block, -+ struct ext3_extent *ex) -+{ -+ struct ext3_ext_cache *cex = tree->cex; -+ -+ /* is there cache storage at all? */ -+ if (!cex) -+ return EXT3_EXT_CACHE_NO; -+ -+ /* has cache valid data? */ -+ if (cex->ec_type == EXT3_EXT_CACHE_NO) -+ return EXT3_EXT_CACHE_NO; -+ -+ EXT_ASSERT(cex->ec_type == EXT3_EXT_CACHE_GAP || -+ cex->ec_type == EXT3_EXT_CACHE_EXTENT); -+ if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { -+ ex->ee_block = cex->ec_block; -+ ex->ee_start = cex->ec_start; -+ ex->ee_len = cex->ec_len; -+ ext_debug(tree, "%lu cached by %lu:%lu:%lu\n", -+ (unsigned long) block, -+ (unsigned long) ex->ee_block, -+ (unsigned long) ex->ee_len, -+ (unsigned long) ex->ee_start); -+ return cex->ec_type; -+ } -+ -+ /* not in cache */ -+ return EXT3_EXT_CACHE_NO; -+} -+ -+/* -+ * routine removes index from the index block -+ * it's used in truncate case only. thus all requests are for -+ * last index in the block only -+ */ -+int ext3_ext_rm_idx(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ struct buffer_head *bh; -+ int err; -+ -+ /* free index block */ -+ path--; -+ EXT_ASSERT(path->p_hdr->eh_entries); -+ if ((err = ext3_ext_get_access(handle, tree, path))) -+ return err; -+ path->p_hdr->eh_entries--; -+ if ((err = ext3_ext_dirty(handle, tree, path))) -+ return err; -+ ext_debug(tree, "index is empty, remove it, free block %d\n", -+ path->p_idx->ei_leaf); -+ bh = sb_get_hash_table(tree->inode->i_sb, path->p_idx->ei_leaf); -+ ext3_forget(handle, 1, tree->inode, bh, path->p_idx->ei_leaf); -+ ext3_free_blocks(handle, tree->inode, path->p_idx->ei_leaf, 1); -+ return err; -+} -+ -+int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path) -+{ -+ int depth = EXT_DEPTH(tree); -+ int needed; -+ -+ if (path) { -+ /* probably there is space in leaf? */ -+ if (path[depth].p_hdr->eh_entries < path[depth].p_hdr->eh_max) -+ return 1; -+ } -+ -+ /* -+ * the worste case we're expecting is creation of the -+ * new root (growing in depth) with index splitting -+ * for splitting we have to consider depth + 1 because -+ * previous growing could increase it -+ */ -+ depth = depth + 1; -+ -+ /* -+ * growing in depth: -+ * block allocation + new root + old root -+ */ -+ needed = EXT3_ALLOC_NEEDED + 2; -+ -+ /* index split. we may need: -+ * allocate intermediate indexes and new leaf -+ * change two blocks at each level, but root -+ * modify root block (inode) -+ */ -+ needed += (depth * EXT3_ALLOC_NEEDED) + (2 * depth) + 1; -+ -+ return needed; -+} -+ -+static int -+ext3_ext_split_for_rm(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, tex; -+ struct ext3_ext_path *npath; -+ int depth, creds, err; -+ -+ depth = EXT_DEPTH(tree); -+ ex = path[depth].p_ext; -+ EXT_ASSERT(ex); -+ EXT_ASSERT(end < ex->ee_block + ex->ee_len - 1); -+ EXT_ASSERT(ex->ee_block < start); -+ -+ /* calculate tail extent */ -+ tex.ee_block = end + 1; -+ EXT_ASSERT(tex.ee_block < ex->ee_block + ex->ee_len); -+ tex.ee_len = ex->ee_block + ex->ee_len - tex.ee_block; -+ -+ creds = ext3_ext_calc_credits_for_insert(tree, path); -+ handle = ext3_ext_journal_restart(handle, creds); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ /* calculate head extent. use primary extent */ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ return err; -+ ex->ee_len = start - ex->ee_block; -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ return err; -+ -+ /* FIXME: some callback to free underlying resource -+ * and correct ee_start? */ -+ ext_debug(tree, "split extent: head %u:%u, tail %u:%u\n", -+ ex->ee_block, ex->ee_len, tex.ee_block, tex.ee_len); -+ -+ npath = ext3_ext_find_extent(tree, ex->ee_block, NULL); -+ if (IS_ERR(npath)) -+ return PTR_ERR(npath); -+ depth = EXT_DEPTH(tree); -+ EXT_ASSERT(npath[depth].p_ext->ee_block == ex->ee_block); -+ EXT_ASSERT(npath[depth].p_ext->ee_len == ex->ee_len); -+ -+ err = ext3_ext_insert_extent(handle, tree, npath, &tex); -+ ext3_ext_drop_refs(npath); -+ kfree(npath); -+ -+ return err; -+} -+ -+static int -+ext3_ext_rm_leaf(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, unsigned long start, -+ unsigned long end) -+{ -+ struct ext3_extent *ex, *fu = NULL, *lu, *le; -+ int err = 0, correct_index = 0; -+ int depth = EXT_DEPTH(tree), credits; -+ struct ext3_extent_header *eh; -+ unsigned a, b, block, num; -+ -+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end); -+ if (!path[depth].p_hdr) -+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh); -+ eh = path[depth].p_hdr; -+ EXT_ASSERT(eh); -+ EXT_ASSERT(eh->eh_entries <= eh->eh_max); -+ EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC); -+ -+ /* find where to start removing */ -+ le = ex = EXT_LAST_EXTENT(eh); -+ while (ex != EXT_FIRST_EXTENT(eh)) { -+ if (ex->ee_block <= end) -+ break; -+ ex--; -+ } -+ -+ if (start > ex->ee_block && end < ex->ee_block + ex->ee_len - 1) { -+ /* removal of internal part of the extent requested -+ * tail and head must be placed in different extent -+ * so, we have to insert one more extent */ -+ path[depth].p_ext = ex; -+ return ext3_ext_split_for_rm(handle, tree, path, start, end); -+ } -+ -+ lu = ex; -+ while (ex >= EXT_FIRST_EXTENT(eh) && ex->ee_block + ex->ee_len > start) { -+ ext_debug(tree, "remove ext %u:%u\n", ex->ee_block, ex->ee_len); -+ path[depth].p_ext = ex; -+ -+ a = ex->ee_block > start ? ex->ee_block : start; -+ b = ex->ee_block + ex->ee_len - 1 < end ? -+ ex->ee_block + ex->ee_len - 1 : end; -+ -+ ext_debug(tree, " border %u:%u\n", a, b); -+ -+ if (a != ex->ee_block && b != ex->ee_block + ex->ee_len - 1) { -+ block = 0; -+ num = 0; -+ BUG(); -+ } else if (a != ex->ee_block) { -+ /* remove tail of the extent */ -+ block = ex->ee_block; -+ num = a - block; -+ } else if (b != ex->ee_block + ex->ee_len - 1) { -+ /* remove head of the extent */ -+ block = a; -+ num = b - a; -+ } else { -+ /* remove whole extent: excelent! */ -+ block = ex->ee_block; -+ num = 0; -+ EXT_ASSERT(a == ex->ee_block && -+ b == ex->ee_block + ex->ee_len - 1); -+ } -+ -+ if (ex == EXT_FIRST_EXTENT(eh)) -+ correct_index = 1; -+ -+ credits = 1; -+ if (correct_index) -+ credits += (EXT_DEPTH(tree) * EXT3_ALLOC_NEEDED) + 1; -+ if (tree->ops->remove_extent_credits) -+ credits+=tree->ops->remove_extent_credits(tree,ex,a,b); -+ -+ handle = ext3_ext_journal_restart(handle, credits); -+ if (IS_ERR(handle)) { -+ err = PTR_ERR(handle); -+ goto out; -+ } -+ -+ err = ext3_ext_get_access(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ if (tree->ops->remove_extent) -+ err = tree->ops->remove_extent(tree, ex, a, b); -+ if (err) -+ goto out; -+ -+ if (num == 0) { -+ /* this extent is removed entirely mark slot unused */ -+ ex->ee_start = 0; -+ eh->eh_entries--; -+ fu = ex; -+ } -+ -+ ex->ee_block = block; -+ ex->ee_len = num; -+ -+ err = ext3_ext_dirty(handle, tree, path + depth); -+ if (err) -+ goto out; -+ -+ ext_debug(tree, "new extent: %u:%u:%u\n", -+ ex->ee_block, ex->ee_len, ex->ee_start); -+ ex--; -+ } -+ -+ if (fu) { -+ /* reuse unused slots */ -+ while (lu < le) { -+ if (lu->ee_start) { -+ *fu = *lu; -+ lu->ee_start = 0; -+ fu++; -+ } -+ lu++; -+ } -+ } -+ -+ if (correct_index && eh->eh_entries) -+ err = ext3_ext_correct_indexes(handle, tree, path); -+ -+ /* if this leaf is free, then we should -+ * remove it from index block above */ -+ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) -+ err = ext3_ext_rm_idx(handle, tree, path + depth); -+ -+out: -+ return err; -+} -+ -+ -+static struct ext3_extent_idx * -+ext3_ext_last_covered(struct ext3_extent_header *hdr, unsigned long block) -+{ -+ struct ext3_extent_idx *ix; -+ -+ ix = EXT_LAST_INDEX(hdr); -+ while (ix != EXT_FIRST_INDEX(hdr)) { -+ if (ix->ei_block <= block) -+ break; -+ ix--; -+ } -+ return ix; -+} -+ -+/* -+ * returns 1 if current index have to be freed (even partial) -+ */ -+static int inline -+ext3_ext_more_to_rm(struct ext3_ext_path *path) -+{ -+ EXT_ASSERT(path->p_idx); -+ -+ if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr)) -+ return 0; -+ -+ /* -+ * if truncate on deeper level happened it it wasn't partial -+ * so we have to consider current index for truncation -+ */ -+ if (path->p_hdr->eh_entries == path->p_block) -+ return 0; -+ return 1; -+} -+ -+int ext3_ext_remove_space(struct ext3_extents_tree *tree, -+ unsigned long start, unsigned long end) -+{ -+ struct inode *inode = tree->inode; -+ struct super_block *sb = inode->i_sb; -+ int depth = EXT_DEPTH(tree); -+ struct ext3_ext_path *path; -+ handle_t *handle; -+ int i = 0, err = 0; -+ -+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end); -+ -+ /* probably first extent we're gonna free will be last in block */ -+ handle = ext3_journal_start(inode, depth + 1); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ ext3_ext_invalidate_cache(tree); -+ -+ /* -+ * we start scanning from right side freeing all the blocks -+ * after i_size and walking into the deep -+ */ -+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 1), GFP_KERNEL); -+ if (IS_ERR(path)) { -+ ext3_error(sb, __FUNCTION__, "Can't allocate path array"); -+ ext3_journal_stop(handle, inode); -+ return -ENOMEM; -+ } -+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1)); -+ path[i].p_hdr = EXT_ROOT_HDR(tree); -+ -+ while (i >= 0 && err == 0) { -+ if (i == depth) { -+ /* this is leaf block */ -+ err = ext3_ext_rm_leaf(handle, tree, path, start, end); -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ continue; -+ } -+ -+ /* this is index block */ -+ if (!path[i].p_hdr) { -+ ext_debug(tree, "initialize header\n"); -+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh); -+ } -+ -+ EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max); -+ EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC); -+ -+ if (!path[i].p_idx) { -+ /* this level hasn't touched yet */ -+ path[i].p_idx = -+ ext3_ext_last_covered(path[i].p_hdr, end); -+ path[i].p_block = path[i].p_hdr->eh_entries + 1; -+ ext_debug(tree, "init index ptr: hdr 0x%p, num %d\n", -+ path[i].p_hdr, path[i].p_hdr->eh_entries); -+ } else { -+ /* we've already was here, see at next index */ -+ path[i].p_idx--; -+ } -+ -+ ext_debug(tree, "level %d - index, first 0x%p, cur 0x%p\n", -+ i, EXT_FIRST_INDEX(path[i].p_hdr), -+ path[i].p_idx); -+ if (ext3_ext_more_to_rm(path + i)) { -+ /* go to the next level */ -+ ext_debug(tree, "move to level %d (block %d)\n", -+ i + 1, path[i].p_idx->ei_leaf); -+ memset(path + i + 1, 0, sizeof(*path)); -+ path[i+1].p_bh = sb_bread(sb, path[i].p_idx->ei_leaf); -+ if (!path[i+1].p_bh) { -+ /* should we reset i_size? */ -+ err = -EIO; -+ break; -+ } -+ /* put actual number of indexes to know is this -+ * number got changed at the next iteration */ -+ path[i].p_block = path[i].p_hdr->eh_entries; -+ i++; -+ } else { -+ /* we finish processing this index, go up */ -+ if (path[i].p_hdr->eh_entries == 0 && i > 0) { -+ /* index is empty, remove it -+ * handle must be already prepared by the -+ * truncatei_leaf() */ -+ err = ext3_ext_rm_idx(handle, tree, path + i); -+ } -+ /* root level have p_bh == NULL, brelse() eats this */ -+ brelse(path[i].p_bh); -+ i--; -+ ext_debug(tree, "return to level %d\n", i); -+ } -+ } -+ -+ /* TODO: flexible tree reduction should be here */ -+ if (path->p_hdr->eh_entries == 0) { -+ /* -+ * truncate to zero freed all the tree -+ * so, we need to correct eh_depth -+ */ -+ err = ext3_ext_get_access(handle, tree, path); -+ if (err == 0) { -+ EXT_ROOT_HDR(tree)->eh_depth = 0; -+ EXT_ROOT_HDR(tree)->eh_max = ext3_ext_space_root(tree); -+ err = ext3_ext_dirty(handle, tree, path); -+ } -+ } -+ ext3_ext_tree_changed(tree); -+ -+ kfree(path); -+ ext3_journal_stop(handle, inode); -+ -+ return err; -+} -+ -+/* -+ * called at mount time -+ */ -+void ext3_ext_init(struct super_block *sb) -+{ -+ /* -+ * possible initialization would be here -+ */ -+ -+ if (test_opt(sb, EXTENTS)) { -+ printk("EXT3-fs: file extents enabled"); -+#ifdef AGRESSIVE_TEST -+ printk(", agressive tests"); -+#endif -+#ifdef CHECK_BINSEARCH -+ printk(", check binsearch"); -+#endif -+ printk("\n"); -+ } -+} -+ -+/* -+ * called at umount time -+ */ -+void ext3_ext_release(struct super_block *sb) -+{ -+} -+ -+/************************************************************************ -+ * VFS related routines -+ ************************************************************************/ -+ -+static int ext3_get_inode_write_access(handle_t *handle, void *buffer) -+{ -+ /* we use in-core data, not bh */ -+ return 0; -+} -+ -+static int ext3_mark_buffer_dirty(handle_t *handle, void *buffer) -+{ -+ struct inode *inode = buffer; -+ return ext3_mark_inode_dirty(handle, inode); -+} -+ -+static int ext3_ext_mergable(struct ext3_extent *ex1, -+ struct ext3_extent *ex2) -+{ -+ /* FIXME: support for large fs */ -+ if (ex1->ee_start + ex1->ee_len == ex2->ee_start) -+ return 1; -+ return 0; -+} -+ -+static int -+ext3_remove_blocks_credits(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed; -+ -+ /* at present, extent can't cross block group */; -+ needed = 4; /* bitmap + group desc + sb + inode */ -+ -+#ifdef CONFIG_QUOTA -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ return needed; -+} -+ -+static int -+ext3_remove_blocks(struct ext3_extents_tree *tree, -+ struct ext3_extent *ex, -+ unsigned long from, unsigned long to) -+{ -+ int needed = ext3_remove_blocks_credits(tree, ex, from, to); -+ handle_t *handle = ext3_journal_start(tree->inode, needed); -+ struct buffer_head *bh; -+ int i; -+ -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ if (from >= ex->ee_block && to == ex->ee_block + ex->ee_len - 1) { -+ /* tail removal */ -+ unsigned long num, start; -+ num = ex->ee_block + ex->ee_len - from; -+ start = ex->ee_start + ex->ee_len - num; -+ ext_debug(tree, "free last %lu blocks starting %lu\n", -+ num, start); -+ for (i = 0; i < num; i++) { -+ bh = sb_get_hash_table(tree->inode->i_sb, start + i); -+ ext3_forget(handle, 0, tree->inode, bh, start + i); -+ } -+ ext3_free_blocks(handle, tree->inode, start, num); -+ } else if (from == ex->ee_block && to <= ex->ee_block + ex->ee_len - 1) { -+ printk("strange request: removal %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } else { -+ printk("strange request: removal(2) %lu-%lu from %u:%u\n", -+ from, to, ex->ee_block, ex->ee_len); -+ } -+ ext3_journal_stop(handle, tree->inode); -+ return 0; -+} -+ -+int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path, -+ unsigned long block) -+{ -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ unsigned long bg_start; -+ unsigned long colour; -+ int depth; -+ -+ if (path) { -+ struct ext3_extent *ex; -+ depth = path->p_depth; -+ -+ /* try to predict block placement */ -+ if ((ex = path[depth].p_ext)) -+ return ex->ee_start + (block - ex->ee_block); -+ -+ /* it looks index is empty -+ * try to find starting from index itself */ -+ if (path[depth].p_bh) -+ return path[depth].p_bh->b_blocknr; -+ } -+ -+ /* OK. use inode's group */ -+ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); -+ colour = (current->pid % 16) * -+ (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); -+ return bg_start + colour + block; -+} -+ -+static int ext3_new_block_cb(handle_t *handle, struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_extent *ex, int *err) -+{ -+ struct inode *inode = tree->inode; -+ int newblock, goal; -+ -+ EXT_ASSERT(path); -+ EXT_ASSERT(ex); -+ EXT_ASSERT(ex->ee_start); -+ EXT_ASSERT(ex->ee_len); -+ -+ /* reuse block from the extent to order data/metadata */ -+ newblock = ex->ee_start++; -+ ex->ee_len--; -+ if (ex->ee_len == 0) { -+ ex->ee_len = 1; -+ /* allocate new block for the extent */ -+ goal = ext3_ext_find_goal(inode, path, ex->ee_block); -+ lock_kernel(); -+ ex->ee_start = ext3_new_block(handle, inode, goal, 0, 0, err); -+ unlock_kernel(); -+ if (ex->ee_start == 0) { -+ /* error occured: restore old extent */ -+ ex->ee_start = newblock; -+ return 0; -+ } -+ } -+ return newblock; -+} -+ -+static struct ext3_extents_helpers ext3_blockmap_helpers = { -+ .get_write_access = ext3_get_inode_write_access, -+ .mark_buffer_dirty = ext3_mark_buffer_dirty, -+ .mergable = ext3_ext_mergable, -+ .new_block = ext3_new_block_cb, -+ .remove_extent = ext3_remove_blocks, -+ .remove_extent_credits = ext3_remove_blocks_credits, -+}; -+ -+void ext3_init_tree_desc(struct ext3_extents_tree *tree, -+ struct inode *inode) -+{ -+ tree->inode = inode; -+ tree->root = (void *) EXT3_I(inode)->i_data; -+ tree->buffer = (void *) inode; -+ tree->buffer_len = sizeof(EXT3_I(inode)->i_data); -+ tree->cex = (struct ext3_ext_cache *) &EXT3_I(inode)->i_cached_extent; -+ tree->ops = &ext3_blockmap_helpers; -+} -+ -+int ext3_ext_get_block(handle_t *handle, struct inode *inode, -+ long iblock, struct buffer_head *bh_result, int create) -+{ -+ struct ext3_ext_path *path = NULL; -+ struct ext3_extent newex; -+ struct ext3_extent *ex; -+ int goal, newblock, err = 0, depth; -+ struct ext3_extents_tree tree; -+ -+ clear_bit(BH_New, &bh_result->b_state); -+ ext3_init_tree_desc(&tree, inode); -+ ext_debug(&tree, "block %d requested for inode %u\n", -+ (int) iblock, (unsigned) inode->i_ino); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ -+ /* check in cache */ -+ if ((goal = ext3_ext_in_cache(&tree, iblock, &newex))) { -+ if (goal == EXT3_EXT_CACHE_GAP) { -+ if (!create) { -+ /* block isn't allocated yet and -+ * user don't want to allocate it */ -+ goto out2; -+ } -+ /* we should allocate requested block */ -+ } else if (goal == EXT3_EXT_CACHE_EXTENT) { -+ /* block is already allocated */ -+ newblock = iblock - newex.ee_block + newex.ee_start; -+ goto out; -+ } else { -+ EXT_ASSERT(0); -+ } -+ } -+ -+ /* find extent for this block */ -+ path = ext3_ext_find_extent(&tree, iblock, NULL); -+ if (IS_ERR(path)) { -+ err = PTR_ERR(path); -+ path = NULL; -+ goto out2; -+ } -+ -+ depth = EXT_DEPTH(&tree); -+ -+ /* -+ * consistent leaf must not be empty -+ * this situations is possible, though, _during_ tree modification -+ * this is why assert can't be put in ext3_ext_find_extent() -+ */ -+ EXT_ASSERT(path[depth].p_ext != NULL || depth == 0); -+ -+ if ((ex = path[depth].p_ext)) { -+ /* if found exent covers block, simple return it */ -+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) { -+ newblock = iblock - ex->ee_block + ex->ee_start; -+ ext_debug(&tree, "%d fit into %d:%d -> %d\n", -+ (int) iblock, ex->ee_block, ex->ee_len, -+ newblock); -+ ext3_ext_put_in_cache(&tree, ex->ee_block, -+ ex->ee_len, ex->ee_start, -+ EXT3_EXT_CACHE_EXTENT); -+ goto out; -+ } -+ } -+ -+ /* -+ * requested block isn't allocated yet -+ * we couldn't try to create block if create flag is zero -+ */ -+ if (!create) { -+ /* put just found gap into cache to speedup subsequest reqs */ -+ ext3_ext_put_gap_in_cache(&tree, path, iblock); -+ goto out2; -+ } -+ -+ /* allocate new block */ -+ goal = ext3_ext_find_goal(inode, path, iblock); -+ lock_kernel(); -+ newblock = ext3_new_block(handle, inode, goal, 0, 0, &err); -+ unlock_kernel(); -+ if (!newblock) -+ goto out2; -+ ext_debug(&tree, "allocate new block: goal %d, found %d\n", -+ goal, newblock); -+ -+ /* try to insert new extent into found leaf and return */ -+ newex.ee_block = iblock; -+ newex.ee_start = newblock; -+ newex.ee_len = 1; -+ err = ext3_ext_insert_extent(handle, &tree, path, &newex); -+ if (err) -+ goto out2; -+ -+ if (inode->i_size > EXT3_I(inode)->i_disksize) -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ -+ /* previous routine could use block we allocated */ -+ newblock = newex.ee_start; -+ set_bit(BH_New, &bh_result->b_state); -+ -+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len, -+ newex.ee_start, EXT3_EXT_CACHE_EXTENT); -+out: -+ ext3_ext_show_leaf(&tree, path); -+ set_bit(BH_Mapped, &bh_result->b_state); -+ bh_result->b_dev = inode->i_sb->s_dev; -+ bh_result->b_blocknr = newblock; -+out2: -+ if (path) { -+ ext3_ext_drop_refs(path); -+ kfree(path); -+ } -+ up_write(&EXT3_I(inode)->truncate_sem); -+ -+ return err; -+} -+ -+void ext3_ext_truncate(struct inode * inode) -+{ -+ struct address_space *mapping = inode->i_mapping; -+ struct super_block *sb = inode->i_sb; -+ struct ext3_extents_tree tree; -+ unsigned long last_block; -+ handle_t *handle; -+ int err = 0; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ /* -+ * probably first extent we're gonna free will be last in block -+ */ -+ err = ext3_writepage_trans_blocks(inode) + 3; -+ handle = ext3_journal_start(inode, err); -+ if (IS_ERR(handle)) -+ return; -+ -+ ext3_block_truncate_page(handle, mapping, inode->i_size); -+ -+ down_write(&EXT3_I(inode)->truncate_sem); -+ ext3_ext_invalidate_cache(&tree); -+ -+ /* -+ * TODO: optimization is possible here -+ * probably we need not scaning at all, -+ * because page truncation is enough -+ */ -+ if (ext3_orphan_add(handle, inode)) -+ goto out_stop; -+ -+ /* we have to know where to truncate from in crash case */ -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_mark_inode_dirty(handle, inode); -+ -+ last_block = (inode->i_size + sb->s_blocksize - 1) >> -+ EXT3_BLOCK_SIZE_BITS(sb); -+ err = ext3_ext_remove_space(&tree, last_block, EXT_MAX_BLOCK); -+ -+ /* In a multi-transaction truncate, we only make the final -+ * transaction synchronous */ -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+out_stop: -+ /* -+ * If this was a simple ftruncate(), and the file will remain alive -+ * then we need to clear up the orphan record which we created above. -+ * However, if this was a real unlink then we were called by -+ * ext3_delete_inode(), and we allow that function to clean up the -+ * orphan info for us. -+ */ -+ if (inode->i_nlink) -+ ext3_orphan_del(handle, inode); -+ -+ up_write(&EXT3_I(inode)->truncate_sem); -+ ext3_journal_stop(handle, inode); -+} -+ -+/* -+ * this routine calculate max number of blocks we could modify -+ * in order to allocate new block for an inode -+ */ -+int ext3_ext_writepage_trans_blocks(struct inode *inode, int num) -+{ -+ struct ext3_extents_tree tree; -+ int needed; -+ -+ ext3_init_tree_desc(&tree, inode); -+ -+ needed = ext3_ext_calc_credits_for_insert(&tree, NULL); -+ -+ /* caller want to allocate num blocks */ -+ needed *= num; -+ -+#ifdef CONFIG_QUOTA -+ /* -+ * FIXME: real calculation should be here -+ * it depends on blockmap format of qouta file -+ */ -+ needed += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ -+ return needed; -+} -+ -+void ext3_extents_initialize_blockmap(handle_t *handle, struct inode *inode) -+{ -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ ext3_extent_tree_init(handle, &tree); -+} -+ -+static int -+ext3_ext_store_extent_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *newex) -+{ -+ struct ext3_extent_buf *buf = (struct ext3_extent_buf *) tree->private; -+ -+ if (newex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ if (buf->err < 0) -+ return EXT_BREAK; -+ if (buf->cur - buf->buffer + sizeof(*newex) > buf->buflen) -+ return EXT_BREAK; -+ -+ if (!copy_to_user(buf->cur, newex, sizeof(*newex))) { -+ buf->err++; -+ buf->cur += sizeof(*newex); -+ } else { -+ buf->err = -EFAULT; -+ return EXT_BREAK; -+ } -+ return EXT_CONTINUE; -+} -+ -+static int -+ext3_ext_collect_stats_cb(struct ext3_extents_tree *tree, -+ struct ext3_ext_path *path, -+ struct ext3_ext_cache *ex) -+{ -+ struct ext3_extent_tree_stats *buf = -+ (struct ext3_extent_tree_stats *) tree->private; -+ int depth; -+ -+ if (ex->ec_type != EXT3_EXT_CACHE_EXTENT) -+ return EXT_CONTINUE; -+ -+ depth = EXT_DEPTH(tree); -+ buf->extents_num++; -+ if (path[depth].p_ext == EXT_FIRST_EXTENT(path[depth].p_hdr)) -+ buf->leaf_num++; -+ return EXT_CONTINUE; -+} -+ -+int ext3_ext_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, -+ unsigned long arg) -+{ -+ int err = 0; -+ -+ if (!(EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)) -+ return -EINVAL; -+ -+ if (cmd == EXT3_IOC_GET_EXTENTS) { -+ struct ext3_extent_buf buf; -+ struct ext3_extents_tree tree; -+ -+ if (copy_from_user(&buf, (void *) arg, sizeof(buf))) -+ return -EFAULT; -+ -+ ext3_init_tree_desc(&tree, inode); -+ buf.cur = buf.buffer; -+ buf.err = 0; -+ tree.private = &buf; -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = ext3_ext_walk_space(&tree, buf.start, EXT_MAX_BLOCK, -+ ext3_ext_store_extent_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (err == 0) -+ err = buf.err; -+ } else if (cmd == EXT3_IOC_GET_TREE_STATS) { -+ struct ext3_extent_tree_stats buf; -+ struct ext3_extents_tree tree; -+ -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ buf.depth = EXT_DEPTH(&tree); -+ buf.extents_num = 0; -+ buf.leaf_num = 0; -+ tree.private = &buf; -+ err = ext3_ext_walk_space(&tree, 0, EXT_MAX_BLOCK, -+ ext3_ext_collect_stats_cb); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ if (!err) -+ err = copy_to_user((void *) arg, &buf, sizeof(buf)); -+ } else if (cmd == EXT3_IOC_GET_TREE_DEPTH) { -+ struct ext3_extents_tree tree; -+ ext3_init_tree_desc(&tree, inode); -+ down_write(&EXT3_I(inode)->truncate_sem); -+ err = EXT_DEPTH(&tree); -+ up_write(&EXT3_I(inode)->truncate_sem); -+ } -+ -+ return err; -+} -+ -+EXPORT_SYMBOL(ext3_init_tree_desc); -+EXPORT_SYMBOL(ext3_mark_inode_dirty); -+EXPORT_SYMBOL(ext3_ext_invalidate_cache); -+EXPORT_SYMBOL(ext3_ext_insert_extent); -+EXPORT_SYMBOL(ext3_ext_walk_space); -+EXPORT_SYMBOL(ext3_ext_find_goal); -+EXPORT_SYMBOL(ext3_ext_calc_credits_for_insert); -Index: linux-2.4.29/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/ialloc.c 2005-05-03 16:50:30.216045296 +0300 -+++ linux-2.4.29/fs/ext3/ialloc.c 2005-05-03 16:52:08.804057640 +0300 -@@ -553,7 +553,8 @@ - inode->i_blksize = PAGE_SIZE; - inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; -- inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; -+ inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & -+ ~(EXT3_INDEX_FL | EXT3_EXTENTS_FL); - if (S_ISLNK(mode)) - inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); - #ifdef EXT3_FRAGMENTS -@@ -592,6 +593,19 @@ - iloc.bh = NULL; - goto fail; - } -+ if (test_opt(sb, EXTENTS) && S_ISREG(inode->i_mode)) { -+ EXT3_I(inode)->i_flags |= EXT3_EXTENTS_FL; -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); -+ ext3_extents_initialize_blockmap(handle, inode); -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS)) { -+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+ if (err) goto fail; -+ EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_EXTENTS); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ } -+ } -+ - err = ext3_mark_iloc_dirty(handle, inode, &iloc); - if (err) goto fail; - -Index: linux-2.4.29/fs/ext3/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/inode.c 2005-05-03 16:51:50.331865840 +0300 -+++ linux-2.4.29/fs/ext3/inode.c 2005-05-03 16:52:08.808057032 +0300 -@@ -861,6 +861,15 @@ - goto reread; - } - -+static inline int -+ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block, -+ struct buffer_head *bh, int create) -+{ -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_get_block(handle, inode, block, bh, create); -+ return ext3_get_block_handle(handle, inode, block, bh, create); -+} -+ - /* - * The BKL is not held on entry here. - */ -@@ -874,7 +883,7 @@ - handle = ext3_journal_current_handle(); - J_ASSERT(handle != 0); - } -- ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create); -+ ret = ext3_get_block_wrap(handle, inode, iblock, bh_result, create); - return ret; - } - -@@ -892,7 +901,7 @@ - dummy.b_state = 0; - dummy.b_blocknr = -1000; - buffer_trace_init(&dummy.b_history); -- *errp = ext3_get_block_handle(handle, inode, block, &dummy, create); -+ *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create); - if (!*errp && buffer_mapped(&dummy)) { - struct buffer_head *bh; - bh = sb_getblk(inode->i_sb, dummy.b_blocknr); -@@ -1416,7 +1425,7 @@ - * This required during truncate. We need to physically zero the tail end - * of that block so it doesn't yield old data if the file is later grown. - */ --static int ext3_block_truncate_page(handle_t *handle, -+int ext3_block_truncate_page(handle_t *handle, - struct address_space *mapping, loff_t from) - { - unsigned long index = from >> PAGE_CACHE_SHIFT; -@@ -1904,6 +1913,9 @@ - - ext3_discard_prealloc(inode); - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_truncate(inode); -+ - handle = start_transaction(inode); - if (IS_ERR(handle)) - return; /* AKPM: return what? */ -@@ -2240,6 +2252,7 @@ - for (block = 0; block < EXT3_N_BLOCKS; block++) - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ memset(&EXT3_I(inode)->i_cached_extent, 0, sizeof(__u32) * 4); - - if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE) - inode->u.ext3_i.i_extra_isize = -@@ -2546,6 +2559,9 @@ - int indirects = (EXT3_NDIR_BLOCKS % bpp) ? 5 : 3; - int ret; - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) -+ return ext3_ext_writepage_trans_blocks(inode, bpp); -+ - if (ext3_should_journal_data(inode)) - ret = 3 * (bpp + indirects) + 2; - else -@@ -2982,7 +2998,7 @@ - - /* alloc blocks one by one */ - for (i = 0; i < nblocks; i++) { -- ret = ext3_get_block_handle(handle, inode, blocks[i], -+ ret = ext3_get_block_wrap(handle, inode, blocks[i], - &bh_tmp, 1); - if (ret) - break; -@@ -3058,7 +3074,7 @@ - if (blocks[i] != 0) - continue; - -- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1); -+ rc = ext3_get_block_wrap(handle, inode, iblock, &bh, 1); - if (rc) { - printk(KERN_INFO "ext3_map_inode_page: error %d " - "allocating block %ld\n", rc, iblock); -Index: linux-2.4.29/fs/ext3/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/ext3/Makefile 2005-05-03 16:51:32.127633304 +0300 -+++ linux-2.4.29/fs/ext3/Makefile 2005-05-03 16:53:38.634401352 +0300 -@@ -13,7 +13,9 @@ - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ - ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \ -- xattr_trusted.o -+ xattr_trusted.o extents.o -+export-objs += extents.o -+ - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.29/fs/ext3/super.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/super.c 2005-05-03 16:50:14.750396432 +0300 -+++ linux-2.4.29/fs/ext3/super.c 2005-05-03 16:52:08.813056272 +0300 -@@ -531,6 +531,7 @@ - #ifdef EXT3_DELETE_THREAD - J_ASSERT(sbi->s_delete_inodes == 0); - #endif -+ ext3_ext_release(sb); - ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { -@@ -702,6 +703,12 @@ - return 0; - } - } -+ else if (!strcmp (this_char, "extents")) -+ set_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "noextents")) -+ clear_opt (*mount_options, EXTENTS); -+ else if (!strcmp (this_char, "extdebug")) -+ set_opt (*mount_options, EXTDEBUG); - else if (!strcmp (this_char, "grpid") || - !strcmp (this_char, "bsdgroups")) - set_opt (*mount_options, GRPID); -@@ -1405,6 +1410,8 @@ - test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": - "writeback"); - -+ ext3_ext_init(sb); -+ - return sb; - - failed_mount3: -Index: linux-2.4.29/fs/ext3/ioctl.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/ioctl.c 2005-05-03 16:49:36.825161944 +0300 -+++ linux-2.4.29/fs/ext3/ioctl.c 2005-05-03 16:52:08.814056120 +0300 -@@ -174,6 +174,10 @@ - return ret; - } - #endif -+ case EXT3_IOC_GET_EXTENTS: -+ case EXT3_IOC_GET_TREE_STATS: -+ case EXT3_IOC_GET_TREE_DEPTH: -+ return ext3_ext_ioctl(inode, filp, cmd, arg); - default: - return -ENOTTY; - } -Index: linux-2.4.29/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-05-03 16:50:30.228043472 +0300 -+++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 16:52:08.817055664 +0300 -@@ -184,8 +184,9 @@ - #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ - #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ - #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ -+#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ - --#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */ -+#define EXT3_FL_USER_VISIBLE 0x00085FFF /* User visible flags */ - #define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ - - /* -@@ -208,6 +209,9 @@ - #ifdef CONFIG_JBD_DEBUG - #define EXT3_IOC_WAIT_FOR_READONLY _IOR('f', 99, long) - #endif -+#define EXT3_IOC_GET_EXTENTS _IOR('f', 7, long) -+#define EXT3_IOC_GET_TREE_DEPTH _IOR('f', 8, long) -+#define EXT3_IOC_GET_TREE_STATS _IOR('f', 9, long) - - /* - * Structure of an inode on the disk -@@ -327,6 +331,8 @@ - #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ - #define EXT3_MOUNT_IOPEN 0x80000 /* Allow access via iopen */ - #define EXT3_MOUNT_IOPEN_NOPRIV 0x100000/* Make iopen world-readable */ -+#define EXT3_MOUNT_EXTENTS 0x200000/* Extents support */ -+#define EXT3_MOUNT_EXTDEBUG 0x400000/* Extents debug */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -506,11 +512,13 @@ - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ - #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010 -+#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ - - #define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ - EXT3_FEATURE_INCOMPAT_RECOVER| \ -- EXT3_FEATURE_INCOMPAT_META_BG) -+ EXT3_FEATURE_INCOMPAT_META_BG| \ -+ EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) -@@ -702,6 +711,8 @@ - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_block_truncate_page(handle_t *, struct address_space *, loff_t); -+extern int ext3_writepage_trans_blocks(struct inode *inode); - extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); -@@ -783,6 +793,16 @@ - extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - -+/* extents.c */ -+extern int ext3_ext_writepage_trans_blocks(struct inode *, int); -+extern int ext3_ext_get_block(handle_t *, struct inode *, long, -+ struct buffer_head *, int); -+extern void ext3_ext_truncate(struct inode *); -+extern void ext3_ext_init(struct super_block *); -+extern void ext3_ext_release(struct super_block *); -+extern void ext3_extents_initialize_blockmap(handle_t *, struct inode *); -+extern int ext3_ext_ioctl(struct inode *inode, struct file *filp, -+ unsigned int cmd, unsigned long arg); - - #endif /* __KERNEL__ */ - -Index: linux-2.4.29/include/linux/ext3_extents.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_extents.h 2005-05-03 16:52:08.724069800 +0300 -+++ linux-2.4.29/include/linux/ext3_extents.h 2005-05-03 16:52:08.819055360 +0300 -@@ -0,0 +1,261 @@ -+/* -+ * Copyright (c) 2003, Cluster File Systems, Inc, info@clusterfs.com -+ * Written by Alex Tomas -+ * -+ * 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. -+ * -+ * 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 Licens -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- -+ */ -+ -+#ifndef _LINUX_EXT3_EXTENTS -+#define _LINUX_EXT3_EXTENTS -+ -+/* -+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks -+ * become very little, so index split, in-depth growing and -+ * other hard changes happens much more often -+ * this is for debug purposes only -+ */ -+#define AGRESSIVE_TEST_ -+ -+/* -+ * if CHECK_BINSEARCH defined, then results of binary search -+ * will be checked by linear search -+ */ -+#define CHECK_BINSEARCH_ -+ -+/* -+ * if EXT_DEBUG is defined you can use 'extdebug' mount option -+ * to get lots of info what's going on -+ */ -+#define EXT_DEBUG_ -+#ifdef EXT_DEBUG -+#define ext_debug(tree,fmt,a...) \ -+do { \ -+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \ -+ printk(fmt, ##a); \ -+} while (0); -+#else -+#define ext_debug(tree,fmt,a...) -+#endif -+ -+/* -+ * if EXT_STATS is defined then stats numbers are collected -+ * these number will be displayed at umount time -+ */ -+#define EXT_STATS_ -+ -+ -+#define EXT3_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */ -+ -+/* -+ * ext3_inode has i_block array (total 60 bytes) -+ * first 4 bytes are used to store: -+ * - tree depth (0 mean there is no tree yet. all extents in the inode) -+ * - number of alive extents in the inode -+ */ -+ -+/* -+ * this is extent on-disk structure -+ * it's used at the bottom of the tree -+ */ -+struct ext3_extent { -+ __u32 ee_block; /* first logical block extent covers */ -+ __u16 ee_len; /* number of blocks covered by extent */ -+ __u16 ee_start_hi; /* high 16 bits of physical block */ -+ __u32 ee_start; /* low 32 bigs of physical block */ -+}; -+ -+/* -+ * this is index on-disk structure -+ * it's used at all the levels, but the bottom -+ */ -+struct ext3_extent_idx { -+ __u32 ei_block; /* index covers logical blocks from 'block' */ -+ __u32 ei_leaf; /* pointer to the physical block of the next * -+ * level. leaf or next index could bet here */ -+ __u16 ei_leaf_hi; /* high 16 bits of physical block */ -+ __u16 ei_unused; -+}; -+ -+/* -+ * each block (leaves and indexes), even inode-stored has header -+ */ -+struct ext3_extent_header { -+ __u16 eh_magic; /* probably will support different formats */ -+ __u16 eh_entries; /* number of valid entries */ -+ __u16 eh_max; /* capacity of store in entries */ -+ __u16 eh_depth; /* has tree real underlaying blocks? */ -+ __u32 eh_generation; /* flags(8 bits) | generation of the tree */ -+}; -+ -+#define EXT3_EXT_MAGIC 0xf30a -+ -+/* -+ * array of ext3_ext_path contains path to some extent -+ * creation/lookup routines use it for traversal/splitting/etc -+ * truncate uses it to simulate recursive walking -+ */ -+struct ext3_ext_path { -+ __u32 p_block; -+ __u16 p_depth; -+ struct ext3_extent *p_ext; -+ struct ext3_extent_idx *p_idx; -+ struct ext3_extent_header *p_hdr; -+ struct buffer_head *p_bh; -+}; -+ -+/* -+ * structure for external API -+ */ -+ -+/* -+ * storage for cached extent -+ */ -+struct ext3_ext_cache { -+ __u32 ec_start; -+ __u32 ec_block; -+ __u32 ec_len; -+ __u32 ec_type; -+}; -+ -+#define EXT3_EXT_CACHE_NO 0 -+#define EXT3_EXT_CACHE_GAP 1 -+#define EXT3_EXT_CACHE_EXTENT 2 -+ -+/* -+ * ext3_extents_tree is used to pass initial information -+ * to top-level extents API -+ */ -+struct ext3_extents_helpers; -+struct ext3_extents_tree { -+ struct inode *inode; /* inode which tree belongs to */ -+ void *root; /* ptr to data top of tree resides at */ -+ void *buffer; /* will be passed as arg to ^^ routines */ -+ int buffer_len; -+ void *private; -+ struct ext3_ext_cache *cex;/* last found extent */ -+ struct ext3_extents_helpers *ops; -+}; -+ -+struct ext3_extents_helpers { -+ int (*get_write_access)(handle_t *h, void *buffer); -+ int (*mark_buffer_dirty)(handle_t *h, void *buffer); -+ int (*mergable)(struct ext3_extent *ex1, struct ext3_extent *ex2); -+ int (*remove_extent_credits)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*remove_extent)(struct ext3_extents_tree *, -+ struct ext3_extent *, unsigned long, -+ unsigned long); -+ int (*new_block)(handle_t *, struct ext3_extents_tree *, -+ struct ext3_ext_path *, struct ext3_extent *, -+ int *); -+}; -+ -+/* -+ * to be called by ext3_ext_walk_space() -+ * negative retcode - error -+ * positive retcode - signal for ext3_ext_walk_space(), see below -+ * callback must return valid extent (passed or newly created) -+ */ -+typedef int (*ext_prepare_callback)(struct ext3_extents_tree *, -+ struct ext3_ext_path *, -+ struct ext3_ext_cache *); -+ -+#define EXT_CONTINUE 0 -+#define EXT_BREAK 1 -+#define EXT_REPEAT 2 -+ -+ -+#define EXT_MAX_BLOCK 0xffffffff -+ -+ -+#define EXT_FIRST_EXTENT(__hdr__) \ -+ ((struct ext3_extent *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_FIRST_INDEX(__hdr__) \ -+ ((struct ext3_extent_idx *) (((char *) (__hdr__)) + \ -+ sizeof(struct ext3_extent_header))) -+#define EXT_HAS_FREE_INDEX(__path__) \ -+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) -+#define EXT_LAST_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_LAST_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) -+#define EXT_MAX_EXTENT(__hdr__) \ -+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_MAX_INDEX(__hdr__) \ -+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) -+#define EXT_HDR_GEN(__hdr__) ((__hdr__)->eh_generation & 0x00ffffff) -+#define EXT_FLAGS(__hdr__) ((__hdr__)->eh_generation >> 24) -+#define EXT_FLAGS_CLR_UNKNOWN 0x7 /* Flags cleared on modification */ -+ -+#define EXT_BLOCK_HDR(__bh__) ((struct ext3_extent_header *)(__bh__)->b_data) -+#define EXT_ROOT_HDR(__tree__) ((struct ext3_extent_header *)(__tree__)->root) -+#define EXT_DEPTH(__tree__) (EXT_ROOT_HDR(__tree__)->eh_depth) -+#define EXT_GENERATION(__tree__) EXT_HDR_GEN(EXT_ROOT_HDR(__tree__)) -+ -+#define EXT_ASSERT(__x__) if (!(__x__)) BUG(); -+ -+#define EXT_CHECK_PATH(tree,path) \ -+{ \ -+ int depth = EXT_DEPTH(tree); \ -+ BUG_ON((unsigned long) (path) < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_idx < \ -+ __PAGE_OFFSET && (path)[depth].p_idx != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_ext < \ -+ __PAGE_OFFSET && (path)[depth].p_ext != NULL); \ -+ BUG_ON((unsigned long) (path)[depth].p_hdr < __PAGE_OFFSET); \ -+ BUG_ON((unsigned long) (path)[depth].p_bh < __PAGE_OFFSET \ -+ && depth != 0); \ -+ BUG_ON((path)[0].p_depth != depth); \ -+} -+ -+ -+/* -+ * this structure is used to gather extents from the tree via ioctl -+ */ -+struct ext3_extent_buf { -+ unsigned long start; -+ int buflen; -+ void *buffer; -+ void *cur; -+ int err; -+}; -+ -+/* -+ * this structure is used to collect stats info about the tree -+ */ -+struct ext3_extent_tree_stats { -+ int depth; -+ int extents_num; -+ int leaf_num; -+}; -+ -+extern void ext3_init_tree_desc(struct ext3_extents_tree *, struct inode *); -+extern int ext3_extent_tree_init(handle_t *, struct ext3_extents_tree *); -+extern int ext3_ext_calc_credits_for_insert(struct ext3_extents_tree *, struct ext3_ext_path *); -+extern int ext3_ext_insert_extent(handle_t *, struct ext3_extents_tree *, struct ext3_ext_path *, struct ext3_extent *); -+extern int ext3_ext_walk_space(struct ext3_extents_tree *, unsigned long, unsigned long, ext_prepare_callback); -+extern int ext3_ext_remove_space(struct ext3_extents_tree *, unsigned long, unsigned long); -+extern struct ext3_ext_path * ext3_ext_find_extent(struct ext3_extents_tree *, int, struct ext3_ext_path *); -+ -+static inline void -+ext3_ext_invalidate_cache(struct ext3_extents_tree *tree) -+{ -+ if (tree->cex) -+ tree->cex->ec_type = EXT3_EXT_CACHE_NO; -+} -+ -+ -+#endif /* _LINUX_EXT3_EXTENTS */ -Index: linux-2.4.29/include/linux/ext3_fs_i.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs_i.h 2005-05-03 16:50:30.229043320 +0300 -+++ linux-2.4.29/include/linux/ext3_fs_i.h 2005-05-03 16:52:08.823054752 +0300 -@@ -76,6 +76,8 @@ - * by other means, so we have truncate_sem. - */ - struct rw_semaphore truncate_sem; -+ -+ __u32 i_cached_extent[4]; - }; - - #endif /* _LINUX_EXT3_FS_I */ diff --git a/lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.21-chaos.patch deleted file mode 100644 index cd37db4..0000000 --- a/lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.21-chaos.patch +++ /dev/null @@ -1,31 +0,0 @@ -Index: 57chaos/fs/ext3/inode.c -=================================================================== ---- 57chaos.orig/fs/ext3/inode.c 2004-06-21 14:15:31.000000000 -0700 -+++ 57chaos/fs/ext3/inode.c 2004-06-21 14:19:27.000000000 -0700 -@@ -2270,6 +2270,12 @@ void ext3_truncate_thread(struct inode * - - memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); - memset(oei->i_data, 0, sizeof(oei->i_data)); -+ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) { -+ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL; -+ ext3_extents_initialize_blockmap(handle, old_inode); -+ } else { -+ EXT3_I(new_inode)->i_flags &= ~EXT3_EXTENTS_FL; -+ } - - nei->i_disksize = oei->i_disksize; - nei->i_state |= EXT3_STATE_DELETE; -@@ -2522,6 +2526,13 @@ void ext3_read_inode(struct inode * inod - else - EXT3_I(inode)->i_extra_isize = 0; - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) { -+ inode->u.ext3_i.i_cached_extent[0] = 0; -+ inode->u.ext3_i.i_cached_extent[1] = 0; -+ inode->u.ext3_i.i_cached_extent[2] = 0; -+ inode->u.ext3_i.i_cached_extent[3] = 0; -+ } -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; diff --git a/lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.24.patch b/lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.24.patch deleted file mode 100644 index bc752e5..0000000 --- a/lustre/kernel_patches/patches/ext3-extents-asyncdel-2.4.24.patch +++ /dev/null @@ -1,31 +0,0 @@ -Index: linux-2.4.24/fs/ext3/inode.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/inode.c 2004-05-18 12:34:48.000000000 -0700 -+++ linux-2.4.24/fs/ext3/inode.c 2004-05-18 12:47:50.000000000 -0700 -@@ -2244,6 +2244,13 @@ - else - inode->u.ext3_i.i_extra_isize = 0; - -+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL) { -+ inode->u.ext3_i.i_cached_extent[0] = 0; -+ inode->u.ext3_i.i_cached_extent[1] = 0; -+ inode->u.ext3_i.i_cached_extent[2] = 0; -+ inode->u.ext3_i.i_cached_extent[3] = 0; -+ } -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; -@@ -2659,6 +2665,12 @@ - - memcpy(nei->i_data, oei->i_data, sizeof(nei->i_data)); - memset(oei->i_data, 0, sizeof(oei->i_data)); -+ if (EXT3_I(old_inode)->i_flags & EXT3_EXTENTS_FL) { -+ EXT3_I(new_inode)->i_flags |= EXT3_EXTENTS_FL; -+ ext3_extents_initialize_blockmap(handle, old_inode); -+ } else { -+ EXT3_I(new_inode)->i_flags &= ~EXT3_EXTENTS_FL; -+ } - - nei->i_disksize = oei->i_disksize; - nei->i_state |= EXT3_STATE_DELETE; diff --git a/lustre/kernel_patches/patches/ext3-htree-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-htree-2.4.21-chaos.patch deleted file mode 100644 index 4b445f5..0000000 --- a/lustre/kernel_patches/patches/ext3-htree-2.4.21-chaos.patch +++ /dev/null @@ -1,2593 +0,0 @@ - fs/ext3/Makefile | 2 - fs/ext3/dir.c | 302 +++++++++ - fs/ext3/file.c | 3 - fs/ext3/hash.c | 215 ++++++ - fs/ext3/namei.c | 1421 ++++++++++++++++++++++++++++++++++++++++----- - fs/ext3/super.c | 7 - include/linux/ext3_fs.h | 85 ++ - include/linux/ext3_fs_sb.h | 2 - include/linux/ext3_jbd.h | 2 - include/linux/rbtree.h | 2 - lib/rbtree.c | 42 + - 11 files changed, 1922 insertions(+), 161 deletions(-) - -Index: linux-2.4.21-chaos/fs/ext3/dir.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/dir.c 2002-05-08 01:53:46.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/dir.c 2003-12-12 16:18:17.000000000 +0300 -@@ -21,12 +21,16 @@ - #include - #include - #include -+#include -+#include - - static unsigned char ext3_filetype_table[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK - }; - - static int ext3_readdir(struct file *, void *, filldir_t); -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir); - - struct file_operations ext3_dir_operations = { - read: generic_read_dir, -@@ -35,6 +39,17 @@ - fsync: ext3_sync_file, /* BKL held */ - }; - -+ -+static unsigned char get_dtype(struct super_block *sb, int filetype) -+{ -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) || -+ (filetype >= EXT3_FT_MAX)) -+ return DT_UNKNOWN; -+ -+ return (ext3_filetype_table[filetype]); -+} -+ -+ - int ext3_check_dir_entry (const char * function, struct inode * dir, - struct ext3_dir_entry_2 * de, - struct buffer_head * bh, -@@ -79,6 +94,16 @@ - - sb = inode->i_sb; - -+ if (is_dx(inode)) { -+ err = ext3_dx_readdir(filp, dirent, filldir); -+ if (err != ERR_BAD_DX_DIR) -+ return err; -+ /* -+ * We don't set the inode dirty flag since it's not -+ * critical that it get flushed back to the disk. -+ */ -+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; -+ } - stored = 0; - bh = NULL; - offset = filp->f_pos & (sb->s_blocksize - 1); -@@ -162,18 +187,12 @@ - * during the copy operation. - */ - unsigned long version = filp->f_version; -- unsigned char d_type = DT_UNKNOWN; - -- if (EXT3_HAS_INCOMPAT_FEATURE(sb, -- EXT3_FEATURE_INCOMPAT_FILETYPE) -- && de->file_type < EXT3_FT_MAX) -- d_type = -- ext3_filetype_table[de->file_type]; - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, - le32_to_cpu(de->inode), -- d_type); -+ get_dtype(sb, de->file_type)); - if (error) - break; - if (version != filp->f_version) -@@ -188,3 +207,272 @@ - UPDATE_ATIME(inode); - return 0; - } -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * These functions convert from the major/minor hash to an f_pos -+ * value. -+ * -+ * Currently we only use major hash numer. This is unfortunate, but -+ * on 32-bit machines, the same VFS interface is used for lseek and -+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of -+ * lseek/telldir/seekdir will blow out spectacularly, and from within -+ * the ext2 low-level routine, we don't know if we're being called by -+ * a 64-bit version of the system call or the 32-bit version of the -+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir -+ * cookie. Sigh. -+ */ -+#define hash2pos(major, minor) (major >> 1) -+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) -+#define pos2min_hash(pos) (0) -+ -+/* -+ * This structure holds the nodes of the red-black tree used to store -+ * the directory entry in hash order. -+ */ -+struct fname { -+ __u32 hash; -+ __u32 minor_hash; -+ rb_node_t rb_hash; -+ struct fname *next; -+ __u32 inode; -+ __u8 name_len; -+ __u8 file_type; -+ char name[0]; -+}; -+ -+/* -+ * This functoin implements a non-recursive way of freeing all of the -+ * nodes in the red-black tree. -+ */ -+static void free_rb_tree_fname(rb_root_t *root) -+{ -+ rb_node_t *n = root->rb_node; -+ rb_node_t *parent; -+ struct fname *fname; -+ -+ while (n) { -+ /* Do the node's children first */ -+ if ((n)->rb_left) { -+ n = n->rb_left; -+ continue; -+ } -+ if (n->rb_right) { -+ n = n->rb_right; -+ continue; -+ } -+ /* -+ * The node has no children; free it, and then zero -+ * out parent's link to it. Finally go to the -+ * beginning of the loop and try to free the parent -+ * node. -+ */ -+ parent = n->rb_parent; -+ fname = rb_entry(n, struct fname, rb_hash); -+ kfree(fname); -+ if (!parent) -+ root->rb_node = 0; -+ else if (parent->rb_left == n) -+ parent->rb_left = 0; -+ else if (parent->rb_right == n) -+ parent->rb_right = 0; -+ n = parent; -+ } -+ root->rb_node = 0; -+} -+ -+ -+struct dir_private_info *create_dir_info(loff_t pos) -+{ -+ struct dir_private_info *p; -+ -+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL); -+ if (!p) -+ return NULL; -+ p->root.rb_node = 0; -+ p->curr_node = 0; -+ p->extra_fname = 0; -+ p->last_pos = 0; -+ p->curr_hash = pos2maj_hash(pos); -+ p->curr_minor_hash = pos2min_hash(pos); -+ p->next_hash = 0; -+ return p; -+} -+ -+void ext3_htree_free_dir_info(struct dir_private_info *p) -+{ -+ free_rb_tree_fname(&p->root); -+ kfree(p); -+} -+ -+/* -+ * Given a directory entry, enter it into the fname rb tree. -+ */ -+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent) -+{ -+ rb_node_t **p, *parent = NULL; -+ struct fname * fname, *new_fn; -+ struct dir_private_info *info; -+ int len; -+ -+ info = (struct dir_private_info *) dir_file->private_data; -+ p = &info->root.rb_node; -+ -+ /* Create and allocate the fname structure */ -+ len = sizeof(struct fname) + dirent->name_len + 1; -+ new_fn = kmalloc(len, GFP_KERNEL); -+ if (!new_fn) -+ return -ENOMEM; -+ memset(new_fn, 0, len); -+ new_fn->hash = hash; -+ new_fn->minor_hash = minor_hash; -+ new_fn->inode = le32_to_cpu(dirent->inode); -+ new_fn->name_len = dirent->name_len; -+ new_fn->file_type = dirent->file_type; -+ memcpy(new_fn->name, dirent->name, dirent->name_len); -+ new_fn->name[dirent->name_len] = 0; -+ -+ while (*p) { -+ parent = *p; -+ fname = rb_entry(parent, struct fname, rb_hash); -+ -+ /* -+ * If the hash and minor hash match up, then we put -+ * them on a linked list. This rarely happens... -+ */ -+ if ((new_fn->hash == fname->hash) && -+ (new_fn->minor_hash == fname->minor_hash)) { -+ new_fn->next = fname->next; -+ fname->next = new_fn; -+ return 0; -+ } -+ -+ if (new_fn->hash < fname->hash) -+ p = &(*p)->rb_left; -+ else if (new_fn->hash > fname->hash) -+ p = &(*p)->rb_right; -+ else if (new_fn->minor_hash < fname->minor_hash) -+ p = &(*p)->rb_left; -+ else /* if (new_fn->minor_hash > fname->minor_hash) */ -+ p = &(*p)->rb_right; -+ } -+ -+ rb_link_node(&new_fn->rb_hash, parent, p); -+ rb_insert_color(&new_fn->rb_hash, &info->root); -+ return 0; -+} -+ -+ -+ -+/* -+ * This is a helper function for ext3_dx_readdir. It calls filldir -+ * for all entres on the fname linked list. (Normally there is only -+ * one entry on the linked list, unless there are 62 bit hash collisions.) -+ */ -+static int call_filldir(struct file * filp, void * dirent, -+ filldir_t filldir, struct fname *fname) -+{ -+ struct dir_private_info *info = filp->private_data; -+ loff_t curr_pos; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct super_block * sb; -+ int error; -+ -+ sb = inode->i_sb; -+ -+ if (!fname) { -+ printk("call_filldir: called with null fname?!?\n"); -+ return 0; -+ } -+ curr_pos = hash2pos(fname->hash, fname->minor_hash); -+ while (fname) { -+ error = filldir(dirent, fname->name, -+ fname->name_len, curr_pos, -+ fname->inode, -+ get_dtype(sb, fname->file_type)); -+ if (error) { -+ filp->f_pos = curr_pos; -+ info->extra_fname = fname->next; -+ return error; -+ } -+ fname = fname->next; -+ } -+ return 0; -+} -+ -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir) -+{ -+ struct dir_private_info *info = filp->private_data; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct fname *fname; -+ int ret; -+ -+ if (!info) { -+ info = create_dir_info(filp->f_pos); -+ if (!info) -+ return -ENOMEM; -+ filp->private_data = info; -+ } -+ -+ /* Some one has messed with f_pos; reset the world */ -+ if (info->last_pos != filp->f_pos) { -+ free_rb_tree_fname(&info->root); -+ info->curr_node = 0; -+ info->extra_fname = 0; -+ info->curr_hash = pos2maj_hash(filp->f_pos); -+ info->curr_minor_hash = pos2min_hash(filp->f_pos); -+ } -+ -+ /* -+ * If there are any leftover names on the hash collision -+ * chain, return them first. -+ */ -+ if (info->extra_fname && -+ call_filldir(filp, dirent, filldir, info->extra_fname)) -+ goto finished; -+ -+ if (!info->curr_node) -+ info->curr_node = rb_get_first(&info->root); -+ -+ while (1) { -+ /* -+ * Fill the rbtree if we have no more entries, -+ * or the inode has changed since we last read in the -+ * cached entries. -+ */ -+ if ((!info->curr_node) || -+ (filp->f_version != inode->i_version)) { -+ info->curr_node = 0; -+ free_rb_tree_fname(&info->root); -+ filp->f_version = inode->i_version; -+ ret = ext3_htree_fill_tree(filp, info->curr_hash, -+ info->curr_minor_hash, -+ &info->next_hash); -+ if (ret < 0) -+ return ret; -+ if (ret == 0) -+ break; -+ info->curr_node = rb_get_first(&info->root); -+ } -+ -+ fname = rb_entry(info->curr_node, struct fname, rb_hash); -+ info->curr_hash = fname->hash; -+ info->curr_minor_hash = fname->minor_hash; -+ if (call_filldir(filp, dirent, filldir, fname)) -+ break; -+ -+ info->curr_node = rb_get_next(info->curr_node); -+ if (!info->curr_node) { -+ info->curr_hash = info->next_hash; -+ info->curr_minor_hash = 0; -+ } -+ } -+finished: -+ info->last_pos = filp->f_pos; -+ UPDATE_ATIME(inode); -+ return 0; -+} -+#endif -Index: linux-2.4.21-chaos/fs/ext3/file.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/file.c 2003-12-05 07:55:47.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/file.c 2003-12-12 16:18:17.000000000 +0300 -@@ -38,6 +38,9 @@ - { - if (filp->f_mode & FMODE_WRITE) - ext3_discard_prealloc (inode); -+ if (is_dx(inode) && filp->private_data) -+ ext3_htree_free_dir_info(filp->private_data); -+ - return 0; - } - -Index: linux-2.4.21-chaos/fs/ext3/hash.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/hash.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/hash.c 2003-12-12 16:18:17.000000000 +0300 -@@ -0,0 +1,215 @@ -+/* -+ * linux/fs/ext3/hash.c -+ * -+ * Copyright (C) 2002 by Theodore Ts'o -+ * -+ * This file is released under the GPL v2. -+ * -+ * This file may be redistributed under the terms of the GNU Public -+ * License. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define DELTA 0x9E3779B9 -+ -+static void TEA_transform(__u32 buf[4], __u32 const in[]) -+{ -+ __u32 sum = 0; -+ __u32 b0 = buf[0], b1 = buf[1]; -+ __u32 a = in[0], b = in[1], c = in[2], d = in[3]; -+ int n = 16; -+ -+ do { -+ sum += DELTA; -+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); -+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); -+ } while(--n); -+ -+ buf[0] += b0; -+ buf[1] += b1; -+} -+ -+/* F, G and H are basic MD4 functions: selection, majority, parity */ -+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+ -+/* -+ * The generic round function. The application is so specific that -+ * we don't bother protecting all the arguments with parens, as is generally -+ * good macro practice, in favor of extra legibility. -+ * Rotation is separate from addition to prevent recomputation -+ */ -+#define ROUND(f, a, b, c, d, x, s) \ -+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) -+#define K1 0 -+#define K2 013240474631UL -+#define K3 015666365641UL -+ -+/* -+ * Basic cut-down MD4 transform. Returns only 32 bits of result. -+ */ -+static void halfMD4Transform (__u32 buf[4], __u32 const in[]) -+{ -+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; -+ -+ /* Round 1 */ -+ ROUND(F, a, b, c, d, in[0] + K1, 3); -+ ROUND(F, d, a, b, c, in[1] + K1, 7); -+ ROUND(F, c, d, a, b, in[2] + K1, 11); -+ ROUND(F, b, c, d, a, in[3] + K1, 19); -+ ROUND(F, a, b, c, d, in[4] + K1, 3); -+ ROUND(F, d, a, b, c, in[5] + K1, 7); -+ ROUND(F, c, d, a, b, in[6] + K1, 11); -+ ROUND(F, b, c, d, a, in[7] + K1, 19); -+ -+ /* Round 2 */ -+ ROUND(G, a, b, c, d, in[1] + K2, 3); -+ ROUND(G, d, a, b, c, in[3] + K2, 5); -+ ROUND(G, c, d, a, b, in[5] + K2, 9); -+ ROUND(G, b, c, d, a, in[7] + K2, 13); -+ ROUND(G, a, b, c, d, in[0] + K2, 3); -+ ROUND(G, d, a, b, c, in[2] + K2, 5); -+ ROUND(G, c, d, a, b, in[4] + K2, 9); -+ ROUND(G, b, c, d, a, in[6] + K2, 13); -+ -+ /* Round 3 */ -+ ROUND(H, a, b, c, d, in[3] + K3, 3); -+ ROUND(H, d, a, b, c, in[7] + K3, 9); -+ ROUND(H, c, d, a, b, in[2] + K3, 11); -+ ROUND(H, b, c, d, a, in[6] + K3, 15); -+ ROUND(H, a, b, c, d, in[1] + K3, 3); -+ ROUND(H, d, a, b, c, in[5] + K3, 9); -+ ROUND(H, c, d, a, b, in[0] + K3, 11); -+ ROUND(H, b, c, d, a, in[4] + K3, 15); -+ -+ buf[0] += a; -+ buf[1] += b; -+ buf[2] += c; -+ buf[3] += d; -+} -+ -+#undef ROUND -+#undef F -+#undef G -+#undef H -+#undef K1 -+#undef K2 -+#undef K3 -+ -+/* The old legacy hash */ -+static __u32 dx_hack_hash (const char *name, int len) -+{ -+ __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; -+ while (len--) { -+ __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); -+ -+ if (hash & 0x80000000) hash -= 0x7fffffff; -+ hash1 = hash0; -+ hash0 = hash; -+ } -+ return (hash0 << 1); -+} -+ -+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) -+{ -+ __u32 pad, val; -+ int i; -+ -+ pad = (__u32)len | ((__u32)len << 8); -+ pad |= pad << 16; -+ -+ val = pad; -+ if (len > num*4) -+ len = num * 4; -+ for (i=0; i < len; i++) { -+ if ((i % 4) == 0) -+ val = pad; -+ val = msg[i] + (val << 8); -+ if ((i % 4) == 3) { -+ *buf++ = val; -+ val = pad; -+ num--; -+ } -+ } -+ if (--num >= 0) -+ *buf++ = val; -+ while (--num >= 0) -+ *buf++ = pad; -+} -+ -+/* -+ * Returns the hash of a filename. If len is 0 and name is NULL, then -+ * this function can be used to test whether or not a hash version is -+ * supported. -+ * -+ * The seed is an 4 longword (32 bits) "secret" which can be used to -+ * uniquify a hash. If the seed is all zero's, then some default seed -+ * may be used. -+ * -+ * A particular hash version specifies whether or not the seed is -+ * represented, and whether or not the returned hash is 32 bits or 64 -+ * bits. 32 bit hashes will return 0 for the minor hash. -+ */ -+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) -+{ -+ __u32 hash; -+ __u32 minor_hash = 0; -+ const char *p; -+ int i; -+ __u32 in[8], buf[4]; -+ -+ /* Initialize the default seed for the hash checksum functions */ -+ buf[0] = 0x67452301; -+ buf[1] = 0xefcdab89; -+ buf[2] = 0x98badcfe; -+ buf[3] = 0x10325476; -+ -+ /* Check to see if the seed is all zero's */ -+ if (hinfo->seed) { -+ for (i=0; i < 4; i++) { -+ if (hinfo->seed[i]) -+ break; -+ } -+ if (i < 4) -+ memcpy(buf, hinfo->seed, sizeof(buf)); -+ } -+ -+ switch (hinfo->hash_version) { -+ case DX_HASH_LEGACY: -+ hash = dx_hack_hash(name, len); -+ break; -+ case DX_HASH_HALF_MD4: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 8); -+ halfMD4Transform(buf, in); -+ len -= 32; -+ p += 32; -+ } -+ minor_hash = buf[2]; -+ hash = buf[1]; -+ break; -+ case DX_HASH_TEA: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 4); -+ TEA_transform(buf, in); -+ len -= 16; -+ p += 16; -+ } -+ hash = buf[0]; -+ minor_hash = buf[1]; -+ break; -+ default: -+ hinfo->hash = 0; -+ return -1; -+ } -+ hinfo->hash = hash & ~1; -+ hinfo->minor_hash = minor_hash; -+ return 0; -+} -Index: linux-2.4.21-chaos/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/Makefile 2003-12-12 16:17:59.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/Makefile 2003-12-12 16:18:17.000000000 +0300 -@@ -12,7 +12,7 @@ - export-objs := super.o inode.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o -+ ioctl.o namei.o super.o symlink.o hash.o - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21-chaos/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/namei.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/namei.c 2003-12-12 16:18:17.000000000 +0300 -@@ -16,6 +16,12 @@ - * David S. Miller (davem@caip.rutgers.edu), 1995 - * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 -+ * Hash Tree Directory indexing (c) -+ * Daniel Phillips, 2001 -+ * Hash Tree Directory indexing porting -+ * Christopher Li, 2002 -+ * Hash Tree Directory indexing cleanup -+ * Theodore Ts'o, 2002 - */ - - #include -@@ -40,6 +46,642 @@ - #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) - #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) - -+static struct buffer_head *ext3_append(handle_t *handle, -+ struct inode *inode, -+ u32 *block, int *err) -+{ -+ struct buffer_head *bh; -+ -+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits; -+ -+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) { -+ inode->i_size += inode->i_sb->s_blocksize; -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_journal_get_write_access(handle,bh); -+ } -+ return bh; -+} -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#ifndef swap -+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) -+#endif -+ -+typedef struct { u32 v; } le_u32; -+typedef struct { u16 v; } le_u16; -+ -+#ifdef DX_DEBUG -+#define dxtrace(command) command -+#else -+#define dxtrace(command) -+#endif -+ -+struct fake_dirent -+{ -+ /*le*/u32 inode; -+ /*le*/u16 rec_len; -+ u8 name_len; -+ u8 file_type; -+}; -+ -+struct dx_countlimit -+{ -+ le_u16 limit; -+ le_u16 count; -+}; -+ -+struct dx_entry -+{ -+ le_u32 hash; -+ le_u32 block; -+}; -+ -+/* -+ * dx_root_info is laid out so that if it should somehow get overlaid by a -+ * dirent the two low bits of the hash version will be zero. Therefore, the -+ * hash version mod 4 should never be 0. Sincerely, the paranoia department. -+ */ -+ -+struct dx_root -+{ -+ struct fake_dirent dot; -+ char dot_name[4]; -+ struct fake_dirent dotdot; -+ char dotdot_name[4]; -+ struct dx_root_info -+ { -+ le_u32 reserved_zero; -+ u8 hash_version; -+ u8 info_length; /* 8 */ -+ u8 indirect_levels; -+ u8 unused_flags; -+ } -+ info; -+ struct dx_entry entries[0]; -+}; -+ -+struct dx_node -+{ -+ struct fake_dirent fake; -+ struct dx_entry entries[0]; -+}; -+ -+ -+struct dx_frame -+{ -+ struct buffer_head *bh; -+ struct dx_entry *entries; -+ struct dx_entry *at; -+}; -+ -+struct dx_map_entry -+{ -+ u32 hash; -+ u32 offs; -+}; -+ -+#ifdef CONFIG_EXT3_INDEX -+static inline unsigned dx_get_block (struct dx_entry *entry); -+static void dx_set_block (struct dx_entry *entry, unsigned value); -+static inline unsigned dx_get_hash (struct dx_entry *entry); -+static void dx_set_hash (struct dx_entry *entry, unsigned value); -+static unsigned dx_get_count (struct dx_entry *entries); -+static unsigned dx_get_limit (struct dx_entry *entries); -+static void dx_set_count (struct dx_entry *entries, unsigned value); -+static void dx_set_limit (struct dx_entry *entries, unsigned value); -+static unsigned dx_root_limit (struct inode *dir, unsigned infosize); -+static unsigned dx_node_limit (struct inode *dir); -+static struct dx_frame *dx_probe(struct dentry *dentry, -+ struct inode *dir, -+ struct dx_hash_info *hinfo, -+ struct dx_frame *frame, -+ int *err); -+static void dx_release (struct dx_frame *frames); -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry map[]); -+static void dx_sort_map(struct dx_map_entry *map, unsigned count); -+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, -+ struct dx_map_entry *offsets, int count); -+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); -+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash); -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err); -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Future: use high four bits of block for coalesce-on-delete flags -+ * Mask them off for now. -+ */ -+ -+static inline unsigned dx_get_block (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->block.v) & 0x00ffffff; -+} -+ -+static inline void dx_set_block (struct dx_entry *entry, unsigned value) -+{ -+ entry->block.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_hash (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->hash.v); -+} -+ -+static inline void dx_set_hash (struct dx_entry *entry, unsigned value) -+{ -+ entry->hash.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_count (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v); -+} -+ -+static inline unsigned dx_get_limit (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v); -+} -+ -+static inline void dx_set_count (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value); -+} -+ -+static inline void dx_set_limit (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value); -+} -+ -+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - -+ EXT3_DIR_REC_LEN(2) - infosize; -+ return 0? 20: entry_space / sizeof(struct dx_entry); -+} -+ -+static inline unsigned dx_node_limit (struct inode *dir) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); -+ return 0? 22: entry_space / sizeof(struct dx_entry); -+} -+ -+/* -+ * Debug -+ */ -+#ifdef DX_DEBUG -+struct stats -+{ -+ unsigned names; -+ unsigned space; -+ unsigned bcount; -+}; -+ -+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de, -+ int size, int show_names) -+{ -+ unsigned names = 0, space = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ printk("names: "); -+ while ((char *) de < base + size) -+ { -+ if (de->inode) -+ { -+ if (show_names) -+ { -+ int len = de->name_len; -+ char *name = de->name; -+ while (len--) printk("%c", *name++); -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ printk(":%x.%u ", h.hash, -+ ((char *) de - base)); -+ } -+ space += EXT3_DIR_REC_LEN(de->name_len); -+ names++; -+ } -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ printk("(%i)\n", names); -+ return (struct stats) { names, space, 1 }; -+} -+ -+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, -+ struct dx_entry *entries, int levels) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count = dx_get_count (entries), names = 0, space = 0, i; -+ unsigned bcount = 0; -+ struct buffer_head *bh; -+ int err; -+ printk("%i indexed blocks...\n", count); -+ for (i = 0; i < count; i++, entries++) -+ { -+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0; -+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; -+ struct stats stats; -+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); -+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue; -+ stats = levels? -+ dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): -+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) bh->b_data, blocksize, 0); -+ names += stats.names; -+ space += stats.space; -+ bcount += stats.bcount; -+ brelse (bh); -+ } -+ if (bcount) -+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ", -+ names, space/bcount,(space/bcount)*100/blocksize); -+ return (struct stats) { names, space, bcount}; -+} -+#endif /* DX_DEBUG */ -+ -+/* -+ * Probe for a directory leaf block to search. -+ * -+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format -+ * error in the directory index, and the caller should fall back to -+ * searching the directory normally. The callers of dx_probe **MUST** -+ * check for this error code, and make sure it never gets reflected -+ * back to userspace. -+ */ -+static struct dx_frame * -+dx_probe(struct dentry *dentry, struct inode *dir, -+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) -+{ -+ unsigned count, indirect; -+ struct dx_entry *at, *entries, *p, *q, *m; -+ struct dx_root *root; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+ -+ frame->bh = NULL; -+ if (dentry) -+ dir = dentry->d_parent->d_inode; -+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) -+ goto fail; -+ root = (struct dx_root *) bh->b_data; -+ if (root->info.hash_version != DX_HASH_TEA && -+ root->info.hash_version != DX_HASH_HALF_MD4 && -+ root->info.hash_version != DX_HASH_LEGACY) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unrecognised inode hash code %d", -+ root->info.hash_version); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ hinfo->hash_version = root->info.hash_version; -+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ if (dentry) -+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); -+ hash = hinfo->hash; -+ -+ if (root->info.unused_flags & 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash flags: %#06x", -+ root->info.unused_flags); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ if ((indirect = root->info.indirect_levels) > 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash depth: %#06x", -+ root->info.indirect_levels); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ entries = (struct dx_entry *) (((char *)&root->info) + -+ root->info.info_length); -+ assert(dx_get_limit(entries) == dx_root_limit(dir, -+ root->info.info_length)); -+ dxtrace (printk("Look up %x", hash)); -+ while (1) -+ { -+ count = dx_get_count(entries); -+ assert (count && count <= dx_get_limit(entries)); -+ p = entries + 1; -+ q = entries + count - 1; -+ while (p <= q) -+ { -+ m = p + (q - p)/2; -+ dxtrace(printk(".")); -+ if (dx_get_hash(m) > hash) -+ q = m - 1; -+ else -+ p = m + 1; -+ } -+ -+ if (0) // linear search cross check -+ { -+ unsigned n = count - 1; -+ at = entries; -+ while (n--) -+ { -+ dxtrace(printk(",")); -+ if (dx_get_hash(++at) > hash) -+ { -+ at--; -+ break; -+ } -+ } -+ assert (at == p - 1); -+ } -+ -+ at = p - 1; -+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); -+ frame->bh = bh; -+ frame->entries = entries; -+ frame->at = at; -+ if (!indirect--) return frame; -+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) -+ goto fail2; -+ at = entries = ((struct dx_node *) bh->b_data)->entries; -+ assert (dx_get_limit(entries) == dx_node_limit (dir)); -+ frame++; -+ } -+fail2: -+ while (frame >= frame_in) { -+ brelse(frame->bh); -+ frame--; -+ } -+fail: -+ return NULL; -+} -+ -+static void dx_release (struct dx_frame *frames) -+{ -+ if (frames[0].bh == NULL) -+ return; -+ -+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) -+ brelse(frames[1].bh); -+ brelse(frames[0].bh); -+} -+ -+/* -+ * This function increments the frame pointer to search the next leaf -+ * block, and reads in the necessary intervening nodes if the search -+ * should be necessary. Whether or not the search is necessary is -+ * controlled by the hash parameter. If the hash value is even, then -+ * the search is only continued if the next block starts with that -+ * hash value. This is used if we are searching for a specific file. -+ * -+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block. -+ * -+ * This function returns 1 if the caller should continue to search, -+ * or 0 if it should not. If there is an error reading one of the -+ * index blocks, it will return -1. -+ * -+ * If start_hash is non-null, it will be filled in with the starting -+ * hash of the next page. -+ */ -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash) -+{ -+ struct dx_frame *p; -+ struct buffer_head *bh; -+ int num_frames = 0; -+ __u32 bhash; -+ -+ *err = ENOENT; -+ p = frame; -+ /* -+ * Find the next leaf page by incrementing the frame pointer. -+ * If we run out of entries in the interior node, loop around and -+ * increment pointer in the parent node. When we break out of -+ * this loop, num_frames indicates the number of interior -+ * nodes need to be read. -+ */ -+ while (1) { -+ if (++(p->at) < p->entries + dx_get_count(p->entries)) -+ break; -+ if (p == frames) -+ return 0; -+ num_frames++; -+ p--; -+ } -+ -+ /* -+ * If the hash is 1, then continue only if the next page has a -+ * continuation hash of any value. This is used for readdir -+ * handling. Otherwise, check to see if the hash matches the -+ * desired contiuation hash. If it doesn't, return since -+ * there's no point to read in the successive index pages. -+ */ -+ bhash = dx_get_hash(p->at); -+ if (start_hash) -+ *start_hash = bhash; -+ if ((hash & 1) == 0) { -+ if ((bhash & ~1) != hash) -+ return 0; -+ } -+ /* -+ * If the hash is HASH_NB_ALWAYS, we always go to the next -+ * block so no check is necessary -+ */ -+ while (num_frames--) { -+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), -+ 0, err))) -+ return -1; /* Failure */ -+ p++; -+ brelse (p->bh); -+ p->bh = bh; -+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; -+ } -+ return 1; -+} -+ -+ -+/* -+ * p is at least 6 bytes before the end of page -+ */ -+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) -+{ -+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); -+} -+ -+/* -+ * This function fills a red-black tree with information from a -+ * directory. We start scanning the directory in hash order, starting -+ * at start_hash and start_minor_hash. -+ * -+ * This function returns the number of entries inserted into the tree, -+ * or a negative error code. -+ */ -+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash) -+{ -+ struct dx_hash_info hinfo; -+ struct buffer_head *bh; -+ struct ext3_dir_entry_2 *de, *top; -+ static struct dx_frame frames[2], *frame; -+ struct inode *dir; -+ int block, err; -+ int count = 0; -+ int ret; -+ __u32 hashval; -+ -+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, -+ start_minor_hash)); -+ dir = dir_file->f_dentry->d_inode; -+ hinfo.hash = start_hash; -+ hinfo.minor_hash = 0; -+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ -+ /* Add '.' and '..' from the htree header */ -+ if (!start_hash && !start_minor_hash) { -+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ de = ext3_next_entry(de); -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ count += 2; -+ } -+ -+ while (1) { -+ block = dx_get_block(frame->at); -+ dxtrace(printk("Reading block %d\n", block)); -+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) -+ goto errout; -+ -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) { -+ ext3fs_dirhash(de->name, de->name_len, &hinfo); -+ if ((hinfo.hash < start_hash) || -+ ((hinfo.hash == start_hash) && -+ (hinfo.minor_hash < start_minor_hash))) -+ continue; -+ if ((err = ext3_htree_store_dirent(dir_file, -+ hinfo.hash, hinfo.minor_hash, de)) != 0) -+ goto errout; -+ count++; -+ } -+ brelse (bh); -+ hashval = ~1; -+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, -+ frame, frames, &err, &hashval); -+ if (next_hash) -+ *next_hash = hashval; -+ if (ret == -1) -+ goto errout; -+ /* -+ * Stop if: (a) there are no more entries, or -+ * (b) we have inserted at least one entry and the -+ * next hash value is not a continuation -+ */ -+ if ((ret == 0) || -+ (count && ((hashval & 1) == 0))) -+ break; -+ } -+ dx_release(frames); -+ dxtrace(printk("Fill tree: returned %d entries\n", count)); -+ return count; -+errout: -+ dx_release(frames); -+ return (err); -+} -+ -+ -+/* -+ * Directory block splitting, compacting -+ */ -+ -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) -+{ -+ int count = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ while ((char *) de < base + size) -+ { -+ if (de->name_len && de->inode) { -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ map_tail--; -+ map_tail->hash = h.hash; -+ map_tail->offs = (u32) ((char *) de - base); -+ count++; -+ } -+ /* XXX: do we need to check rec_len == 0 case? -Chris */ -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ return count; -+} -+ -+static void dx_sort_map (struct dx_map_entry *map, unsigned count) -+{ -+ struct dx_map_entry *p, *q, *top = map + count - 1; -+ int more; -+ /* Combsort until bubble sort doesn't suck */ -+ while (count > 2) -+ { -+ count = count*10/13; -+ if (count - 9 < 2) /* 9, 10 -> 11 */ -+ count = 11; -+ for (p = top, q = p - count; q >= map; p--, q--) -+ if (p->hash < q->hash) -+ swap(*p, *q); -+ } -+ /* Garden variety bubble sort */ -+ do { -+ more = 0; -+ q = top; -+ while (q-- > map) -+ { -+ if (q[1].hash >= q[0].hash) -+ continue; -+ swap(*(q+1), *q); -+ more = 1; -+ } -+ } while(more); -+} -+ -+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) -+{ -+ struct dx_entry *entries = frame->entries; -+ struct dx_entry *old = frame->at, *new = old + 1; -+ int count = dx_get_count(entries); -+ -+ assert(count < dx_get_limit(entries)); -+ assert(old < entries + count); -+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new)); -+ dx_set_hash(new, hash); -+ dx_set_block(new, block); -+ dx_set_count(entries, count + 1); -+} -+#endif -+ -+ -+static void ext3_update_dx_flag(struct inode *inode) -+{ -+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb, -+ EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL; -+} -+ - /* - * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure. - * -@@ -96,6 +738,7 @@ - return 0; - } - -+ - /* - * ext3_find_entry() - * -@@ -107,6 +750,8 @@ - * The returned buffer_head has ->b_count elevated. The caller is expected - * to brelse() it when appropriate. - */ -+ -+ - static struct buffer_head * ext3_find_entry (struct dentry *dentry, - struct ext3_dir_entry_2 ** res_dir) - { -@@ -121,12 +766,32 @@ - int num = 0; - int nblocks, i, err; - struct inode *dir = dentry->d_parent->d_inode; -+ int namelen; -+ const u8 *name; -+ unsigned blocksize; - - *res_dir = NULL; - sb = dir->i_sb; -- -+ blocksize = sb->s_blocksize; -+ namelen = dentry->d_name.len; -+ name = dentry->d_name.name; -+ if (namelen > EXT3_NAME_LEN) -+ return NULL; -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ bh = ext3_dx_find_entry(dentry, res_dir, &err); -+ /* -+ * On success, or if the error was file not found, -+ * return. Otherwise, fall back to doing a search the -+ * old fashioned way. -+ */ -+ if (bh || (err != ERR_BAD_DX_DIR)) -+ return bh; -+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n")); -+ } -+#endif - nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb); -- start = dir->u.ext3_i.i_dir_start_lookup; -+ start = EXT3_I(dir)->i_dir_start_lookup; - if (start >= nblocks) - start = 0; - block = start; -@@ -167,7 +832,7 @@ - i = search_dirblock(bh, dir, dentry, - block << EXT3_BLOCK_SIZE_BITS(sb), res_dir); - if (i == 1) { -- dir->u.ext3_i.i_dir_start_lookup = block; -+ EXT3_I(dir)->i_dir_start_lookup = block; - ret = bh; - goto cleanup_and_exit; - } else { -@@ -198,6 +863,66 @@ - return ret; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err) -+{ -+ struct super_block * sb; -+ struct dx_hash_info hinfo; -+ u32 hash; -+ struct dx_frame frames[2], *frame; -+ struct ext3_dir_entry_2 *de, *top; -+ struct buffer_head *bh; -+ unsigned long block; -+ int retval; -+ int namelen = dentry->d_name.len; -+ const u8 *name = dentry->d_name.name; -+ struct inode *dir = dentry->d_parent->d_inode; -+ -+ sb = dir->i_sb; -+ if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err))) -+ return NULL; -+ hash = hinfo.hash; -+ do { -+ block = dx_get_block(frame->at); -+ if (!(bh = ext3_bread (NULL,dir, block, 0, err))) -+ goto errout; -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) -+ if (ext3_match (namelen, name, de)) { -+ if (!ext3_check_dir_entry("ext3_find_entry", -+ dir, de, bh, -+ (block<b_data))) { -+ brelse (bh); -+ goto errout; -+ } -+ *res_dir = de; -+ dx_release (frames); -+ return bh; -+ } -+ brelse (bh); -+ /* Check to see if we should continue to search */ -+ retval = ext3_htree_next_block(dir, hash, frame, -+ frames, err, 0); -+ if (retval == -1) { -+ ext3_warning(sb, __FUNCTION__, -+ "error reading index page in directory #%lu", -+ dir->i_ino); -+ goto errout; -+ } -+ } while (retval == 1); -+ -+ *err = -ENOENT; -+errout: -+ dxtrace(printk("%s not found\n", name)); -+ dx_release (frames); -+ return NULL; -+} -+#endif -+ - static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) - { - struct inode * inode; -@@ -214,8 +939,9 @@ - brelse (bh); - inode = iget(dir->i_sb, ino); - -- if (!inode) -+ if (!inode) { - return ERR_PTR(-EACCES); -+ } - } - d_add(dentry, inode); - return NULL; -@@ -239,6 +965,301 @@ - de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct ext3_dir_entry_2 * -+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) -+{ -+ unsigned rec_len = 0; -+ -+ while (count--) { -+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ memcpy (to, de, rec_len); -+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len); -+ de->inode = 0; -+ map++; -+ to += rec_len; -+ } -+ return (struct ext3_dir_entry_2 *) (to - rec_len); -+} -+ -+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) -+{ -+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; -+ unsigned rec_len = 0; -+ -+ prev = to = de; -+ while ((char*)de < base + size) { -+ next = (struct ext3_dir_entry_2 *) ((char *) de + -+ le16_to_cpu(de->rec_len)); -+ if (de->inode && de->name_len) { -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ if (de > to) -+ memmove(to, de, rec_len); -+ to->rec_len = cpu_to_le16(rec_len); -+ prev = to; -+ to = (struct ext3_dir_entry_2 *)((char *) to + rec_len); -+ } -+ de = next; -+ } -+ return prev; -+} -+ -+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, -+ struct buffer_head **bh,struct dx_frame *frame, -+ struct dx_hash_info *hinfo, int *error) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count, continued; -+ struct buffer_head *bh2; -+ u32 newblock; -+ u32 hash2; -+ struct dx_map_entry *map; -+ char *data1 = (*bh)->b_data, *data2; -+ unsigned split; -+ struct ext3_dir_entry_2 *de = NULL, *de2; -+ int err; -+ -+ bh2 = ext3_append (handle, dir, &newblock, error); -+ if (!(bh2)) { -+ brelse(*bh); -+ *bh = NULL; -+ goto errout; -+ } -+ -+ BUFFER_TRACE(*bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, *bh); -+ if (err) { -+ journal_error: -+ brelse(*bh); -+ brelse(bh2); -+ *bh = NULL; -+ ext3_std_error(dir->i_sb, err); -+ goto errout; -+ } -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ -+ data2 = bh2->b_data; -+ -+ /* create map in the end of data2 block */ -+ map = (struct dx_map_entry *) (data2 + blocksize); -+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1, -+ blocksize, hinfo, map); -+ map -= count; -+ split = count/2; // need to adjust to actual middle -+ dx_sort_map (map, count); -+ hash2 = map[split].hash; -+ continued = hash2 == map[split - 1].hash; -+ dxtrace(printk("Split block %i at %x, %i/%i\n", -+ dx_get_block(frame->at), hash2, split, count-split)); -+ -+ /* Fancy dance to stay within two buffers */ -+ de2 = dx_move_dirents(data1, data2, map + split, count - split); -+ de = dx_pack_dirents(data1,blocksize); -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); -+ -+ /* Which block gets the new entry? */ -+ if (hinfo->hash >= hash2) -+ { -+ swap(*bh, bh2); -+ de = de2; -+ } -+ dx_insert_block (frame, hash2 + continued, newblock); -+ err = ext3_journal_dirty_metadata (handle, bh2); -+ if (err) -+ goto journal_error; -+ err = ext3_journal_dirty_metadata (handle, frame->bh); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ dxtrace(dx_show_index ("frame", frame->entries)); -+errout: -+ return de; -+} -+#endif -+ -+ -+/* -+ * Add a new entry into a directory (leaf) block. If de is non-NULL, -+ * it points to a directory entry which is guaranteed to be large -+ * enough for new directory entry. If de is NULL, then -+ * add_dirent_to_buf will attempt search the directory block for -+ * space. It will return -ENOSPC if no space is available, and -EIO -+ * and -EEXIST if directory entry already exists. -+ * -+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In -+ * all other cases bh is released. -+ */ -+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct ext3_dir_entry_2 *de, -+ struct buffer_head * bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned long offset = 0; -+ unsigned short reclen; -+ int nlen, rlen, err; -+ char *top; -+ -+ reclen = EXT3_DIR_REC_LEN(namelen); -+ if (!de) { -+ de = (struct ext3_dir_entry_2 *)bh->b_data; -+ top = bh->b_data + dir->i_sb->s_blocksize - reclen; -+ while ((char *) de <= top) { -+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de, -+ bh, offset)) { -+ brelse (bh); -+ return -EIO; -+ } -+ if (ext3_match (namelen, name, de)) { -+ brelse (bh); -+ return -EEXIST; -+ } -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if ((de->inode? rlen - nlen: rlen) >= reclen) -+ break; -+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen); -+ offset += rlen; -+ } -+ if ((char *) de > top) -+ return -ENOSPC; -+ } -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) { -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return err; -+ } -+ -+ /* By now the buffer is marked for journaling */ -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if (de->inode) { -+ struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); -+ de1->rec_len = cpu_to_le16(rlen - nlen); -+ de->rec_len = cpu_to_le16(nlen); -+ de = de1; -+ } -+ de->file_type = EXT3_FT_UNKNOWN; -+ if (inode) { -+ de->inode = cpu_to_le32(inode->i_ino); -+ ext3_set_de_type(dir->i_sb, de, inode->i_mode); -+ } else -+ de->inode = 0; -+ de->name_len = namelen; -+ memcpy (de->name, name, namelen); -+ /* -+ * XXX shouldn't update any times until successful -+ * completion of syscall, but too many callers depend -+ * on this. -+ * -+ * XXX similarly, too many callers depend on -+ * ext3_new_inode() setting the times, but error -+ * recovery deletes the inode, so the worst that can -+ * happen is that the times are slightly out of date -+ * and/or different from the directory change time. -+ */ -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME; -+ ext3_update_dx_flag(dir); -+ dir->i_version = ++event; -+ ext3_mark_inode_dirty(handle, dir); -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return 0; -+} -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * This converts a one block unindexed directory to a 3 block indexed -+ * directory, and adds the dentry to the indexed directory. -+ */ -+static int make_indexed_dir(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct buffer_head *bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+ struct dx_root *root; -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries; -+ struct ext3_dir_entry_2 *de, *de2; -+ char *data1, *top; -+ unsigned len; -+ int retval; -+ unsigned blocksize; -+ struct dx_hash_info hinfo; -+ u32 block; -+ -+ blocksize = dir->i_sb->s_blocksize; -+ dxtrace(printk("Creating index\n")); -+ retval = ext3_journal_get_write_access(handle, bh); -+ if (retval) { -+ ext3_std_error(dir->i_sb, retval); -+ brelse(bh); -+ return retval; -+ } -+ root = (struct dx_root *) bh->b_data; -+ -+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; -+ bh2 = ext3_append (handle, dir, &block, &retval); -+ if (!(bh2)) { -+ brelse(bh); -+ return retval; -+ } -+ data1 = bh2->b_data; -+ -+ /* The 0th block becomes the root, move the dirents out */ -+ de = (struct ext3_dir_entry_2 *)&root->dotdot; -+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len)); -+ len = ((char *) root) + blocksize - (char *) de; -+ memcpy (data1, de, len); -+ de = (struct ext3_dir_entry_2 *) data1; -+ top = data1 + len; -+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top) -+ de = de2; -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ /* Initialize the root; the dot dirents already exist */ -+ de = (struct ext3_dir_entry_2 *) (&root->dotdot); -+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); -+ memset (&root->info, 0, sizeof(root->info)); -+ root->info.info_length = sizeof(root->info); -+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version; -+ entries = root->entries; -+ dx_set_block (entries, 1); -+ dx_set_count (entries, 1); -+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info))); -+ -+ /* Initialize as for dx_probe */ -+ hinfo.hash_version = root->info.hash_version; -+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ ext3fs_dirhash(name, namelen, &hinfo); -+ frame = frames; -+ frame->entries = entries; -+ frame->at = entries; -+ frame->bh = bh; -+ bh = bh2; -+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval); -+ dx_release (frames); -+ if (!(de)) -+ return retval; -+ -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} -+#endif -+ - /* - * ext3_add_entry() - * -@@ -249,127 +1270,198 @@ - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -- --/* -- * AKPM: the journalling code here looks wrong on the error paths -- */ - static int ext3_add_entry (handle_t *handle, struct dentry *dentry, - struct inode *inode) - { - struct inode *dir = dentry->d_parent->d_inode; -- const char *name = dentry->d_name.name; -- int namelen = dentry->d_name.len; - unsigned long offset; -- unsigned short rec_len; - struct buffer_head * bh; -- struct ext3_dir_entry_2 * de, * de1; -+ struct ext3_dir_entry_2 *de; - struct super_block * sb; - int retval; -+#ifdef CONFIG_EXT3_INDEX -+ int dx_fallback=0; -+#endif -+ unsigned blocksize; -+ unsigned nlen, rlen; -+ u32 block, blocks; - - sb = dir->i_sb; -- -- if (!namelen) -+ blocksize = sb->s_blocksize; -+ if (!dentry->d_name.len) - return -EINVAL; -- bh = ext3_bread (handle, dir, 0, 0, &retval); -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ retval = ext3_dx_add_entry(handle, dentry, inode); -+ if (!retval || (retval != ERR_BAD_DX_DIR)) -+ return retval; -+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; -+ dx_fallback++; -+ ext3_mark_inode_dirty(handle, dir); -+ } -+#endif -+ blocks = dir->i_size >> sb->s_blocksize_bits; -+ for (block = 0, offset = 0; block < blocks; block++) { -+ bh = ext3_bread(handle, dir, block, 0, &retval); -+ if(!bh) -+ return retval; -+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (retval != -ENOSPC) -+ return retval; -+ -+#ifdef CONFIG_EXT3_INDEX -+ if (blocks == 1 && !dx_fallback && -+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ return make_indexed_dir(handle, dentry, inode, bh); -+#endif -+ brelse(bh); -+ } -+ bh = ext3_append(handle, dir, &block, &retval); - if (!bh) - return retval; -- rec_len = EXT3_DIR_REC_LEN(namelen); -- offset = 0; - de = (struct ext3_dir_entry_2 *) bh->b_data; -- while (1) { -- if ((char *)de >= sb->s_blocksize + bh->b_data) { -- brelse (bh); -- bh = NULL; -- bh = ext3_bread (handle, dir, -- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval); -- if (!bh) -- return retval; -- if (dir->i_size <= offset) { -- if (dir->i_size == 0) { -- brelse(bh); -- return -ENOENT; -- } -+ de->inode = 0; -+ de->rec_len = cpu_to_le16(rlen = blocksize); -+ nlen = 0; -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} - -- ext3_debug ("creating next block\n"); -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * Returns 0 for success, or a negative error value -+ */ -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries, *at; -+ struct dx_hash_info hinfo; -+ struct buffer_head * bh; -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct super_block * sb = dir->i_sb; -+ struct ext3_dir_entry_2 *de; -+ int err; - -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- de->inode = 0; -- de->rec_len = le16_to_cpu(sb->s_blocksize); -- dir->u.ext3_i.i_disksize = -- dir->i_size = offset + sb->s_blocksize; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- ext3_mark_inode_dirty(handle, dir); -- } else { -+ frame = dx_probe(dentry, 0, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ entries = frame->entries; -+ at = frame->at; - -- ext3_debug ("skipping to next block\n"); -+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) -+ goto cleanup; - -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- } -- } -- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh, -- offset)) { -- brelse (bh); -- return -ENOENT; -- } -- if (ext3_match (namelen, name, de)) { -- brelse (bh); -- return -EEXIST; -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) -+ goto journal_error; -+ -+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (err != -ENOSPC) { -+ bh = 0; -+ goto cleanup; -+ } -+ -+ /* Block full, should compress but for now just split */ -+ dxtrace(printk("using %u of %u node entries\n", -+ dx_get_count(entries), dx_get_limit(entries))); -+ /* Need to split index? */ -+ if (dx_get_count(entries) == dx_get_limit(entries)) { -+ u32 newblock; -+ unsigned icount = dx_get_count(entries); -+ int levels = frame - frames; -+ struct dx_entry *entries2; -+ struct dx_node *node2; -+ struct buffer_head *bh2; -+ -+ if (levels && (dx_get_count(frames->entries) == -+ dx_get_limit(frames->entries))) { -+ ext3_warning(sb, __FUNCTION__, -+ "Directory index full!\n"); -+ err = -ENOSPC; -+ goto cleanup; - } -- if ((le32_to_cpu(de->inode) == 0 && -- le16_to_cpu(de->rec_len) >= rec_len) || -- (le16_to_cpu(de->rec_len) >= -- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) { -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- /* By now the buffer is marked for journaling */ -- offset += le16_to_cpu(de->rec_len); -- if (le32_to_cpu(de->inode)) { -- de1 = (struct ext3_dir_entry_2 *) ((char *) de + -- EXT3_DIR_REC_LEN(de->name_len)); -- de1->rec_len = -- cpu_to_le16(le16_to_cpu(de->rec_len) - -- EXT3_DIR_REC_LEN(de->name_len)); -- de->rec_len = cpu_to_le16( -- EXT3_DIR_REC_LEN(de->name_len)); -- de = de1; -+ bh2 = ext3_append (handle, dir, &newblock, &err); -+ if (!(bh2)) -+ goto cleanup; -+ node2 = (struct dx_node *)(bh2->b_data); -+ entries2 = node2->entries; -+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); -+ node2->fake.inode = 0; -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ if (levels) { -+ unsigned icount1 = icount/2, icount2 = icount - icount1; -+ unsigned hash2 = dx_get_hash(entries + icount1); -+ dxtrace(printk("Split index %i/%i\n", icount1, icount2)); -+ -+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ -+ err = ext3_journal_get_write_access(handle, -+ frames[0].bh); -+ if (err) -+ goto journal_error; -+ -+ memcpy ((char *) entries2, (char *) (entries + icount1), -+ icount2 * sizeof(struct dx_entry)); -+ dx_set_count (entries, icount1); -+ dx_set_count (entries2, icount2); -+ dx_set_limit (entries2, dx_node_limit(dir)); -+ -+ /* Which index block gets the new entry? */ -+ if (at - entries >= icount1) { -+ frame->at = at = at - entries - icount1 + entries2; -+ frame->entries = entries = entries2; -+ swap(frame->bh, bh2); - } -- de->file_type = EXT3_FT_UNKNOWN; -- if (inode) { -- de->inode = cpu_to_le32(inode->i_ino); -- ext3_set_de_type(dir->i_sb, de, inode->i_mode); -- } else -- de->inode = 0; -- de->name_len = namelen; -- memcpy (de->name, name, namelen); -- /* -- * XXX shouldn't update any times until successful -- * completion of syscall, but too many callers depend -- * on this. -- * -- * XXX similarly, too many callers depend on -- * ext3_new_inode() setting the times, but error -- * recovery deletes the inode, so the worst that can -- * happen is that the times are slightly out of date -- * and/or different from the directory change time. -- */ -- dir->i_mtime = dir->i_ctime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- dir->i_version = ++event; -- ext3_mark_inode_dirty(handle, dir); -- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -- ext3_journal_dirty_metadata(handle, bh); -- brelse(bh); -- return 0; -+ dx_insert_block (frames + 0, hash2, newblock); -+ dxtrace(dx_show_index ("node", frames[1].entries)); -+ dxtrace(dx_show_index ("node", -+ ((struct dx_node *) bh2->b_data)->entries)); -+ err = ext3_journal_dirty_metadata(handle, bh2); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ } else { -+ dxtrace(printk("Creating second level index...\n")); -+ memcpy((char *) entries2, (char *) entries, -+ icount * sizeof(struct dx_entry)); -+ dx_set_limit(entries2, dx_node_limit(dir)); -+ -+ /* Set up root */ -+ dx_set_count(entries, 1); -+ dx_set_block(entries + 0, newblock); -+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; -+ -+ /* Add new access path frame */ -+ frame = frames + 1; -+ frame->at = at = at - entries + entries2; -+ frame->entries = entries = entries2; -+ frame->bh = bh2; -+ err = ext3_journal_get_write_access(handle, -+ frame->bh); -+ if (err) -+ goto journal_error; - } -- offset += le16_to_cpu(de->rec_len); -- de = (struct ext3_dir_entry_2 *) -- ((char *) de + le16_to_cpu(de->rec_len)); -+ ext3_journal_dirty_metadata(handle, frames[0].bh); - } -- brelse (bh); -- return -ENOSPC; -+ de = do_split(handle, dir, &bh, frame, &hinfo, &err); -+ if (!de) -+ goto cleanup; -+ err = add_dirent_to_buf(handle, dentry, inode, de, bh); -+ bh = 0; -+ goto cleanup; -+ -+journal_error: -+ ext3_std_error(dir->i_sb, err); -+cleanup: -+ if (bh) -+ brelse(bh); -+ dx_release(frames); -+ return err; - } -+#endif - - /* - * ext3_delete_entry deletes a directory entry by merging it with the -@@ -456,9 +1548,11 @@ - struct inode * inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -482,9 +1576,11 @@ - struct inode *inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -513,9 +1609,11 @@ - if (dir->i_nlink >= EXT3_LINK_MAX) - return -EMLINK; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -527,7 +1625,7 @@ - - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; -- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize; -+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ -@@ -556,21 +1654,19 @@ - brelse (dir_block); - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); -- if (err) -- goto out_no_entry; -+ if (err) { -+ inode->i_nlink = 0; -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - dir->i_nlink++; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- inode->i_nlink = 0; -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - /* -@@ -657,7 +1753,7 @@ - int err = 0, rc; - - lock_super(sb); -- if (!list_empty(&inode->u.ext3_i.i_orphan)) -+ if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - - /* Orphan handling is only valid for files with data blocks -@@ -698,7 +1794,7 @@ - * This is safe: on error we're going to ignore the orphan list - * anyway on the next recovery. */ - if (!err) -- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan); -+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", -@@ -716,25 +1812,26 @@ - int ext3_orphan_del(handle_t *handle, struct inode *inode) - { - struct list_head *prev; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_sb_info *sbi; - unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; - - lock_super(inode->i_sb); -- if (list_empty(&inode->u.ext3_i.i_orphan)) { -+ if (list_empty(&ei->i_orphan)) { - unlock_super(inode->i_sb); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); -- prev = inode->u.ext3_i.i_orphan.prev; -+ prev = ei->i_orphan.prev; - sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - -- list_del(&inode->u.ext3_i.i_orphan); -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ list_del(&ei->i_orphan); -+ INIT_LIST_HEAD(&ei->i_orphan); - - /* If we're on an error path, we may not have a valid - * transaction handle with which to update the orphan list on -@@ -795,8 +1892,9 @@ - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - retval = -ENOENT; - bh = ext3_find_entry (dentry, &de); -@@ -834,7 +1932,7 @@ - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - - end_rmdir: -@@ -852,8 +1950,9 @@ - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -880,7 +1979,7 @@ - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; - if (!inode->i_nlink) -@@ -906,9 +2005,11 @@ - if (l > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -918,7 +2019,7 @@ - if (IS_ERR(inode)) - goto out_stop; - -- if (l > sizeof (inode->u.ext3_i.i_data)) { -+ if (l > sizeof (EXT3_I(inode)->i_data)) { - inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* -@@ -927,24 +2028,22 @@ - * i_size in generic_commit_write(). - */ - err = block_symlink(inode, symname, l); -- if (err) -- goto out_no_entry; -+ if (err) { -+ ext3_dec_count(handle, inode); -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - } else { - inode->i_op = &ext3_fast_symlink_inode_operations; -- memcpy((char*)&inode->u.ext3_i.i_data,symname,l); -+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l); - inode->i_size = l-1; - } -- inode->u.ext3_i.i_disksize = inode->i_size; -+ EXT3_I(inode)->i_disksize = inode->i_size; - err = ext3_add_nondir(handle, dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- ext3_dec_count(handle, inode); -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - static int ext3_link (struct dentry * old_dentry, -@@ -957,12 +2056,15 @@ - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) -+ if (inode->i_nlink >= EXT3_LINK_MAX) { - return -EMLINK; -+ } - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -995,9 +2097,11 @@ - - old_bh = new_bh = dir_bh = NULL; - -- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(old_dir) || IS_SYNC(new_dir)) - handle->h_sync = 1; -@@ -1070,14 +2174,37 @@ - /* - * ok, that's it - */ -- ext3_delete_entry(handle, old_dir, old_de, old_bh); -+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino || -+ old_de->name_len != old_dentry->d_name.len || -+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || -+ (retval = ext3_delete_entry(handle, old_dir, -+ old_de, old_bh)) == -ENOENT) { -+ /* old_de could have moved from under us during htree split, so -+ * make sure that we are deleting the right entry. We might -+ * also be pointing to a stale entry in the unused part of -+ * old_bh so just checking inum and the name isn't enough. */ -+ struct buffer_head *old_bh2; -+ struct ext3_dir_entry_2 *old_de2; -+ -+ old_bh2 = ext3_find_entry(old_dentry, &old_de2); -+ if (old_bh2) { -+ retval = ext3_delete_entry(handle, old_dir, -+ old_de2, old_bh2); -+ brelse(old_bh2); -+ } -+ } -+ if (retval) { -+ ext3_warning(old_dir->i_sb, "ext3_rename", -+ "Deleting old file (%lu), %d, error=%d", -+ old_dir->i_ino, old_dir->i_nlink, retval); -+ } - - if (new_inode) { - new_inode->i_nlink--; - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(old_dir); - if (dir_bh) { - BUFFER_TRACE(dir_bh, "get_write_access"); - ext3_journal_get_write_access(handle, dir_bh); -@@ -1089,7 +2212,7 @@ - new_inode->i_nlink--; - } else { - new_dir->i_nlink++; -- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } - } -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 16:17:59.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 16:18:17.000000000 +0300 -@@ -777,6 +777,7 @@ - es->s_mtime = cpu_to_le32(CURRENT_TIME); - ext3_update_dynamic_rev(sb); - EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -+ - ext3_commit_super (sb, es, 1); - if (test_opt (sb, DEBUG)) - printk (KERN_INFO -@@ -787,6 +788,7 @@ - EXT3_BLOCKS_PER_GROUP(sb), - EXT3_INODES_PER_GROUP(sb), - sbi->s_mount_opt); -+ - printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ", - bdevname(sb->s_dev)); - if (EXT3_SB(sb)->s_journal->j_inode == NULL) { -@@ -960,6 +962,7 @@ - return res; - } - -+ - struct super_block * ext3_read_super (struct super_block * sb, void * data, - int silent) - { -@@ -1146,6 +1149,9 @@ - sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); -+ for (i=0; i < 4; i++) -+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); -+ sbi->s_def_hash_version = es->s_def_hash_version; - - if (sbi->s_blocks_per_group > blocksize * 8) { - printk (KERN_ERR -@@ -1938,6 +1944,7 @@ - unregister_filesystem(&ext3_fs_type); - } - -+EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 16:18:17.000000000 +0300 -@@ -40,6 +40,11 @@ - #define EXT3FS_VERSION "2.4-0.9.19" - - /* -+ * Always enable hashed directories -+ */ -+#define CONFIG_EXT3_INDEX -+ -+/* - * Debug code - */ - #ifdef EXT3FS_DEBUG -@@ -415,8 +420,11 @@ - /*E0*/ __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ -- --/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */ -+ __u32 s_hash_seed[4]; /* HTREE hash seed */ -+ __u8 s_def_hash_version; /* Default hash version to use */ -+ __u8 s_reserved_char_pad; -+ __u16 s_reserved_word_pad; -+ __u32 s_reserved[192]; /* Padding to the end of the block */ - }; - - #ifdef __KERNEL__ -@@ -553,9 +561,46 @@ - #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) - #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ - ~EXT3_DIR_ROUND) -+/* -+ * Hash Tree Directory indexing -+ * (c) Daniel Phillips, 2001 -+ */ -+ -+#ifdef CONFIG_EXT3_INDEX -+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \ -+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \ -+ (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) -+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) -+#else -+ #define is_dx(dir) 0 -+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2) -+#endif -+ -+/* Legal values for the dx_root hash_version field: */ -+ -+#define DX_HASH_LEGACY 0 -+#define DX_HASH_HALF_MD4 1 -+#define DX_HASH_TEA 2 -+ -+/* hash info structure used by the directory hash */ -+struct dx_hash_info -+{ -+ u32 hash; -+ u32 minor_hash; -+ int hash_version; -+ u32 *seed; -+}; - - #ifdef __KERNEL__ - /* -+ * Control parameters used by ext3_htree_next_block -+ */ -+#define HASH_NB_ALWAYS 1 -+ -+ -+/* - * Describe an inode's exact location on disk and in memory - */ - struct ext3_iloc -@@ -565,6 +610,27 @@ - unsigned long block_group; - }; - -+ -+/* -+ * This structure is stuffed into the struct file's private_data field -+ * for directories. It is where we put information so that we can do -+ * readdir operations in hash tree order. -+ */ -+struct dir_private_info { -+ rb_root_t root; -+ rb_node_t *curr_node; -+ struct fname *extra_fname; -+ loff_t last_pos; -+ __u32 curr_hash; -+ __u32 curr_minor_hash; -+ __u32 next_hash; -+}; -+ -+/* -+ * Special error return code only used by dx_probe() and its callers. -+ */ -+#define ERR_BAD_DX_DIR -75000 -+ - /* - * Function prototypes - */ -@@ -592,11 +658,20 @@ - - /* dir.c */ - extern int ext3_check_dir_entry(const char *, struct inode *, -- struct ext3_dir_entry_2 *, struct buffer_head *, -- unsigned long); -+ struct ext3_dir_entry_2 *, -+ struct buffer_head *, unsigned long); -+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent); -+extern void ext3_htree_free_dir_info(struct dir_private_info *p); -+ - /* fsync.c */ - extern int ext3_sync_file (struct file *, struct dentry *, int); - -+/* hash.c */ -+extern int ext3fs_dirhash(const char *name, int len, struct -+ dx_hash_info *hinfo); -+ - /* ialloc.c */ - extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); - extern void ext3_free_inode (handle_t *, struct inode *); -@@ -630,6 +705,8 @@ - /* namei.c */ - extern int ext3_orphan_add(handle_t *, struct inode *); - extern int ext3_orphan_del(handle_t *, struct inode *); -+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash); - - /* super.c */ - extern void ext3_error (struct super_block *, const char *, const char *, ...) -Index: linux-2.4.21-chaos/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs_sb.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs_sb.h 2003-12-12 16:18:17.000000000 +0300 -@@ -62,6 +62,8 @@ - int s_inode_size; - int s_first_ino; - u32 s_next_generation; -+ u32 s_hash_seed[4]; -+ int s_def_hash_version; - - /* Journaling */ - struct inode * s_journal_inode; -Index: linux-2.4.21-chaos/include/linux/ext3_jbd.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_jbd.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_jbd.h 2003-12-12 16:18:17.000000000 +0300 -@@ -69,6 +69,8 @@ - - #define EXT3_RESERVE_TRANS_BLOCKS 12U - -+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 -+ - int - ext3_mark_iloc_dirty(handle_t *handle, - struct inode *inode, -Index: linux-2.4.21-chaos/include/linux/rbtree.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/rbtree.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/rbtree.h 2003-12-12 16:18:17.000000000 +0300 -@@ -120,6 +120,8 @@ - - extern void rb_insert_color(rb_node_t *, rb_root_t *); - extern void rb_erase(rb_node_t *, rb_root_t *); -+extern rb_node_t *rb_get_first(rb_root_t *root); -+extern rb_node_t *rb_get_next(rb_node_t *n); - - static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) - { -Index: linux-2.4.21-chaos/lib/rbtree.c -=================================================================== ---- linux-2.4.21-chaos.orig/lib/rbtree.c 2002-09-25 21:14:03.000000000 +0400 -+++ linux-2.4.21-chaos/lib/rbtree.c 2003-12-12 16:18:17.000000000 +0300 -@@ -17,6 +17,8 @@ - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -+ -+ rb_get_first and rb_get_next written by Theodore Ts'o, 9/8/2002 - */ - - #include -@@ -294,3 +296,43 @@ - __rb_erase_color(child, parent, root); - } - EXPORT_SYMBOL(rb_erase); -+ -+/* -+ * This function returns the first node (in sort order) of the tree. -+ */ -+rb_node_t *rb_get_first(rb_root_t *root) -+{ -+ rb_node_t *n; -+ -+ n = root->rb_node; -+ if (!n) -+ return 0; -+ while (n->rb_left) -+ n = n->rb_left; -+ return n; -+} -+EXPORT_SYMBOL(rb_get_first); -+ -+/* -+ * Given a node, this function will return the next node in the tree. -+ */ -+rb_node_t *rb_get_next(rb_node_t *n) -+{ -+ rb_node_t *parent; -+ -+ if (n->rb_right) { -+ n = n->rb_right; -+ while (n->rb_left) -+ n = n->rb_left; -+ return n; -+ } else { -+ while ((parent = n->rb_parent)) { -+ if (n == parent->rb_left) -+ return parent; -+ n = parent; -+ } -+ return 0; -+ } -+} -+EXPORT_SYMBOL(rb_get_next); -+ diff --git a/lustre/kernel_patches/patches/ext3-htree-2.4.21-rhel.patch b/lustre/kernel_patches/patches/ext3-htree-2.4.21-rhel.patch deleted file mode 100644 index c42156b..0000000 --- a/lustre/kernel_patches/patches/ext3-htree-2.4.21-rhel.patch +++ /dev/null @@ -1,2531 +0,0 @@ - fs/ext3/Makefile | 2 - fs/ext3/dir.c | 302 +++++++++ - fs/ext3/file.c | 3 - fs/ext3/hash.c | 215 ++++++ - fs/ext3/namei.c | 1421 ++++++++++++++++++++++++++++++++++++++++----- - fs/ext3/super.c | 7 - include/linux/ext3_fs.h | 85 ++ - include/linux/ext3_fs_sb.h | 2 - include/linux/ext3_jbd.h | 2 - include/linux/rbtree.h | 2 - lib/rbtree.c | 42 + - 11 files changed, 1922 insertions(+), 161 deletions(-) - -Index: linux-2.4.21/fs/ext3/dir.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/dir.c 2001-11-09 17:25:04.000000000 -0500 -+++ linux-2.4.21/fs/ext3/dir.c 2004-09-16 19:41:03.000000000 -0400 -@@ -21,12 +21,16 @@ - #include - #include - #include -+#include -+#include - - static unsigned char ext3_filetype_table[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK - }; - - static int ext3_readdir(struct file *, void *, filldir_t); -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir); - - struct file_operations ext3_dir_operations = { - read: generic_read_dir, -@@ -35,6 +39,17 @@ - fsync: ext3_sync_file, /* BKL held */ - }; - -+ -+static unsigned char get_dtype(struct super_block *sb, int filetype) -+{ -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) || -+ (filetype >= EXT3_FT_MAX)) -+ return DT_UNKNOWN; -+ -+ return (ext3_filetype_table[filetype]); -+} -+ -+ - int ext3_check_dir_entry (const char * function, struct inode * dir, - struct ext3_dir_entry_2 * de, - struct buffer_head * bh, -@@ -79,6 +94,16 @@ - - sb = inode->i_sb; - -+ if (is_dx(inode)) { -+ err = ext3_dx_readdir(filp, dirent, filldir); -+ if (err != ERR_BAD_DX_DIR) -+ return err; -+ /* -+ * We don't set the inode dirty flag since it's not -+ * critical that it get flushed back to the disk. -+ */ -+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; -+ } - stored = 0; - bh = NULL; - offset = filp->f_pos & (sb->s_blocksize - 1); -@@ -162,18 +187,12 @@ - * during the copy operation. - */ - unsigned long version = filp->f_version; -- unsigned char d_type = DT_UNKNOWN; - -- if (EXT3_HAS_INCOMPAT_FEATURE(sb, -- EXT3_FEATURE_INCOMPAT_FILETYPE) -- && de->file_type < EXT3_FT_MAX) -- d_type = -- ext3_filetype_table[de->file_type]; - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, - le32_to_cpu(de->inode), -- d_type); -+ get_dtype(sb, de->file_type)); - if (error) - break; - if (version != filp->f_version) -@@ -188,3 +207,272 @@ - UPDATE_ATIME(inode); - return 0; - } -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * These functions convert from the major/minor hash to an f_pos -+ * value. -+ * -+ * Currently we only use major hash numer. This is unfortunate, but -+ * on 32-bit machines, the same VFS interface is used for lseek and -+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of -+ * lseek/telldir/seekdir will blow out spectacularly, and from within -+ * the ext2 low-level routine, we don't know if we're being called by -+ * a 64-bit version of the system call or the 32-bit version of the -+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir -+ * cookie. Sigh. -+ */ -+#define hash2pos(major, minor) (major >> 1) -+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) -+#define pos2min_hash(pos) (0) -+ -+/* -+ * This structure holds the nodes of the red-black tree used to store -+ * the directory entry in hash order. -+ */ -+struct fname { -+ __u32 hash; -+ __u32 minor_hash; -+ rb_node_t rb_hash; -+ struct fname *next; -+ __u32 inode; -+ __u8 name_len; -+ __u8 file_type; -+ char name[0]; -+}; -+ -+/* -+ * This functoin implements a non-recursive way of freeing all of the -+ * nodes in the red-black tree. -+ */ -+static void free_rb_tree_fname(rb_root_t *root) -+{ -+ rb_node_t *n = root->rb_node; -+ rb_node_t *parent; -+ struct fname *fname; -+ -+ while (n) { -+ /* Do the node's children first */ -+ if ((n)->rb_left) { -+ n = n->rb_left; -+ continue; -+ } -+ if (n->rb_right) { -+ n = n->rb_right; -+ continue; -+ } -+ /* -+ * The node has no children; free it, and then zero -+ * out parent's link to it. Finally go to the -+ * beginning of the loop and try to free the parent -+ * node. -+ */ -+ parent = n->rb_parent; -+ fname = rb_entry(n, struct fname, rb_hash); -+ kfree(fname); -+ if (!parent) -+ root->rb_node = 0; -+ else if (parent->rb_left == n) -+ parent->rb_left = 0; -+ else if (parent->rb_right == n) -+ parent->rb_right = 0; -+ n = parent; -+ } -+ root->rb_node = 0; -+} -+ -+ -+struct dir_private_info *create_dir_info(loff_t pos) -+{ -+ struct dir_private_info *p; -+ -+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL); -+ if (!p) -+ return NULL; -+ p->root.rb_node = 0; -+ p->curr_node = 0; -+ p->extra_fname = 0; -+ p->last_pos = 0; -+ p->curr_hash = pos2maj_hash(pos); -+ p->curr_minor_hash = pos2min_hash(pos); -+ p->next_hash = 0; -+ return p; -+} -+ -+void ext3_htree_free_dir_info(struct dir_private_info *p) -+{ -+ free_rb_tree_fname(&p->root); -+ kfree(p); -+} -+ -+/* -+ * Given a directory entry, enter it into the fname rb tree. -+ */ -+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent) -+{ -+ rb_node_t **p, *parent = NULL; -+ struct fname * fname, *new_fn; -+ struct dir_private_info *info; -+ int len; -+ -+ info = (struct dir_private_info *) dir_file->private_data; -+ p = &info->root.rb_node; -+ -+ /* Create and allocate the fname structure */ -+ len = sizeof(struct fname) + dirent->name_len + 1; -+ new_fn = kmalloc(len, GFP_KERNEL); -+ if (!new_fn) -+ return -ENOMEM; -+ memset(new_fn, 0, len); -+ new_fn->hash = hash; -+ new_fn->minor_hash = minor_hash; -+ new_fn->inode = le32_to_cpu(dirent->inode); -+ new_fn->name_len = dirent->name_len; -+ new_fn->file_type = dirent->file_type; -+ memcpy(new_fn->name, dirent->name, dirent->name_len); -+ new_fn->name[dirent->name_len] = 0; -+ -+ while (*p) { -+ parent = *p; -+ fname = rb_entry(parent, struct fname, rb_hash); -+ -+ /* -+ * If the hash and minor hash match up, then we put -+ * them on a linked list. This rarely happens... -+ */ -+ if ((new_fn->hash == fname->hash) && -+ (new_fn->minor_hash == fname->minor_hash)) { -+ new_fn->next = fname->next; -+ fname->next = new_fn; -+ return 0; -+ } -+ -+ if (new_fn->hash < fname->hash) -+ p = &(*p)->rb_left; -+ else if (new_fn->hash > fname->hash) -+ p = &(*p)->rb_right; -+ else if (new_fn->minor_hash < fname->minor_hash) -+ p = &(*p)->rb_left; -+ else /* if (new_fn->minor_hash > fname->minor_hash) */ -+ p = &(*p)->rb_right; -+ } -+ -+ rb_link_node(&new_fn->rb_hash, parent, p); -+ rb_insert_color(&new_fn->rb_hash, &info->root); -+ return 0; -+} -+ -+ -+ -+/* -+ * This is a helper function for ext3_dx_readdir. It calls filldir -+ * for all entres on the fname linked list. (Normally there is only -+ * one entry on the linked list, unless there are 62 bit hash collisions.) -+ */ -+static int call_filldir(struct file * filp, void * dirent, -+ filldir_t filldir, struct fname *fname) -+{ -+ struct dir_private_info *info = filp->private_data; -+ loff_t curr_pos; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct super_block * sb; -+ int error; -+ -+ sb = inode->i_sb; -+ -+ if (!fname) { -+ printk("call_filldir: called with null fname?!?\n"); -+ return 0; -+ } -+ curr_pos = hash2pos(fname->hash, fname->minor_hash); -+ while (fname) { -+ error = filldir(dirent, fname->name, -+ fname->name_len, curr_pos, -+ fname->inode, -+ get_dtype(sb, fname->file_type)); -+ if (error) { -+ filp->f_pos = curr_pos; -+ info->extra_fname = fname->next; -+ return error; -+ } -+ fname = fname->next; -+ } -+ return 0; -+} -+ -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir) -+{ -+ struct dir_private_info *info = filp->private_data; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct fname *fname; -+ int ret; -+ -+ if (!info) { -+ info = create_dir_info(filp->f_pos); -+ if (!info) -+ return -ENOMEM; -+ filp->private_data = info; -+ } -+ -+ /* Some one has messed with f_pos; reset the world */ -+ if (info->last_pos != filp->f_pos) { -+ free_rb_tree_fname(&info->root); -+ info->curr_node = 0; -+ info->extra_fname = 0; -+ info->curr_hash = pos2maj_hash(filp->f_pos); -+ info->curr_minor_hash = pos2min_hash(filp->f_pos); -+ } -+ -+ /* -+ * If there are any leftover names on the hash collision -+ * chain, return them first. -+ */ -+ if (info->extra_fname && -+ call_filldir(filp, dirent, filldir, info->extra_fname)) -+ goto finished; -+ -+ if (!info->curr_node) -+ info->curr_node = rb_first(&info->root); -+ -+ while (1) { -+ /* -+ * Fill the rbtree if we have no more entries, -+ * or the inode has changed since we last read in the -+ * cached entries. -+ */ -+ if ((!info->curr_node) || -+ (filp->f_version != inode->i_version)) { -+ info->curr_node = 0; -+ free_rb_tree_fname(&info->root); -+ filp->f_version = inode->i_version; -+ ret = ext3_htree_fill_tree(filp, info->curr_hash, -+ info->curr_minor_hash, -+ &info->next_hash); -+ if (ret < 0) -+ return ret; -+ if (ret == 0) -+ break; -+ info->curr_node = rb_first(&info->root); -+ } -+ -+ fname = rb_entry(info->curr_node, struct fname, rb_hash); -+ info->curr_hash = fname->hash; -+ info->curr_minor_hash = fname->minor_hash; -+ if (call_filldir(filp, dirent, filldir, fname)) -+ break; -+ -+ info->curr_node = rb_next(info->curr_node); -+ if (!info->curr_node) { -+ info->curr_hash = info->next_hash; -+ info->curr_minor_hash = 0; -+ } -+ } -+finished: -+ info->last_pos = filp->f_pos; -+ UPDATE_ATIME(inode); -+ return 0; -+} -+#endif -Index: linux-2.4.21/fs/ext3/file.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/file.c 2004-09-11 10:16:28.000000000 -0400 -+++ linux-2.4.21/fs/ext3/file.c 2004-09-16 19:40:16.000000000 -0400 -@@ -38,6 +38,9 @@ - { - if (filp->f_mode & FMODE_WRITE) - ext3_discard_prealloc (inode); -+ if (is_dx(inode) && filp->private_data) -+ ext3_htree_free_dir_info(filp->private_data); -+ - return 0; - } - -Index: linux-2.4.21/fs/ext3/hash.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/hash.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.4.21/fs/ext3/hash.c 2004-09-16 19:40:16.000000000 -0400 -@@ -0,0 +1,215 @@ -+/* -+ * linux/fs/ext3/hash.c -+ * -+ * Copyright (C) 2002 by Theodore Ts'o -+ * -+ * This file is released under the GPL v2. -+ * -+ * This file may be redistributed under the terms of the GNU Public -+ * License. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define DELTA 0x9E3779B9 -+ -+static void TEA_transform(__u32 buf[4], __u32 const in[]) -+{ -+ __u32 sum = 0; -+ __u32 b0 = buf[0], b1 = buf[1]; -+ __u32 a = in[0], b = in[1], c = in[2], d = in[3]; -+ int n = 16; -+ -+ do { -+ sum += DELTA; -+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); -+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); -+ } while(--n); -+ -+ buf[0] += b0; -+ buf[1] += b1; -+} -+ -+/* F, G and H are basic MD4 functions: selection, majority, parity */ -+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+ -+/* -+ * The generic round function. The application is so specific that -+ * we don't bother protecting all the arguments with parens, as is generally -+ * good macro practice, in favor of extra legibility. -+ * Rotation is separate from addition to prevent recomputation -+ */ -+#define ROUND(f, a, b, c, d, x, s) \ -+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) -+#define K1 0 -+#define K2 013240474631UL -+#define K3 015666365641UL -+ -+/* -+ * Basic cut-down MD4 transform. Returns only 32 bits of result. -+ */ -+static void halfMD4Transform (__u32 buf[4], __u32 const in[]) -+{ -+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; -+ -+ /* Round 1 */ -+ ROUND(F, a, b, c, d, in[0] + K1, 3); -+ ROUND(F, d, a, b, c, in[1] + K1, 7); -+ ROUND(F, c, d, a, b, in[2] + K1, 11); -+ ROUND(F, b, c, d, a, in[3] + K1, 19); -+ ROUND(F, a, b, c, d, in[4] + K1, 3); -+ ROUND(F, d, a, b, c, in[5] + K1, 7); -+ ROUND(F, c, d, a, b, in[6] + K1, 11); -+ ROUND(F, b, c, d, a, in[7] + K1, 19); -+ -+ /* Round 2 */ -+ ROUND(G, a, b, c, d, in[1] + K2, 3); -+ ROUND(G, d, a, b, c, in[3] + K2, 5); -+ ROUND(G, c, d, a, b, in[5] + K2, 9); -+ ROUND(G, b, c, d, a, in[7] + K2, 13); -+ ROUND(G, a, b, c, d, in[0] + K2, 3); -+ ROUND(G, d, a, b, c, in[2] + K2, 5); -+ ROUND(G, c, d, a, b, in[4] + K2, 9); -+ ROUND(G, b, c, d, a, in[6] + K2, 13); -+ -+ /* Round 3 */ -+ ROUND(H, a, b, c, d, in[3] + K3, 3); -+ ROUND(H, d, a, b, c, in[7] + K3, 9); -+ ROUND(H, c, d, a, b, in[2] + K3, 11); -+ ROUND(H, b, c, d, a, in[6] + K3, 15); -+ ROUND(H, a, b, c, d, in[1] + K3, 3); -+ ROUND(H, d, a, b, c, in[5] + K3, 9); -+ ROUND(H, c, d, a, b, in[0] + K3, 11); -+ ROUND(H, b, c, d, a, in[4] + K3, 15); -+ -+ buf[0] += a; -+ buf[1] += b; -+ buf[2] += c; -+ buf[3] += d; -+} -+ -+#undef ROUND -+#undef F -+#undef G -+#undef H -+#undef K1 -+#undef K2 -+#undef K3 -+ -+/* The old legacy hash */ -+static __u32 dx_hack_hash (const char *name, int len) -+{ -+ __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; -+ while (len--) { -+ __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); -+ -+ if (hash & 0x80000000) hash -= 0x7fffffff; -+ hash1 = hash0; -+ hash0 = hash; -+ } -+ return (hash0 << 1); -+} -+ -+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) -+{ -+ __u32 pad, val; -+ int i; -+ -+ pad = (__u32)len | ((__u32)len << 8); -+ pad |= pad << 16; -+ -+ val = pad; -+ if (len > num*4) -+ len = num * 4; -+ for (i=0; i < len; i++) { -+ if ((i % 4) == 0) -+ val = pad; -+ val = msg[i] + (val << 8); -+ if ((i % 4) == 3) { -+ *buf++ = val; -+ val = pad; -+ num--; -+ } -+ } -+ if (--num >= 0) -+ *buf++ = val; -+ while (--num >= 0) -+ *buf++ = pad; -+} -+ -+/* -+ * Returns the hash of a filename. If len is 0 and name is NULL, then -+ * this function can be used to test whether or not a hash version is -+ * supported. -+ * -+ * The seed is an 4 longword (32 bits) "secret" which can be used to -+ * uniquify a hash. If the seed is all zero's, then some default seed -+ * may be used. -+ * -+ * A particular hash version specifies whether or not the seed is -+ * represented, and whether or not the returned hash is 32 bits or 64 -+ * bits. 32 bit hashes will return 0 for the minor hash. -+ */ -+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) -+{ -+ __u32 hash; -+ __u32 minor_hash = 0; -+ const char *p; -+ int i; -+ __u32 in[8], buf[4]; -+ -+ /* Initialize the default seed for the hash checksum functions */ -+ buf[0] = 0x67452301; -+ buf[1] = 0xefcdab89; -+ buf[2] = 0x98badcfe; -+ buf[3] = 0x10325476; -+ -+ /* Check to see if the seed is all zero's */ -+ if (hinfo->seed) { -+ for (i=0; i < 4; i++) { -+ if (hinfo->seed[i]) -+ break; -+ } -+ if (i < 4) -+ memcpy(buf, hinfo->seed, sizeof(buf)); -+ } -+ -+ switch (hinfo->hash_version) { -+ case DX_HASH_LEGACY: -+ hash = dx_hack_hash(name, len); -+ break; -+ case DX_HASH_HALF_MD4: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 8); -+ halfMD4Transform(buf, in); -+ len -= 32; -+ p += 32; -+ } -+ minor_hash = buf[2]; -+ hash = buf[1]; -+ break; -+ case DX_HASH_TEA: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 4); -+ TEA_transform(buf, in); -+ len -= 16; -+ p += 16; -+ } -+ hash = buf[0]; -+ minor_hash = buf[1]; -+ break; -+ default: -+ hinfo->hash = 0; -+ return -1; -+ } -+ hinfo->hash = hash & ~1; -+ hinfo->minor_hash = minor_hash; -+ return 0; -+} -Index: linux-2.4.21/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21.orig/fs/ext3/Makefile 2004-09-16 19:21:00.000000000 -0400 -+++ linux-2.4.21/fs/ext3/Makefile 2004-09-16 19:40:16.000000000 -0400 -@@ -12,7 +12,7 @@ - export-objs := super.o inode.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o -+ ioctl.o namei.o super.o symlink.o hash.o - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/namei.c 2004-09-11 10:16:28.000000000 -0400 -+++ linux-2.4.21/fs/ext3/namei.c 2004-09-16 19:40:16.000000000 -0400 -@@ -16,6 +16,12 @@ - * David S. Miller (davem@caip.rutgers.edu), 1995 - * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 -+ * Hash Tree Directory indexing (c) -+ * Daniel Phillips, 2001 -+ * Hash Tree Directory indexing porting -+ * Christopher Li, 2002 -+ * Hash Tree Directory indexing cleanup -+ * Theodore Ts'o, 2002 - */ - - #include -@@ -40,6 +46,642 @@ - #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) - #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) - -+static struct buffer_head *ext3_append(handle_t *handle, -+ struct inode *inode, -+ u32 *block, int *err) -+{ -+ struct buffer_head *bh; -+ -+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits; -+ -+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) { -+ inode->i_size += inode->i_sb->s_blocksize; -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_journal_get_write_access(handle,bh); -+ } -+ return bh; -+} -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#ifndef swap -+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) -+#endif -+ -+typedef struct { u32 v; } le_u32; -+typedef struct { u16 v; } le_u16; -+ -+#ifdef DX_DEBUG -+#define dxtrace(command) command -+#else -+#define dxtrace(command) -+#endif -+ -+struct fake_dirent -+{ -+ /*le*/u32 inode; -+ /*le*/u16 rec_len; -+ u8 name_len; -+ u8 file_type; -+}; -+ -+struct dx_countlimit -+{ -+ le_u16 limit; -+ le_u16 count; -+}; -+ -+struct dx_entry -+{ -+ le_u32 hash; -+ le_u32 block; -+}; -+ -+/* -+ * dx_root_info is laid out so that if it should somehow get overlaid by a -+ * dirent the two low bits of the hash version will be zero. Therefore, the -+ * hash version mod 4 should never be 0. Sincerely, the paranoia department. -+ */ -+ -+struct dx_root -+{ -+ struct fake_dirent dot; -+ char dot_name[4]; -+ struct fake_dirent dotdot; -+ char dotdot_name[4]; -+ struct dx_root_info -+ { -+ le_u32 reserved_zero; -+ u8 hash_version; -+ u8 info_length; /* 8 */ -+ u8 indirect_levels; -+ u8 unused_flags; -+ } -+ info; -+ struct dx_entry entries[0]; -+}; -+ -+struct dx_node -+{ -+ struct fake_dirent fake; -+ struct dx_entry entries[0]; -+}; -+ -+ -+struct dx_frame -+{ -+ struct buffer_head *bh; -+ struct dx_entry *entries; -+ struct dx_entry *at; -+}; -+ -+struct dx_map_entry -+{ -+ u32 hash; -+ u32 offs; -+}; -+ -+#ifdef CONFIG_EXT3_INDEX -+static inline unsigned dx_get_block (struct dx_entry *entry); -+static void dx_set_block (struct dx_entry *entry, unsigned value); -+static inline unsigned dx_get_hash (struct dx_entry *entry); -+static void dx_set_hash (struct dx_entry *entry, unsigned value); -+static unsigned dx_get_count (struct dx_entry *entries); -+static unsigned dx_get_limit (struct dx_entry *entries); -+static void dx_set_count (struct dx_entry *entries, unsigned value); -+static void dx_set_limit (struct dx_entry *entries, unsigned value); -+static unsigned dx_root_limit (struct inode *dir, unsigned infosize); -+static unsigned dx_node_limit (struct inode *dir); -+static struct dx_frame *dx_probe(struct dentry *dentry, -+ struct inode *dir, -+ struct dx_hash_info *hinfo, -+ struct dx_frame *frame, -+ int *err); -+static void dx_release (struct dx_frame *frames); -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry map[]); -+static void dx_sort_map(struct dx_map_entry *map, unsigned count); -+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, -+ struct dx_map_entry *offsets, int count); -+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); -+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash); -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err); -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Future: use high four bits of block for coalesce-on-delete flags -+ * Mask them off for now. -+ */ -+ -+static inline unsigned dx_get_block (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->block.v) & 0x00ffffff; -+} -+ -+static inline void dx_set_block (struct dx_entry *entry, unsigned value) -+{ -+ entry->block.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_hash (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->hash.v); -+} -+ -+static inline void dx_set_hash (struct dx_entry *entry, unsigned value) -+{ -+ entry->hash.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_count (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v); -+} -+ -+static inline unsigned dx_get_limit (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v); -+} -+ -+static inline void dx_set_count (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value); -+} -+ -+static inline void dx_set_limit (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value); -+} -+ -+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - -+ EXT3_DIR_REC_LEN(2) - infosize; -+ return 0? 20: entry_space / sizeof(struct dx_entry); -+} -+ -+static inline unsigned dx_node_limit (struct inode *dir) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); -+ return 0? 22: entry_space / sizeof(struct dx_entry); -+} -+ -+/* -+ * Debug -+ */ -+#ifdef DX_DEBUG -+struct stats -+{ -+ unsigned names; -+ unsigned space; -+ unsigned bcount; -+}; -+ -+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de, -+ int size, int show_names) -+{ -+ unsigned names = 0, space = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ printk("names: "); -+ while ((char *) de < base + size) -+ { -+ if (de->inode) -+ { -+ if (show_names) -+ { -+ int len = de->name_len; -+ char *name = de->name; -+ while (len--) printk("%c", *name++); -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ printk(":%x.%u ", h.hash, -+ ((char *) de - base)); -+ } -+ space += EXT3_DIR_REC_LEN(de->name_len); -+ names++; -+ } -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ printk("(%i)\n", names); -+ return (struct stats) { names, space, 1 }; -+} -+ -+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, -+ struct dx_entry *entries, int levels) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count = dx_get_count (entries), names = 0, space = 0, i; -+ unsigned bcount = 0; -+ struct buffer_head *bh; -+ int err; -+ printk("%i indexed blocks...\n", count); -+ for (i = 0; i < count; i++, entries++) -+ { -+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0; -+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; -+ struct stats stats; -+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); -+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue; -+ stats = levels? -+ dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): -+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) bh->b_data, blocksize, 0); -+ names += stats.names; -+ space += stats.space; -+ bcount += stats.bcount; -+ brelse (bh); -+ } -+ if (bcount) -+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ", -+ names, space/bcount,(space/bcount)*100/blocksize); -+ return (struct stats) { names, space, bcount}; -+} -+#endif /* DX_DEBUG */ -+ -+/* -+ * Probe for a directory leaf block to search. -+ * -+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format -+ * error in the directory index, and the caller should fall back to -+ * searching the directory normally. The callers of dx_probe **MUST** -+ * check for this error code, and make sure it never gets reflected -+ * back to userspace. -+ */ -+static struct dx_frame * -+dx_probe(struct dentry *dentry, struct inode *dir, -+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) -+{ -+ unsigned count, indirect; -+ struct dx_entry *at, *entries, *p, *q, *m; -+ struct dx_root *root; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+ -+ frame->bh = NULL; -+ if (dentry) -+ dir = dentry->d_parent->d_inode; -+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) -+ goto fail; -+ root = (struct dx_root *) bh->b_data; -+ if (root->info.hash_version != DX_HASH_TEA && -+ root->info.hash_version != DX_HASH_HALF_MD4 && -+ root->info.hash_version != DX_HASH_LEGACY) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unrecognised inode hash code %d", -+ root->info.hash_version); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ hinfo->hash_version = root->info.hash_version; -+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ if (dentry) -+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); -+ hash = hinfo->hash; -+ -+ if (root->info.unused_flags & 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash flags: %#06x", -+ root->info.unused_flags); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ if ((indirect = root->info.indirect_levels) > 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash depth: %#06x", -+ root->info.indirect_levels); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ entries = (struct dx_entry *) (((char *)&root->info) + -+ root->info.info_length); -+ assert(dx_get_limit(entries) == dx_root_limit(dir, -+ root->info.info_length)); -+ dxtrace (printk("Look up %x", hash)); -+ while (1) -+ { -+ count = dx_get_count(entries); -+ assert (count && count <= dx_get_limit(entries)); -+ p = entries + 1; -+ q = entries + count - 1; -+ while (p <= q) -+ { -+ m = p + (q - p)/2; -+ dxtrace(printk(".")); -+ if (dx_get_hash(m) > hash) -+ q = m - 1; -+ else -+ p = m + 1; -+ } -+ -+ if (0) // linear search cross check -+ { -+ unsigned n = count - 1; -+ at = entries; -+ while (n--) -+ { -+ dxtrace(printk(",")); -+ if (dx_get_hash(++at) > hash) -+ { -+ at--; -+ break; -+ } -+ } -+ assert (at == p - 1); -+ } -+ -+ at = p - 1; -+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); -+ frame->bh = bh; -+ frame->entries = entries; -+ frame->at = at; -+ if (!indirect--) return frame; -+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) -+ goto fail2; -+ at = entries = ((struct dx_node *) bh->b_data)->entries; -+ assert (dx_get_limit(entries) == dx_node_limit (dir)); -+ frame++; -+ } -+fail2: -+ while (frame >= frame_in) { -+ brelse(frame->bh); -+ frame--; -+ } -+fail: -+ return NULL; -+} -+ -+static void dx_release (struct dx_frame *frames) -+{ -+ if (frames[0].bh == NULL) -+ return; -+ -+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) -+ brelse(frames[1].bh); -+ brelse(frames[0].bh); -+} -+ -+/* -+ * This function increments the frame pointer to search the next leaf -+ * block, and reads in the necessary intervening nodes if the search -+ * should be necessary. Whether or not the search is necessary is -+ * controlled by the hash parameter. If the hash value is even, then -+ * the search is only continued if the next block starts with that -+ * hash value. This is used if we are searching for a specific file. -+ * -+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block. -+ * -+ * This function returns 1 if the caller should continue to search, -+ * or 0 if it should not. If there is an error reading one of the -+ * index blocks, it will return -1. -+ * -+ * If start_hash is non-null, it will be filled in with the starting -+ * hash of the next page. -+ */ -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash) -+{ -+ struct dx_frame *p; -+ struct buffer_head *bh; -+ int num_frames = 0; -+ __u32 bhash; -+ -+ *err = ENOENT; -+ p = frame; -+ /* -+ * Find the next leaf page by incrementing the frame pointer. -+ * If we run out of entries in the interior node, loop around and -+ * increment pointer in the parent node. When we break out of -+ * this loop, num_frames indicates the number of interior -+ * nodes need to be read. -+ */ -+ while (1) { -+ if (++(p->at) < p->entries + dx_get_count(p->entries)) -+ break; -+ if (p == frames) -+ return 0; -+ num_frames++; -+ p--; -+ } -+ -+ /* -+ * If the hash is 1, then continue only if the next page has a -+ * continuation hash of any value. This is used for readdir -+ * handling. Otherwise, check to see if the hash matches the -+ * desired contiuation hash. If it doesn't, return since -+ * there's no point to read in the successive index pages. -+ */ -+ bhash = dx_get_hash(p->at); -+ if (start_hash) -+ *start_hash = bhash; -+ if ((hash & 1) == 0) { -+ if ((bhash & ~1) != hash) -+ return 0; -+ } -+ /* -+ * If the hash is HASH_NB_ALWAYS, we always go to the next -+ * block so no check is necessary -+ */ -+ while (num_frames--) { -+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), -+ 0, err))) -+ return -1; /* Failure */ -+ p++; -+ brelse (p->bh); -+ p->bh = bh; -+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; -+ } -+ return 1; -+} -+ -+ -+/* -+ * p is at least 6 bytes before the end of page -+ */ -+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) -+{ -+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); -+} -+ -+/* -+ * This function fills a red-black tree with information from a -+ * directory. We start scanning the directory in hash order, starting -+ * at start_hash and start_minor_hash. -+ * -+ * This function returns the number of entries inserted into the tree, -+ * or a negative error code. -+ */ -+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash) -+{ -+ struct dx_hash_info hinfo; -+ struct buffer_head *bh; -+ struct ext3_dir_entry_2 *de, *top; -+ static struct dx_frame frames[2], *frame; -+ struct inode *dir; -+ int block, err; -+ int count = 0; -+ int ret; -+ __u32 hashval; -+ -+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, -+ start_minor_hash)); -+ dir = dir_file->f_dentry->d_inode; -+ hinfo.hash = start_hash; -+ hinfo.minor_hash = 0; -+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ -+ /* Add '.' and '..' from the htree header */ -+ if (!start_hash && !start_minor_hash) { -+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ de = ext3_next_entry(de); -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ count += 2; -+ } -+ -+ while (1) { -+ block = dx_get_block(frame->at); -+ dxtrace(printk("Reading block %d\n", block)); -+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) -+ goto errout; -+ -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) { -+ ext3fs_dirhash(de->name, de->name_len, &hinfo); -+ if ((hinfo.hash < start_hash) || -+ ((hinfo.hash == start_hash) && -+ (hinfo.minor_hash < start_minor_hash))) -+ continue; -+ if ((err = ext3_htree_store_dirent(dir_file, -+ hinfo.hash, hinfo.minor_hash, de)) != 0) -+ goto errout; -+ count++; -+ } -+ brelse (bh); -+ hashval = ~1; -+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, -+ frame, frames, &err, &hashval); -+ if (next_hash) -+ *next_hash = hashval; -+ if (ret == -1) -+ goto errout; -+ /* -+ * Stop if: (a) there are no more entries, or -+ * (b) we have inserted at least one entry and the -+ * next hash value is not a continuation -+ */ -+ if ((ret == 0) || -+ (count && ((hashval & 1) == 0))) -+ break; -+ } -+ dx_release(frames); -+ dxtrace(printk("Fill tree: returned %d entries\n", count)); -+ return count; -+errout: -+ dx_release(frames); -+ return (err); -+} -+ -+ -+/* -+ * Directory block splitting, compacting -+ */ -+ -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) -+{ -+ int count = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ while ((char *) de < base + size) -+ { -+ if (de->name_len && de->inode) { -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ map_tail--; -+ map_tail->hash = h.hash; -+ map_tail->offs = (u32) ((char *) de - base); -+ count++; -+ } -+ /* XXX: do we need to check rec_len == 0 case? -Chris */ -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ return count; -+} -+ -+static void dx_sort_map (struct dx_map_entry *map, unsigned count) -+{ -+ struct dx_map_entry *p, *q, *top = map + count - 1; -+ int more; -+ /* Combsort until bubble sort doesn't suck */ -+ while (count > 2) -+ { -+ count = count*10/13; -+ if (count - 9 < 2) /* 9, 10 -> 11 */ -+ count = 11; -+ for (p = top, q = p - count; q >= map; p--, q--) -+ if (p->hash < q->hash) -+ swap(*p, *q); -+ } -+ /* Garden variety bubble sort */ -+ do { -+ more = 0; -+ q = top; -+ while (q-- > map) -+ { -+ if (q[1].hash >= q[0].hash) -+ continue; -+ swap(*(q+1), *q); -+ more = 1; -+ } -+ } while(more); -+} -+ -+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) -+{ -+ struct dx_entry *entries = frame->entries; -+ struct dx_entry *old = frame->at, *new = old + 1; -+ int count = dx_get_count(entries); -+ -+ assert(count < dx_get_limit(entries)); -+ assert(old < entries + count); -+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new)); -+ dx_set_hash(new, hash); -+ dx_set_block(new, block); -+ dx_set_count(entries, count + 1); -+} -+#endif -+ -+ -+static void ext3_update_dx_flag(struct inode *inode) -+{ -+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb, -+ EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL; -+} -+ - /* - * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure. - * -@@ -96,6 +738,7 @@ - return 0; - } - -+ - /* - * ext3_find_entry() - * -@@ -107,6 +750,8 @@ - * The returned buffer_head has ->b_count elevated. The caller is expected - * to brelse() it when appropriate. - */ -+ -+ - static struct buffer_head * ext3_find_entry (struct dentry *dentry, - struct ext3_dir_entry_2 ** res_dir) - { -@@ -121,12 +766,32 @@ - int num = 0; - int nblocks, i, err; - struct inode *dir = dentry->d_parent->d_inode; -+ int namelen; -+ const u8 *name; -+ unsigned blocksize; - - *res_dir = NULL; - sb = dir->i_sb; -- -+ blocksize = sb->s_blocksize; -+ namelen = dentry->d_name.len; -+ name = dentry->d_name.name; -+ if (namelen > EXT3_NAME_LEN) -+ return NULL; -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ bh = ext3_dx_find_entry(dentry, res_dir, &err); -+ /* -+ * On success, or if the error was file not found, -+ * return. Otherwise, fall back to doing a search the -+ * old fashioned way. -+ */ -+ if (bh || (err != ERR_BAD_DX_DIR)) -+ return bh; -+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n")); -+ } -+#endif - nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb); -- start = dir->u.ext3_i.i_dir_start_lookup; -+ start = EXT3_I(dir)->i_dir_start_lookup; - if (start >= nblocks) - start = 0; - block = start; -@@ -167,7 +832,7 @@ - i = search_dirblock(bh, dir, dentry, - block << EXT3_BLOCK_SIZE_BITS(sb), res_dir); - if (i == 1) { -- dir->u.ext3_i.i_dir_start_lookup = block; -+ EXT3_I(dir)->i_dir_start_lookup = block; - ret = bh; - goto cleanup_and_exit; - } else { -@@ -198,6 +863,74 @@ - return ret; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err) -+{ -+ struct super_block * sb; -+ struct dx_hash_info hinfo; -+ u32 hash; -+ struct dx_frame frames[2], *frame; -+ struct ext3_dir_entry_2 *de, *top; -+ struct buffer_head *bh; -+ unsigned long block; -+ int retval; -+ int namelen = dentry->d_name.len; -+ const u8 *name = dentry->d_name.name; -+ struct inode *dir = dentry->d_parent->d_inode; -+ -+ sb = dir->i_sb; -+ /* NFS may look up ".." - look at dx_root directory block */ -+ if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){ -+ if (!(frame = dx_probe(dentry, 0, &hinfo, frames, err))) -+ return NULL; -+ } else { -+ frame = frames; -+ frame->bh = NULL; /* for dx_release() */ -+ frame->at = (struct dx_entry *)frames; /* hack for zero entry*/ -+ dx_set_block(frame->at, 0); /* dx_root block is 0 */ -+ } -+ hash = hinfo.hash; -+ do { -+ block = dx_get_block(frame->at); -+ if (!(bh = ext3_bread (NULL,dir, block, 0, err))) -+ goto errout; -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *)((char *)de + sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) -+ if (ext3_match (namelen, name, de)) { -+ if (!ext3_check_dir_entry("ext3_find_entry", -+ dir, de, bh, -+ (block<b_data))) { -+ brelse (bh); -+ goto errout; -+ } -+ *res_dir = de; -+ dx_release (frames); -+ return bh; -+ } -+ brelse (bh); -+ /* Check to see if we should continue to search */ -+ retval = ext3_htree_next_block(dir, hash, frame, -+ frames, err, 0); -+ if (retval == -1) { -+ ext3_warning(sb, __FUNCTION__, -+ "error reading index page in directory #%lu", -+ dir->i_ino); -+ goto errout; -+ } -+ } while (retval == 1); -+ -+ *err = -ENOENT; -+errout: -+ dxtrace(printk("%s not found\n", name)); -+ dx_release (frames); -+ return NULL; -+} -+#endif -+ - static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) - { - struct inode * inode; -@@ -214,8 +939,9 @@ - brelse (bh); - inode = iget(dir->i_sb, ino); - -- if (!inode) -+ if (!inode) { - return ERR_PTR(-EACCES); -+ } - } - d_add(dentry, inode); - return NULL; -@@ -239,6 +965,301 @@ - de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct ext3_dir_entry_2 * -+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) -+{ -+ unsigned rec_len = 0; -+ -+ while (count--) { -+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ memcpy (to, de, rec_len); -+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len); -+ de->inode = 0; -+ map++; -+ to += rec_len; -+ } -+ return (struct ext3_dir_entry_2 *) (to - rec_len); -+} -+ -+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) -+{ -+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; -+ unsigned rec_len = 0; -+ -+ prev = to = de; -+ while ((char*)de < base + size) { -+ next = (struct ext3_dir_entry_2 *) ((char *) de + -+ le16_to_cpu(de->rec_len)); -+ if (de->inode && de->name_len) { -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ if (de > to) -+ memmove(to, de, rec_len); -+ to->rec_len = cpu_to_le16(rec_len); -+ prev = to; -+ to = (struct ext3_dir_entry_2 *)((char *) to + rec_len); -+ } -+ de = next; -+ } -+ return prev; -+} -+ -+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, -+ struct buffer_head **bh,struct dx_frame *frame, -+ struct dx_hash_info *hinfo, int *error) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count, continued; -+ struct buffer_head *bh2; -+ u32 newblock; -+ u32 hash2; -+ struct dx_map_entry *map; -+ char *data1 = (*bh)->b_data, *data2; -+ unsigned split; -+ struct ext3_dir_entry_2 *de = NULL, *de2; -+ int err; -+ -+ bh2 = ext3_append (handle, dir, &newblock, error); -+ if (!(bh2)) { -+ brelse(*bh); -+ *bh = NULL; -+ goto errout; -+ } -+ -+ BUFFER_TRACE(*bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, *bh); -+ if (err) { -+ journal_error: -+ brelse(*bh); -+ brelse(bh2); -+ *bh = NULL; -+ ext3_std_error(dir->i_sb, err); -+ goto errout; -+ } -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ -+ data2 = bh2->b_data; -+ -+ /* create map in the end of data2 block */ -+ map = (struct dx_map_entry *) (data2 + blocksize); -+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1, -+ blocksize, hinfo, map); -+ map -= count; -+ split = count/2; // need to adjust to actual middle -+ dx_sort_map (map, count); -+ hash2 = map[split].hash; -+ continued = hash2 == map[split - 1].hash; -+ dxtrace(printk("Split block %i at %x, %i/%i\n", -+ dx_get_block(frame->at), hash2, split, count-split)); -+ -+ /* Fancy dance to stay within two buffers */ -+ de2 = dx_move_dirents(data1, data2, map + split, count - split); -+ de = dx_pack_dirents(data1,blocksize); -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); -+ -+ /* Which block gets the new entry? */ -+ if (hinfo->hash >= hash2) -+ { -+ swap(*bh, bh2); -+ de = de2; -+ } -+ dx_insert_block (frame, hash2 + continued, newblock); -+ err = ext3_journal_dirty_metadata (handle, bh2); -+ if (err) -+ goto journal_error; -+ err = ext3_journal_dirty_metadata (handle, frame->bh); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ dxtrace(dx_show_index ("frame", frame->entries)); -+errout: -+ return de; -+} -+#endif -+ -+ -+/* -+ * Add a new entry into a directory (leaf) block. If de is non-NULL, -+ * it points to a directory entry which is guaranteed to be large -+ * enough for new directory entry. If de is NULL, then -+ * add_dirent_to_buf will attempt search the directory block for -+ * space. It will return -ENOSPC if no space is available, and -EIO -+ * and -EEXIST if directory entry already exists. -+ * -+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In -+ * all other cases bh is released. -+ */ -+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct ext3_dir_entry_2 *de, -+ struct buffer_head * bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned long offset = 0; -+ unsigned short reclen; -+ int nlen, rlen, err; -+ char *top; -+ -+ reclen = EXT3_DIR_REC_LEN(namelen); -+ if (!de) { -+ de = (struct ext3_dir_entry_2 *)bh->b_data; -+ top = bh->b_data + dir->i_sb->s_blocksize - reclen; -+ while ((char *) de <= top) { -+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de, -+ bh, offset)) { -+ brelse (bh); -+ return -EIO; -+ } -+ if (ext3_match (namelen, name, de)) { -+ brelse (bh); -+ return -EEXIST; -+ } -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if ((de->inode? rlen - nlen: rlen) >= reclen) -+ break; -+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen); -+ offset += rlen; -+ } -+ if ((char *) de > top) -+ return -ENOSPC; -+ } -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) { -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return err; -+ } -+ -+ /* By now the buffer is marked for journaling */ -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if (de->inode) { -+ struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); -+ de1->rec_len = cpu_to_le16(rlen - nlen); -+ de->rec_len = cpu_to_le16(nlen); -+ de = de1; -+ } -+ de->file_type = EXT3_FT_UNKNOWN; -+ if (inode) { -+ de->inode = cpu_to_le32(inode->i_ino); -+ ext3_set_de_type(dir->i_sb, de, inode->i_mode); -+ } else -+ de->inode = 0; -+ de->name_len = namelen; -+ memcpy (de->name, name, namelen); -+ /* -+ * XXX shouldn't update any times until successful -+ * completion of syscall, but too many callers depend -+ * on this. -+ * -+ * XXX similarly, too many callers depend on -+ * ext3_new_inode() setting the times, but error -+ * recovery deletes the inode, so the worst that can -+ * happen is that the times are slightly out of date -+ * and/or different from the directory change time. -+ */ -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME; -+ ext3_update_dx_flag(dir); -+ dir->i_version = ++event; -+ ext3_mark_inode_dirty(handle, dir); -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return 0; -+} -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * This converts a one block unindexed directory to a 3 block indexed -+ * directory, and adds the dentry to the indexed directory. -+ */ -+static int make_indexed_dir(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct buffer_head *bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+ struct dx_root *root; -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries; -+ struct ext3_dir_entry_2 *de, *de2; -+ char *data1, *top; -+ unsigned len; -+ int retval; -+ unsigned blocksize; -+ struct dx_hash_info hinfo; -+ u32 block; -+ -+ blocksize = dir->i_sb->s_blocksize; -+ dxtrace(printk("Creating index\n")); -+ retval = ext3_journal_get_write_access(handle, bh); -+ if (retval) { -+ ext3_std_error(dir->i_sb, retval); -+ brelse(bh); -+ return retval; -+ } -+ root = (struct dx_root *) bh->b_data; -+ -+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; -+ bh2 = ext3_append (handle, dir, &block, &retval); -+ if (!(bh2)) { -+ brelse(bh); -+ return retval; -+ } -+ data1 = bh2->b_data; -+ -+ /* The 0th block becomes the root, move the dirents out */ -+ de = (struct ext3_dir_entry_2 *)&root->dotdot; -+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len)); -+ len = ((char *) root) + blocksize - (char *) de; -+ memcpy (data1, de, len); -+ de = (struct ext3_dir_entry_2 *) data1; -+ top = data1 + len; -+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top) -+ de = de2; -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ /* Initialize the root; the dot dirents already exist */ -+ de = (struct ext3_dir_entry_2 *) (&root->dotdot); -+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); -+ memset (&root->info, 0, sizeof(root->info)); -+ root->info.info_length = sizeof(root->info); -+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version; -+ entries = root->entries; -+ dx_set_block (entries, 1); -+ dx_set_count (entries, 1); -+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info))); -+ -+ /* Initialize as for dx_probe */ -+ hinfo.hash_version = root->info.hash_version; -+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ ext3fs_dirhash(name, namelen, &hinfo); -+ frame = frames; -+ frame->entries = entries; -+ frame->at = entries; -+ frame->bh = bh; -+ bh = bh2; -+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval); -+ dx_release (frames); -+ if (!(de)) -+ return retval; -+ -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} -+#endif -+ - /* - * ext3_add_entry() - * -@@ -249,127 +1270,198 @@ - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -- --/* -- * AKPM: the journalling code here looks wrong on the error paths -- */ - static int ext3_add_entry (handle_t *handle, struct dentry *dentry, - struct inode *inode) - { - struct inode *dir = dentry->d_parent->d_inode; -- const char *name = dentry->d_name.name; -- int namelen = dentry->d_name.len; - unsigned long offset; -- unsigned short rec_len; - struct buffer_head * bh; -- struct ext3_dir_entry_2 * de, * de1; -+ struct ext3_dir_entry_2 *de; - struct super_block * sb; - int retval; -+#ifdef CONFIG_EXT3_INDEX -+ int dx_fallback=0; -+#endif -+ unsigned blocksize; -+ unsigned nlen, rlen; -+ u32 block, blocks; - - sb = dir->i_sb; -- -- if (!namelen) -+ blocksize = sb->s_blocksize; -+ if (!dentry->d_name.len) - return -EINVAL; -- bh = ext3_bread (handle, dir, 0, 0, &retval); -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ retval = ext3_dx_add_entry(handle, dentry, inode); -+ if (!retval || (retval != ERR_BAD_DX_DIR)) -+ return retval; -+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; -+ dx_fallback++; -+ ext3_mark_inode_dirty(handle, dir); -+ } -+#endif -+ blocks = dir->i_size >> sb->s_blocksize_bits; -+ for (block = 0, offset = 0; block < blocks; block++) { -+ bh = ext3_bread(handle, dir, block, 0, &retval); -+ if(!bh) -+ return retval; -+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (retval != -ENOSPC) -+ return retval; -+ -+#ifdef CONFIG_EXT3_INDEX -+ if (blocks == 1 && !dx_fallback && -+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ return make_indexed_dir(handle, dentry, inode, bh); -+#endif -+ brelse(bh); -+ } -+ bh = ext3_append(handle, dir, &block, &retval); - if (!bh) - return retval; -- rec_len = EXT3_DIR_REC_LEN(namelen); -- offset = 0; - de = (struct ext3_dir_entry_2 *) bh->b_data; -- while (1) { -- if ((char *)de >= sb->s_blocksize + bh->b_data) { -- brelse (bh); -- bh = NULL; -- bh = ext3_bread (handle, dir, -- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval); -- if (!bh) -- return retval; -- if (dir->i_size <= offset) { -- if (dir->i_size == 0) { -- brelse(bh); -- return -ENOENT; -- } -+ de->inode = 0; -+ de->rec_len = cpu_to_le16(rlen = blocksize); -+ nlen = 0; -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} - -- ext3_debug ("creating next block\n"); -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * Returns 0 for success, or a negative error value -+ */ -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries, *at; -+ struct dx_hash_info hinfo; -+ struct buffer_head * bh; -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct super_block * sb = dir->i_sb; -+ struct ext3_dir_entry_2 *de; -+ int err; - -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- de->inode = 0; -- de->rec_len = le16_to_cpu(sb->s_blocksize); -- dir->u.ext3_i.i_disksize = -- dir->i_size = offset + sb->s_blocksize; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- ext3_mark_inode_dirty(handle, dir); -- } else { -+ frame = dx_probe(dentry, 0, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ entries = frame->entries; -+ at = frame->at; - -- ext3_debug ("skipping to next block\n"); -+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) -+ goto cleanup; - -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- } -- } -- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh, -- offset)) { -- brelse (bh); -- return -ENOENT; -- } -- if (ext3_match (namelen, name, de)) { -- brelse (bh); -- return -EEXIST; -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) -+ goto journal_error; -+ -+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (err != -ENOSPC) { -+ bh = 0; -+ goto cleanup; -+ } -+ -+ /* Block full, should compress but for now just split */ -+ dxtrace(printk("using %u of %u node entries\n", -+ dx_get_count(entries), dx_get_limit(entries))); -+ /* Need to split index? */ -+ if (dx_get_count(entries) == dx_get_limit(entries)) { -+ u32 newblock; -+ unsigned icount = dx_get_count(entries); -+ int levels = frame - frames; -+ struct dx_entry *entries2; -+ struct dx_node *node2; -+ struct buffer_head *bh2; -+ -+ if (levels && (dx_get_count(frames->entries) == -+ dx_get_limit(frames->entries))) { -+ ext3_warning(sb, __FUNCTION__, -+ "Directory index full!\n"); -+ err = -ENOSPC; -+ goto cleanup; - } -- if ((le32_to_cpu(de->inode) == 0 && -- le16_to_cpu(de->rec_len) >= rec_len) || -- (le16_to_cpu(de->rec_len) >= -- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) { -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- /* By now the buffer is marked for journaling */ -- offset += le16_to_cpu(de->rec_len); -- if (le32_to_cpu(de->inode)) { -- de1 = (struct ext3_dir_entry_2 *) ((char *) de + -- EXT3_DIR_REC_LEN(de->name_len)); -- de1->rec_len = -- cpu_to_le16(le16_to_cpu(de->rec_len) - -- EXT3_DIR_REC_LEN(de->name_len)); -- de->rec_len = cpu_to_le16( -- EXT3_DIR_REC_LEN(de->name_len)); -- de = de1; -+ bh2 = ext3_append (handle, dir, &newblock, &err); -+ if (!(bh2)) -+ goto cleanup; -+ node2 = (struct dx_node *)(bh2->b_data); -+ entries2 = node2->entries; -+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); -+ node2->fake.inode = 0; -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ if (levels) { -+ unsigned icount1 = icount/2, icount2 = icount - icount1; -+ unsigned hash2 = dx_get_hash(entries + icount1); -+ dxtrace(printk("Split index %i/%i\n", icount1, icount2)); -+ -+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ -+ err = ext3_journal_get_write_access(handle, -+ frames[0].bh); -+ if (err) -+ goto journal_error; -+ -+ memcpy ((char *) entries2, (char *) (entries + icount1), -+ icount2 * sizeof(struct dx_entry)); -+ dx_set_count (entries, icount1); -+ dx_set_count (entries2, icount2); -+ dx_set_limit (entries2, dx_node_limit(dir)); -+ -+ /* Which index block gets the new entry? */ -+ if (at - entries >= icount1) { -+ frame->at = at = at - entries - icount1 + entries2; -+ frame->entries = entries = entries2; -+ swap(frame->bh, bh2); - } -- de->file_type = EXT3_FT_UNKNOWN; -- if (inode) { -- de->inode = cpu_to_le32(inode->i_ino); -- ext3_set_de_type(dir->i_sb, de, inode->i_mode); -- } else -- de->inode = 0; -- de->name_len = namelen; -- memcpy (de->name, name, namelen); -- /* -- * XXX shouldn't update any times until successful -- * completion of syscall, but too many callers depend -- * on this. -- * -- * XXX similarly, too many callers depend on -- * ext3_new_inode() setting the times, but error -- * recovery deletes the inode, so the worst that can -- * happen is that the times are slightly out of date -- * and/or different from the directory change time. -- */ -- dir->i_mtime = dir->i_ctime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- dir->i_version = ++event; -- ext3_mark_inode_dirty(handle, dir); -- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -- ext3_journal_dirty_metadata(handle, bh); -- brelse(bh); -- return 0; -+ dx_insert_block (frames + 0, hash2, newblock); -+ dxtrace(dx_show_index ("node", frames[1].entries)); -+ dxtrace(dx_show_index ("node", -+ ((struct dx_node *) bh2->b_data)->entries)); -+ err = ext3_journal_dirty_metadata(handle, bh2); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ } else { -+ dxtrace(printk("Creating second level index...\n")); -+ memcpy((char *) entries2, (char *) entries, -+ icount * sizeof(struct dx_entry)); -+ dx_set_limit(entries2, dx_node_limit(dir)); -+ -+ /* Set up root */ -+ dx_set_count(entries, 1); -+ dx_set_block(entries + 0, newblock); -+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; -+ -+ /* Add new access path frame */ -+ frame = frames + 1; -+ frame->at = at = at - entries + entries2; -+ frame->entries = entries = entries2; -+ frame->bh = bh2; -+ err = ext3_journal_get_write_access(handle, -+ frame->bh); -+ if (err) -+ goto journal_error; - } -- offset += le16_to_cpu(de->rec_len); -- de = (struct ext3_dir_entry_2 *) -- ((char *) de + le16_to_cpu(de->rec_len)); -+ ext3_journal_dirty_metadata(handle, frames[0].bh); - } -- brelse (bh); -- return -ENOSPC; -+ de = do_split(handle, dir, &bh, frame, &hinfo, &err); -+ if (!de) -+ goto cleanup; -+ err = add_dirent_to_buf(handle, dentry, inode, de, bh); -+ bh = 0; -+ goto cleanup; -+ -+journal_error: -+ ext3_std_error(dir->i_sb, err); -+cleanup: -+ if (bh) -+ brelse(bh); -+ dx_release(frames); -+ return err; - } -+#endif - - /* - * ext3_delete_entry deletes a directory entry by merging it with the -@@ -456,9 +1548,11 @@ - struct inode * inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -482,9 +1576,11 @@ - struct inode *inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -513,9 +1609,11 @@ - if (dir->i_nlink >= EXT3_LINK_MAX) - return -EMLINK; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -527,7 +1625,7 @@ - - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; -- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize; -+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ -@@ -556,21 +1654,19 @@ - brelse (dir_block); - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); -- if (err) -- goto out_no_entry; -+ if (err) { -+ inode->i_nlink = 0; -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - dir->i_nlink++; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- inode->i_nlink = 0; -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - /* -@@ -657,7 +1753,7 @@ - int err = 0, rc; - - lock_super(sb); -- if (!list_empty(&inode->u.ext3_i.i_orphan)) -+ if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - - /* Orphan handling is only valid for files with data blocks -@@ -698,7 +1794,7 @@ - * This is safe: on error we're going to ignore the orphan list - * anyway on the next recovery. */ - if (!err) -- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan); -+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", -@@ -716,25 +1812,26 @@ - int ext3_orphan_del(handle_t *handle, struct inode *inode) - { - struct list_head *prev; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_sb_info *sbi; - unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; - - lock_super(inode->i_sb); -- if (list_empty(&inode->u.ext3_i.i_orphan)) { -+ if (list_empty(&ei->i_orphan)) { - unlock_super(inode->i_sb); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); -- prev = inode->u.ext3_i.i_orphan.prev; -+ prev = ei->i_orphan.prev; - sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - -- list_del(&inode->u.ext3_i.i_orphan); -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ list_del(&ei->i_orphan); -+ INIT_LIST_HEAD(&ei->i_orphan); - - /* If we're on an error path, we may not have a valid - * transaction handle with which to update the orphan list on -@@ -795,8 +1892,9 @@ - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - retval = -ENOENT; - bh = ext3_find_entry (dentry, &de); -@@ -834,7 +1932,7 @@ - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - - end_rmdir: -@@ -852,8 +1950,9 @@ - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -880,7 +1979,7 @@ - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; - if (!inode->i_nlink) -@@ -906,9 +2005,11 @@ - if (l > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -918,7 +2019,7 @@ - if (IS_ERR(inode)) - goto out_stop; - -- if (l > sizeof (inode->u.ext3_i.i_data)) { -+ if (l > sizeof (EXT3_I(inode)->i_data)) { - inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* -@@ -927,24 +2028,22 @@ - * i_size in generic_commit_write(). - */ - err = block_symlink(inode, symname, l); -- if (err) -- goto out_no_entry; -+ if (err) { -+ ext3_dec_count(handle, inode); -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - } else { - inode->i_op = &ext3_fast_symlink_inode_operations; -- memcpy((char*)&inode->u.ext3_i.i_data,symname,l); -+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l); - inode->i_size = l-1; - } -- inode->u.ext3_i.i_disksize = inode->i_size; -+ EXT3_I(inode)->i_disksize = inode->i_size; - err = ext3_add_nondir(handle, dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- ext3_dec_count(handle, inode); -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - static int ext3_link (struct dentry * old_dentry, -@@ -957,12 +2056,15 @@ - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) -+ if (inode->i_nlink >= EXT3_LINK_MAX) { - return -EMLINK; -+ } - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -995,9 +2097,11 @@ - - old_bh = new_bh = dir_bh = NULL; - -- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(old_dir) || IS_SYNC(new_dir)) - handle->h_sync = 1; -@@ -1070,14 +2174,37 @@ - /* - * ok, that's it - */ -- ext3_delete_entry(handle, old_dir, old_de, old_bh); -+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino || -+ old_de->name_len != old_dentry->d_name.len || -+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || -+ (retval = ext3_delete_entry(handle, old_dir, -+ old_de, old_bh)) == -ENOENT) { -+ /* old_de could have moved from under us during htree split, so -+ * make sure that we are deleting the right entry. We might -+ * also be pointing to a stale entry in the unused part of -+ * old_bh so just checking inum and the name isn't enough. */ -+ struct buffer_head *old_bh2; -+ struct ext3_dir_entry_2 *old_de2; -+ -+ old_bh2 = ext3_find_entry(old_dentry, &old_de2); -+ if (old_bh2) { -+ retval = ext3_delete_entry(handle, old_dir, -+ old_de2, old_bh2); -+ brelse(old_bh2); -+ } -+ } -+ if (retval) { -+ ext3_warning(old_dir->i_sb, "ext3_rename", -+ "Deleting old file (%lu), %d, error=%d", -+ old_dir->i_ino, old_dir->i_nlink, retval); -+ } - - if (new_inode) { - new_inode->i_nlink--; - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(old_dir); - if (dir_bh) { - BUFFER_TRACE(dir_bh, "get_write_access"); - ext3_journal_get_write_access(handle, dir_bh); -@@ -1089,7 +2216,7 @@ - new_inode->i_nlink--; - } else { - new_dir->i_nlink++; -- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } - } -Index: linux-2.4.21/fs/ext3/super.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/super.c 2004-09-16 19:21:00.000000000 -0400 -+++ linux-2.4.21/fs/ext3/super.c 2004-09-16 19:40:16.000000000 -0400 -@@ -777,6 +777,7 @@ - es->s_mtime = cpu_to_le32(CURRENT_TIME); - ext3_update_dynamic_rev(sb); - EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -+ - ext3_commit_super (sb, es, 1); - if (test_opt (sb, DEBUG)) - printk (KERN_INFO -@@ -787,6 +788,7 @@ - EXT3_BLOCKS_PER_GROUP(sb), - EXT3_INODES_PER_GROUP(sb), - sbi->s_mount_opt); -+ - printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ", - bdevname(sb->s_dev)); - if (EXT3_SB(sb)->s_journal->j_inode == NULL) { -@@ -960,6 +962,7 @@ - return res; - } - -+ - struct super_block * ext3_read_super (struct super_block * sb, void * data, - int silent) - { -@@ -1146,6 +1149,9 @@ - sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); -+ for (i=0; i < 4; i++) -+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); -+ sbi->s_def_hash_version = es->s_def_hash_version; - - if (sbi->s_blocks_per_group > blocksize * 8) { - printk (KERN_ERR -@@ -1938,6 +1944,7 @@ - unregister_filesystem(&ext3_fs_type); - } - -+EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); -Index: linux-2.4.21/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21.orig/include/linux/ext3_fs.h 2004-09-11 10:16:28.000000000 -0400 -+++ linux-2.4.21/include/linux/ext3_fs.h 2004-09-16 19:40:16.000000000 -0400 -@@ -40,6 +40,11 @@ - #define EXT3FS_VERSION "2.4-0.9.19" - - /* -+ * Always enable hashed directories -+ */ -+#define CONFIG_EXT3_INDEX -+ -+/* - * Debug code - */ - #ifdef EXT3FS_DEBUG -@@ -415,8 +420,11 @@ - /*E0*/ __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ -- --/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */ -+ __u32 s_hash_seed[4]; /* HTREE hash seed */ -+ __u8 s_def_hash_version; /* Default hash version to use */ -+ __u8 s_reserved_char_pad; -+ __u16 s_reserved_word_pad; -+ __u32 s_reserved[192]; /* Padding to the end of the block */ - }; - - #ifdef __KERNEL__ -@@ -553,9 +561,46 @@ - #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) - #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ - ~EXT3_DIR_ROUND) -+/* -+ * Hash Tree Directory indexing -+ * (c) Daniel Phillips, 2001 -+ */ -+ -+#ifdef CONFIG_EXT3_INDEX -+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \ -+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \ -+ (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) -+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) -+#else -+ #define is_dx(dir) 0 -+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2) -+#endif -+ -+/* Legal values for the dx_root hash_version field: */ -+ -+#define DX_HASH_LEGACY 0 -+#define DX_HASH_HALF_MD4 1 -+#define DX_HASH_TEA 2 -+ -+/* hash info structure used by the directory hash */ -+struct dx_hash_info -+{ -+ u32 hash; -+ u32 minor_hash; -+ int hash_version; -+ u32 *seed; -+}; - - #ifdef __KERNEL__ - /* -+ * Control parameters used by ext3_htree_next_block -+ */ -+#define HASH_NB_ALWAYS 1 -+ -+ -+/* - * Describe an inode's exact location on disk and in memory - */ - struct ext3_iloc -@@ -565,6 +610,27 @@ - unsigned long block_group; - }; - -+ -+/* -+ * This structure is stuffed into the struct file's private_data field -+ * for directories. It is where we put information so that we can do -+ * readdir operations in hash tree order. -+ */ -+struct dir_private_info { -+ rb_root_t root; -+ rb_node_t *curr_node; -+ struct fname *extra_fname; -+ loff_t last_pos; -+ __u32 curr_hash; -+ __u32 curr_minor_hash; -+ __u32 next_hash; -+}; -+ -+/* -+ * Special error return code only used by dx_probe() and its callers. -+ */ -+#define ERR_BAD_DX_DIR -75000 -+ - /* - * Function prototypes - */ -@@ -592,11 +658,20 @@ - - /* dir.c */ - extern int ext3_check_dir_entry(const char *, struct inode *, -- struct ext3_dir_entry_2 *, struct buffer_head *, -- unsigned long); -+ struct ext3_dir_entry_2 *, -+ struct buffer_head *, unsigned long); -+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent); -+extern void ext3_htree_free_dir_info(struct dir_private_info *p); -+ - /* fsync.c */ - extern int ext3_sync_file (struct file *, struct dentry *, int); - -+/* hash.c */ -+extern int ext3fs_dirhash(const char *name, int len, struct -+ dx_hash_info *hinfo); -+ - /* ialloc.c */ - extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); - extern void ext3_free_inode (handle_t *, struct inode *); -@@ -630,6 +705,8 @@ - /* namei.c */ - extern int ext3_orphan_add(handle_t *, struct inode *); - extern int ext3_orphan_del(handle_t *, struct inode *); -+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash); - - /* super.c */ - extern void ext3_error (struct super_block *, const char *, const char *, ...) -Index: linux-2.4.21/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.21.orig/include/linux/ext3_fs_sb.h 2004-09-11 10:16:39.000000000 -0400 -+++ linux-2.4.21/include/linux/ext3_fs_sb.h 2004-09-16 19:40:16.000000000 -0400 -@@ -62,6 +62,8 @@ - int s_inode_size; - int s_first_ino; - u32 s_next_generation; -+ u32 s_hash_seed[4]; -+ int s_def_hash_version; - - /* Journaling */ - struct inode * s_journal_inode; -Index: linux-2.4.21/include/linux/ext3_jbd.h -=================================================================== ---- linux-2.4.21.orig/include/linux/ext3_jbd.h 2004-09-11 10:16:39.000000000 -0400 -+++ linux-2.4.21/include/linux/ext3_jbd.h 2004-09-16 19:40:16.000000000 -0400 -@@ -69,6 +69,8 @@ - - #define EXT3_RESERVE_TRANS_BLOCKS 12U - -+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 -+ - int - ext3_mark_iloc_dirty(handle_t *handle, - struct inode *inode, diff --git a/lustre/kernel_patches/patches/ext3-htree-2.4.22-rh.patch b/lustre/kernel_patches/patches/ext3-htree-2.4.22-rh.patch deleted file mode 100644 index 7895513..0000000 --- a/lustre/kernel_patches/patches/ext3-htree-2.4.22-rh.patch +++ /dev/null @@ -1,2581 +0,0 @@ - fs/ext3/Makefile | 2 - fs/ext3/dir.c | 302 +++++++++ - fs/ext3/file.c | 3 - fs/ext3/hash.c | 215 ++++++ - fs/ext3/namei.c | 1421 ++++++++++++++++++++++++++++++++++++++++----- - fs/ext3/super.c | 7 - include/linux/ext3_fs.h | 85 ++ - include/linux/ext3_fs_sb.h | 2 - include/linux/ext3_jbd.h | 2 - include/linux/rbtree.h | 2 - lib/rbtree.c | 42 + - 11 files changed, 1922 insertions(+), 161 deletions(-) - ---- linux-2.4.22-ac1/fs/ext3/dir.c~ext3-htree-2.4.22-rh 2001-11-10 01:25:04.000000000 +0300 -+++ linux-2.4.22-ac1-alexey/fs/ext3/dir.c 2003-09-25 14:58:30.000000000 +0400 -@@ -21,12 +21,16 @@ - #include - #include - #include -+#include -+#include - - static unsigned char ext3_filetype_table[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK - }; - - static int ext3_readdir(struct file *, void *, filldir_t); -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir); - - struct file_operations ext3_dir_operations = { - read: generic_read_dir, -@@ -35,6 +39,17 @@ struct file_operations ext3_dir_operatio - fsync: ext3_sync_file, /* BKL held */ - }; - -+ -+static unsigned char get_dtype(struct super_block *sb, int filetype) -+{ -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) || -+ (filetype >= EXT3_FT_MAX)) -+ return DT_UNKNOWN; -+ -+ return (ext3_filetype_table[filetype]); -+} -+ -+ - int ext3_check_dir_entry (const char * function, struct inode * dir, - struct ext3_dir_entry_2 * de, - struct buffer_head * bh, -@@ -79,6 +94,16 @@ static int ext3_readdir(struct file * fi - - sb = inode->i_sb; - -+ if (is_dx(inode)) { -+ err = ext3_dx_readdir(filp, dirent, filldir); -+ if (err != ERR_BAD_DX_DIR) -+ return err; -+ /* -+ * We don't set the inode dirty flag since it's not -+ * critical that it get flushed back to the disk. -+ */ -+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; -+ } - stored = 0; - bh = NULL; - offset = filp->f_pos & (sb->s_blocksize - 1); -@@ -162,18 +187,12 @@ revalidate: - * during the copy operation. - */ - unsigned long version = filp->f_version; -- unsigned char d_type = DT_UNKNOWN; - -- if (EXT3_HAS_INCOMPAT_FEATURE(sb, -- EXT3_FEATURE_INCOMPAT_FILETYPE) -- && de->file_type < EXT3_FT_MAX) -- d_type = -- ext3_filetype_table[de->file_type]; - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, - le32_to_cpu(de->inode), -- d_type); -+ get_dtype(sb, de->file_type)); - if (error) - break; - if (version != filp->f_version) -@@ -188,3 +207,272 @@ revalidate: - UPDATE_ATIME(inode); - return 0; - } -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * These functions convert from the major/minor hash to an f_pos -+ * value. -+ * -+ * Currently we only use major hash numer. This is unfortunate, but -+ * on 32-bit machines, the same VFS interface is used for lseek and -+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of -+ * lseek/telldir/seekdir will blow out spectacularly, and from within -+ * the ext2 low-level routine, we don't know if we're being called by -+ * a 64-bit version of the system call or the 32-bit version of the -+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir -+ * cookie. Sigh. -+ */ -+#define hash2pos(major, minor) (major >> 1) -+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) -+#define pos2min_hash(pos) (0) -+ -+/* -+ * This structure holds the nodes of the red-black tree used to store -+ * the directory entry in hash order. -+ */ -+struct fname { -+ __u32 hash; -+ __u32 minor_hash; -+ rb_node_t rb_hash; -+ struct fname *next; -+ __u32 inode; -+ __u8 name_len; -+ __u8 file_type; -+ char name[0]; -+}; -+ -+/* -+ * This functoin implements a non-recursive way of freeing all of the -+ * nodes in the red-black tree. -+ */ -+static void free_rb_tree_fname(rb_root_t *root) -+{ -+ rb_node_t *n = root->rb_node; -+ rb_node_t *parent; -+ struct fname *fname; -+ -+ while (n) { -+ /* Do the node's children first */ -+ if ((n)->rb_left) { -+ n = n->rb_left; -+ continue; -+ } -+ if (n->rb_right) { -+ n = n->rb_right; -+ continue; -+ } -+ /* -+ * The node has no children; free it, and then zero -+ * out parent's link to it. Finally go to the -+ * beginning of the loop and try to free the parent -+ * node. -+ */ -+ parent = n->rb_parent; -+ fname = rb_entry(n, struct fname, rb_hash); -+ kfree(fname); -+ if (!parent) -+ root->rb_node = 0; -+ else if (parent->rb_left == n) -+ parent->rb_left = 0; -+ else if (parent->rb_right == n) -+ parent->rb_right = 0; -+ n = parent; -+ } -+ root->rb_node = 0; -+} -+ -+ -+struct dir_private_info *create_dir_info(loff_t pos) -+{ -+ struct dir_private_info *p; -+ -+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL); -+ if (!p) -+ return NULL; -+ p->root.rb_node = 0; -+ p->curr_node = 0; -+ p->extra_fname = 0; -+ p->last_pos = 0; -+ p->curr_hash = pos2maj_hash(pos); -+ p->curr_minor_hash = pos2min_hash(pos); -+ p->next_hash = 0; -+ return p; -+} -+ -+void ext3_htree_free_dir_info(struct dir_private_info *p) -+{ -+ free_rb_tree_fname(&p->root); -+ kfree(p); -+} -+ -+/* -+ * Given a directory entry, enter it into the fname rb tree. -+ */ -+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent) -+{ -+ rb_node_t **p, *parent = NULL; -+ struct fname * fname, *new_fn; -+ struct dir_private_info *info; -+ int len; -+ -+ info = (struct dir_private_info *) dir_file->private_data; -+ p = &info->root.rb_node; -+ -+ /* Create and allocate the fname structure */ -+ len = sizeof(struct fname) + dirent->name_len + 1; -+ new_fn = kmalloc(len, GFP_KERNEL); -+ if (!new_fn) -+ return -ENOMEM; -+ memset(new_fn, 0, len); -+ new_fn->hash = hash; -+ new_fn->minor_hash = minor_hash; -+ new_fn->inode = le32_to_cpu(dirent->inode); -+ new_fn->name_len = dirent->name_len; -+ new_fn->file_type = dirent->file_type; -+ memcpy(new_fn->name, dirent->name, dirent->name_len); -+ new_fn->name[dirent->name_len] = 0; -+ -+ while (*p) { -+ parent = *p; -+ fname = rb_entry(parent, struct fname, rb_hash); -+ -+ /* -+ * If the hash and minor hash match up, then we put -+ * them on a linked list. This rarely happens... -+ */ -+ if ((new_fn->hash == fname->hash) && -+ (new_fn->minor_hash == fname->minor_hash)) { -+ new_fn->next = fname->next; -+ fname->next = new_fn; -+ return 0; -+ } -+ -+ if (new_fn->hash < fname->hash) -+ p = &(*p)->rb_left; -+ else if (new_fn->hash > fname->hash) -+ p = &(*p)->rb_right; -+ else if (new_fn->minor_hash < fname->minor_hash) -+ p = &(*p)->rb_left; -+ else /* if (new_fn->minor_hash > fname->minor_hash) */ -+ p = &(*p)->rb_right; -+ } -+ -+ rb_link_node(&new_fn->rb_hash, parent, p); -+ rb_insert_color(&new_fn->rb_hash, &info->root); -+ return 0; -+} -+ -+ -+ -+/* -+ * This is a helper function for ext3_dx_readdir. It calls filldir -+ * for all entres on the fname linked list. (Normally there is only -+ * one entry on the linked list, unless there are 62 bit hash collisions.) -+ */ -+static int call_filldir(struct file * filp, void * dirent, -+ filldir_t filldir, struct fname *fname) -+{ -+ struct dir_private_info *info = filp->private_data; -+ loff_t curr_pos; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct super_block * sb; -+ int error; -+ -+ sb = inode->i_sb; -+ -+ if (!fname) { -+ printk("call_filldir: called with null fname?!?\n"); -+ return 0; -+ } -+ curr_pos = hash2pos(fname->hash, fname->minor_hash); -+ while (fname) { -+ error = filldir(dirent, fname->name, -+ fname->name_len, curr_pos, -+ fname->inode, -+ get_dtype(sb, fname->file_type)); -+ if (error) { -+ filp->f_pos = curr_pos; -+ info->extra_fname = fname->next; -+ return error; -+ } -+ fname = fname->next; -+ } -+ return 0; -+} -+ -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir) -+{ -+ struct dir_private_info *info = filp->private_data; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct fname *fname; -+ int ret; -+ -+ if (!info) { -+ info = create_dir_info(filp->f_pos); -+ if (!info) -+ return -ENOMEM; -+ filp->private_data = info; -+ } -+ -+ /* Some one has messed with f_pos; reset the world */ -+ if (info->last_pos != filp->f_pos) { -+ free_rb_tree_fname(&info->root); -+ info->curr_node = 0; -+ info->extra_fname = 0; -+ info->curr_hash = pos2maj_hash(filp->f_pos); -+ info->curr_minor_hash = pos2min_hash(filp->f_pos); -+ } -+ -+ /* -+ * If there are any leftover names on the hash collision -+ * chain, return them first. -+ */ -+ if (info->extra_fname && -+ call_filldir(filp, dirent, filldir, info->extra_fname)) -+ goto finished; -+ -+ if (!info->curr_node) -+ info->curr_node = rb_get_first(&info->root); -+ -+ while (1) { -+ /* -+ * Fill the rbtree if we have no more entries, -+ * or the inode has changed since we last read in the -+ * cached entries. -+ */ -+ if ((!info->curr_node) || -+ (filp->f_version != inode->i_version)) { -+ info->curr_node = 0; -+ free_rb_tree_fname(&info->root); -+ filp->f_version = inode->i_version; -+ ret = ext3_htree_fill_tree(filp, info->curr_hash, -+ info->curr_minor_hash, -+ &info->next_hash); -+ if (ret < 0) -+ return ret; -+ if (ret == 0) -+ break; -+ info->curr_node = rb_get_first(&info->root); -+ } -+ -+ fname = rb_entry(info->curr_node, struct fname, rb_hash); -+ info->curr_hash = fname->hash; -+ info->curr_minor_hash = fname->minor_hash; -+ if (call_filldir(filp, dirent, filldir, fname)) -+ break; -+ -+ info->curr_node = rb_get_next(info->curr_node); -+ if (!info->curr_node) { -+ info->curr_hash = info->next_hash; -+ info->curr_minor_hash = 0; -+ } -+ } -+finished: -+ info->last_pos = filp->f_pos; -+ UPDATE_ATIME(inode); -+ return 0; -+} -+#endif ---- linux-2.4.22-ac1/fs/ext3/file.c~ext3-htree-2.4.22-rh 2003-08-25 15:44:43.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/file.c 2003-09-25 14:55:12.000000000 +0400 -@@ -35,6 +35,9 @@ static int ext3_release_file (struct ino - { - if (filp->f_mode & FMODE_WRITE) - ext3_discard_prealloc (inode); -+ if (is_dx(inode) && filp->private_data) -+ ext3_htree_free_dir_info(filp->private_data); -+ - return 0; - } - ---- /dev/null 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.22-ac1-alexey/fs/ext3/hash.c 2003-09-25 14:55:12.000000000 +0400 -@@ -0,0 +1,215 @@ -+/* -+ * linux/fs/ext3/hash.c -+ * -+ * Copyright (C) 2002 by Theodore Ts'o -+ * -+ * This file is released under the GPL v2. -+ * -+ * This file may be redistributed under the terms of the GNU Public -+ * License. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define DELTA 0x9E3779B9 -+ -+static void TEA_transform(__u32 buf[4], __u32 const in[]) -+{ -+ __u32 sum = 0; -+ __u32 b0 = buf[0], b1 = buf[1]; -+ __u32 a = in[0], b = in[1], c = in[2], d = in[3]; -+ int n = 16; -+ -+ do { -+ sum += DELTA; -+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); -+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); -+ } while(--n); -+ -+ buf[0] += b0; -+ buf[1] += b1; -+} -+ -+/* F, G and H are basic MD4 functions: selection, majority, parity */ -+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+ -+/* -+ * The generic round function. The application is so specific that -+ * we don't bother protecting all the arguments with parens, as is generally -+ * good macro practice, in favor of extra legibility. -+ * Rotation is separate from addition to prevent recomputation -+ */ -+#define ROUND(f, a, b, c, d, x, s) \ -+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) -+#define K1 0 -+#define K2 013240474631UL -+#define K3 015666365641UL -+ -+/* -+ * Basic cut-down MD4 transform. Returns only 32 bits of result. -+ */ -+static void halfMD4Transform (__u32 buf[4], __u32 const in[]) -+{ -+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; -+ -+ /* Round 1 */ -+ ROUND(F, a, b, c, d, in[0] + K1, 3); -+ ROUND(F, d, a, b, c, in[1] + K1, 7); -+ ROUND(F, c, d, a, b, in[2] + K1, 11); -+ ROUND(F, b, c, d, a, in[3] + K1, 19); -+ ROUND(F, a, b, c, d, in[4] + K1, 3); -+ ROUND(F, d, a, b, c, in[5] + K1, 7); -+ ROUND(F, c, d, a, b, in[6] + K1, 11); -+ ROUND(F, b, c, d, a, in[7] + K1, 19); -+ -+ /* Round 2 */ -+ ROUND(G, a, b, c, d, in[1] + K2, 3); -+ ROUND(G, d, a, b, c, in[3] + K2, 5); -+ ROUND(G, c, d, a, b, in[5] + K2, 9); -+ ROUND(G, b, c, d, a, in[7] + K2, 13); -+ ROUND(G, a, b, c, d, in[0] + K2, 3); -+ ROUND(G, d, a, b, c, in[2] + K2, 5); -+ ROUND(G, c, d, a, b, in[4] + K2, 9); -+ ROUND(G, b, c, d, a, in[6] + K2, 13); -+ -+ /* Round 3 */ -+ ROUND(H, a, b, c, d, in[3] + K3, 3); -+ ROUND(H, d, a, b, c, in[7] + K3, 9); -+ ROUND(H, c, d, a, b, in[2] + K3, 11); -+ ROUND(H, b, c, d, a, in[6] + K3, 15); -+ ROUND(H, a, b, c, d, in[1] + K3, 3); -+ ROUND(H, d, a, b, c, in[5] + K3, 9); -+ ROUND(H, c, d, a, b, in[0] + K3, 11); -+ ROUND(H, b, c, d, a, in[4] + K3, 15); -+ -+ buf[0] += a; -+ buf[1] += b; -+ buf[2] += c; -+ buf[3] += d; -+} -+ -+#undef ROUND -+#undef F -+#undef G -+#undef H -+#undef K1 -+#undef K2 -+#undef K3 -+ -+/* The old legacy hash */ -+static __u32 dx_hack_hash (const char *name, int len) -+{ -+ __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; -+ while (len--) { -+ __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); -+ -+ if (hash & 0x80000000) hash -= 0x7fffffff; -+ hash1 = hash0; -+ hash0 = hash; -+ } -+ return (hash0 << 1); -+} -+ -+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) -+{ -+ __u32 pad, val; -+ int i; -+ -+ pad = (__u32)len | ((__u32)len << 8); -+ pad |= pad << 16; -+ -+ val = pad; -+ if (len > num*4) -+ len = num * 4; -+ for (i=0; i < len; i++) { -+ if ((i % 4) == 0) -+ val = pad; -+ val = msg[i] + (val << 8); -+ if ((i % 4) == 3) { -+ *buf++ = val; -+ val = pad; -+ num--; -+ } -+ } -+ if (--num >= 0) -+ *buf++ = val; -+ while (--num >= 0) -+ *buf++ = pad; -+} -+ -+/* -+ * Returns the hash of a filename. If len is 0 and name is NULL, then -+ * this function can be used to test whether or not a hash version is -+ * supported. -+ * -+ * The seed is an 4 longword (32 bits) "secret" which can be used to -+ * uniquify a hash. If the seed is all zero's, then some default seed -+ * may be used. -+ * -+ * A particular hash version specifies whether or not the seed is -+ * represented, and whether or not the returned hash is 32 bits or 64 -+ * bits. 32 bit hashes will return 0 for the minor hash. -+ */ -+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) -+{ -+ __u32 hash; -+ __u32 minor_hash = 0; -+ const char *p; -+ int i; -+ __u32 in[8], buf[4]; -+ -+ /* Initialize the default seed for the hash checksum functions */ -+ buf[0] = 0x67452301; -+ buf[1] = 0xefcdab89; -+ buf[2] = 0x98badcfe; -+ buf[3] = 0x10325476; -+ -+ /* Check to see if the seed is all zero's */ -+ if (hinfo->seed) { -+ for (i=0; i < 4; i++) { -+ if (hinfo->seed[i]) -+ break; -+ } -+ if (i < 4) -+ memcpy(buf, hinfo->seed, sizeof(buf)); -+ } -+ -+ switch (hinfo->hash_version) { -+ case DX_HASH_LEGACY: -+ hash = dx_hack_hash(name, len); -+ break; -+ case DX_HASH_HALF_MD4: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 8); -+ halfMD4Transform(buf, in); -+ len -= 32; -+ p += 32; -+ } -+ minor_hash = buf[2]; -+ hash = buf[1]; -+ break; -+ case DX_HASH_TEA: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 4); -+ TEA_transform(buf, in); -+ len -= 16; -+ p += 16; -+ } -+ hash = buf[0]; -+ minor_hash = buf[1]; -+ break; -+ default: -+ hinfo->hash = 0; -+ return -1; -+ } -+ hinfo->hash = hash & ~1; -+ hinfo->minor_hash = minor_hash; -+ return 0; -+} ---- linux-2.4.22-ac1/fs/ext3/Makefile~ext3-htree-2.4.22-rh 2003-09-25 14:39:01.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/Makefile 2003-09-25 14:55:12.000000000 +0400 -@@ -12,7 +12,7 @@ O_TARGET := ext3.o - export-objs := super.o inode.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o -+ ioctl.o namei.o super.o symlink.o hash.o - obj-m := $(O_TARGET) - - include $(TOPDIR)/Rules.make ---- linux-2.4.22-ac1/fs/ext3/namei.c~ext3-htree-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/namei.c 2003-09-25 14:58:37.000000000 +0400 -@@ -16,6 +16,12 @@ - * David S. Miller (davem@caip.rutgers.edu), 1995 - * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 -+ * Hash Tree Directory indexing (c) -+ * Daniel Phillips, 2001 -+ * Hash Tree Directory indexing porting -+ * Christopher Li, 2002 -+ * Hash Tree Directory indexing cleanup -+ * Theodore Ts'o, 2002 - */ - - #include -@@ -38,6 +44,642 @@ - #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) - #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) - -+static struct buffer_head *ext3_append(handle_t *handle, -+ struct inode *inode, -+ u32 *block, int *err) -+{ -+ struct buffer_head *bh; -+ -+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits; -+ -+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) { -+ inode->i_size += inode->i_sb->s_blocksize; -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_journal_get_write_access(handle,bh); -+ } -+ return bh; -+} -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#ifndef swap -+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) -+#endif -+ -+typedef struct { u32 v; } le_u32; -+typedef struct { u16 v; } le_u16; -+ -+#ifdef DX_DEBUG -+#define dxtrace(command) command -+#else -+#define dxtrace(command) -+#endif -+ -+struct fake_dirent -+{ -+ /*le*/u32 inode; -+ /*le*/u16 rec_len; -+ u8 name_len; -+ u8 file_type; -+}; -+ -+struct dx_countlimit -+{ -+ le_u16 limit; -+ le_u16 count; -+}; -+ -+struct dx_entry -+{ -+ le_u32 hash; -+ le_u32 block; -+}; -+ -+/* -+ * dx_root_info is laid out so that if it should somehow get overlaid by a -+ * dirent the two low bits of the hash version will be zero. Therefore, the -+ * hash version mod 4 should never be 0. Sincerely, the paranoia department. -+ */ -+ -+struct dx_root -+{ -+ struct fake_dirent dot; -+ char dot_name[4]; -+ struct fake_dirent dotdot; -+ char dotdot_name[4]; -+ struct dx_root_info -+ { -+ le_u32 reserved_zero; -+ u8 hash_version; -+ u8 info_length; /* 8 */ -+ u8 indirect_levels; -+ u8 unused_flags; -+ } -+ info; -+ struct dx_entry entries[0]; -+}; -+ -+struct dx_node -+{ -+ struct fake_dirent fake; -+ struct dx_entry entries[0]; -+}; -+ -+ -+struct dx_frame -+{ -+ struct buffer_head *bh; -+ struct dx_entry *entries; -+ struct dx_entry *at; -+}; -+ -+struct dx_map_entry -+{ -+ u32 hash; -+ u32 offs; -+}; -+ -+#ifdef CONFIG_EXT3_INDEX -+static inline unsigned dx_get_block (struct dx_entry *entry); -+static void dx_set_block (struct dx_entry *entry, unsigned value); -+static inline unsigned dx_get_hash (struct dx_entry *entry); -+static void dx_set_hash (struct dx_entry *entry, unsigned value); -+static unsigned dx_get_count (struct dx_entry *entries); -+static unsigned dx_get_limit (struct dx_entry *entries); -+static void dx_set_count (struct dx_entry *entries, unsigned value); -+static void dx_set_limit (struct dx_entry *entries, unsigned value); -+static unsigned dx_root_limit (struct inode *dir, unsigned infosize); -+static unsigned dx_node_limit (struct inode *dir); -+static struct dx_frame *dx_probe(struct dentry *dentry, -+ struct inode *dir, -+ struct dx_hash_info *hinfo, -+ struct dx_frame *frame, -+ int *err); -+static void dx_release (struct dx_frame *frames); -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry map[]); -+static void dx_sort_map(struct dx_map_entry *map, unsigned count); -+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, -+ struct dx_map_entry *offsets, int count); -+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); -+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash); -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err); -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Future: use high four bits of block for coalesce-on-delete flags -+ * Mask them off for now. -+ */ -+ -+static inline unsigned dx_get_block (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->block.v) & 0x00ffffff; -+} -+ -+static inline void dx_set_block (struct dx_entry *entry, unsigned value) -+{ -+ entry->block.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_hash (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->hash.v); -+} -+ -+static inline void dx_set_hash (struct dx_entry *entry, unsigned value) -+{ -+ entry->hash.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_count (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v); -+} -+ -+static inline unsigned dx_get_limit (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v); -+} -+ -+static inline void dx_set_count (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value); -+} -+ -+static inline void dx_set_limit (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value); -+} -+ -+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - -+ EXT3_DIR_REC_LEN(2) - infosize; -+ return 0? 20: entry_space / sizeof(struct dx_entry); -+} -+ -+static inline unsigned dx_node_limit (struct inode *dir) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); -+ return 0? 22: entry_space / sizeof(struct dx_entry); -+} -+ -+/* -+ * Debug -+ */ -+#ifdef DX_DEBUG -+struct stats -+{ -+ unsigned names; -+ unsigned space; -+ unsigned bcount; -+}; -+ -+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de, -+ int size, int show_names) -+{ -+ unsigned names = 0, space = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ printk("names: "); -+ while ((char *) de < base + size) -+ { -+ if (de->inode) -+ { -+ if (show_names) -+ { -+ int len = de->name_len; -+ char *name = de->name; -+ while (len--) printk("%c", *name++); -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ printk(":%x.%u ", h.hash, -+ ((char *) de - base)); -+ } -+ space += EXT3_DIR_REC_LEN(de->name_len); -+ names++; -+ } -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ printk("(%i)\n", names); -+ return (struct stats) { names, space, 1 }; -+} -+ -+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, -+ struct dx_entry *entries, int levels) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count = dx_get_count (entries), names = 0, space = 0, i; -+ unsigned bcount = 0; -+ struct buffer_head *bh; -+ int err; -+ printk("%i indexed blocks...\n", count); -+ for (i = 0; i < count; i++, entries++) -+ { -+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0; -+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; -+ struct stats stats; -+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); -+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue; -+ stats = levels? -+ dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): -+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) bh->b_data, blocksize, 0); -+ names += stats.names; -+ space += stats.space; -+ bcount += stats.bcount; -+ brelse (bh); -+ } -+ if (bcount) -+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ", -+ names, space/bcount,(space/bcount)*100/blocksize); -+ return (struct stats) { names, space, bcount}; -+} -+#endif /* DX_DEBUG */ -+ -+/* -+ * Probe for a directory leaf block to search. -+ * -+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format -+ * error in the directory index, and the caller should fall back to -+ * searching the directory normally. The callers of dx_probe **MUST** -+ * check for this error code, and make sure it never gets reflected -+ * back to userspace. -+ */ -+static struct dx_frame * -+dx_probe(struct dentry *dentry, struct inode *dir, -+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) -+{ -+ unsigned count, indirect; -+ struct dx_entry *at, *entries, *p, *q, *m; -+ struct dx_root *root; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+ -+ frame->bh = NULL; -+ if (dentry) -+ dir = dentry->d_parent->d_inode; -+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) -+ goto fail; -+ root = (struct dx_root *) bh->b_data; -+ if (root->info.hash_version != DX_HASH_TEA && -+ root->info.hash_version != DX_HASH_HALF_MD4 && -+ root->info.hash_version != DX_HASH_LEGACY) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unrecognised inode hash code %d", -+ root->info.hash_version); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ hinfo->hash_version = root->info.hash_version; -+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ if (dentry) -+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); -+ hash = hinfo->hash; -+ -+ if (root->info.unused_flags & 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash flags: %#06x", -+ root->info.unused_flags); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ if ((indirect = root->info.indirect_levels) > 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash depth: %#06x", -+ root->info.indirect_levels); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ entries = (struct dx_entry *) (((char *)&root->info) + -+ root->info.info_length); -+ assert(dx_get_limit(entries) == dx_root_limit(dir, -+ root->info.info_length)); -+ dxtrace (printk("Look up %x", hash)); -+ while (1) -+ { -+ count = dx_get_count(entries); -+ assert (count && count <= dx_get_limit(entries)); -+ p = entries + 1; -+ q = entries + count - 1; -+ while (p <= q) -+ { -+ m = p + (q - p)/2; -+ dxtrace(printk(".")); -+ if (dx_get_hash(m) > hash) -+ q = m - 1; -+ else -+ p = m + 1; -+ } -+ -+ if (0) // linear search cross check -+ { -+ unsigned n = count - 1; -+ at = entries; -+ while (n--) -+ { -+ dxtrace(printk(",")); -+ if (dx_get_hash(++at) > hash) -+ { -+ at--; -+ break; -+ } -+ } -+ assert (at == p - 1); -+ } -+ -+ at = p - 1; -+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); -+ frame->bh = bh; -+ frame->entries = entries; -+ frame->at = at; -+ if (!indirect--) return frame; -+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) -+ goto fail2; -+ at = entries = ((struct dx_node *) bh->b_data)->entries; -+ assert (dx_get_limit(entries) == dx_node_limit (dir)); -+ frame++; -+ } -+fail2: -+ while (frame >= frame_in) { -+ brelse(frame->bh); -+ frame--; -+ } -+fail: -+ return NULL; -+} -+ -+static void dx_release (struct dx_frame *frames) -+{ -+ if (frames[0].bh == NULL) -+ return; -+ -+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) -+ brelse(frames[1].bh); -+ brelse(frames[0].bh); -+} -+ -+/* -+ * This function increments the frame pointer to search the next leaf -+ * block, and reads in the necessary intervening nodes if the search -+ * should be necessary. Whether or not the search is necessary is -+ * controlled by the hash parameter. If the hash value is even, then -+ * the search is only continued if the next block starts with that -+ * hash value. This is used if we are searching for a specific file. -+ * -+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block. -+ * -+ * This function returns 1 if the caller should continue to search, -+ * or 0 if it should not. If there is an error reading one of the -+ * index blocks, it will return -1. -+ * -+ * If start_hash is non-null, it will be filled in with the starting -+ * hash of the next page. -+ */ -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash) -+{ -+ struct dx_frame *p; -+ struct buffer_head *bh; -+ int num_frames = 0; -+ __u32 bhash; -+ -+ *err = ENOENT; -+ p = frame; -+ /* -+ * Find the next leaf page by incrementing the frame pointer. -+ * If we run out of entries in the interior node, loop around and -+ * increment pointer in the parent node. When we break out of -+ * this loop, num_frames indicates the number of interior -+ * nodes need to be read. -+ */ -+ while (1) { -+ if (++(p->at) < p->entries + dx_get_count(p->entries)) -+ break; -+ if (p == frames) -+ return 0; -+ num_frames++; -+ p--; -+ } -+ -+ /* -+ * If the hash is 1, then continue only if the next page has a -+ * continuation hash of any value. This is used for readdir -+ * handling. Otherwise, check to see if the hash matches the -+ * desired contiuation hash. If it doesn't, return since -+ * there's no point to read in the successive index pages. -+ */ -+ bhash = dx_get_hash(p->at); -+ if (start_hash) -+ *start_hash = bhash; -+ if ((hash & 1) == 0) { -+ if ((bhash & ~1) != hash) -+ return 0; -+ } -+ /* -+ * If the hash is HASH_NB_ALWAYS, we always go to the next -+ * block so no check is necessary -+ */ -+ while (num_frames--) { -+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), -+ 0, err))) -+ return -1; /* Failure */ -+ p++; -+ brelse (p->bh); -+ p->bh = bh; -+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; -+ } -+ return 1; -+} -+ -+ -+/* -+ * p is at least 6 bytes before the end of page -+ */ -+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) -+{ -+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); -+} -+ -+/* -+ * This function fills a red-black tree with information from a -+ * directory. We start scanning the directory in hash order, starting -+ * at start_hash and start_minor_hash. -+ * -+ * This function returns the number of entries inserted into the tree, -+ * or a negative error code. -+ */ -+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash) -+{ -+ struct dx_hash_info hinfo; -+ struct buffer_head *bh; -+ struct ext3_dir_entry_2 *de, *top; -+ static struct dx_frame frames[2], *frame; -+ struct inode *dir; -+ int block, err; -+ int count = 0; -+ int ret; -+ __u32 hashval; -+ -+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, -+ start_minor_hash)); -+ dir = dir_file->f_dentry->d_inode; -+ hinfo.hash = start_hash; -+ hinfo.minor_hash = 0; -+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ -+ /* Add '.' and '..' from the htree header */ -+ if (!start_hash && !start_minor_hash) { -+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ de = ext3_next_entry(de); -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ count += 2; -+ } -+ -+ while (1) { -+ block = dx_get_block(frame->at); -+ dxtrace(printk("Reading block %d\n", block)); -+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) -+ goto errout; -+ -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) { -+ ext3fs_dirhash(de->name, de->name_len, &hinfo); -+ if ((hinfo.hash < start_hash) || -+ ((hinfo.hash == start_hash) && -+ (hinfo.minor_hash < start_minor_hash))) -+ continue; -+ if ((err = ext3_htree_store_dirent(dir_file, -+ hinfo.hash, hinfo.minor_hash, de)) != 0) -+ goto errout; -+ count++; -+ } -+ brelse (bh); -+ hashval = ~1; -+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, -+ frame, frames, &err, &hashval); -+ if (next_hash) -+ *next_hash = hashval; -+ if (ret == -1) -+ goto errout; -+ /* -+ * Stop if: (a) there are no more entries, or -+ * (b) we have inserted at least one entry and the -+ * next hash value is not a continuation -+ */ -+ if ((ret == 0) || -+ (count && ((hashval & 1) == 0))) -+ break; -+ } -+ dx_release(frames); -+ dxtrace(printk("Fill tree: returned %d entries\n", count)); -+ return count; -+errout: -+ dx_release(frames); -+ return (err); -+} -+ -+ -+/* -+ * Directory block splitting, compacting -+ */ -+ -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) -+{ -+ int count = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ while ((char *) de < base + size) -+ { -+ if (de->name_len && de->inode) { -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ map_tail--; -+ map_tail->hash = h.hash; -+ map_tail->offs = (u32) ((char *) de - base); -+ count++; -+ } -+ /* XXX: do we need to check rec_len == 0 case? -Chris */ -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ return count; -+} -+ -+static void dx_sort_map (struct dx_map_entry *map, unsigned count) -+{ -+ struct dx_map_entry *p, *q, *top = map + count - 1; -+ int more; -+ /* Combsort until bubble sort doesn't suck */ -+ while (count > 2) -+ { -+ count = count*10/13; -+ if (count - 9 < 2) /* 9, 10 -> 11 */ -+ count = 11; -+ for (p = top, q = p - count; q >= map; p--, q--) -+ if (p->hash < q->hash) -+ swap(*p, *q); -+ } -+ /* Garden variety bubble sort */ -+ do { -+ more = 0; -+ q = top; -+ while (q-- > map) -+ { -+ if (q[1].hash >= q[0].hash) -+ continue; -+ swap(*(q+1), *q); -+ more = 1; -+ } -+ } while(more); -+} -+ -+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) -+{ -+ struct dx_entry *entries = frame->entries; -+ struct dx_entry *old = frame->at, *new = old + 1; -+ int count = dx_get_count(entries); -+ -+ assert(count < dx_get_limit(entries)); -+ assert(old < entries + count); -+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new)); -+ dx_set_hash(new, hash); -+ dx_set_block(new, block); -+ dx_set_count(entries, count + 1); -+} -+#endif -+ -+ -+static void ext3_update_dx_flag(struct inode *inode) -+{ -+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb, -+ EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL; -+} -+ - /* - * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure. - * -@@ -94,6 +736,7 @@ static int inline search_dirblock(struct - return 0; - } - -+ - /* - * ext3_find_entry() - * -@@ -105,6 +748,8 @@ static int inline search_dirblock(struct - * The returned buffer_head has ->b_count elevated. The caller is expected - * to brelse() it when appropriate. - */ -+ -+ - static struct buffer_head * ext3_find_entry (struct dentry *dentry, - struct ext3_dir_entry_2 ** res_dir) - { -@@ -119,12 +764,32 @@ static struct buffer_head * ext3_find_en - int num = 0; - int nblocks, i, err; - struct inode *dir = dentry->d_parent->d_inode; -+ int namelen; -+ const u8 *name; -+ unsigned blocksize; - - *res_dir = NULL; - sb = dir->i_sb; -- -+ blocksize = sb->s_blocksize; -+ namelen = dentry->d_name.len; -+ name = dentry->d_name.name; -+ if (namelen > EXT3_NAME_LEN) -+ return NULL; -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ bh = ext3_dx_find_entry(dentry, res_dir, &err); -+ /* -+ * On success, or if the error was file not found, -+ * return. Otherwise, fall back to doing a search the -+ * old fashioned way. -+ */ -+ if (bh || (err != ERR_BAD_DX_DIR)) -+ return bh; -+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n")); -+ } -+#endif - nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb); -- start = dir->u.ext3_i.i_dir_start_lookup; -+ start = EXT3_I(dir)->i_dir_start_lookup; - if (start >= nblocks) - start = 0; - block = start; -@@ -166,7 +831,7 @@ restart: - i = search_dirblock(bh, dir, dentry, - block << EXT3_BLOCK_SIZE_BITS(sb), res_dir); - if (i == 1) { -- dir->u.ext3_i.i_dir_start_lookup = block; -+ EXT3_I(dir)->i_dir_start_lookup = block; - ret = bh; - goto cleanup_and_exit; - } else { -@@ -197,6 +862,74 @@ cleanup_and_exit: - return ret; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err) -+{ -+ struct super_block * sb; -+ struct dx_hash_info hinfo; -+ u32 hash; -+ struct dx_frame frames[2], *frame; -+ struct ext3_dir_entry_2 *de, *top; -+ struct buffer_head *bh; -+ unsigned long block; -+ int retval; -+ int namelen = dentry->d_name.len; -+ const u8 *name = dentry->d_name.name; -+ struct inode *dir = dentry->d_parent->d_inode; -+ -+ sb = dir->i_sb; -+ /* NFS may look up ".." - look at dx_root directory block */ -+ if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){ -+ if (!(frame = dx_probe(dentry, 0, &hinfo, frames, err))) -+ return NULL; -+ } else { -+ frame = frames; -+ frame->bh = NULL; /* for dx_release() */ -+ frame->at = (struct dx_entry *)frames; /* hack for zero entry*/ -+ dx_set_block(frame->at, 0); /* dx_root block is 0 */ -+ } -+ hash = hinfo.hash; -+ do { -+ block = dx_get_block(frame->at); -+ if (!(bh = ext3_bread (NULL,dir, block, 0, err))) -+ goto errout; -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *)((char *)de + sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) -+ if (ext3_match (namelen, name, de)) { -+ if (!ext3_check_dir_entry("ext3_find_entry", -+ dir, de, bh, -+ (block<b_data))) { -+ brelse (bh); -+ goto errout; -+ } -+ *res_dir = de; -+ dx_release (frames); -+ return bh; -+ } -+ brelse (bh); -+ /* Check to see if we should continue to search */ -+ retval = ext3_htree_next_block(dir, hash, frame, -+ frames, err, 0); -+ if (retval == -1) { -+ ext3_warning(sb, __FUNCTION__, -+ "error reading index page in directory #%lu", -+ dir->i_ino); -+ goto errout; -+ } -+ } while (retval == 1); -+ -+ *err = -ENOENT; -+errout: -+ dxtrace(printk("%s not found\n", name)); -+ dx_release (frames); -+ return NULL; -+} -+#endif -+ - static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) - { - struct inode * inode; -@@ -213,8 +938,9 @@ static struct dentry *ext3_lookup(struct - brelse (bh); - inode = iget(dir->i_sb, ino); - -- if (!inode) -+ if (!inode) { - return ERR_PTR(-EACCES); -+ } - } - d_add(dentry, inode); - return NULL; -@@ -238,6 +964,301 @@ static inline void ext3_set_de_type(stru - de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct ext3_dir_entry_2 * -+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) -+{ -+ unsigned rec_len = 0; -+ -+ while (count--) { -+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ memcpy (to, de, rec_len); -+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len); -+ de->inode = 0; -+ map++; -+ to += rec_len; -+ } -+ return (struct ext3_dir_entry_2 *) (to - rec_len); -+} -+ -+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) -+{ -+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; -+ unsigned rec_len = 0; -+ -+ prev = to = de; -+ while ((char*)de < base + size) { -+ next = (struct ext3_dir_entry_2 *) ((char *) de + -+ le16_to_cpu(de->rec_len)); -+ if (de->inode && de->name_len) { -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ if (de > to) -+ memmove(to, de, rec_len); -+ to->rec_len = cpu_to_le16(rec_len); -+ prev = to; -+ to = (struct ext3_dir_entry_2 *)((char *)to + rec_len); -+ } -+ de = next; -+ } -+ return prev; -+} -+ -+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, -+ struct buffer_head **bh,struct dx_frame *frame, -+ struct dx_hash_info *hinfo, int *error) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count, continued; -+ struct buffer_head *bh2; -+ u32 newblock; -+ u32 hash2; -+ struct dx_map_entry *map; -+ char *data1 = (*bh)->b_data, *data2; -+ unsigned split; -+ struct ext3_dir_entry_2 *de = NULL, *de2; -+ int err; -+ -+ bh2 = ext3_append (handle, dir, &newblock, error); -+ if (!(bh2)) { -+ brelse(*bh); -+ *bh = NULL; -+ goto errout; -+ } -+ -+ BUFFER_TRACE(*bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, *bh); -+ if (err) { -+ journal_error: -+ brelse(*bh); -+ brelse(bh2); -+ *bh = NULL; -+ ext3_std_error(dir->i_sb, err); -+ goto errout; -+ } -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ -+ data2 = bh2->b_data; -+ -+ /* create map in the end of data2 block */ -+ map = (struct dx_map_entry *) (data2 + blocksize); -+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1, -+ blocksize, hinfo, map); -+ map -= count; -+ split = count/2; // need to adjust to actual middle -+ dx_sort_map (map, count); -+ hash2 = map[split].hash; -+ continued = hash2 == map[split - 1].hash; -+ dxtrace(printk("Split block %i at %x, %i/%i\n", -+ dx_get_block(frame->at), hash2, split, count-split)); -+ -+ /* Fancy dance to stay within two buffers */ -+ de2 = dx_move_dirents(data1, data2, map + split, count - split); -+ de = dx_pack_dirents(data1,blocksize); -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); -+ -+ /* Which block gets the new entry? */ -+ if (hinfo->hash >= hash2) -+ { -+ swap(*bh, bh2); -+ de = de2; -+ } -+ dx_insert_block (frame, hash2 + continued, newblock); -+ err = ext3_journal_dirty_metadata (handle, bh2); -+ if (err) -+ goto journal_error; -+ err = ext3_journal_dirty_metadata (handle, frame->bh); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ dxtrace(dx_show_index ("frame", frame->entries)); -+errout: -+ return de; -+} -+#endif -+ -+ -+/* -+ * Add a new entry into a directory (leaf) block. If de is non-NULL, -+ * it points to a directory entry which is guaranteed to be large -+ * enough for new directory entry. If de is NULL, then -+ * add_dirent_to_buf will attempt search the directory block for -+ * space. It will return -ENOSPC if no space is available, and -EIO -+ * and -EEXIST if directory entry already exists. -+ * -+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In -+ * all other cases bh is released. -+ */ -+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct ext3_dir_entry_2 *de, -+ struct buffer_head * bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned long offset = 0; -+ unsigned short reclen; -+ int nlen, rlen, err; -+ char *top; -+ -+ reclen = EXT3_DIR_REC_LEN(namelen); -+ if (!de) { -+ de = (struct ext3_dir_entry_2 *)bh->b_data; -+ top = bh->b_data + dir->i_sb->s_blocksize - reclen; -+ while ((char *) de <= top) { -+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de, -+ bh, offset)) { -+ brelse (bh); -+ return -EIO; -+ } -+ if (ext3_match (namelen, name, de)) { -+ brelse (bh); -+ return -EEXIST; -+ } -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if ((de->inode? rlen - nlen: rlen) >= reclen) -+ break; -+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen); -+ offset += rlen; -+ } -+ if ((char *) de > top) -+ return -ENOSPC; -+ } -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) { -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return err; -+ } -+ -+ /* By now the buffer is marked for journaling */ -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if (de->inode) { -+ struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); -+ de1->rec_len = cpu_to_le16(rlen - nlen); -+ de->rec_len = cpu_to_le16(nlen); -+ de = de1; -+ } -+ de->file_type = EXT3_FT_UNKNOWN; -+ if (inode) { -+ de->inode = cpu_to_le32(inode->i_ino); -+ ext3_set_de_type(dir->i_sb, de, inode->i_mode); -+ } else -+ de->inode = 0; -+ de->name_len = namelen; -+ memcpy (de->name, name, namelen); -+ /* -+ * XXX shouldn't update any times until successful -+ * completion of syscall, but too many callers depend -+ * on this. -+ * -+ * XXX similarly, too many callers depend on -+ * ext3_new_inode() setting the times, but error -+ * recovery deletes the inode, so the worst that can -+ * happen is that the times are slightly out of date -+ * and/or different from the directory change time. -+ */ -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME; -+ ext3_update_dx_flag(dir); -+ dir->i_version = ++event; -+ ext3_mark_inode_dirty(handle, dir); -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return 0; -+} -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * This converts a one block unindexed directory to a 3 block indexed -+ * directory, and adds the dentry to the indexed directory. -+ */ -+static int make_indexed_dir(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct buffer_head *bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+ struct dx_root *root; -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries; -+ struct ext3_dir_entry_2 *de, *de2; -+ char *data1, *top; -+ unsigned len; -+ int retval; -+ unsigned blocksize; -+ struct dx_hash_info hinfo; -+ u32 block; -+ -+ blocksize = dir->i_sb->s_blocksize; -+ dxtrace(printk("Creating index\n")); -+ retval = ext3_journal_get_write_access(handle, bh); -+ if (retval) { -+ ext3_std_error(dir->i_sb, retval); -+ brelse(bh); -+ return retval; -+ } -+ root = (struct dx_root *) bh->b_data; -+ -+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; -+ bh2 = ext3_append (handle, dir, &block, &retval); -+ if (!(bh2)) { -+ brelse(bh); -+ return retval; -+ } -+ data1 = bh2->b_data; -+ -+ /* The 0th block becomes the root, move the dirents out */ -+ de = (struct ext3_dir_entry_2 *)&root->dotdot; -+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len)); -+ len = ((char *) root) + blocksize - (char *) de; -+ memcpy (data1, de, len); -+ de = (struct ext3_dir_entry_2 *) data1; -+ top = data1 + len; -+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top) -+ de = de2; -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ /* Initialize the root; the dot dirents already exist */ -+ de = (struct ext3_dir_entry_2 *) (&root->dotdot); -+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); -+ memset (&root->info, 0, sizeof(root->info)); -+ root->info.info_length = sizeof(root->info); -+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version; -+ entries = root->entries; -+ dx_set_block (entries, 1); -+ dx_set_count (entries, 1); -+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info))); -+ -+ /* Initialize as for dx_probe */ -+ hinfo.hash_version = root->info.hash_version; -+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ ext3fs_dirhash(name, namelen, &hinfo); -+ frame = frames; -+ frame->entries = entries; -+ frame->at = entries; -+ frame->bh = bh; -+ bh = bh2; -+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval); -+ dx_release (frames); -+ if (!(de)) -+ return retval; -+ -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} -+#endif -+ - /* - * ext3_add_entry() - * -@@ -248,127 +1269,198 @@ static inline void ext3_set_de_type(stru - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -- --/* -- * AKPM: the journalling code here looks wrong on the error paths -- */ - static int ext3_add_entry (handle_t *handle, struct dentry *dentry, - struct inode *inode) - { - struct inode *dir = dentry->d_parent->d_inode; -- const char *name = dentry->d_name.name; -- int namelen = dentry->d_name.len; - unsigned long offset; -- unsigned short rec_len; - struct buffer_head * bh; -- struct ext3_dir_entry_2 * de, * de1; -+ struct ext3_dir_entry_2 *de; - struct super_block * sb; - int retval; -+#ifdef CONFIG_EXT3_INDEX -+ int dx_fallback=0; -+#endif -+ unsigned blocksize; -+ unsigned nlen, rlen; -+ u32 block, blocks; - - sb = dir->i_sb; -- -- if (!namelen) -+ blocksize = sb->s_blocksize; -+ if (!dentry->d_name.len) - return -EINVAL; -- bh = ext3_bread (handle, dir, 0, 0, &retval); -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ retval = ext3_dx_add_entry(handle, dentry, inode); -+ if (!retval || (retval != ERR_BAD_DX_DIR)) -+ return retval; -+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; -+ dx_fallback++; -+ ext3_mark_inode_dirty(handle, dir); -+ } -+#endif -+ blocks = dir->i_size >> sb->s_blocksize_bits; -+ for (block = 0, offset = 0; block < blocks; block++) { -+ bh = ext3_bread(handle, dir, block, 0, &retval); -+ if(!bh) -+ return retval; -+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (retval != -ENOSPC) -+ return retval; -+ -+#ifdef CONFIG_EXT3_INDEX -+ if (blocks == 1 && !dx_fallback && -+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ return make_indexed_dir(handle, dentry, inode, bh); -+#endif -+ brelse(bh); -+ } -+ bh = ext3_append(handle, dir, &block, &retval); - if (!bh) - return retval; -- rec_len = EXT3_DIR_REC_LEN(namelen); -- offset = 0; - de = (struct ext3_dir_entry_2 *) bh->b_data; -- while (1) { -- if ((char *)de >= sb->s_blocksize + bh->b_data) { -- brelse (bh); -- bh = NULL; -- bh = ext3_bread (handle, dir, -- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval); -- if (!bh) -- return retval; -- if (dir->i_size <= offset) { -- if (dir->i_size == 0) { -- brelse(bh); -- return -ENOENT; -- } -+ de->inode = 0; -+ de->rec_len = cpu_to_le16(rlen = blocksize); -+ nlen = 0; -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} - -- ext3_debug ("creating next block\n"); -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * Returns 0 for success, or a negative error value -+ */ -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries, *at; -+ struct dx_hash_info hinfo; -+ struct buffer_head * bh; -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct super_block * sb = dir->i_sb; -+ struct ext3_dir_entry_2 *de; -+ int err; - -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- de->inode = 0; -- de->rec_len = le16_to_cpu(sb->s_blocksize); -- dir->u.ext3_i.i_disksize = -- dir->i_size = offset + sb->s_blocksize; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- ext3_mark_inode_dirty(handle, dir); -- } else { -+ frame = dx_probe(dentry, 0, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ entries = frame->entries; -+ at = frame->at; - -- ext3_debug ("skipping to next block\n"); -+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) -+ goto cleanup; - -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- } -- } -- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh, -- offset)) { -- brelse (bh); -- return -ENOENT; -- } -- if (ext3_match (namelen, name, de)) { -- brelse (bh); -- return -EEXIST; -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) -+ goto journal_error; -+ -+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (err != -ENOSPC) { -+ bh = 0; -+ goto cleanup; -+ } -+ -+ /* Block full, should compress but for now just split */ -+ dxtrace(printk("using %u of %u node entries\n", -+ dx_get_count(entries), dx_get_limit(entries))); -+ /* Need to split index? */ -+ if (dx_get_count(entries) == dx_get_limit(entries)) { -+ u32 newblock; -+ unsigned icount = dx_get_count(entries); -+ int levels = frame - frames; -+ struct dx_entry *entries2; -+ struct dx_node *node2; -+ struct buffer_head *bh2; -+ -+ if (levels && (dx_get_count(frames->entries) == -+ dx_get_limit(frames->entries))) { -+ ext3_warning(sb, __FUNCTION__, -+ "Directory index full!\n"); -+ err = -ENOSPC; -+ goto cleanup; - } -- if ((le32_to_cpu(de->inode) == 0 && -- le16_to_cpu(de->rec_len) >= rec_len) || -- (le16_to_cpu(de->rec_len) >= -- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) { -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- /* By now the buffer is marked for journaling */ -- offset += le16_to_cpu(de->rec_len); -- if (le32_to_cpu(de->inode)) { -- de1 = (struct ext3_dir_entry_2 *) ((char *) de + -- EXT3_DIR_REC_LEN(de->name_len)); -- de1->rec_len = -- cpu_to_le16(le16_to_cpu(de->rec_len) - -- EXT3_DIR_REC_LEN(de->name_len)); -- de->rec_len = cpu_to_le16( -- EXT3_DIR_REC_LEN(de->name_len)); -- de = de1; -+ bh2 = ext3_append (handle, dir, &newblock, &err); -+ if (!(bh2)) -+ goto cleanup; -+ node2 = (struct dx_node *)(bh2->b_data); -+ entries2 = node2->entries; -+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); -+ node2->fake.inode = 0; -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ if (levels) { -+ unsigned icount1 = icount/2, icount2 = icount - icount1; -+ unsigned hash2 = dx_get_hash(entries + icount1); -+ dxtrace(printk("Split index %i/%i\n", icount1, icount2)); -+ -+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ -+ err = ext3_journal_get_write_access(handle, -+ frames[0].bh); -+ if (err) -+ goto journal_error; -+ -+ memcpy ((char *) entries2, (char *) (entries + icount1), -+ icount2 * sizeof(struct dx_entry)); -+ dx_set_count (entries, icount1); -+ dx_set_count (entries2, icount2); -+ dx_set_limit (entries2, dx_node_limit(dir)); -+ -+ /* Which index block gets the new entry? */ -+ if (at - entries >= icount1) { -+ frame->at = at = at - entries - icount1 + entries2; -+ frame->entries = entries = entries2; -+ swap(frame->bh, bh2); - } -- de->file_type = EXT3_FT_UNKNOWN; -- if (inode) { -- de->inode = cpu_to_le32(inode->i_ino); -- ext3_set_de_type(dir->i_sb, de, inode->i_mode); -- } else -- de->inode = 0; -- de->name_len = namelen; -- memcpy (de->name, name, namelen); -- /* -- * XXX shouldn't update any times until successful -- * completion of syscall, but too many callers depend -- * on this. -- * -- * XXX similarly, too many callers depend on -- * ext3_new_inode() setting the times, but error -- * recovery deletes the inode, so the worst that can -- * happen is that the times are slightly out of date -- * and/or different from the directory change time. -- */ -- dir->i_mtime = dir->i_ctime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- dir->i_version = ++event; -- ext3_mark_inode_dirty(handle, dir); -- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -- ext3_journal_dirty_metadata(handle, bh); -- brelse(bh); -- return 0; -+ dx_insert_block (frames + 0, hash2, newblock); -+ dxtrace(dx_show_index ("node", frames[1].entries)); -+ dxtrace(dx_show_index ("node", -+ ((struct dx_node *) bh2->b_data)->entries)); -+ err = ext3_journal_dirty_metadata(handle, bh2); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ } else { -+ dxtrace(printk("Creating second level index...\n")); -+ memcpy((char *) entries2, (char *) entries, -+ icount * sizeof(struct dx_entry)); -+ dx_set_limit(entries2, dx_node_limit(dir)); -+ -+ /* Set up root */ -+ dx_set_count(entries, 1); -+ dx_set_block(entries + 0, newblock); -+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; -+ -+ /* Add new access path frame */ -+ frame = frames + 1; -+ frame->at = at = at - entries + entries2; -+ frame->entries = entries = entries2; -+ frame->bh = bh2; -+ err = ext3_journal_get_write_access(handle, -+ frame->bh); -+ if (err) -+ goto journal_error; - } -- offset += le16_to_cpu(de->rec_len); -- de = (struct ext3_dir_entry_2 *) -- ((char *) de + le16_to_cpu(de->rec_len)); -+ ext3_journal_dirty_metadata(handle, frames[0].bh); - } -- brelse (bh); -- return -ENOSPC; -+ de = do_split(handle, dir, &bh, frame, &hinfo, &err); -+ if (!de) -+ goto cleanup; -+ err = add_dirent_to_buf(handle, dentry, inode, de, bh); -+ bh = 0; -+ goto cleanup; -+ -+journal_error: -+ ext3_std_error(dir->i_sb, err); -+cleanup: -+ if (bh) -+ brelse(bh); -+ dx_release(frames); -+ return err; - } -+#endif - - /* - * ext3_delete_entry deletes a directory entry by merging it with the -@@ -455,9 +1547,11 @@ static int ext3_create (struct inode * d - struct inode * inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -481,9 +1575,11 @@ static int ext3_mknod (struct inode * di - struct inode *inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -509,9 +1605,11 @@ static int ext3_mkdir(struct inode * dir - if (dir->i_nlink >= EXT3_LINK_MAX) - return -EMLINK; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -523,7 +1621,7 @@ static int ext3_mkdir(struct inode * dir - - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; -- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize; -+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - inode->i_blocks = 0; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { -@@ -556,21 +1654,19 @@ static int ext3_mkdir(struct inode * dir - inode->i_mode |= S_ISGID; - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); -- if (err) -- goto out_no_entry; -+ if (err) { -+ inode->i_nlink = 0; -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - dir->i_nlink++; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- inode->i_nlink = 0; -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - /* -@@ -657,7 +1753,7 @@ int ext3_orphan_add(handle_t *handle, st - int err = 0, rc; - - lock_super(sb); -- if (!list_empty(&inode->u.ext3_i.i_orphan)) -+ if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - - /* Orphan handling is only valid for files with data blocks -@@ -698,7 +1794,7 @@ int ext3_orphan_add(handle_t *handle, st - * This is safe: on error we're going to ignore the orphan list - * anyway on the next recovery. */ - if (!err) -- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan); -+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", -@@ -716,25 +1812,26 @@ out_unlock: - int ext3_orphan_del(handle_t *handle, struct inode *inode) - { - struct list_head *prev; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_sb_info *sbi; - unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; - - lock_super(inode->i_sb); -- if (list_empty(&inode->u.ext3_i.i_orphan)) { -+ if (list_empty(&ei->i_orphan)) { - unlock_super(inode->i_sb); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); -- prev = inode->u.ext3_i.i_orphan.prev; -+ prev = ei->i_orphan.prev; - sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - -- list_del(&inode->u.ext3_i.i_orphan); -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ list_del(&ei->i_orphan); -+ INIT_LIST_HEAD(&ei->i_orphan); - - /* If we're on an error path, we may not have a valid - * transaction handle with which to update the orphan list on -@@ -795,8 +1892,9 @@ static int ext3_rmdir (struct inode * di - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - retval = -ENOENT; - bh = ext3_find_entry (dentry, &de); -@@ -834,7 +1932,7 @@ static int ext3_rmdir (struct inode * di - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - - end_rmdir: -@@ -852,8 +1950,9 @@ static int ext3_unlink(struct inode * di - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -880,7 +1979,7 @@ static int ext3_unlink(struct inode * di - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; - if (!inode->i_nlink) -@@ -906,9 +2005,11 @@ static int ext3_symlink (struct inode * - if (l > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -918,7 +2019,7 @@ static int ext3_symlink (struct inode * - if (IS_ERR(inode)) - goto out_stop; - -- if (l > sizeof (inode->u.ext3_i.i_data)) { -+ if (l > sizeof (EXT3_I(inode)->i_data)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* -@@ -927,24 +2028,22 @@ static int ext3_symlink (struct inode * - * i_size in generic_commit_write(). - */ - err = block_symlink(inode, symname, l); -- if (err) -- goto out_no_entry; -+ if (err) { -+ ext3_dec_count(handle, inode); -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - } else { - inode->i_op = &ext3_fast_symlink_inode_operations; -- memcpy((char*)&inode->u.ext3_i.i_data,symname,l); -+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l); - inode->i_size = l-1; - } -- inode->u.ext3_i.i_disksize = inode->i_size; -+ EXT3_I(inode)->i_disksize = inode->i_size; - err = ext3_add_nondir(handle, dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- ext3_dec_count(handle, inode); -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - static int ext3_link (struct dentry * old_dentry, -@@ -957,12 +2056,15 @@ static int ext3_link (struct dentry * ol - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) -+ if (inode->i_nlink >= EXT3_LINK_MAX) { - return -EMLINK; -+ } - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -995,9 +2097,11 @@ static int ext3_rename (struct inode * o - - old_bh = new_bh = dir_bh = NULL; - -- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(old_dir) || IS_SYNC(new_dir)) - handle->h_sync = 1; -@@ -1070,14 +2174,37 @@ static int ext3_rename (struct inode * o - /* - * ok, that's it - */ -- ext3_delete_entry(handle, old_dir, old_de, old_bh); -+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino || -+ old_de->name_len != old_dentry->d_name.len || -+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || -+ (retval = ext3_delete_entry(handle, old_dir, -+ old_de, old_bh)) == -ENOENT) { -+ /* old_de could have moved from under us during htree split, so -+ * make sure that we are deleting the right entry. We might -+ * also be pointing to a stale entry in the unused part of -+ * old_bh so just checking inum and the name isn't enough. */ -+ struct buffer_head *old_bh2; -+ struct ext3_dir_entry_2 *old_de2; -+ -+ old_bh2 = ext3_find_entry(old_dentry, &old_de2); -+ if (old_bh2) { -+ retval = ext3_delete_entry(handle, old_dir, -+ old_de2, old_bh2); -+ brelse(old_bh2); -+ } -+ } -+ if (retval) { -+ ext3_warning(old_dir->i_sb, "ext3_rename", -+ "Deleting old file (%lu), %d, error=%d", -+ old_dir->i_ino, old_dir->i_nlink, retval); -+ } - - if (new_inode) { - new_inode->i_nlink--; - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(old_dir); - if (dir_bh) { - BUFFER_TRACE(dir_bh, "get_write_access"); - ext3_journal_get_write_access(handle, dir_bh); -@@ -1089,7 +2212,7 @@ static int ext3_rename (struct inode * o - new_inode->i_nlink--; - } else { - new_dir->i_nlink++; -- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } - } ---- linux-2.4.22-ac1/fs/ext3/super.c~ext3-htree-2.4.22-rh 2003-09-25 14:39:01.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-09-25 14:55:12.000000000 +0400 -@@ -714,6 +714,7 @@ static int ext3_setup_super(struct super - es->s_mtime = cpu_to_le32(CURRENT_TIME); - ext3_update_dynamic_rev(sb); - EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -+ - ext3_commit_super (sb, es, 1); - if (test_opt (sb, DEBUG)) - printk (KERN_INFO -@@ -724,6 +725,7 @@ static int ext3_setup_super(struct super - EXT3_BLOCKS_PER_GROUP(sb), - EXT3_INODES_PER_GROUP(sb), - sbi->s_mount_opt); -+ - printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ", - bdevname(sb->s_dev)); - if (EXT3_SB(sb)->s_journal->j_inode == NULL) { -@@ -897,6 +899,7 @@ static loff_t ext3_max_size(int bits) - return res; - } - -+ - struct super_block * ext3_read_super (struct super_block * sb, void * data, - int silent) - { -@@ -1073,6 +1076,9 @@ struct super_block * ext3_read_super (st - sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); -+ for (i=0; i < 4; i++) -+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); -+ sbi->s_def_hash_version = es->s_def_hash_version; - - if (sbi->s_blocks_per_group > blocksize * 8) { - printk (KERN_ERR -@@ -1846,6 +1852,7 @@ static void __exit exit_ext3_fs(void) - unregister_filesystem(&ext3_fs_type); - } - -+EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); ---- linux-2.4.22-ac1/include/linux/ext3_fs.h~ext3-htree-2.4.22-rh 2003-09-25 14:16:29.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs.h 2003-09-25 14:58:30.000000000 +0400 -@@ -40,6 +40,11 @@ - #define EXT3FS_VERSION "2.4-0.9.19" - - /* -+ * Always enable hashed directories -+ */ -+#define CONFIG_EXT3_INDEX -+ -+/* - * Debug code - */ - #ifdef EXT3FS_DEBUG -@@ -440,8 +445,11 @@ struct ext3_super_block { - /*E0*/ __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ -- --/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */ -+ __u32 s_hash_seed[4]; /* HTREE hash seed */ -+ __u8 s_def_hash_version; /* Default hash version to use */ -+ __u8 s_reserved_char_pad; -+ __u16 s_reserved_word_pad; -+ __u32 s_reserved[192]; /* Padding to the end of the block */ - }; - - #ifdef __KERNEL__ -@@ -578,9 +586,46 @@ struct ext3_dir_entry_2 { - #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) - #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ - ~EXT3_DIR_ROUND) -+/* -+ * Hash Tree Directory indexing -+ * (c) Daniel Phillips, 2001 -+ */ -+ -+#ifdef CONFIG_EXT3_INDEX -+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \ -+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \ -+ (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) -+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) -+#else -+ #define is_dx(dir) 0 -+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2) -+#endif -+ -+/* Legal values for the dx_root hash_version field: */ -+ -+#define DX_HASH_LEGACY 0 -+#define DX_HASH_HALF_MD4 1 -+#define DX_HASH_TEA 2 -+ -+/* hash info structure used by the directory hash */ -+struct dx_hash_info -+{ -+ u32 hash; -+ u32 minor_hash; -+ int hash_version; -+ u32 *seed; -+}; - - #ifdef __KERNEL__ - /* -+ * Control parameters used by ext3_htree_next_block -+ */ -+#define HASH_NB_ALWAYS 1 -+ -+ -+/* - * Describe an inode's exact location on disk and in memory - */ - struct ext3_iloc -@@ -590,6 +635,27 @@ struct ext3_iloc - unsigned long block_group; - }; - -+ -+/* -+ * This structure is stuffed into the struct file's private_data field -+ * for directories. It is where we put information so that we can do -+ * readdir operations in hash tree order. -+ */ -+struct dir_private_info { -+ rb_root_t root; -+ rb_node_t *curr_node; -+ struct fname *extra_fname; -+ loff_t last_pos; -+ __u32 curr_hash; -+ __u32 curr_minor_hash; -+ __u32 next_hash; -+}; -+ -+/* -+ * Special error return code only used by dx_probe() and its callers. -+ */ -+#define ERR_BAD_DX_DIR -75000 -+ - /* - * Function prototypes - */ -@@ -617,11 +683,20 @@ extern struct ext3_group_desc * ext3_get - - /* dir.c */ - extern int ext3_check_dir_entry(const char *, struct inode *, -- struct ext3_dir_entry_2 *, struct buffer_head *, -- unsigned long); -+ struct ext3_dir_entry_2 *, -+ struct buffer_head *, unsigned long); -+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent); -+extern void ext3_htree_free_dir_info(struct dir_private_info *p); -+ - /* fsync.c */ - extern int ext3_sync_file (struct file *, struct dentry *, int); - -+/* hash.c */ -+extern int ext3fs_dirhash(const char *name, int len, struct -+ dx_hash_info *hinfo); -+ - /* ialloc.c */ - extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int); - extern void ext3_free_inode (handle_t *, struct inode *); -@@ -655,6 +730,8 @@ extern int ext3_ioctl (struct inode *, s - /* namei.c */ - extern int ext3_orphan_add(handle_t *, struct inode *); - extern int ext3_orphan_del(handle_t *, struct inode *); -+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash); - - /* super.c */ - extern void ext3_error (struct super_block *, const char *, const char *, ...) ---- linux-2.4.22-ac1/include/linux/ext3_fs_sb.h~ext3-htree-2.4.22-rh 2003-09-25 14:16:34.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_sb.h 2003-09-25 14:55:12.000000000 +0400 -@@ -62,6 +62,8 @@ struct ext3_sb_info { - int s_inode_size; - int s_first_ino; - u32 s_next_generation; -+ u32 s_hash_seed[4]; -+ int s_def_hash_version; - - unsigned long s_dir_count; - u8 *s_debts; ---- linux-2.4.22-ac1/include/linux/ext3_jbd.h~ext3-htree-2.4.22-rh 2003-06-13 18:51:38.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/include/linux/ext3_jbd.h 2003-09-25 14:55:12.000000000 +0400 -@@ -63,6 +63,8 @@ extern int ext3_writepage_trans_blocks(s - - #define EXT3_RESERVE_TRANS_BLOCKS 12U - -+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 -+ - int - ext3_mark_iloc_dirty(handle_t *handle, - struct inode *inode, ---- linux-2.4.22-ac1/include/linux/rbtree.h~ext3-htree-2.4.22-rh 2001-11-22 22:46:18.000000000 +0300 -+++ linux-2.4.22-ac1-alexey/include/linux/rbtree.h 2003-09-25 14:55:12.000000000 +0400 -@@ -120,6 +120,8 @@ rb_root_t; - - extern void rb_insert_color(rb_node_t *, rb_root_t *); - extern void rb_erase(rb_node_t *, rb_root_t *); -+extern rb_node_t *rb_get_first(rb_root_t *root); -+extern rb_node_t *rb_get_next(rb_node_t *n); - - static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) - { ---- linux-2.4.22-ac1/lib/rbtree.c~ext3-htree-2.4.22-rh 2002-08-03 04:39:46.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/lib/rbtree.c 2003-09-25 14:55:12.000000000 +0400 -@@ -17,6 +17,8 @@ - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - linux/lib/rbtree.c -+ -+ rb_get_first and rb_get_next written by Theodore Ts'o, 9/8/2002 - */ - - #include -@@ -294,3 +296,43 @@ void rb_erase(rb_node_t * node, rb_root_ - __rb_erase_color(child, parent, root); - } - EXPORT_SYMBOL(rb_erase); -+ -+/* -+ * This function returns the first node (in sort order) of the tree. -+ */ -+rb_node_t *rb_get_first(rb_root_t *root) -+{ -+ rb_node_t *n; -+ -+ n = root->rb_node; -+ if (!n) -+ return 0; -+ while (n->rb_left) -+ n = n->rb_left; -+ return n; -+} -+EXPORT_SYMBOL(rb_get_first); -+ -+/* -+ * Given a node, this function will return the next node in the tree. -+ */ -+rb_node_t *rb_get_next(rb_node_t *n) -+{ -+ rb_node_t *parent; -+ -+ if (n->rb_right) { -+ n = n->rb_right; -+ while (n->rb_left) -+ n = n->rb_left; -+ return n; -+ } else { -+ while ((parent = n->rb_parent)) { -+ if (n == parent->rb_left) -+ return parent; -+ n = parent; -+ } -+ return 0; -+ } -+} -+EXPORT_SYMBOL(rb_get_next); -+ - -_ diff --git a/lustre/kernel_patches/patches/ext3-htree-2.4.29.patch b/lustre/kernel_patches/patches/ext3-htree-2.4.29.patch deleted file mode 100644 index 259c7b7..0000000 --- a/lustre/kernel_patches/patches/ext3-htree-2.4.29.patch +++ /dev/null @@ -1,2496 +0,0 @@ -Index: linux-2.4.29/fs/ext3/dir.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/dir.c 2005-04-07 18:53:53.000000000 +0300 -+++ linux-2.4.29/fs/ext3/dir.c 2005-05-03 16:34:05.481747664 +0300 -@@ -21,12 +21,16 @@ - #include - #include - #include -+#include -+#include - - static unsigned char ext3_filetype_table[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK - }; - - static int ext3_readdir(struct file *, void *, filldir_t); -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir); - - struct file_operations ext3_dir_operations = { - read: generic_read_dir, -@@ -35,6 +39,17 @@ - fsync: ext3_sync_file, /* BKL held */ - }; - -+ -+static unsigned char get_dtype(struct super_block *sb, int filetype) -+{ -+ if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_FILETYPE) || -+ (filetype >= EXT3_FT_MAX)) -+ return DT_UNKNOWN; -+ -+ return (ext3_filetype_table[filetype]); -+} -+ -+ - int ext3_check_dir_entry (const char * function, struct inode * dir, - struct ext3_dir_entry_2 * de, - struct buffer_head * bh, -@@ -79,6 +94,16 @@ - - sb = inode->i_sb; - -+ if (is_dx(inode)) { -+ err = ext3_dx_readdir(filp, dirent, filldir); -+ if (err != ERR_BAD_DX_DIR) -+ return err; -+ /* -+ * We don't set the inode dirty flag since it's not -+ * critical that it get flushed back to the disk. -+ */ -+ EXT3_I(filp->f_dentry->d_inode)->i_flags &= ~EXT3_INDEX_FL; -+ } - stored = 0; - bh = NULL; - offset = filp->f_pos & (sb->s_blocksize - 1); -@@ -162,18 +187,12 @@ - * during the copy operation. - */ - unsigned long version = filp->f_version; -- unsigned char d_type = DT_UNKNOWN; - -- if (EXT3_HAS_INCOMPAT_FEATURE(sb, -- EXT3_FEATURE_INCOMPAT_FILETYPE) -- && de->file_type < EXT3_FT_MAX) -- d_type = -- ext3_filetype_table[de->file_type]; - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, - le32_to_cpu(de->inode), -- d_type); -+ get_dtype(sb, de->file_type)); - if (error) - break; - if (version != filp->f_version) -@@ -188,3 +207,272 @@ - UPDATE_ATIME(inode); - return 0; - } -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * These functions convert from the major/minor hash to an f_pos -+ * value. -+ * -+ * Currently we only use major hash numer. This is unfortunate, but -+ * on 32-bit machines, the same VFS interface is used for lseek and -+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of -+ * lseek/telldir/seekdir will blow out spectacularly, and from within -+ * the ext2 low-level routine, we don't know if we're being called by -+ * a 64-bit version of the system call or the 32-bit version of the -+ * system call. Worse yet, NFSv2 only allows for a 32-bit readdir -+ * cookie. Sigh. -+ */ -+#define hash2pos(major, minor) (major >> 1) -+#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) -+#define pos2min_hash(pos) (0) -+ -+/* -+ * This structure holds the nodes of the red-black tree used to store -+ * the directory entry in hash order. -+ */ -+struct fname { -+ __u32 hash; -+ __u32 minor_hash; -+ rb_node_t rb_hash; -+ struct fname *next; -+ __u32 inode; -+ __u8 name_len; -+ __u8 file_type; -+ char name[0]; -+}; -+ -+/* -+ * This functoin implements a non-recursive way of freeing all of the -+ * nodes in the red-black tree. -+ */ -+static void free_rb_tree_fname(rb_root_t *root) -+{ -+ rb_node_t *n = root->rb_node; -+ rb_node_t *parent; -+ struct fname *fname; -+ -+ while (n) { -+ /* Do the node's children first */ -+ if ((n)->rb_left) { -+ n = n->rb_left; -+ continue; -+ } -+ if (n->rb_right) { -+ n = n->rb_right; -+ continue; -+ } -+ /* -+ * The node has no children; free it, and then zero -+ * out parent's link to it. Finally go to the -+ * beginning of the loop and try to free the parent -+ * node. -+ */ -+ parent = n->rb_parent; -+ fname = rb_entry(n, struct fname, rb_hash); -+ kfree(fname); -+ if (!parent) -+ root->rb_node = 0; -+ else if (parent->rb_left == n) -+ parent->rb_left = 0; -+ else if (parent->rb_right == n) -+ parent->rb_right = 0; -+ n = parent; -+ } -+ root->rb_node = 0; -+} -+ -+ -+struct dir_private_info *create_dir_info(loff_t pos) -+{ -+ struct dir_private_info *p; -+ -+ p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL); -+ if (!p) -+ return NULL; -+ p->root.rb_node = 0; -+ p->curr_node = 0; -+ p->extra_fname = 0; -+ p->last_pos = 0; -+ p->curr_hash = pos2maj_hash(pos); -+ p->curr_minor_hash = pos2min_hash(pos); -+ p->next_hash = 0; -+ return p; -+} -+ -+void ext3_htree_free_dir_info(struct dir_private_info *p) -+{ -+ free_rb_tree_fname(&p->root); -+ kfree(p); -+} -+ -+/* -+ * Given a directory entry, enter it into the fname rb tree. -+ */ -+int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent) -+{ -+ rb_node_t **p, *parent = NULL; -+ struct fname * fname, *new_fn; -+ struct dir_private_info *info; -+ int len; -+ -+ info = (struct dir_private_info *) dir_file->private_data; -+ p = &info->root.rb_node; -+ -+ /* Create and allocate the fname structure */ -+ len = sizeof(struct fname) + dirent->name_len + 1; -+ new_fn = kmalloc(len, GFP_KERNEL); -+ if (!new_fn) -+ return -ENOMEM; -+ memset(new_fn, 0, len); -+ new_fn->hash = hash; -+ new_fn->minor_hash = minor_hash; -+ new_fn->inode = le32_to_cpu(dirent->inode); -+ new_fn->name_len = dirent->name_len; -+ new_fn->file_type = dirent->file_type; -+ memcpy(new_fn->name, dirent->name, dirent->name_len); -+ new_fn->name[dirent->name_len] = 0; -+ -+ while (*p) { -+ parent = *p; -+ fname = rb_entry(parent, struct fname, rb_hash); -+ -+ /* -+ * If the hash and minor hash match up, then we put -+ * them on a linked list. This rarely happens... -+ */ -+ if ((new_fn->hash == fname->hash) && -+ (new_fn->minor_hash == fname->minor_hash)) { -+ new_fn->next = fname->next; -+ fname->next = new_fn; -+ return 0; -+ } -+ -+ if (new_fn->hash < fname->hash) -+ p = &(*p)->rb_left; -+ else if (new_fn->hash > fname->hash) -+ p = &(*p)->rb_right; -+ else if (new_fn->minor_hash < fname->minor_hash) -+ p = &(*p)->rb_left; -+ else /* if (new_fn->minor_hash > fname->minor_hash) */ -+ p = &(*p)->rb_right; -+ } -+ -+ rb_link_node(&new_fn->rb_hash, parent, p); -+ rb_insert_color(&new_fn->rb_hash, &info->root); -+ return 0; -+} -+ -+ -+ -+/* -+ * This is a helper function for ext3_dx_readdir. It calls filldir -+ * for all entres on the fname linked list. (Normally there is only -+ * one entry on the linked list, unless there are 62 bit hash collisions.) -+ */ -+static int call_filldir(struct file * filp, void * dirent, -+ filldir_t filldir, struct fname *fname) -+{ -+ struct dir_private_info *info = filp->private_data; -+ loff_t curr_pos; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct super_block * sb; -+ int error; -+ -+ sb = inode->i_sb; -+ -+ if (!fname) { -+ printk("call_filldir: called with null fname?!?\n"); -+ return 0; -+ } -+ curr_pos = hash2pos(fname->hash, fname->minor_hash); -+ while (fname) { -+ error = filldir(dirent, fname->name, -+ fname->name_len, curr_pos, -+ fname->inode, -+ get_dtype(sb, fname->file_type)); -+ if (error) { -+ filp->f_pos = curr_pos; -+ info->extra_fname = fname->next; -+ return error; -+ } -+ fname = fname->next; -+ } -+ return 0; -+} -+ -+static int ext3_dx_readdir(struct file * filp, -+ void * dirent, filldir_t filldir) -+{ -+ struct dir_private_info *info = filp->private_data; -+ struct inode *inode = filp->f_dentry->d_inode; -+ struct fname *fname; -+ int ret; -+ -+ if (!info) { -+ info = create_dir_info(filp->f_pos); -+ if (!info) -+ return -ENOMEM; -+ filp->private_data = info; -+ } -+ -+ /* Some one has messed with f_pos; reset the world */ -+ if (info->last_pos != filp->f_pos) { -+ free_rb_tree_fname(&info->root); -+ info->curr_node = 0; -+ info->extra_fname = 0; -+ info->curr_hash = pos2maj_hash(filp->f_pos); -+ info->curr_minor_hash = pos2min_hash(filp->f_pos); -+ } -+ -+ /* -+ * If there are any leftover names on the hash collision -+ * chain, return them first. -+ */ -+ if (info->extra_fname && -+ call_filldir(filp, dirent, filldir, info->extra_fname)) -+ goto finished; -+ -+ if (!info->curr_node) -+ info->curr_node = rb_first(&info->root); -+ -+ while (1) { -+ /* -+ * Fill the rbtree if we have no more entries, -+ * or the inode has changed since we last read in the -+ * cached entries. -+ */ -+ if ((!info->curr_node) || -+ (filp->f_version != inode->i_version)) { -+ info->curr_node = 0; -+ free_rb_tree_fname(&info->root); -+ filp->f_version = inode->i_version; -+ ret = ext3_htree_fill_tree(filp, info->curr_hash, -+ info->curr_minor_hash, -+ &info->next_hash); -+ if (ret < 0) -+ return ret; -+ if (ret == 0) -+ break; -+ info->curr_node = rb_first(&info->root); -+ } -+ -+ fname = rb_entry(info->curr_node, struct fname, rb_hash); -+ info->curr_hash = fname->hash; -+ info->curr_minor_hash = fname->minor_hash; -+ if (call_filldir(filp, dirent, filldir, fname)) -+ break; -+ -+ info->curr_node = rb_next(info->curr_node); -+ if (!info->curr_node) { -+ info->curr_hash = info->next_hash; -+ info->curr_minor_hash = 0; -+ } -+ } -+finished: -+ info->last_pos = filp->f_pos; -+ UPDATE_ATIME(inode); -+ return 0; -+} -+#endif -Index: linux-2.4.29/fs/ext3/file.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/file.c 2005-04-07 18:55:11.000000000 +0300 -+++ linux-2.4.29/fs/ext3/file.c 2005-05-03 16:29:50.563501128 +0300 -@@ -35,6 +35,9 @@ - { - if (filp->f_mode & FMODE_WRITE) - ext3_discard_prealloc (inode); -+ if (is_dx(inode) && filp->private_data) -+ ext3_htree_free_dir_info(filp->private_data); -+ - return 0; - } - -Index: linux-2.4.29/fs/ext3/hash.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/hash.c 2005-05-03 16:29:50.539504776 +0300 -+++ linux-2.4.29/fs/ext3/hash.c 2005-05-03 16:29:50.565500824 +0300 -@@ -0,0 +1,215 @@ -+/* -+ * linux/fs/ext3/hash.c -+ * -+ * Copyright (C) 2002 by Theodore Ts'o -+ * -+ * This file is released under the GPL v2. -+ * -+ * This file may be redistributed under the terms of the GNU Public -+ * License. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#define DELTA 0x9E3779B9 -+ -+static void TEA_transform(__u32 buf[4], __u32 const in[]) -+{ -+ __u32 sum = 0; -+ __u32 b0 = buf[0], b1 = buf[1]; -+ __u32 a = in[0], b = in[1], c = in[2], d = in[3]; -+ int n = 16; -+ -+ do { -+ sum += DELTA; -+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); -+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); -+ } while(--n); -+ -+ buf[0] += b0; -+ buf[1] += b1; -+} -+ -+/* F, G and H are basic MD4 functions: selection, majority, parity */ -+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -+#define H(x, y, z) ((x) ^ (y) ^ (z)) -+ -+/* -+ * The generic round function. The application is so specific that -+ * we don't bother protecting all the arguments with parens, as is generally -+ * good macro practice, in favor of extra legibility. -+ * Rotation is separate from addition to prevent recomputation -+ */ -+#define ROUND(f, a, b, c, d, x, s) \ -+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) -+#define K1 0 -+#define K2 013240474631UL -+#define K3 015666365641UL -+ -+/* -+ * Basic cut-down MD4 transform. Returns only 32 bits of result. -+ */ -+static void halfMD4Transform (__u32 buf[4], __u32 const in[]) -+{ -+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; -+ -+ /* Round 1 */ -+ ROUND(F, a, b, c, d, in[0] + K1, 3); -+ ROUND(F, d, a, b, c, in[1] + K1, 7); -+ ROUND(F, c, d, a, b, in[2] + K1, 11); -+ ROUND(F, b, c, d, a, in[3] + K1, 19); -+ ROUND(F, a, b, c, d, in[4] + K1, 3); -+ ROUND(F, d, a, b, c, in[5] + K1, 7); -+ ROUND(F, c, d, a, b, in[6] + K1, 11); -+ ROUND(F, b, c, d, a, in[7] + K1, 19); -+ -+ /* Round 2 */ -+ ROUND(G, a, b, c, d, in[1] + K2, 3); -+ ROUND(G, d, a, b, c, in[3] + K2, 5); -+ ROUND(G, c, d, a, b, in[5] + K2, 9); -+ ROUND(G, b, c, d, a, in[7] + K2, 13); -+ ROUND(G, a, b, c, d, in[0] + K2, 3); -+ ROUND(G, d, a, b, c, in[2] + K2, 5); -+ ROUND(G, c, d, a, b, in[4] + K2, 9); -+ ROUND(G, b, c, d, a, in[6] + K2, 13); -+ -+ /* Round 3 */ -+ ROUND(H, a, b, c, d, in[3] + K3, 3); -+ ROUND(H, d, a, b, c, in[7] + K3, 9); -+ ROUND(H, c, d, a, b, in[2] + K3, 11); -+ ROUND(H, b, c, d, a, in[6] + K3, 15); -+ ROUND(H, a, b, c, d, in[1] + K3, 3); -+ ROUND(H, d, a, b, c, in[5] + K3, 9); -+ ROUND(H, c, d, a, b, in[0] + K3, 11); -+ ROUND(H, b, c, d, a, in[4] + K3, 15); -+ -+ buf[0] += a; -+ buf[1] += b; -+ buf[2] += c; -+ buf[3] += d; -+} -+ -+#undef ROUND -+#undef F -+#undef G -+#undef H -+#undef K1 -+#undef K2 -+#undef K3 -+ -+/* The old legacy hash */ -+static __u32 dx_hack_hash (const char *name, int len) -+{ -+ __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; -+ while (len--) { -+ __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); -+ -+ if (hash & 0x80000000) hash -= 0x7fffffff; -+ hash1 = hash0; -+ hash0 = hash; -+ } -+ return (hash0 << 1); -+} -+ -+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) -+{ -+ __u32 pad, val; -+ int i; -+ -+ pad = (__u32)len | ((__u32)len << 8); -+ pad |= pad << 16; -+ -+ val = pad; -+ if (len > num*4) -+ len = num * 4; -+ for (i=0; i < len; i++) { -+ if ((i % 4) == 0) -+ val = pad; -+ val = msg[i] + (val << 8); -+ if ((i % 4) == 3) { -+ *buf++ = val; -+ val = pad; -+ num--; -+ } -+ } -+ if (--num >= 0) -+ *buf++ = val; -+ while (--num >= 0) -+ *buf++ = pad; -+} -+ -+/* -+ * Returns the hash of a filename. If len is 0 and name is NULL, then -+ * this function can be used to test whether or not a hash version is -+ * supported. -+ * -+ * The seed is an 4 longword (32 bits) "secret" which can be used to -+ * uniquify a hash. If the seed is all zero's, then some default seed -+ * may be used. -+ * -+ * A particular hash version specifies whether or not the seed is -+ * represented, and whether or not the returned hash is 32 bits or 64 -+ * bits. 32 bit hashes will return 0 for the minor hash. -+ */ -+int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) -+{ -+ __u32 hash; -+ __u32 minor_hash = 0; -+ const char *p; -+ int i; -+ __u32 in[8], buf[4]; -+ -+ /* Initialize the default seed for the hash checksum functions */ -+ buf[0] = 0x67452301; -+ buf[1] = 0xefcdab89; -+ buf[2] = 0x98badcfe; -+ buf[3] = 0x10325476; -+ -+ /* Check to see if the seed is all zero's */ -+ if (hinfo->seed) { -+ for (i=0; i < 4; i++) { -+ if (hinfo->seed[i]) -+ break; -+ } -+ if (i < 4) -+ memcpy(buf, hinfo->seed, sizeof(buf)); -+ } -+ -+ switch (hinfo->hash_version) { -+ case DX_HASH_LEGACY: -+ hash = dx_hack_hash(name, len); -+ break; -+ case DX_HASH_HALF_MD4: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 8); -+ halfMD4Transform(buf, in); -+ len -= 32; -+ p += 32; -+ } -+ minor_hash = buf[2]; -+ hash = buf[1]; -+ break; -+ case DX_HASH_TEA: -+ p = name; -+ while (len > 0) { -+ str2hashbuf(p, len, in, 4); -+ TEA_transform(buf, in); -+ len -= 16; -+ p += 16; -+ } -+ hash = buf[0]; -+ minor_hash = buf[1]; -+ break; -+ default: -+ hinfo->hash = 0; -+ return -1; -+ } -+ hinfo->hash = hash & ~1; -+ hinfo->minor_hash = minor_hash; -+ return 0; -+} -Index: linux-2.4.29/fs/ext3/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/ext3/Makefile 2005-04-07 18:59:19.000000000 +0300 -+++ linux-2.4.29/fs/ext3/Makefile 2005-05-03 16:29:50.565500824 +0300 -@@ -12,7 +12,7 @@ - export-objs := super.o inode.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o -+ ioctl.o namei.o super.o symlink.o hash.o - obj-m := $(O_TARGET) - - include $(TOPDIR)/Rules.make -Index: linux-2.4.29/fs/ext3/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/namei.c 2005-04-07 18:53:59.000000000 +0300 -+++ linux-2.4.29/fs/ext3/namei.c 2005-05-03 16:29:50.576499152 +0300 -@@ -16,6 +16,12 @@ - * David S. Miller (davem@caip.rutgers.edu), 1995 - * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 -+ * Hash Tree Directory indexing (c) -+ * Daniel Phillips, 2001 -+ * Hash Tree Directory indexing porting -+ * Christopher Li, 2002 -+ * Hash Tree Directory indexing cleanup -+ * Theodore Ts'o, 2002 - */ - - #include -@@ -38,6 +44,642 @@ - #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) - #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) - -+static struct buffer_head *ext3_append(handle_t *handle, -+ struct inode *inode, -+ u32 *block, int *err) -+{ -+ struct buffer_head *bh; -+ -+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits; -+ -+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) { -+ inode->i_size += inode->i_sb->s_blocksize; -+ EXT3_I(inode)->i_disksize = inode->i_size; -+ ext3_journal_get_write_access(handle,bh); -+ } -+ return bh; -+} -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#ifndef swap -+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0) -+#endif -+ -+typedef struct { u32 v; } le_u32; -+typedef struct { u16 v; } le_u16; -+ -+#ifdef DX_DEBUG -+#define dxtrace(command) command -+#else -+#define dxtrace(command) -+#endif -+ -+struct fake_dirent -+{ -+ /*le*/u32 inode; -+ /*le*/u16 rec_len; -+ u8 name_len; -+ u8 file_type; -+}; -+ -+struct dx_countlimit -+{ -+ le_u16 limit; -+ le_u16 count; -+}; -+ -+struct dx_entry -+{ -+ le_u32 hash; -+ le_u32 block; -+}; -+ -+/* -+ * dx_root_info is laid out so that if it should somehow get overlaid by a -+ * dirent the two low bits of the hash version will be zero. Therefore, the -+ * hash version mod 4 should never be 0. Sincerely, the paranoia department. -+ */ -+ -+struct dx_root -+{ -+ struct fake_dirent dot; -+ char dot_name[4]; -+ struct fake_dirent dotdot; -+ char dotdot_name[4]; -+ struct dx_root_info -+ { -+ le_u32 reserved_zero; -+ u8 hash_version; -+ u8 info_length; /* 8 */ -+ u8 indirect_levels; -+ u8 unused_flags; -+ } -+ info; -+ struct dx_entry entries[0]; -+}; -+ -+struct dx_node -+{ -+ struct fake_dirent fake; -+ struct dx_entry entries[0]; -+}; -+ -+ -+struct dx_frame -+{ -+ struct buffer_head *bh; -+ struct dx_entry *entries; -+ struct dx_entry *at; -+}; -+ -+struct dx_map_entry -+{ -+ u32 hash; -+ u32 offs; -+}; -+ -+#ifdef CONFIG_EXT3_INDEX -+static inline unsigned dx_get_block (struct dx_entry *entry); -+static void dx_set_block (struct dx_entry *entry, unsigned value); -+static inline unsigned dx_get_hash (struct dx_entry *entry); -+static void dx_set_hash (struct dx_entry *entry, unsigned value); -+static unsigned dx_get_count (struct dx_entry *entries); -+static unsigned dx_get_limit (struct dx_entry *entries); -+static void dx_set_count (struct dx_entry *entries, unsigned value); -+static void dx_set_limit (struct dx_entry *entries, unsigned value); -+static unsigned dx_root_limit (struct inode *dir, unsigned infosize); -+static unsigned dx_node_limit (struct inode *dir); -+static struct dx_frame *dx_probe(struct dentry *dentry, -+ struct inode *dir, -+ struct dx_hash_info *hinfo, -+ struct dx_frame *frame, -+ int *err); -+static void dx_release (struct dx_frame *frames); -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry map[]); -+static void dx_sort_map(struct dx_map_entry *map, unsigned count); -+static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, -+ struct dx_map_entry *offsets, int count); -+static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); -+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash); -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err); -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Future: use high four bits of block for coalesce-on-delete flags -+ * Mask them off for now. -+ */ -+ -+static inline unsigned dx_get_block (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->block.v) & 0x00ffffff; -+} -+ -+static inline void dx_set_block (struct dx_entry *entry, unsigned value) -+{ -+ entry->block.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_hash (struct dx_entry *entry) -+{ -+ return le32_to_cpu(entry->hash.v); -+} -+ -+static inline void dx_set_hash (struct dx_entry *entry, unsigned value) -+{ -+ entry->hash.v = cpu_to_le32(value); -+} -+ -+static inline unsigned dx_get_count (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v); -+} -+ -+static inline unsigned dx_get_limit (struct dx_entry *entries) -+{ -+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v); -+} -+ -+static inline void dx_set_count (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value); -+} -+ -+static inline void dx_set_limit (struct dx_entry *entries, unsigned value) -+{ -+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value); -+} -+ -+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) - -+ EXT3_DIR_REC_LEN(2) - infosize; -+ return 0? 20: entry_space / sizeof(struct dx_entry); -+} -+ -+static inline unsigned dx_node_limit (struct inode *dir) -+{ -+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0); -+ return 0? 22: entry_space / sizeof(struct dx_entry); -+} -+ -+/* -+ * Debug -+ */ -+#ifdef DX_DEBUG -+struct stats -+{ -+ unsigned names; -+ unsigned space; -+ unsigned bcount; -+}; -+ -+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_entry_2 *de, -+ int size, int show_names) -+{ -+ unsigned names = 0, space = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ printk("names: "); -+ while ((char *) de < base + size) -+ { -+ if (de->inode) -+ { -+ if (show_names) -+ { -+ int len = de->name_len; -+ char *name = de->name; -+ while (len--) printk("%c", *name++); -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ printk(":%x.%u ", h.hash, -+ ((char *) de - base)); -+ } -+ space += EXT3_DIR_REC_LEN(de->name_len); -+ names++; -+ } -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ printk("(%i)\n", names); -+ return (struct stats) { names, space, 1 }; -+} -+ -+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, -+ struct dx_entry *entries, int levels) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count = dx_get_count (entries), names = 0, space = 0, i; -+ unsigned bcount = 0; -+ struct buffer_head *bh; -+ int err; -+ printk("%i indexed blocks...\n", count); -+ for (i = 0; i < count; i++, entries++) -+ { -+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0; -+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; -+ struct stats stats; -+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); -+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue; -+ stats = levels? -+ dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1): -+ dx_show_leaf(hinfo, (struct ext3_dir_entry_2 *) bh->b_data, blocksize, 0); -+ names += stats.names; -+ space += stats.space; -+ bcount += stats.bcount; -+ brelse (bh); -+ } -+ if (bcount) -+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ", -+ names, space/bcount,(space/bcount)*100/blocksize); -+ return (struct stats) { names, space, bcount}; -+} -+#endif /* DX_DEBUG */ -+ -+/* -+ * Probe for a directory leaf block to search. -+ * -+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format -+ * error in the directory index, and the caller should fall back to -+ * searching the directory normally. The callers of dx_probe **MUST** -+ * check for this error code, and make sure it never gets reflected -+ * back to userspace. -+ */ -+static struct dx_frame * -+dx_probe(struct dentry *dentry, struct inode *dir, -+ struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err) -+{ -+ unsigned count, indirect; -+ struct dx_entry *at, *entries, *p, *q, *m; -+ struct dx_root *root; -+ struct buffer_head *bh; -+ struct dx_frame *frame = frame_in; -+ u32 hash; -+ -+ frame->bh = NULL; -+ if (dentry) -+ dir = dentry->d_parent->d_inode; -+ if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) -+ goto fail; -+ root = (struct dx_root *) bh->b_data; -+ if (root->info.hash_version != DX_HASH_TEA && -+ root->info.hash_version != DX_HASH_HALF_MD4 && -+ root->info.hash_version != DX_HASH_LEGACY) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unrecognised inode hash code %d", -+ root->info.hash_version); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ hinfo->hash_version = root->info.hash_version; -+ hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ if (dentry) -+ ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); -+ hash = hinfo->hash; -+ -+ if (root->info.unused_flags & 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash flags: %#06x", -+ root->info.unused_flags); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ if ((indirect = root->info.indirect_levels) > 1) { -+ ext3_warning(dir->i_sb, __FUNCTION__, -+ "Unimplemented inode hash depth: %#06x", -+ root->info.indirect_levels); -+ brelse(bh); -+ *err = ERR_BAD_DX_DIR; -+ goto fail; -+ } -+ -+ entries = (struct dx_entry *) (((char *)&root->info) + -+ root->info.info_length); -+ assert(dx_get_limit(entries) == dx_root_limit(dir, -+ root->info.info_length)); -+ dxtrace (printk("Look up %x", hash)); -+ while (1) -+ { -+ count = dx_get_count(entries); -+ assert (count && count <= dx_get_limit(entries)); -+ p = entries + 1; -+ q = entries + count - 1; -+ while (p <= q) -+ { -+ m = p + (q - p)/2; -+ dxtrace(printk(".")); -+ if (dx_get_hash(m) > hash) -+ q = m - 1; -+ else -+ p = m + 1; -+ } -+ -+ if (0) // linear search cross check -+ { -+ unsigned n = count - 1; -+ at = entries; -+ while (n--) -+ { -+ dxtrace(printk(",")); -+ if (dx_get_hash(++at) > hash) -+ { -+ at--; -+ break; -+ } -+ } -+ assert (at == p - 1); -+ } -+ -+ at = p - 1; -+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at))); -+ frame->bh = bh; -+ frame->entries = entries; -+ frame->at = at; -+ if (!indirect--) return frame; -+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) -+ goto fail2; -+ at = entries = ((struct dx_node *) bh->b_data)->entries; -+ assert (dx_get_limit(entries) == dx_node_limit (dir)); -+ frame++; -+ } -+fail2: -+ while (frame >= frame_in) { -+ brelse(frame->bh); -+ frame--; -+ } -+fail: -+ return NULL; -+} -+ -+static void dx_release (struct dx_frame *frames) -+{ -+ if (frames[0].bh == NULL) -+ return; -+ -+ if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels) -+ brelse(frames[1].bh); -+ brelse(frames[0].bh); -+} -+ -+/* -+ * This function increments the frame pointer to search the next leaf -+ * block, and reads in the necessary intervening nodes if the search -+ * should be necessary. Whether or not the search is necessary is -+ * controlled by the hash parameter. If the hash value is even, then -+ * the search is only continued if the next block starts with that -+ * hash value. This is used if we are searching for a specific file. -+ * -+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block. -+ * -+ * This function returns 1 if the caller should continue to search, -+ * or 0 if it should not. If there is an error reading one of the -+ * index blocks, it will return -1. -+ * -+ * If start_hash is non-null, it will be filled in with the starting -+ * hash of the next page. -+ */ -+static int ext3_htree_next_block(struct inode *dir, __u32 hash, -+ struct dx_frame *frame, -+ struct dx_frame *frames, int *err, -+ __u32 *start_hash) -+{ -+ struct dx_frame *p; -+ struct buffer_head *bh; -+ int num_frames = 0; -+ __u32 bhash; -+ -+ *err = ENOENT; -+ p = frame; -+ /* -+ * Find the next leaf page by incrementing the frame pointer. -+ * If we run out of entries in the interior node, loop around and -+ * increment pointer in the parent node. When we break out of -+ * this loop, num_frames indicates the number of interior -+ * nodes need to be read. -+ */ -+ while (1) { -+ if (++(p->at) < p->entries + dx_get_count(p->entries)) -+ break; -+ if (p == frames) -+ return 0; -+ num_frames++; -+ p--; -+ } -+ -+ /* -+ * If the hash is 1, then continue only if the next page has a -+ * continuation hash of any value. This is used for readdir -+ * handling. Otherwise, check to see if the hash matches the -+ * desired contiuation hash. If it doesn't, return since -+ * there's no point to read in the successive index pages. -+ */ -+ bhash = dx_get_hash(p->at); -+ if (start_hash) -+ *start_hash = bhash; -+ if ((hash & 1) == 0) { -+ if ((bhash & ~1) != hash) -+ return 0; -+ } -+ /* -+ * If the hash is HASH_NB_ALWAYS, we always go to the next -+ * block so no check is necessary -+ */ -+ while (num_frames--) { -+ if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), -+ 0, err))) -+ return -1; /* Failure */ -+ p++; -+ brelse (p->bh); -+ p->bh = bh; -+ p->at = p->entries = ((struct dx_node *) bh->b_data)->entries; -+ } -+ return 1; -+} -+ -+ -+/* -+ * p is at least 6 bytes before the end of page -+ */ -+static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) -+{ -+ return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); -+} -+ -+/* -+ * This function fills a red-black tree with information from a -+ * directory. We start scanning the directory in hash order, starting -+ * at start_hash and start_minor_hash. -+ * -+ * This function returns the number of entries inserted into the tree, -+ * or a negative error code. -+ */ -+int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash) -+{ -+ struct dx_hash_info hinfo; -+ struct buffer_head *bh; -+ struct ext3_dir_entry_2 *de, *top; -+ static struct dx_frame frames[2], *frame; -+ struct inode *dir; -+ int block, err; -+ int count = 0; -+ int ret; -+ __u32 hashval; -+ -+ dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, -+ start_minor_hash)); -+ dir = dir_file->f_dentry->d_inode; -+ hinfo.hash = start_hash; -+ hinfo.minor_hash = 0; -+ frame = dx_probe(0, dir_file->f_dentry->d_inode, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ -+ /* Add '.' and '..' from the htree header */ -+ if (!start_hash && !start_minor_hash) { -+ de = (struct ext3_dir_entry_2 *) frames[0].bh->b_data; -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ de = ext3_next_entry(de); -+ if ((err = ext3_htree_store_dirent(dir_file, 0, 0, de)) != 0) -+ goto errout; -+ count += 2; -+ } -+ -+ while (1) { -+ block = dx_get_block(frame->at); -+ dxtrace(printk("Reading block %d\n", block)); -+ if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) -+ goto errout; -+ -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + dir->i_sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) { -+ ext3fs_dirhash(de->name, de->name_len, &hinfo); -+ if ((hinfo.hash < start_hash) || -+ ((hinfo.hash == start_hash) && -+ (hinfo.minor_hash < start_minor_hash))) -+ continue; -+ if ((err = ext3_htree_store_dirent(dir_file, -+ hinfo.hash, hinfo.minor_hash, de)) != 0) -+ goto errout; -+ count++; -+ } -+ brelse (bh); -+ hashval = ~1; -+ ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, -+ frame, frames, &err, &hashval); -+ if (next_hash) -+ *next_hash = hashval; -+ if (ret == -1) -+ goto errout; -+ /* -+ * Stop if: (a) there are no more entries, or -+ * (b) we have inserted at least one entry and the -+ * next hash value is not a continuation -+ */ -+ if ((ret == 0) || -+ (count && ((hashval & 1) == 0))) -+ break; -+ } -+ dx_release(frames); -+ dxtrace(printk("Fill tree: returned %d entries\n", count)); -+ return count; -+errout: -+ dx_release(frames); -+ return (err); -+} -+ -+ -+/* -+ * Directory block splitting, compacting -+ */ -+ -+static int dx_make_map (struct ext3_dir_entry_2 *de, int size, -+ struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) -+{ -+ int count = 0; -+ char *base = (char *) de; -+ struct dx_hash_info h = *hinfo; -+ -+ while ((char *) de < base + size) -+ { -+ if (de->name_len && de->inode) { -+ ext3fs_dirhash(de->name, de->name_len, &h); -+ map_tail--; -+ map_tail->hash = h.hash; -+ map_tail->offs = (u32) ((char *) de - base); -+ count++; -+ } -+ /* XXX: do we need to check rec_len == 0 case? -Chris */ -+ de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); -+ } -+ return count; -+} -+ -+static void dx_sort_map (struct dx_map_entry *map, unsigned count) -+{ -+ struct dx_map_entry *p, *q, *top = map + count - 1; -+ int more; -+ /* Combsort until bubble sort doesn't suck */ -+ while (count > 2) -+ { -+ count = count*10/13; -+ if (count - 9 < 2) /* 9, 10 -> 11 */ -+ count = 11; -+ for (p = top, q = p - count; q >= map; p--, q--) -+ if (p->hash < q->hash) -+ swap(*p, *q); -+ } -+ /* Garden variety bubble sort */ -+ do { -+ more = 0; -+ q = top; -+ while (q-- > map) -+ { -+ if (q[1].hash >= q[0].hash) -+ continue; -+ swap(*(q+1), *q); -+ more = 1; -+ } -+ } while(more); -+} -+ -+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) -+{ -+ struct dx_entry *entries = frame->entries; -+ struct dx_entry *old = frame->at, *new = old + 1; -+ int count = dx_get_count(entries); -+ -+ assert(count < dx_get_limit(entries)); -+ assert(old < entries + count); -+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new)); -+ dx_set_hash(new, hash); -+ dx_set_block(new, block); -+ dx_set_count(entries, count + 1); -+} -+#endif -+ -+ -+static void ext3_update_dx_flag(struct inode *inode) -+{ -+ if (!EXT3_HAS_COMPAT_FEATURE(inode->i_sb, -+ EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL; -+} -+ - /* - * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure. - * -@@ -94,6 +736,7 @@ - return 0; - } - -+ - /* - * ext3_find_entry() - * -@@ -105,6 +748,8 @@ - * The returned buffer_head has ->b_count elevated. The caller is expected - * to brelse() it when appropriate. - */ -+ -+ - static struct buffer_head * ext3_find_entry (struct dentry *dentry, - struct ext3_dir_entry_2 ** res_dir) - { -@@ -119,12 +764,32 @@ - int num = 0; - int nblocks, i, err; - struct inode *dir = dentry->d_parent->d_inode; -+ int namelen; -+ const u8 *name; -+ unsigned blocksize; - - *res_dir = NULL; - sb = dir->i_sb; -- -+ blocksize = sb->s_blocksize; -+ namelen = dentry->d_name.len; -+ name = dentry->d_name.name; -+ if (namelen > EXT3_NAME_LEN) -+ return NULL; -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ bh = ext3_dx_find_entry(dentry, res_dir, &err); -+ /* -+ * On success, or if the error was file not found, -+ * return. Otherwise, fall back to doing a search the -+ * old fashioned way. -+ */ -+ if (bh || (err != ERR_BAD_DX_DIR)) -+ return bh; -+ dxtrace(printk("ext3_find_entry: dx failed, falling back\n")); -+ } -+#endif - nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb); -- start = dir->u.ext3_i.i_dir_start_lookup; -+ start = EXT3_I(dir)->i_dir_start_lookup; - if (start >= nblocks) - start = 0; - block = start; -@@ -165,7 +830,7 @@ - i = search_dirblock(bh, dir, dentry, - block << EXT3_BLOCK_SIZE_BITS(sb), res_dir); - if (i == 1) { -- dir->u.ext3_i.i_dir_start_lookup = block; -+ EXT3_I(dir)->i_dir_start_lookup = block; - ret = bh; - goto cleanup_and_exit; - } else { -@@ -196,6 +861,66 @@ - return ret; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, -+ struct ext3_dir_entry_2 **res_dir, int *err) -+{ -+ struct super_block * sb; -+ struct dx_hash_info hinfo; -+ u32 hash; -+ struct dx_frame frames[2], *frame; -+ struct ext3_dir_entry_2 *de, *top; -+ struct buffer_head *bh; -+ unsigned long block; -+ int retval; -+ int namelen = dentry->d_name.len; -+ const u8 *name = dentry->d_name.name; -+ struct inode *dir = dentry->d_parent->d_inode; -+ -+ sb = dir->i_sb; -+ if (!(frame = dx_probe (dentry, 0, &hinfo, frames, err))) -+ return NULL; -+ hash = hinfo.hash; -+ do { -+ block = dx_get_block(frame->at); -+ if (!(bh = ext3_bread (NULL,dir, block, 0, err))) -+ goto errout; -+ de = (struct ext3_dir_entry_2 *) bh->b_data; -+ top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize - -+ EXT3_DIR_REC_LEN(0)); -+ for (; de < top; de = ext3_next_entry(de)) -+ if (ext3_match (namelen, name, de)) { -+ if (!ext3_check_dir_entry("ext3_find_entry", -+ dir, de, bh, -+ (block<b_data))) { -+ brelse (bh); -+ goto errout; -+ } -+ *res_dir = de; -+ dx_release (frames); -+ return bh; -+ } -+ brelse (bh); -+ /* Check to see if we should continue to search */ -+ retval = ext3_htree_next_block(dir, hash, frame, -+ frames, err, 0); -+ if (retval == -1) { -+ ext3_warning(sb, __FUNCTION__, -+ "error reading index page in directory #%lu", -+ dir->i_ino); -+ goto errout; -+ } -+ } while (retval == 1); -+ -+ *err = -ENOENT; -+errout: -+ dxtrace(printk("%s not found\n", name)); -+ dx_release (frames); -+ return NULL; -+} -+#endif -+ - static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry) - { - struct inode * inode; -@@ -212,8 +937,9 @@ - brelse (bh); - inode = iget(dir->i_sb, ino); - -- if (!inode) -+ if (!inode) { - return ERR_PTR(-EACCES); -+ } - } - d_add(dentry, inode); - return NULL; -@@ -237,6 +963,301 @@ - de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; - } - -+#ifdef CONFIG_EXT3_INDEX -+static struct ext3_dir_entry_2 * -+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) -+{ -+ unsigned rec_len = 0; -+ -+ while (count--) { -+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *) (from + map->offs); -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ memcpy (to, de, rec_len); -+ ((struct ext3_dir_entry_2 *)to)->rec_len = cpu_to_le16(rec_len); -+ de->inode = 0; -+ map++; -+ to += rec_len; -+ } -+ return (struct ext3_dir_entry_2 *) (to - rec_len); -+} -+ -+static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) -+{ -+ struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; -+ unsigned rec_len = 0; -+ -+ prev = to = de; -+ while ((char*)de < base + size) { -+ next = (struct ext3_dir_entry_2 *) ((char *) de + -+ le16_to_cpu(de->rec_len)); -+ if (de->inode && de->name_len) { -+ rec_len = EXT3_DIR_REC_LEN(de->name_len); -+ if (de > to) -+ memmove(to, de, rec_len); -+ to->rec_len = cpu_to_le16(rec_len); -+ prev = to; -+ to = (struct ext3_dir_entry_2 *)((char *)to + rec_len); -+ } -+ de = next; -+ } -+ return prev; -+} -+ -+static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, -+ struct buffer_head **bh,struct dx_frame *frame, -+ struct dx_hash_info *hinfo, int *error) -+{ -+ unsigned blocksize = dir->i_sb->s_blocksize; -+ unsigned count, continued; -+ struct buffer_head *bh2; -+ u32 newblock; -+ u32 hash2; -+ struct dx_map_entry *map; -+ char *data1 = (*bh)->b_data, *data2; -+ unsigned split; -+ struct ext3_dir_entry_2 *de = NULL, *de2; -+ int err; -+ -+ bh2 = ext3_append (handle, dir, &newblock, error); -+ if (!(bh2)) { -+ brelse(*bh); -+ *bh = NULL; -+ goto errout; -+ } -+ -+ BUFFER_TRACE(*bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, *bh); -+ if (err) { -+ journal_error: -+ brelse(*bh); -+ brelse(bh2); -+ *bh = NULL; -+ ext3_std_error(dir->i_sb, err); -+ goto errout; -+ } -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ -+ data2 = bh2->b_data; -+ -+ /* create map in the end of data2 block */ -+ map = (struct dx_map_entry *) (data2 + blocksize); -+ count = dx_make_map ((struct ext3_dir_entry_2 *) data1, -+ blocksize, hinfo, map); -+ map -= count; -+ split = count/2; // need to adjust to actual middle -+ dx_sort_map (map, count); -+ hash2 = map[split].hash; -+ continued = hash2 == map[split - 1].hash; -+ dxtrace(printk("Split block %i at %x, %i/%i\n", -+ dx_get_block(frame->at), hash2, split, count-split)); -+ -+ /* Fancy dance to stay within two buffers */ -+ de2 = dx_move_dirents(data1, data2, map + split, count - split); -+ de = dx_pack_dirents(data1,blocksize); -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); -+ dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); -+ -+ /* Which block gets the new entry? */ -+ if (hinfo->hash >= hash2) -+ { -+ swap(*bh, bh2); -+ de = de2; -+ } -+ dx_insert_block (frame, hash2 + continued, newblock); -+ err = ext3_journal_dirty_metadata (handle, bh2); -+ if (err) -+ goto journal_error; -+ err = ext3_journal_dirty_metadata (handle, frame->bh); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ dxtrace(dx_show_index ("frame", frame->entries)); -+errout: -+ return de; -+} -+#endif -+ -+ -+/* -+ * Add a new entry into a directory (leaf) block. If de is non-NULL, -+ * it points to a directory entry which is guaranteed to be large -+ * enough for new directory entry. If de is NULL, then -+ * add_dirent_to_buf will attempt search the directory block for -+ * space. It will return -ENOSPC if no space is available, and -EIO -+ * and -EEXIST if directory entry already exists. -+ * -+ * NOTE! bh is NOT released in the case where ENOSPC is returned. In -+ * all other cases bh is released. -+ */ -+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct ext3_dir_entry_2 *de, -+ struct buffer_head * bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned long offset = 0; -+ unsigned short reclen; -+ int nlen, rlen, err; -+ char *top; -+ -+ reclen = EXT3_DIR_REC_LEN(namelen); -+ if (!de) { -+ de = (struct ext3_dir_entry_2 *)bh->b_data; -+ top = bh->b_data + dir->i_sb->s_blocksize - reclen; -+ while ((char *) de <= top) { -+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de, -+ bh, offset)) { -+ brelse (bh); -+ return -EIO; -+ } -+ if (ext3_match (namelen, name, de)) { -+ brelse (bh); -+ return -EEXIST; -+ } -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if ((de->inode? rlen - nlen: rlen) >= reclen) -+ break; -+ de = (struct ext3_dir_entry_2 *)((char *)de + rlen); -+ offset += rlen; -+ } -+ if ((char *) de > top) -+ return -ENOSPC; -+ } -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) { -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return err; -+ } -+ -+ /* By now the buffer is marked for journaling */ -+ nlen = EXT3_DIR_REC_LEN(de->name_len); -+ rlen = le16_to_cpu(de->rec_len); -+ if (de->inode) { -+ struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); -+ de1->rec_len = cpu_to_le16(rlen - nlen); -+ de->rec_len = cpu_to_le16(nlen); -+ de = de1; -+ } -+ de->file_type = EXT3_FT_UNKNOWN; -+ if (inode) { -+ de->inode = cpu_to_le32(inode->i_ino); -+ ext3_set_de_type(dir->i_sb, de, inode->i_mode); -+ } else -+ de->inode = 0; -+ de->name_len = namelen; -+ memcpy (de->name, name, namelen); -+ /* -+ * XXX shouldn't update any times until successful -+ * completion of syscall, but too many callers depend -+ * on this. -+ * -+ * XXX similarly, too many callers depend on -+ * ext3_new_inode() setting the times, but error -+ * recovery deletes the inode, so the worst that can -+ * happen is that the times are slightly out of date -+ * and/or different from the directory change time. -+ */ -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME; -+ ext3_update_dx_flag(dir); -+ dir->i_version = ++event; -+ ext3_mark_inode_dirty(handle, dir); -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) -+ ext3_std_error(dir->i_sb, err); -+ brelse(bh); -+ return 0; -+} -+ -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * This converts a one block unindexed directory to a 3 block indexed -+ * directory, and adds the dentry to the indexed directory. -+ */ -+static int make_indexed_dir(handle_t *handle, struct dentry *dentry, -+ struct inode *inode, struct buffer_head *bh) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ struct buffer_head *bh2; -+ struct dx_root *root; -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries; -+ struct ext3_dir_entry_2 *de, *de2; -+ char *data1, *top; -+ unsigned len; -+ int retval; -+ unsigned blocksize; -+ struct dx_hash_info hinfo; -+ u32 block; -+ -+ blocksize = dir->i_sb->s_blocksize; -+ dxtrace(printk("Creating index\n")); -+ retval = ext3_journal_get_write_access(handle, bh); -+ if (retval) { -+ ext3_std_error(dir->i_sb, retval); -+ brelse(bh); -+ return retval; -+ } -+ root = (struct dx_root *) bh->b_data; -+ -+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL; -+ bh2 = ext3_append (handle, dir, &block, &retval); -+ if (!(bh2)) { -+ brelse(bh); -+ return retval; -+ } -+ data1 = bh2->b_data; -+ -+ /* The 0th block becomes the root, move the dirents out */ -+ de = (struct ext3_dir_entry_2 *)&root->dotdot; -+ de = (struct ext3_dir_entry_2 *)((char *)de + le16_to_cpu(de->rec_len)); -+ len = ((char *) root) + blocksize - (char *) de; -+ memcpy (data1, de, len); -+ de = (struct ext3_dir_entry_2 *) data1; -+ top = data1 + len; -+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top) -+ de = de2; -+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); -+ /* Initialize the root; the dot dirents already exist */ -+ de = (struct ext3_dir_entry_2 *) (&root->dotdot); -+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); -+ memset (&root->info, 0, sizeof(root->info)); -+ root->info.info_length = sizeof(root->info); -+ root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version; -+ entries = root->entries; -+ dx_set_block (entries, 1); -+ dx_set_count (entries, 1); -+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info))); -+ -+ /* Initialize as for dx_probe */ -+ hinfo.hash_version = root->info.hash_version; -+ hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ ext3fs_dirhash(name, namelen, &hinfo); -+ frame = frames; -+ frame->entries = entries; -+ frame->at = entries; -+ frame->bh = bh; -+ bh = bh2; -+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval); -+ dx_release (frames); -+ if (!(de)) -+ return retval; -+ -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} -+#endif -+ - /* - * ext3_add_entry() - * -@@ -247,127 +1268,198 @@ - * may not sleep between calling this and putting something into - * the entry, as someone else might have used it while you slept. - */ -- --/* -- * AKPM: the journalling code here looks wrong on the error paths -- */ - static int ext3_add_entry (handle_t *handle, struct dentry *dentry, - struct inode *inode) - { - struct inode *dir = dentry->d_parent->d_inode; -- const char *name = dentry->d_name.name; -- int namelen = dentry->d_name.len; - unsigned long offset; -- unsigned short rec_len; - struct buffer_head * bh; -- struct ext3_dir_entry_2 * de, * de1; -+ struct ext3_dir_entry_2 *de; - struct super_block * sb; - int retval; -+#ifdef CONFIG_EXT3_INDEX -+ int dx_fallback=0; -+#endif -+ unsigned blocksize; -+ unsigned nlen, rlen; -+ u32 block, blocks; - - sb = dir->i_sb; -- -- if (!namelen) -+ blocksize = sb->s_blocksize; -+ if (!dentry->d_name.len) - return -EINVAL; -- bh = ext3_bread (handle, dir, 0, 0, &retval); -+#ifdef CONFIG_EXT3_INDEX -+ if (is_dx(dir)) { -+ retval = ext3_dx_add_entry(handle, dentry, inode); -+ if (!retval || (retval != ERR_BAD_DX_DIR)) -+ return retval; -+ EXT3_I(dir)->i_flags &= ~EXT3_INDEX_FL; -+ dx_fallback++; -+ ext3_mark_inode_dirty(handle, dir); -+ } -+#endif -+ blocks = dir->i_size >> sb->s_blocksize_bits; -+ for (block = 0, offset = 0; block < blocks; block++) { -+ bh = ext3_bread(handle, dir, block, 0, &retval); -+ if(!bh) -+ return retval; -+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (retval != -ENOSPC) -+ return retval; -+ -+#ifdef CONFIG_EXT3_INDEX -+ if (blocks == 1 && !dx_fallback && -+ EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX)) -+ return make_indexed_dir(handle, dentry, inode, bh); -+#endif -+ brelse(bh); -+ } -+ bh = ext3_append(handle, dir, &block, &retval); - if (!bh) - return retval; -- rec_len = EXT3_DIR_REC_LEN(namelen); -- offset = 0; - de = (struct ext3_dir_entry_2 *) bh->b_data; -- while (1) { -- if ((char *)de >= sb->s_blocksize + bh->b_data) { -- brelse (bh); -- bh = NULL; -- bh = ext3_bread (handle, dir, -- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval); -- if (!bh) -- return retval; -- if (dir->i_size <= offset) { -- if (dir->i_size == 0) { -- brelse(bh); -- return -ENOENT; -- } -+ de->inode = 0; -+ de->rec_len = cpu_to_le16(rlen = blocksize); -+ nlen = 0; -+ return add_dirent_to_buf(handle, dentry, inode, de, bh); -+} - -- ext3_debug ("creating next block\n"); -+#ifdef CONFIG_EXT3_INDEX -+/* -+ * Returns 0 for success, or a negative error value -+ */ -+static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ struct dx_frame frames[2], *frame; -+ struct dx_entry *entries, *at; -+ struct dx_hash_info hinfo; -+ struct buffer_head * bh; -+ struct inode *dir = dentry->d_parent->d_inode; -+ struct super_block * sb = dir->i_sb; -+ struct ext3_dir_entry_2 *de; -+ int err; - -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- de->inode = 0; -- de->rec_len = le16_to_cpu(sb->s_blocksize); -- dir->u.ext3_i.i_disksize = -- dir->i_size = offset + sb->s_blocksize; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- ext3_mark_inode_dirty(handle, dir); -- } else { -+ frame = dx_probe(dentry, 0, &hinfo, frames, &err); -+ if (!frame) -+ return err; -+ entries = frame->entries; -+ at = frame->at; - -- ext3_debug ("skipping to next block\n"); -+ if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) -+ goto cleanup; - -- de = (struct ext3_dir_entry_2 *) bh->b_data; -- } -- } -- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh, -- offset)) { -- brelse (bh); -- return -ENOENT; -- } -- if (ext3_match (namelen, name, de)) { -- brelse (bh); -- return -EEXIST; -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) -+ goto journal_error; -+ -+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh); -+ if (err != -ENOSPC) { -+ bh = 0; -+ goto cleanup; -+ } -+ -+ /* Block full, should compress but for now just split */ -+ dxtrace(printk("using %u of %u node entries\n", -+ dx_get_count(entries), dx_get_limit(entries))); -+ /* Need to split index? */ -+ if (dx_get_count(entries) == dx_get_limit(entries)) { -+ u32 newblock; -+ unsigned icount = dx_get_count(entries); -+ int levels = frame - frames; -+ struct dx_entry *entries2; -+ struct dx_node *node2; -+ struct buffer_head *bh2; -+ -+ if (levels && (dx_get_count(frames->entries) == -+ dx_get_limit(frames->entries))) { -+ ext3_warning(sb, __FUNCTION__, -+ "Directory index full!\n"); -+ err = -ENOSPC; -+ goto cleanup; - } -- if ((le32_to_cpu(de->inode) == 0 && -- le16_to_cpu(de->rec_len) >= rec_len) || -- (le16_to_cpu(de->rec_len) >= -- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) { -- BUFFER_TRACE(bh, "get_write_access"); -- ext3_journal_get_write_access(handle, bh); -- /* By now the buffer is marked for journaling */ -- offset += le16_to_cpu(de->rec_len); -- if (le32_to_cpu(de->inode)) { -- de1 = (struct ext3_dir_entry_2 *) ((char *) de + -- EXT3_DIR_REC_LEN(de->name_len)); -- de1->rec_len = -- cpu_to_le16(le16_to_cpu(de->rec_len) - -- EXT3_DIR_REC_LEN(de->name_len)); -- de->rec_len = cpu_to_le16( -- EXT3_DIR_REC_LEN(de->name_len)); -- de = de1; -+ bh2 = ext3_append (handle, dir, &newblock, &err); -+ if (!(bh2)) -+ goto cleanup; -+ node2 = (struct dx_node *)(bh2->b_data); -+ entries2 = node2->entries; -+ node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); -+ node2->fake.inode = 0; -+ BUFFER_TRACE(frame->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, frame->bh); -+ if (err) -+ goto journal_error; -+ if (levels) { -+ unsigned icount1 = icount/2, icount2 = icount - icount1; -+ unsigned hash2 = dx_get_hash(entries + icount1); -+ dxtrace(printk("Split index %i/%i\n", icount1, icount2)); -+ -+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ -+ err = ext3_journal_get_write_access(handle, -+ frames[0].bh); -+ if (err) -+ goto journal_error; -+ -+ memcpy ((char *) entries2, (char *) (entries + icount1), -+ icount2 * sizeof(struct dx_entry)); -+ dx_set_count (entries, icount1); -+ dx_set_count (entries2, icount2); -+ dx_set_limit (entries2, dx_node_limit(dir)); -+ -+ /* Which index block gets the new entry? */ -+ if (at - entries >= icount1) { -+ frame->at = at = at - entries - icount1 + entries2; -+ frame->entries = entries = entries2; -+ swap(frame->bh, bh2); - } -- de->file_type = EXT3_FT_UNKNOWN; -- if (inode) { -- de->inode = cpu_to_le32(inode->i_ino); -- ext3_set_de_type(dir->i_sb, de, inode->i_mode); -- } else -- de->inode = 0; -- de->name_len = namelen; -- memcpy (de->name, name, namelen); -- /* -- * XXX shouldn't update any times until successful -- * completion of syscall, but too many callers depend -- * on this. -- * -- * XXX similarly, too many callers depend on -- * ext3_new_inode() setting the times, but error -- * recovery deletes the inode, so the worst that can -- * happen is that the times are slightly out of date -- * and/or different from the directory change time. -- */ -- dir->i_mtime = dir->i_ctime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -- dir->i_version = ++event; -- ext3_mark_inode_dirty(handle, dir); -- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -- ext3_journal_dirty_metadata(handle, bh); -- brelse(bh); -- return 0; -+ dx_insert_block (frames + 0, hash2, newblock); -+ dxtrace(dx_show_index ("node", frames[1].entries)); -+ dxtrace(dx_show_index ("node", -+ ((struct dx_node *) bh2->b_data)->entries)); -+ err = ext3_journal_dirty_metadata(handle, bh2); -+ if (err) -+ goto journal_error; -+ brelse (bh2); -+ } else { -+ dxtrace(printk("Creating second level index...\n")); -+ memcpy((char *) entries2, (char *) entries, -+ icount * sizeof(struct dx_entry)); -+ dx_set_limit(entries2, dx_node_limit(dir)); -+ -+ /* Set up root */ -+ dx_set_count(entries, 1); -+ dx_set_block(entries + 0, newblock); -+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; -+ -+ /* Add new access path frame */ -+ frame = frames + 1; -+ frame->at = at = at - entries + entries2; -+ frame->entries = entries = entries2; -+ frame->bh = bh2; -+ err = ext3_journal_get_write_access(handle, -+ frame->bh); -+ if (err) -+ goto journal_error; - } -- offset += le16_to_cpu(de->rec_len); -- de = (struct ext3_dir_entry_2 *) -- ((char *) de + le16_to_cpu(de->rec_len)); -+ ext3_journal_dirty_metadata(handle, frames[0].bh); - } -- brelse (bh); -- return -ENOSPC; -+ de = do_split(handle, dir, &bh, frame, &hinfo, &err); -+ if (!de) -+ goto cleanup; -+ err = add_dirent_to_buf(handle, dentry, inode, de, bh); -+ bh = 0; -+ goto cleanup; -+ -+journal_error: -+ ext3_std_error(dir->i_sb, err); -+cleanup: -+ if (bh) -+ brelse(bh); -+ dx_release(frames); -+ return err; - } -+#endif - - /* - * ext3_delete_entry deletes a directory entry by merging it with the -@@ -454,9 +1546,11 @@ - struct inode * inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -480,9 +1574,11 @@ - struct inode *inode; - int err; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -508,9 +1604,11 @@ - if (dir->i_nlink >= EXT3_LINK_MAX) - return -EMLINK; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -522,7 +1620,7 @@ - - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; -- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize; -+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - inode->i_blocks = 0; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { -@@ -555,21 +1653,19 @@ - inode->i_mode |= S_ISGID; - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); -- if (err) -- goto out_no_entry; -+ if (err) { -+ inode->i_nlink = 0; -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - dir->i_nlink++; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- inode->i_nlink = 0; -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - /* -@@ -656,7 +1752,7 @@ - int err = 0, rc; - - lock_super(sb); -- if (!list_empty(&inode->u.ext3_i.i_orphan)) -+ if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - - /* Orphan handling is only valid for files with data blocks -@@ -697,7 +1793,7 @@ - * This is safe: on error we're going to ignore the orphan list - * anyway on the next recovery. */ - if (!err) -- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan); -+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", -@@ -715,25 +1811,26 @@ - int ext3_orphan_del(handle_t *handle, struct inode *inode) - { - struct list_head *prev; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_sb_info *sbi; - unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; - - lock_super(inode->i_sb); -- if (list_empty(&inode->u.ext3_i.i_orphan)) { -+ if (list_empty(&ei->i_orphan)) { - unlock_super(inode->i_sb); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); -- prev = inode->u.ext3_i.i_orphan.prev; -+ prev = ei->i_orphan.prev; - sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - -- list_del(&inode->u.ext3_i.i_orphan); -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ list_del(&ei->i_orphan); -+ INIT_LIST_HEAD(&ei->i_orphan); - - /* If we're on an error path, we may not have a valid - * transaction handle with which to update the orphan list on -@@ -794,8 +1891,9 @@ - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - retval = -ENOENT; - bh = ext3_find_entry (dentry, &de); -@@ -833,7 +1931,7 @@ - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - - end_rmdir: -@@ -851,8 +1949,9 @@ - handle_t *handle; - - handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -879,7 +1978,7 @@ - if (retval) - goto end_unlink; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; - if (!inode->i_nlink) -@@ -905,9 +2004,11 @@ - if (l > dir->i_sb->s_blocksize) - return -ENAMETOOLONG; - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -917,7 +2018,7 @@ - if (IS_ERR(inode)) - goto out_stop; - -- if (l > sizeof (inode->u.ext3_i.i_data)) { -+ if (l > sizeof (EXT3_I(inode)->i_data)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* -@@ -926,24 +2027,22 @@ - * i_size in generic_commit_write(). - */ - err = block_symlink(inode, symname, l); -- if (err) -- goto out_no_entry; -+ if (err) { -+ ext3_dec_count(handle, inode); -+ ext3_mark_inode_dirty(handle, inode); -+ iput (inode); -+ goto out_stop; -+ } - } else { - inode->i_op = &ext3_fast_symlink_inode_operations; -- memcpy((char*)&inode->u.ext3_i.i_data,symname,l); -+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l); - inode->i_size = l-1; - } -- inode->u.ext3_i.i_disksize = inode->i_size; -+ EXT3_I(inode)->i_disksize = inode->i_size; - err = ext3_add_nondir(handle, dentry, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -- --out_no_entry: -- ext3_dec_count(handle, inode); -- ext3_mark_inode_dirty(handle, inode); -- iput (inode); -- goto out_stop; - } - - static int ext3_link (struct dentry * old_dentry, -@@ -956,12 +2055,15 @@ - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) -+ if (inode->i_nlink >= EXT3_LINK_MAX) { - return -EMLINK; -+ } - -- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(dir)) - handle->h_sync = 1; -@@ -994,9 +2096,11 @@ - - old_bh = new_bh = dir_bh = NULL; - -- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2); -- if (IS_ERR(handle)) -+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + -+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); -+ if (IS_ERR(handle)) { - return PTR_ERR(handle); -+ } - - if (IS_SYNC(old_dir) || IS_SYNC(new_dir)) - handle->h_sync = 1; -@@ -1069,14 +2173,37 @@ - /* - * ok, that's it - */ -- ext3_delete_entry(handle, old_dir, old_de, old_bh); -+ if (le32_to_cpu(old_de->inode) != old_inode->i_ino || -+ old_de->name_len != old_dentry->d_name.len || -+ strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) || -+ (retval = ext3_delete_entry(handle, old_dir, -+ old_de, old_bh)) == -ENOENT) { -+ /* old_de could have moved from under us during htree split, so -+ * make sure that we are deleting the right entry. We might -+ * also be pointing to a stale entry in the unused part of -+ * old_bh so just checking inum and the name isn't enough. */ -+ struct buffer_head *old_bh2; -+ struct ext3_dir_entry_2 *old_de2; -+ -+ old_bh2 = ext3_find_entry(old_dentry, &old_de2); -+ if (old_bh2) { -+ retval = ext3_delete_entry(handle, old_dir, -+ old_de2, old_bh2); -+ brelse(old_bh2); -+ } -+ } -+ if (retval) { -+ ext3_warning(old_dir->i_sb, "ext3_rename", -+ "Deleting old file (%lu), %d, error=%d", -+ old_dir->i_ino, old_dir->i_nlink, retval); -+ } - - if (new_inode) { - new_inode->i_nlink--; - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(old_dir); - if (dir_bh) { - BUFFER_TRACE(dir_bh, "get_write_access"); - ext3_journal_get_write_access(handle, dir_bh); -@@ -1088,7 +2215,7 @@ - new_inode->i_nlink--; - } else { - new_dir->i_nlink++; -- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL; -+ ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } - } -Index: linux-2.4.29/fs/ext3/super.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/super.c 2005-04-07 18:59:19.000000000 +0300 -+++ linux-2.4.29/fs/ext3/super.c 2005-05-03 16:29:50.580498544 +0300 -@@ -712,6 +712,7 @@ - es->s_mtime = cpu_to_le32(CURRENT_TIME); - ext3_update_dynamic_rev(sb); - EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -+ - ext3_commit_super (sb, es, 1); - if (test_opt (sb, DEBUG)) - printk (KERN_INFO -@@ -722,6 +723,7 @@ - EXT3_BLOCKS_PER_GROUP(sb), - EXT3_INODES_PER_GROUP(sb), - sbi->s_mount_opt); -+ - printk(KERN_INFO "EXT3 FS " EXT3FS_VERSION ", " EXT3FS_DATE " on %s, ", - bdevname(sb->s_dev)); - if (EXT3_SB(sb)->s_journal->j_inode == NULL) { -@@ -915,6 +917,7 @@ - return res; - } - -+ - struct super_block * ext3_read_super (struct super_block * sb, void * data, - int silent) - { -@@ -1094,6 +1097,9 @@ - sbi->s_mount_state = le16_to_cpu(es->s_state); - sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb)); - sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb)); -+ for (i=0; i < 4; i++) -+ sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); -+ sbi->s_def_hash_version = es->s_def_hash_version; - - if (sbi->s_blocks_per_group > blocksize * 8) { - printk (KERN_ERR -@@ -1845,6 +1851,7 @@ - unregister_filesystem(&ext3_fs_type); - } - -+EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); - - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); -Index: linux-2.4.29/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-04-07 18:52:26.000000000 +0300 -+++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 16:29:50.584497936 +0300 -@@ -40,6 +40,11 @@ - #define EXT3FS_VERSION "2.4-0.9.19" - - /* -+ * Always enable hashed directories -+ */ -+#define CONFIG_EXT3_INDEX -+ -+/* - * Debug code - */ - #ifdef EXT3FS_DEBUG -@@ -593,9 +598,46 @@ - #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) - #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ - ~EXT3_DIR_ROUND) -+/* -+ * Hash Tree Directory indexing -+ * (c) Daniel Phillips, 2001 -+ */ -+ -+#ifdef CONFIG_EXT3_INDEX -+ #define is_dx(dir) (EXT3_HAS_COMPAT_FEATURE(dir->i_sb, \ -+ EXT3_FEATURE_COMPAT_DIR_INDEX) && \ -+ (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) -+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1) -+#else -+ #define is_dx(dir) 0 -+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX) -+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2) -+#endif -+ -+/* Legal values for the dx_root hash_version field: */ -+ -+#define DX_HASH_LEGACY 0 -+#define DX_HASH_HALF_MD4 1 -+#define DX_HASH_TEA 2 -+ -+/* hash info structure used by the directory hash */ -+struct dx_hash_info -+{ -+ u32 hash; -+ u32 minor_hash; -+ int hash_version; -+ u32 *seed; -+}; - - #ifdef __KERNEL__ - /* -+ * Control parameters used by ext3_htree_next_block -+ */ -+#define HASH_NB_ALWAYS 1 -+ -+ -+/* - * Describe an inode's exact location on disk and in memory - */ - struct ext3_iloc -@@ -605,6 +647,27 @@ - unsigned long block_group; - }; - -+ -+/* -+ * This structure is stuffed into the struct file's private_data field -+ * for directories. It is where we put information so that we can do -+ * readdir operations in hash tree order. -+ */ -+struct dir_private_info { -+ rb_root_t root; -+ rb_node_t *curr_node; -+ struct fname *extra_fname; -+ loff_t last_pos; -+ __u32 curr_hash; -+ __u32 curr_minor_hash; -+ __u32 next_hash; -+}; -+ -+/* -+ * Special error return code only used by dx_probe() and its callers. -+ */ -+#define ERR_BAD_DX_DIR -75000 -+ - /* - * Function prototypes - */ -@@ -632,11 +695,20 @@ - - /* dir.c */ - extern int ext3_check_dir_entry(const char *, struct inode *, -- struct ext3_dir_entry_2 *, struct buffer_head *, -- unsigned long); -+ struct ext3_dir_entry_2 *, -+ struct buffer_head *, unsigned long); -+extern int ext3_htree_store_dirent(struct file *dir_file, __u32 hash, -+ __u32 minor_hash, -+ struct ext3_dir_entry_2 *dirent); -+extern void ext3_htree_free_dir_info(struct dir_private_info *p); -+ - /* fsync.c */ - extern int ext3_sync_file (struct file *, struct dentry *, int); - -+/* hash.c */ -+extern int ext3fs_dirhash(const char *name, int len, struct -+ dx_hash_info *hinfo); -+ - /* ialloc.c */ - extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int); - extern void ext3_free_inode (handle_t *, struct inode *); -@@ -669,6 +741,8 @@ - /* namei.c */ - extern int ext3_orphan_add(handle_t *, struct inode *); - extern int ext3_orphan_del(handle_t *, struct inode *); -+extern int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, -+ __u32 start_minor_hash, __u32 *next_hash); - - /* super.c */ - extern void ext3_error (struct super_block *, const char *, const char *, ...) -Index: linux-2.4.29/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs_sb.h 2005-04-07 18:54:55.000000000 +0300 -+++ linux-2.4.29/include/linux/ext3_fs_sb.h 2005-05-03 16:29:50.586497632 +0300 -@@ -62,6 +62,8 @@ - int s_inode_size; - int s_first_ino; - u32 s_next_generation; -+ u32 s_hash_seed[4]; -+ int s_def_hash_version; - - /* Journaling */ - struct inode * s_journal_inode; -Index: linux-2.4.29/include/linux/ext3_jbd.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_jbd.h 2005-04-07 18:52:32.000000000 +0300 -+++ linux-2.4.29/include/linux/ext3_jbd.h 2005-05-03 16:29:50.587497480 +0300 -@@ -63,6 +63,8 @@ - - #define EXT3_RESERVE_TRANS_BLOCKS 12U - -+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8 -+ - int - ext3_mark_iloc_dirty(handle_t *handle, - struct inode *inode, diff --git a/lustre/kernel_patches/patches/ext3-ialloc-2.4.21-suse2.patch b/lustre/kernel_patches/patches/ext3-ialloc-2.4.21-suse2.patch deleted file mode 100644 index acd404e..0000000 --- a/lustre/kernel_patches/patches/ext3-ialloc-2.4.21-suse2.patch +++ /dev/null @@ -1,237 +0,0 @@ -Index: linux-2.4.21-suse2/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/ialloc.c 2005-08-04 09:14:23.000000000 -0600 -+++ linux-2.4.21-suse2/fs/ext3/ialloc.c 2005-08-04 09:17:49.000000000 -0600 -@@ -328,19 +328,140 @@ - * directories already is chosen. - * - * For other inodes, search forward from the parent directory's block -- * group to find a free inode. -+ * group to find a free inode in a group with some free blocks. - */ -+static int find_group_dir(struct super_block *sb, const struct inode *parent, -+ struct ext3_group_desc **best_desc, -+ struct buffer_head **best_bh) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int ngroups = sbi->s_groups_count; -+ int avefreei; -+ struct ext3_group_desc *desc; -+ struct buffer_head *bh; -+ int group, best_group = -1, ndir_best = 999999999; -+ -+ *best_desc = NULL; -+ *best_bh = NULL; -+ -+ avefreei = le32_to_cpu(sbi->s_es->s_free_inodes_count) / ngroups; -+ -+ for (group = 0; group < ngroups; group++) { -+ desc = ext3_get_group_desc(sb, group, &bh); -+ if (!desc || !desc->bg_free_inodes_count) -+ continue; -+ if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei) -+ continue; -+ if (le16_to_cpu(desc->bg_used_dirs_count) > ndir_best) -+ continue; -+ if (!*best_desc || -+ (le16_to_cpu(desc->bg_free_blocks_count) > -+ le16_to_cpu((*best_desc)->bg_free_blocks_count))) { -+ *best_bh = bh; -+ *best_desc = desc; -+ best_group = group; -+ ndir_best = le16_to_cpu(desc->bg_used_dirs_count); -+ } -+ } -+ -+ return best_group; -+} -+ -+static int find_group_other(struct super_block *sb, const struct inode *parent, -+ struct ext3_group_desc **best_desc, -+ struct buffer_head **best_bh) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int parent_group = EXT3_I(parent)->i_block_group; -+ int ngroups = sbi->s_groups_count; -+ int avefreeb; -+ struct ext3_group_desc *desc; -+ struct buffer_head *bh; -+ int group, i, best_group = -1; -+ -+ *best_desc = NULL; -+ *best_bh = NULL; -+ -+ /* -+ * Try to place the inode in its parent directory -+ */ -+ group = parent_group; -+ desc = ext3_get_group_desc (sb, group, &bh); -+ if (desc && le16_to_cpu(desc->bg_free_inodes_count) && -+ le16_to_cpu(desc->bg_free_blocks_count)) { -+ *best_desc = desc; -+ *best_bh = bh; -+ return group; -+ } -+ -+ /* -+ * We're going to place this inode in a different blockgroup from its -+ * parent. We want to cause files in a common directory to all land in -+ * the same blockgroup if it has space. But we want files which are -+ * in a different directory which shares a blockgroup with our parent -+ * to land in a different blockgroup. -+ * -+ * So add our directory's i_ino into the starting point for the hash. -+ */ -+ group = (group + parent->i_ino) % ngroups; -+ -+ avefreeb = le32_to_cpu(sbi->s_es->s_free_blocks_count) / -+ sbi->s_groups_count / ngroups; -+ -+ /* -+ * Use a quadratic hash to find a group with a free inode and some free -+ * blocks. -+ */ -+ for (i = 1; i < ngroups; i <<= 1) { -+ group += i; -+ if (group >= ngroups) -+ group -= ngroups; -+ desc = ext3_get_group_desc(sb, group, &bh); -+ if (!desc || !desc->bg_free_inodes_count) -+ continue; -+ if (le16_to_cpu(desc->bg_free_blocks_count) > avefreeb) { -+ *best_bh = bh; -+ *best_desc = desc; -+ return group; -+ } -+ } -+ -+ /* -+ * That failed: try linear search for a group with free inodes and -+ * preferrably free blocks, returning as soon as we find a good one. -+ */ -+ group = sbi->s_last_group; -+ for (i = 0; i < ngroups; i++) { -+ if (++group >= ngroups) -+ group = 0; -+ desc = ext3_get_group_desc(sb, group, &bh); -+ if (!desc || !desc->bg_free_inodes_count) -+ continue; -+ if (!*best_desc || -+ (le16_to_cpu(desc->bg_free_blocks_count) > -+ le16_to_cpu((*best_desc)->bg_free_blocks_count))) { -+ *best_bh = bh; -+ *best_desc = desc; -+ best_group = group; -+ if (le16_to_cpu(desc->bg_free_blocks_count) >= avefreeb) -+ break; -+ } -+ } -+ sbi->s_last_group = best_group; -+ -+ return best_group; -+} -+ - struct inode * ext3_new_inode(handle_t *handle, const struct inode * dir, - int mode, unsigned long goal) - { - struct super_block * sb; - struct buffer_head * bh; - struct buffer_head * bh2; -- int i, j, avefreei; -+ int i, j; - struct inode * inode; - int bitmap_nr; - struct ext3_group_desc * gdp; -- struct ext3_group_desc * tmp; - struct ext3_super_block * es; - struct ext3_iloc iloc; - int err = 0; -@@ -392,72 +513,10 @@ - } - - repeat: -- gdp = NULL; -- i = 0; -- -- if (S_ISDIR(mode)) { -- avefreei = le32_to_cpu(es->s_free_inodes_count) / -- sb->u.ext3_sb.s_groups_count; -- if (!gdp) { -- for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) { -- struct buffer_head *temp_buffer; -- tmp = ext3_get_group_desc (sb, j, &temp_buffer); -- if (tmp && -- le16_to_cpu(tmp->bg_free_inodes_count) && -- le16_to_cpu(tmp->bg_free_inodes_count) >= -- avefreei) { -- if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) > -- le16_to_cpu(gdp->bg_free_blocks_count))) { -- i = j; -- gdp = tmp; -- bh2 = temp_buffer; -- } -- } -- } -- } -- } else { -- /* -- * Try to place the inode in its parent directory -- */ -- i = dir->u.ext3_i.i_block_group; -- tmp = ext3_get_group_desc (sb, i, &bh2); -- if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) -- gdp = tmp; -- else -- { -- /* -- * Use a quadratic hash to find a group with a -- * free inode -- */ -- for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) { -- i += j; -- if (i >= sb->u.ext3_sb.s_groups_count) -- i -= sb->u.ext3_sb.s_groups_count; -- tmp = ext3_get_group_desc (sb, i, &bh2); -- if (tmp && -- le16_to_cpu(tmp->bg_free_inodes_count)) { -- gdp = tmp; -- break; -- } -- } -- } -- if (!gdp) { -- /* -- * That failed: try linear search for a free inode -- */ -- i = dir->u.ext3_i.i_block_group + 1; -- for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) { -- if (++i >= sb->u.ext3_sb.s_groups_count) -- i = 0; -- tmp = ext3_get_group_desc (sb, i, &bh2); -- if (tmp && -- le16_to_cpu(tmp->bg_free_inodes_count)) { -- gdp = tmp; -- break; -- } -- } -- } -- } -+ if (S_ISDIR(mode)) -+ i = find_group_dir(sb, dir, &gdp, &bh2); -+ else -+ i = find_group_other(sb, dir, &gdp, &bh2); - - err = -ENOSPC; - if (!gdp) -Index: linux-2.4.21-suse2/include/linux/ext3_fs_sb.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/ext3_fs_sb.h 2005-08-04 09:14:21.000000000 -0600 -+++ linux-2.4.21-suse2/include/linux/ext3_fs_sb.h 2005-08-04 09:19:32.000000000 -0600 -@@ -45,6 +45,7 @@ - unsigned long s_gdb_count; /* Number of group descriptor blocks */ - unsigned long s_desc_per_block; /* Number of group descriptors per block */ - unsigned long s_groups_count; /* Number of groups in the fs */ -+ unsigned long s_last_group; /* Last group used for inode allocation */ - struct buffer_head * s_sbh; /* Buffer containing the super block */ - struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */ - struct buffer_head ** s_group_desc; diff --git a/lustre/kernel_patches/patches/ext3-ialloc-2.4.24.patch b/lustre/kernel_patches/patches/ext3-ialloc-2.4.24.patch deleted file mode 100644 index 83e25fa..0000000 --- a/lustre/kernel_patches/patches/ext3-ialloc-2.4.24.patch +++ /dev/null @@ -1,238 +0,0 @@ -Index: lum/fs/ext3/ialloc.c -=================================================================== ---- lum.orig/fs/ext3/ialloc.c 2004-08-26 13:14:35.000000000 -0600 -+++ lum/fs/ext3/ialloc.c 2004-08-31 15:00:35.000000000 -0600 -@@ -327,8 +327,130 @@ int ext3_itable_block_used(struct super_ - * directories already is chosen. - * - * For other inodes, search forward from the parent directory's block -- * group to find a free inode. -+ * group to find a free inode in a group with some free blocks. - */ -+static int find_group_dir(struct super_block *sb, const struct inode *parent, -+ struct ext3_group_desc **best_desc, -+ struct buffer_head **best_bh) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int ngroups = sbi->s_groups_count; -+ int avefreei; -+ struct ext3_group_desc *desc; -+ struct buffer_head *bh; -+ int group, best_group = -1, ndir_best = 999999999; -+ -+ *best_desc = NULL; -+ *best_bh = NULL; -+ -+ avefreei = le32_to_cpu(sbi->s_es->s_free_inodes_count) / ngroups; -+ -+ for (group = 0; group < ngroups; group++) { -+ desc = ext3_get_group_desc(sb, group, &bh); -+ if (!desc || !desc->bg_free_inodes_count) -+ continue; -+ if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei) -+ continue; -+ if (le16_to_cpu(desc->bg_used_dirs_count) > ndir_best) -+ continue; -+ if (!*best_desc || -+ (le16_to_cpu(desc->bg_free_blocks_count) > -+ le16_to_cpu((*best_desc)->bg_free_blocks_count))) { -+ *best_bh = bh; -+ *best_desc = desc; -+ best_group = group; -+ ndir_best = le16_to_cpu(desc->bg_used_dirs_count); -+ } -+ } -+ -+ return best_group; -+} -+ -+static int find_group_other(struct super_block *sb, const struct inode *parent, -+ struct ext3_group_desc **best_desc, -+ struct buffer_head **best_bh) -+{ -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ int parent_group = EXT3_I(parent)->i_block_group; -+ int ngroups = sbi->s_groups_count; -+ int avefreeb; -+ struct ext3_group_desc *desc; -+ struct buffer_head *bh; -+ int group, i, best_group = -1; -+ -+ *best_desc = NULL; -+ *best_bh = NULL; -+ -+ /* -+ * Try to place the inode in its parent directory -+ */ -+ group = parent_group; -+ desc = ext3_get_group_desc (sb, group, &bh); -+ if (desc && le16_to_cpu(desc->bg_free_inodes_count) && -+ le16_to_cpu(desc->bg_free_blocks_count)) { -+ *best_desc = desc; -+ *best_bh = bh; -+ return group; -+ } -+ -+ /* -+ * We're going to place this inode in a different blockgroup from its -+ * parent. We want to cause files in a common directory to all land in -+ * the same blockgroup if it has space. But we want files which are -+ * in a different directory which shares a blockgroup with our parent -+ * to land in a different blockgroup. -+ * -+ * So add our directory's i_ino into the starting point for the hash. -+ */ -+ group = (group + parent->i_ino) % ngroups; -+ -+ avefreeb = le32_to_cpu(sbi->s_es->s_free_blocks_count) / -+ sbi->s_groups_count / ngroups; -+ -+ /* -+ * Use a quadratic hash to find a group with a free inode and some free -+ * blocks. -+ */ -+ for (i = 1; i < ngroups; i <<= 1) { -+ group += i; -+ if (group >= ngroups) -+ group -= ngroups; -+ desc = ext3_get_group_desc(sb, group, &bh); -+ if (!desc || !desc->bg_free_inodes_count) -+ continue; -+ if (le16_to_cpu(desc->bg_free_blocks_count) > avefreeb) { -+ *best_bh = bh; -+ *best_desc = desc; -+ return group; -+ } -+ } -+ -+ /* -+ * That failed: try linear search for a group with free inodes and -+ * preferrably free blocks, returning as soon as we find a good one. -+ */ -+ group = sbi->s_last_group; -+ for (i = 0; i < ngroups; i++) { -+ if (++group >= ngroups) -+ group = 0; -+ desc = ext3_get_group_desc(sb, group, &bh); -+ if (!desc || !desc->bg_free_inodes_count) -+ continue; -+ if (!*best_desc || -+ (le16_to_cpu(desc->bg_free_blocks_count) > -+ le16_to_cpu((*best_desc)->bg_free_blocks_count))) { -+ *best_bh = bh; -+ *best_desc = desc; -+ best_group = group; -+ if (le16_to_cpu(desc->bg_free_blocks_count) >= avefreeb) -+ break; -+ } -+ } -+ sbi->s_last_group = best_group; -+ -+ return best_group; -+} -+ - struct inode * ext3_new_inode (handle_t *handle, - const struct inode * dir, int mode, - unsigned long goal) -@@ -336,11 +459,10 @@ struct inode * ext3_new_inode (handle_t - struct super_block * sb; - struct buffer_head * bh; - struct buffer_head * bh2; -- int i, j, avefreei; -+ int i, j; - struct inode * inode; - int bitmap_nr; - struct ext3_group_desc * gdp; -- struct ext3_group_desc * tmp; - struct ext3_super_block * es; - struct ext3_iloc iloc; - int err = 0; -@@ -392,72 +514,10 @@ struct inode * ext3_new_inode (handle_t - } - - repeat: -- gdp = NULL; -- i = 0; -- -- if (S_ISDIR(mode)) { -- avefreei = le32_to_cpu(es->s_free_inodes_count) / -- sb->u.ext3_sb.s_groups_count; -- if (!gdp) { -- for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) { -- struct buffer_head *temp_buffer; -- tmp = ext3_get_group_desc (sb, j, &temp_buffer); -- if (tmp && -- le16_to_cpu(tmp->bg_free_inodes_count) && -- le16_to_cpu(tmp->bg_free_inodes_count) >= -- avefreei) { -- if (!gdp || (le16_to_cpu(tmp->bg_free_blocks_count) > -- le16_to_cpu(gdp->bg_free_blocks_count))) { -- i = j; -- gdp = tmp; -- bh2 = temp_buffer; -- } -- } -- } -- } -- } else { -- /* -- * Try to place the inode in its parent directory -- */ -- i = dir->u.ext3_i.i_block_group; -- tmp = ext3_get_group_desc (sb, i, &bh2); -- if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) -- gdp = tmp; -- else -- { -- /* -- * Use a quadratic hash to find a group with a -- * free inode -- */ -- for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) { -- i += j; -- if (i >= sb->u.ext3_sb.s_groups_count) -- i -= sb->u.ext3_sb.s_groups_count; -- tmp = ext3_get_group_desc (sb, i, &bh2); -- if (tmp && -- le16_to_cpu(tmp->bg_free_inodes_count)) { -- gdp = tmp; -- break; -- } -- } -- } -- if (!gdp) { -- /* -- * That failed: try linear search for a free inode -- */ -- i = dir->u.ext3_i.i_block_group + 1; -- for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) { -- if (++i >= sb->u.ext3_sb.s_groups_count) -- i = 0; -- tmp = ext3_get_group_desc (sb, i, &bh2); -- if (tmp && -- le16_to_cpu(tmp->bg_free_inodes_count)) { -- gdp = tmp; -- break; -- } -- } -- } -- } -+ if (S_ISDIR(mode)) -+ i = find_group_dir(sb, dir, &gdp, &bh2); -+ else -+ i = find_group_other(sb, dir, &gdp, &bh2); - - err = -ENOSPC; - if (!gdp) -Index: lum/include/linux/ext3_fs_sb.h -=================================================================== ---- lum.orig/include/linux/ext3_fs_sb.h 2004-08-26 13:28:53.000000000 -0600 -+++ lum/include/linux/ext3_fs_sb.h 2004-08-31 11:04:27.000000000 -0600 -@@ -45,6 +45,7 @@ struct ext3_sb_info { - unsigned long s_gdb_count; /* Number of group descriptor blocks */ - unsigned long s_desc_per_block; /* Number of group descriptors per block */ - unsigned long s_groups_count; /* Number of groups in the fs */ -+ unsigned long s_last_group; /* Last group used for inode allocation */ - struct buffer_head * s_sbh; /* Buffer containing the super block */ - struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */ - struct buffer_head ** s_group_desc; diff --git a/lustre/kernel_patches/patches/ext3-ino_sb_macro-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-ino_sb_macro-2.4.21-chaos.patch deleted file mode 100644 index fb739a5..0000000 --- a/lustre/kernel_patches/patches/ext3-ino_sb_macro-2.4.21-chaos.patch +++ /dev/null @@ -1,1514 +0,0 @@ -Index: linux-2.4.21-chaos/fs/ext3/balloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/balloc.c 2003-07-15 02:09:35.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/balloc.c 2003-12-12 12:50:34.000000000 +0300 -@@ -46,18 +46,18 @@ - unsigned long desc; - struct ext3_group_desc * gdp; - -- if (block_group >= sb->u.ext3_sb.s_groups_count) { -+ if (block_group >= EXT3_SB(sb)->s_groups_count) { - ext3_error (sb, "ext3_get_group_desc", - "block_group >= groups_count - " - "block_group = %d, groups_count = %lu", -- block_group, sb->u.ext3_sb.s_groups_count); -+ block_group, EXT3_SB(sb)->s_groups_count); - - return NULL; - } - - group_desc = block_group / EXT3_DESC_PER_BLOCK(sb); - desc = block_group % EXT3_DESC_PER_BLOCK(sb); -- if (!sb->u.ext3_sb.s_group_desc[group_desc]) { -+ if (!EXT3_SB(sb)->s_group_desc[group_desc]) { - ext3_error (sb, "ext3_get_group_desc", - "Group descriptor not loaded - " - "block_group = %d, group_desc = %lu, desc = %lu", -@@ -66,9 +66,9 @@ - } - - gdp = (struct ext3_group_desc *) -- sb->u.ext3_sb.s_group_desc[group_desc]->b_data; -+ EXT3_SB(sb)->s_group_desc[group_desc]->b_data; - if (bh) -- *bh = sb->u.ext3_sb.s_group_desc[group_desc]; -+ *bh = EXT3_SB(sb)->s_group_desc[group_desc]; - return gdp + desc; - } - -@@ -104,8 +104,8 @@ - * this group. The IO will be retried next time. - */ - error_out: -- sb->u.ext3_sb.s_block_bitmap_number[bitmap_nr] = block_group; -- sb->u.ext3_sb.s_block_bitmap[bitmap_nr] = bh; -+ EXT3_SB(sb)->s_block_bitmap_number[bitmap_nr] = block_group; -+ EXT3_SB(sb)->s_block_bitmap[bitmap_nr] = bh; - return retval; - } - -@@ -128,16 +128,17 @@ - int i, j, retval = 0; - unsigned long block_bitmap_number; - struct buffer_head * block_bitmap; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); - -- if (block_group >= sb->u.ext3_sb.s_groups_count) -+ if (block_group >= sbi->s_groups_count) - ext3_panic (sb, "load_block_bitmap", - "block_group >= groups_count - " - "block_group = %d, groups_count = %lu", -- block_group, sb->u.ext3_sb.s_groups_count); -+ block_group, EXT3_SB(sb)->s_groups_count); - -- if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED) { -- if (sb->u.ext3_sb.s_block_bitmap[block_group]) { -- if (sb->u.ext3_sb.s_block_bitmap_number[block_group] == -+ if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED) { -+ if (sbi->s_block_bitmap[block_group]) { -+ if (sbi->s_block_bitmap_number[block_group] == - block_group) - return block_group; - ext3_error (sb, "__load_block_bitmap", -@@ -149,21 +150,20 @@ - return block_group; - } - -- for (i = 0; i < sb->u.ext3_sb.s_loaded_block_bitmaps && -- sb->u.ext3_sb.s_block_bitmap_number[i] != block_group; i++) -+ for (i = 0; i < sbi->s_loaded_block_bitmaps && -+ sbi->s_block_bitmap_number[i] != block_group; i++) - ; -- if (i < sb->u.ext3_sb.s_loaded_block_bitmaps && -- sb->u.ext3_sb.s_block_bitmap_number[i] == block_group) { -- block_bitmap_number = sb->u.ext3_sb.s_block_bitmap_number[i]; -- block_bitmap = sb->u.ext3_sb.s_block_bitmap[i]; -+ if (i < sbi->s_loaded_block_bitmaps && -+ sbi->s_block_bitmap_number[i] == block_group) { -+ block_bitmap_number = sbi->s_block_bitmap_number[i]; -+ block_bitmap = sbi->s_block_bitmap[i]; - for (j = i; j > 0; j--) { -- sb->u.ext3_sb.s_block_bitmap_number[j] = -- sb->u.ext3_sb.s_block_bitmap_number[j - 1]; -- sb->u.ext3_sb.s_block_bitmap[j] = -- sb->u.ext3_sb.s_block_bitmap[j - 1]; -+ sbi->s_block_bitmap_number[j] = -+ sbi->s_block_bitmap_number[j - 1]; -+ sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1]; - } -- sb->u.ext3_sb.s_block_bitmap_number[0] = block_bitmap_number; -- sb->u.ext3_sb.s_block_bitmap[0] = block_bitmap; -+ sbi->s_block_bitmap_number[0] = block_bitmap_number; -+ sbi->s_block_bitmap[0] = block_bitmap; - - /* - * There's still one special case here --- if block_bitmap == 0 -@@ -173,17 +173,14 @@ - if (!block_bitmap) - retval = read_block_bitmap (sb, block_group, 0); - } else { -- if (sb->u.ext3_sb.s_loaded_block_bitmapsu.ext3_sb.s_loaded_block_bitmaps++; -+ if (sbi->s_loaded_block_bitmapss_loaded_block_bitmaps++; - else -- brelse (sb->u.ext3_sb.s_block_bitmap -- [EXT3_MAX_GROUP_LOADED - 1]); -- for (j = sb->u.ext3_sb.s_loaded_block_bitmaps - 1; -- j > 0; j--) { -- sb->u.ext3_sb.s_block_bitmap_number[j] = -- sb->u.ext3_sb.s_block_bitmap_number[j - 1]; -- sb->u.ext3_sb.s_block_bitmap[j] = -- sb->u.ext3_sb.s_block_bitmap[j - 1]; -+ brelse(sbi->s_block_bitmap[EXT3_MAX_GROUP_LOADED - 1]); -+ for (j = sbi->s_loaded_block_bitmaps - 1; j > 0; j--) { -+ sbi->s_block_bitmap_number[j] = -+ sbi->s_block_bitmap_number[j - 1]; -+ sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1]; - } - retval = read_block_bitmap (sb, block_group, 0); - } -@@ -206,24 +203,25 @@ - static inline int load_block_bitmap (struct super_block * sb, - unsigned int block_group) - { -+ struct ext3_sb_info *sbi = EXT3_SB(sb); - int slot; -- -+ - /* - * Do the lookup for the slot. First of all, check if we're asking - * for the same slot as last time, and did we succeed that last time? - */ -- if (sb->u.ext3_sb.s_loaded_block_bitmaps > 0 && -- sb->u.ext3_sb.s_block_bitmap_number[0] == block_group && -- sb->u.ext3_sb.s_block_bitmap[0]) { -+ if (sbi->s_loaded_block_bitmaps > 0 && -+ sbi->s_block_bitmap_number[0] == block_group && -+ sbi->s_block_bitmap[0]) { - return 0; - } - /* - * Or can we do a fast lookup based on a loaded group on a filesystem - * small enough to be mapped directly into the superblock? - */ -- else if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED && -- sb->u.ext3_sb.s_block_bitmap_number[block_group]==block_group -- && sb->u.ext3_sb.s_block_bitmap[block_group]) { -+ else if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED && -+ sbi->s_block_bitmap_number[block_group] == block_group -+ && sbi->s_block_bitmap[block_group]) { - slot = block_group; - } - /* -@@ -243,7 +241,7 @@ - * If it's a valid slot, we may still have cached a previous IO error, - * in which case the bh in the superblock cache will be zero. - */ -- if (!sb->u.ext3_sb.s_block_bitmap[slot]) -+ if (!sbi->s_block_bitmap[slot]) - return -EIO; - - /* -@@ -275,7 +273,7 @@ - return; - } - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; - if (block < le32_to_cpu(es->s_first_data_block) || - block + count < block || - (block + count) > le32_to_cpu(es->s_blocks_count)) { -@@ -305,7 +303,7 @@ - if (bitmap_nr < 0) - goto error_return; - -- bitmap_bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr]; -+ bitmap_bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr]; - gdp = ext3_get_group_desc (sb, block_group, &gd_bh); - if (!gdp) - goto error_return; -@@ -330,8 +328,8 @@ - if (err) - goto error_return; - -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access"); -- err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); - if (err) - goto error_return; - -@@ -409,8 +407,8 @@ - if (!err) err = ret; - - /* And the superblock */ -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "dirtied superblock"); -- ret = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "dirtied superblock"); -+ ret = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - if (!err) err = ret; - - if (overflow && !err) { -@@ -563,12 +561,12 @@ - } - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; - if (le32_to_cpu(es->s_free_blocks_count) <= - le32_to_cpu(es->s_r_blocks_count) && -- ((sb->u.ext3_sb.s_resuid != current->fsuid) && -- (sb->u.ext3_sb.s_resgid == 0 || -- !in_group_p (sb->u.ext3_sb.s_resgid)) && -+ ((EXT3_SB(sb)->s_resuid != current->fsuid) && -+ (EXT3_SB(sb)->s_resgid == 0 || -+ !in_group_p (EXT3_SB(sb)->s_resgid)) && - !capable(CAP_SYS_RESOURCE))) - goto out; - -@@ -598,7 +596,7 @@ - if (bitmap_nr < 0) - goto io_error; - -- bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr]; -+ bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr]; - - ext3_debug ("goal is at %d:%d.\n", i, j); - -@@ -621,9 +619,9 @@ - * Now search the rest of the groups. We assume that - * i and gdp correctly point to the last group visited. - */ -- for (k = 0; k < sb->u.ext3_sb.s_groups_count; k++) { -+ for (k = 0; k < EXT3_SB(sb)->s_groups_count; k++) { - i++; -- if (i >= sb->u.ext3_sb.s_groups_count) -+ if (i >= EXT3_SB(sb)->s_groups_count) - i = 0; - gdp = ext3_get_group_desc (sb, i, &bh2); - if (!gdp) { -@@ -635,7 +633,7 @@ - if (bitmap_nr < 0) - goto io_error; - -- bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr]; -+ bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr]; - j = find_next_usable_block(-1, bh, - EXT3_BLOCKS_PER_GROUP(sb)); - if (j >= 0) -@@ -673,8 +671,8 @@ - fatal = ext3_journal_get_write_access(handle, bh2); - if (fatal) goto out; - -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access"); -- fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access"); -+ fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); - if (fatal) goto out; - - tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb) -@@ -807,7 +805,7 @@ - if (!fatal) fatal = err; - - BUFFER_TRACE(bh, "journal_dirty_metadata for superblock"); -- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - if (!fatal) fatal = err; - - sb->s_dirt = 1; -@@ -845,11 +843,11 @@ - int i; - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; - desc_count = 0; - bitmap_count = 0; - gdp = NULL; -- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) { -+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { - gdp = ext3_get_group_desc (sb, i, NULL); - if (!gdp) - continue; -@@ -858,7 +856,7 @@ - if (bitmap_nr < 0) - continue; - -- x = ext3_count_free (sb->u.ext3_sb.s_block_bitmap[bitmap_nr], -+ x = ext3_count_free (EXT3_SB(sb)->s_block_bitmap[bitmap_nr], - sb->s_blocksize); - printk ("group %d: stored = %d, counted = %lu\n", - i, le16_to_cpu(gdp->bg_free_blocks_count), x); -@@ -869,7 +867,7 @@ - unlock_super (sb); - return bitmap_count; - #else -- return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count); -+ return le32_to_cpu(EXT3_SB(sb)->s_es->s_free_blocks_count); - #endif - } - -@@ -878,7 +876,7 @@ - unsigned char * map) - { - return ext3_test_bit ((block - -- le32_to_cpu(sb->u.ext3_sb.s_es->s_first_data_block)) % -+ le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) % - EXT3_BLOCKS_PER_GROUP(sb), map); - } - -@@ -946,11 +944,11 @@ - struct ext3_group_desc * gdp; - int i; - -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; - desc_count = 0; - bitmap_count = 0; - gdp = NULL; -- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) { -+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { - gdp = ext3_get_group_desc (sb, i, NULL); - if (!gdp) - continue; -@@ -984,7 +982,7 @@ - "Inode bitmap for group %d is marked free", - i); - -- for (j = 0; j < sb->u.ext3_sb.s_itb_per_group; j++) -+ for (j = 0; j < EXT3_SB(sb)->s_itb_per_group; j++) - if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, - sb, bh->b_data)) - ext3_error (sb, "ext3_check_blocks_bitmap", -Index: linux-2.4.21-chaos/fs/ext3/dir.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/dir.c 2003-12-12 11:36:13.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/dir.c 2003-12-12 12:50:34.000000000 +0300 -@@ -67,7 +67,7 @@ - else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) - error_msg = "directory entry across blocks"; - else if (le32_to_cpu(de->inode) > -- le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) -+ le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count)) - error_msg = "inode out of bounds"; - - if (error_msg != NULL) -Index: linux-2.4.21-chaos/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/ialloc.c 2003-12-12 12:53:11.000000000 +0300 -@@ -75,8 +75,8 @@ - * this group. The IO will be retried next time. - */ - error_out: -- sb->u.ext3_sb.s_inode_bitmap_number[bitmap_nr] = block_group; -- sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh; -+ EXT3_SB(sb)->s_inode_bitmap_number[bitmap_nr] = block_group; -+ EXT3_SB(sb)->s_inode_bitmap[bitmap_nr] = bh; - return retval; - } - -@@ -228,7 +228,7 @@ - clear_inode (inode); - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; - if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { - ext3_error (sb, "ext3_free_inode", - "reserved or nonexistent inode %lu", ino); -@@ -240,7 +240,7 @@ - if (bitmap_nr < 0) - goto error_return; - -- bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr]; -+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; - - BUFFER_TRACE(bh, "get_write_access"); - fatal = ext3_journal_get_write_access(handle, bh); -@@ -258,8 +258,8 @@ - fatal = ext3_journal_get_write_access(handle, bh2); - if (fatal) goto error_return; - -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get write access"); -- fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get write access"); -+ fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); - if (fatal) goto error_return; - - if (gdp) { -@@ -274,9 +274,9 @@ - if (!fatal) fatal = err; - es->s_free_inodes_count = - cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1); -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, - "call ext3_journal_dirty_metadata"); -- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - if (!fatal) fatal = err; - } - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -@@ -307,6 +307,8 @@ - int i, j, avefreei; - struct inode * inode; - int bitmap_nr; -+ struct ext3_inode_info *ei; -+ struct ext3_sb_info *sbi; - struct ext3_group_desc * gdp; - struct ext3_group_desc * tmp; - struct ext3_super_block * es; -@@ -320,19 +322,21 @@ - inode = new_inode(sb); - if (!inode) - return ERR_PTR(-ENOMEM); -- init_rwsem(&inode->u.ext3_i.truncate_sem); -+ sbi = EXT3_SB(sb); -+ ei = EXT3_I(inode); -+ init_rwsem(&ei->truncate_sem); - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = sbi->s_es; - repeat: - gdp = NULL; - i = 0; - - if (S_ISDIR(mode)) { - avefreei = le32_to_cpu(es->s_free_inodes_count) / -- sb->u.ext3_sb.s_groups_count; -+ sbi->s_groups_count; - if (!gdp) { -- for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) { -+ for (j = 0; j < sbi->s_groups_count; j++) { - struct buffer_head *temp_buffer; - tmp = ext3_get_group_desc (sb, j, &temp_buffer); - if (tmp && -@@ -352,7 +356,7 @@ - /* - * Try to place the inode in its parent directory - */ -- i = dir->u.ext3_i.i_block_group; -+ i = EXT3_I(dir)->i_block_group; - tmp = ext3_get_group_desc (sb, i, &bh2); - if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) - gdp = tmp; -@@ -362,10 +366,10 @@ - * Use a quadratic hash to find a group with a - * free inode - */ -- for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) { -+ for (j = 1; j < sbi->s_groups_count; j <<= 1) { - i += j; -- if (i >= sb->u.ext3_sb.s_groups_count) -- i -= sb->u.ext3_sb.s_groups_count; -+ if (i >= sbi->s_groups_count) -+ i -= sbi->s_groups_count; - tmp = ext3_get_group_desc (sb, i, &bh2); - if (tmp && - le16_to_cpu(tmp->bg_free_inodes_count)) { -@@ -378,9 +382,9 @@ - /* - * That failed: try linear search for a free inode - */ -- i = dir->u.ext3_i.i_block_group + 1; -- for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) { -- if (++i >= sb->u.ext3_sb.s_groups_count) -+ i = EXT3_I(dir)->i_block_group + 1; -+ for (j = 2; j < sbi->s_groups_count; j++) { -+ if (++i >= sbi->s_groups_count) - i = 0; - tmp = ext3_get_group_desc (sb, i, &bh2); - if (tmp && -@@ -401,11 +405,11 @@ - if (bitmap_nr < 0) - goto fail; - -- bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr]; -+ bh = sbi->s_inode_bitmap[bitmap_nr]; - - if ((j = ext3_find_first_zero_bit ((unsigned long *) bh->b_data, -- EXT3_INODES_PER_GROUP(sb))) < -- EXT3_INODES_PER_GROUP(sb)) { -+ sbi->s_inodes_per_group)) < -+ sbi->s_inodes_per_group) { - BUFFER_TRACE(bh, "get_write_access"); - err = ext3_journal_get_write_access(handle, bh); - if (err) goto fail; -@@ -459,13 +463,13 @@ - err = ext3_journal_dirty_metadata(handle, bh2); - if (err) goto fail; - -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access"); -- err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(sbi->s_sbh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, sbi->s_sbh); - if (err) goto fail; - es->s_free_inodes_count = - cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1); -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "call ext3_journal_dirty_metadata"); -- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(sbi->s_sbh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, sbi->s_sbh); - sb->s_dirt = 1; - if (err) goto fail; - -@@ -485,35 +489,35 @@ - inode->i_blksize = PAGE_SIZE; - inode->i_blocks = 0; - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; -- inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; -+ ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL; - if (S_ISLNK(mode)) -- inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); -+ ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); - #ifdef EXT3_FRAGMENTS -- inode->u.ext3_i.i_faddr = 0; -- inode->u.ext3_i.i_frag_no = 0; -- inode->u.ext3_i.i_frag_size = 0; -+ ei->i_faddr = 0; -+ ei->i_frag_no = 0; -+ ei->i_frag_size = 0; - #endif -- inode->u.ext3_i.i_file_acl = 0; -- inode->u.ext3_i.i_dir_acl = 0; -- inode->u.ext3_i.i_dtime = 0; -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ ei->i_file_acl = 0; -+ ei->i_dir_acl = 0; -+ ei->i_dtime = 0; -+ INIT_LIST_HEAD(&ei->i_orphan); - #ifdef EXT3_PREALLOCATE -- inode->u.ext3_i.i_prealloc_count = 0; -+ ei->i_prealloc_count = 0; - #endif -- inode->u.ext3_i.i_block_group = i; -+ ei->i_block_group = i; - - ext3_set_inode_flags(inode); - if (IS_SYNC(inode)) - handle->h_sync = 1; - insert_inode_hash(inode); -- inode->i_generation = sb->u.ext3_sb.s_next_generation++; -+ inode->i_generation = sbi->s_next_generation++; - -- inode->u.ext3_i.i_state = EXT3_STATE_NEW; -+ ei->i_state = EXT3_STATE_NEW; - err = ext3_mark_inode_dirty(handle, inode); - if (err) goto fail; - - #ifdef CONFIG_EXT3_FS_XATTR -- init_rwsem(&inode->u.ext3_i.xattr_sem); -+ init_rwsem(&EXT3_I(inode)->xattr_sem); - #endif - - unlock_super (sb); -@@ -600,19 +604,19 @@ - - unsigned long ext3_count_free_inodes (struct super_block * sb) - { -+ struct ext3_sb_info *sbi = EXT3_SB(sb); -+ struct ext3_super_block *es = sbi->s_es; - #ifdef EXT3FS_DEBUG -- struct ext3_super_block * es; - unsigned long desc_count, bitmap_count, x; - int bitmap_nr; - struct ext3_group_desc * gdp; - int i; - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; - desc_count = 0; - bitmap_count = 0; - gdp = NULL; -- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) { -+ for (i = 0; i < sbi->s_groups_count; i++) { - gdp = ext3_get_group_desc (sb, i, NULL); - if (!gdp) - continue; -@@ -621,8 +625,8 @@ - if (bitmap_nr < 0) - continue; - -- x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr], -- EXT3_INODES_PER_GROUP(sb) / 8); -+ x = ext3_count_free(sbi->s_inode_bitmap[bitmap_nr], -+ sbi->s_inodes_per_group / 8); - printk ("group %d: stored = %d, counted = %lu\n", - i, le16_to_cpu(gdp->bg_free_inodes_count), x); - bitmap_count += x; -@@ -632,7 +636,7 @@ - unlock_super (sb); - return desc_count; - #else -- return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_inodes_count); -+ return le32_to_cpu(es->s_free_inodes_count); - #endif - } - -@@ -641,16 +645,18 @@ - void ext3_check_inodes_bitmap (struct super_block * sb) - { - struct ext3_super_block * es; -+ struct ext3_sb_info *sbi; - unsigned long desc_count, bitmap_count, x; - int bitmap_nr; - struct ext3_group_desc * gdp; - int i; - -- es = sb->u.ext3_sb.s_es; -+ sbi = EXT3_SB(sb); -+ es = sbi->s_es; - desc_count = 0; - bitmap_count = 0; - gdp = NULL; -- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) { -+ for (i = 0; i < sbi->s_groups_count; i++) { - gdp = ext3_get_group_desc (sb, i, NULL); - if (!gdp) - continue; -@@ -659,7 +665,7 @@ - if (bitmap_nr < 0) - continue; - -- x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr], -+ x = ext3_count_free (sbi->s_inode_bitmap[bitmap_nr], - EXT3_INODES_PER_GROUP(sb) / 8); - if (le16_to_cpu(gdp->bg_free_inodes_count) != x) - ext3_error (sb, "ext3_check_inodes_bitmap", -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-05 07:55:47.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 12:55:41.000000000 +0300 -@@ -47,7 +47,7 @@ - */ - static inline int ext3_inode_is_fast_symlink(struct inode *inode) - { -- int ea_blocks = inode->u.ext3_i.i_file_acl ? -+ int ea_blocks = EXT3_I(inode)->i_file_acl ? - (inode->i_sb->s_blocksize >> 9) : 0; - - return (S_ISLNK(inode->i_mode) && -@@ -224,7 +224,7 @@ - * (Well, we could do this if we need to, but heck - it works) - */ - ext3_orphan_del(handle, inode); -- inode->u.ext3_i.i_dtime = CURRENT_TIME; -+ EXT3_I(inode)->i_dtime = CURRENT_TIME; - - /* - * One subtle ordering requirement: if anything has gone wrong -@@ -248,13 +248,14 @@ - void ext3_discard_prealloc (struct inode * inode) - { - #ifdef EXT3_PREALLOCATE -+ struct ext3_inode_info *ei = EXT3_I(inode); - lock_kernel(); - /* Writer: ->i_prealloc* */ -- if (inode->u.ext3_i.i_prealloc_count) { -- unsigned short total = inode->u.ext3_i.i_prealloc_count; -- unsigned long block = inode->u.ext3_i.i_prealloc_block; -- inode->u.ext3_i.i_prealloc_count = 0; -- inode->u.ext3_i.i_prealloc_block = 0; -+ if (ei->i_prealloc_count) { -+ unsigned short total = ei->i_prealloc_count; -+ unsigned long block = ei->i_prealloc_block; -+ ei->i_prealloc_count = 0; -+ ei->i_prealloc_block = 0; - /* Writer: end */ - ext3_free_blocks (inode, block, total); - } -@@ -271,13 +272,15 @@ - unsigned long result; - - #ifdef EXT3_PREALLOCATE -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ - /* Writer: ->i_prealloc* */ -- if (inode->u.ext3_i.i_prealloc_count && -- (goal == inode->u.ext3_i.i_prealloc_block || -- goal + 1 == inode->u.ext3_i.i_prealloc_block)) -+ if (ei->i_prealloc_count && -+ (goal == ei->i_prealloc_block || -+ goal + 1 == ei->i_prealloc_block)) - { -- result = inode->u.ext3_i.i_prealloc_block++; -- inode->u.ext3_i.i_prealloc_count--; -+ result = ei->i_prealloc_block++; -+ ei->i_prealloc_count--; - /* Writer: end */ - ext3_debug ("preallocation hit (%lu/%lu).\n", - ++alloc_hits, ++alloc_attempts); -@@ -287,8 +290,8 @@ - alloc_hits, ++alloc_attempts); - if (S_ISREG(inode->i_mode)) - result = ext3_new_block (inode, goal, -- &inode->u.ext3_i.i_prealloc_count, -- &inode->u.ext3_i.i_prealloc_block, err); -+ &ei->i_prealloc_count, -+ &ei->i_prealloc_block, err); - else - result = ext3_new_block (inode, goal, 0, 0, err); - /* -@@ -422,7 +425,7 @@ - - *err = 0; - /* i_data is not going away, no lock needed */ -- add_chain (chain, NULL, inode->u.ext3_i.i_data + *offsets); -+ add_chain (chain, NULL, EXT3_I(inode)->i_data + *offsets); - if (!p->key) - goto no_block; - while (--depth) { -@@ -466,7 +469,8 @@ - - static inline unsigned long ext3_find_near(struct inode *inode, Indirect *ind) - { -- u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext3_i.i_data; -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data; - u32 *p; - - /* Try to find previous block */ -@@ -482,9 +486,8 @@ - * It is going to be refered from inode itself? OK, just put it into - * the same cylinder group then. - */ -- return (inode->u.ext3_i.i_block_group * -- EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -- le32_to_cpu(inode->i_sb->u.ext3_sb.s_es->s_first_data_block); -+ return (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + -+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); - } - - /** -@@ -503,14 +506,15 @@ - static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4], - Indirect *partial, unsigned long *goal) - { -+ struct ext3_inode_info *ei = EXT3_I(inode); - /* Writer: ->i_next_alloc* */ -- if (block == inode->u.ext3_i.i_next_alloc_block + 1) { -- inode->u.ext3_i.i_next_alloc_block++; -- inode->u.ext3_i.i_next_alloc_goal++; -+ if (block == ei->i_next_alloc_block + 1) { -+ ei->i_next_alloc_block++; -+ ei->i_next_alloc_goal++; - } - #ifdef SEARCH_FROM_ZERO -- inode->u.ext3_i.i_next_alloc_block = 0; -- inode->u.ext3_i.i_next_alloc_goal = 0; -+ ei->i_next_alloc_block = 0; -+ ei->i_next_alloc_goal = 0; - #endif - /* Writer: end */ - /* Reader: pointers, ->i_next_alloc* */ -@@ -519,8 +523,8 @@ - * try the heuristic for sequential allocation, - * failing that at least try to get decent locality. - */ -- if (block == inode->u.ext3_i.i_next_alloc_block) -- *goal = inode->u.ext3_i.i_next_alloc_goal; -+ if (block == ei->i_next_alloc_block) -+ *goal = ei->i_next_alloc_goal; - if (!*goal) - *goal = ext3_find_near(inode, partial); - #ifdef SEARCH_FROM_ZERO -@@ -646,6 +650,7 @@ - { - int i; - int err = 0; -+ struct ext3_inode_info *ei = EXT3_I(inode); - - /* - * If we're splicing into a [td]indirect block (as opposed to the -@@ -668,11 +673,11 @@ - /* That's it */ - - *where->p = where->key; -- inode->u.ext3_i.i_next_alloc_block = block; -- inode->u.ext3_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key); -+ ei->i_next_alloc_block = block; -+ ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key); - #ifdef SEARCH_FROM_ZERO -- inode->u.ext3_i.i_next_alloc_block = 0; -- inode->u.ext3_i.i_next_alloc_goal = 0; -+ ei->i_next_alloc_block = 0; -+ ei->i_next_alloc_goal = 0; - #endif - /* Writer: end */ - -@@ -756,6 +761,7 @@ - unsigned long goal; - int left; - int depth = ext3_block_to_path(inode, iblock, offsets); -+ struct ext3_inode_info *ei = EXT3_I(inode); - loff_t new_size; - - J_ASSERT(handle != NULL || create == 0); -@@ -809,7 +815,7 @@ - /* - * Block out ext3_truncate while we alter the tree - */ -- down_read(&inode->u.ext3_i.truncate_sem); -+ down_read(&ei->truncate_sem); - err = ext3_alloc_branch(handle, inode, left, goal, - offsets+(partial-chain), partial); - -@@ -821,7 +827,7 @@ - if (!err) - err = ext3_splice_branch(handle, inode, iblock, chain, - partial, left); -- up_read(&inode->u.ext3_i.truncate_sem); -+ up_read(&ei->truncate_sem); - if (err == -EAGAIN) - goto changed; - if (err) -@@ -981,7 +987,7 @@ - struct buffer_head *tmp_bh; - - for (i = 1; -- inode->u.ext3_i.i_prealloc_count && -+ EXT3_I(inode)->i_prealloc_count && - i < EXT3_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks; - i++) { - /* -@@ -1199,8 +1205,8 @@ - kunmap(page); - } - } -- if (inode->i_size > inode->u.ext3_i.i_disksize) { -- inode->u.ext3_i.i_disksize = inode->i_size; -+ if (inode->i_size > EXT3_I(inode)->i_disksize) { -+ EXT3_I(inode)->i_disksize = inode->i_size; - ret2 = ext3_mark_inode_dirty(handle, inode); - if (!ret) - ret = ret2; -@@ -2011,7 +2017,8 @@ - void ext3_truncate(struct inode * inode) - { - handle_t *handle; -- u32 *i_data = inode->u.ext3_i.i_data; -+ struct ext3_inode_info *ei = EXT3_I(inode); -+ u32 *i_data = EXT3_I(inode)->i_data; - int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb); - int offsets[4]; - Indirect chain[4]; -@@ -2072,13 +2079,13 @@ - * on-disk inode. We do this via i_disksize, which is the value which - * ext3 *really* writes onto the disk inode. - */ -- inode->u.ext3_i.i_disksize = inode->i_size; -+ ei->i_disksize = inode->i_size; - - /* - * From here we block out all ext3_get_block() callers who want to - * modify the block allocation tree. - */ -- down_write(&inode->u.ext3_i.truncate_sem); -+ down_write(&ei->truncate_sem); - - if (n == 1) { /* direct blocks */ - ext3_free_data(handle, inode, NULL, i_data+offsets[0], -@@ -2142,7 +2149,7 @@ - case EXT3_TIND_BLOCK: - ; - } -- up_write(&inode->u.ext3_i.truncate_sem); -+ up_write(&ei->truncate_sem); - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); - -@@ -2179,6 +2186,8 @@ - - int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc) - { -+ struct super_block *sb = inode->i_sb; -+ struct ext3_sb_info *sbi = EXT3_SB(sb); - struct buffer_head *bh = 0; - unsigned long block; - unsigned long block_group; -@@ -2189,25 +2198,21 @@ - - if ((inode->i_ino != EXT3_ROOT_INO && - inode->i_ino != EXT3_JOURNAL_INO && -- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) || -- inode->i_ino > le32_to_cpu( -- inode->i_sb->u.ext3_sb.s_es->s_inodes_count)) { -- ext3_error (inode->i_sb, "ext3_get_inode_loc", -- "bad inode number: %lu", inode->i_ino); -+ inode->i_ino < EXT3_FIRST_INO(sb)) || -+ inode->i_ino > le32_to_cpu(sbi->s_es->s_inodes_count)) { -+ ext3_error (sb, __FUNCTION__, "bad inode #%lu", inode->i_ino); - goto bad_inode; - } -- block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb); -- if (block_group >= inode->i_sb->u.ext3_sb.s_groups_count) { -- ext3_error (inode->i_sb, "ext3_get_inode_loc", -- "group >= groups count"); -+ block_group = (inode->i_ino - 1) / sbi->s_inodes_per_group; -+ if (block_group >= sbi->s_groups_count) { -+ ext3_error(sb, __FUNCTION__, "group >= groups count"); - goto bad_inode; - } -- group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb); -- desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1); -- bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc]; -+ group_desc = block_group >> sbi->s_desc_per_block_bits; -+ desc = block_group & (sbi->s_desc_per_block - 1); -+ bh = sbi->s_group_desc[group_desc]; - if (!bh) { -- ext3_error (inode->i_sb, "ext3_get_inode_loc", -- "Descriptor not loaded"); -+ ext3_error(sb, __FUNCTION__, "Descriptor not loaded"); - goto bad_inode; - } - -@@ -2215,17 +2220,17 @@ - /* - * Figure out the offset within the block group inode table - */ -- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) * -- EXT3_INODE_SIZE(inode->i_sb); -+ offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group) * -+ sbi->s_inode_size; - block = le32_to_cpu(gdp[desc].bg_inode_table) + -- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb)); -- if (!(bh = sb_bread(inode->i_sb, block))) { -- ext3_error (inode->i_sb, "ext3_get_inode_loc", -+ (offset >> EXT3_BLOCK_SIZE_BITS(sb)); -+ if (!(bh = sb_bread(sb, block))) { -+ ext3_error (sb, __FUNCTION__, - "unable to read inode block - " - "inode=%lu, block=%lu", inode->i_ino, block); - goto bad_inode; - } -- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1); -+ offset &= (EXT3_BLOCK_SIZE(sb) - 1); - - iloc->bh = bh; - iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset); -@@ -2239,7 +2244,7 @@ - - void ext3_set_inode_flags(struct inode *inode) - { -- unsigned int flags = inode->u.ext3_i.i_flags; -+ unsigned int flags = EXT3_I(inode)->i_flags; - - inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME); - if (flags & EXT3_SYNC_FL) -@@ -2257,6 +2262,7 @@ - { - struct ext3_iloc iloc; - struct ext3_inode *raw_inode; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct buffer_head *bh; - int block; - -@@ -2264,7 +2270,7 @@ - goto bad_inode; - bh = iloc.bh; - raw_inode = iloc.raw_inode; -- init_rwsem(&inode->u.ext3_i.truncate_sem); -+ init_rwsem(&ei->truncate_sem); - inode->i_mode = le16_to_cpu(raw_inode->i_mode); - inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); - inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low); -@@ -2277,7 +2283,7 @@ - inode->i_atime = le32_to_cpu(raw_inode->i_atime); - inode->i_ctime = le32_to_cpu(raw_inode->i_ctime); - inode->i_mtime = le32_to_cpu(raw_inode->i_mtime); -- inode->u.ext3_i.i_dtime = le32_to_cpu(raw_inode->i_dtime); -+ ei->i_dtime = le32_to_cpu(raw_inode->i_dtime); - /* We now have enough fields to check if the inode was active or not. - * This is needed because nfsd might try to access dead inodes - * the test is that same one that e2fsck uses -@@ -2285,7 +2291,7 @@ - */ - if (inode->i_nlink == 0) { - if (inode->i_mode == 0 || -- !(inode->i_sb->u.ext3_sb.s_mount_state & EXT3_ORPHAN_FS)) { -+ !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ORPHAN_FS)) { - /* this inode is deleted */ - brelse (bh); - goto bad_inode; -@@ -2300,33 +2306,33 @@ - * size */ - inode->i_blocks = le32_to_cpu(raw_inode->i_blocks); - inode->i_version = ++event; -- inode->u.ext3_i.i_flags = le32_to_cpu(raw_inode->i_flags); -+ ei->i_flags = le32_to_cpu(raw_inode->i_flags); - #ifdef EXT3_FRAGMENTS -- inode->u.ext3_i.i_faddr = le32_to_cpu(raw_inode->i_faddr); -- inode->u.ext3_i.i_frag_no = raw_inode->i_frag; -- inode->u.ext3_i.i_frag_size = raw_inode->i_fsize; -+ ei->i_faddr = le32_to_cpu(raw_inode->i_faddr); -+ ei->i_frag_no = raw_inode->i_frag; -+ ei->i_frag_size = raw_inode->i_fsize; - #endif -- inode->u.ext3_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl); -+ ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl); - if (!S_ISREG(inode->i_mode)) { -- inode->u.ext3_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); -+ ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); - } else { - inode->i_size |= - ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; - } -- inode->u.ext3_i.i_disksize = inode->i_size; -+ ei->i_disksize = inode->i_size; - inode->i_generation = le32_to_cpu(raw_inode->i_generation); - #ifdef EXT3_PREALLOCATE -- inode->u.ext3_i.i_prealloc_count = 0; -+ ei->i_prealloc_count = 0; - #endif -- inode->u.ext3_i.i_block_group = iloc.block_group; -+ ei->i_block_group = iloc.block_group; - - /* - * NOTE! The in-memory inode i_data array is in little-endian order - * even on big-endian machines: we do NOT byteswap the block numbers! - */ - for (block = 0; block < EXT3_N_BLOCKS; block++) -- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; -- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); -+ ei->i_data[block] = iloc.raw_inode->i_block[block]; -+ INIT_LIST_HEAD(&ei->i_orphan); - - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; -@@ -2350,15 +2356,15 @@ - brelse (iloc.bh); - ext3_set_inode_flags(inode); - #ifdef CONFIG_EXT3_FS_XATTR -- init_rwsem(&inode->u.ext3_i.xattr_sem); -+ init_rwsem(&ei->xattr_sem); - #endif - #ifdef CONFIG_EXT3_FS_POSIX_ACL -- if (inode->u.ext3_i.i_file_acl) { -+ if (ei->i_file_acl) { - /* The filesystem is mounted with ACL support, and there - are extended attributes for this inode. However we do - not yet know whether there are actually any ACLs. */ -- inode->u.ext3_i.i_acl = EXT3_ACL_NOT_CACHED; -- inode->u.ext3_i.i_default_acl = EXT3_ACL_NOT_CACHED; -+ ei->i_acl = EXT3_ACL_NOT_CACHED; -+ ei->i_default_acl = EXT3_ACL_NOT_CACHED; - } - #endif - -@@ -2380,6 +2386,7 @@ - struct ext3_iloc *iloc) - { - struct ext3_inode *raw_inode = iloc->raw_inode; -+ struct ext3_inode_info *ei = EXT3_I(inode); - struct buffer_head *bh = iloc->bh; - int err = 0, rc, block; - -@@ -2397,7 +2404,7 @@ - * Fix up interoperability with old kernels. Otherwise, old inodes get - * re-used with the upper 16 bits of the uid/gid intact - */ -- if(!inode->u.ext3_i.i_dtime) { -+ if(!ei->i_dtime) { - raw_inode->i_uid_high = - cpu_to_le16(high_16_bits(inode->i_uid)); - raw_inode->i_gid_high = -@@ -2415,34 +2422,33 @@ - raw_inode->i_gid_high = 0; - } - raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); -- raw_inode->i_size = cpu_to_le32(inode->u.ext3_i.i_disksize); -+ raw_inode->i_size = cpu_to_le32(ei->i_disksize); - raw_inode->i_atime = cpu_to_le32(inode->i_atime); - raw_inode->i_ctime = cpu_to_le32(inode->i_ctime); - raw_inode->i_mtime = cpu_to_le32(inode->i_mtime); - raw_inode->i_blocks = cpu_to_le32(inode->i_blocks); -- raw_inode->i_dtime = cpu_to_le32(inode->u.ext3_i.i_dtime); -- raw_inode->i_flags = cpu_to_le32(inode->u.ext3_i.i_flags); -+ raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); -+ raw_inode->i_flags = cpu_to_le32(ei->i_flags); - #ifdef EXT3_FRAGMENTS -- raw_inode->i_faddr = cpu_to_le32(inode->u.ext3_i.i_faddr); -- raw_inode->i_frag = inode->u.ext3_i.i_frag_no; -- raw_inode->i_fsize = inode->u.ext3_i.i_frag_size; -+ raw_inode->i_faddr = cpu_to_le32(ei->i_faddr); -+ raw_inode->i_frag = ei->i_frag_no; -+ raw_inode->i_fsize = ei->i_frag_size; - #else - /* If we are not tracking these fields in the in-memory inode, - * then preserve them on disk, but still initialise them to zero - * for new inodes. */ -- if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) { -+ if (ei->i_state & EXT3_STATE_NEW) { - raw_inode->i_faddr = 0; - raw_inode->i_frag = 0; - raw_inode->i_fsize = 0; - } - #endif -- raw_inode->i_file_acl = cpu_to_le32(inode->u.ext3_i.i_file_acl); -+ raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl); - if (!S_ISREG(inode->i_mode)) { -- raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext3_i.i_dir_acl); -+ raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); - } else { -- raw_inode->i_size_high = -- cpu_to_le32(inode->u.ext3_i.i_disksize >> 32); -- if (inode->u.ext3_i.i_disksize > 0x7fffffffULL) { -+ raw_inode->i_size_high = cpu_to_le32(ei->i_disksize >> 32); -+ if (ei->i_disksize > MAX_NON_LFS) { - struct super_block *sb = inode->i_sb; - if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, - EXT3_FEATURE_RO_COMPAT_LARGE_FILE) || -@@ -2452,7 +2458,7 @@ - * created, add a flag to the superblock. - */ - err = ext3_journal_get_write_access(handle, -- sb->u.ext3_sb.s_sbh); -+ EXT3_SB(sb)->s_sbh); - if (err) - goto out_brelse; - ext3_update_dynamic_rev(sb); -@@ -2461,7 +2467,7 @@ - sb->s_dirt = 1; - handle->h_sync = 1; - err = ext3_journal_dirty_metadata(handle, -- sb->u.ext3_sb.s_sbh); -+ EXT3_SB(sb)->s_sbh); - } - } - } -@@ -2470,13 +2476,13 @@ - raw_inode->i_block[0] = - cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); - else for (block = 0; block < EXT3_N_BLOCKS; block++) -- raw_inode->i_block[block] = inode->u.ext3_i.i_data[block]; -+ raw_inode->i_block[block] = ei->i_data[block]; - - BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); - rc = ext3_journal_dirty_metadata(handle, bh); - if (!err) - err = rc; -- EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW; -+ ei->i_state &= ~EXT3_STATE_NEW; - - out_brelse: - brelse (bh); -@@ -2581,7 +2587,7 @@ - } - - error = ext3_orphan_add(handle, inode); -- inode->u.ext3_i.i_disksize = attr->ia_size; -+ EXT3_I(inode)->i_disksize = attr->ia_size; - rc = ext3_mark_inode_dirty(handle, inode); - if (!error) - error = rc; -@@ -2843,9 +2849,9 @@ - */ - - if (val) -- inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL; -+ EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL; - else -- inode->u.ext3_i.i_flags &= ~EXT3_JOURNAL_DATA_FL; -+ EXT3_I(inode)->i_flags &= ~EXT3_JOURNAL_DATA_FL; - - journal_unlock_updates(journal); - -Index: linux-2.4.21-chaos/fs/ext3/ioctl.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ioctl.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/ioctl.c 2003-12-12 12:50:34.000000000 +0300 -@@ -18,13 +18,14 @@ - int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - unsigned long arg) - { -+ struct ext3_inode_info *ei = EXT3_I(inode); - unsigned int flags; - - ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg); - - switch (cmd) { - case EXT3_IOC_GETFLAGS: -- flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE; -+ flags = ei->i_flags & EXT3_FL_USER_VISIBLE; - return put_user(flags, (int *) arg); - case EXT3_IOC_SETFLAGS: { - handle_t *handle = NULL; -@@ -42,7 +43,7 @@ - if (get_user(flags, (int *) arg)) - return -EFAULT; - -- oldflags = inode->u.ext3_i.i_flags; -+ oldflags = ei->i_flags; - - /* The JOURNAL_DATA flag is modifiable only by root */ - jflag = flags & EXT3_JOURNAL_DATA_FL; -@@ -79,7 +80,7 @@ - - flags = flags & EXT3_FL_USER_MODIFIABLE; - flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE; -- inode->u.ext3_i.i_flags = flags; -+ ei->i_flags = flags; - - ext3_set_inode_flags(inode); - inode->i_ctime = CURRENT_TIME; -@@ -138,12 +139,12 @@ - int ret = 0; - - set_current_state(TASK_INTERRUPTIBLE); -- add_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait); -- if (timer_pending(&sb->u.ext3_sb.turn_ro_timer)) { -+ add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait); -+ if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) { - schedule(); - ret = 1; - } -- remove_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait); -+ remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait); - return ret; - } - #endif -Index: linux-2.4.21-chaos/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/namei.c 2003-12-12 11:36:13.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/namei.c 2003-12-12 12:56:27.000000000 +0300 -@@ -343,7 +343,7 @@ - goto fail; - } - hinfo->hash_version = root->info.hash_version; -- hinfo->seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ hinfo->seed = EXT3_SB(dir->i_sb)->s_hash_seed; - if (dentry) - ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo); - hash = hinfo->hash; -@@ -1236,7 +1236,7 @@ - de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); - memset (&root->info, 0, sizeof(root->info)); - root->info.info_length = sizeof(root->info); -- root->info.hash_version = dir->i_sb->u.ext3_sb.s_def_hash_version; -+ root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; - entries = root->entries; - dx_set_block (entries, 1); - dx_set_count (entries, 1); -@@ -1244,7 +1244,7 @@ - - /* Initialize as for dx_probe */ - hinfo.hash_version = root->info.hash_version; -- hinfo.seed = dir->i_sb->u.ext3_sb.s_hash_seed; -+ hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed; - ext3fs_dirhash(name, namelen, &hinfo); - frame = frames; - frame->entries = entries; -@@ -1768,8 +1768,8 @@ - J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) || inode->i_nlink == 0); - -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access"); -- err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); - if (err) - goto out_unlock; - -@@ -1780,7 +1780,7 @@ - /* Insert this inode at the head of the on-disk orphan list... */ - NEXT_ORPHAN(inode) = le32_to_cpu(EXT3_SB(sb)->s_es->s_last_orphan); - EXT3_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino); -- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh); -+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); - rc = ext3_mark_iloc_dirty(handle, inode, &iloc); - if (!err) - err = rc; -@@ -1854,8 +1854,7 @@ - err = ext3_journal_dirty_metadata(handle, sbi->s_sbh); - } else { - struct ext3_iloc iloc2; -- struct inode *i_prev = -- list_entry(prev, struct inode, u.ext3_i.i_orphan); -+ struct inode *i_prev = orphan_list_entry(prev); - - jbd_debug(4, "orphan inode %lu will point to %lu\n", - i_prev->i_ino, ino_next); -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-12 12:14:29.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-12 12:50:34.000000000 +0300 -@@ -125,7 +125,7 @@ - /* If no overrides were specified on the mount, then fall back - * to the default behaviour set in the filesystem's superblock - * on disk. */ -- switch (le16_to_cpu(sb->u.ext3_sb.s_es->s_errors)) { -+ switch (le16_to_cpu(EXT3_SB(sb)->s_es->s_errors)) { - case EXT3_ERRORS_PANIC: - return EXT3_ERRORS_PANIC; - case EXT3_ERRORS_RO: -@@ -299,9 +299,9 @@ - return; - - printk (KERN_CRIT "Remounting filesystem read-only\n"); -- sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS; -+ EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; - sb->s_flags |= MS_RDONLY; -- sb->u.ext3_sb.s_mount_opt |= EXT3_MOUNT_ABORT; -+ EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT; - journal_abort(EXT3_SB(sb)->s_journal, -EIO); - } - -@@ -407,8 +407,6 @@ - return ret; - } - --#define orphan_list_entry(l) list_entry((l), struct inode, u.ext3_i.i_orphan) -- - static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi) - { - struct list_head *l; -@@ -889,7 +887,7 @@ - return; - } - -- if (sb->u.ext3_sb.s_mount_state & EXT3_ERROR_FS) { -+ if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) { - if (es->s_last_orphan) - jbd_debug(1, "Errors on filesystem, " - "clearing orphan list.\n"); -@@ -1571,12 +1569,14 @@ - struct ext3_super_block * es, - int sync) - { -+ struct buffer_head *sbh = EXT3_SB(sb)->s_sbh; -+ - es->s_wtime = cpu_to_le32(CURRENT_TIME); -- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "marking dirty"); -- mark_buffer_dirty(sb->u.ext3_sb.s_sbh); -+ BUFFER_TRACE(sbh, "marking dirty"); -+ mark_buffer_dirty(sbh); - if (sync) { -- ll_rw_block(WRITE, 1, &sb->u.ext3_sb.s_sbh); -- wait_on_buffer(sb->u.ext3_sb.s_sbh); -+ ll_rw_block(WRITE, 1, &sbh); -+ wait_on_buffer(sbh); - } - } - -@@ -1627,7 +1627,7 @@ - ext3_warning(sb, __FUNCTION__, "Marking fs in need of " - "filesystem check."); - -- sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS; -+ EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; - es->s_state |= cpu_to_le16(EXT3_ERROR_FS); - ext3_commit_super (sb, es, 1); - -Index: linux-2.4.21-chaos/fs/ext3/symlink.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/symlink.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/symlink.c 2003-12-12 12:50:34.000000000 +0300 -@@ -24,14 +24,14 @@ - - static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen) - { -- char *s = (char *)dentry->d_inode->u.ext3_i.i_data; -- return vfs_readlink(dentry, buffer, buflen, s); -+ struct ext3_inode_info *ei = EXT3_I(dentry->d_inode); -+ return vfs_readlink(dentry, buffer, buflen, (char *)ei->i_data); - } - - static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd) - { -- char *s = (char *)dentry->d_inode->u.ext3_i.i_data; -- return vfs_follow_link(nd, s); -+ struct ext3_inode_info *ei = EXT3_I(dentry->d_inode); -+ return vfs_follow_link(nd, (char*)ei->i_data); - } - - struct inode_operations ext3_symlink_inode_operations = { -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 11:36:14.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 12:50:34.000000000 +0300 -@@ -87,22 +87,25 @@ - #define EXT3_MIN_BLOCK_SIZE 1024 - #define EXT3_MAX_BLOCK_SIZE 4096 - #define EXT3_MIN_BLOCK_LOG_SIZE 10 -+ - #ifdef __KERNEL__ --# define EXT3_BLOCK_SIZE(s) ((s)->s_blocksize) --#else --# define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size) --#endif --#define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32)) --#ifdef __KERNEL__ --# define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) --#else --# define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) --#endif --#ifdef __KERNEL__ --#define EXT3_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext3_sb.s_addr_per_block_bits) --#define EXT3_INODE_SIZE(s) ((s)->u.ext3_sb.s_inode_size) --#define EXT3_FIRST_INO(s) ((s)->u.ext3_sb.s_first_ino) -+#define EXT3_SB(sb) (&((sb)->u.ext3_sb)) -+#define EXT3_I(inode) (&((inode)->u.ext3_i)) -+ -+#define EXT3_BLOCK_SIZE(s) ((s)->s_blocksize) -+#define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -+#define EXT3_ADDR_PER_BLOCK_BITS(s) (EXT3_SB(s)->s_addr_per_block_bits) -+#define EXT3_INODE_SIZE(s) (EXT3_SB(s)->s_inode_size) -+#define EXT3_FIRST_INO(s) (EXT3_SB(s)->s_first_ino) - #else -+ -+/* Assume that user mode programs are passing in an ext3fs superblock, not -+ * a kernel struct super_block. This will allow us to call the feature-test -+ * macros from user land. */ -+#define EXT3_SB(sb) (sb) -+ -+#define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size) -+#define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) - #define EXT3_INODE_SIZE(s) (((s)->s_rev_level == EXT3_GOOD_OLD_REV) ? \ - EXT3_GOOD_OLD_INODE_SIZE : \ - (s)->s_inode_size) -@@ -110,6 +113,7 @@ - EXT3_GOOD_OLD_FIRST_INO : \ - (s)->s_first_ino) - #endif -+#define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32)) - - /* - * Macro-instructions used to manage fragments -@@ -118,8 +122,8 @@ - #define EXT3_MAX_FRAG_SIZE 4096 - #define EXT3_MIN_FRAG_LOG_SIZE 10 - #ifdef __KERNEL__ --# define EXT3_FRAG_SIZE(s) ((s)->u.ext3_sb.s_frag_size) --# define EXT3_FRAGS_PER_BLOCK(s) ((s)->u.ext3_sb.s_frags_per_block) -+# define EXT3_FRAG_SIZE(s) (EXT3_SB(s)->s_frag_size) -+# define EXT3_FRAGS_PER_BLOCK(s) (EXT3_SB(s)->s_frags_per_block) - #else - # define EXT3_FRAG_SIZE(s) (EXT3_MIN_FRAG_SIZE << (s)->s_log_frag_size) - # define EXT3_FRAGS_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / EXT3_FRAG_SIZE(s)) -@@ -143,15 +147,13 @@ - /* - * Macro-instructions used to manage group descriptors - */ -+# define EXT3_BLOCKS_PER_GROUP(s) (EXT3_SB(s)->s_blocks_per_group) -+# define EXT3_INODES_PER_GROUP(s) (EXT3_SB(s)->s_inodes_per_group) - #ifdef __KERNEL__ --# define EXT3_BLOCKS_PER_GROUP(s) ((s)->u.ext3_sb.s_blocks_per_group) --# define EXT3_DESC_PER_BLOCK(s) ((s)->u.ext3_sb.s_desc_per_block) --# define EXT3_INODES_PER_GROUP(s) ((s)->u.ext3_sb.s_inodes_per_group) --# define EXT3_DESC_PER_BLOCK_BITS(s) ((s)->u.ext3_sb.s_desc_per_block_bits) -+# define EXT3_DESC_PER_BLOCK(s) (EXT3_SB(s)->s_desc_per_block) -+# define EXT3_DESC_PER_BLOCK_BITS(s) (EXT3_SB(s)->s_desc_per_block_bits) - #else --# define EXT3_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group) - # define EXT3_DESC_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_group_desc)) --# define EXT3_INODES_PER_GROUP(s) ((s)->s_inodes_per_group) - #endif - - /* -@@ -326,7 +328,7 @@ - #ifndef _LINUX_EXT2_FS_H - #define clear_opt(o, opt) o &= ~EXT3_MOUNT_##opt - #define set_opt(o, opt) o |= EXT3_MOUNT_##opt --#define test_opt(sb, opt) ((sb)->u.ext3_sb.s_mount_opt & \ -+#define test_opt(sb, opt) (EXT3_SB(sb)->s_mount_opt & \ - EXT3_MOUNT_##opt) - #else - #define EXT2_MOUNT_NOLOAD EXT3_MOUNT_NOLOAD -@@ -427,17 +429,11 @@ - __u32 s_reserved[192]; /* Padding to the end of the block */ - }; - --#ifdef __KERNEL__ --#define EXT3_SB(sb) (&((sb)->u.ext3_sb)) --#define EXT3_I(inode) (&((inode)->u.ext3_i)) --#else --/* Assume that user mode programs are passing in an ext3fs superblock, not -- * a kernel struct super_block. This will allow us to call the feature-test -- * macros from user land. */ --#define EXT3_SB(sb) (sb) --#endif -- --#define NEXT_ORPHAN(inode) (inode)->u.ext3_i.i_dtime -+#define NEXT_ORPHAN(inode) EXT3_I(inode)->i_dtime -+static inline struct inode *orphan_list_entry(struct list_head *l) -+{ -+ return list_entry(l, struct inode, u.ext3_i.i_orphan); -+} - - /* - * Codes for operating systems -Index: linux-2.4.21-chaos/include/linux/ext3_jbd.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_jbd.h 2003-12-12 11:36:14.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_jbd.h 2003-12-12 12:50:34.000000000 +0300 -@@ -285,7 +285,7 @@ - return 1; - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA) - return 1; -- if (inode->u.ext3_i.i_flags & EXT3_JOURNAL_DATA_FL) -+ if (EXT3_I(inode)->i_flags & EXT3_JOURNAL_DATA_FL) - return 1; - return 0; - } diff --git a/lustre/kernel_patches/patches/ext3-largefile.patch b/lustre/kernel_patches/patches/ext3-largefile.patch deleted file mode 100644 index aa7a2f2..0000000 --- a/lustre/kernel_patches/patches/ext3-largefile.patch +++ /dev/null @@ -1,16 +0,0 @@ - fs/ext3/inode.c | 2 +- - 1 files changed, 1 insertion(+), 1 deletion(-) - ---- linux-2.4.20/fs/ext3/inode.c~ext3-largefile 2003-04-08 23:35:36.000000000 -0600 -+++ linux-2.4.20-braam/fs/ext3/inode.c 2003-04-08 23:35:36.000000000 -0600 -@@ -2562,7 +2562,7 @@ void ext3_dirty_inode(struct inode *inod - handle_t *handle; - - lock_kernel(); -- handle = ext3_journal_start(inode, 1); -+ handle = ext3_journal_start(inode, 2); - if (IS_ERR(handle)) - goto out; - if (current_handle && - -_ diff --git a/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch b/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch deleted file mode 100644 index 8fc1bd7..0000000 --- a/lustre/kernel_patches/patches/ext3-lookup-dotdot-2.4.20.patch +++ /dev/null @@ -1,63 +0,0 @@ -Index: linux-2.4.21/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/namei.c 2006-04-29 20:48:26.000000000 +0400 -+++ linux-2.4.21/fs/ext3/namei.c 2006-05-06 01:31:51.000000000 +0400 -@@ -955,6 +955,38 @@ static struct dentry *ext3_lookup(struct - } - } - -+ /* ".." shouldn't go into dcache to preserve dcache hierarchy -+ * otherwise we'll get parent being a child of actual child. -+ * see bug 10458 for details -bzzz */ -+ if (inode && (dentry->d_name.name[0] == '.' && (dentry->d_name.len == 1 || -+ (dentry->d_name.len == 2 && dentry->d_name.name[1] == '.')))) { -+ struct dentry *tmp, *goal = NULL; -+ struct list_head *lp; -+ -+ /* first, look for an existing dentry - any one is good */ -+ spin_lock(&dcache_lock); -+ list_for_each(lp, &inode->i_dentry) { -+ tmp = list_entry(lp, struct dentry, d_alias); -+ goal = tmp; -+ dget_locked(goal); -+ break; -+ } -+ if (goal == NULL) { -+ /* there is no alias, we need to make current dentry: -+ * a) inaccessible for __d_lookup() -+ * b) inaccessible for iopen */ -+ J_ASSERT(list_empty(&dentry->d_alias)); -+ dentry->d_flags |= DCACHE_NFSFS_RENAMED; -+ /* this is d_instantiate() ... */ -+ list_add(&dentry->d_alias, &inode->i_dentry); -+ dentry->d_inode = inode; -+ } -+ spin_unlock(&dcache_lock); -+ if (goal) -+ iput(inode); -+ return goal; -+ } -+ - return iopen_connect_dentry(dentry, inode, 1); - } - -Index: linux-2.4.21/fs/ext3/iopen.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/iopen.c 2006-04-29 20:48:23.000000000 +0400 -+++ linux-2.4.21/fs/ext3/iopen.c 2006-04-29 20:59:50.000000000 +0400 -@@ -92,9 +92,12 @@ static struct dentry *iopen_lookup(struc - assert(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED)); - } - -- if (!list_empty(&inode->i_dentry)) { -- alternate = list_entry(inode->i_dentry.next, -- struct dentry, d_alias); -+ list_for_each(lp, &inode->i_dentry) { -+ alternate = list_entry(lp, struct dentry, d_alias); -+ /* ignore dentries created for ".." to preserve -+ * proper dcache hierarchy -- bug 10458 */ -+ if (alternate->d_flags & DCACHE_NFSFS_RENAMED) -+ continue; - dget_locked(alternate); - alternate->d_vfs_flags |= DCACHE_REFERENCED; - iput(inode); diff --git a/lustre/kernel_patches/patches/ext3-map_inode_page-2.4.21-suse2.patch b/lustre/kernel_patches/patches/ext3-map_inode_page-2.4.21-suse2.patch deleted file mode 100644 index 76f5e21..0000000 --- a/lustre/kernel_patches/patches/ext3-map_inode_page-2.4.21-suse2.patch +++ /dev/null @@ -1,119 +0,0 @@ - - - - fs/ext3/ext3-exports.c | 3 ++ - fs/ext3/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 58 insertions(+) - -Index: linux-2.4.21-suse2/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/inode.c 2004-01-10 15:38:24.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/inode.c 2004-01-10 16:22:45.000000000 +0300 -@@ -3084,7 +3084,7 @@ - /* alloc blocks one by one */ - for (i = 0; i < nblocks; i++) { - ret = ext3_get_block_handle(handle, inode, blocks[i], -- &bh_tmp, 1); -+ &bh_tmp, 1, 1); - if (ret) - break; - -@@ -3105,3 +3105,80 @@ - ret = ret2; - return ret; - } -+ -+/* copied from fs/buffer.c */ -+static void unmap_underlying_metadata(struct buffer_head * bh) -+{ -+ struct buffer_head *old_bh; -+ -+ old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); -+ if (old_bh) { -+ mark_buffer_clean(old_bh); -+ wait_on_buffer(old_bh); -+ clear_bit(BH_Req, &old_bh->b_state); -+ __brelse(old_bh); -+ } -+} -+ -+int ext3_map_inode_page(struct inode *inode, struct page *page, -+ unsigned long *blocks, int *created, int create) -+{ -+ unsigned int blocksize, blocks_per_page; -+ unsigned long iblock; -+ void *handle; -+ int i, rc = 0, failed = 0, needed_blocks; -+ -+ blocksize = inode->i_sb->s_blocksize; -+ blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; -+ iblock = page->index * blocks_per_page; -+ -+ for (i = 0; i < blocks_per_page; i++, iblock++) { -+ blocks[i] = ext3_bmap(inode->i_mapping, iblock); -+ if (blocks[i] == 0) { -+ failed++; -+ if (created) -+ created[i] = -1; -+ } else if (created) { -+ created[i] = 0; -+ } -+ } -+ -+ if (failed == 0 || create == 0) -+ return 0; -+ -+ needed_blocks = ext3_writepage_trans_blocks(inode); -+ lock_kernel(); -+ handle = ext3_journal_start(inode, needed_blocks); -+ unlock_kernel(); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ iblock = page->index * blocks_per_page; -+ for (i = 0; i < blocks_per_page; i++, iblock++) { -+ struct buffer_head bh; -+ -+ if (blocks[i] != 0) -+ continue; -+ -+ rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1); -+ if (rc) { -+ printk(KERN_INFO "ext3_map_inode_page: error %d " -+ "allocating block %ld\n", rc, iblock); -+ goto out; -+ } -+ /* Unmap any metadata buffers from the block mapping, to avoid -+ * data corruption due to direct-write from Lustre being -+ * clobbered by a later flush of the blockdev metadata buffer.*/ -+ if (buffer_new(&bh)) -+ unmap_underlying_metadata(&bh); -+ blocks[i] = bh.b_blocknr; -+ if (created) -+ created[i] = 1; -+ } -+ -+ out: -+ lock_kernel(); -+ ext3_journal_stop(handle, inode); -+ unlock_kernel(); -+ return rc; -+} -Index: linux-2.4.21-suse2/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.21-suse2.orig/fs/ext3/ext3-exports.c 2004-01-10 15:38:24.000000000 +0300 -+++ linux-2.4.21-suse2/fs/ext3/ext3-exports.c 2004-01-10 16:22:09.000000000 +0300 -@@ -9,6 +9,8 @@ - - int ext3_prep_san_write(struct inode *inode, long *blocks, - int nblocks, loff_t newsize); -+int ext3_map_inode_page(struct inode *inode, struct page *page, -+ unsigned long *block, int *created, int create); - - EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); -@@ -19,3 +21,4 @@ - EXPORT_SYMBOL(ext3_xattr_list); - EXPORT_SYMBOL(ext3_xattr_set); - EXPORT_SYMBOL(ext3_prep_san_write); -+EXPORT_SYMBOL(ext3_map_inode_page); diff --git a/lustre/kernel_patches/patches/ext3-map_inode_page.patch b/lustre/kernel_patches/patches/ext3-map_inode_page.patch deleted file mode 100644 index 4dda8d4..0000000 --- a/lustre/kernel_patches/patches/ext3-map_inode_page.patch +++ /dev/null @@ -1,110 +0,0 @@ - - - - fs/ext3/ext3-exports.c | 3 ++ - fs/ext3/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 58 insertions(+) - -Index: lum/fs/ext3/inode.c -=================================================================== ---- lum.orig/fs/ext3/inode.c Sat Nov 22 16:38:51 2003 -+++ lum/fs/ext3/inode.c Fri Nov 28 00:37:18 2003 -@@ -2979,3 +2979,80 @@ - ret = ret2; - return ret; - } -+ -+/* copied from fs/buffer.c */ -+static void unmap_underlying_metadata(struct buffer_head * bh) -+{ -+ struct buffer_head *old_bh; -+ -+ old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); -+ if (old_bh) { -+ mark_buffer_clean(old_bh); -+ wait_on_buffer(old_bh); -+ clear_bit(BH_Req, &old_bh->b_state); -+ __brelse(old_bh); -+ } -+} -+ -+int ext3_map_inode_page(struct inode *inode, struct page *page, -+ unsigned long *blocks, int *created, int create) -+{ -+ unsigned int blocksize, blocks_per_page; -+ unsigned long iblock; -+ void *handle; -+ int i, rc = 0, failed = 0, needed_blocks; -+ -+ blocksize = inode->i_sb->s_blocksize; -+ blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; -+ iblock = page->index * blocks_per_page; -+ -+ for (i = 0; i < blocks_per_page; i++, iblock++) { -+ blocks[i] = ext3_bmap(inode->i_mapping, iblock); -+ if (blocks[i] == 0) { -+ failed++; -+ if (created) -+ created[i] = -1; -+ } else if (created) { -+ created[i] = 0; -+ } -+ } -+ -+ if (failed == 0 || create == 0) -+ return 0; -+ -+ needed_blocks = ext3_writepage_trans_blocks(inode); -+ lock_kernel(); -+ handle = ext3_journal_start(inode, needed_blocks); -+ unlock_kernel(); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ iblock = page->index * blocks_per_page; -+ for (i = 0; i < blocks_per_page; i++, iblock++) { -+ struct buffer_head bh; -+ -+ if (blocks[i] != 0) -+ continue; -+ -+ rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1); -+ if (rc) { -+ printk(KERN_INFO "ext3_map_inode_page: error %d " -+ "allocating block %ld\n", rc, iblock); -+ goto out; -+ } -+ /* Unmap any metadata buffers from the block mapping, to avoid -+ * data corruption due to direct-write from Lustre being -+ * clobbered by a later flush of the blockdev metadata buffer.*/ -+ if (buffer_new(&bh)) -+ unmap_underlying_metadata(&bh); -+ blocks[i] = bh.b_blocknr; -+ if (created) -+ created[i] = 1; -+ } -+ -+ out: -+ lock_kernel(); -+ ext3_journal_stop(handle, inode); -+ unlock_kernel(); -+ return rc; -+} -Index: lum/fs/ext3/ext3-exports.c -=================================================================== ---- lum.orig/fs/ext3/ext3-exports.c Sat Nov 22 16:38:51 2003 -+++ lum/fs/ext3/ext3-exports.c Sat Nov 22 16:38:51 2003 -@@ -9,6 +9,8 @@ - - int ext3_prep_san_write(struct inode *inode, long *blocks, - int nblocks, loff_t newsize); -+int ext3_map_inode_page(struct inode *inode, struct page *page, -+ unsigned long *block, int *created, int create); - - EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); -@@ -18,3 +20,4 @@ - EXPORT_SYMBOL(ext3_xattr_list); - EXPORT_SYMBOL(ext3_xattr_set); - EXPORT_SYMBOL(ext3_prep_san_write); -+EXPORT_SYMBOL(ext3_map_inode_page); diff --git a/lustre/kernel_patches/patches/ext3-map_inode_page_2.4.18.patch b/lustre/kernel_patches/patches/ext3-map_inode_page_2.4.18.patch deleted file mode 100644 index ca1c4a7..0000000 --- a/lustre/kernel_patches/patches/ext3-map_inode_page_2.4.18.patch +++ /dev/null @@ -1,110 +0,0 @@ - - - - fs/ext3/ext3-exports.c | 3 ++ - fs/ext3/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 58 insertions(+) - -Index: linux-2.4.18-p4smp/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.18-p4smp.orig/fs/ext3/ext3-exports.c Thu Nov 27 22:18:40 2003 -+++ linux-2.4.18-p4smp/fs/ext3/ext3-exports.c Thu Nov 27 22:18:40 2003 -@@ -9,6 +9,8 @@ - - int ext3_prep_san_write(struct inode *inode, long *blocks, - int nblocks, loff_t newsize); -+int ext3_map_inode_page(struct inode *inode, struct page *page, -+ unsigned long *block, int *created, int create); - - EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); -@@ -18,3 +20,4 @@ - EXPORT_SYMBOL(ext3_xattr_list); - EXPORT_SYMBOL(ext3_xattr_set); - EXPORT_SYMBOL(ext3_prep_san_write); -+EXPORT_SYMBOL(ext3_map_inode_page); -Index: linux-2.4.18-p4smp/fs/ext3/inode.c -=================================================================== ---- linux-2.4.18-p4smp.orig/fs/ext3/inode.c Thu Nov 27 22:18:40 2003 -+++ linux-2.4.18-p4smp/fs/ext3/inode.c Thu Nov 27 22:20:36 2003 -@@ -3004,3 +3004,80 @@ - ret = ret2; - return ret; - } -+ -+/* copied from fs/buffer.c */ -+static void unmap_underlying_metadata(struct buffer_head * bh) -+{ -+ struct buffer_head *old_bh; -+ -+ old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); -+ if (old_bh) { -+ mark_buffer_clean(old_bh); -+ wait_on_buffer(old_bh); -+ clear_bit(BH_Req, &old_bh->b_state); -+ __brelse(old_bh); -+ } -+} -+ -+int ext3_map_inode_page(struct inode *inode, struct page *page, -+ unsigned long *blocks, int *created, int create) -+{ -+ unsigned int blocksize, blocks_per_page; -+ unsigned long iblock; -+ void *handle; -+ int i, rc = 0, failed = 0, needed_blocks; -+ -+ blocksize = inode->i_sb->s_blocksize; -+ blocks_per_page = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; -+ iblock = page->index * blocks_per_page; -+ -+ for (i = 0; i < blocks_per_page; i++, iblock++) { -+ blocks[i] = ext3_bmap(inode->i_mapping, iblock); -+ if (blocks[i] == 0) { -+ failed++; -+ if (created) -+ created[i] = -1; -+ } else if (created) { -+ created[i] = 0; -+ } -+ } -+ -+ if (failed == 0 || create == 0) -+ return 0; -+ -+ needed_blocks = ext3_writepage_trans_blocks(inode); -+ lock_kernel(); -+ handle = ext3_journal_start(inode, needed_blocks); -+ unlock_kernel(); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ iblock = page->index * blocks_per_page; -+ for (i = 0; i < blocks_per_page; i++, iblock++) { -+ struct buffer_head bh; -+ -+ if (blocks[i] != 0) -+ continue; -+ -+ rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1); -+ if (rc) { -+ printk(KERN_INFO "ext3_map_inode_page: error %d " -+ "allocating block %ld\n", rc, iblock); -+ goto out; -+ } -+ /* Unmap any metadata buffers from the block mapping, to avoid -+ * data corruption due to direct-write from Lustre being -+ * clobbered by a later flush of the blockdev metadata buffer.*/ -+ if (buffer_new(&bh)) -+ unmap_underlying_metadata(&bh); -+ blocks[i] = bh.b_blocknr; -+ if (created) -+ created[i] = 1; -+ } -+ -+ out: -+ lock_kernel(); -+ ext3_journal_stop(handle, inode); -+ unlock_kernel(); -+ return rc; -+} diff --git a/lustre/kernel_patches/patches/ext3-nlinks-2.4.20-hp_pnnl.patch b/lustre/kernel_patches/patches/ext3-nlinks-2.4.20-hp_pnnl.patch deleted file mode 100644 index 56ea50a..0000000 --- a/lustre/kernel_patches/patches/ext3-nlinks-2.4.20-hp_pnnl.patch +++ /dev/null @@ -1,172 +0,0 @@ -Index: linux/fs/ext3/namei.c -=================================================================== ---- linux.orig/fs/ext3/namei.c -+++ linux/fs/ext3/namei.c -@@ -1549,11 +1549,17 @@ static int ext3_delete_entry (handle_t * - static inline void ext3_inc_count(handle_t *handle, struct inode *inode) - { - inode->i_nlink++; -+ if (is_dx(inode) && inode->i_nlink > 1) { -+ /* limit is 16-bit i_links_count */ -+ if (inode->i_nlink >= EXT3_LINK_MAX || inode->i_nlink == 2) -+ inode->i_nlink = 1; -+ } - } - - static inline void ext3_dec_count(handle_t *handle, struct inode *inode) - { -- inode->i_nlink--; -+ if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) -+ inode->i_nlink--; - } - - static int ext3_add_nondir(handle_t *handle, -@@ -1654,7 +1660,7 @@ static int ext3_mkdir(struct inode * dir - struct ext3_dir_entry_2 * de; - int err; - -- if (dir->i_nlink >= EXT3_LINK_MAX) -+ if (EXT3_DIR_LINK_MAX(dir)) - return -EMLINK; - - handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -@@ -1676,7 +1682,7 @@ static int ext3_mkdir(struct inode * dir - inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { -- inode->i_nlink--; /* is this nlink == 0? */ -+ ext3_dec_count(handle, inode); /* is this nlink == 0? */ - ext3_mark_inode_dirty(handle, inode); - iput (inode); - goto out_stop; -@@ -1708,7 +1714,7 @@ static int ext3_mkdir(struct inode * dir - iput (inode); - goto out_stop; - } -- dir->i_nlink++; -+ ext3_inc_count(handle, dir); - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); -@@ -1769,10 +1775,11 @@ static int empty_dir (struct inode * ino - } - de = (struct ext3_dir_entry_2 *) bh->b_data; - } -- if (!ext3_check_dir_entry ("empty_dir", inode, de, bh, -- offset)) { -- brelse (bh); -- return 1; -+ if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) { -+ /* On error skip the de and offset to the next block. */ -+ de = (void *)(bh->b_data + sb->s_blocksize); -+ offset = (offset | (sb->s_blocksize - 1)) + 1; -+ continue; - } - if (le32_to_cpu(de->inode)) { - brelse (bh); -@@ -1965,14 +1972,14 @@ static int ext3_rmdir (struct inode * di - retval = ext3_delete_entry(handle, dir, de, bh); - if (retval) - goto end_rmdir; -- if (inode->i_nlink != 2) -- ext3_warning (inode->i_sb, "ext3_rmdir", -- "empty directory has nlink!=2 (%d)", -- inode->i_nlink); -+ if (!EXT3_DIR_LINK_EMPTY(inode)) -+ ext3_warning(inode->i_sb, __FUNCTION__, -+ "empty directory has too many links (%d)", -+ inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; - ext3_orphan_add(handle, inode); -- dir->i_nlink--; -+ ext3_dec_count(handle, dir); - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); - ext3_update_dx_flag(dir); -@@ -2024,7 +2031,7 @@ static int ext3_unlink(struct inode * di - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); -- inode->i_nlink--; -+ ext3_dec_count(handle, inode); - if (!inode->i_nlink) - ext3_orphan_add(handle, inode); - inode->i_ctime = dir->i_ctime; -@@ -2116,9 +2123,8 @@ static int ext3_link (struct dentry * ol - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) { -+ if (EXT3_DIR_LINK_MAX(inode)) - return -EMLINK; -- } - - handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + - EXT3_INDEX_EXTRA_TRANS_BLOCKS); -@@ -2202,8 +2208,8 @@ static int ext3_rename (struct inode * o - if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) - goto end_rename; - retval = -EMLINK; -- if (!new_inode && new_dir!=old_dir && -- new_dir->i_nlink >= EXT3_LINK_MAX) -+ if (!new_inode && new_dir != old_dir && -+ EXT3_DIR_LINK_MAX(new_dir)) - goto end_rename; - } - if (!new_bh) { -@@ -2261,7 +2267,7 @@ static int ext3_rename (struct inode * o - } - - if (new_inode) { -- new_inode->i_nlink--; -+ ext3_dec_count(handle, new_inode); - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -@@ -2272,11 +2278,13 @@ static int ext3_rename (struct inode * o - PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); - BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, dir_bh); -- old_dir->i_nlink--; -+ ext3_dec_count(handle, old_dir); - if (new_inode) { -- new_inode->i_nlink--; -+ /* checked empty_dir above, can't have another parent, -+ * ext3_dec_count() won't work for many-linked dirs */ -+ new_inode->i_nlink = 0; - } else { -- new_dir->i_nlink++; -+ ext3_inc_count(handle, new_dir); - ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } -Index: linux/include/linux/ext3_fs.h -=================================================================== ---- linux.orig/include/linux/ext3_fs.h -+++ linux/include/linux/ext3_fs.h -@@ -79,7 +79,7 @@ - /* - * Maximal count of links to a file - */ --#define EXT3_LINK_MAX 32000 -+#define EXT3_LINK_MAX 65000 - - /* - * Macro-instructions used to manage several block sizes -@@ -503,6 +503,7 @@ struct ext3_super_block { - #define EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 - #define EXT3_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 - #define EXT3_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 -+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 - - #define EXT3_FEATURE_INCOMPAT_COMPRESSION 0x0001 - #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 -@@ -516,6 +517,7 @@ struct ext3_super_block { - EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ -+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) - - /* diff --git a/lustre/kernel_patches/patches/ext3-nlinks-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-nlinks-2.4.21-chaos.patch deleted file mode 100644 index bed994b..0000000 --- a/lustre/kernel_patches/patches/ext3-nlinks-2.4.21-chaos.patch +++ /dev/null @@ -1,172 +0,0 @@ -Index: linux-2.4.21/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21.orig/fs/ext3/namei.c -+++ linux-2.4.21/fs/ext3/namei.c -@@ -1550,11 +1550,17 @@ static int ext3_delete_entry (handle_t * - static inline void ext3_inc_count(handle_t *handle, struct inode *inode) - { - inode->i_nlink++; -+ if (is_dx(inode) && inode->i_nlink > 1) { -+ /* limit is 16-bit i_links_count */ -+ if (inode->i_nlink >= EXT3_LINK_MAX || inode->i_nlink == 2) -+ inode->i_nlink = 1; -+ } - } - - static inline void ext3_dec_count(handle_t *handle, struct inode *inode) - { -- inode->i_nlink--; -+ if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) -+ inode->i_nlink--; - } - - static int ext3_add_nondir(handle_t *handle, -@@ -1658,7 +1664,7 @@ static int ext3_mkdir(struct inode * dir - struct ext3_dir_entry_2 * de; - int err; - -- if (dir->i_nlink >= EXT3_LINK_MAX) -+ if (EXT3_DIR_LINK_MAX(dir)) - return -EMLINK; - - handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -@@ -1680,7 +1686,7 @@ static int ext3_mkdir(struct inode * dir - inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { -- inode->i_nlink--; /* is this nlink == 0? */ -+ ext3_dec_count(handle, inode); /* is this nlink == 0? */ - ext3_mark_inode_dirty(handle, inode); - iput (inode); - goto out_stop; -@@ -1712,7 +1718,7 @@ static int ext3_mkdir(struct inode * dir - iput (inode); - goto out_stop; - } -- dir->i_nlink++; -+ ext3_inc_count(handle, dir); - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); -@@ -1773,10 +1779,11 @@ static int empty_dir (struct inode * ino - } - de = (struct ext3_dir_entry_2 *) bh->b_data; - } -- if (!ext3_check_dir_entry ("empty_dir", inode, de, bh, -- offset)) { -- brelse (bh); -- return 1; -+ if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) { -+ /* On error skip the de and offset to the next block. */ -+ de = (void *)(bh->b_data + sb->s_blocksize); -+ offset = (offset | (sb->s_blocksize - 1)) + 1; -+ continue; - } - if (le32_to_cpu(de->inode)) { - brelse (bh); -@@ -1968,14 +1975,14 @@ static int ext3_rmdir (struct inode * di - retval = ext3_delete_entry(handle, dir, de, bh); - if (retval) - goto end_rmdir; -- if (inode->i_nlink != 2) -- ext3_warning (inode->i_sb, "ext3_rmdir", -- "empty directory has nlink!=2 (%d)", -- inode->i_nlink); -+ if (!EXT3_DIR_LINK_EMPTY(inode)) -+ ext3_warning(inode->i_sb, __FUNCTION__, -+ "empty directory has too many links (%d)", -+ inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; - ext3_orphan_add(handle, inode); -- dir->i_nlink--; -+ ext3_dec_count(handle, dir); - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); - ext3_update_dx_flag(dir); -@@ -2061,7 +2068,7 @@ static int ext3_unlink(struct inode * di - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); -- inode->i_nlink--; -+ ext3_dec_count(handle, inode); - if (!inode->i_nlink) { - ext3_try_to_delay_deletion(inode); - ext3_orphan_add(handle, inode); -@@ -2155,9 +2162,8 @@ static int ext3_link (struct dentry * ol - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) { -+ if (EXT3_DIR_LINK_MAX(inode)) - return -EMLINK; -- } - - handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + - EXT3_INDEX_EXTRA_TRANS_BLOCKS); -@@ -2241,8 +2247,8 @@ static int ext3_rename (struct inode * o - if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) - goto end_rename; - retval = -EMLINK; -- if (!new_inode && new_dir!=old_dir && -- new_dir->i_nlink >= EXT3_LINK_MAX) -+ if (!new_inode && new_dir != old_dir && -+ EXT3_DIR_LINK_MAX(new_dir)) - goto end_rename; - } - if (!new_bh) { -@@ -2300,7 +2306,7 @@ static int ext3_rename (struct inode * o - } - - if (new_inode) { -- new_inode->i_nlink--; -+ ext3_dec_count(handle, new_inode); - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -@@ -2311,11 +2317,13 @@ static int ext3_rename (struct inode * o - PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); - BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, dir_bh); -- old_dir->i_nlink--; -+ ext3_dec_count(handle, old_dir); - if (new_inode) { -- new_inode->i_nlink--; -+ /* checked empty_dir above, can't have another parent, -+ * ext3_dec_count() won't work for many-linked dirs */ -+ new_inode->i_nlink = 0; - } else { -- new_dir->i_nlink++; -+ ext3_inc_count(handle, new_dir); - ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } -Index: linux-2.4.21/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21.orig/include/linux/ext3_fs.h -+++ linux-2.4.21/include/linux/ext3_fs.h -@@ -81,7 +81,7 @@ - /* - * Maximal count of links to a file - */ --#define EXT3_LINK_MAX 32000 -+#define EXT3_LINK_MAX 65000 - - /* - * Macro-instructions used to manage several block sizes -@@ -505,6 +505,7 @@ static inline struct inode *orphan_list_ - #define EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 - #define EXT3_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 - #define EXT3_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 -+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 - - #define EXT3_FEATURE_INCOMPAT_COMPRESSION 0x0001 - #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 -@@ -518,6 +519,7 @@ static inline struct inode *orphan_list_ - EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ -+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) - - /* diff --git a/lustre/kernel_patches/patches/ext3-nlinks-2.4.24.patch b/lustre/kernel_patches/patches/ext3-nlinks-2.4.24.patch deleted file mode 100644 index 0e47e28..0000000 --- a/lustre/kernel_patches/patches/ext3-nlinks-2.4.24.patch +++ /dev/null @@ -1,172 +0,0 @@ -Index: linux-2.4.24/fs/ext3/namei.c -=================================================================== ---- linux-2.4.24.orig/fs/ext3/namei.c -+++ linux-2.4.24/fs/ext3/namei.c -@@ -1549,11 +1549,17 @@ static int ext3_delete_entry (handle_t * - static inline void ext3_inc_count(handle_t *handle, struct inode *inode) - { - inode->i_nlink++; -+ if (is_dx(inode) && inode->i_nlink > 1) { -+ /* limit is 16-bit i_links_count */ -+ if (inode->i_nlink >= EXT3_LINK_MAX || inode->i_nlink == 2) -+ inode->i_nlink = 1; -+ } - } - - static inline void ext3_dec_count(handle_t *handle, struct inode *inode) - { -- inode->i_nlink--; -+ if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) -+ inode->i_nlink--; - } - - static int ext3_add_nondir(handle_t *handle, -@@ -1654,7 +1660,7 @@ static int ext3_mkdir(struct inode * dir - struct ext3_dir_entry_2 * de; - int err; - -- if (dir->i_nlink >= EXT3_LINK_MAX) -+ if (EXT3_DIR_LINK_MAX(dir)) - return -EMLINK; - - handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + -@@ -1676,7 +1682,7 @@ static int ext3_mkdir(struct inode * dir - inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { -- inode->i_nlink--; /* is this nlink == 0? */ -+ ext3_dec_count(handle, inode); /* is this nlink == 0? */ - ext3_mark_inode_dirty(handle, inode); - iput (inode); - goto out_stop; -@@ -1708,7 +1714,7 @@ static int ext3_mkdir(struct inode * dir - iput (inode); - goto out_stop; - } -- dir->i_nlink++; -+ ext3_inc_count(handle, dir); - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); - d_instantiate(dentry, inode); -@@ -1769,10 +1775,11 @@ static int empty_dir (struct inode * ino - } - de = (struct ext3_dir_entry_2 *) bh->b_data; - } -- if (!ext3_check_dir_entry ("empty_dir", inode, de, bh, -- offset)) { -- brelse (bh); -- return 1; -+ if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) { -+ /* On error skip the de and offset to the next block. */ -+ de = (void *)(bh->b_data + sb->s_blocksize); -+ offset = (offset | (sb->s_blocksize - 1)) + 1; -+ continue; - } - if (le32_to_cpu(de->inode)) { - brelse (bh); -@@ -1965,14 +1972,14 @@ static int ext3_rmdir (struct inode * di - retval = ext3_delete_entry(handle, dir, de, bh); - if (retval) - goto end_rmdir; -- if (inode->i_nlink != 2) -- ext3_warning (inode->i_sb, "ext3_rmdir", -- "empty directory has nlink!=2 (%d)", -- inode->i_nlink); -+ if (!EXT3_DIR_LINK_EMPTY(inode)) -+ ext3_warning(inode->i_sb, __FUNCTION__, -+ "empty directory has too many links (%d)", -+ inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; - ext3_orphan_add(handle, inode); -- dir->i_nlink--; -+ ext3_dec_count(handle, dir); - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_mark_inode_dirty(handle, inode); - ext3_update_dx_flag(dir); -@@ -2058,7 +2065,7 @@ static int ext3_unlink(struct inode * di - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - ext3_update_dx_flag(dir); - ext3_mark_inode_dirty(handle, dir); -- inode->i_nlink--; -+ ext3_dec_count(handle, inode); - if (!inode->i_nlink) { - ext3_try_to_delay_deletion(inode); - ext3_orphan_add(handle, inode); -@@ -2152,9 +2159,8 @@ static int ext3_link (struct dentry * ol - if (S_ISDIR(inode->i_mode)) - return -EPERM; - -- if (inode->i_nlink >= EXT3_LINK_MAX) { -+ if (EXT3_DIR_LINK_MAX(inode)) - return -EMLINK; -- } - - handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + - EXT3_INDEX_EXTRA_TRANS_BLOCKS); -@@ -2238,8 +2244,8 @@ static int ext3_rename (struct inode * o - if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) - goto end_rename; - retval = -EMLINK; -- if (!new_inode && new_dir!=old_dir && -- new_dir->i_nlink >= EXT3_LINK_MAX) -+ if (!new_inode && new_dir != old_dir && -+ EXT3_DIR_LINK_MAX(new_dir)) - goto end_rename; - } - if (!new_bh) { -@@ -2297,7 +2303,7 @@ static int ext3_rename (struct inode * o - } - - if (new_inode) { -- new_inode->i_nlink--; -+ ext3_dec_count(handle, new_inode); - new_inode->i_ctime = CURRENT_TIME; - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; -@@ -2308,11 +2314,13 @@ static int ext3_rename (struct inode * o - PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); - BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, dir_bh); -- old_dir->i_nlink--; -+ ext3_dec_count(handle, old_dir); - if (new_inode) { -- new_inode->i_nlink--; -+ /* checked empty_dir above, can't have another parent, -+ * ext3_dec_count() won't work for many-linked dirs */ -+ new_inode->i_nlink = 0; - } else { -- new_dir->i_nlink++; -+ ext3_inc_count(handle, new_dir); - ext3_update_dx_flag(new_dir); - ext3_mark_inode_dirty(handle, new_dir); - } -Index: linux-2.4.24/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.24.orig/include/linux/ext3_fs.h -+++ linux-2.4.24/include/linux/ext3_fs.h -@@ -79,7 +79,7 @@ - /* - * Maximal count of links to a file - */ --#define EXT3_LINK_MAX 32000 -+#define EXT3_LINK_MAX 65000 - - /* - * Macro-instructions used to manage several block sizes -@@ -504,6 +504,7 @@ struct ext3_super_block { - #define EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 - #define EXT3_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 - #define EXT3_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 -+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 - - #define EXT3_FEATURE_INCOMPAT_COMPRESSION 0x0001 - #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 -@@ -517,6 +518,7 @@ struct ext3_super_block { - EXT3_FEATURE_INCOMPAT_EXTENTS) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ -+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) - - /* diff --git a/lustre/kernel_patches/patches/ext3-no-write-super-chaos.patch b/lustre/kernel_patches/patches/ext3-no-write-super-chaos.patch deleted file mode 100644 index 37a5d7a..0000000 --- a/lustre/kernel_patches/patches/ext3-no-write-super-chaos.patch +++ /dev/null @@ -1,15 +0,0 @@ - fs/ext3/super.c | 1 - - 1 files changed, 1 deletion(-) - ---- linux-2.4.18-chaos/fs/ext3/super.c~ext3-no-write-super-chaos 2003-08-24 21:34:53.000000000 +0400 -+++ linux-2.4.18-chaos-alexey/fs/ext3/super.c 2003-08-24 21:40:47.000000000 +0400 -@@ -1818,7 +1818,6 @@ void ext3_write_super (struct super_bloc - if (down_trylock(&sb->s_lock) == 0) - BUG(); - sb->s_dirt = 0; -- log_start_commit(EXT3_SB(sb)->s_journal, NULL); - } - - static int ext3_sync_fs(struct super_block *sb) - -_ diff --git a/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch b/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch deleted file mode 100644 index f8270b2..0000000 --- a/lustre/kernel_patches/patches/ext3-noread-2.4.20.patch +++ /dev/null @@ -1,218 +0,0 @@ - fs/ext3/ialloc.c | 47 ++++++++++++++++++++++- - fs/ext3/inode.c | 96 +++++++++++++++++++++++++++++++++++++----------- - include/linux/ext3_fs.h | 2 + - 3 files changed, 121 insertions(+), 24 deletions(-) - ---- linux-2.4.20/fs/ext3/ialloc.c~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800 -+++ linux-2.4.20-root/fs/ext3/ialloc.c 2003-05-16 12:21:46.000000000 +0800 -@@ -289,6 +289,37 @@ error_return: - } - - /* -+ * @block_group: block group of inode -+ * @offset: relative offset of inode within @block_group -+ * -+ * Check whether any of the inodes in this disk block are in use. -+ * -+ * Caller must be holding superblock lock (group/bitmap read lock in future). -+ */ -+int ext3_itable_block_used(struct super_block *sb, unsigned int block_group, -+ int offset) -+{ -+ int bitmap_nr = load_inode_bitmap(sb, block_group); -+ int inodes_per_block; -+ unsigned long inum, iend; -+ struct buffer_head *ibitmap; -+ -+ if (bitmap_nr < 0) -+ return 1; -+ -+ inodes_per_block = sb->s_blocksize / EXT3_SB(sb)->s_inode_size; -+ inum = offset & ~(inodes_per_block - 1); -+ iend = inum + inodes_per_block; -+ ibitmap = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; -+ for (; inum < iend; inum++) { -+ if (inum != offset && ext3_test_bit(inum, ibitmap->b_data)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* - * There are two policies for allocating an inode. If the new inode is - * a directory, then a forward search is made for a block group with both - * free space and a low directory-to-inode ratio; if that fails, then of -@@ -310,6 +341,7 @@ struct inode * ext3_new_inode (handle_t - struct ext3_group_desc * gdp; - struct ext3_group_desc * tmp; - struct ext3_super_block * es; -+ struct ext3_iloc iloc; - int err = 0; - - /* Cannot create files in a deleted directory */ -@@ -510,8 +542,19 @@ repeat: - inode->i_generation = sb->u.ext3_sb.s_next_generation++; - - inode->u.ext3_i.i_state = EXT3_STATE_NEW; -- err = ext3_mark_inode_dirty(handle, inode); -- if (err) goto fail; -+ err = ext3_get_inode_loc_new(inode, &iloc, 1); -+ if (err) goto fail; -+ BUFFER_TRACE(iloc->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, iloc.bh); -+ if (err) { -+ brelse(iloc.bh); -+ iloc.bh = NULL; -+ goto fail; -+ } -+ err = ext3_mark_iloc_dirty(handle, inode, &iloc); -+ if (err) goto fail; -+ -+ - - unlock_super (sb); - if(DQUOT_ALLOC_INODE(inode)) { ---- linux-2.4.20/fs/ext3/inode.c~ext3-noread-2.4.20 2003-05-16 12:21:41.000000000 +0800 -+++ linux-2.4.20-root/fs/ext3/inode.c 2003-05-16 12:22:15.000000000 +0800 -@@ -2013,14 +2013,19 @@ out_stop: - ext3_journal_stop(handle, inode); - } - --/* -- * ext3_get_inode_loc returns with an extra refcount against the -- * inode's underlying buffer_head on success. -- */ -- --int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc) -+#define NUM_INODE_PREREAD 16 -+ -+/* -+ * ext3_get_inode_loc returns with an extra refcount against the inode's -+ * underlying buffer_head on success. If this is for a new inode allocation -+ * (new is non-zero) then we may be able to optimize away the read if there -+ * are no other in-use inodes in this inode table block. If we need to do -+ * a read, then read in a whole chunk of blocks to avoid blocking again soon -+ * if we are doing lots of creates/updates. -+ */ -+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new) - { -- struct buffer_head *bh = 0; -+ struct buffer_head *bh[NUM_INODE_PREREAD]; - unsigned long block; - unsigned long block_group; - unsigned long group_desc; -@@ -2045,31 +2050,73 @@ int ext3_get_inode_loc (struct inode *in - } - group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb); - desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1); -- bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc]; -- if (!bh) { -+ if (!(inode->i_sb->u.ext3_sb.s_group_desc[group_desc])) { - ext3_error (inode->i_sb, "ext3_get_inode_loc", - "Descriptor not loaded"); - goto bad_inode; - } - -- gdp = (struct ext3_group_desc *) bh->b_data; -+ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data); - /* - * Figure out the offset within the block group inode table - */ -- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) * -- EXT3_INODE_SIZE(inode->i_sb); -+ offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)); -+ - block = le32_to_cpu(gdp[desc].bg_inode_table) + -- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb)); -- if (!(bh = sb_bread(inode->i_sb, block))) { -- ext3_error (inode->i_sb, "ext3_get_inode_loc", -- "unable to read inode block - " -- "inode=%lu, block=%lu", inode->i_ino, block); -- goto bad_inode; -- } -- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1); -+ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb)); - -- iloc->bh = bh; -- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset); -+ bh[0] = sb_getblk(inode->i_sb, block); -+ if (buffer_uptodate(bh[0])) -+ goto done; -+ -+ /* If we don't really need to read this block, and it isn't already -+ * in memory, then we just zero it out. Otherwise, we keep the -+ * current block contents (deleted inode data) for posterity. -+ */ -+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) { -+ lock_buffer(bh[0]); -+ memset(bh[0]->b_data, 0, bh[0]->b_size); -+ mark_buffer_uptodate(bh[0], 1); -+ unlock_buffer(bh[0]); -+ } else { -+ unsigned long block_end, itable_end; -+ int count = 1; -+ -+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) + -+ inode->i_sb->u.ext3_sb.s_itb_per_group; -+ block_end = block + NUM_INODE_PREREAD; -+ if (block_end > itable_end) -+ block_end = itable_end; -+ -+ for (++block; block < block_end; block++) { -+ bh[count] = sb_getblk(inode->i_sb, block); -+ if (count && (buffer_uptodate(bh[count]) || -+ buffer_locked(bh[count]))) { -+ __brelse(bh[count]); -+ } else -+ count++; -+ } -+ -+ ll_rw_block(READ, count, bh); -+ -+ /* Release all but the block we actually need (bh[0]) */ -+ while (--count > 0) -+ __brelse(bh[count]); -+ -+ wait_on_buffer(bh[0]); -+ if (!buffer_uptodate(bh[0])) { -+ ext3_error(inode->i_sb, __FUNCTION__, -+ "unable to read inode block - " -+ "inode=%lu, block=%lu", inode->i_ino, -+ bh[0]->b_blocknr); -+ goto bad_inode; -+ } -+ } -+done: -+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1); -+ -+ iloc->bh = bh[0]; -+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset); - iloc->block_group = block_group; - - return 0; -@@ -2078,6 +2125,11 @@ int ext3_get_inode_loc (struct inode *in - return -EIO; - } - -+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc) -+{ -+ return ext3_get_inode_loc_new(inode, iloc, 0); -+} -+ - void ext3_read_inode(struct inode * inode) - { - struct ext3_iloc iloc; ---- linux-2.4.20/include/linux/ext3_fs.h~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800 -+++ linux-2.4.20-root/include/linux/ext3_fs.h 2003-05-16 12:21:46.000000000 +0800 -@@ -683,6 +683,8 @@ extern int ext3_forget(handle_t *, int, - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); - -+extern int ext3_itable_block_used(struct super_block *sb, unsigned int, int); -+extern int ext3_get_inode_loc_new(struct inode *, struct ext3_iloc *, int); - extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *); - extern void ext3_read_inode (struct inode *); - extern void ext3_write_inode (struct inode *, int); - -_ diff --git a/lustre/kernel_patches/patches/ext3-noread-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-noread-2.4.21-chaos.patch deleted file mode 100644 index 1903baa..0000000 --- a/lustre/kernel_patches/patches/ext3-noread-2.4.21-chaos.patch +++ /dev/null @@ -1,223 +0,0 @@ - fs/ext3/ialloc.c | 47 ++++++++++++++++++++++- - fs/ext3/inode.c | 96 +++++++++++++++++++++++++++++++++++++----------- - include/linux/ext3_fs.h | 2 + - 3 files changed, 121 insertions(+), 24 deletions(-) - -Index: linux-2.4.21-chaos/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c 2003-12-12 12:56:39.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ialloc.c 2003-12-12 13:21:50.000000000 +0300 -@@ -290,6 +290,37 @@ - } - - /* -+ * @block_group: block group of inode -+ * @offset: relative offset of inode within @block_group -+ * -+ * Check whether any of the inodes in this disk block are in use. -+ * -+ * Caller must be holding superblock lock (group/bitmap read lock in future). -+ */ -+int ext3_itable_block_used(struct super_block *sb, unsigned int block_group, -+ int offset) -+{ -+ int bitmap_nr = load_inode_bitmap(sb, block_group); -+ int inodes_per_block; -+ unsigned long inum, iend; -+ struct buffer_head *ibitmap; -+ -+ if (bitmap_nr < 0) -+ return 1; -+ -+ inodes_per_block = sb->s_blocksize / EXT3_SB(sb)->s_inode_size; -+ inum = offset & ~(inodes_per_block - 1); -+ iend = inum + inodes_per_block; -+ ibitmap = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; -+ for (; inum < iend; inum++) { -+ if (inum != offset && ext3_test_bit(inum, ibitmap->b_data)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* - * There are two policies for allocating an inode. If the new inode is - * a directory, then a forward search is made for a block group with both - * free space and a low directory-to-inode ratio; if that fails, then of -@@ -312,6 +343,7 @@ - struct ext3_group_desc * gdp; - struct ext3_group_desc * tmp; - struct ext3_super_block * es; -+ struct ext3_iloc iloc; - int err = 0; - - /* Cannot create files in a deleted directory */ -@@ -513,8 +545,19 @@ - inode->i_generation = sbi->s_next_generation++; - - ei->i_state = EXT3_STATE_NEW; -- err = ext3_mark_inode_dirty(handle, inode); -- if (err) goto fail; -+ err = ext3_get_inode_loc_new(inode, &iloc, 1); -+ if (err) goto fail; -+ BUFFER_TRACE(iloc->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, iloc.bh); -+ if (err) { -+ brelse(iloc.bh); -+ iloc.bh = NULL; -+ goto fail; -+ } -+ err = ext3_mark_iloc_dirty(handle, inode, &iloc); -+ if (err) goto fail; -+ -+ - - #ifdef CONFIG_EXT3_FS_XATTR - init_rwsem(&EXT3_I(inode)->xattr_sem); -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 13:01:48.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 13:22:45.000000000 +0300 -@@ -2291,16 +2291,21 @@ - } - #endif /* EXT3_DELETE_THREAD */ - --/* -- * ext3_get_inode_loc returns with an extra refcount against the -- * inode's underlying buffer_head on success. -- */ -- --int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc) -+#define NUM_INODE_PREREAD 16 -+ -+/* -+ * ext3_get_inode_loc returns with an extra refcount against the inode's -+ * underlying buffer_head on success. If this is for a new inode allocation -+ * (new is non-zero) then we may be able to optimize away the read if there -+ * are no other in-use inodes in this inode table block. If we need to do -+ * a read, then read in a whole chunk of blocks to avoid blocking again soon -+ * if we are doing lots of creates/updates. -+ */ -+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new) - { - struct super_block *sb = inode->i_sb; - struct ext3_sb_info *sbi = EXT3_SB(sb); -- struct buffer_head *bh = 0; -+ struct buffer_head *bh[NUM_INODE_PREREAD]; - unsigned long block; - unsigned long block_group; - unsigned long group_desc; -@@ -2322,30 +2327,72 @@ - } - group_desc = block_group >> sbi->s_desc_per_block_bits; - desc = block_group & (sbi->s_desc_per_block - 1); -- bh = sbi->s_group_desc[group_desc]; -- if (!bh) { -+ if (!(sbi->s_group_desc[group_desc])) { - ext3_error(sb, __FUNCTION__, "Descriptor not loaded"); - goto bad_inode; - } - -- gdp = (struct ext3_group_desc *) bh->b_data; -+ gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data); - /* - * Figure out the offset within the block group inode table - */ -- offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group) * -- sbi->s_inode_size; -+ offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)); -+ - block = le32_to_cpu(gdp[desc].bg_inode_table) + -- (offset >> EXT3_BLOCK_SIZE_BITS(sb)); -- if (!(bh = sb_bread(sb, block))) { -- ext3_error (sb, __FUNCTION__, -- "unable to read inode block - " -- "inode=%lu, block=%lu", inode->i_ino, block); -- goto bad_inode; -- } -- offset &= (EXT3_BLOCK_SIZE(sb) - 1); -+ (offset * EXT3_INODE_SIZE(sb) >> EXT3_BLOCK_SIZE_BITS(sb)); - -- iloc->bh = bh; -- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset); -+ bh[0] = sb_getblk(inode->i_sb, block); -+ if (buffer_uptodate(bh[0])) -+ goto done; -+ -+ /* If we don't really need to read this block, and it isn't already -+ * in memory, then we just zero it out. Otherwise, we keep the -+ * current block contents (deleted inode data) for posterity. -+ */ -+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) { -+ lock_buffer(bh[0]); -+ memset(bh[0]->b_data, 0, bh[0]->b_size); -+ mark_buffer_uptodate(bh[0], 1); -+ unlock_buffer(bh[0]); -+ } else { -+ unsigned long block_end, itable_end; -+ int count = 1; -+ -+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) + -+ inode->i_sb->u.ext3_sb.s_itb_per_group; -+ block_end = block + NUM_INODE_PREREAD; -+ if (block_end > itable_end) -+ block_end = itable_end; -+ -+ for (++block; block < block_end; block++) { -+ bh[count] = sb_getblk(inode->i_sb, block); -+ if (count && (buffer_uptodate(bh[count]) || -+ buffer_locked(bh[count]))) { -+ __brelse(bh[count]); -+ } else -+ count++; -+ } -+ -+ ll_rw_block(READ, count, bh); -+ -+ /* Release all but the block we actually need (bh[0]) */ -+ while (--count > 0) -+ __brelse(bh[count]); -+ -+ wait_on_buffer(bh[0]); -+ if (!buffer_uptodate(bh[0])) { -+ ext3_error(inode->i_sb, __FUNCTION__, -+ "unable to read inode block - " -+ "inode=%lu, block=%lu", inode->i_ino, -+ bh[0]->b_blocknr); -+ goto bad_inode; -+ } -+ } -+ done: -+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1); -+ -+ iloc->bh = bh[0]; -+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset); - iloc->block_group = block_group; - - return 0; -@@ -2370,6 +2417,11 @@ - } - - -+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc) -+{ -+ return ext3_get_inode_loc_new(inode, iloc, 0); -+} -+ - void ext3_read_inode(struct inode * inode) - { - struct ext3_iloc iloc; -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 13:01:48.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 13:21:50.000000000 +0300 -@@ -683,6 +683,8 @@ - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); - -+extern int ext3_itable_block_used(struct super_block *sb, unsigned int, int); -+extern int ext3_get_inode_loc_new(struct inode *, struct ext3_iloc *, int); - extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *); - extern void ext3_read_inode (struct inode *); - extern void ext3_write_inode (struct inode *, int); diff --git a/lustre/kernel_patches/patches/ext3-noread-2.4.21-suse2.patch b/lustre/kernel_patches/patches/ext3-noread-2.4.21-suse2.patch deleted file mode 100644 index 66274d8..0000000 --- a/lustre/kernel_patches/patches/ext3-noread-2.4.21-suse2.patch +++ /dev/null @@ -1,218 +0,0 @@ - fs/ext3/ialloc.c | 47 ++++++++++++++++++++++- - fs/ext3/inode.c | 96 +++++++++++++++++++++++++++++++++++++----------- - include/linux/ext3_fs.h | 2 + - 3 files changed, 121 insertions(+), 24 deletions(-) - ---- linux-2.4.20/fs/ext3/ialloc.c~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800 -+++ linux-2.4.20-root/fs/ext3/ialloc.c 2003-05-16 12:21:46.000000000 +0800 -@@ -289,6 +289,37 @@ error_return: - } - - /* -+ * @block_group: block group of inode -+ * @offset: relative offset of inode within @block_group -+ * -+ * Check whether any of the inodes in this disk block are in use. -+ * -+ * Caller must be holding superblock lock (group/bitmap read lock in future). -+ */ -+int ext3_itable_block_used(struct super_block *sb, unsigned int block_group, -+ int offset) -+{ -+ int bitmap_nr = load_inode_bitmap(sb, block_group); -+ int inodes_per_block; -+ unsigned long inum, iend; -+ struct buffer_head *ibitmap; -+ -+ if (bitmap_nr < 0) -+ return 1; -+ -+ inodes_per_block = sb->s_blocksize / EXT3_SB(sb)->s_inode_size; -+ inum = offset & ~(inodes_per_block - 1); -+ iend = inum + inodes_per_block; -+ ibitmap = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; -+ for (; inum < iend; inum++) { -+ if (inum != offset && ext3_test_bit(inum, ibitmap->b_data)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* - * There are two policies for allocating an inode. If the new inode is - * a directory, then a forward search is made for a block group with both - * free space and a low directory-to-inode ratio; if that fails, then of -@@ -310,6 +341,7 @@ struct inode * ext3_new_inode (handle_t - struct ext3_group_desc * gdp; - struct ext3_group_desc * tmp; - struct ext3_super_block * es; -+ struct ext3_iloc iloc; - int err = 0; - - /* Cannot create files in a deleted directory */ -@@ -510,8 +542,19 @@ repeat: - inode->i_generation = sb->u.ext3_sb.s_next_generation++; - - inode->u.ext3_i.i_state = EXT3_STATE_NEW; -- err = ext3_mark_inode_dirty(handle, inode); -- if (err) goto fail; -+ err = ext3_get_inode_loc_new(inode, &iloc, 1); -+ if (err) goto fail; -+ BUFFER_TRACE(iloc->bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, iloc.bh); -+ if (err) { -+ brelse(iloc.bh); -+ iloc.bh = NULL; -+ goto fail; -+ } -+ err = ext3_mark_iloc_dirty(handle, inode, &iloc); -+ if (err) goto fail; -+ -+ - - #ifdef CONFIG_EXT3_FS_XATTR - init_rwsem(&inode->u.ext3_i.xattr_sem); ---- linux-2.4.20/fs/ext3/inode.c~ext3-noread-2.4.20 2003-05-16 12:21:41.000000000 +0800 -+++ linux-2.4.20-root/fs/ext3/inode.c 2003-05-16 12:22:15.000000000 +0800 -@@ -2013,14 +2013,19 @@ out_stop: - ext3_journal_stop(handle, inode); - } - --/* -- * ext3_get_inode_loc returns with an extra refcount against the -- * inode's underlying buffer_head on success. -- */ -- --int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc) -+#define NUM_INODE_PREREAD 16 -+ -+/* -+ * ext3_get_inode_loc returns with an extra refcount against the inode's -+ * underlying buffer_head on success. If this is for a new inode allocation -+ * (new is non-zero) then we may be able to optimize away the read if there -+ * are no other in-use inodes in this inode table block. If we need to do -+ * a read, then read in a whole chunk of blocks to avoid blocking again soon -+ * if we are doing lots of creates/updates. -+ */ -+int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new) - { -- struct buffer_head *bh = 0; -+ struct buffer_head *bh[NUM_INODE_PREREAD]; - unsigned long block; - unsigned long block_group; - unsigned long group_desc; -@@ -2045,31 +2050,73 @@ int ext3_get_inode_loc (struct inode *in - } - group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb); - desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1); -- bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc]; -- if (!bh) { -+ if (!(inode->i_sb->u.ext3_sb.s_group_desc[group_desc])) { - ext3_error (inode->i_sb, "ext3_get_inode_loc", - "Descriptor not loaded"); - goto bad_inode; - } - -- gdp = (struct ext3_group_desc *) bh->b_data; -+ gdp = (struct ext3_group_desc *)(inode->i_sb->u.ext3_sb.s_group_desc[group_desc]->b_data); - /* - * Figure out the offset within the block group inode table - */ -- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) * -- EXT3_INODE_SIZE(inode->i_sb); -+ offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)); -+ - block = le32_to_cpu(gdp[desc].bg_inode_table) + -- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb)); -- if (!(bh = sb_bread(inode->i_sb, block))) { -- ext3_error (inode->i_sb, "ext3_get_inode_loc", -- "unable to read inode block - " -- "inode=%lu, block=%lu", inode->i_ino, block); -- goto bad_inode; -- } -- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1); -+ (offset * EXT3_INODE_SIZE(inode->i_sb) >> EXT3_BLOCK_SIZE_BITS(inode->i_sb)); - -- iloc->bh = bh; -- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset); -+ bh[0] = sb_getblk(inode->i_sb, block); -+ if (buffer_uptodate(bh[0])) -+ goto done; -+ -+ /* If we don't really need to read this block, and it isn't already -+ * in memory, then we just zero it out. Otherwise, we keep the -+ * current block contents (deleted inode data) for posterity. -+ */ -+ if (new && !ext3_itable_block_used(inode->i_sb, block_group, offset)) { -+ lock_buffer(bh[0]); -+ memset(bh[0]->b_data, 0, bh[0]->b_size); -+ mark_buffer_uptodate(bh[0], 1); -+ unlock_buffer(bh[0]); -+ } else { -+ unsigned long block_end, itable_end; -+ int count = 1; -+ -+ itable_end = le32_to_cpu(gdp[desc].bg_inode_table) + -+ inode->i_sb->u.ext3_sb.s_itb_per_group; -+ block_end = block + NUM_INODE_PREREAD; -+ if (block_end > itable_end) -+ block_end = itable_end; -+ -+ for (++block; block < block_end; block++) { -+ bh[count] = sb_getblk(inode->i_sb, block); -+ if (count && (buffer_uptodate(bh[count]) || -+ buffer_locked(bh[count]))) { -+ __brelse(bh[count]); -+ } else -+ count++; -+ } -+ -+ ll_rw_block(READ, count, bh); -+ -+ /* Release all but the block we actually need (bh[0]) */ -+ while (--count > 0) -+ __brelse(bh[count]); -+ -+ wait_on_buffer(bh[0]); -+ if (!buffer_uptodate(bh[0])) { -+ ext3_error(inode->i_sb, __FUNCTION__, -+ "unable to read inode block - " -+ "inode=%lu, block=%lu", inode->i_ino, -+ bh[0]->b_blocknr); -+ goto bad_inode; -+ } -+ } -+ done: -+ offset = (offset * EXT3_INODE_SIZE(inode->i_sb)) & (EXT3_BLOCK_SIZE(inode->i_sb) - 1); -+ -+ iloc->bh = bh[0]; -+ iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset); - iloc->block_group = block_group; - - return 0; -@@ -2078,6 +2125,11 @@ int ext3_get_inode_loc (struct inode *in - return -EIO; - } - -+int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc) -+{ -+ return ext3_get_inode_loc_new(inode, iloc, 0); -+} -+ - void ext3_read_inode(struct inode * inode) - { - struct ext3_iloc iloc; ---- linux-2.4.20/include/linux/ext3_fs.h~ext3-noread-2.4.20 2003-05-16 12:21:39.000000000 +0800 -+++ linux-2.4.20-root/include/linux/ext3_fs.h 2003-05-16 12:21:46.000000000 +0800 -@@ -683,6 +683,8 @@ extern int ext3_forget(handle_t *, int, - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); - -+extern int ext3_itable_block_used(struct super_block *sb, unsigned int, int); -+extern int ext3_get_inode_loc_new(struct inode *, struct ext3_iloc *, int); - extern int ext3_get_inode_loc (struct inode *, struct ext3_iloc *); - extern void ext3_read_inode (struct inode *); - extern void ext3_write_inode (struct inode *, int); - -_ diff --git a/lustre/kernel_patches/patches/ext3-o_direct-2.4.21-chaos.patch b/lustre/kernel_patches/patches/ext3-o_direct-2.4.21-chaos.patch deleted file mode 100644 index 6f7bf17..0000000 --- a/lustre/kernel_patches/patches/ext3-o_direct-2.4.21-chaos.patch +++ /dev/null @@ -1,23 +0,0 @@ - -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 16:19:13.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 16:19:16.000000000 +0300 -@@ -3154,7 +3154,7 @@ - /* alloc blocks one by one */ - for (i = 0; i < nblocks; i++) { - ret = ext3_get_block_handle(handle, inode, blocks[i], -- &bh_tmp, 1); -+ &bh_tmp, 1, 1); - if (ret) - break; - -@@ -3229,7 +3229,7 @@ - if (blocks[i] != 0) - continue; - -- rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1); -+ rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1); - if (rc) { - printk(KERN_INFO "ext3_map_inode_page: error %d " - "allocating block %ld\n", rc, iblock); diff --git a/lustre/kernel_patches/patches/ext3-orphan_lock-2.4.22-rh.patch b/lustre/kernel_patches/patches/ext3-orphan_lock-2.4.22-rh.patch deleted file mode 100644 index f2d4889..0000000 --- a/lustre/kernel_patches/patches/ext3-orphan_lock-2.4.22-rh.patch +++ /dev/null @@ -1,82 +0,0 @@ - fs/ext3/namei.c | 15 +++++++-------- - fs/ext3/namei.c.orig | 21 +++++++++++++++------ - fs/ext3/super.c | 1 + - include/linux/ext3_fs_sb.h | 1 + - include/linux/ext3_fs_sb.h.orig | 2 ++ - 5 files changed, 26 insertions(+), 14 deletions(-) - ---- linux-2.4.22-ac1/fs/ext3/namei.c~ext3-orphan_lock-2.4.22-rh 2003-09-26 00:24:09.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/namei.c 2003-09-26 00:26:36.000000000 +0400 -@@ -1748,8 +1748,8 @@ int ext3_orphan_add(handle_t *handle, st - struct super_block *sb = inode->i_sb; - struct ext3_iloc iloc; - int err = 0, rc; -- -- lock_super(sb); -+ -+ down(&EXT3_SB(sb)->s_orphan_lock); - if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - -@@ -1797,7 +1797,7 @@ int ext3_orphan_add(handle_t *handle, st - jbd_debug(4, "orphan inode %ld will point to %d\n", - inode->i_ino, NEXT_ORPHAN(inode)); - out_unlock: -- unlock_super(sb); -+ up(&EXT3_SB(sb)->s_orphan_lock); - ext3_std_error(inode->i_sb, err); - return err; - } -@@ -1810,20 +1810,19 @@ int ext3_orphan_del(handle_t *handle, st - { - struct list_head *prev; - struct ext3_inode_info *ei = EXT3_I(inode); -- struct ext3_sb_info *sbi; -+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb); - unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; - -- lock_super(inode->i_sb); -+ down(&sbi->s_orphan_lock); - if (list_empty(&ei->i_orphan)) { -- unlock_super(inode->i_sb); -+ up(&sbi->s_orphan_lock); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); - prev = ei->i_orphan.prev; -- sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - -@@ -1872,7 +1871,7 @@ int ext3_orphan_del(handle_t *handle, st - out_err: - ext3_std_error(inode->i_sb, err); - out: -- unlock_super(inode->i_sb); -+ up(&sbi->s_orphan_lock); - return err; - - out_brelse: ---- linux-2.4.22-ac1/fs/ext3/super.c~ext3-orphan_lock-2.4.22-rh 2003-09-26 00:24:09.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/fs/ext3/super.c 2003-09-26 00:25:22.000000000 +0400 -@@ -1164,6 +1164,7 @@ struct super_block * ext3_read_super (st - sb->s_op = &ext3_sops; - sb->dq_op = &ext3_qops; - INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ -+ sema_init(&sbi->s_orphan_lock, 1); - - sb->s_root = 0; - ---- linux-2.4.22-ac1/include/linux/ext3_fs_sb.h~ext3-orphan_lock-2.4.22-rh 2003-09-26 00:24:08.000000000 +0400 -+++ linux-2.4.22-ac1-alexey/include/linux/ext3_fs_sb.h 2003-09-26 00:25:22.000000000 +0400 -@@ -72,6 +72,7 @@ struct ext3_sb_info { - struct inode * s_journal_inode; - struct journal_s * s_journal; - struct list_head s_orphan; -+ struct semaphore s_orphan_lock; - unsigned long s_commit_interval; - struct block_device *journal_bdev; - #ifdef CONFIG_JBD_DEBUG diff --git a/lustre/kernel_patches/patches/ext3-orphan_lock.patch b/lustre/kernel_patches/patches/ext3-orphan_lock.patch deleted file mode 100644 index d1e5c8d..0000000 --- a/lustre/kernel_patches/patches/ext3-orphan_lock.patch +++ /dev/null @@ -1,79 +0,0 @@ ---- linux/fs/ext3/namei.c.orig Fri Mar 14 14:11:58 2003 -+++ linux/fs/ext3/namei.c Fri Mar 14 14:39:48 2003 -@@ -1406,8 +1409,8 @@ - struct super_block *sb = inode->i_sb; - struct ext3_iloc iloc; - int err = 0, rc; -- -- lock_super(sb); -+ -+ down(&EXT3_SB(sb)->s_orphan_lock); - if (!list_empty(&EXT3_I(inode)->i_orphan)) - goto out_unlock; - -@@ -1455,7 +1458,7 @@ - jbd_debug(4, "orphan inode %ld will point to %d\n", - inode->i_ino, NEXT_ORPHAN(inode)); - out_unlock: -- unlock_super(sb); -+ up(&EXT3_SB(sb)->s_orphan_lock); - ext3_std_error(inode->i_sb, err); - return err; - } -@@ -1468,20 +1471,19 @@ - { - struct list_head *prev; - struct ext3_inode_info *ei = EXT3_I(inode); -- struct ext3_sb_info *sbi; -+ struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb); - unsigned long ino_next; - struct ext3_iloc iloc; - int err = 0; - -- lock_super(inode->i_sb); -+ down(&sbi->s_orphan_lock); - if (list_empty(&ei->i_orphan)) { -- unlock_super(inode->i_sb); -+ up(&sbi->s_orphan_lock); - return 0; - } - - ino_next = NEXT_ORPHAN(inode); - prev = ei->i_orphan.prev; -- sbi = EXT3_SB(inode->i_sb); - - jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino); - -@@ -1525,10 +1527,10 @@ - if (err) - goto out_brelse; - --out_err: -+out_err: - ext3_std_error(inode->i_sb, err); - out: -- unlock_super(inode->i_sb); -+ up(&sbi->s_orphan_lock); - return err; - - out_brelse: ---- linux/fs/ext3/super.c.orig Fri Mar 14 14:11:58 2003 -+++ linux/fs/ext3/super.c Fri Mar 14 14:36:00 2003 -@@ -1134,6 +1314,7 @@ - */ - sb->s_op = &ext3_sops; - INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ -+ sema_init(&sbi->s_orphan_lock, 1); - - sb->s_root = 0; - ---- linux/include/linux/ext3_fs_sb.h.orig Tue Feb 11 16:34:33 2003 -+++ linux/include/linux/ext3_fs_sb.h Fri Mar 14 14:30:11 2003 -@@ -67,6 +69,7 @@ - struct inode * s_journal_inode; - struct journal_s * s_journal; - struct list_head s_orphan; -+ struct semaphore s_orphan_lock; - unsigned long s_commit_interval; - struct block_device *journal_bdev; - #ifdef CONFIG_JBD_DEBUG diff --git a/lustre/kernel_patches/patches/ext3-raw-lookup.patch b/lustre/kernel_patches/patches/ext3-raw-lookup.patch deleted file mode 100644 index 216accc..0000000 --- a/lustre/kernel_patches/patches/ext3-raw-lookup.patch +++ /dev/null @@ -1,61 +0,0 @@ - fs/ext3/namei.c | 29 +++++++++++++++++++++++++++++ - include/linux/fs.h | 1 + - 2 files changed, 30 insertions(+) - ---- linux-2.4.20-vanilla/include/linux/fs.h~ext3-raw-lookup 2003-09-13 17:03:05.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/include/linux/fs.h 2003-09-15 10:16:38.000000000 +0400 -@@ -865,6 +865,7 @@ struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); - int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ int (*lookup_raw) (struct inode *, const char *, int, ino_t *); - struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); - int (*link_raw) (struct nameidata *,struct nameidata *); ---- linux-2.4.20-vanilla/fs/ext3/namei.c~ext3-raw-lookup 2003-09-13 17:03:05.000000000 +0400 -+++ linux-2.4.20-vanilla-alexey/fs/ext3/namei.c 2003-09-15 10:18:52.000000000 +0400 -@@ -957,6 +957,34 @@ static struct dentry *ext3_lookup(struct - return NULL; - } - -+static int ext3_lookup_raw(struct inode *dir, const char *name, -+ int len, ino_t *data) -+{ -+ struct ext3_dir_entry_2 *de; -+ struct buffer_head *bh; -+ struct dentry parent; -+ struct dentry dentry; -+ -+ if (len > EXT3_NAME_LEN) -+ return -ENAMETOOLONG; -+ -+ parent.d_inode = dir; -+ dentry.d_parent = &parent; -+ dentry.d_name.name = name; -+ dentry.d_name.len = len; -+ -+ bh = ext3_find_entry(&dentry, &de); -+ if (bh) { -+ unsigned long ino = le32_to_cpu(de->inode); -+ brelse (bh); -+ if (data) -+ *data = ino; -+ return 0; /* found name */ -+ } -+ -+ return -ENOENT; -+} -+ - #define S_SHIFT 12 - static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = { - [S_IFREG >> S_SHIFT] EXT3_FT_REG_FILE, -@@ -2247,6 +2275,7 @@ end_rename: - struct inode_operations ext3_dir_inode_operations = { - create: ext3_create, /* BKL held */ - lookup: ext3_lookup, /* BKL held */ -+ lookup_raw: ext3_lookup_raw, /* BKL held */ - link: ext3_link, /* BKL held */ - unlink: ext3_unlink, /* BKL held */ - symlink: ext3_symlink, /* BKL held */ - -_ diff --git a/lustre/kernel_patches/patches/ext3-san-2.4.20.patch b/lustre/kernel_patches/patches/ext3-san-2.4.20.patch deleted file mode 100644 index 148f4e3..0000000 --- a/lustre/kernel_patches/patches/ext3-san-2.4.20.patch +++ /dev/null @@ -1,117 +0,0 @@ - fs/ext3/ext3-exports.c | 9 ++++- - fs/ext3/inode.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 89 insertions(+), 1 deletion(-) - ---- linux/fs/ext3/inode.c~ext3-san-2.4.20-hp Tue Apr 29 11:01:52 2003 -+++ linux-mmonroe/fs/ext3/inode.c Tue Apr 29 11:01:53 2003 -@@ -2734,3 +2734,84 @@ int ext3_change_inode_journal_flag(struc - * here, in ext3_aops_journal_start() to ensure that the forthcoming "see if we - * need to extend" test in ext3_prepare_write() succeeds. - */ -+ -+/* for each block: 1 ind + 1 dind + 1 tind -+ * for each block: 3 bitmap blocks -+ * for each block: 3 group descriptor blocks -+ * i inode block -+ * 1 superblock -+ * 2 * EXT3_SINGLEDATA_TRANS_BLOCKS for the quote files -+ * ((1+1+1) * 3 * nblocks) + 1 + 1 + 2 * EXT3_SINGLEDATA_TRANS_BLOCKS -+ * -+ * XXX assuming: -+ * (1) fs logic block size == page size -+ * (2) ext3 in writeback mode -+ */ -+static inline int ext3_san_write_trans_blocks(int nblocks) -+{ -+ int ret; -+ -+ ret = (1 + 1 + 1) * 3 * nblocks + 1 + 1; -+ -+#ifdef CONFIG_QUOTA -+ ret += 2 * EXT3_SINGLEDATA_TRANS_BLOCKS; -+#endif -+ -+ return ret; -+} -+ -+/* Alloc blocks for an inode, while don't create any buffer/page -+ * for data I/O; set the inode size if file is extended. -+ * -+ * @inode: target inode -+ * @blocks: array of logic block number -+ * @nblocks: how many blocks need be alloced -+ * @newsize: new filesize we should set -+ * -+ * return: 0 success, otherwise failed -+ * (*blocks) contains physical block number alloced -+ * -+ * XXX this assume the fs block size == page size -+ */ -+int ext3_prep_san_write(struct inode *inode, long *blocks, -+ int nblocks, loff_t newsize) -+{ -+ handle_t *handle; -+ struct buffer_head bh_tmp; -+ int needed_blocks; -+ int i, ret = 0, ret2; -+ -+ needed_blocks = ext3_san_write_trans_blocks(nblocks); -+ -+ lock_kernel(); -+ handle = ext3_journal_start(inode, needed_blocks); -+ if (IS_ERR(handle)) { -+ unlock_kernel(); -+ return PTR_ERR(handle); -+ } -+ unlock_kernel(); -+ -+ /* alloc blocks one by one */ -+ for (i = 0; i < nblocks; i++) { -+ ret = ext3_get_block_handle(handle, inode, blocks[i], -+ &bh_tmp, 1); -+ if (ret) -+ break; -+ -+ blocks[i] = bh_tmp.b_blocknr; -+ } -+ -+ /* set inode size if needed */ -+ if (!ret && (newsize > inode->i_size)) { -+ inode->i_size = newsize; -+ ext3_mark_inode_dirty(handle, inode); -+ } -+ -+ lock_kernel(); -+ ret2 = ext3_journal_stop(handle, inode); -+ unlock_kernel(); -+ -+ if (!ret) -+ ret = ret2; -+ return ret; -+} ---- linux/fs/ext3/ext3-exports.c~ext3-san-2.4.20-hp Tue Apr 29 11:01:51 2003 -+++ linux-mmonroe/fs/ext3/ext3-exports.c Tue Apr 29 11:07:19 2003 -@@ -1,9 +1,15 @@ - #include - #include --#include -+#include -+#include -+#include - #include -+#include - #include - -+int ext3_prep_san_write(struct inode *inode, long *blocks, -+ int nblocks, loff_t newsize); -+ - EXPORT_SYMBOL(ext3_force_commit); - EXPORT_SYMBOL(ext3_bread); - EXPORT_SYMBOL(ext3_xattr_register); -@@ -11,3 +17,4 @@ EXPORT_SYMBOL(ext3_xattr_unregister); - EXPORT_SYMBOL(ext3_xattr_get); - EXPORT_SYMBOL(ext3_xattr_list); - EXPORT_SYMBOL(ext3_xattr_set); -+EXPORT_SYMBOL(ext3_prep_san_write); - -_ diff --git a/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch b/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch deleted file mode 100644 index 950ec9a..0000000 --- a/lustre/kernel_patches/patches/ext3-sector_t-overflow-2.4.patch +++ /dev/null @@ -1,41 +0,0 @@ -Subject: Avoid disk sector_t overflow for >2TB ext3 filesystem -From: Mingming Cao - - -If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. -CONFIG_LBD not defined in the kernel), the calculation of the disk sector -will overflow. Add check at ext3_fill_super() and ext3_group_extend() to -prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4 -bytes. - -Verified this patch on a 32 bit platform without CONFIG_LBD defined -(sector_t is 32 bits long), mount refuse to mount a 10TB ext3. - -Signed-off-by: Mingming Cao -Acked-by: Andreas Dilger -Signed-off-by: Andrew Morton ---- - - fs/ext3/resize.c | 10 ++++++++++ - fs/ext3/super.c | 10 ++++++++++ - 2 files changed, 20 insertions(+) - -diff -puN fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem fs/ext3/super.c ---- devel/fs/ext3/super.c~avoid-disk-sector_t-overflow-for-2tb-ext3-filesystem 2006-05-22 14:09:53.000000000 -0700 -+++ devel-akpm/fs/ext3/super.c 2006-05-22 14:11:10.000000000 -0700 -@@ -1565,6 +1565,14 @@ static int ext3_fill_super (struct super - goto failed_mount; - } - -+ if (le32_to_cpu(es->s_blocks_count) > -+ (unsigned long)(~0ULL) >> (sb->s_blocksize_bits - 9)) { -+ printk(KERN_ERR "EXT3-fs: filesystem on %s: " -+ "too large to mount safely - %u blocks\n", -+ bdevname(sb->s_dev), le32_to_cpu(es->s_blocks_count)); -+ goto failed_mount; -+ } -+ - sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) - - le32_to_cpu(es->s_first_data_block) + - EXT3_BLOCKS_PER_GROUP(sb) - 1) / -_ diff --git a/lustre/kernel_patches/patches/ext3-truncate-buffer-head.patch b/lustre/kernel_patches/patches/ext3-truncate-buffer-head.patch deleted file mode 100644 index 3741213..0000000 --- a/lustre/kernel_patches/patches/ext3-truncate-buffer-head.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- lum/fs/ext3/inode.c~ 2004-01-30 16:47:12.000000000 -0800 -+++ lum/fs/ext3/inode.c 2004-01-30 16:46:14.000000000 -0800 -@@ -1485,6 +1485,7 @@ - if (ext3_should_order_data(inode)) - err = ext3_journal_dirty_data(handle, bh, 0); - __mark_buffer_dirty(bh); -+ buffer_insert_inode_data_queue(bh, inode); - } - - unlock: diff --git a/lustre/kernel_patches/patches/ext3-truncate_blocks.patch b/lustre/kernel_patches/patches/ext3-truncate_blocks.patch deleted file mode 100644 index ce3928d..0000000 --- a/lustre/kernel_patches/patches/ext3-truncate_blocks.patch +++ /dev/null @@ -1,92 +0,0 @@ ---- ./fs/ext3/inode.c.orig Wed Mar 12 02:44:06 2003 -+++ ./fs/ext3/inode.c Wed Mar 12 11:55:20 2003 -@@ -99,7 +99,35 @@ int ext3_forget(handle_t *handle, int is - return err; - } - --/* -+/* -+ * Work out how many blocks we need to progress with the next chunk of a -+ * truncate transaction. -+ */ -+ -+static unsigned long blocks_for_truncate(struct inode *inode) -+{ -+ unsigned long needed; -+ -+ needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9); -+ -+ /* Give ourselves just enough room to cope with inodes in which -+ * i_blocks is corrupt: we've seen disk corruptions in the past -+ * which resulted in random data in an inode which looked enough -+ * like a regular file for ext3 to try to delete it. Things -+ * will go a bit crazy if that happens, but at least we should -+ * try not to panic the whole kernel. */ -+ if (needed < 2) -+ needed = 2; -+ -+ /* But we need to bound the transaction so we don't overflow the -+ * journal. */ -+ if (needed > EXT3_MAX_TRANS_DATA) -+ needed = EXT3_MAX_TRANS_DATA; -+ -+ return EXT3_DATA_TRANS_BLOCKS + needed; -+} -+ -+/* - * Truncate transactions can be complex and absolutely huge. So we need to - * be able to restart the transaction at a conventient checkpoint to make - * sure we don't overflow the journal. -@@ -110,19 +138,14 @@ int ext3_forget(handle_t *handle, int is - * transaction in the top-level truncate loop. --sct - */ - --static handle_t *start_transaction(struct inode *inode) -+static handle_t *start_transaction(struct inode *inode) - { -- long needed; - handle_t *result; -- -- needed = inode->i_blocks; -- if (needed > EXT3_MAX_TRANS_DATA) -- needed = EXT3_MAX_TRANS_DATA; -- -- result = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS + needed); -+ -+ result = ext3_journal_start(inode, blocks_for_truncate(inode)); - if (!IS_ERR(result)) - return result; -- -+ - ext3_std_error(inode->i_sb, PTR_ERR(result)); - return result; - } -@@ -135,14 +158,9 @@ static handle_t *start_transaction(struc - */ - static int try_to_extend_transaction(handle_t *handle, struct inode *inode) - { -- long needed; -- - if (handle->h_buffer_credits > EXT3_RESERVE_TRANS_BLOCKS) - return 0; -- needed = inode->i_blocks; -- if (needed > EXT3_MAX_TRANS_DATA) -- needed = EXT3_MAX_TRANS_DATA; -- if (!ext3_journal_extend(handle, EXT3_RESERVE_TRANS_BLOCKS + needed)) -+ if (!ext3_journal_extend(handle, blocks_for_truncate(inode))) - return 0; - return 1; - } -@@ -154,11 +172,8 @@ static int try_to_extend_transaction(han - */ - static int ext3_journal_test_restart(handle_t *handle, struct inode *inode) - { -- long needed = inode->i_blocks; -- if (needed > EXT3_MAX_TRANS_DATA) -- needed = EXT3_MAX_TRANS_DATA; - jbd_debug(2, "restarting handle %p\n", handle); -- return ext3_journal_restart(handle, EXT3_DATA_TRANS_BLOCKS + needed); -+ return ext3_journal_restart(handle, blocks_for_truncate(inode)); - } - - /* diff --git a/lustre/kernel_patches/patches/ext3-trusted_ea-2.4.20.patch b/lustre/kernel_patches/patches/ext3-trusted_ea-2.4.20.patch deleted file mode 100644 index 0a3bdb8..0000000 --- a/lustre/kernel_patches/patches/ext3-trusted_ea-2.4.20.patch +++ /dev/null @@ -1,180 +0,0 @@ - fs/ext3/xattr.c | 12 +++++- - fs/ext3/xattr_trusted.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/ext3_xattr.h | 6 +++ - 3 files changed, 102 insertions(+), 2 deletions(-) - -Index: linux-2.4.20/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.20.orig/fs/ext3/xattr.c 2003-10-22 02:29:40.000000000 +0400 -+++ linux-2.4.20/fs/ext3/xattr.c 2003-10-24 01:03:22.000000000 +0400 -@@ -1771,18 +1771,25 @@ - int __init - init_ext3_xattr(void) - { -+ int error; -+ - ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, - sizeof(struct mb_cache_entry) + - sizeof(struct mb_cache_entry_index), 1, 61); - if (!ext3_xattr_cache) - return -ENOMEM; - -- return 0; -+ error = init_ext3_xattr_trusted(); -+ if (error) -+ mb_cache_destroy(ext3_xattr_cache); -+ -+ return error; - } - - void - exit_ext3_xattr(void) - { -+ exit_ext3_xattr_trusted(); - if (ext3_xattr_cache) - mb_cache_destroy(ext3_xattr_cache); - ext3_xattr_cache = NULL; -@@ -1793,12 +1800,13 @@ - int __init - init_ext3_xattr(void) - { -- return 0; -+ return init_ext3_xattr_trusted(); - } - - void - exit_ext3_xattr(void) - { -+ exit_ext3_xattr_trusted(); - } - - #endif /* CONFIG_EXT3_FS_XATTR_SHARING */ -Index: linux-2.4.20/fs/ext3/xattr_trusted.c -=================================================================== ---- linux-2.4.20.orig/fs/ext3/xattr_trusted.c 2003-10-24 01:03:22.000000000 +0400 -+++ linux-2.4.20/fs/ext3/xattr_trusted.c 2003-10-24 01:03:22.000000000 +0400 -@@ -0,0 +1,86 @@ -+/* -+ * linux/fs/ext3/xattr_trusted.c -+ * Handler for trusted extended attributes. -+ * -+ * Copyright (C) 2003 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define XATTR_TRUSTED_PREFIX "trusted." -+ -+static size_t -+ext3_xattr_trusted_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1; -+ -+ if (!capable(CAP_SYS_ADMIN)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext3_xattr_trusted_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name, -+ buffer, size); -+} -+ -+static int -+ext3_xattr_trusted_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ handle_t *handle; -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_TRUSTED, name, -+ value, size, flags); -+ ext3_journal_stop(handle, inode); -+ -+ return error; -+} -+ -+struct ext3_xattr_handler ext3_xattr_trusted_handler = { -+ .prefix = XATTR_TRUSTED_PREFIX, -+ .list = ext3_xattr_trusted_list, -+ .get = ext3_xattr_trusted_get, -+ .set = ext3_xattr_trusted_set, -+}; -+ -+int __init -+init_ext3_xattr_trusted(void) -+{ -+ return ext3_xattr_register(EXT3_XATTR_INDEX_TRUSTED, -+ &ext3_xattr_trusted_handler); -+} -+ -+void -+exit_ext3_xattr_trusted(void) -+{ -+ ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED, -+ &ext3_xattr_trusted_handler); -+} -Index: linux-2.4.20/include/linux/ext3_xattr.h -=================================================================== ---- linux-2.4.20.orig/include/linux/ext3_xattr.h 2003-10-22 02:29:39.000000000 +0400 -+++ linux-2.4.20/include/linux/ext3_xattr.h 2003-10-24 01:03:22.000000000 +0400 -@@ -21,6 +21,9 @@ - #define EXT3_XATTR_INDEX_USER 1 - #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 - #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+#define EXT3_XATTR_INDEX_TRUSTED 4 -+#define EXT3_XATTR_INDEX_LUSTRE 5 -+#define EXT3_XATTR_INDEX_SECURITY 6 - - struct ext3_xattr_header { - __u32 h_magic; /* magic number for identification */ -@@ -84,6 +87,9 @@ - extern int init_ext3_xattr(void) __init; - extern void exit_ext3_xattr(void); - -+extern int init_ext3_xattr_trusted(void) __init; -+extern void exit_ext3_xattr_trusted(void); -+ - # else /* CONFIG_EXT3_FS_XATTR */ - # define ext3_setxattr NULL - # define ext3_getxattr NULL -Index: linux-2.4.20/fs/ext3/Makefile -=================================================================== ---- linux-2.4.20.orig/fs/ext3/Makefile 2003-10-22 02:29:40.000000000 +0400 -+++ linux-2.4.20/fs/ext3/Makefile 2003-10-24 01:03:47.000000000 +0400 -@@ -12,7 +12,8 @@ - export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ -- ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o \ -+ xattr_trusted.o - obj-m := $(O_TARGET) - - export-objs += xattr.o diff --git a/lustre/kernel_patches/patches/ext3-use-after-free.patch b/lustre/kernel_patches/patches/ext3-use-after-free.patch deleted file mode 100644 index dd999bf..0000000 --- a/lustre/kernel_patches/patches/ext3-use-after-free.patch +++ /dev/null @@ -1,53 +0,0 @@ - ./fs/ext3/namei.c | 11 +++++------ - 1 files changed, 5 insertions(+), 6 deletions(-) - ---- linux-2.4.20/./fs/ext3/namei.c~ext3-use-after-free 2003-04-08 23:35:51.000000000 -0600 -+++ linux-2.4.20-braam/./fs/ext3/namei.c 2003-04-08 23:35:51.000000000 -0600 -@@ -1521,8 +1521,11 @@ static int ext3_add_nondir(handle_t *han - { - int err = ext3_add_entry(handle, dentry, inode); - if (!err) { -- d_instantiate(dentry, inode); -- return 0; -+ err = ext3_mark_inode_dirty(handle, inode); -+ if (err == 0) { -+ d_instantiate(dentry, inode); -+ return 0; -+ } - } - ext3_dec_count(handle, inode); - iput(inode); -@@ -1559,7 +1562,6 @@ static int ext3_create (struct inode * d - inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; - err = ext3_add_nondir(handle, dentry, inode); -- ext3_mark_inode_dirty(handle, inode); - } - ext3_journal_stop(handle, dir); - return err; -@@ -1586,7 +1588,6 @@ static int ext3_mknod (struct inode * di - if (!IS_ERR(inode)) { - init_special_inode(inode, mode, rdev); - err = ext3_add_nondir(handle, dentry, inode); -- ext3_mark_inode_dirty(handle, inode); - } - ext3_journal_stop(handle, dir); - return err; -@@ -2035,7 +2036,6 @@ static int ext3_symlink (struct inode * - } - EXT3_I(inode)->i_disksize = inode->i_size; - err = ext3_add_nondir(handle, dentry, inode); -- ext3_mark_inode_dirty(handle, inode); - out_stop: - ext3_journal_stop(handle, dir); - return err; -@@ -2069,7 +2069,6 @@ static int ext3_link (struct dentry * ol - atomic_inc(&inode->i_count); - - err = ext3_add_nondir(handle, dentry, inode); -- ext3_mark_inode_dirty(handle, inode); - ext3_journal_stop(handle, dir); - return err; - } - -_ diff --git a/lustre/kernel_patches/patches/ext3-xattr-ptr-arith-fix.patch b/lustre/kernel_patches/patches/ext3-xattr-ptr-arith-fix.patch deleted file mode 100644 index 818596c..0000000 --- a/lustre/kernel_patches/patches/ext3-xattr-ptr-arith-fix.patch +++ /dev/null @@ -1,18 +0,0 @@ -Index: linux-2.4.20/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.20.orig/fs/ext3/xattr.c 2003-11-13 10:59:33.000000000 +0800 -+++ linux-2.4.20/fs/ext3/xattr.c 2003-11-25 21:16:51.000000000 +0800 -@@ -1293,9 +1293,10 @@ - goto cleanup; - memcpy(header, HDR(bh), bh->b_size); - header->h_refcount = cpu_to_le32(1); -- offset = (char *)header - bh->b_data; -- here = ENTRY((char *)here + offset); -- last = ENTRY((char *)last + offset); -+ offset = (char *)here - bh->b_data; -+ here = ENTRY((char *)header + offset); -+ offset = (char *)last - bh->b_data; -+ last = ENTRY((char *)header + offset); - } - } else { - /* Allocate a buffer where we construct the new block. */ diff --git a/lustre/kernel_patches/patches/extN-2.4.18-ino_sb_fixup.patch b/lustre/kernel_patches/patches/extN-2.4.18-ino_sb_fixup.patch deleted file mode 100644 index df46643..0000000 --- a/lustre/kernel_patches/patches/extN-2.4.18-ino_sb_fixup.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- ./include/linux/ext3_fs.h.orig Tue May 7 17:06:03 2002 -+++ ./include/linux/ext3_fs.h Tue May 7 17:07:11 2002 -@@ -17,6 +17,8 @@ - #define _LINUX_EXT3_FS_H - - #include -+#include -+#include - - /* - * The second extended filesystem constants/structures -@@ -86,8 +88,8 @@ - #define EXT3_MIN_BLOCK_LOG_SIZE 10 - - #ifdef __KERNEL__ --#define EXT3_SB(sb) (&((sb)->u.ext3_sb)) --#define EXT3_I(inode) (&((inode)->u.ext3_i)) -+#define EXT3_SB(sb) ((struct ext3_sb_info *)&((sb)->u.generic_sbp)) -+#define EXT3_I(inode) ((struct ext3_inode_info *)&((inode)->u.generic_ip)) - - #define EXT3_BLOCK_SIZE(s) ((s)->s_blocksize) - #define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -447,7 +447,9 @@ - #define NEXT_ORPHAN(inode) EXT3_I(inode)->i_dtime - static inline struct inode *orphan_list_entry(struct list_head *l) - { -- return list_entry(l, struct inode, u.ext3_i.i_orphan); -+ return ((struct inode *)((char *)l - -+ (unsigned long)(offsetof(struct inode, u.generic_ip) + -+ offsetof(struct ext3_inode_info, i_orphan)))); - } - - /* diff --git a/lustre/kernel_patches/patches/extN-misc-fixup.patch b/lustre/kernel_patches/patches/extN-misc-fixup.patch deleted file mode 100644 index 65d9347..0000000 --- a/lustre/kernel_patches/patches/extN-misc-fixup.patch +++ /dev/null @@ -1,20 +0,0 @@ - fs/ext3/super.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - ---- linux-2.4.18-p4smp/fs/ext3/super.c~extN-misc-fixup 2003-07-21 23:07:50.000000000 -0600 -+++ linux-2.4.18-p4smp-braam/fs/ext3/super.c 2003-07-21 23:08:06.000000000 -0600 -@@ -1578,10 +1578,10 @@ static journal_t *ext3_get_dev_journal(s - printk(KERN_ERR "EXT3-fs: I/O error on journal device\n"); - goto out_journal; - } -- if (ntohl(journal->j_superblock->s_nr_users) != 1) { -+ if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) { - printk(KERN_ERR "EXT3-fs: External journal has more than one " - "user (unsupported) - %d\n", -- ntohl(journal->j_superblock->s_nr_users)); -+ be32_to_cpu(journal->j_superblock->s_nr_users)); - goto out_journal; - } - EXT3_SB(sb)->journal_bdev = bdev; - -_ diff --git a/lustre/kernel_patches/patches/extN-wantedi-2.4.21-chaos.patch b/lustre/kernel_patches/patches/extN-wantedi-2.4.21-chaos.patch deleted file mode 100644 index 3dba64d..0000000 --- a/lustre/kernel_patches/patches/extN-wantedi-2.4.21-chaos.patch +++ /dev/null @@ -1,213 +0,0 @@ -diff -urp linux-2.4.21.orig/fs/ext3/ialloc.c linux-2.4.21/fs/ext3/ialloc.c ---- linux-2.4.21.orig/fs/ext3/ialloc.c 2007-02-16 10:23:09.000000000 +0200 -+++ linux-2.4.21/fs/ext3/ialloc.c 2007-02-16 10:30:28.000000000 +0200 -@@ -330,7 +330,8 @@ int ext3_itable_block_used(struct super_ - * For other inodes, search forward from the parent directory's block - * group to find a free inode. - */ --struct inode * ext3_new_inode (handle_t *handle, struct inode * dir, int mode) -+struct inode * ext3_new_inode(handle_t *handle, const struct inode * dir, -+ int mode, unsigned long goal) - { - struct super_block * sb; - struct buffer_head * bh; -@@ -359,7 +360,41 @@ struct inode * ext3_new_inode (handle_t - init_rwsem(&ei->truncate_sem); - - lock_super (sb); -- es = sbi->s_es; -+ es = EXT3_SB(sb)->s_es; -+ -+ if (goal) { -+ i = (goal - 1) / EXT3_INODES_PER_GROUP(sb); -+ j = (goal - 1) % EXT3_INODES_PER_GROUP(sb); -+ gdp = ext3_get_group_desc(sb, i, &bh2); -+ -+ bitmap_nr = load_inode_bitmap (sb, i); -+ if (bitmap_nr < 0) { -+ err = bitmap_nr; -+ goto fail; -+ } -+ -+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; -+ -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) goto fail; -+ -+ if (ext3_set_bit(j, bh->b_data)) { -+ printk(KERN_ERR "goal inode %lu unavailable\n", goal); -+ /* Oh well, we tried. */ -+ goto repeat; -+ } -+ -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) goto fail; -+ -+ /* We've shortcircuited the allocation system successfully, -+ * now finish filling in the inode. -+ */ -+ goto have_bit_and_group; -+ } -+ - repeat: - gdp = NULL; - i = 0; -@@ -474,6 +509,7 @@ repeat: - } - goto repeat; - } -+ have_bit_and_group: - j += i * EXT3_INODES_PER_GROUP(sb) + 1; - if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) { - ext3_error (sb, "ext3_new_inode", -diff -urp linux-2.4.21.orig/fs/ext3/inode.c linux-2.4.21/fs/ext3/inode.c ---- linux-2.4.21.orig/fs/ext3/inode.c 2007-02-16 10:23:09.000000000 +0200 -+++ linux-2.4.21/fs/ext3/inode.c 2007-02-16 10:30:28.000000000 +0200 -@@ -2235,7 +2235,7 @@ void ext3_truncate_thread(struct inode * - if (IS_ERR(handle)) - goto out_truncate; - -- new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode, 0); - if (IS_ERR(new_inode)) { - ext3_debug("truncate inode %lu directly (no new inodes)\n", - old_inode->i_ino); -diff -urp linux-2.4.21.orig/fs/ext3/ioctl.c linux-2.4.21/fs/ext3/ioctl.c ---- linux-2.4.21.orig/fs/ext3/ioctl.c 2007-02-16 10:23:09.000000000 +0200 -+++ linux-2.4.21/fs/ext3/ioctl.c 2007-02-16 10:30:28.000000000 +0200 -@@ -24,6 +24,31 @@ int ext3_ioctl (struct inode * inode, st - ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg); - - switch (cmd) { -+ case EXT3_IOC_CREATE_INUM: { -+ char name[32]; -+ struct dentry *dchild, *dparent; -+ int rc = 0; -+ -+ dparent = list_entry(inode->i_dentry.next, struct dentry, -+ d_alias); -+ snprintf(name, sizeof name, "%lu", arg); -+ dchild = lookup_one_len(name, dparent, strlen(name)); -+ if (dchild->d_inode) { -+ printk(KERN_ERR "%*s/%lu already exists (ino %lu)\n", -+ dparent->d_name.len, dparent->d_name.name, arg, -+ dchild->d_inode->i_ino); -+ rc = -EEXIST; -+ } else { -+ dchild->d_fsdata = (void *)arg; -+ rc = vfs_create(inode, dchild, 0644); -+ if (rc) -+ printk(KERN_ERR "vfs_create: %d\n", rc); -+ else if (dchild->d_inode->i_ino != arg) -+ rc = -EEXIST; -+ } -+ dput(dchild); -+ return rc; -+ } - case EXT3_IOC_GETFLAGS: - flags = ei->i_flags & EXT3_FL_USER_VISIBLE; - return put_user(flags, (int *) arg); -diff -urp linux-2.4.21.orig/fs/ext3/namei.c linux-2.4.21/fs/ext3/namei.c ---- linux-2.4.21.orig/fs/ext3/namei.c 2007-02-16 10:23:09.000000000 +0200 -+++ linux-2.4.21/fs/ext3/namei.c 2007-02-16 10:32:17.000000000 +0200 -@@ -143,6 +143,14 @@ struct dx_map_entry - u32 offs; - }; - -+#define LVFS_DENTRY_PARAM_MAGIC 20070216UL -+struct lvfs_dentry_params -+{ -+ unsigned long p_inum; -+ void *p_ptr; -+ u32 magic; -+}; -+ - #ifdef CONFIG_EXT3_INDEX - static inline unsigned dx_get_block (struct dx_entry *entry); - static void dx_set_block (struct dx_entry *entry, unsigned value); -@@ -1542,6 +1550,20 @@ static int ext3_add_nondir(handle_t *han - return err; - } - -+static struct inode * ext3_new_inode_wantedi(handle_t *handle, struct inode *dir, -+ int mode, struct dentry *dentry) -+{ -+ unsigned long inum = 0; -+ -+ if (dentry->d_fsdata != NULL) { -+ struct lvfs_dentry_params *param = -+ dentry->d_fsdata; -+ if (param->magic == LVFS_DENTRY_PARAM_MAGIC) -+ inum = param->p_inum; -+ } -+ return ext3_new_inode(handle, dir, mode, inum); -+} -+ - /* - * By the time this is called, we already have created - * the directory cache entry for the new file, but it -@@ -1565,7 +1587,7 @@ static int ext3_create (struct inode * d - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, mode); -+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry); - err = PTR_ERR(inode); - if (!IS_ERR(inode)) { - inode->i_op = &ext3_file_inode_operations; -@@ -1593,7 +1615,7 @@ static int ext3_mknod (struct inode * di - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, mode); -+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry); - err = PTR_ERR(inode); - if (!IS_ERR(inode)) { - init_special_inode(inode, inode->i_mode, rdev); -@@ -1626,7 +1648,7 @@ static int ext3_mkdir(struct inode * dir - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFDIR | mode); -+ inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -@@ -2056,7 +2078,7 @@ static int ext3_symlink (struct inode * - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO); -+ inode = ext3_new_inode_wantedi (handle, dir, S_IFLNK|S_IRWXUGO, dentry); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -diff -urp linux-2.4.21.orig/include/linux/ext3_fs.h linux-2.4.21/include/linux/ext3_fs.h ---- linux-2.4.21.orig/include/linux/ext3_fs.h 2007-02-16 10:23:09.000000000 +0200 -+++ linux-2.4.21/include/linux/ext3_fs.h 2007-02-16 10:30:28.000000000 +0200 -@@ -204,6 +204,7 @@ struct ext3_group_desc - #define EXT3_IOC_SETFLAGS _IOW('f', 2, long) - #define EXT3_IOC_GETVERSION _IOR('f', 3, long) - #define EXT3_IOC_SETVERSION _IOW('f', 4, long) -+/* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */ - #define EXT3_IOC_GETVERSION_OLD _IOR('v', 1, long) - #define EXT3_IOC_SETVERSION_OLD _IOW('v', 2, long) - #ifdef CONFIG_JBD_DEBUG -@@ -671,7 +672,8 @@ extern int ext3fs_dirhash(const char *na - dx_hash_info *hinfo); - - /* ialloc.c */ --extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); -+extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int, -+ unsigned long); - extern void ext3_free_inode (handle_t *, struct inode *); - extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); - extern unsigned long ext3_count_free_inodes (struct super_block *); -@@ -763,4 +765,5 @@ extern struct inode_operations ext3_fast - - #endif /* __KERNEL__ */ - -+#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long) - #endif /* _LINUX_EXT3_FS_H */ diff --git a/lustre/kernel_patches/patches/extN-wantedi-2.4.21-suse2.patch b/lustre/kernel_patches/patches/extN-wantedi-2.4.21-suse2.patch deleted file mode 100644 index 400f7a8..0000000 --- a/lustre/kernel_patches/patches/extN-wantedi-2.4.21-suse2.patch +++ /dev/null @@ -1,226 +0,0 @@ - fs/ext3/ialloc.c | 40 ++++++++++++++++++++++++++++++++++++++-- - fs/ext3/inode.c | 2 +- - fs/ext3/ioctl.c | 25 +++++++++++++++++++++++++ - fs/ext3/namei.c | 21 +++++++++++++++++---- - include/linux/dcache.h | 5 +++++ - include/linux/ext3_fs.h | 5 ++++- - 6 files changed, 90 insertions(+), 8 deletions(-) - -Index: linux-2.4.21-chaos/fs/ext3/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/namei.c 2003-12-12 16:18:41.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/namei.c 2003-12-12 16:18:53.000000000 +0300 -@@ -1534,6 +1534,19 @@ - return err; - } - -+static struct inode * ext3_new_inode_wantedi(handle_t *handle, struct inode *dir, -+ int mode, struct dentry *dentry) -+{ -+ unsigned long inum = 0; -+ -+ if (dentry->d_fsdata != NULL) { -+ struct dentry_params *param = -+ (struct dentry_params *) dentry->d_fsdata; -+ inum = param->p_inum; -+ } -+ return ext3_new_inode(handle, dir, mode, inum); -+} -+ - /* - * By the time this is called, we already have created - * the directory cache entry for the new file, but it -@@ -1557,7 +1570,7 @@ - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, mode); -+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry); - err = PTR_ERR(inode); - if (!IS_ERR(inode)) { - inode->i_op = &ext3_file_inode_operations; -@@ -1585,7 +1598,7 @@ - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, mode); -+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry); - err = PTR_ERR(inode); - if (!IS_ERR(inode)) { - init_special_inode(inode, inode->i_mode, rdev); -@@ -1618,7 +1631,7 @@ - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFDIR | mode); -+ inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -@@ -2012,7 +2025,7 @@ - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO); -+ inode = ext3_new_inode_wantedi (handle, dir, S_IFLNK|S_IRWXUGO, dentry); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -Index: linux-2.4.21-chaos/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ialloc.c 2003-12-12 16:18:52.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ialloc.c 2003-12-12 16:18:53.000000000 +0300 -@@ -330,7 +330,8 @@ - * For other inodes, search forward from the parent directory's block - * group to find a free inode. - */ --struct inode * ext3_new_inode (handle_t *handle, struct inode * dir, int mode) -+struct inode * ext3_new_inode(handle_t *handle, const struct inode * dir, -+ int mode, unsigned long goal) - { - struct super_block * sb; - struct buffer_head * bh; -@@ -359,7 +360,41 @@ - init_rwsem(&ei->truncate_sem); - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; -+ -+ if (goal) { -+ i = (goal - 1) / EXT3_INODES_PER_GROUP(sb); -+ j = (goal - 1) % EXT3_INODES_PER_GROUP(sb); -+ gdp = ext3_get_group_desc(sb, i, &bh2); -+ -+ bitmap_nr = load_inode_bitmap (sb, i); -+ if (bitmap_nr < 0) { -+ err = bitmap_nr; -+ goto fail; -+ } -+ -+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; -+ -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) goto fail; -+ -+ if (ext3_set_bit(j, bh->b_data)) { -+ printk(KERN_ERR "goal inode %lu unavailable\n", goal); -+ /* Oh well, we tried. */ -+ goto repeat; -+ } -+ -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) goto fail; -+ -+ /* We've shortcircuited the allocation system successfully, -+ * now finish filling in the inode. -+ */ -+ goto have_bit_and_group; -+ } -+ - repeat: - gdp = NULL; - i = 0; -@@ -474,6 +509,7 @@ - } - goto repeat; - } -+ have_bit_and_group: - j += i * EXT3_INODES_PER_GROUP(sb) + 1; - if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) { - ext3_error (sb, "ext3_new_inode", -Index: linux-2.4.21-chaos/fs/ext3/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/inode.c 2003-12-12 16:18:52.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/inode.c 2003-12-12 16:18:53.000000000 +0300 -@@ -2233,7 +2233,7 @@ - if (IS_ERR(handle)) - goto out_truncate; - -- new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode, 0); - if (IS_ERR(new_inode)) { - ext3_debug("truncate inode %lu directly (no new inodes)\n", - old_inode->i_ino); -Index: linux-2.4.21-chaos/fs/ext3/ioctl.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ioctl.c 2003-12-12 16:18:40.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ioctl.c 2003-12-12 16:18:53.000000000 +0300 -@@ -24,6 +24,31 @@ - ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg); - - switch (cmd) { -+ case EXT3_IOC_CREATE_INUM: { -+ char name[32]; -+ struct dentry *dchild, *dparent; -+ int rc = 0; -+ -+ dparent = list_entry(inode->i_dentry.next, struct dentry, -+ d_alias); -+ snprintf(name, sizeof name, "%lu", arg); -+ dchild = lookup_one_len(name, dparent, strlen(name)); -+ if (dchild->d_inode) { -+ printk(KERN_ERR "%*s/%lu already exists (ino %lu)\n", -+ dparent->d_name.len, dparent->d_name.name, arg, -+ dchild->d_inode->i_ino); -+ rc = -EEXIST; -+ } else { -+ dchild->d_fsdata = (void *)arg; -+ rc = vfs_create(inode, dchild, 0644); -+ if (rc) -+ printk(KERN_ERR "vfs_create: %d\n", rc); -+ else if (dchild->d_inode->i_ino != arg) -+ rc = -EEXIST; -+ } -+ dput(dchild); -+ return rc; -+ } - case EXT3_IOC_GETFLAGS: - flags = ei->i_flags & EXT3_FL_USER_VISIBLE; - return put_user(flags, (int *) arg); -Index: linux-2.4.21-chaos/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_fs.h 2003-12-12 16:18:52.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_fs.h 2003-12-12 16:18:53.000000000 +0300 -@@ -204,6 +204,7 @@ - #define EXT3_IOC_SETFLAGS _IOW('f', 2, long) - #define EXT3_IOC_GETVERSION _IOR('f', 3, long) - #define EXT3_IOC_SETVERSION _IOW('f', 4, long) -+/* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */ - #define EXT3_IOC_GETVERSION_OLD _IOR('v', 1, long) - #define EXT3_IOC_SETVERSION_OLD _IOW('v', 2, long) - #ifdef CONFIG_JBD_DEBUG -@@ -671,7 +672,8 @@ - dx_hash_info *hinfo); - - /* ialloc.c */ --extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); -+extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int, -+ unsigned long); - extern void ext3_free_inode (handle_t *, struct inode *); - extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); - extern unsigned long ext3_count_free_inodes (struct super_block *); -@@ -763,4 +765,5 @@ - - #endif /* __KERNEL__ */ - -+#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long) - #endif /* _LINUX_EXT3_FS_H */ -Index: linux-2.4.21-chaos/include/linux/dcache.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/dcache.h 2003-12-12 16:18:06.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/dcache.h 2003-12-12 16:18:53.000000000 +0300 -@@ -63,6 +63,11 @@ - - #define IS_ROOT(x) ((x) == (x)->d_parent) - -+struct dentry_params { -+ unsigned long p_inum; -+ void *p_ptr; -+}; -+ - /* - * "quick string" -- eases parameter passing, but more importantly - * saves "metadata" about the string (ie length and the hash). diff --git a/lustre/kernel_patches/patches/extN-wantedi.patch b/lustre/kernel_patches/patches/extN-wantedi.patch deleted file mode 100644 index e9cb3bc..0000000 --- a/lustre/kernel_patches/patches/extN-wantedi.patch +++ /dev/null @@ -1,213 +0,0 @@ -diff -urp linux-2.4.24.orig/fs/ext3/ialloc.c linux-2.4.24/fs/ext3/ialloc.c ---- linux-2.4.24.orig/fs/ext3/ialloc.c 2007-02-16 10:54:31.000000000 +0200 -+++ linux-2.4.24/fs/ext3/ialloc.c 2007-02-16 10:55:30.000000000 +0200 -@@ -330,7 +330,8 @@ int ext3_itable_block_used(struct super_ - * group to find a free inode. - */ - struct inode * ext3_new_inode (handle_t *handle, -- const struct inode * dir, int mode) -+ const struct inode * dir, int mode, -+ unsigned long goal) - { - struct super_block * sb; - struct buffer_head * bh; -@@ -355,7 +356,41 @@ struct inode * ext3_new_inode (handle_t - init_rwsem(&inode->u.ext3_i.truncate_sem); - - lock_super (sb); -- es = sb->u.ext3_sb.s_es; -+ es = EXT3_SB(sb)->s_es; -+ -+ if (goal) { -+ i = (goal - 1) / EXT3_INODES_PER_GROUP(sb); -+ j = (goal - 1) % EXT3_INODES_PER_GROUP(sb); -+ gdp = ext3_get_group_desc(sb, i, &bh2); -+ -+ bitmap_nr = load_inode_bitmap (sb, i); -+ if (bitmap_nr < 0) { -+ err = bitmap_nr; -+ goto fail; -+ } -+ -+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]; -+ -+ BUFFER_TRACE(bh, "get_write_access"); -+ err = ext3_journal_get_write_access(handle, bh); -+ if (err) goto fail; -+ -+ if (ext3_set_bit(j, bh->b_data)) { -+ printk(KERN_ERR "goal inode %lu unavailable\n", goal); -+ /* Oh well, we tried. */ -+ goto repeat; -+ } -+ -+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); -+ err = ext3_journal_dirty_metadata(handle, bh); -+ if (err) goto fail; -+ -+ /* We've shortcircuited the allocation system successfully, -+ * now finish filling in the inode. -+ */ -+ goto have_bit_and_group; -+ } -+ - repeat: - gdp = NULL; - i = 0; -@@ -470,6 +505,7 @@ repeat: - } - goto repeat; - } -+ have_bit_and_group: - j += i * EXT3_INODES_PER_GROUP(sb) + 1; - if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) { - ext3_error (sb, "ext3_new_inode", -diff -urp linux-2.4.24.orig/fs/ext3/inode.c linux-2.4.24/fs/ext3/inode.c ---- linux-2.4.24.orig/fs/ext3/inode.c 2007-02-16 10:54:31.000000000 +0200 -+++ linux-2.4.24/fs/ext3/inode.c 2007-02-16 10:55:30.000000000 +0200 -@@ -2605,7 +2605,7 @@ void ext3_truncate_thread(struct inode * - if (IS_ERR(handle)) - goto out_truncate; - -- new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode); -+ new_inode = ext3_new_inode(handle, old_inode, old_inode->i_mode, 0); - if (IS_ERR(new_inode)) { - ext3_debug("truncate inode %lu directly (no new inodes)\n", - old_inode->i_ino); -diff -urp linux-2.4.24.orig/fs/ext3/ioctl.c linux-2.4.24/fs/ext3/ioctl.c ---- linux-2.4.24.orig/fs/ext3/ioctl.c 2003-06-13 17:51:37.000000000 +0300 -+++ linux-2.4.24/fs/ext3/ioctl.c 2007-02-16 10:55:30.000000000 +0200 -@@ -23,6 +23,31 @@ int ext3_ioctl (struct inode * inode, st - ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg); - - switch (cmd) { -+ case EXT3_IOC_CREATE_INUM: { -+ char name[32]; -+ struct dentry *dchild, *dparent; -+ int rc = 0; -+ -+ dparent = list_entry(inode->i_dentry.next, struct dentry, -+ d_alias); -+ snprintf(name, sizeof name, "%lu", arg); -+ dchild = lookup_one_len(name, dparent, strlen(name)); -+ if (dchild->d_inode) { -+ printk(KERN_ERR "%*s/%lu already exists (ino %lu)\n", -+ dparent->d_name.len, dparent->d_name.name, arg, -+ dchild->d_inode->i_ino); -+ rc = -EEXIST; -+ } else { -+ dchild->d_fsdata = (void *)arg; -+ rc = vfs_create(inode, dchild, 0644); -+ if (rc) -+ printk(KERN_ERR "vfs_create: %d\n", rc); -+ else if (dchild->d_inode->i_ino != arg) -+ rc = -EEXIST; -+ } -+ dput(dchild); -+ return rc; -+ } - case EXT3_IOC_GETFLAGS: - flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE; - return put_user(flags, (int *) arg); -diff -urp linux-2.4.24.orig/fs/ext3/namei.c linux-2.4.24/fs/ext3/namei.c ---- linux-2.4.24.orig/fs/ext3/namei.c 2007-02-16 10:54:31.000000000 +0200 -+++ linux-2.4.24/fs/ext3/namei.c 2007-02-16 10:56:22.000000000 +0200 -@@ -142,6 +142,14 @@ struct dx_map_entry - u32 offs; - }; - -+#define LVFS_DENTRY_PARAM_MAGIC 20070216UL -+struct lvfs_dentry_params -+{ -+ unsigned long p_inum; -+ void *p_ptr; -+ u32 magic; -+}; -+ - #ifdef CONFIG_EXT3_INDEX - static inline unsigned dx_get_block (struct dx_entry *entry); - static void dx_set_block (struct dx_entry *entry, unsigned value); -@@ -1541,6 +1549,20 @@ static int ext3_add_nondir(handle_t *han - return err; - } - -+static struct inode * ext3_new_inode_wantedi(handle_t *handle, struct inode *dir, -+ int mode, struct dentry *dentry) -+{ -+ unsigned long inum = 0; -+ -+ if (dentry->d_fsdata != NULL) { -+ struct lvfs_dentry_params *param = dentry->d_fsdata; -+ -+ if (param->magic == LVFS_DENTRY_PARAM_MAGIC) -+ inum = param->p_inum; -+ } -+ return ext3_new_inode(handle, dir, mode, inum); -+} -+ - /* - * By the time this is called, we already have created - * the directory cache entry for the new file, but it -@@ -1564,7 +1586,7 @@ static int ext3_create (struct inode * d - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, mode); -+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry); - err = PTR_ERR(inode); - if (!IS_ERR(inode)) { - inode->i_op = &ext3_file_inode_operations; -@@ -1592,7 +1614,7 @@ static int ext3_mknod (struct inode * di - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, mode); -+ inode = ext3_new_inode_wantedi (handle, dir, mode, dentry); - err = PTR_ERR(inode); - if (!IS_ERR(inode)) { - init_special_inode(inode, mode, rdev); -@@ -1622,7 +1644,7 @@ static int ext3_mkdir(struct inode * dir - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFDIR | mode); -+ inode = ext3_new_inode_wantedi (handle, dir, S_IFDIR | mode, dentry); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -@@ -2053,7 +2075,7 @@ static int ext3_symlink (struct inode * - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO); -+ inode = ext3_new_inode_wantedi (handle, dir, S_IFLNK|S_IRWXUGO, dentry); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -diff -urp linux-2.4.24.orig/include/linux/ext3_fs.h linux-2.4.24/include/linux/ext3_fs.h ---- linux-2.4.24.orig/include/linux/ext3_fs.h 2007-02-16 10:54:31.000000000 +0200 -+++ linux-2.4.24/include/linux/ext3_fs.h 2007-02-16 10:55:30.000000000 +0200 -@@ -202,6 +202,7 @@ struct ext3_group_desc - #define EXT3_IOC_SETFLAGS _IOW('f', 2, long) - #define EXT3_IOC_GETVERSION _IOR('f', 3, long) - #define EXT3_IOC_SETVERSION _IOW('f', 4, long) -+/* EXT3_IOC_CREATE_INUM at bottom of file (visible to kernel and user). */ - #define EXT3_IOC_GETVERSION_OLD _IOR('v', 1, long) - #define EXT3_IOC_SETVERSION_OLD _IOW('v', 2, long) - #ifdef CONFIG_JBD_DEBUG -@@ -674,7 +675,8 @@ extern int ext3fs_dirhash(const char *na - dx_hash_info *hinfo); - - /* ialloc.c */ --extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int); -+extern struct inode * ext3_new_inode (handle_t *, const struct inode *, int, -+ unsigned long); - extern void ext3_free_inode (handle_t *, struct inode *); - extern struct inode * ext3_orphan_get (struct super_block *, unsigned long); - extern unsigned long ext3_count_free_inodes (struct super_block *); -@@ -766,4 +768,5 @@ extern struct inode_operations ext3_fast - - #endif /* __KERNEL__ */ - -+#define EXT3_IOC_CREATE_INUM _IOW('f', 5, long) - #endif /* _LINUX_EXT3_FS_H */ diff --git a/lustre/kernel_patches/patches/fsprivate-2.4-suse.patch b/lustre/kernel_patches/patches/fsprivate-2.4-suse.patch deleted file mode 100644 index fc3a72a..0000000 --- a/lustre/kernel_patches/patches/fsprivate-2.4-suse.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- uml-2.4.24/include/linux/fs.h.orig 2005-05-18 21:27:58.120742112 +0300 -+++ uml-2.4.24/include/linux/fs.h 2005-05-18 22:48:12.081908776 +0300 -@@ -592,6 +592,7 @@ - /* needed for tty driver, and maybe others */ - void *private_data; - struct lookup_intent *f_it; -+ void *fs_private; - struct list_head f_ep_links; - spinlock_t f_ep_lock; - }; diff --git a/lustre/kernel_patches/patches/fsprivate-2.4.patch b/lustre/kernel_patches/patches/fsprivate-2.4.patch deleted file mode 100644 index 4e83dbe..0000000 --- a/lustre/kernel_patches/patches/fsprivate-2.4.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- uml-2.4.24/include/linux/fs.h.orig 2005-05-18 21:27:58.120742112 +0300 -+++ uml-2.4.24/include/linux/fs.h 2005-05-18 22:48:12.081908776 +0300 -@@ -592,6 +592,7 @@ - /* needed for tty driver, and maybe others */ - void *private_data; - struct lookup_intent *f_it; -+ void *fs_private; - - /* preallocated helper kiobuf to speedup O_DIRECT */ - struct kiobuf *f_iobuf; diff --git a/lustre/kernel_patches/patches/gfp_debug-2.4.21-rhel.patch b/lustre/kernel_patches/patches/gfp_debug-2.4.21-rhel.patch deleted file mode 100644 index 6686b15..0000000 --- a/lustre/kernel_patches/patches/gfp_debug-2.4.21-rhel.patch +++ /dev/null @@ -1,77 +0,0 @@ -Index: linux-2.4.21-rhel/kernel/sysctl.c -=================================================================== ---- linux-2.4.21-rhel.orig/kernel/sysctl.c 2005-01-20 18:52:39.000000000 -0700 -+++ linux-2.4.21-rhel/kernel/sysctl.c 2005-05-31 18:47:22.000000000 -0600 -@@ -355,6 +355,8 @@ - extern int skip_mapped_pages; - - static ctl_table vm_table[] = { -+ {VM_GFP_DEBUG, "vm_gfp_debug", -+ &vm_gfp_debug, sizeof(int), 0644, NULL, &proc_dointvec}, - {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL, - &proc_dointvec_minmax, &sysctl_intvec, NULL, - &bdflush_min, &bdflush_max}, -Index: linux-2.4.21-rhel/mm/page_alloc.c -=================================================================== ---- linux-2.4.21-rhel.orig/mm/page_alloc.c 2005-05-31 18:29:37.000000000 -0600 -+++ linux-2.4.21-rhel/mm/page_alloc.c 2005-05-31 18:49:27.000000000 -0600 -@@ -58,6 +58,8 @@ - static int zone_extrafree_max[MAX_NR_ZONES] __initdata = { 1024 , 1024, 0, }; - #endif - -+int vm_gfp_debug = 0; -+ - /* - * Temporary debugging check. - */ -@@ -773,8 +775,12 @@ - } - - out_failed: -- /* No luck.. */ --// printk(KERN_ERR "__alloc_pages: %lu-order allocation failed.\n", order); -+ if (!(gfp_mask & __GFP_NOWARN)) { -+ printk(KERN_ERR "__alloc_pages: %lu-order allocation failed (gfp=%#x/%i).\n", -+ order, gfp_mask, !!(current->flags & PF_MEMALLOC)); -+ if (unlikely(vm_gfp_debug)) -+ dump_stack(); -+ } - return NULL; - } - -Index: linux-2.4.21-rhel/include/linux/sysctl.h -=================================================================== ---- linux-2.4.21-rhel.orig/include/linux/sysctl.h 2005-03-18 18:25:26.000000000 -0700 -+++ linux-2.4.21-rhel/include/linux/sysctl.h 2005-05-31 18:48:17.000000000 -0600 -@@ -153,6 +153,7 @@ - VM_MIN_READAHEAD=12, /* Min file readahead */ - VM_MAX_READAHEAD=13, /* Max file readahead */ - VM_OVERCOMMIT_RATIO=16, /* percent of RAM to allow overcommit in */ -+ VM_GFP_DEBUG=18, /* debug GFP failures */ - VM_PAGEBUF=22, /* struct: Control pagebuf parameters */ - VM_HUGETLB_POOL=23, /* int: size of the hugetlb pool, in MB */ - VM_DCACHE_PRIORITY=24, /* int: priority of the dcache pool */ -Index: linux-2.4.21-rhel/include/linux/mm.h -=================================================================== ---- linux-2.4.21-rhel.orig/include/linux/mm.h 2005-05-31 18:50:32.000000000 -0600 -+++ linux-2.4.21-rhel/include/linux/mm.h 2005-05-31 18:50:45.000000000 -0600 -@@ -846,6 +846,7 @@ - #define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */ - #define __GFP_FS 0x100 /* Can call down to low-level FS? */ - #define __GFP_WIRED 0x200 /* Highmem bias and wired */ -+#define __GFP_NOWARN 0x400 /* Don't report error on allocation failure */ - - #define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO) - #define GFP_NOIO (__GFP_HIGH | __GFP_WAIT) -Index: linux-2.4.21-rhel/include/linux/swap.h -=================================================================== ---- linux-2.4.21-rhel.orig/include/linux/swap.h 2005-03-18 18:25:26.000000000 -0700 -+++ linux-2.4.21-rhel/include/linux/swap.h 2005-05-31 18:52:44.000000000 -0600 -@@ -178,6 +178,7 @@ - extern int rebalance_inactive(int); - extern void wakeup_kswapd(unsigned int); - extern void rss_free_pages(unsigned int); -+extern int vm_gfp_debug; - - /* - * Limits, in percent, on how large the cache can be and how to do diff --git a/lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-2.4.21-suse2.patch b/lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-2.4.21-suse2.patch deleted file mode 100644 index 94c50d0..0000000 --- a/lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-2.4.21-suse2.patch +++ /dev/null @@ -1,85 +0,0 @@ -Index: linux-2.4.21-suse2/mm/filemap.c -=================================================================== ---- linux-2.4.21-suse2.orig/mm/filemap.c 2005-04-04 05:58:21.000000000 -0600 -+++ linux-2.4.21-suse2/mm/filemap.c 2005-04-04 06:18:57.000000000 -0600 -@@ -1022,6 +1022,14 @@ - */ - struct page *grab_cache_page_nowait(struct address_space *mapping, unsigned long index) - { -+ return grab_cache_page_nowait_gfp(mapping, index, mapping->gfp_mask); -+} -+ -+ -+struct page *grab_cache_page_nowait_gfp(struct address_space *mapping, -+ unsigned long index, -+ unsigned int gfp_mask) -+{ - struct page *page, **hash; - - hash = page_hash(mapping, index); -@@ -1046,7 +1054,7 @@ - } - } - -- page = page_cache_alloc(mapping); -+ page = alloc_pages(gfp_mask, 0); - if ( unlikely(!page) ) - return NULL; /* Failed to allocate a page */ - -Index: linux-2.4.21-suse2/mm/page_alloc.c -=================================================================== ---- linux-2.4.21-suse2.orig/mm/page_alloc.c 2005-04-04 05:58:04.000000000 -0600 -+++ linux-2.4.21-suse2/mm/page_alloc.c 2005-04-04 06:12:11.000000000 -0600 -@@ -435,7 +435,7 @@ - break; - - min = z->watermarks[class_idx].min; -- if (!(gfp_mask & __GFP_WAIT)) -+ if (!(gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_HIGH)) - min >>= 2; - else if (current->rt_priority) - min >>= 1; -@@ -504,6 +504,7 @@ - } - - out: -+ if (!(gfp_mask & __GFP_NOWARN)) - printk(KERN_NOTICE "__alloc_pages: %u-order allocation failed (gfp=0x%x/%i)\n", - order, gfp_mask, !!(current->flags & PF_MEMALLOC)); - if (unlikely(vm_gfp_debug)) -Index: linux-2.4.21-suse2/kernel/ksyms.c -=================================================================== ---- linux-2.4.21-suse2.orig/kernel/ksyms.c 2005-04-04 06:01:39.000000000 -0600 -+++ linux-2.4.21-suse2/kernel/ksyms.c 2005-04-04 06:01:43.000000000 -0600 -@@ -326,6 +326,7 @@ - EXPORT_SYMBOL(__find_lock_page); - EXPORT_SYMBOL(find_or_create_page); - EXPORT_SYMBOL(grab_cache_page_nowait); -+EXPORT_SYMBOL(grab_cache_page_nowait_gfp); - EXPORT_SYMBOL(read_cache_page); - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); -Index: linux-2.4.21-suse2/include/linux/pagemap.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/pagemap.h 2003-11-10 17:44:33.000000000 -0700 -+++ linux-2.4.21-suse2/include/linux/pagemap.h 2005-04-04 06:01:43.000000000 -0600 -@@ -110,6 +110,7 @@ - - - extern struct page * grab_cache_page_nowait (struct address_space *, unsigned long); -+extern struct page * grab_cache_page_nowait_gfp (struct address_space *, unsigned long, unsigned int); - - typedef int filler_t(void *, struct page*); - -Index: linux-2.4.21-suse2/include/linux/mm.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/mm.h 2005-04-04 05:58:14.000000000 -0600 -+++ linux-2.4.21-suse2/include/linux/mm.h 2005-04-04 06:17:10.000000000 -0600 -@@ -661,6 +661,7 @@ - #define __GFP_IO 0x40 /* Can start low memory physical IO? */ - #define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */ - #define __GFP_FS 0x100 /* Can call down to low-level FS? */ -+#define __GFP_NOWARN 0x200 /* Don't warn on allocation failure */ - - #define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO) - #define GFP_NOIO (__GFP_HIGH | __GFP_WAIT) diff --git a/lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-rh-2.4.patch b/lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-rh-2.4.patch deleted file mode 100644 index c7b00f7..0000000 --- a/lustre/kernel_patches/patches/grab_cache_page_nowait_gfp-rh-2.4.patch +++ /dev/null @@ -1,65 +0,0 @@ -Index: linux-2.4.20/mm/filemap.c -=================================================================== ---- linux-2.4.20.orig/mm/filemap.c 2004-12-17 17:51:44.000000000 -0500 -+++ linux-2.4.20/mm/filemap.c 2004-12-17 17:56:54.000000000 -0500 -@@ -1153,6 +1153,14 @@ - */ - struct page *grab_cache_page_nowait(struct address_space *mapping, unsigned long index) - { -+ return grab_cache_page_nowait_gfp(mapping, index, mapping->gfp_mask); -+} -+ -+ -+struct page *grab_cache_page_nowait_gfp(struct address_space *mapping, -+ unsigned long index, -+ unsigned int gfp_mask) -+{ - struct page *page, **hash; - - hash = page_hash(mapping, index); -@@ -1177,7 +1185,7 @@ - } - } - -- page = page_cache_alloc(mapping); -+ page = alloc_pages(gfp_mask, 0); - if ( unlikely(!page) ) - return NULL; /* Failed to allocate a page */ - -Index: linux-2.4.20/mm/page_alloc.c -=================================================================== ---- linux-2.4.20.orig/mm/page_alloc.c 2004-12-17 17:51:30.000000000 -0500 -+++ linux-2.4.20/mm/page_alloc.c 2004-12-17 18:26:45.000000000 -0500 -@@ -547,6 +547,8 @@ - */ - return NULL; - } -+ } else if (!(gfp_mask & __GFP_HIGH)) { -+ return NULL; - } - } - -Index: linux-2.4.20/kernel/ksyms.c -=================================================================== ---- linux-2.4.20.orig/kernel/ksyms.c 2004-12-17 17:51:46.000000000 -0500 -+++ linux-2.4.20/kernel/ksyms.c 2004-12-17 17:52:59.000000000 -0500 -@@ -300,6 +300,7 @@ - EXPORT_SYMBOL(__find_lock_page); - EXPORT_SYMBOL(find_or_create_page); - EXPORT_SYMBOL(grab_cache_page_nowait); -+EXPORT_SYMBOL(grab_cache_page_nowait_gfp); - EXPORT_SYMBOL(read_cache_page); - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); -Index: linux-2.4.20/include/linux/pagemap.h -=================================================================== ---- linux-2.4.20.orig/include/linux/pagemap.h 2004-05-27 14:25:05.000000000 -0400 -+++ linux-2.4.20/include/linux/pagemap.h 2004-12-17 18:11:09.000000000 -0500 -@@ -110,6 +110,7 @@ - - - extern struct page * grab_cache_page_nowait (struct address_space *, unsigned long); -+extern struct page * grab_cache_page_nowait_gfp (struct address_space *, unsigned long, unsigned int); - - typedef int filler_t(void *, struct page*); - diff --git a/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch b/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch deleted file mode 100644 index 9203859..0000000 --- a/lustre/kernel_patches/patches/inode-max-readahead-2.4.24.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- linux-2.4.24-l32/mm/filemap.c.inode_ramax 2004-03-14 13:16:21.000000000 -0800 -+++ linux-2.4.24-l32/mm/filemap.c 2004-03-16 10:57:14.000000000 -0800 -@@ -1226,6 +1226,8 @@ - - static inline int get_max_readahead(struct inode * inode) - { -+ if (inode->i_mapping->a_ops->max_readahead) -+ return inode->i_mapping->a_ops->max_readahead(inode); - if (!inode->i_dev || !max_readahead[MAJOR(inode->i_dev)]) - return vm_max_readahead; - return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)]; ---- linux-2.4.24-l32/include/linux/fs.h.inode_ramax 2004-03-14 13:15:49.000000000 -0800 -+++ linux-2.4.24-l32/include/linux/fs.h 2004-03-15 11:56:56.000000000 -0800 -@@ -410,6 +410,8 @@ - #define KERNEL_HAS_DIRECT_FILEIO /* Unfortunate kludge due to lack of foresight */ - int (*direct_fileIO)(int, struct file *, struct kiobuf *, unsigned long, int); - void (*removepage)(struct page *); /* called when page gets removed from the inode */ -+#define KERNEL_HAS_AS_MAX_READAHEAD -+ int (*max_readahead)(struct inode *); - }; - - struct address_space { diff --git a/lustre/kernel_patches/patches/invalidate_show-2.4.20-hp.patch b/lustre/kernel_patches/patches/invalidate_show-2.4.20-hp.patch deleted file mode 100644 index fad6233..0000000 --- a/lustre/kernel_patches/patches/invalidate_show-2.4.20-hp.patch +++ /dev/null @@ -1,123 +0,0 @@ - - - - fs/inode.c | 21 ++++++++++++++------- - fs/smbfs/inode.c | 2 +- - fs/super.c | 4 ++-- - include/linux/fs.h | 2 +- - 4 files changed, 18 insertions(+), 11 deletions(-) - -Index: linux/fs/inode.c -=================================================================== ---- linux.orig/fs/inode.c Mon Feb 2 21:24:21 2004 -+++ linux/fs/inode.c Mon Feb 2 21:27:53 2004 -@@ -632,7 +632,8 @@ - /* - * Invalidate all inodes for a device. - */ --static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose) -+static int invalidate_list(struct list_head *head, struct super_block * sb, -+ struct list_head * dispose, int show) - { - struct list_head *next; - int busy = 0, count = 0; -@@ -657,6 +658,11 @@ - count++; - continue; - } -+ if (show) -+ printk(KERN_ERR -+ "inode busy: dev %s:%lu (%p) mode %o count %u\n", -+ kdevname(sb->s_dev), inode->i_ino, inode, -+ inode->i_mode, atomic_read(&inode->i_count)); - busy = 1; - } - /* only unused inodes may be cached with i_count zero */ -@@ -675,23 +681,24 @@ - /** - * invalidate_inodes - discard the inodes on a device - * @sb: superblock -+ * @show: whether we should display any busy inodes found - * - * Discard all of the inodes for a given superblock. If the discard - * fails because there are busy inodes then a non zero value is returned. - * If the discard is successful all the inodes have been discarded. - */ - --int invalidate_inodes(struct super_block * sb) -+int invalidate_inodes(struct super_block * sb, int show) - { - int busy; - LIST_HEAD(throw_away); - - spin_lock(&inode_lock); -- busy = invalidate_list(&inode_in_use, sb, &throw_away); -- busy |= invalidate_list(&inode_unused, sb, &throw_away); -- busy |= invalidate_list(&inode_unused_pagecache, sb, &throw_away); -- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away); -- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away); -+ busy = invalidate_list(&inode_in_use, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused_pagecache, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show); - spin_unlock(&inode_lock); - - dispose_list(&throw_away); -@@ -717,7 +724,7 @@ - * hold). - */ - shrink_dcache_sb(sb); -- res = invalidate_inodes(sb); -+ res = invalidate_inodes(sb, 0); - drop_super(sb); - } - invalidate_buffers(dev); -Index: linux/fs/super.c -=================================================================== ---- linux.orig/fs/super.c Mon Feb 2 21:24:21 2004 -+++ linux/fs/super.c Mon Feb 2 21:26:08 2004 -@@ -844,7 +844,7 @@ - lock_super(sb); - lock_kernel(); - sb->s_flags &= ~MS_ACTIVE; -- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ -+ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */ - if (sop) { - if (sop->write_super && sb->s_dirt) - sop->write_super(sb); -@@ -853,7 +853,7 @@ - } - - /* Forget any remaining inodes */ -- if (invalidate_inodes(sb)) { -+ if (invalidate_inodes(sb, 1)) { - printk(KERN_ERR "VFS: Busy inodes after unmount. " - "Self-destruct in 5 seconds. Have a nice day...\n"); - } -Index: linux/include/linux/fs.h -=================================================================== ---- linux.orig/include/linux/fs.h Mon Feb 2 21:24:23 2004 -+++ linux/include/linux/fs.h Mon Feb 2 21:26:08 2004 -@@ -1257,7 +1257,7 @@ - extern void set_buffer_flushtime(struct buffer_head *); - extern void balance_dirty(void); - extern int check_disk_change(kdev_t); --extern int invalidate_inodes(struct super_block *); -+extern int invalidate_inodes(struct super_block *, int); - extern int invalidate_device(kdev_t, int); - extern void invalidate_inode_pages(struct inode *); - extern void invalidate_inode_pages2(struct address_space *); -Index: linux/fs/smbfs/inode.c -=================================================================== ---- linux.orig/fs/smbfs/inode.c Thu Nov 28 18:53:15 2002 -+++ linux/fs/smbfs/inode.c Mon Feb 2 21:26:08 2004 -@@ -167,7 +167,7 @@ - { - VERBOSE("\n"); - shrink_dcache_sb(SB_of(server)); -- invalidate_inodes(SB_of(server)); -+ invalidate_inodes(SB_of(server), 0); - } - - /* diff --git a/lustre/kernel_patches/patches/invalidate_show-2.4.20-rh.patch b/lustre/kernel_patches/patches/invalidate_show-2.4.20-rh.patch deleted file mode 100644 index 2ff807a..0000000 --- a/lustre/kernel_patches/patches/invalidate_show-2.4.20-rh.patch +++ /dev/null @@ -1,114 +0,0 @@ - fs/inode.c | 23 +++++++++++++++-------- - fs/smbfs/inode.c | 2 +- - fs/super.c | 4 ++-- - include/linux/fs.h | 2 +- - 4 files changed, 19 insertions(+), 12 deletions(-) - ---- kernel-2.4.20/fs/inode.c~invalidate_show-2.4.20-rh 2003-05-24 01:56:40.000000000 -0400 -+++ kernel-2.4.20-root/fs/inode.c 2003-06-02 00:35:37.000000000 -0400 -@@ -628,7 +628,8 @@ static void dispose_list(struct list_hea - /* - * Invalidate all inodes for a device. - */ --static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose) -+static int invalidate_list(struct list_head *head, struct super_block * sb, -+ struct list_head * dispose, int show) - { - struct list_head *next; - int busy = 0, count = 0; -@@ -653,6 +654,11 @@ static int invalidate_list(struct list_h - count++; - continue; - } -+ if (show) -+ printk(KERN_ERR -+ "inode busy: dev %s:%lu (%p) mode %o count %u\n", -+ kdevname(sb->s_dev), inode->i_ino, inode, -+ inode->i_mode, atomic_read(&inode->i_count)); - busy = 1; - } - /* only unused inodes may be cached with i_count zero */ -@@ -671,23 +677,24 @@ static int invalidate_list(struct list_h - /** - * invalidate_inodes - discard the inodes on a device - * @sb: superblock -+ * @show: whether we should display any busy inodes found - * - * Discard all of the inodes for a given superblock. If the discard - * fails because there are busy inodes then a non zero value is returned. - * If the discard is successful all the inodes have been discarded. - */ - --int invalidate_inodes(struct super_block * sb) -+int invalidate_inodes(struct super_block * sb, int show) - { - int busy; - LIST_HEAD(throw_away); - - spin_lock(&inode_lock); -- busy = invalidate_list(&inode_in_use, sb, &throw_away); -- busy |= invalidate_list(&inode_unused, sb, &throw_away); -- busy |= invalidate_list(&inode_unused_pagecache, sb, &throw_away); -- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away); -- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away); -+ busy = invalidate_list(&inode_in_use, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused_pagecache, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show); - spin_unlock(&inode_lock); - - dispose_list(&throw_away); -@@ -713,7 +720,7 @@ int invalidate_device(kdev_t dev, int do - * hold). - */ - shrink_dcache_sb(sb); -- res = invalidate_inodes(sb); -+ res = invalidate_inodes(sb, 0); - drop_super(sb); - } - invalidate_buffers(dev); ---- kernel-2.4.20/fs/super.c~invalidate_show-2.4.20-rh 2003-05-24 01:56:24.000000000 -0400 -+++ kernel-2.4.20-root/fs/super.c 2003-06-02 00:35:00.000000000 -0400 -@@ -943,7 +943,7 @@ void kill_super(struct super_block *sb) - lock_super(sb); - lock_kernel(); - sb->s_flags &= ~MS_ACTIVE; -- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ -+ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */ - if (sop) { - if (sop->write_super && sb->s_dirt) - sop->write_super(sb); -@@ -952,7 +952,7 @@ void kill_super(struct super_block *sb) - } - - /* Forget any remaining inodes */ -- if (invalidate_inodes(sb)) { -+ if (invalidate_inodes(sb, 1)) { - printk(KERN_ERR "VFS: Busy inodes after unmount. " - "Self-destruct in 5 seconds. Have a nice day...\n"); - } ---- kernel-2.4.20/include/linux/fs.h~invalidate_show-2.4.20-rh 2003-06-02 00:31:47.000000000 -0400 -+++ kernel-2.4.20-root/include/linux/fs.h 2003-06-02 00:35:00.000000000 -0400 -@@ -1284,7 +1284,7 @@ static inline void mark_buffer_dirty_ino - extern void set_buffer_flushtime(struct buffer_head *); - extern void balance_dirty(void); - extern int check_disk_change(kdev_t); --extern int invalidate_inodes(struct super_block *); -+extern int invalidate_inodes(struct super_block *, int); - extern int invalidate_device(kdev_t, int); - extern void invalidate_inode_pages(struct inode *); - extern void invalidate_inode_pages2(struct address_space *); ---- kernel-2.4.20/fs/smbfs/inode.c~invalidate_show-2.4.20-rh 2002-11-28 18:53:15.000000000 -0500 -+++ kernel-2.4.20-root/fs/smbfs/inode.c 2003-06-02 00:35:00.000000000 -0400 -@@ -167,7 +167,7 @@ smb_invalidate_inodes(struct smb_sb_info - { - VERBOSE("\n"); - shrink_dcache_sb(SB_of(server)); -- invalidate_inodes(SB_of(server)); -+ invalidate_inodes(SB_of(server), 0); - } - - /* - -_ diff --git a/lustre/kernel_patches/patches/invalidate_show-2.4.29.patch b/lustre/kernel_patches/patches/invalidate_show-2.4.29.patch deleted file mode 100644 index dedc90b..0000000 --- a/lustre/kernel_patches/patches/invalidate_show-2.4.29.patch +++ /dev/null @@ -1,107 +0,0 @@ -Index: linux-2.4.29/fs/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/inode.c 2005-04-07 18:55:16.732416736 +0300 -+++ linux-2.4.29/fs/inode.c 2005-04-07 19:16:46.772300864 +0300 -@@ -670,7 +670,8 @@ - /* - * Invalidate all inodes for a device. - */ --static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose) -+static int invalidate_list(struct list_head *head, struct super_block * sb, -+ struct list_head * dispose, int show) - { - struct list_head *next; - int busy = 0, count = 0; -@@ -695,6 +696,11 @@ - count++; - continue; - } -+ if (show) -+ printk(KERN_ERR -+ "inode busy: dev %s:%lu (%p) mode %o count %u\n", -+ kdevname(sb->s_dev), inode->i_ino, inode, -+ inode->i_mode, atomic_read(&inode->i_count)); - busy = 1; - } - /* only unused inodes may be cached with i_count zero */ -@@ -719,17 +725,17 @@ - * If the discard is successful all the inodes have been discarded. - */ - --int invalidate_inodes(struct super_block * sb) -+int invalidate_inodes(struct super_block * sb, int show) - { - int busy; - LIST_HEAD(throw_away); - - spin_lock(&inode_lock); -- busy = invalidate_list(&inode_in_use, sb, &throw_away); -- busy |= invalidate_list(&inode_unused, sb, &throw_away); -- busy |= invalidate_list(&inode_unused_pagecache, sb, &throw_away); -- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away); -- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away); -+ busy = invalidate_list(&inode_in_use, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused_pagecache, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show); - spin_unlock(&inode_lock); - - dispose_list(&throw_away); -@@ -755,7 +761,7 @@ - * hold). - */ - shrink_dcache_sb(sb); -- res = invalidate_inodes(sb); -+ res = invalidate_inodes(sb, 0); - drop_super(sb); - } - invalidate_buffers(dev); -Index: linux-2.4.29/fs/super.c -=================================================================== ---- linux-2.4.29.orig/fs/super.c 2005-04-07 18:53:30.978493776 +0300 -+++ linux-2.4.29/fs/super.c 2005-04-07 19:14:26.187672976 +0300 -@@ -844,7 +844,7 @@ - lock_super(sb); - lock_kernel(); - sb->s_flags &= ~MS_ACTIVE; -- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ -+ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */ - if (sop) { - if (sop->write_super && sb->s_dirt) - sop->write_super(sb); -@@ -853,7 +853,7 @@ - } - - /* Forget any remaining inodes */ -- if (invalidate_inodes(sb)) { -+ if (invalidate_inodes(sb, 1)) { - printk(KERN_ERR "VFS: Busy inodes after unmount. " - "Self-destruct in 5 seconds. Have a nice day...\n"); - } -Index: linux-2.4.29/include/linux/fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs.h 2005-04-07 19:14:06.319693368 +0300 -+++ linux-2.4.29/include/linux/fs.h 2005-04-07 19:14:26.190672520 +0300 -@@ -1286,7 +1286,7 @@ - extern int get_buffer_flushtime(void); - extern void balance_dirty(void); - extern int check_disk_change(kdev_t); --extern int invalidate_inodes(struct super_block *); -+extern int invalidate_inodes(struct super_block *, int); - extern int invalidate_device(kdev_t, int); - extern void invalidate_inode_pages(struct inode *); - extern void invalidate_inode_pages2(struct address_space *); -Index: linux-2.4.29/fs/smbfs/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/smbfs/inode.c 2005-04-07 18:52:37.889564520 +0300 -+++ linux-2.4.29/fs/smbfs/inode.c 2005-04-07 19:14:26.192672216 +0300 -@@ -175,7 +175,7 @@ - { - VERBOSE("\n"); - shrink_dcache_sb(SB_of(server)); -- invalidate_inodes(SB_of(server)); -+ invalidate_inodes(SB_of(server), 0); - } - - /* diff --git a/lustre/kernel_patches/patches/invalidate_show.patch b/lustre/kernel_patches/patches/invalidate_show.patch deleted file mode 100644 index 217e98e..0000000 --- a/lustre/kernel_patches/patches/invalidate_show.patch +++ /dev/null @@ -1,112 +0,0 @@ - fs/inode.c | 21 ++++++++++++++------- - fs/smbfs/inode.c | 2 +- - fs/super.c | 4 ++-- - include/linux/fs.h | 2 +- - 4 files changed, 18 insertions(+), 11 deletions(-) - ---- linux-rh-2.4.20-8/fs/inode.c~invalidate_show 2003-04-11 14:04:56.000000000 +0800 -+++ linux-rh-2.4.20-8-root/fs/inode.c 2003-04-16 20:59:35.000000000 +0800 -@@ -604,7 +604,8 @@ static void dispose_list(struct list_hea - /* - * Invalidate all inodes for a device. - */ --static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose) -+static int invalidate_list(struct list_head *head, struct super_block * sb, -+ struct list_head * dispose, int show) - { - struct list_head *next; - int busy = 0, count = 0; -@@ -629,6 +630,11 @@ static int invalidate_list(struct list_h - count++; - continue; - } -+ if (show) -+ printk(KERN_ERR -+ "inode busy: dev %s:%lu (%p) mode %o count %u\n", -+ kdevname(sb->s_dev), inode->i_ino, inode, -+ inode->i_mode, atomic_read(&inode->i_count)); - busy = 1; - } - /* only unused inodes may be cached with i_count zero */ -@@ -647,22 +653,23 @@ static int invalidate_list(struct list_h - /** - * invalidate_inodes - discard the inodes on a device - * @sb: superblock -+ * @show: whether we should display any busy inodes found - * - * Discard all of the inodes for a given superblock. If the discard - * fails because there are busy inodes then a non zero value is returned. - * If the discard is successful all the inodes have been discarded. - */ - --int invalidate_inodes(struct super_block * sb) -+int invalidate_inodes(struct super_block * sb, int show) - { - int busy; - LIST_HEAD(throw_away); - - spin_lock(&inode_lock); -- busy = invalidate_list(&inode_in_use, sb, &throw_away); -- busy |= invalidate_list(&inode_unused, sb, &throw_away); -- busy |= invalidate_list(&sb->s_dirty, sb, &throw_away); -- busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away); -+ busy = invalidate_list(&inode_in_use, sb, &throw_away, show); -+ busy |= invalidate_list(&inode_unused, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_dirty, sb, &throw_away, show); -+ busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away, show); - spin_unlock(&inode_lock); - - dispose_list(&throw_away); -@@ -688,7 +695,7 @@ int invalidate_device(kdev_t dev, int do - * hold). - */ - shrink_dcache_sb(sb); -- res = invalidate_inodes(sb); -+ res = invalidate_inodes(sb, 0); - drop_super(sb); - } - invalidate_buffers(dev); ---- linux-rh-2.4.20-8/fs/super.c~invalidate_show 2003-04-11 14:04:57.000000000 +0800 -+++ linux-rh-2.4.20-8-root/fs/super.c 2003-04-16 20:59:35.000000000 +0800 -@@ -943,7 +943,7 @@ void kill_super(struct super_block *sb) - lock_super(sb); - lock_kernel(); - sb->s_flags &= ~MS_ACTIVE; -- invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ -+ invalidate_inodes(sb, 0); /* bad name - it should be evict_inodes() */ - if (sop) { - if (sop->write_super && sb->s_dirt) - sop->write_super(sb); -@@ -952,7 +952,7 @@ void kill_super(struct super_block *sb) - } - - /* Forget any remaining inodes */ -- if (invalidate_inodes(sb)) { -+ if (invalidate_inodes(sb, 1)) { - printk(KERN_ERR "VFS: Busy inodes after unmount. " - "Self-destruct in 5 seconds. Have a nice day...\n"); - } ---- linux-rh-2.4.20-8/include/linux/fs.h~invalidate_show 2003-04-16 20:55:35.000000000 +0800 -+++ linux-rh-2.4.20-8-root/include/linux/fs.h 2003-04-16 20:59:35.000000000 +0800 -@@ -1283,7 +1283,7 @@ static inline void mark_buffer_dirty_ino - extern void set_buffer_flushtime(struct buffer_head *); - extern void balance_dirty(void); - extern int check_disk_change(kdev_t); --extern int invalidate_inodes(struct super_block *); -+extern int invalidate_inodes(struct super_block *, int); - extern int invalidate_device(kdev_t, int); - extern void invalidate_inode_pages(struct inode *); - extern void invalidate_inode_pages2(struct address_space *); ---- linux-rh-2.4.20-8/fs/smbfs/inode.c~invalidate_show 2003-04-16 20:59:48.000000000 +0800 -+++ linux-rh-2.4.20-8-root/fs/smbfs/inode.c 2003-04-16 21:00:43.000000000 +0800 -@@ -167,7 +167,7 @@ smb_invalidate_inodes(struct smb_sb_info - { - VERBOSE("\n"); - shrink_dcache_sb(SB_of(server)); -- invalidate_inodes(SB_of(server)); -+ invalidate_inodes(SB_of(server), 0); - } - - /* - -_ diff --git a/lustre/kernel_patches/patches/iod-rmap-exports-2.4.21-chaos.patch b/lustre/kernel_patches/patches/iod-rmap-exports-2.4.21-chaos.patch deleted file mode 100644 index 63a6274..0000000 --- a/lustre/kernel_patches/patches/iod-rmap-exports-2.4.21-chaos.patch +++ /dev/null @@ -1,94 +0,0 @@ - fs/Makefile | 4 +++- - fs/inode.c | 4 +++- - mm/Makefile | 2 +- - mm/page_alloc.c | 1 + - mm/vmscan.c | 3 +++ - 5 files changed, 11 insertions(+), 3 deletions(-) - -Index: linux-2.4.21-chaos/fs/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/inode.c 2003-12-12 16:18:06.000000000 +0300 -+++ linux-2.4.21-chaos/fs/inode.c 2003-12-12 16:18:08.000000000 +0300 -@@ -5,6 +5,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -69,7 +70,8 @@ - * NOTE! You also have to own the lock if you change - * the i_state of an inode while it is in use.. - */ --static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; -+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; -+EXPORT_SYMBOL(inode_lock); - - /* - * Statistics gathering.. -Index: linux-2.4.21-chaos/fs/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/Makefile 2003-07-15 04:41:00.000000000 +0400 -+++ linux-2.4.21-chaos/fs/Makefile 2003-12-12 16:18:08.000000000 +0300 -@@ -1,3 +1,5 @@ -+ -+ - # - # Makefile for the Linux filesystems. - # -@@ -7,7 +9,7 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o - mod-subdirs := nls - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.21-chaos/mm/vmscan.c -=================================================================== ---- linux-2.4.21-chaos.orig/mm/vmscan.c 2003-12-05 07:55:51.000000000 +0300 -+++ linux-2.4.21-chaos/mm/vmscan.c 2003-12-12 16:18:08.000000000 +0300 -@@ -15,6 +15,8 @@ - * O(1) rmap vm, Arjan van de ven - */ - -+#include -+#include - #include - #include - #include -@@ -1210,6 +1212,7 @@ - set_current_state(TASK_RUNNING); - remove_wait_queue(&kswapd_done, &wait); - } -+EXPORT_SYMBOL(wakeup_kswapd); - - static void wakeup_memwaiters(void) - { -Index: linux-2.4.21-chaos/mm/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/mm/Makefile 2003-07-15 04:41:42.000000000 +0400 -+++ linux-2.4.21-chaos/mm/Makefile 2003-12-12 16:18:08.000000000 +0300 -@@ -9,7 +9,7 @@ - - O_TARGET := mm.o - --export-objs := shmem.o filemap.o memory.o page_alloc.o mempool.o usercopy.o -+export-objs := shmem.o filemap.o memory.o page_alloc.o mempool.o usercopy.o vmscan.o - - obj-y := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \ - vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \ -Index: linux-2.4.21-chaos/mm/page_alloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/mm/page_alloc.c 2003-12-05 07:55:51.000000000 +0300 -+++ linux-2.4.21-chaos/mm/page_alloc.c 2003-12-12 16:18:08.000000000 +0300 -@@ -27,6 +27,7 @@ - - int nr_swap_pages; - pg_data_t *pgdat_list; -+EXPORT_SYMBOL(pgdat_list); - - /* - * diff --git a/lustre/kernel_patches/patches/iod-stock-24-exports_hp.patch b/lustre/kernel_patches/patches/iod-stock-24-exports_hp.patch deleted file mode 100644 index 3035f55..0000000 --- a/lustre/kernel_patches/patches/iod-stock-24-exports_hp.patch +++ /dev/null @@ -1,48 +0,0 @@ - fs/Makefile | 2 +- - fs/inode.c | 4 +++- - mm/page_alloc.c | 1 + - 3 files changed, 5 insertions(+), 2 deletions(-) - ---- linux/fs/inode.c~iod-stock-24-exports_hp Wed Apr 9 10:44:54 2003 -+++ linux-mmonroe/fs/inode.c Wed Apr 9 10:49:50 2003 -@@ -5,6 +5,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -66,7 +67,8 @@ static LIST_HEAD(anon_hash_chain); /* fo - * NOTE! You also have to own the lock if you change - * the i_state of an inode while it is in use.. - */ --static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; -+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; -+EXPORT_SYMBOL(inode_lock); - - /* - * Statistics gathering.. ---- linux/fs/Makefile~iod-stock-24-exports_hp Wed Apr 9 10:26:08 2003 -+++ linux-mmonroe/fs/Makefile Wed Apr 9 10:49:50 2003 -@@ -7,7 +7,7 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o - mod-subdirs := nls xfs - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ ---- linux/mm/page_alloc.c~iod-stock-24-exports_hp Wed Apr 9 10:26:14 2003 -+++ linux-mmonroe/mm/page_alloc.c Wed Apr 9 10:49:50 2003 -@@ -28,6 +28,7 @@ int nr_inactive_pages; - LIST_HEAD(inactive_list); - LIST_HEAD(active_list); - pg_data_t *pgdat_list; -+EXPORT_SYMBOL(pgdat_list); - - /* - * - -_ diff --git a/lustre/kernel_patches/patches/iod-stock-exports-2.4.22.patch b/lustre/kernel_patches/patches/iod-stock-exports-2.4.22.patch deleted file mode 100644 index 47a6ff9..0000000 --- a/lustre/kernel_patches/patches/iod-stock-exports-2.4.22.patch +++ /dev/null @@ -1,52 +0,0 @@ - fs/Makefile | 2 +- - fs/inode.c | 4 +++- - mm/page_alloc.c | 1 + - 3 files changed, 5 insertions(+), 2 deletions(-) - -Index: linux-2.4.22-vanilla/fs/inode.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/inode.c 2003-11-03 23:22:24.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/inode.c 2003-11-03 23:25:00.000000000 +0300 -@@ -5,6 +5,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -66,7 +67,8 @@ - * NOTE! You also have to own the lock if you change - * the i_state of an inode while it is in use.. - */ --static spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; -+spinlock_t inode_lock = SPIN_LOCK_UNLOCKED; -+EXPORT_SYMBOL(inode_lock); - - /* - * Statistics gathering.. -Index: linux-2.4.22-vanilla/fs/Makefile -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/Makefile 2003-11-03 23:22:11.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/Makefile 2003-11-03 23:25:24.000000000 +0300 -@@ -7,7 +7,7 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o - mod-subdirs := nls - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.22-vanilla/mm/page_alloc.c -=================================================================== ---- linux-2.4.22-vanilla.orig/mm/page_alloc.c 2003-11-03 23:21:29.000000000 +0300 -+++ linux-2.4.22-vanilla/mm/page_alloc.c 2003-11-03 23:25:00.000000000 +0300 -@@ -28,6 +28,7 @@ - LIST_HEAD(inactive_list); - LIST_HEAD(active_list); - pg_data_t *pgdat_list; -+EXPORT_SYMBOL(pgdat_list); - - /* - * diff --git a/lustre/kernel_patches/patches/iopen-2.4.20.patch b/lustre/kernel_patches/patches/iopen-2.4.20.patch deleted file mode 100644 index d5a28e6..0000000 --- a/lustre/kernel_patches/patches/iopen-2.4.20.patch +++ /dev/null @@ -1,495 +0,0 @@ - Documentation/filesystems/ext2.txt | 16 ++ - fs/ext3/Makefile | 2 - fs/ext3/inode.c | 4 - fs/ext3/iopen.c | 259 +++++++++++++++++++++++++++++++++++++ - fs/ext3/iopen.h | 13 + - fs/ext3/namei.c | 13 + - fs/ext3/super.c | 11 + - include/linux/ext3_fs.h | 2 - 8 files changed, 318 insertions(+), 2 deletions(-) - -Index: lum/Documentation/filesystems/ext2.txt -=================================================================== ---- lum.orig/Documentation/filesystems/ext2.txt 2001-07-11 16:44:45.000000000 -0600 -+++ lum/Documentation/filesystems/ext2.txt 2004-03-09 16:46:38.000000000 -0700 -@@ -35,6 +35,22 @@ - - sb=n Use alternate superblock at this location. - -+iopen Makes an invisible pseudo-directory called -+ __iopen__ available in the root directory -+ of the filesystem. Allows open-by-inode- -+ number. i.e., inode 3145 can be accessed -+ via /mntpt/__iopen__/3145 -+ -+iopen_nopriv This option makes the iopen directory be -+ world-readable. This may be safer since it -+ allows daemons to run as an unprivileged user, -+ however it significantly changes the security -+ model of a Unix filesystem, since previously -+ all files under a mode 700 directory were not -+ generally avilable even if the -+ permissions on the file itself is -+ world-readable. -+ - grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. - - -Index: lum/fs/ext3/Makefile -=================================================================== ---- lum.orig/fs/ext3/Makefile 2004-01-30 14:54:50.000000000 -0700 -+++ lum/fs/ext3/Makefile 2004-03-09 16:46:39.000000000 -0700 -@@ -11,7 +11,7 @@ - - export-objs := ext3-exports.o - --obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -+obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ - ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - -Index: lum/fs/ext3/inode.c -=================================================================== ---- lum.orig/fs/ext3/inode.c 2004-01-30 14:54:55.000000000 -0700 -+++ lum/fs/ext3/inode.c 2004-03-09 16:46:41.000000000 -0700 -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include "iopen.h" - - /* - * SEARCH_FROM_ZERO forces each block allocation to search from the start -@@ -2153,6 +2154,9 @@ - struct buffer_head *bh; - int block; - -+ if (ext3_iopen_get_inode(inode)) -+ return; -+ - if(ext3_get_inode_loc(inode, &iloc)) - goto bad_inode; - bh = iloc.bh; -Index: lum/fs/ext3/iopen.c -=================================================================== ---- lum.orig/fs/ext3/iopen.c 2004-03-09 16:46:37.000000000 -0700 -+++ lum/fs/ext3/iopen.c 2004-03-09 16:48:03.000000000 -0700 -@@ -0,0 +1,285 @@ -+/* -+ * linux/fs/ext3/iopen.c -+ * -+ * Special support for open by inode number -+ * -+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * -+ * This file may be redistributed under the terms of the GNU General -+ * Public License. -+ * -+ * -+ * Invariants: -+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias -+ * for an inode at one time. -+ * - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry -+ * aliases on an inode at the same time. -+ * -+ * If we have any connected dentry aliases for an inode, use one of those -+ * in iopen_lookup(). Otherwise, we instantiate a single NFSD_DISCONNECTED -+ * dentry for this inode, which thereafter will be found by the dcache -+ * when looking up this inode number in __iopen__, so we don't return here -+ * until it is gone. -+ * -+ * If we get an inode via a regular name lookup, then we "rename" the -+ * NFSD_DISCONNECTED dentry to the proper name and parent. This ensures -+ * existing users of the disconnected dentry will continue to use the same -+ * dentry as the connected users, and there will never be both kinds of -+ * dentry aliases at one time. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "iopen.h" -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#define IOPEN_NAME_LEN 32 -+ -+/* -+ * This implements looking up an inode by number. -+ */ -+static struct dentry *iopen_lookup(struct inode *dir, struct dentry *dentry) -+{ -+ struct inode *inode; -+ unsigned long ino; -+ struct list_head *lp; -+ struct dentry *alternate; -+ char buf[IOPEN_NAME_LEN]; -+ -+ if (dentry->d_name.len >= IOPEN_NAME_LEN) -+ return ERR_PTR(-ENAMETOOLONG); -+ -+ memcpy(buf, dentry->d_name.name, dentry->d_name.len); -+ buf[dentry->d_name.len] = 0; -+ -+ if (strcmp(buf, ".") == 0) -+ ino = dir->i_ino; -+ else if (strcmp(buf, "..") == 0) -+ ino = EXT3_ROOT_INO; -+ else -+ ino = simple_strtoul(buf, 0, 0); -+ -+ if ((ino != EXT3_ROOT_INO && -+ //ino != EXT3_ACL_IDX_INO && -+ //ino != EXT3_ACL_DATA_INO && -+ ino < EXT3_FIRST_INO(dir->i_sb)) || -+ ino > le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) -+ return ERR_PTR(-ENOENT); -+ -+ inode = iget(dir->i_sb, ino); -+ if (!inode) -+ return ERR_PTR(-EACCES); -+ if (is_bad_inode(inode)) { -+ iput(inode); -+ return ERR_PTR(-ENOENT); -+ } -+ -+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ -+ assert(list_empty(&dentry->d_hash)); /* d_rehash */ -+ -+ /* preferrably return a connected dentry */ -+ spin_lock(&dcache_lock); -+ list_for_each(lp, &inode->i_dentry) { -+ alternate = list_entry(lp, struct dentry, d_alias); -+ assert(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED)); -+ } -+ -+ if (!list_empty(&inode->i_dentry)) { -+ alternate = list_entry(inode->i_dentry.next, -+ struct dentry, d_alias); -+ dget_locked(alternate); -+ alternate->d_vfs_flags |= DCACHE_REFERENCED; -+ iput(inode); -+ spin_unlock(&dcache_lock); -+ return alternate; -+ } -+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; -+ -+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ -+ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ -+ dentry->d_inode = inode; -+ -+ __d_rehash(dentry, 0); /* d_rehash */ -+ spin_unlock(&dcache_lock); -+ -+ return NULL; -+} -+ -+#define do_switch(x,y) do { \ -+ __typeof__ (x) __tmp = x; \ -+ x = y; y = __tmp; } while (0) -+ -+static inline void switch_names(struct dentry *dentry, struct dentry *target) -+{ -+ const unsigned char *old_name, *new_name; -+ -+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); -+ old_name = target->d_name.name; -+ new_name = dentry->d_name.name; -+ if (old_name == target->d_iname) -+ old_name = dentry->d_iname; -+ if (new_name == dentry->d_iname) -+ new_name = target->d_iname; -+ target->d_name.name = new_name; -+ dentry->d_name.name = old_name; -+} -+ -+/* This function is spliced into ext3_lookup and does the move of a -+ * disconnected dentry (if it exists) to a connected dentry. -+ */ -+struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode, -+ int rehash) -+{ -+ struct dentry *tmp, *goal = NULL; -+ struct list_head *lp; -+ -+ /* verify this dentry is really new */ -+ assert(dentry->d_inode == NULL); -+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ -+ if (rehash) -+ assert(list_empty(&dentry->d_hash)); /* d_rehash */ -+ assert(list_empty(&dentry->d_subdirs)); -+ -+ spin_lock(&dcache_lock); -+ if (!inode) -+ goto do_rehash; -+ -+ /* preferrably return a connected dentry */ -+ list_for_each(lp, &inode->i_dentry) { -+ tmp = list_entry(lp, struct dentry, d_alias); -+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) { -+ assert(tmp->d_alias.next == &inode->i_dentry); -+ assert(tmp->d_alias.prev == &inode->i_dentry); -+ goal = tmp; -+ dget_locked(goal); -+ break; -+ } -+ } -+ -+ if (!goal) -+ goto do_instantiate; -+ -+ if (!test_opt(inode->i_sb, IOPEN)) -+ goto do_instantiate; -+ -+ /* Move the goal to the de hash queue - like d_move() */ -+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED; -+ list_del_init(&goal->d_hash); -+ -+ list_del(&goal->d_child); -+ list_del(&dentry->d_child); -+ -+ /* Switch the parents and the names.. */ -+ switch_names(goal, dentry); -+ do_switch(goal->d_parent, dentry->d_parent); -+ do_switch(goal->d_name.len, dentry->d_name.len); -+ do_switch(goal->d_name.hash, dentry->d_name.hash); -+ -+ /* And add them back to the (new) parent lists */ -+ list_add(&goal->d_child, &goal->d_parent->d_subdirs); -+ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); -+ __d_rehash(goal, 0); -+ spin_unlock(&dcache_lock); -+ iput(inode); -+ -+ return goal; -+ -+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ -+do_instantiate: -+ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ -+ dentry->d_inode = inode; -+do_rehash: -+ if (rehash) -+ __d_rehash(dentry, 0); /* d_rehash */ -+ spin_unlock(&dcache_lock); -+ -+ return NULL; -+} -+ -+/* -+ * These are the special structures for the iopen pseudo directory. -+ */ -+ -+static struct inode_operations iopen_inode_operations = { -+ lookup: iopen_lookup, /* BKL held */ -+}; -+ -+static struct file_operations iopen_file_operations = { -+ read: generic_read_dir, -+}; -+ -+static int match_dentry(struct dentry *dentry, const char *name) -+{ -+ int len; -+ -+ len = strlen(name); -+ if (dentry->d_name.len != len) -+ return 0; -+ if (strncmp(dentry->d_name.name, name, len)) -+ return 0; -+ return 1; -+} -+ -+/* -+ * This function is spliced into ext3_lookup and returns 1 the file -+ * name is __iopen__ and dentry has been filled in appropriately. -+ */ -+int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry) -+{ -+ struct inode *inode; -+ -+ if (dir->i_ino != EXT3_ROOT_INO || -+ !test_opt(dir->i_sb, IOPEN) || -+ !match_dentry(dentry, "__iopen__")) -+ return 0; -+ -+ inode = iget(dir->i_sb, EXT3_BAD_INO); -+ -+ if (!inode) -+ return 0; -+ d_add(dentry, inode); -+ return 1; -+} -+ -+/* -+ * This function is spliced into read_inode; it returns 1 if inode -+ * number is the one for /__iopen__, in which case the inode is filled -+ * in appropriately. Otherwise, this fuction returns 0. -+ */ -+int ext3_iopen_get_inode(struct inode *inode) -+{ -+ if (inode->i_ino != EXT3_BAD_INO) -+ return 0; -+ -+ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR; -+ if (test_opt(inode->i_sb, IOPEN_NOPRIV)) -+ inode->i_mode |= 0777; -+ inode->i_uid = 0; -+ inode->i_gid = 0; -+ inode->i_nlink = 1; -+ inode->i_size = 4096; -+ inode->i_atime = CURRENT_TIME; -+ inode->i_ctime = CURRENT_TIME; -+ inode->i_mtime = CURRENT_TIME; -+ inode->u.ext3_i.i_dtime = 0; -+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size -+ * (for stat), not the fs block -+ * size */ -+ inode->i_blocks = 0; -+ inode->i_version = 1; -+ inode->i_generation = 0; -+ -+ inode->i_op = &iopen_inode_operations; -+ inode->i_fop = &iopen_file_operations; -+ inode->i_mapping->a_ops = 0; -+ -+ return 1; -+} -Index: lum/fs/ext3/iopen.h -=================================================================== ---- lum.orig/fs/ext3/iopen.h 2004-03-09 16:46:37.000000000 -0700 -+++ lum/fs/ext3/iopen.h 2004-03-09 16:48:03.000000000 -0700 -@@ -0,0 +1,15 @@ -+/* -+ * iopen.h -+ * -+ * Special support for opening files by inode number. -+ * -+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * -+ * This file may be redistributed under the terms of the GNU General -+ * Public License. -+ */ -+ -+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry); -+extern int ext3_iopen_get_inode(struct inode *inode); -+extern struct dentry *iopen_connect_dentry(struct dentry *dentry, -+ struct inode *inode, int rehash); -Index: lum/fs/ext3/namei.c -=================================================================== ---- lum.orig/fs/ext3/namei.c 2004-01-30 14:54:53.000000000 -0700 -+++ lum/fs/ext3/namei.c 2004-03-09 16:49:25.000000000 -0700 -@@ -35,7 +35,7 @@ - #include - #include - #include -- -+#include "iopen.h" - - /* - * define how far ahead to read directories while searching them. -@@ -931,6 +931,9 @@ - if (dentry->d_name.len > EXT3_NAME_LEN) - return ERR_PTR(-ENAMETOOLONG); - -+ if (ext3_check_for_iopen(dir, dentry)) -+ return NULL; -+ - bh = ext3_find_entry(dentry, &de); - inode = NULL; - if (bh) { -@@ -942,8 +945,8 @@ - return ERR_PTR(-EACCES); - } - } -- d_add(dentry, inode); -- return NULL; -+ -+ return iopen_connect_dentry(dentry, inode, 1); - } - - #define S_SHIFT 12 -@@ -1932,10 +1935,6 @@ - inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; -- /* There's no need to set i_disksize: the fact that i_nlink is -- * zero will ensure that the right thing happens during any -- * recovery. */ -- inode->i_size = 0; - ext3_orphan_add(handle, inode); - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -@@ -2086,6 +2085,23 @@ - return err; - } - -+/* Like ext3_add_nondir() except for call to iopen_connect_dentry */ -+static int ext3_add_link(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ int err = ext3_add_entry(handle, dentry, inode); -+ if (!err) { -+ err = ext3_mark_inode_dirty(handle, inode); -+ if (err == 0) { -+ dput(iopen_connect_dentry(dentry, inode, 0)); -+ return 0; -+ } -+ } -+ ext3_dec_count(handle, inode); -+ iput(inode); -+ return err; -+} -+ - static int ext3_link (struct dentry * old_dentry, - struct inode * dir, struct dentry *dentry) - { -@@ -2113,7 +2129,8 @@ - ext3_inc_count(handle, inode); - atomic_inc(&inode->i_count); - -- err = ext3_add_nondir(handle, dentry, inode); -+ err = ext3_add_link(handle, dentry, inode); -+ ext3_orphan_del(handle, inode); - ext3_journal_stop(handle, dir); - return err; - } -Index: lum/fs/ext3/super.c -=================================================================== ---- lum.orig/fs/ext3/super.c 2004-01-30 14:54:53.000000000 -0700 -+++ lum/fs/ext3/super.c 2004-03-09 16:46:45.000000000 -0700 -@@ -742,6 +742,18 @@ - || !strcmp (this_char, "quota") - || !strcmp (this_char, "usrquota")) - /* Don't do anything ;-) */ ; -+ else if (!strcmp (this_char, "iopen")) { -+ set_opt (sbi->s_mount_opt, IOPEN); -+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); -+ } -+ else if (!strcmp (this_char, "noiopen")) { -+ clear_opt (sbi->s_mount_opt, IOPEN); -+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); -+ } -+ else if (!strcmp (this_char, "iopen_nopriv")) { -+ set_opt (sbi->s_mount_opt, IOPEN); -+ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV); -+ } - else if (!strcmp (this_char, "journal")) { - /* @@@ FIXME */ - /* Eventually we will want to be able to create -Index: lum/include/linux/ext3_fs.h -=================================================================== ---- lum.orig/include/linux/ext3_fs.h 2004-01-30 14:54:53.000000000 -0700 -+++ lum/include/linux/ext3_fs.h 2004-03-09 16:46:46.000000000 -0700 -@@ -324,4 +324,6 @@ - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ -+#define EXT3_MOUNT_IOPEN 0x80000 /* Allow access via iopen */ -+#define EXT3_MOUNT_IOPEN_NOPRIV 0x100000/* Make iopen world-readable */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ diff --git a/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch b/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch deleted file mode 100644 index 1510c9b..0000000 --- a/lustre/kernel_patches/patches/iopen-2.4.21-chaos.patch +++ /dev/null @@ -1,497 +0,0 @@ - Documentation/filesystems/ext2.txt | 16 ++ - fs/ext3/Makefile | 2 - fs/ext3/inode.c | 4 - fs/ext3/iopen.c | 259 +++++++++++++++++++++++++++++++++++++ - fs/ext3/iopen.h | 13 + - fs/ext3/namei.c | 13 + - fs/ext3/super.c | 11 + - include/linux/ext3_fs.h | 2 - 8 files changed, 318 insertions(+), 2 deletions(-) - -Index: linux-ia64/Documentation/filesystems/ext2.txt -=================================================================== ---- linux-ia64.orig/Documentation/filesystems/ext2.txt 2004-03-17 15:47:15.000000000 -0800 -+++ linux-ia64/Documentation/filesystems/ext2.txt 2004-03-17 18:03:15.000000000 -0800 -@@ -35,6 +35,22 @@ resgid=n The group ID which may use th - - sb=n Use alternate superblock at this location. - -+iopen Makes an invisible pseudo-directory called -+ __iopen__ available in the root directory -+ of the filesystem. Allows open-by-inode- -+ number. i.e., inode 3145 can be accessed -+ via /mntpt/__iopen__/3145 -+ -+iopen_nopriv This option makes the iopen directory be -+ world-readable. This may be safer since it -+ allows daemons to run as an unprivileged user, -+ however it significantly changes the security -+ model of a Unix filesystem, since previously -+ all files under a mode 700 directory were not -+ generally avilable even if the -+ permissions on the file itself is -+ world-readable. -+ - grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2. - - -Index: linux-ia64/fs/ext3/Makefile -=================================================================== ---- linux-ia64.orig/fs/ext3/Makefile 2004-03-17 18:03:14.000000000 -0800 -+++ linux-ia64/fs/ext3/Makefile 2004-03-17 18:03:15.000000000 -0800 -@@ -11,7 +11,7 @@ O_TARGET := ext3.o - - export-objs := ext3-exports.o - --obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -+obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \ - ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - -Index: linux-ia64/fs/ext3/inode.c -=================================================================== ---- linux-ia64.orig/fs/ext3/inode.c 2004-03-17 18:03:15.000000000 -0800 -+++ linux-ia64/fs/ext3/inode.c 2004-03-17 18:10:36.000000000 -0800 -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include "iopen.h" - - /* - * SEARCH_FROM_ZERO forces each block allocation to search from the start -@@ -2430,6 +2431,9 @@ void ext3_read_inode(struct inode * inod - struct buffer_head *bh; - int block; - -+ if (ext3_iopen_get_inode(inode)) -+ return; -+ - if(ext3_get_inode_loc(inode, &iloc)) - goto bad_inode; - bh = iloc.bh; -Index: linux-ia64/fs/ext3/iopen.c -=================================================================== ---- linux-ia64.orig/fs/ext3/iopen.c 2004-03-17 18:02:08.000000000 -0800 -+++ linux-ia64/fs/ext3/iopen.c 2004-03-17 18:10:58.000000000 -0800 -@@ -0,0 +1,285 @@ -+/* -+ * linux/fs/ext3/iopen.c -+ * -+ * Special support for open by inode number -+ * -+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * -+ * This file may be redistributed under the terms of the GNU General -+ * Public License. -+ * -+ * -+ * Invariants: -+ * - there is only ever a single DCACHE_NFSD_DISCONNECTED dentry alias -+ * for an inode at one time. -+ * - there are never both connected and DCACHE_NFSD_DISCONNECTED dentry -+ * aliases on an inode at the same time. -+ * -+ * If we have any connected dentry aliases for an inode, use one of those -+ * in iopen_lookup(). Otherwise, we instantiate a single NFSD_DISCONNECTED -+ * dentry for this inode, which thereafter will be found by the dcache -+ * when looking up this inode number in __iopen__, so we don't return here -+ * until it is gone. -+ * -+ * If we get an inode via a regular name lookup, then we "rename" the -+ * NFSD_DISCONNECTED dentry to the proper name and parent. This ensures -+ * existing users of the disconnected dentry will continue to use the same -+ * dentry as the connected users, and there will never be both kinds of -+ * dentry aliases at one time. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "iopen.h" -+ -+#ifndef assert -+#define assert(test) J_ASSERT(test) -+#endif -+ -+#define IOPEN_NAME_LEN 32 -+ -+/* -+ * This implements looking up an inode by number. -+ */ -+static struct dentry *iopen_lookup(struct inode *dir, struct dentry *dentry) -+{ -+ struct inode *inode; -+ unsigned long ino; -+ struct list_head *lp; -+ struct dentry *alternate; -+ char buf[IOPEN_NAME_LEN]; -+ -+ if (dentry->d_name.len >= IOPEN_NAME_LEN) -+ return ERR_PTR(-ENAMETOOLONG); -+ -+ memcpy(buf, dentry->d_name.name, dentry->d_name.len); -+ buf[dentry->d_name.len] = 0; -+ -+ if (strcmp(buf, ".") == 0) -+ ino = dir->i_ino; -+ else if (strcmp(buf, "..") == 0) -+ ino = EXT3_ROOT_INO; -+ else -+ ino = simple_strtoul(buf, 0, 0); -+ -+ if ((ino != EXT3_ROOT_INO && -+ //ino != EXT3_ACL_IDX_INO && -+ //ino != EXT3_ACL_DATA_INO && -+ ino < EXT3_FIRST_INO(dir->i_sb)) || -+ ino > le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count)) -+ return ERR_PTR(-ENOENT); -+ -+ inode = iget(dir->i_sb, ino); -+ if (!inode) -+ return ERR_PTR(-EACCES); -+ if (is_bad_inode(inode)) { -+ iput(inode); -+ return ERR_PTR(-ENOENT); -+ } -+ -+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ -+ assert(list_empty(&dentry->d_hash)); /* d_rehash */ -+ -+ /* preferrably return a connected dentry */ -+ spin_lock(&dcache_lock); -+ list_for_each(lp, &inode->i_dentry) { -+ alternate = list_entry(lp, struct dentry, d_alias); -+ assert(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED)); -+ } -+ -+ if (!list_empty(&inode->i_dentry)) { -+ alternate = list_entry(inode->i_dentry.next, -+ struct dentry, d_alias); -+ dget_locked(alternate); -+ alternate->d_vfs_flags |= DCACHE_REFERENCED; -+ iput(inode); -+ spin_unlock(&dcache_lock); -+ return alternate; -+ } -+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED; -+ -+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ -+ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ -+ dentry->d_inode = inode; -+ -+ __d_rehash(dentry, 0); /* d_rehash */ -+ spin_unlock(&dcache_lock); -+ -+ return NULL; -+} -+ -+#define do_switch(x,y) do { \ -+ __typeof__ (x) __tmp = x; \ -+ x = y; y = __tmp; } while (0) -+ -+static inline void switch_names(struct dentry *dentry, struct dentry *target) -+{ -+ const unsigned char *old_name, *new_name; -+ -+ memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); -+ old_name = target->d_name.name; -+ new_name = dentry->d_name.name; -+ if (old_name == target->d_iname) -+ old_name = dentry->d_iname; -+ if (new_name == dentry->d_iname) -+ new_name = target->d_iname; -+ target->d_name.name = new_name; -+ dentry->d_name.name = old_name; -+} -+ -+/* This function is spliced into ext3_lookup and does the move of a -+ * disconnected dentry (if it exists) to a connected dentry. -+ */ -+struct dentry *iopen_connect_dentry(struct dentry *dentry, struct inode *inode, -+ int rehash) -+{ -+ struct dentry *tmp, *goal = NULL; -+ struct list_head *lp; -+ -+ /* verify this dentry is really new */ -+ assert(dentry->d_inode == NULL); -+ assert(list_empty(&dentry->d_alias)); /* d_instantiate */ -+ if (rehash) -+ assert(list_empty(&dentry->d_hash)); /* d_rehash */ -+ assert(list_empty(&dentry->d_subdirs)); -+ -+ spin_lock(&dcache_lock); -+ if (!inode) -+ goto do_rehash; -+ -+ if (!test_opt(inode->i_sb, IOPEN)) -+ goto do_instantiate; -+ -+ /* preferrably return a connected dentry */ -+ list_for_each(lp, &inode->i_dentry) { -+ tmp = list_entry(lp, struct dentry, d_alias); -+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) { -+ assert(tmp->d_alias.next == &inode->i_dentry); -+ assert(tmp->d_alias.prev == &inode->i_dentry); -+ goal = tmp; -+ dget_locked(goal); -+ break; -+ } -+ } -+ -+ if (!goal) -+ goto do_instantiate; -+ -+ /* Move the goal to the de hash queue - like d_move() */ -+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED; -+ list_del_init(&goal->d_hash); -+ -+ list_del(&goal->d_child); -+ list_del(&dentry->d_child); -+ -+ /* Switch the parents and the names.. */ -+ switch_names(goal, dentry); -+ do_switch(goal->d_parent, dentry->d_parent); -+ do_switch(goal->d_name.len, dentry->d_name.len); -+ do_switch(goal->d_name.hash, dentry->d_name.hash); -+ -+ /* And add them back to the (new) parent lists */ -+ list_add(&goal->d_child, &goal->d_parent->d_subdirs); -+ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); -+ __d_rehash(goal, 0); -+ spin_unlock(&dcache_lock); -+ iput(inode); -+ -+ return goal; -+ -+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */ -+do_instantiate: -+ list_add(&dentry->d_alias, &inode->i_dentry); /* d_instantiate */ -+ dentry->d_inode = inode; -+do_rehash: -+ if (rehash) -+ __d_rehash(dentry, 0); /* d_rehash */ -+ spin_unlock(&dcache_lock); -+ -+ return NULL; -+} -+ -+/* -+ * These are the special structures for the iopen pseudo directory. -+ */ -+ -+static struct inode_operations iopen_inode_operations = { -+ lookup: iopen_lookup, /* BKL held */ -+}; -+ -+static struct file_operations iopen_file_operations = { -+ read: generic_read_dir, -+}; -+ -+static int match_dentry(struct dentry *dentry, const char *name) -+{ -+ int len; -+ -+ len = strlen(name); -+ if (dentry->d_name.len != len) -+ return 0; -+ if (strncmp(dentry->d_name.name, name, len)) -+ return 0; -+ return 1; -+} -+ -+/* -+ * This function is spliced into ext3_lookup and returns 1 the file -+ * name is __iopen__ and dentry has been filled in appropriately. -+ */ -+int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry) -+{ -+ struct inode *inode; -+ -+ if (dir->i_ino != EXT3_ROOT_INO || -+ !test_opt(dir->i_sb, IOPEN) || -+ !match_dentry(dentry, "__iopen__")) -+ return 0; -+ -+ inode = iget(dir->i_sb, EXT3_BAD_INO); -+ -+ if (!inode) -+ return 0; -+ d_add(dentry, inode); -+ return 1; -+} -+ -+/* -+ * This function is spliced into read_inode; it returns 1 if inode -+ * number is the one for /__iopen__, in which case the inode is filled -+ * in appropriately. Otherwise, this fuction returns 0. -+ */ -+int ext3_iopen_get_inode(struct inode *inode) -+{ -+ if (inode->i_ino != EXT3_BAD_INO) -+ return 0; -+ -+ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR; -+ if (test_opt(inode->i_sb, IOPEN_NOPRIV)) -+ inode->i_mode |= 0777; -+ inode->i_uid = 0; -+ inode->i_gid = 0; -+ inode->i_nlink = 1; -+ inode->i_size = 4096; -+ inode->i_atime = CURRENT_TIME; -+ inode->i_ctime = CURRENT_TIME; -+ inode->i_mtime = CURRENT_TIME; -+ inode->u.ext3_i.i_dtime = 0; -+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size -+ * (for stat), not the fs block -+ * size */ -+ inode->i_blocks = 0; -+ inode->i_version = 1; -+ inode->i_generation = 0; -+ -+ inode->i_op = &iopen_inode_operations; -+ inode->i_fop = &iopen_file_operations; -+ inode->i_mapping->a_ops = 0; -+ -+ return 1; -+} -Index: linux-ia64/fs/ext3/iopen.h -=================================================================== ---- linux-ia64.orig/fs/ext3/iopen.h 2004-03-17 15:47:15.000000000 -0800 -+++ linux-ia64/fs/ext3/iopen.h 2004-03-17 18:03:15.000000000 -0800 -@@ -0,0 +1,15 @@ -+/* -+ * iopen.h -+ * -+ * Special support for opening files by inode number. -+ * -+ * Copyright (C) 2001 by Theodore Ts'o (tytso@alum.mit.edu). -+ * -+ * This file may be redistributed under the terms of the GNU General -+ * Public License. -+ */ -+ -+extern int ext3_check_for_iopen(struct inode *dir, struct dentry *dentry); -+extern int ext3_iopen_get_inode(struct inode *inode); -+extern struct dentry *iopen_connect_dentry(struct dentry *dentry, -+ struct inode *inode, int rehash); -Index: linux-ia64/fs/ext3/namei.c -=================================================================== ---- linux-ia64.orig/fs/ext3/namei.c 2004-03-17 18:03:15.000000000 -0800 -+++ linux-ia64/fs/ext3/namei.c 2004-03-17 18:10:35.000000000 -0800 -@@ -36,7 +36,7 @@ - #include - #include - #include -- -+#include "iopen.h" - - /* - * define how far ahead to read directories while searching them. -@@ -932,6 +932,9 @@ static struct dentry *ext3_lookup(struct - if (dentry->d_name.len > EXT3_NAME_LEN) - return ERR_PTR(-ENAMETOOLONG); - -+ if (ext3_check_for_iopen(dir, dentry)) -+ return NULL; -+ - bh = ext3_find_entry(dentry, &de); - inode = NULL; - if (bh) { -@@ -943,8 +946,8 @@ static struct dentry *ext3_lookup(struct - return ERR_PTR(-EACCES); - } - } -- d_add(dentry, inode); -- return NULL; -+ -+ return iopen_connect_dentry(dentry, inode, 1); - } - - #define S_SHIFT 12 -@@ -1935,10 +1938,6 @@ static int ext3_rmdir (struct inode * di - inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; -- /* There's no need to set i_disksize: the fact that i_nlink is -- * zero will ensure that the right thing happens during any -- * recovery. */ -- inode->i_size = 0; - ext3_orphan_add(handle, inode); - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -@@ -2057,6 +2056,23 @@ out_stop: - return err; - } - -+/* Like ext3_add_nondir() except for call to iopen_connect_dentry */ -+static int ext3_add_link(handle_t *handle, struct dentry *dentry, -+ struct inode *inode) -+{ -+ int err = ext3_add_entry(handle, dentry, inode); -+ if (!err) { -+ err = ext3_mark_inode_dirty(handle, inode); -+ if (err == 0) { -+ dput(iopen_connect_dentry(dentry, inode, 0)); -+ return 0; -+ } -+ } -+ ext3_dec_count(handle, inode); -+ iput(inode); -+ return err; -+} -+ - static int ext3_link (struct dentry * old_dentry, - struct inode * dir, struct dentry *dentry) - { -@@ -2084,7 +2100,8 @@ static int ext3_link (struct dentry * ol - ext3_inc_count(handle, inode); - atomic_inc(&inode->i_count); - -- err = ext3_add_nondir(handle, dentry, inode); -+ err = ext3_add_link(handle, dentry, inode); -+ ext3_orphan_del(handle, inode); - ext3_journal_stop(handle, dir); - return err; - } -Index: linux-ia64/fs/ext3/super.c -=================================================================== ---- linux-ia64.orig/fs/ext3/super.c 2004-03-17 18:03:14.000000000 -0800 -+++ linux-ia64/fs/ext3/super.c 2004-03-17 18:10:35.000000000 -0800 -@@ -891,6 +891,18 @@ static int parse_options (char * options - || !strcmp (this_char, "quota") - || !strcmp (this_char, "usrquota")) - /* Don't do anything ;-) */ ; -+ else if (!strcmp (this_char, "iopen")) { -+ set_opt (sbi->s_mount_opt, IOPEN); -+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); -+ } -+ else if (!strcmp (this_char, "noiopen")) { -+ clear_opt (sbi->s_mount_opt, IOPEN); -+ clear_opt (sbi->s_mount_opt, IOPEN_NOPRIV); -+ } -+ else if (!strcmp (this_char, "iopen_nopriv")) { -+ set_opt (sbi->s_mount_opt, IOPEN); -+ set_opt (sbi->s_mount_opt, IOPEN_NOPRIV); -+ } - else if (!strcmp (this_char, "journal")) { - /* @@@ FIXME */ - /* Eventually we will want to be able to create -Index: linux-ia64/include/linux/ext3_fs.h -=================================================================== ---- linux-ia64.orig/include/linux/ext3_fs.h 2004-03-17 18:03:15.000000000 -0800 -+++ linux-ia64/include/linux/ext3_fs.h 2004-03-17 18:03:15.000000000 -0800 -@@ -328,6 +328,8 @@ struct ext3_inode { - #define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - #define EXT3_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */ - #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */ -+#define EXT3_MOUNT_IOPEN 0x80000 /* Allow access via iopen */ -+#define EXT3_MOUNT_IOPEN_NOPRIV 0x100000/* Make iopen world-readable */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H diff --git a/lustre/kernel_patches/patches/jbd-commit-tricks-rhel3.patch b/lustre/kernel_patches/patches/jbd-commit-tricks-rhel3.patch deleted file mode 100644 index 725931c..0000000 --- a/lustre/kernel_patches/patches/jbd-commit-tricks-rhel3.patch +++ /dev/null @@ -1,132 +0,0 @@ - ---- linux-2.4.18/fs/jbd/checkpoint.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/checkpoint.c Mon Jul 28 14:03:59 2003 -@@ -77,19 +77,23 @@ static int __try_to_free_cp_buf(struct j - * to wait for a checkpoint to free up some space in the log. - */ - --void log_wait_for_space(journal_t *journal, int nblocks) -+void log_wait_for_space(journal_t *journal) - { -+ int nblocks; -+ -+ nblocks = jbd_space_needed(journal); - while (log_space_left(journal) < nblocks) { - if (journal->j_flags & JFS_ABORT) - return; - unlock_journal(journal); - down(&journal->j_checkpoint_sem); - lock_journal(journal); -+ nblocks = jbd_space_needed(journal); - - /* Test again, another process may have checkpointed - * while we were waiting for the checkpoint lock */ - if (log_space_left(journal) < nblocks) { -- log_do_checkpoint(journal, nblocks); -+ log_do_checkpoint(journal); - } - up(&journal->j_checkpoint_sem); - } -@@ -260,8 +264,7 @@ static int __flush_buffer(journal_t *jou - * The journal should be locked before calling this function. - */ - --/* @@@ `nblocks' is unused. Should it be used? */ --int log_do_checkpoint (journal_t *journal, int nblocks) -+int log_do_checkpoint (journal_t *journal) - { - transaction_t *transaction, *last_transaction, *next_transaction; - int result; -@@ -315,6 +318,8 @@ repeat: - retry = __flush_buffer(journal, jh, bhs, &batch_count, - &drop_count); - } while (jh != last_jh && !retry); -+ if (journal->j_checkpoint_transactions != transaction) -+ goto done; - if (batch_count) { - __flush_batch(bhs, &batch_count); - goto repeat; -@@ -328,6 +333,8 @@ repeat: - */ - cleanup_ret = __cleanup_transaction(journal, transaction); - J_ASSERT(drop_count != 0 || cleanup_ret != 0); -+ if (journal->j_checkpoint_transactions != transaction) -+ goto done; - goto repeat; /* __cleanup may have dropped lock */ - } while (transaction != last_transaction); - ---- linux-2.4.18/fs/jbd/journal.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/journal.c Mon Jul 28 14:03:59 2003 -@@ -1115,7 +1115,7 @@ void journal_destroy (journal_t *journal - /* Force any old transactions to disk */ - lock_journal(journal); - while (journal->j_checkpoint_transactions != NULL) -- log_do_checkpoint(journal, 1); -+ log_do_checkpoint(journal); - - J_ASSERT(journal->j_running_transaction == NULL); - J_ASSERT(journal->j_committing_transaction == NULL); -@@ -1302,7 +1302,7 @@ int journal_flush (journal_t *journal) - /* ...and flush everything in the log out to disk. */ - lock_journal(journal); - while (!err && journal->j_checkpoint_transactions != NULL) -- err = log_do_checkpoint(journal, journal->j_maxlen); -+ err = log_do_checkpoint(journal); - cleanup_journal_tail(journal); - - /* Finally, mark the journal as really needing no recovery. ---- linux-2.4.18/fs/jbd/transaction.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/transaction.c Mon Jul 28 14:03:59 2003 -@@ -182,14 +182,9 @@ repeat_locked: - * Also, this test is inconsitent with the matching one in - * journal_extend(). - */ -- needed = journal->j_max_transaction_buffers; -- if (journal->j_committing_transaction) -- needed += journal->j_committing_transaction-> -- t_outstanding_credits; -- -- if (log_space_left(journal) < needed) { -+ if (log_space_left(journal) < jbd_space_needed(journal)) { - jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); -- log_wait_for_space(journal, needed); -+ log_wait_for_space(journal); - goto repeat_locked; - } - ---- linux-2.4.18/include/linux/jbd.h~jbd-commit-tricks Mon Jul 28 13:52:17 2003 -+++ linux-2.4.18-alexey/include/linux/jbd.h Mon Jul 28 14:03:59 2003 -@@ -740,9 +740,9 @@ extern void journal_brelse_array(stru - extern int log_space_left (journal_t *); /* Called with journal locked */ - extern tid_t log_start_commit (journal_t *, transaction_t *); - extern int log_wait_commit (journal_t *, tid_t); --extern int log_do_checkpoint (journal_t *, int); -+extern int log_do_checkpoint (journal_t *); - --extern void log_wait_for_space(journal_t *, int nblocks); -+extern void log_wait_for_space(journal_t *); - extern void __journal_drop_transaction(journal_t *, transaction_t *); - extern int cleanup_journal_tail(journal_t *); - -@@ -815,6 +815,19 @@ static inline int tid_geq(tid_t x, tid_t - } - - extern int journal_blocks_per_page(struct inode *inode); -+ -+/* -+ * Return the minimum number of blocks which must be free in the journal -+ * before a new transaction may be started. Must be called under j_state_lock. -+ */ -+static inline int jbd_space_needed(journal_t *journal) -+{ -+ int nblocks = journal->j_max_transaction_buffers; -+ if (journal->j_committing_transaction) -+ nblocks += journal->j_committing_transaction-> -+ t_outstanding_credits; -+ return nblocks; -+} - - /* - * Definitions which augment the buffer_head layer - -_ diff --git a/lustre/kernel_patches/patches/jbd-commit-tricks.patch b/lustre/kernel_patches/patches/jbd-commit-tricks.patch deleted file mode 100644 index 467c29f..0000000 --- a/lustre/kernel_patches/patches/jbd-commit-tricks.patch +++ /dev/null @@ -1,132 +0,0 @@ - ---- linux-2.4.18/fs/jbd/checkpoint.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/checkpoint.c Mon Jul 28 14:03:59 2003 -@@ -77,19 +77,23 @@ static int __try_to_free_cp_buf(struct j - * to wait for a checkpoint to free up some space in the log. - */ - --void log_wait_for_space(journal_t *journal, int nblocks) -+void log_wait_for_space(journal_t *journal) - { -+ int nblocks; -+ -+ nblocks = jbd_space_needed(journal); - while (log_space_left(journal) < nblocks) { - if (journal->j_flags & JFS_ABORT) - return; - unlock_journal(journal); - down(&journal->j_checkpoint_sem); - lock_journal(journal); -+ nblocks = jbd_space_needed(journal); - - /* Test again, another process may have checkpointed - * while we were waiting for the checkpoint lock */ - if (log_space_left(journal) < nblocks) { -- log_do_checkpoint(journal, nblocks); -+ log_do_checkpoint(journal); - } - up(&journal->j_checkpoint_sem); - } -@@ -260,8 +264,7 @@ static int __flush_buffer(journal_t *jou - * The journal should be locked before calling this function. - */ - --/* @@@ `nblocks' is unused. Should it be used? */ --int log_do_checkpoint (journal_t *journal, int nblocks) -+int log_do_checkpoint (journal_t *journal) - { - transaction_t *transaction, *last_transaction, *next_transaction; - int result; -@@ -315,6 +318,8 @@ repeat: - retry = __flush_buffer(journal, jh, bhs, &batch_count, - &drop_count); - } while (jh != last_jh && !retry); -+ if (journal->j_checkpoint_transactions != transaction) -+ goto done; - if (batch_count) { - __flush_batch(bhs, &batch_count); - goto repeat; -@@ -328,6 +333,8 @@ repeat: - */ - cleanup_ret = __cleanup_transaction(journal, transaction); - J_ASSERT(drop_count != 0 || cleanup_ret != 0); -+ if (journal->j_checkpoint_transactions != transaction) -+ goto done; - goto repeat; /* __cleanup may have dropped lock */ - } while (transaction != last_transaction); - ---- linux-2.4.18/fs/jbd/journal.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/journal.c Mon Jul 28 14:03:59 2003 -@@ -1115,7 +1115,7 @@ void journal_destroy (journal_t *journal - /* Force any old transactions to disk */ - lock_journal(journal); - while (journal->j_checkpoint_transactions != NULL) -- log_do_checkpoint(journal, 1); -+ log_do_checkpoint(journal); - - J_ASSERT(journal->j_running_transaction == NULL); - J_ASSERT(journal->j_committing_transaction == NULL); -@@ -1302,7 +1302,7 @@ int journal_flush (journal_t *journal) - /* ...and flush everything in the log out to disk. */ - lock_journal(journal); - while (!err && journal->j_checkpoint_transactions != NULL) -- err = log_do_checkpoint(journal, journal->j_maxlen); -+ err = log_do_checkpoint(journal); - cleanup_journal_tail(journal); - - /* Finally, mark the journal as really needing no recovery. ---- linux-2.4.18/fs/jbd/transaction.c~jbd-commit-tricks Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/transaction.c Mon Jul 28 14:03:59 2003 -@@ -182,14 +182,9 @@ repeat_locked: - * Also, this test is inconsitent with the matching one in - * journal_extend(). - */ -- needed = journal->j_max_transaction_buffers; -- if (journal->j_committing_transaction) -- needed += journal->j_committing_transaction-> -- t_outstanding_credits; -- -- if (log_space_left(journal) < needed) { -+ if (log_space_left(journal) < jbd_space_needed(journal)) { - jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); -- log_wait_for_space(journal, needed); -+ log_wait_for_space(journal); - goto repeat_locked; - } - ---- linux-2.4.18/include/linux/jbd.h~jbd-commit-tricks Mon Jul 28 13:52:17 2003 -+++ linux-2.4.18-alexey/include/linux/jbd.h Mon Jul 28 14:03:59 2003 -@@ -740,9 +740,9 @@ extern void journal_brelse_array(stru - extern int log_space_left (journal_t *); /* Called with journal locked */ - extern tid_t log_start_commit (journal_t *, transaction_t *); - extern void log_wait_commit (journal_t *, tid_t); --extern int log_do_checkpoint (journal_t *, int); -+extern int log_do_checkpoint (journal_t *); - --extern void log_wait_for_space(journal_t *, int nblocks); -+extern void log_wait_for_space(journal_t *); - extern void __journal_drop_transaction(journal_t *, transaction_t *); - extern int cleanup_journal_tail(journal_t *); - -@@ -815,6 +815,19 @@ static inline int tid_geq(tid_t x, tid_t - } - - extern int journal_blocks_per_page(struct inode *inode); -+ -+/* -+ * Return the minimum number of blocks which must be free in the journal -+ * before a new transaction may be started. Must be called under j_state_lock. -+ */ -+static inline int jbd_space_needed(journal_t *journal) -+{ -+ int nblocks = journal->j_max_transaction_buffers; -+ if (journal->j_committing_transaction) -+ nblocks += journal->j_committing_transaction-> -+ t_outstanding_credits; -+ return nblocks; -+} - - /* - * Definitions which augment the buffer_head layer - -_ diff --git a/lustre/kernel_patches/patches/jbd-ctx_switch.patch b/lustre/kernel_patches/patches/jbd-ctx_switch.patch deleted file mode 100644 index 8d4607f..0000000 --- a/lustre/kernel_patches/patches/jbd-ctx_switch.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -rup linux-2.4.20-uml/fs/jbd/transaction.c linux-2.4.21-rc2/fs/jbd/transaction.c ---- linux-2.4.20-uml/fs/jbd/transaction.c Thu Nov 28 16:53:15 2002 -+++ linux-2.4.21-rc2/fs/jbd/transaction.c Fri May 16 11:00:40 2003 -@@ -666,7 +673,8 @@ repeat: - spin_unlock(&journal_datalist_lock); - unlock_journal(journal); - /* commit wakes up all shadow buffers after IO */ -- sleep_on(&jh2bh(jh)->b_wait); -+ wait_event(jh2bh(jh)->b_wait, -+ jh->b_jlist != BJ_Shadow); - lock_journal(journal); - goto repeat; - } diff --git a/lustre/kernel_patches/patches/jbd-dont-account-blocks-twice.patch b/lustre/kernel_patches/patches/jbd-dont-account-blocks-twice.patch deleted file mode 100644 index d1be6f02..0000000 --- a/lustre/kernel_patches/patches/jbd-dont-account-blocks-twice.patch +++ /dev/null @@ -1,17 +0,0 @@ - ---- linux-2.4.18/fs/jbd/commit.c~jbd-dont-account-blocks-twice Mon Jul 28 13:52:05 2003 -+++ linux-2.4.18-alexey/fs/jbd/commit.c Mon Jul 28 14:03:53 2003 -@@ -407,6 +407,11 @@ sync_datalist_empty: - continue; - } - -+ /* start_this_handle() accounts t_outstanding_credits -+ * to know free space in log, but this counter is changed -+ * by journal_next_log_block() also. */ -+ commit_transaction->t_outstanding_credits--; -+ - /* Bump b_count to prevent truncate from stumbling over - the shadowed buffer! @@@ This can go if we ever get - rid of the BJ_IO/BJ_Shadow pairing of buffers. */ - -_ diff --git a/lustre/kernel_patches/patches/jbd-flushtime.patch b/lustre/kernel_patches/patches/jbd-flushtime.patch deleted file mode 100644 index 938c142..0000000 --- a/lustre/kernel_patches/patches/jbd-flushtime.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff -rup linux-2.4.20-uml/fs/jbd/transaction.c linux-2.4.21-rc2/fs/jbd/transaction.c ---- linux-2.4.20-uml/fs/jbd/transaction.c Thu Nov 28 16:53:15 2002 -+++ linux-2.4.21-rc2/fs/jbd/transaction.c Fri May 16 11:00:40 2003 -@@ -1109,7 +1142,6 @@ int journal_dirty_metadata (handle_t *ha - - spin_lock(&journal_datalist_lock); - set_bit(BH_JBDDirty, &bh->b_state); -- set_buffer_flushtime(bh); - - J_ASSERT_JH(jh, jh->b_transaction != NULL); - -@@ -2035,6 +2093,13 @@ void journal_file_buffer(struct journal_ - spin_unlock(&journal_datalist_lock); - } - -+static void jbd_refile_buffer(struct buffer_head *bh) -+{ -+ if (buffer_dirty(bh) && (bh->b_list != BUF_DIRTY)) -+ set_buffer_flushtime(bh); -+ refile_buffer(bh); -+} -+ - /* - * Remove a buffer from its current buffer list in preparation for - * dropping it from its current transaction entirely. If the buffer has -@@ -2055,7 +2120,7 @@ void __journal_refile_buffer(struct jour - __journal_unfile_buffer(jh); - jh->b_transaction = NULL; - /* Onto BUF_DIRTY for writeback */ -- refile_buffer(jh2bh(jh)); -+ jbd_refile_buffer(jh2bh(jh)); - return; - } - diff --git a/lustre/kernel_patches/patches/jbd-get_write_access.patch b/lustre/kernel_patches/patches/jbd-get_write_access.patch deleted file mode 100644 index ea569dc..0000000 --- a/lustre/kernel_patches/patches/jbd-get_write_access.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff -rup linux-2.4.20-uml/fs/jbd/transaction.c linux-2.4.21-rc2/fs/jbd/transaction.c ---- linux-2.4.20-uml/fs/jbd/transaction.c Thu Nov 28 16:53:15 2002 -+++ linux-2.4.21-rc2/fs/jbd/transaction.c Fri May 16 11:00:40 2003 -@@ -735,7 +743,8 @@ done_locked: - int offset; - char *source; - -- J_ASSERT_JH(jh, buffer_uptodate(jh2bh(jh))); -+ J_EXPECT_JH(jh, buffer_uptodate(jh2bh(jh)), -+ "Possible IO failure.\n"); - page = jh2bh(jh)->b_page; - offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK; - source = kmap(page); -diff -rup linux-2.4.20-uml/include/linux/jbd.h linux-2.4.21-rc2/include/linux/jbd.h ---- linux-2.4.20-uml/include/linux/jbd.h Mon Aug 25 16:16:57 2003 -+++ linux-2.4.21-rc2/include/linux/jbd.h Tue May 13 13:28:29 2003 -@@ -40,6 +40,15 @@ - */ - #undef JBD_PARANOID_WRITES - -+/* -+ * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds -+ * certain classes of error which can occur due to failed IOs. Under -+ * normal use we want ext3 to continue after such errors, because -+ * hardware _can_ fail, but for debugging purposes when running tests on -+ * known-good hardware we may want to trap these errors. -+ */ -+#undef JBD_PARANOID_IOFAIL -+ - #ifdef CONFIG_JBD_DEBUG - /* - * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal -@@ -232,6 +272,23 @@ void buffer_assertion_failure(struct buf - #define J_ASSERT(assert) do { } while (0) - #endif /* JBD_ASSERTIONS */ - -+#if defined(JBD_PARANOID_IOFAIL) -+#define J_EXPECT(expr, why...) J_ASSERT(expr) -+#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr) -+#define J_EXPECT_JH(jh, expr, why...) J_ASSERT_JH(jh, expr) -+#else -+#define __journal_expect(expr, why...) \ -+ do { \ -+ if (!(expr)) { \ -+ printk(KERN_ERR "EXT3-fs unexpected failure: %s;\n", # expr); \ -+ printk(KERN_ERR why); \ -+ } \ -+ } while (0) -+#define J_EXPECT(expr, why...) __journal_expect(expr, ## why) -+#define J_EXPECT_BH(bh, expr, why...) __journal_expect(expr, ## why) -+#define J_EXPECT_JH(jh, expr, why...) __journal_expect(expr, ## why) -+#endif -+ - enum jbd_state_bits { - BH_JWrite - = BH_PrivateStart, /* 1 if being written to log (@@@ DEBUGGING) */ diff --git a/lustre/kernel_patches/patches/kallsyms-2.4.29.patch b/lustre/kernel_patches/patches/kallsyms-2.4.29.patch deleted file mode 100644 index d270aa4..0000000 --- a/lustre/kernel_patches/patches/kallsyms-2.4.29.patch +++ /dev/null @@ -1,689 +0,0 @@ -Index: linux-2.4.29/arch/arm/vmlinux-armo.lds.in -=================================================================== ---- linux-2.4.29.orig/arch/arm/vmlinux-armo.lds.in 2005-05-08 23:06:26.916055656 +0300 -+++ linux-2.4.29/arch/arm/vmlinux-armo.lds.in 2005-05-08 23:07:11.214321296 +0300 -@@ -62,6 +62,10 @@ - *(__ksymtab) - __stop___ksymtab = .; - -+ __start___kallsyms = .; /* All kernel symbols */ -+ *(__kallsyms) -+ __stop___kallsyms = .; -+ - *(.got) /* Global offset table */ - - _etext = .; /* End of text section */ -Index: linux-2.4.29/arch/arm/vmlinux-armv.lds.in -=================================================================== ---- linux-2.4.29.orig/arch/arm/vmlinux-armv.lds.in 2005-05-08 23:06:26.917055504 +0300 -+++ linux-2.4.29/arch/arm/vmlinux-armv.lds.in 2005-05-08 23:07:11.215321144 +0300 -@@ -67,6 +67,12 @@ - __stop___ksymtab = .; - } - -+ __kallsyms : { /* Kernel debugging table */ -+ __start___kallsyms = .; /* All kernel symbols */ -+ *(__kallsyms) -+ __stop___kallsyms = .; -+ } -+ - . = ALIGN(8192); - - .data : { -Index: linux-2.4.29/arch/ppc/config.in -=================================================================== ---- linux-2.4.29.orig/arch/ppc/config.in 2005-05-08 23:06:26.933053072 +0300 -+++ linux-2.4.29/arch/ppc/config.in 2005-05-08 23:07:11.216320992 +0300 -@@ -655,6 +655,7 @@ - fi - fi - fi -+bool 'Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS - - if [ "$CONFIG_ALL_PPC" = "y" ]; then - bool 'Support for early boot text console (BootX or OpenFirmware only)' CONFIG_BOOTX_TEXT -Index: linux-2.4.29/arch/ppc/vmlinux.lds -=================================================================== ---- linux-2.4.29.orig/arch/ppc/vmlinux.lds 2005-05-08 23:06:26.934052920 +0300 -+++ linux-2.4.29/arch/ppc/vmlinux.lds 2005-05-08 23:07:11.217320840 +0300 -@@ -74,6 +74,10 @@ - __ksymtab : { *(__ksymtab) } - __stop___ksymtab = .; - -+ __start___kallsyms = .; /* All kernel symbols */ -+ __kallsyms : { *(__kallsyms) } -+ __stop___kallsyms = .; -+ - . = ALIGN(8); - __start___ftr_fixup = .; - __ftr_fixup : { *(__ftr_fixup) } -Index: linux-2.4.29/arch/i386/config.in -=================================================================== ---- linux-2.4.29.orig/arch/i386/config.in 2005-05-08 23:07:09.946514032 +0300 -+++ linux-2.4.29/arch/i386/config.in 2005-05-08 23:33:00.395809912 +0300 -@@ -512,6 +512,7 @@ - bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ - bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK - bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER -+ bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS - fi - - int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0 -Index: linux-2.4.29/arch/ia64/config.in -=================================================================== ---- linux-2.4.29.orig/arch/ia64/config.in 2005-05-08 23:06:26.936052616 +0300 -+++ linux-2.4.29/arch/ia64/config.in 2005-05-08 23:07:11.219320536 +0300 -@@ -318,4 +318,6 @@ - - int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0 - -+bool ' Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS -+ - endmenu -Index: linux-2.4.29/arch/alpha/vmlinux.lds.in -=================================================================== ---- linux-2.4.29.orig/arch/alpha/vmlinux.lds.in 2005-05-08 23:06:26.937052464 +0300 -+++ linux-2.4.29/arch/alpha/vmlinux.lds.in 2005-05-08 23:07:11.220320384 +0300 -@@ -28,6 +28,10 @@ - __stop___ksymtab = .; - .kstrtab : { *(.kstrtab) } - -+ __start___kallsyms = .; /* All kernel symbols */ -+ __kallsyms : { *(__kallsyms) } -+ __stop___kallsyms = .; -+ - /* Startup code */ - . = ALIGN(8192); - __init_begin = .; -Index: linux-2.4.29/Makefile -=================================================================== ---- linux-2.4.29.orig/Makefile 2005-05-08 22:59:19.203077912 +0300 -+++ linux-2.4.29/Makefile 2005-05-08 23:07:11.222320080 +0300 -@@ -37,6 +37,7 @@ - MAKEFILES = $(TOPDIR)/.config - GENKSYMS = /sbin/genksyms - DEPMOD = /sbin/depmod -+KALLSYMS = /sbin/kallsyms - MODFLAGS = -DMODULE - CFLAGS_KERNEL = - PERL = perl -@@ -44,6 +45,8 @@ - RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ - else echo rpm; fi) - -+TMPPREFIX = -+ - export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ - CONFIG_SHELL TOPDIR HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ - CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS MODFLAGS PERL AWK -@@ -202,7 +205,7 @@ - CLEAN_FILES = \ - kernel/ksyms.lst include/linux/compile.h \ - vmlinux System.map \ -- .tmp* \ -+ $(TMPPREFIX).tmp* \ - drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \ - drivers/char/conmakehash \ - drivers/char/drm/*-mod.c \ -@@ -285,16 +288,39 @@ - boot: vmlinux - @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot - -+LD_VMLINUX := $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \ -+ --start-group \ -+ $(CORE_FILES) \ -+ $(DRIVERS) \ -+ $(NETWORKS) \ -+ $(LIBS) \ -+ --end-group -+ifeq ($(CONFIG_KALLSYMS),y) -+LD_VMLINUX_KALLSYMS := $(TMPPREFIX).tmp_kallsyms3.o -+else -+LD_VMLINUX_KALLSYMS := -+endif -+ - vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs -- $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \ -- --start-group \ -- $(CORE_FILES) \ -- $(DRIVERS) \ -- $(NETWORKS) \ -- $(LIBS) \ -- --end-group \ -- -o vmlinux -+ @$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" kallsyms -+ -+.PHONY: kallsyms -+ -+kallsyms: -+ifeq ($(CONFIG_KALLSYMS),y) -+ @echo kallsyms pass 1 -+ $(LD_VMLINUX) -o $(TMPPREFIX).tmp_vmlinux1 -+ @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux1 > $(TMPPREFIX).tmp_kallsyms1.o -+ @echo kallsyms pass 2 -+ @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms1.o -o $(TMPPREFIX).tmp_vmlinux2 -+ @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux2 > $(TMPPREFIX).tmp_kallsyms2.o -+ @echo kallsyms pass 3 -+ @$(LD_VMLINUX) $(TMPPREFIX).tmp_kallsyms2.o -o $(TMPPREFIX).tmp_vmlinux3 -+ @$(KALLSYMS) $(TMPPREFIX).tmp_vmlinux3 > $(TMPPREFIX).tmp_kallsyms3.o -+endif -+ $(LD_VMLINUX) $(LD_VMLINUX_KALLSYMS) -o vmlinux - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map -+ @rm -f $(TMPPREFIX).tmp_vmlinux* $(TMPPREFIX).tmp_kallsyms* - - symlinks: - rm -f include/asm -Index: linux-2.4.29/kernel/Makefile -=================================================================== ---- linux-2.4.29.orig/kernel/Makefile 2005-05-08 23:06:26.939052160 +0300 -+++ linux-2.4.29/kernel/Makefile 2005-05-08 23:07:11.223319928 +0300 -@@ -19,6 +19,7 @@ - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += ksyms.o - obj-$(CONFIG_PM) += pm.o -+obj-$(CONFIG_KALLSYMS) += kallsyms.o - - ifneq ($(CONFIG_IA64),y) - # According to Alan Modra , the -fno-omit-frame-pointer is -Index: linux-2.4.29/kernel/ksyms.c -=================================================================== ---- linux-2.4.29.orig/kernel/ksyms.c 2005-05-08 23:07:10.878372368 +0300 -+++ linux-2.4.29/kernel/ksyms.c 2005-05-08 23:07:11.224319776 +0300 -@@ -59,6 +59,9 @@ - #ifdef CONFIG_KMOD - #include - #endif -+#ifdef CONFIG_KALLSYMS -+#include -+#endif - - extern void set_device_ro(kdev_t dev,int flag); - -@@ -87,6 +90,15 @@ - EXPORT_SYMBOL(inter_module_put); - EXPORT_SYMBOL(try_inc_mod_count); - -+#ifdef CONFIG_KALLSYMS -+extern const char __start___kallsyms[]; -+extern const char __stop___kallsyms[]; -+EXPORT_SYMBOL(__start___kallsyms); -+EXPORT_SYMBOL(__stop___kallsyms); -+ -+ -+#endif -+ - /* process memory management */ - EXPORT_SYMBOL(do_mmap_pgoff); - EXPORT_SYMBOL(do_munmap); -Index: linux-2.4.29/kernel/kallsyms.c -=================================================================== ---- linux-2.4.29.orig/kernel/kallsyms.c 2005-05-08 23:07:11.196324032 +0300 -+++ linux-2.4.29/kernel/kallsyms.c 2005-05-08 23:07:11.226319472 +0300 -@@ -0,0 +1,306 @@ -+/* An example of using kallsyms data in a kernel debugger. -+ -+ Copyright 2000 Keith Owens April 2000 -+ -+ This file is part of the Linux modutils. -+ -+ 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. -+ */ -+ -+#ident "$Id: kallsyms-2.4-bgl.patch,v 1.1.20.1 2005/03/24 22:50:28 jacob Exp $" -+ -+/* -+ This code uses the list of all kernel and module symbols to :- -+ -+ * Find any non-stack symbol in a kernel or module. Symbols do -+ not have to be exported for debugging. -+ -+ * Convert an address to the module (or kernel) that owns it, the -+ section it is in and the nearest symbol. This finds all non-stack -+ symbols, not just exported ones. -+ -+ You need modutils >= 2.3.11 and a kernel with the kallsyms patch -+ which was compiled with CONFIG_KALLSYMS. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* These external symbols are only set on kernels compiled with -+ * CONFIG_KALLSYMS. -+ */ -+ -+extern const char __start___kallsyms[]; -+extern const char __stop___kallsyms[]; -+ -+static struct module **kallsyms_module_list; -+ -+static void kallsyms_get_module_list(void) -+{ -+ const struct kallsyms_header *ka_hdr; -+ const struct kallsyms_section *ka_sec; -+ const struct kallsyms_symbol *ka_sym; -+ const char *ka_str; -+ int i; -+ const char *p; -+ -+ if (__start___kallsyms >= __stop___kallsyms) -+ return; -+ ka_hdr = (struct kallsyms_header *)__start___kallsyms; -+ ka_sec = (struct kallsyms_section *) -+ ((char *)(ka_hdr) + ka_hdr->section_off); -+ ka_sym = (struct kallsyms_symbol *) -+ ((char *)(ka_hdr) + ka_hdr->symbol_off); -+ ka_str = -+ ((char *)(ka_hdr) + ka_hdr->string_off); -+ -+ for (i = 0; i < ka_hdr->symbols; kallsyms_next_sym(ka_hdr, ka_sym), ++i) { -+ p = ka_str + ka_sym->name_off; -+ if (strcmp(p, "module_list") == 0) { -+ if (ka_sym->symbol_addr) -+ kallsyms_module_list = (struct module **)(ka_sym->symbol_addr); -+ break; -+ } -+ } -+} -+ -+static inline void kallsyms_do_first_time(void) -+{ -+ static int first_time = 1; -+ if (first_time) -+ kallsyms_get_module_list(); -+ first_time = 0; -+} -+ -+/* A symbol can appear in more than one module. A token is used to -+ * restart the scan at the next module, set the token to 0 for the -+ * first scan of each symbol. -+ */ -+ -+int kallsyms_symbol_to_address( -+ const char *name, /* Name to lookup */ -+ unsigned long *token, /* Which module to start at */ -+ const char **mod_name, /* Set to module name */ -+ unsigned long *mod_start, /* Set to start address of module */ -+ unsigned long *mod_end, /* Set to end address of module */ -+ const char **sec_name, /* Set to section name */ -+ unsigned long *sec_start, /* Set to start address of section */ -+ unsigned long *sec_end, /* Set to end address of section */ -+ const char **sym_name, /* Set to full symbol name */ -+ unsigned long *sym_start, /* Set to start address of symbol */ -+ unsigned long *sym_end /* Set to end address of symbol */ -+ ) -+{ -+ const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ -+ const struct kallsyms_section *ka_sec; -+ const struct kallsyms_symbol *ka_sym = NULL; -+ const char *ka_str = NULL; -+ const struct module *m; -+ int i = 0, l; -+ const char *p, *pt_R; -+ char *p2; -+ -+ kallsyms_do_first_time(); -+ if (!kallsyms_module_list) -+ return(0); -+ -+ /* Restart? */ -+ m = *kallsyms_module_list; -+ if (token && *token) { -+ for (; m; m = m->next) -+ if ((unsigned long)m == *token) -+ break; -+ if (m) -+ m = m->next; -+ } -+ -+ for (; m; m = m->next) { -+ if (!mod_member_present(m, kallsyms_start) || -+ !mod_member_present(m, kallsyms_end) || -+ m->kallsyms_start >= m->kallsyms_end) -+ continue; -+ ka_hdr = (struct kallsyms_header *)m->kallsyms_start; -+ ka_sym = (struct kallsyms_symbol *) -+ ((char *)(ka_hdr) + ka_hdr->symbol_off); -+ ka_str = -+ ((char *)(ka_hdr) + ka_hdr->string_off); -+ for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) { -+ p = ka_str + ka_sym->name_off; -+ if (strcmp(p, name) == 0) -+ break; -+ /* Unversioned requests match versioned names */ -+ if (!(pt_R = strstr(p, "_R"))) -+ continue; -+ l = strlen(pt_R); -+ if (l < 10) -+ continue; /* Not _R.*xxxxxxxx */ -+ (void)simple_strtoul(pt_R+l-8, &p2, 16); -+ if (*p2) -+ continue; /* Not _R.*xxxxxxxx */ -+ if (strncmp(p, name, pt_R-p) == 0) -+ break; /* Match with version */ -+ } -+ if (i < ka_hdr->symbols) -+ break; -+ } -+ -+ if (token) -+ *token = (unsigned long)m; -+ if (!m) -+ return(0); /* not found */ -+ -+ ka_sec = (const struct kallsyms_section *) -+ ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off); -+ *mod_name = *(m->name) ? m->name : "kernel"; -+ *mod_start = ka_hdr->start; -+ *mod_end = ka_hdr->end; -+ *sec_name = ka_sec->name_off + ka_str; -+ *sec_start = ka_sec->start; -+ *sec_end = ka_sec->start + ka_sec->size; -+ *sym_name = ka_sym->name_off + ka_str; -+ *sym_start = ka_sym->symbol_addr; -+ if (i < ka_hdr->symbols-1) { -+ const struct kallsyms_symbol *ka_symn = ka_sym; -+ kallsyms_next_sym(ka_hdr, ka_symn); -+ *sym_end = ka_symn->symbol_addr; -+ } -+ else -+ *sym_end = *sec_end; -+ return(1); -+} -+ -+int kallsyms_address_to_symbol( -+ unsigned long address, /* Address to lookup */ -+ const char **mod_name, /* Set to module name */ -+ unsigned long *mod_start, /* Set to start address of module */ -+ unsigned long *mod_end, /* Set to end address of module */ -+ const char **sec_name, /* Set to section name */ -+ unsigned long *sec_start, /* Set to start address of section */ -+ unsigned long *sec_end, /* Set to end address of section */ -+ const char **sym_name, /* Set to full symbol name */ -+ unsigned long *sym_start, /* Set to start address of symbol */ -+ unsigned long *sym_end /* Set to end address of symbol */ -+ ) -+{ -+ const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ -+ const struct kallsyms_section *ka_sec = NULL; -+ const struct kallsyms_symbol *ka_sym; -+ const char *ka_str; -+ const struct module *m; -+ int i; -+ unsigned long end; -+ -+ kallsyms_do_first_time(); -+ if (!kallsyms_module_list) -+ return(0); -+ -+ for (m = *kallsyms_module_list; m; m = m->next) { -+ if (!mod_member_present(m, kallsyms_start) || -+ !mod_member_present(m, kallsyms_end) || -+ m->kallsyms_start >= m->kallsyms_end) -+ continue; -+ ka_hdr = (struct kallsyms_header *)m->kallsyms_start; -+ ka_sec = (const struct kallsyms_section *) -+ ((char *)ka_hdr + ka_hdr->section_off); -+ /* Is the address in any section in this module? */ -+ for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) { -+ if (ka_sec->start <= address && -+ (ka_sec->start + ka_sec->size) > address) -+ break; -+ } -+ if (i < ka_hdr->sections) -+ break; /* Found a matching section */ -+ } -+ -+ if (!m) -+ return(0); /* not found */ -+ -+ ka_sym = (struct kallsyms_symbol *) -+ ((char *)(ka_hdr) + ka_hdr->symbol_off); -+ ka_str = -+ ((char *)(ka_hdr) + ka_hdr->string_off); -+ *mod_name = *(m->name) ? m->name : "kernel"; -+ *mod_start = ka_hdr->start; -+ *mod_end = ka_hdr->end; -+ *sec_name = ka_sec->name_off + ka_str; -+ *sec_start = ka_sec->start; -+ *sec_end = ka_sec->start + ka_sec->size; -+ *sym_name = *sec_name; /* In case we find no matching symbol */ -+ *sym_start = *sec_start; -+ *sym_end = *sec_end; -+ -+ for (i = 0; i < ka_hdr->symbols; ++i, kallsyms_next_sym(ka_hdr, ka_sym)) { -+ if (ka_sym->symbol_addr > address) -+ continue; -+ if (i < ka_hdr->symbols-1) { -+ const struct kallsyms_symbol *ka_symn = ka_sym; -+ kallsyms_next_sym(ka_hdr, ka_symn); -+ end = ka_symn->symbol_addr; -+ } -+ else -+ end = *sec_end; -+ if (end <= address) -+ continue; -+ if ((char *)ka_hdr + ka_hdr->section_off + ka_sym->section_off -+ != (char *)ka_sec) -+ continue; /* wrong section */ -+ *sym_name = ka_str + ka_sym->name_off; -+ *sym_start = ka_sym->symbol_addr; -+ *sym_end = end; -+ break; -+ } -+ return(1); -+} -+ -+/* List all sections in all modules. The callback routine is invoked with -+ * token, module name, section name, section start, section end, section flags. -+ */ -+int kallsyms_sections(void *token, -+ int (*callback)(void *, const char *, const char *, ElfW(Addr), ElfW(Addr), ElfW(Word))) -+{ -+ const struct kallsyms_header *ka_hdr = NULL; /* stupid gcc */ -+ const struct kallsyms_section *ka_sec = NULL; -+ const char *ka_str; -+ const struct module *m; -+ int i; -+ -+ kallsyms_do_first_time(); -+ if (!kallsyms_module_list) -+ return(0); -+ -+ for (m = *kallsyms_module_list; m; m = m->next) { -+ if (!mod_member_present(m, kallsyms_start) || -+ !mod_member_present(m, kallsyms_end) || -+ m->kallsyms_start >= m->kallsyms_end) -+ continue; -+ ka_hdr = (struct kallsyms_header *)m->kallsyms_start; -+ ka_sec = (const struct kallsyms_section *) ((char *)ka_hdr + ka_hdr->section_off); -+ ka_str = ((char *)(ka_hdr) + ka_hdr->string_off); -+ for (i = 0; i < ka_hdr->sections; ++i, kallsyms_next_sec(ka_hdr, ka_sec)) { -+ if (callback( -+ token, -+ *(m->name) ? m->name : "kernel", -+ ka_sec->name_off + ka_str, -+ ka_sec->start, -+ ka_sec->start + ka_sec->size, -+ ka_sec->flags)) -+ return(0); -+ } -+ } -+ return(1); -+} -Index: linux-2.4.29/include/linux/kallsyms.h -=================================================================== ---- linux-2.4.29.orig/include/linux/kallsyms.h 2005-05-08 23:07:11.196324032 +0300 -+++ linux-2.4.29/include/linux/kallsyms.h 2005-05-08 23:08:04.316248576 +0300 -@@ -0,0 +1,141 @@ -+/* kallsyms headers -+ Copyright 2000 Keith Owens -+ -+ This file is part of the Linux modutils. It is exported to kernel -+ space so debuggers can access the kallsyms data. -+ -+ The kallsyms data contains all the non-stack symbols from a kernel -+ or a module. The kernel symbols are held between __start___kallsyms -+ and __stop___kallsyms. The symbols for a module are accessed via -+ the struct module chain which is based at module_list. -+ -+ 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. -+ */ -+ -+#ident "$Id: kallsyms-2.4-bgl.patch,v 1.1.20.1 2005/03/24 22:50:28 jacob Exp $" -+ -+#ifndef MODUTILS_KALLSYMS_H -+#define MODUTILS_KALLSYMS_H 1 -+ -+/* Have to (re)define these ElfW entries here because external kallsyms -+ * code does not have access to modutils/include/obj.h. This code is -+ * included from user spaces tools (modutils) and kernel, they need -+ * different includes. -+ */ -+ -+#ifndef ELFCLASS32 -+#ifdef __KERNEL__ -+#include -+#else /* __KERNEL__ */ -+#include -+#endif /* __KERNEL__ */ -+#endif /* ELFCLASS32 */ -+ -+#ifndef ELFCLASSM -+#define ELFCLASSM ELF_CLASS -+#endif -+ -+#ifndef ElfW -+# if ELFCLASSM == ELFCLASS32 -+# define ElfW(x) Elf32_ ## x -+# define ELFW(x) ELF32_ ## x -+# else -+# define ElfW(x) Elf64_ ## x -+# define ELFW(x) ELF64_ ## x -+# endif -+#endif -+ -+/* Format of data in the kallsyms section. -+ * Most of the fields are small numbers but the total size and all -+ * offsets can be large so use the 32/64 bit types for these fields. -+ * -+ * Do not use sizeof() on these structures, modutils may be using extra -+ * fields. Instead use the size fields in the header to access the -+ * other bits of data. -+ */ -+ -+struct kallsyms_header { -+ int size; /* Size of this header */ -+ ElfW(Word) total_size; /* Total size of kallsyms data */ -+ int sections; /* Number of section entries */ -+ ElfW(Off) section_off; /* Offset to first section entry */ -+ int section_size; /* Size of one section entry */ -+ int symbols; /* Number of symbol entries */ -+ ElfW(Off) symbol_off; /* Offset to first symbol entry */ -+ int symbol_size; /* Size of one symbol entry */ -+ ElfW(Off) string_off; /* Offset to first string */ -+ ElfW(Addr) start; /* Start address of first section */ -+ ElfW(Addr) end; /* End address of last section */ -+}; -+ -+struct kallsyms_section { -+ ElfW(Addr) start; /* Start address of section */ -+ ElfW(Word) size; /* Size of this section */ -+ ElfW(Off) name_off; /* Offset to section name */ -+ ElfW(Word) flags; /* Flags from section */ -+}; -+ -+struct kallsyms_symbol { -+ ElfW(Off) section_off; /* Offset to section that owns this symbol */ -+ ElfW(Addr) symbol_addr; /* Address of symbol */ -+ ElfW(Off) name_off; /* Offset to symbol name */ -+}; -+ -+#define KALLSYMS_SEC_NAME "__kallsyms" -+#define KALLSYMS_IDX 2 /* obj_kallsyms creates kallsyms as section 2 */ -+ -+#define kallsyms_next_sec(h,s) \ -+ ((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size)) -+#define kallsyms_next_sym(h,s) \ -+ ((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size)) -+ -+int kallsyms_symbol_to_address( -+ const char *name, /* Name to lookup */ -+ unsigned long *token, /* Which module to start with */ -+ const char **mod_name, /* Set to module name or "kernel" */ -+ unsigned long *mod_start, /* Set to start address of module */ -+ unsigned long *mod_end, /* Set to end address of module */ -+ const char **sec_name, /* Set to section name */ -+ unsigned long *sec_start, /* Set to start address of section */ -+ unsigned long *sec_end, /* Set to end address of section */ -+ const char **sym_name, /* Set to full symbol name */ -+ unsigned long *sym_start, /* Set to start address of symbol */ -+ unsigned long *sym_end /* Set to end address of symbol */ -+ ); -+ -+int kallsyms_address_to_symbol( -+ unsigned long address, /* Address to lookup */ -+ const char **mod_name, /* Set to module name */ -+ unsigned long *mod_start, /* Set to start address of module */ -+ unsigned long *mod_end, /* Set to end address of module */ -+ const char **sec_name, /* Set to section name */ -+ unsigned long *sec_start, /* Set to start address of section */ -+ unsigned long *sec_end, /* Set to end address of section */ -+ const char **sym_name, /* Set to full symbol name */ -+ unsigned long *sym_start, /* Set to start address of symbol */ -+ unsigned long *sym_end /* Set to end address of symbol */ -+ ); -+ -+int kallsyms_sections(void *token, -+ int (*callback)(void *, /* token */ -+ const char *, /* module name */ -+ const char *, /* section name */ -+ ElfW(Addr), /* Section start */ -+ ElfW(Addr), /* Section end */ -+ ElfW(Word) /* Section flags */ -+ ) -+ ); -+ -+#endif /* kallsyms.h */ -Index: linux-2.4.29/arch/i386/vmlinux.lds.S -=================================================================== ---- linux-2.4.29.orig/arch/i386/vmlinux.lds.S 2005-05-08 23:07:09.948513728 +0300 -+++ linux-2.4.29/arch/i386/vmlinux.lds.S 2005-05-08 23:14:24.128508336 +0300 -@@ -28,6 +28,10 @@ - __ksymtab : { *(__ksymtab) } - __stop___ksymtab = .; - -+ __start___kallsyms = .; /* All kernel symbols */ -+ __kallsyms : { *(__kallsyms) } -+ __stop___kallsyms = .; -+ - .data : { /* Data */ - *(.data) - CONSTRUCTORS diff --git a/lustre/kernel_patches/patches/linux-2.4.20-xattr-0.8.54-hp.patch b/lustre/kernel_patches/patches/linux-2.4.20-xattr-0.8.54-hp.patch deleted file mode 100644 index 3c156e8..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.20-xattr-0.8.54-hp.patch +++ /dev/null @@ -1,4875 +0,0 @@ - Documentation/Configure.help | 66 ++ - arch/ia64/defconfig | 7 - fs/Config.in | 14 - fs/Makefile | 3 - fs/ext2/Makefile | 4 - fs/ext2/file.c | 5 - fs/ext2/ialloc.c | 2 - fs/ext2/inode.c | 34 - - fs/ext2/namei.c | 14 - fs/ext2/super.c | 29 - fs/ext2/symlink.c | 14 - fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++ - fs/ext2/xattr_user.c | 103 +++ - fs/ext3/Makefile | 9 - fs/ext3/ext3-exports.c | 13 - fs/ext3/file.c | 5 - fs/ext3/ialloc.c | 2 - fs/ext3/inode.c | 35 - - fs/ext3/namei.c | 21 - fs/ext3/super.c | 36 + - fs/ext3/symlink.c | 14 - fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++ - fs/ext3/xattr_user.c | 111 +++ - fs/jfs/jfs_xattr.h | 6 - fs/jfs/xattr.c | 6 - fs/mbcache.c | 648 ++++++++++++++++++++++ - include/linux/cache_def.h | 15 - include/linux/errno.h | 4 - include/linux/ext2_fs.h | 31 - - include/linux/ext2_xattr.h | 157 +++++ - include/linux/ext3_fs.h | 31 - - include/linux/ext3_jbd.h | 8 - include/linux/ext3_xattr.h | 157 +++++ - include/linux/fs.h | 2 - include/linux/mbcache.h | 69 ++ - kernel/ksyms.c | 4 - mm/vmscan.c | 35 + - 62 files changed, 4343 insertions(+), 182 deletions(-) - ---- linux/Documentation/Configure.help~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:23 2003 -+++ linux-mmonroe/Documentation/Configure.help Fri May 16 08:43:00 2003 -@@ -15309,6 +15309,39 @@ CONFIG_EXT2_FS - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. - -+Ext2 extended attributes -+CONFIG_EXT2_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext2 extended attribute block sharing -+CONFIG_EXT2_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext2 extended user attributes -+CONFIG_EXT2_FS_XATTR_USER -+ This option enables extended user attributes on ext2. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext2 trusted extended attributes -+CONFIG_EXT2_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext2 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Ext3 journalling file system support (EXPERIMENTAL) - CONFIG_EXT3_FS - This is the journalling version of the Second extended file system -@@ -15341,6 +15374,39 @@ CONFIG_EXT3_FS - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this may be dangerous. - -+Ext3 extended attributes -+CONFIG_EXT3_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext3 extended attribute block sharing -+CONFIG_EXT3_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext3 extended user attributes -+CONFIG_EXT3_FS_XATTR_USER -+ This option enables extended user attributes on ext3. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext3 trusted extended attributes -+CONFIG_EXT3_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext3 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Journal Block Device support (JBD for ext3) (EXPERIMENTAL) - CONFIG_JBD - This is a generic journalling layer for block devices. It is ---- linux/arch/ia64/defconfig~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003 -+++ linux-mmonroe/arch/ia64/defconfig Fri May 16 08:43:00 2003 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - - # - # Code maturity level options ---- linux/fs/Config.in~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:14 2003 -+++ linux-mmonroe/fs/Config.in Fri May 16 08:43:01 2003 -@@ -35,6 +35,11 @@ dep_mbool ' Debug Befs' CONFIG_BEFS_DEB - dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL - - tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS -+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS -+dep_bool ' Ext3 extended attribute block sharing' \ -+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR -+dep_bool ' Ext3 extended user attributes' \ -+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR - # CONFIG_JBD could be its own option (even modular), but until there are - # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS - # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS -@@ -98,6 +103,11 @@ dep_mbool ' QNX4FS write support (DANGE - tristate 'ROM file system support' CONFIG_ROMFS_FS - - tristate 'Second extended fs support' CONFIG_EXT2_FS -+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS -+dep_bool ' Ext2 extended attribute block sharing' \ -+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR -+dep_bool ' Ext2 extended user attributes' \ -+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR - - tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS - -@@ -176,6 +186,10 @@ else - define_tristate CONFIG_ZISOFS_FS n - fi - -+# Meta block cache for Extended Attributes (ext2/ext3) -+#tristate 'Meta block cache' CONFIG_FS_MBCACHE -+define_tristate CONFIG_FS_MBCACHE y -+ - mainmenu_option next_comment - comment 'Partition Types' - source fs/partitions/Config.in ---- linux/fs/Makefile~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003 -+++ linux-mmonroe/fs/Makefile Fri May 16 08:43:01 2003 -@@ -80,6 +80,9 @@ obj-y += binfmt_script.o - - obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o - -+export-objs += mbcache.o -+obj-$(CONFIG_FS_MBCACHE) += mbcache.o -+ - # persistent filesystems - obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) - ---- linux/fs/ext2/Makefile~linux-2.4.20-xattr-0.8.54-hp Thu Oct 11 08:05:18 2001 -+++ linux-mmonroe/fs/ext2/Makefile Fri May 16 08:43:01 2003 -@@ -13,4 +13,8 @@ obj-y := balloc.o bitmap.o dir.o file - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) - -+export-objs += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make ---- linux/fs/ext2/file.c~linux-2.4.20-xattr-0.8.54-hp Thu Oct 11 08:05:18 2001 -+++ linux-mmonroe/fs/ext2/file.c Fri May 16 08:43:01 2003 -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - - /* -@@ -51,4 +52,8 @@ struct file_operations ext2_file_operati - - struct inode_operations ext2_file_inode_operations = { - truncate: ext2_truncate, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; ---- linux/fs/ext2/ialloc.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/ext2/ialloc.c Fri May 16 08:43:01 2003 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -167,6 +168,7 @@ void ext2_free_inode (struct inode * ino - */ - if (!is_bad_inode(inode)) { - /* Quota is already initialized in iput() */ -+ ext2_xattr_delete_inode(inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - } ---- linux/fs/ext2/inode.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/ext2/inode.c Fri May 16 08:43:01 2003 -@@ -39,6 +39,18 @@ MODULE_LICENSE("GPL"); - static int ext2_update_inode(struct inode * inode, int do_sync); - - /* -+ * Test whether an inode is a fast symlink. -+ */ -+static inline int ext2_inode_is_fast_symlink(struct inode *inode) -+{ -+ int ea_blocks = inode->u.ext2_i.i_file_acl ? -+ (inode->i_sb->s_blocksize >> 9) : 0; -+ -+ return (S_ISLNK(inode->i_mode) && -+ inode->i_blocks - ea_blocks == 0); -+} -+ -+/* - * Called at each iput() - */ - void ext2_put_inode (struct inode * inode) -@@ -53,9 +65,7 @@ void ext2_delete_inode (struct inode * i - { - lock_kernel(); - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - inode->u.ext2_i.i_dtime = CURRENT_TIME; - mark_inode_dirty(inode); -@@ -801,6 +811,8 @@ void ext2_truncate (struct inode * inode - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; -+ if (ext2_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -888,8 +900,7 @@ void ext2_read_inode (struct inode * ino - unsigned long offset; - struct ext2_group_desc * gdp; - -- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO && -- inode->i_ino != EXT2_ACL_DATA_INO && -+ if ((inode->i_ino != EXT2_ROOT_INO && - inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) { - ext2_error (inode->i_sb, "ext2_read_inode", -@@ -974,10 +985,7 @@ void ext2_read_inode (struct inode * ino - for (block = 0; block < EXT2_N_BLOCKS; block++) - inode->u.ext2_i.i_data[block] = raw_inode->i_block[block]; - -- if (inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext2_file_inode_operations; - inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; -@@ -986,15 +994,17 @@ void ext2_read_inode (struct inode * ino - inode->i_fop = &ext2_dir_operations; - inode->i_mapping->a_ops = &ext2_aops; - } else if (S_ISLNK(inode->i_mode)) { -- if (!inode->i_blocks) -+ if (ext2_inode_is_fast_symlink(inode)) - inode->i_op = &ext2_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - } -- } else -+ } else { -+ inode->i_op = &ext2_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); -+ } - brelse (bh); - inode->i_attr_flags = 0; - if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) { ---- linux/fs/ext2/namei.c~linux-2.4.20-xattr-0.8.54-hp Wed Oct 3 22:57:36 2001 -+++ linux-mmonroe/fs/ext2/namei.c Fri May 16 08:43:01 2003 -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - - /* -@@ -136,7 +137,7 @@ static int ext2_symlink (struct inode * - - if (l > sizeof (inode->u.ext2_i.i_data)) { - /* slow symlink */ -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); - if (err) -@@ -345,4 +346,15 @@ struct inode_operations ext2_dir_inode_o - rmdir: ext2_rmdir, - mknod: ext2_mknod, - rename: ext2_rename, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ -+struct inode_operations ext2_special_inode_operations = { -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; ---- linux/fs/ext2/super.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/ext2/super.c Fri May 16 08:43:01 2003 -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -125,6 +126,7 @@ void ext2_put_super (struct super_block - int db_count; - int i; - -+ ext2_xattr_put_super(sb); - if (!(sb->s_flags & MS_RDONLY)) { - struct ext2_super_block *es = EXT2_SB(sb)->s_es; - -@@ -175,6 +177,13 @@ static int parse_options (char * options - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -424,6 +433,9 @@ struct super_block * ext2_read_super (st - blocksize = BLOCK_SIZE; - - sb->u.ext2_sb.s_mount_opt = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */ -+#endif - if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, - &sb->u.ext2_sb.s_mount_opt)) { - return NULL; -@@ -813,12 +825,27 @@ static DECLARE_FSTYPE_DEV(ext2_fs_type, - - static int __init init_ext2_fs(void) - { -- return register_filesystem(&ext2_fs_type); -+ int error = init_ext2_xattr(); -+ if (error) -+ return error; -+ error = init_ext2_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext2_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext2_xattr_user(); -+fail: -+ exit_ext2_xattr(); -+ return error; - } - - static void __exit exit_ext2_fs(void) - { - unregister_filesystem(&ext2_fs_type); -+ exit_ext2_xattr_user(); -+ exit_ext2_xattr(); - } - - EXPORT_NO_SYMBOLS; ---- linux/fs/ext2/symlink.c~linux-2.4.20-xattr-0.8.54-hp Wed Sep 27 13:41:33 2000 -+++ linux-mmonroe/fs/ext2/symlink.c Fri May 16 08:43:01 2003 -@@ -19,6 +19,7 @@ - - #include - #include -+#include - - static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -32,7 +33,20 @@ static int ext2_follow_link(struct dentr - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext2_symlink_inode_operations = { -+ readlink: page_readlink, -+ follow_link: page_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ - struct inode_operations ext2_fast_symlink_inode_operations = { - readlink: ext2_readlink, - follow_link: ext2_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/fs/ext2/xattr.c Fri May 16 08:43:01 2003 -@@ -0,0 +1,1212 @@ -+/* -+ * linux/fs/ext2/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT2_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT2_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext2_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* These symbols may be needed by a module. */ -+EXPORT_SYMBOL(ext2_xattr_register); -+EXPORT_SYMBOL(ext2_xattr_unregister); -+EXPORT_SYMBOL(ext2_xattr_get); -+EXPORT_SYMBOL(ext2_xattr_list); -+EXPORT_SYMBOL(ext2_xattr_set); -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT2_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext2_xattr_set2(struct inode *, struct buffer_head *, -+ struct ext2_xattr_header *); -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+static int ext2_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext2_xattr_cache_find(struct inode *, -+ struct ext2_xattr_header *); -+static void ext2_xattr_cache_remove(struct buffer_head *); -+static void ext2_xattr_rehash(struct ext2_xattr_header *, -+ struct ext2_xattr_entry *); -+ -+static struct mb_cache *ext2_xattr_cache; -+ -+#else -+# define ext2_xattr_cache_insert(bh) 0 -+# define ext2_xattr_cache_find(inode, header) NULL -+# define ext2_xattr_cache_remove(bh) while(0) {} -+# define ext2_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext2_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext2_xattr_sem); -+ -+static inline int -+ext2_xattr_new_block(struct inode *inode, int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) + -+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext2_new_block(inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext2_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext2_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext2_xattr_free_block(struct inode * inode, unsigned long block) -+{ -+ ext2_free_blocks(inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext2_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext2_xattr_free_block(inode, block) \ -+ ext2_free_blocks(inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX]; -+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ if (!ext2_xattr_handlers[name_index-1]) { -+ ext2_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext2_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler) -+{ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ ext2_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext2_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static struct ext2_xattr_handler * -+ext2_xattr_resolve_name(const char **name) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext2_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext2_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext2_handler_lock); -+ return handler; -+} -+ -+static inline struct ext2_xattr_handler * -+ext2_xattr_handler(int name_index) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ read_lock(&ext2_handler_lock); -+ handler = ext2_xattr_handlers[name_index-1]; -+ read_unlock(&ext2_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext2_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext2_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT2_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT2_I(inode)->i_file_acl) -+ return 0; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext2_xattr_update_super_block(struct super_block *sb) -+{ -+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT2_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext2_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_header *header = NULL; -+ struct ext2_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT2_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext2_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(sb, "ext2_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext2_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT2_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT2_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT2_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext2_xattr_cache_remove(bh); -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT2_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT2_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext2_xattr_set2(inode, bh, NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT2_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT2_XATTR_PAD, 0, -+ EXT2_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext2_xattr_rehash(header, here); -+ -+ error = ext2_xattr_set2(inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext2_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext2_xattr_set(): Update the file system. -+ */ -+static int -+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, -+ struct ext2_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext2_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext2_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext2_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT2_I(inode)->i_file_acl != 0; -+ int block = ext2_xattr_new_block(inode, &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+ ext2_xattr_free_block(inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext2_xattr_cache_insert(new_bh); -+ -+ ext2_xattr_update_super_block(sb); -+ } -+ mark_buffer_dirty(new_bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &new_bh); -+ wait_on_buffer(new_bh); -+ error = -EIO; -+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh)) -+ goto cleanup; -+ } -+ } -+ -+ /* Update the inode. */ -+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ if (IS_SYNC(inode)) { -+ error = ext2_sync_inode (inode); -+ if (error) -+ goto cleanup; -+ } else -+ mark_inode_dirty(inode); -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext2_xattr_free_block(inode, old_bh->b_blocknr); -+ mark_buffer_clean(old_bh); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext2_xattr_quota_free(inode); -+ mark_buffer_dirty(old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT2_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext2_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext2_xattr_cache_remove(bh); -+ ext2_xattr_free_block(inode, block); -+ bforget(bh); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ mark_buffer_dirty(bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &bh); -+ wait_on_buffer(bh); -+ } -+ ext2_xattr_quota_free(inode); -+ } -+ EXT2_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext2_xattr_sem); -+} -+ -+/* -+ * ext2_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+/* -+ * ext2_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext2_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext2_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext2_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext2_xattr_cmp(struct ext2_xattr_header *header1, -+ struct ext2_xattr_header *header2) -+{ -+ struct ext2_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT2_XATTR_NEXT(entry1); -+ entry2 = EXT2_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext2_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT2_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT2_XATTR_REFCOUNT_MAX); -+ } else if (!ext2_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext2_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext2_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext2_xattr_rehash(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ struct ext2_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext2_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT2_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext2_xattr(void) -+{ -+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext2_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+ mb_cache_destroy(ext2_xattr_cache); -+} -+ -+#else /* CONFIG_EXT2_FS_XATTR_SHARING */ -+ -+int __init -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */ ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/fs/ext2/xattr_user.c Fri May 16 08:43:01 2003 -@@ -0,0 +1,103 @@ -+/* -+ * linux/fs/ext2/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext2_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext2_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext2_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, -+ value, size, flags); -+} -+ -+struct ext2_xattr_handler ext2_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext2_xattr_user_list, -+ get: ext2_xattr_user_get, -+ set: ext2_xattr_user_set, -+}; -+ -+int __init -+init_ext2_xattr_user(void) -+{ -+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -+ -+void -+exit_ext2_xattr_user(void) -+{ -+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} ---- linux/fs/ext3/Makefile~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003 -+++ linux-mmonroe/fs/ext3/Makefile Fri May 16 08:43:01 2003 -@@ -1,5 +1,5 @@ - # --# Makefile for the linux ext2-filesystem routines. -+# Makefile for the linux ext3-filesystem routines. - # - # Note! Dependencies are done automagically by 'make dep', which also - # removes any old dependencies. DON'T put your own dependencies here -@@ -9,10 +9,13 @@ - - O_TARGET := ext3.o - --export-objs := super.o inode.o -+export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o hash.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - -+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make ---- linux/fs/ext3/file.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003 -+++ linux-mmonroe/fs/ext3/file.c Fri May 16 08:43:01 2003 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -126,5 +127,9 @@ struct file_operations ext3_file_operati - struct inode_operations ext3_file_inode_operations = { - truncate: ext3_truncate, /* BKL held */ - setattr: ext3_setattr, /* BKL held */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; - ---- linux/fs/ext3/ialloc.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/ext3/ialloc.c Fri May 16 08:43:01 2003 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -216,6 +217,7 @@ void ext3_free_inode (handle_t *handle, - * as writing the quota to disk may need the lock as well. - */ - DQUOT_INIT(inode); -+ ext3_xattr_delete_inode(handle, inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - ---- linux/fs/ext3/inode.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/ext3/inode.c Fri May 16 08:43:01 2003 -@@ -39,6 +39,18 @@ - */ - #undef SEARCH_FROM_ZERO - -+/* -+ * Test whether an inode is a fast symlink. -+ */ -+static inline int ext3_inode_is_fast_symlink(struct inode *inode) -+{ -+ int ea_blocks = inode->u.ext3_i.i_file_acl ? -+ (inode->i_sb->s_blocksize >> 9) : 0; -+ -+ return (S_ISLNK(inode->i_mode) && -+ inode->i_blocks - ea_blocks == 0); -+} -+ - /* The ext3 forget function must perform a revoke if we are freeing data - * which has been journaled. Metadata (eg. indirect blocks) must be - * revoked in all cases. -@@ -48,7 +60,7 @@ - * still needs to be revoked. - */ - --static int ext3_forget(handle_t *handle, int is_metadata, -+int ext3_forget(handle_t *handle, int is_metadata, - struct inode *inode, struct buffer_head *bh, - int blocknr) - { -@@ -164,9 +176,7 @@ void ext3_delete_inode (struct inode * i - { - handle_t *handle; - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT3_ACL_IDX_INO || -- inode->i_ino == EXT3_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - - lock_kernel(); -@@ -1855,6 +1865,8 @@ void ext3_truncate(struct inode * inode) - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; -+ if (ext3_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -2002,8 +2014,6 @@ int ext3_get_inode_loc (struct inode *in - struct ext3_group_desc * gdp; - - if ((inode->i_ino != EXT3_ROOT_INO && -- inode->i_ino != EXT3_ACL_IDX_INO && -- inode->i_ino != EXT3_ACL_DATA_INO && - inode->i_ino != EXT3_JOURNAL_INO && - inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu( -@@ -2130,10 +2140,7 @@ void ext3_read_inode(struct inode * inod - - brelse (iloc.bh); - -- if (inode->i_ino == EXT3_ACL_IDX_INO || -- inode->i_ino == EXT3_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; -@@ -2141,15 +2148,17 @@ void ext3_read_inode(struct inode * inod - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; - } else if (S_ISLNK(inode->i_mode)) { -- if (!inode->i_blocks) -+ if (ext3_inode_is_fast_symlink(inode)) - inode->i_op = &ext3_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - } -- } else -+ } else { -+ inode->i_op = &ext3_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(iloc.raw_inode->i_block[0])); -+ } - /* inode->i_attr_flags = 0; unused */ - if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) { - /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */ ---- linux/fs/ext3/namei.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:47 2003 -+++ linux-mmonroe/fs/ext3/namei.c Fri May 16 08:43:01 2003 -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1611,7 +1612,7 @@ static int ext3_mkdir(struct inode * dir - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFDIR); -+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -@@ -1619,7 +1620,6 @@ static int ext3_mkdir(struct inode * dir - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; - inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; -- inode->i_blocks = 0; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ -@@ -1646,9 +1646,6 @@ static int ext3_mkdir(struct inode * dir - BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, dir_block); - brelse (dir_block); -- inode->i_mode = S_IFDIR | mode; -- if (dir->i_mode & S_ISGID) -- inode->i_mode |= S_ISGID; - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); - if (err) { -@@ -2017,7 +2014,7 @@ static int ext3_symlink (struct inode * - goto out_stop; - - if (l > sizeof (EXT3_I(inode)->i_data)) { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* - * block_symlink() calls back into ext3_prepare/commit_write. -@@ -2244,4 +2241,16 @@ struct inode_operations ext3_dir_inode_o - rmdir: ext3_rmdir, /* BKL held */ - mknod: ext3_mknod, /* BKL held */ - rename: ext3_rename, /* BKL held */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; -+ -+struct inode_operations ext3_special_inode_operations = { -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ -+}; -+ ---- linux/fs/ext3/super.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003 -+++ linux-mmonroe/fs/ext3/super.c Fri May 16 08:43:01 2003 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -406,6 +407,7 @@ void ext3_put_super (struct super_block - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+ ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { - EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -@@ -502,6 +504,7 @@ static int parse_options (char * options - int is_remount) - { - unsigned long *mount_options = &sbi->s_mount_opt; -+ - uid_t *resuid = &sbi->s_resuid; - gid_t *resgid = &sbi->s_resgid; - char * this_char; -@@ -514,6 +517,13 @@ static int parse_options (char * options - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT3_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -931,6 +941,12 @@ struct super_block * ext3_read_super (st - sbi->s_mount_opt = 0; - sbi->s_resuid = EXT3_DEF_RESUID; - sbi->s_resgid = EXT3_DEF_RESGID; -+ -+ /* Default extended attribute flags */ -+#ifdef CONFIG_EXT3_FS_XATTR_USER -+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */ -+#endif -+ - if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) { - sb->s_dev = 0; - goto out_fail; -@@ -1768,17 +1784,29 @@ static DECLARE_FSTYPE_DEV(ext3_fs_type, - - static int __init init_ext3_fs(void) - { -- return register_filesystem(&ext3_fs_type); -+ int error = init_ext3_xattr(); -+ if (error) -+ return error; -+ error = init_ext3_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext3_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext3_xattr_user(); -+fail: -+ exit_ext3_xattr(); -+ return error; - } - - static void __exit exit_ext3_fs(void) - { - unregister_filesystem(&ext3_fs_type); -+ exit_ext3_xattr_user(); -+ exit_ext3_xattr(); - } - --EXPORT_SYMBOL(ext3_force_commit); --EXPORT_SYMBOL(ext3_bread); -- - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); - MODULE_LICENSE("GPL"); ---- linux/fs/ext3/symlink.c~linux-2.4.20-xattr-0.8.54-hp Fri Nov 9 14:25:04 2001 -+++ linux-mmonroe/fs/ext3/symlink.c Fri May 16 08:43:01 2003 -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -33,7 +34,20 @@ static int ext3_follow_link(struct dentr - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext3_symlink_inode_operations = { -+ readlink: page_readlink, /* BKL not held. Don't need */ -+ follow_link: page_follow_link, /* BKL not held. Don't need */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ -+}; -+ - struct inode_operations ext3_fast_symlink_inode_operations = { - readlink: ext3_readlink, /* BKL not held. Don't need */ - follow_link: ext3_follow_link, /* BKL not held. Don't need */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/fs/ext3/xattr.c Fri May 16 08:43:01 2003 -@@ -0,0 +1,1225 @@ -+/* -+ * linux/fs/ext3/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Ext3 code with a lot of help from Eric Jarman . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT3_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define EXT3_EA_USER "user." -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT3_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *, -+ struct ext3_xattr_header *); -+ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ -+static int ext3_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext3_xattr_cache_find(struct inode *, -+ struct ext3_xattr_header *); -+static void ext3_xattr_cache_remove(struct buffer_head *); -+static void ext3_xattr_rehash(struct ext3_xattr_header *, -+ struct ext3_xattr_entry *); -+ -+static struct mb_cache *ext3_xattr_cache; -+ -+#else -+# define ext3_xattr_cache_insert(bh) 0 -+# define ext3_xattr_cache_find(inode, header) NULL -+# define ext3_xattr_cache_remove(bh) while(0) {} -+# define ext3_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext3_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext3_xattr_sem); -+ -+static inline int -+ext3_xattr_new_block(handle_t *handle, struct inode *inode, -+ int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) + -+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext3_new_block(handle, inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext3_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext3_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext3_xattr_free_block(handle_t *handle, struct inode * inode, -+ unsigned long block) -+{ -+ ext3_free_blocks(handle, inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext3_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext3_xattr_free_block(handle, inode, block) \ -+ ext3_free_blocks(handle, inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX]; -+rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) { -+ write_lock(&ext3_handler_lock); -+ if (!ext3_xattr_handlers[name_index-1]) { -+ ext3_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext3_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler) -+{ -+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) { -+ write_lock(&ext3_handler_lock); -+ ext3_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext3_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static inline struct ext3_xattr_handler * -+ext3_xattr_resolve_name(const char **name) -+{ -+ struct ext3_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext3_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext3_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext3_handler_lock); -+ return handler; -+} -+ -+static inline struct ext3_xattr_handler * -+ext3_xattr_handler(int name_index) -+{ -+ struct ext3_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) { -+ read_lock(&ext3_handler_lock); -+ handler = ext3_xattr_handlers[name_index-1]; -+ read_unlock(&ext3_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext3_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext3_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext3_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext3_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext3_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT3_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT3_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT3_I(inode)->i_file_acl) -+ return 0; -+ block = EXT3_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT3_XATTR_NEXT(entry)) { -+ struct ext3_xattr_handler *handler; -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext3_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT3_XATTR_NEXT(entry)) { -+ struct ext3_xattr_handler *handler; -+ -+ handler = ext3_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext3_xattr_update_super_block(handle_t *handle, -+ struct super_block *sb) -+{ -+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT3_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext3_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_header *header = NULL; -+ struct ext3_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT3_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext3_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(sb, "ext3_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT3_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT3_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT3_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext3_xattr_cache_remove(bh); -+ error = ext3_journal_get_write_access(handle, bh); -+ if (error) -+ goto cleanup; -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT3_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT3_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT3_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext3_xattr_set2(handle, inode, bh,NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT3_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT3_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT3_XATTR_PAD, 0, -+ EXT3_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext3_xattr_rehash(header, here); -+ -+ error = ext3_xattr_set2(handle, inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext3_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext3_xattr_set(): Update the file system. -+ */ -+static int -+ext3_xattr_set2(handle_t *handle, struct inode *inode, -+ struct buffer_head *old_bh, struct ext3_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext3_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext3_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ error = ext3_journal_get_write_access(handle, new_bh); -+ if (error) -+ goto cleanup; -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext3_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT3_I(inode)->i_file_acl != 0; -+ int block = ext3_xattr_new_block(handle, inode, -+ &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+getblk_failed: ext3_xattr_free_block(handle, inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ error = ext3_journal_get_create_access(handle, new_bh); -+ if (error) { -+ unlock_buffer(new_bh); -+ goto getblk_failed; -+ } -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext3_xattr_cache_insert(new_bh); -+ -+ ext3_xattr_update_super_block(handle, sb); -+ } -+ error = ext3_journal_dirty_metadata(handle, new_bh); -+ if (error) -+ goto cleanup; -+ } -+ -+ /* Update the inode. */ -+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ ext3_mark_inode_dirty(handle, inode); -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ error = ext3_journal_get_write_access(handle, old_bh); -+ if (error) -+ goto cleanup; -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext3_xattr_free_block(handle, inode, old_bh->b_blocknr); -+ -+ /* ext3_forget() calls bforget() for us, but we -+ let our caller release old_bh, so we need to -+ duplicate the handle before. */ -+ get_bh(old_bh); -+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext3_xattr_quota_free(inode); -+ ext3_journal_dirty_metadata(handle, old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT3_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext3_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ext3_journal_get_write_access(handle, bh); -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext3_xattr_cache_remove(bh); -+ ext3_xattr_free_block(handle, inode, block); -+ ext3_forget(handle, 1, inode, bh, block); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ ext3_journal_dirty_metadata(handle, bh); -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ ext3_xattr_quota_free(inode); -+ } -+ EXT3_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext3_xattr_sem); -+} -+ -+/* -+ * ext3_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext3_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ mb_cache_shrink(ext3_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ -+/* -+ * ext3_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext3_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext3_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext3_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext3_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext3_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext3_xattr_cmp(struct ext3_xattr_header *header1, -+ struct ext3_xattr_header *header2) -+{ -+ struct ext3_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT3_XATTR_NEXT(entry1); -+ entry2 = EXT3_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext3_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext3_error(inode->i_sb, "ext3_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT3_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT3_XATTR_REFCOUNT_MAX); -+ } else if (!ext3_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext3_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext3_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext3_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext3_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header, -+ struct ext3_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext3_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext3_xattr_rehash(struct ext3_xattr_header *header, -+ struct ext3_xattr_entry *entry) -+{ -+ struct ext3_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext3_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT3_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext3_xattr(void) -+{ -+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext3_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext3_xattr(void) -+{ -+ if (ext3_xattr_cache) -+ mb_cache_destroy(ext3_xattr_cache); -+ ext3_xattr_cache = NULL; -+} -+ -+#else /* CONFIG_EXT3_FS_XATTR_SHARING */ -+ -+int __init -+init_ext3_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext3_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT3_FS_XATTR_SHARING */ ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/fs/ext3/xattr_user.c Fri May 16 08:43:01 2003 -@@ -0,0 +1,111 @@ -+/* -+ * linux/fs/ext3/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext3_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext3_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+ error = ext3_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext3_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ handle_t *handle; -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+ error = ext3_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name, -+ value, size, flags); -+ ext3_journal_stop(handle, inode); -+ -+ return error; -+} -+ -+struct ext3_xattr_handler ext3_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext3_xattr_user_list, -+ get: ext3_xattr_user_get, -+ set: ext3_xattr_user_set, -+}; -+ -+int __init -+init_ext3_xattr_user(void) -+{ -+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER, -+ &ext3_xattr_user_handler); -+} -+ -+void -+exit_ext3_xattr_user(void) -+{ -+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, -+ &ext3_xattr_user_handler); -+} ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/fs/ext3/ext3-exports.c Fri May 16 08:43:01 2003 -@@ -0,0 +1,13 @@ -+#include -+#include -+#include -+#include -+#include -+ -+EXPORT_SYMBOL(ext3_force_commit); -+EXPORT_SYMBOL(ext3_bread); -+EXPORT_SYMBOL(ext3_xattr_register); -+EXPORT_SYMBOL(ext3_xattr_unregister); -+EXPORT_SYMBOL(ext3_xattr_get); -+EXPORT_SYMBOL(ext3_xattr_list); -+EXPORT_SYMBOL(ext3_xattr_set); ---- linux/fs/jfs/jfs_xattr.h~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/jfs/jfs_xattr.h Fri May 16 08:43:01 2003 -@@ -52,8 +52,10 @@ struct jfs_ea_list { - #define END_EALIST(ealist) \ - ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) - --extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int); --extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int); -+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, -+ int); -+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, -+ int); - extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); - extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); - extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); ---- linux/fs/jfs/xattr.c~linux-2.4.20-xattr-0.8.54-hp Thu Nov 28 15:53:15 2002 -+++ linux-mmonroe/fs/jfs/xattr.c Fri May 16 08:43:01 2003 -@@ -641,7 +641,7 @@ static int ea_put(struct inode *inode, s - } - - static int can_set_xattr(struct inode *inode, const char *name, -- void *value, size_t value_len) -+ const void *value, size_t value_len) - { - if (IS_RDONLY(inode)) - return -EROFS; -@@ -660,7 +660,7 @@ static int can_set_xattr(struct inode *i - return permission(inode, MAY_WRITE); - } - --int __jfs_setxattr(struct inode *inode, const char *name, void *value, -+int __jfs_setxattr(struct inode *inode, const char *name, const void *value, - size_t value_len, int flags) - { - struct jfs_ea_list *ealist; -@@ -799,7 +799,7 @@ int __jfs_setxattr(struct inode *inode, - return rc; - } - --int jfs_setxattr(struct dentry *dentry, const char *name, void *value, -+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t value_len, int flags) - { - if (value == NULL) { /* empty EA, do not remove */ ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/fs/mbcache.c Fri May 16 08:43:01 2003 -@@ -0,0 +1,648 @@ -+/* -+ * linux/fs/mbcache.c -+ * (C) 2001-2002 Andreas Gruenbacher, -+ */ -+ -+/* -+ * Filesystem Meta Information Block Cache (mbcache) -+ * -+ * The mbcache caches blocks of block devices that need to be located -+ * by their device/block number, as well as by other criteria (such -+ * as the block's contents). -+ * -+ * There can only be one cache entry in a cache per device and block number. -+ * Additional indexes need not be unique in this sense. The number of -+ * additional indexes (=other criteria) can be hardwired at compile time -+ * or specified at cache create time. -+ * -+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid' -+ * in the cache. A valid entry is in the main hash tables of the cache, -+ * and may also be in the lru list. An invalid entry is not in any hashes -+ * or lists. -+ * -+ * A valid cache entry is only in the lru list if no handles refer to it. -+ * Invalid cache entries will be freed when the last handle to the cache -+ * entry is released. Entries that cannot be freed immediately are put -+ * back on the lru list. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#ifdef MB_CACHE_DEBUG -+# define mb_debug(f...) do { \ -+ printk(KERN_DEBUG f); \ -+ printk("\n"); \ -+ } while (0) -+#define mb_assert(c) do { if (!(c)) \ -+ printk(KERN_ERR "assertion " #c " failed\n"); \ -+ } while(0) -+#else -+# define mb_debug(f...) do { } while(0) -+# define mb_assert(c) do { } while(0) -+#endif -+#define mb_error(f...) do { \ -+ printk(KERN_ERR f); \ -+ printk("\n"); \ -+ } while(0) -+ -+MODULE_AUTHOR("Andreas Gruenbacher "); -+MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_SYMBOL(mb_cache_create); -+EXPORT_SYMBOL(mb_cache_shrink); -+EXPORT_SYMBOL(mb_cache_destroy); -+EXPORT_SYMBOL(mb_cache_entry_alloc); -+EXPORT_SYMBOL(mb_cache_entry_insert); -+EXPORT_SYMBOL(mb_cache_entry_release); -+EXPORT_SYMBOL(mb_cache_entry_takeout); -+EXPORT_SYMBOL(mb_cache_entry_free); -+EXPORT_SYMBOL(mb_cache_entry_dup); -+EXPORT_SYMBOL(mb_cache_entry_get); -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+EXPORT_SYMBOL(mb_cache_entry_find_first); -+EXPORT_SYMBOL(mb_cache_entry_find_next); -+#endif -+ -+ -+/* -+ * Global data: list of all mbcache's, lru list, and a spinlock for -+ * accessing cache data structures on SMP machines. The lru list is -+ * global across all mbcaches. -+ */ -+ -+static LIST_HEAD(mb_cache_list); -+static LIST_HEAD(mb_cache_lru_list); -+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED; -+ -+static inline int -+mb_cache_indexes(struct mb_cache *cache) -+{ -+#ifdef MB_CACHE_INDEXES_COUNT -+ return MB_CACHE_INDEXES_COUNT; -+#else -+ return cache->c_indexes_count; -+#endif -+} -+ -+/* -+ * What the mbcache registers as to get shrunk dynamically. -+ */ -+ -+static void -+mb_cache_memory_pressure(int priority, unsigned int gfp_mask); -+ -+static struct cache_definition mb_cache_definition = { -+ "mb_cache", -+ mb_cache_memory_pressure -+}; -+ -+ -+static inline int -+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce) -+{ -+ return !list_empty(&ce->e_block_list); -+} -+ -+ -+static inline void -+__mb_cache_entry_unhash(struct mb_cache_entry *ce) -+{ -+ int n; -+ -+ if (__mb_cache_entry_is_hashed(ce)) { -+ list_del_init(&ce->e_block_list); -+ for (n=0; ne_cache); n++) -+ list_del(&ce->e_indexes[n].o_list); -+ } -+} -+ -+ -+static inline void -+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask) -+{ -+ struct mb_cache *cache = ce->e_cache; -+ -+ mb_assert(atomic_read(&ce->e_used) == 0); -+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) { -+ /* free failed -- put back on the lru list -+ for freeing later. */ -+ spin_lock(&mb_cache_spinlock); -+ list_add(&ce->e_lru_list, &mb_cache_lru_list); -+ spin_unlock(&mb_cache_spinlock); -+ } else { -+ kmem_cache_free(cache->c_entry_cache, ce); -+ atomic_dec(&cache->c_entry_count); -+ } -+} -+ -+ -+static inline void -+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce) -+{ -+ if (atomic_dec_and_test(&ce->e_used)) { -+ if (__mb_cache_entry_is_hashed(ce)) -+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list); -+ else { -+ spin_unlock(&mb_cache_spinlock); -+ __mb_cache_entry_forget(ce, GFP_KERNEL); -+ return; -+ } -+ } -+ spin_unlock(&mb_cache_spinlock); -+} -+ -+ -+/* -+ * mb_cache_memory_pressure() memory pressure callback -+ * -+ * This function is called by the kernel memory management when memory -+ * gets low. -+ * -+ * @priority: Amount by which to shrink the cache (0 = highes priority) -+ * @gfp_mask: (ignored) -+ */ -+static void -+mb_cache_memory_pressure(int priority, unsigned int gfp_mask) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ int count = 0; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &mb_cache_list) { -+ struct mb_cache *cache = -+ list_entry(l, struct mb_cache, c_cache_list); -+ mb_debug("cache %s (%d)", cache->c_name, -+ atomic_read(&cache->c_entry_count)); -+ count += atomic_read(&cache->c_entry_count); -+ } -+ mb_debug("trying to free %d of %d entries", -+ count / (priority ? priority : 1), count); -+ if (priority) -+ count /= priority; -+ while (count-- && !list_empty(&mb_cache_lru_list)) { -+ struct mb_cache_entry *ce = -+ list_entry(mb_cache_lru_list.next, -+ struct mb_cache_entry, e_lru_list); -+ list_del(&ce->e_lru_list); -+ __mb_cache_entry_unhash(ce); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ } -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), gfp_mask); -+ } -+} -+ -+ -+/* -+ * mb_cache_create() create a new cache -+ * -+ * All entries in one cache are equal size. Cache entries may be from -+ * multiple devices. If this is the first mbcache created, registers -+ * the cache with kernel memory management. Returns NULL if no more -+ * memory was available. -+ * -+ * @name: name of the cache (informal) -+ * @cache_op: contains the callback called when freeing a cache entry -+ * @entry_size: The size of a cache entry, including -+ * struct mb_cache_entry -+ * @indexes_count: number of additional indexes in the cache. Must equal -+ * MB_CACHE_INDEXES_COUNT if the number of indexes is -+ * hardwired. -+ * @bucket_count: number of hash buckets -+ */ -+struct mb_cache * -+mb_cache_create(const char *name, struct mb_cache_op *cache_op, -+ size_t entry_size, int indexes_count, int bucket_count) -+{ -+ int m=0, n; -+ struct mb_cache *cache = NULL; -+ -+ if(entry_size < sizeof(struct mb_cache_entry) + -+ indexes_count * sizeof(struct mb_cache_entry_index)) -+ return NULL; -+ -+ MOD_INC_USE_COUNT; -+ cache = kmalloc(sizeof(struct mb_cache) + -+ indexes_count * sizeof(struct list_head), GFP_KERNEL); -+ if (!cache) -+ goto fail; -+ cache->c_name = name; -+ cache->c_op.free = NULL; -+ if (cache_op) -+ cache->c_op.free = cache_op->free; -+ atomic_set(&cache->c_entry_count, 0); -+ cache->c_bucket_count = bucket_count; -+#ifdef MB_CACHE_INDEXES_COUNT -+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT); -+#else -+ cache->c_indexes_count = indexes_count; -+#endif -+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head), -+ GFP_KERNEL); -+ if (!cache->c_block_hash) -+ goto fail; -+ for (n=0; nc_block_hash[n]); -+ for (m=0; mc_indexes_hash[m] = kmalloc(bucket_count * -+ sizeof(struct list_head), -+ GFP_KERNEL); -+ if (!cache->c_indexes_hash[m]) -+ goto fail; -+ for (n=0; nc_indexes_hash[m][n]); -+ } -+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0, -+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL); -+ if (!cache->c_entry_cache) -+ goto fail; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_add(&cache->c_cache_list, &mb_cache_list); -+ spin_unlock(&mb_cache_spinlock); -+ return cache; -+ -+fail: -+ if (cache) { -+ while (--m >= 0) -+ kfree(cache->c_indexes_hash[m]); -+ if (cache->c_block_hash) -+ kfree(cache->c_block_hash); -+ kfree(cache); -+ } -+ MOD_DEC_USE_COUNT; -+ return NULL; -+} -+ -+ -+/* -+ * mb_cache_shrink() -+ * -+ * Removes all cache entires of a device from the cache. All cache entries -+ * currently in use cannot be freed, and thus remain in the cache. -+ * -+ * @cache: which cache to shrink -+ * @dev: which device's cache entries to shrink -+ */ -+void -+mb_cache_shrink(struct mb_cache *cache, kdev_t dev) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_lru_list); -+ if (ce->e_dev == dev) { -+ list_del(&ce->e_lru_list); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ __mb_cache_entry_unhash(ce); -+ } -+ } -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), GFP_KERNEL); -+ } -+} -+ -+ -+/* -+ * mb_cache_destroy() -+ * -+ * Shrinks the cache to its minimum possible size (hopefully 0 entries), -+ * and then destroys it. If this was the last mbcache, un-registers the -+ * mbcache from kernel memory management. -+ */ -+void -+mb_cache_destroy(struct mb_cache *cache) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ int n; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_lru_list); -+ if (ce->e_cache == cache) { -+ list_del(&ce->e_lru_list); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ __mb_cache_entry_unhash(ce); -+ } -+ } -+ list_del(&cache->c_cache_list); -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), GFP_KERNEL); -+ } -+ -+ if (atomic_read(&cache->c_entry_count) > 0) { -+ mb_error("cache %s: %d orphaned entries", -+ cache->c_name, -+ atomic_read(&cache->c_entry_count)); -+ } -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) -+ /* We don't have kmem_cache_destroy() in 2.2.x */ -+ kmem_cache_shrink(cache->c_entry_cache); -+#else -+ kmem_cache_destroy(cache->c_entry_cache); -+#endif -+ for (n=0; n < mb_cache_indexes(cache); n++) -+ kfree(cache->c_indexes_hash[n]); -+ kfree(cache->c_block_hash); -+ kfree(cache); -+ -+ MOD_DEC_USE_COUNT; -+} -+ -+ -+/* -+ * mb_cache_entry_alloc() -+ * -+ * Allocates a new cache entry. The new entry will not be valid initially, -+ * and thus cannot be looked up yet. It should be filled with data, and -+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL -+ * if no more memory was available. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_alloc(struct mb_cache *cache) -+{ -+ struct mb_cache_entry *ce; -+ -+ atomic_inc(&cache->c_entry_count); -+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL); -+ if (ce) { -+ INIT_LIST_HEAD(&ce->e_lru_list); -+ INIT_LIST_HEAD(&ce->e_block_list); -+ ce->e_cache = cache; -+ atomic_set(&ce->e_used, 1); -+ } -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_insert() -+ * -+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into -+ * the cache. After this, the cache entry can be looked up, but is not yet -+ * in the lru list as the caller still holds a handle to it. Returns 0 on -+ * success, or -EBUSY if a cache entry for that device + inode exists -+ * already (this may happen after a failed lookup, if another process has -+ * inserted the same cache entry in the meantime). -+ * -+ * @dev: device the cache entry belongs to -+ * @block: block number -+ * @keys: array of additional keys. There must be indexes_count entries -+ * in the array (as specified when creating the cache). -+ */ -+int -+mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev, -+ unsigned long block, unsigned int keys[]) -+{ -+ struct mb_cache *cache = ce->e_cache; -+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count; -+ struct list_head *l; -+ int error = -EBUSY, n; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &cache->c_block_hash[bucket]) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_block_list); -+ if (ce->e_dev == dev && ce->e_block == block) -+ goto out; -+ } -+ __mb_cache_entry_unhash(ce); -+ ce->e_dev = dev; -+ ce->e_block = block; -+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]); -+ for (n=0; ne_indexes[n].o_key = keys[n]; -+ bucket = keys[n] % cache->c_bucket_count; -+ list_add(&ce->e_indexes[n].o_list, -+ &cache->c_indexes_hash[n][bucket]); -+ } -+out: -+ spin_unlock(&mb_cache_spinlock); -+ return error; -+} -+ -+ -+/* -+ * mb_cache_entry_release() -+ * -+ * Release a handle to a cache entry. When the last handle to a cache entry -+ * is released it is either freed (if it is invalid) or otherwise inserted -+ * in to the lru list. -+ */ -+void -+mb_cache_entry_release(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ __mb_cache_entry_release_unlock(ce); -+} -+ -+ -+/* -+ * mb_cache_entry_takeout() -+ * -+ * Take a cache entry out of the cache, making it invalid. The entry can later -+ * be re-inserted using mb_cache_entry_insert(), or released using -+ * mb_cache_entry_release(). -+ */ -+void -+mb_cache_entry_takeout(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ mb_assert(list_empty(&ce->e_lru_list)); -+ __mb_cache_entry_unhash(ce); -+ spin_unlock(&mb_cache_spinlock); -+} -+ -+ -+/* -+ * mb_cache_entry_free() -+ * -+ * This is equivalent to the sequence mb_cache_entry_takeout() -- -+ * mb_cache_entry_release(). -+ */ -+void -+mb_cache_entry_free(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ mb_assert(list_empty(&ce->e_lru_list)); -+ __mb_cache_entry_unhash(ce); -+ __mb_cache_entry_release_unlock(ce); -+} -+ -+ -+/* -+ * mb_cache_entry_dup() -+ * -+ * Duplicate a handle to a cache entry (does not duplicate the cache entry -+ * itself). After the call, both the old and the new handle must be released. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_dup(struct mb_cache_entry *ce) -+{ -+ atomic_inc(&ce->e_used); -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_get() -+ * -+ * Get a cache entry by device / block number. (There can only be one entry -+ * in the cache per device and block.) Returns NULL if no such cache entry -+ * exists. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block) -+{ -+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &cache->c_block_hash[bucket]) { -+ ce = list_entry(l, struct mb_cache_entry, e_block_list); -+ if (ce->e_dev == dev && ce->e_block == block) { -+ if (!list_empty(&ce->e_lru_list)) -+ list_del_init(&ce->e_lru_list); -+ atomic_inc(&ce->e_used); -+ goto cleanup; -+ } -+ } -+ ce = NULL; -+ -+cleanup: -+ spin_unlock(&mb_cache_spinlock); -+ return ce; -+} -+ -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+ -+static struct mb_cache_entry * -+__mb_cache_entry_find(struct list_head *l, struct list_head *head, -+ int index, kdev_t dev, unsigned int key) -+{ -+ while (l != head) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, -+ e_indexes[index].o_list); -+ if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) { -+ if (!list_empty(&ce->e_lru_list)) -+ list_del_init(&ce->e_lru_list); -+ atomic_inc(&ce->e_used); -+ return ce; -+ } -+ l = l->next; -+ } -+ return NULL; -+} -+ -+ -+/* -+ * mb_cache_entry_find_first() -+ * -+ * Find the first cache entry on a given device with a certain key in -+ * an additional index. Additonal matches can be found with -+ * mb_cache_entry_find_next(). Returns NULL if no match was found. -+ * -+ * @cache: the cache to search -+ * @index: the number of the additonal index to search (0<=indexc_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ mb_assert(index < mb_cache_indexes(cache)); -+ spin_lock(&mb_cache_spinlock); -+ l = cache->c_indexes_hash[index][bucket].next; -+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket], -+ index, dev, key); -+ spin_unlock(&mb_cache_spinlock); -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_find_next() -+ * -+ * Find the next cache entry on a given device with a certain key in an -+ * additional index. Returns NULL if no match could be found. The previous -+ * entry is atomatically released, so that mb_cache_entry_find_next() can -+ * be called like this: -+ * -+ * entry = mb_cache_entry_find_first(); -+ * while (entry) { -+ * ... -+ * entry = mb_cache_entry_find_next(entry, ...); -+ * } -+ * -+ * @prev: The previous match -+ * @index: the number of the additonal index to search (0<=indexe_cache; -+ unsigned int bucket = key % cache->c_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ mb_assert(index < mb_cache_indexes(cache)); -+ spin_lock(&mb_cache_spinlock); -+ l = prev->e_indexes[index].o_list.next; -+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket], -+ index, dev, key); -+ __mb_cache_entry_release_unlock(prev); -+ return ce; -+} -+ -+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */ -+ -+static int __init init_mbcache(void) -+{ -+ register_cache(&mb_cache_definition); -+ return 0; -+} -+ -+static void __exit exit_mbcache(void) -+{ -+ unregister_cache(&mb_cache_definition); -+} -+ -+module_init(init_mbcache) -+module_exit(exit_mbcache) -+ ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/include/linux/cache_def.h Fri May 16 08:43:01 2003 -@@ -0,0 +1,15 @@ -+/* -+ * linux/cache_def.h -+ * Handling of caches defined in drivers, filesystems, ... -+ * -+ * Copyright (C) 2002 by Andreas Gruenbacher, -+ */ -+ -+struct cache_definition { -+ const char *name; -+ void (*shrink)(int, unsigned int); -+ struct list_head link; -+}; -+ -+extern void register_cache(struct cache_definition *); -+extern void unregister_cache(struct cache_definition *); ---- linux/include/linux/errno.h~linux-2.4.20-xattr-0.8.54-hp Fri Feb 9 14:46:13 2001 -+++ linux-mmonroe/include/linux/errno.h Fri May 16 08:43:01 2003 -@@ -23,4 +23,8 @@ - - #endif - -+/* Defined for extended attributes */ -+#define ENOATTR ENODATA /* No such attribute */ -+#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -+ - #endif ---- linux/include/linux/ext2_fs.h~linux-2.4.20-xattr-0.8.54-hp Thu Nov 22 11:46:52 2001 -+++ linux-mmonroe/include/linux/ext2_fs.h Fri May 16 08:43:01 2003 -@@ -57,8 +57,6 @@ - */ - #define EXT2_BAD_INO 1 /* Bad blocks inode */ - #define EXT2_ROOT_INO 2 /* Root inode */ --#define EXT2_ACL_IDX_INO 3 /* ACL inode */ --#define EXT2_ACL_DATA_INO 4 /* ACL inode */ - #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ - -@@ -86,7 +84,6 @@ - #else - # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry)) - #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -121,28 +118,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext2_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext2_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext2_group_desc -@@ -314,6 +289,7 @@ struct ext2_inode { - #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ - #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ - #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ -+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt - #define set_opt(o, opt) o |= EXT2_MOUNT_##opt -@@ -397,6 +373,7 @@ struct ext2_super_block { - - #ifdef __KERNEL__ - #define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -+#define EXT2_I(inode) (&((inode)->u.ext2_i)) - #else - /* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test -@@ -466,7 +443,7 @@ struct ext2_super_block { - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 - #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - --#define EXT2_FEATURE_COMPAT_SUPP 0 -+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE - #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ -@@ -623,8 +600,10 @@ extern struct address_space_operations e - - /* namei.c */ - extern struct inode_operations ext2_dir_inode_operations; -+extern struct inode_operations ext2_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext2_symlink_inode_operations; - extern struct inode_operations ext2_fast_symlink_inode_operations; - - #endif /* __KERNEL__ */ ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/include/linux/ext2_xattr.h Fri May 16 08:43:01 2003 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext2_xattr.h -+ -+ On-disk format of extended attributes for the ext2 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT2_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT2_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT2_XATTR_INDEX_MAX 10 -+#define EXT2_XATTR_INDEX_USER 1 -+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext2_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext2_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT2_XATTR_PAD_BITS 2 -+#define EXT2_XATTR_PAD (1<e_name_len)) ) -+#define EXT2_XATTR_SIZE(size) \ -+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT2_FS_XATTR -+ -+struct ext2_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext2_xattr_register(int, struct ext2_xattr_handler *); -+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *); -+ -+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); -+extern int ext2_removexattr(struct dentry *, const char *); -+ -+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext2_xattr_list(struct inode *, char *, size_t); -+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext2_xattr_delete_inode(struct inode *); -+extern void ext2_xattr_put_super(struct super_block *); -+ -+extern int init_ext2_xattr(void) __init; -+extern void exit_ext2_xattr(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR */ -+# define ext2_setxattr NULL -+# define ext2_getxattr NULL -+# define ext2_listxattr NULL -+# define ext2_removexattr NULL -+ -+static inline int -+ext2_xattr_get(struct inode *inode, int name_index, -+ const char *name, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+} -+ -+static inline void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR */ -+ -+# ifdef CONFIG_EXT2_FS_XATTR_USER -+ -+extern int init_ext2_xattr_user(void) __init; -+extern void exit_ext2_xattr_user(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+static inline int -+init_ext2_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr_user(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ ---- linux/include/linux/ext3_fs.h~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:47 2003 -+++ linux-mmonroe/include/linux/ext3_fs.h Fri May 16 08:43:01 2003 -@@ -63,8 +63,6 @@ - */ - #define EXT3_BAD_INO 1 /* Bad blocks inode */ - #define EXT3_ROOT_INO 2 /* Root inode */ --#define EXT3_ACL_IDX_INO 3 /* ACL inode */ --#define EXT3_ACL_DATA_INO 4 /* ACL inode */ - #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */ - #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */ -@@ -94,7 +92,6 @@ - #else - # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry)) - #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -129,28 +126,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext3_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext3_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext3_group_desc -@@ -344,6 +319,7 @@ struct ext3_inode { - #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */ - #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ -+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -520,7 +496,7 @@ struct ext3_super_block { - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ - --#define EXT3_FEATURE_COMPAT_SUPP 0 -+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ - EXT3_FEATURE_INCOMPAT_RECOVER) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ -@@ -703,6 +679,7 @@ extern void ext3_check_inodes_bitmap (st - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); - -@@ -771,8 +748,10 @@ extern struct address_space_operations e - - /* namei.c */ - extern struct inode_operations ext3_dir_inode_operations; -+extern struct inode_operations ext3_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - - ---- linux/include/linux/ext3_jbd.h~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003 -+++ linux-mmonroe/include/linux/ext3_jbd.h Fri May 16 08:43:01 2003 -@@ -30,13 +30,19 @@ - - #define EXT3_SINGLEDATA_TRANS_BLOCKS 8 - -+/* Extended attributes may touch two data buffers, two bitmap buffers, -+ * and two group and summaries. */ -+ -+#define EXT3_XATTR_TRANS_BLOCKS 8 -+ - /* Define the minimum size for a transaction which modifies data. This - * needs to take into account the fact that we may end up modifying two - * quota files too (one for the group, one for the user quota). The - * superblock only gets updated once, of course, so don't bother - * counting that again for the quota updates. */ - --#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2) -+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \ -+ EXT3_XATTR_TRANS_BLOCKS - 2) - - extern int ext3_writepage_trans_blocks(struct inode *inode); - ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/include/linux/ext3_xattr.h Fri May 16 08:43:01 2003 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext3_xattr.h -+ -+ On-disk format of extended attributes for the ext3 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT3_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT3_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT3_XATTR_INDEX_MAX 10 -+#define EXT3_XATTR_INDEX_USER 1 -+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext3_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext3_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT3_XATTR_PAD_BITS 2 -+#define EXT3_XATTR_PAD (1<e_name_len)) ) -+#define EXT3_XATTR_SIZE(size) \ -+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT3_FS_XATTR -+ -+struct ext3_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext3_xattr_register(int, struct ext3_xattr_handler *); -+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *); -+ -+extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); -+extern int ext3_removexattr(struct dentry *, const char *); -+ -+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext3_xattr_list(struct inode *, char *, size_t); -+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext3_xattr_delete_inode(handle_t *, struct inode *); -+extern void ext3_xattr_put_super(struct super_block *); -+ -+extern int init_ext3_xattr(void) __init; -+extern void exit_ext3_xattr(void); -+ -+# else /* CONFIG_EXT3_FS_XATTR */ -+# define ext3_setxattr NULL -+# define ext3_getxattr NULL -+# define ext3_listxattr NULL -+# define ext3_removexattr NULL -+ -+static inline int -+ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext3_xattr_list(struct inode *inode, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) -+{ -+} -+ -+static inline void -+ext3_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext3_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext3_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT3_FS_XATTR */ -+ -+# ifdef CONFIG_EXT3_FS_XATTR_USER -+ -+extern int init_ext3_xattr_user(void) __init; -+extern void exit_ext3_xattr_user(void); -+ -+# else /* CONFIG_EXT3_FS_XATTR_USER */ -+ -+static inline int -+init_ext3_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext3_xattr_user(void) -+{ -+} -+ -+#endif /* CONFIG_EXT3_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ ---- linux/include/linux/fs.h~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:46 2003 -+++ linux-mmonroe/include/linux/fs.h Fri May 16 08:43:01 2003 -@@ -909,7 +909,7 @@ struct inode_operations { - int (*setattr) (struct dentry *, struct iattr *); - int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); -- int (*setxattr) (struct dentry *, const char *, void *, size_t, int); -+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); - ssize_t (*listxattr) (struct dentry *, char *, size_t); - int (*removexattr) (struct dentry *, const char *); ---- /dev/null Mon May 20 21:11:23 2002 -+++ linux-mmonroe/include/linux/mbcache.h Fri May 16 08:43:01 2003 -@@ -0,0 +1,69 @@ -+/* -+ File: linux/mbcache.h -+ -+ (C) 2001 by Andreas Gruenbacher, -+*/ -+ -+/* Hardwire the number of additional indexes */ -+#define MB_CACHE_INDEXES_COUNT 1 -+ -+struct mb_cache_entry; -+ -+struct mb_cache_op { -+ int (*free)(struct mb_cache_entry *, int); -+}; -+ -+struct mb_cache { -+ struct list_head c_cache_list; -+ const char *c_name; -+ struct mb_cache_op c_op; -+ atomic_t c_entry_count; -+ int c_bucket_count; -+#ifndef MB_CACHE_INDEXES_COUNT -+ int c_indexes_count; -+#endif -+ kmem_cache_t *c_entry_cache; -+ struct list_head *c_block_hash; -+ struct list_head *c_indexes_hash[0]; -+}; -+ -+struct mb_cache_entry_index { -+ struct list_head o_list; -+ unsigned int o_key; -+}; -+ -+struct mb_cache_entry { -+ struct list_head e_lru_list; -+ struct mb_cache *e_cache; -+ atomic_t e_used; -+ kdev_t e_dev; -+ unsigned long e_block; -+ struct list_head e_block_list; -+ struct mb_cache_entry_index e_indexes[0]; -+}; -+ -+/* Functions on caches */ -+ -+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t, -+ int, int); -+void mb_cache_shrink(struct mb_cache *, kdev_t); -+void mb_cache_destroy(struct mb_cache *); -+ -+/* Functions on cache entries */ -+ -+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *); -+int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long, -+ unsigned int[]); -+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]); -+void mb_cache_entry_release(struct mb_cache_entry *); -+void mb_cache_entry_takeout(struct mb_cache_entry *); -+void mb_cache_entry_free(struct mb_cache_entry *); -+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *); -+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t, -+ unsigned long); -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int, -+ kdev_t, unsigned int); -+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int, -+ kdev_t, unsigned int); -+#endif ---- linux/kernel/ksyms.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:42:45 2003 -+++ linux-mmonroe/kernel/ksyms.c Fri May 16 08:43:52 2003 -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -106,6 +107,7 @@ EXPORT_SYMBOL(exit_mm); - EXPORT_SYMBOL(exit_files); - EXPORT_SYMBOL(exit_fs); - EXPORT_SYMBOL(exit_sighand); -+EXPORT_SYMBOL(copy_fs_struct); - EXPORT_SYMBOL_GPL(make_pages_present); - - /* internal kernel memory management */ -@@ -126,6 +128,8 @@ EXPORT_SYMBOL(kmem_cache_validate); - EXPORT_SYMBOL(kmem_cache_alloc); - EXPORT_SYMBOL(kmem_cache_free); - EXPORT_SYMBOL(kmem_cache_size); -+EXPORT_SYMBOL(register_cache); -+EXPORT_SYMBOL(unregister_cache); - EXPORT_SYMBOL(kmalloc); - EXPORT_SYMBOL(kfree); - EXPORT_SYMBOL(vfree); ---- linux/mm/vmscan.c~linux-2.4.20-xattr-0.8.54-hp Fri May 16 08:39:23 2003 -+++ linux-mmonroe/mm/vmscan.c Fri May 16 08:43:01 2003 -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -35,6 +36,39 @@ - */ - #define DEF_PRIORITY (6) - -+static DECLARE_MUTEX(other_caches_sem); -+static LIST_HEAD(cache_definitions); -+ -+void register_cache(struct cache_definition *cache) -+{ -+ down(&other_caches_sem); -+ list_add(&cache->link, &cache_definitions); -+ up(&other_caches_sem); -+} -+ -+void unregister_cache(struct cache_definition *cache) -+{ -+ down(&other_caches_sem); -+ list_del(&cache->link); -+ up(&other_caches_sem); -+} -+ -+static void shrink_other_caches(unsigned int priority, int gfp_mask) -+{ -+ struct list_head *p; -+ -+ if (down_trylock(&other_caches_sem)) -+ return; -+ -+ list_for_each_prev(p, &cache_definitions) { -+ struct cache_definition *cache = -+ list_entry(p, struct cache_definition, link); -+ -+ cache->shrink(priority, gfp_mask); -+ } -+ up(&other_caches_sem); -+} -+ - /* - * The swap-out function returns 1 if it successfully - * scanned all the pages it was asked to (`count'). -@@ -579,6 +613,7 @@ static int shrink_caches(zone_t * classz - - shrink_dcache_memory(priority, gfp_mask); - shrink_icache_memory(priority, gfp_mask); -+ shrink_other_caches(priority, gfp_mask); - #ifdef CONFIG_QUOTA - shrink_dqcache_memory(DEF_PRIORITY, gfp_mask); - #endif - -_ diff --git a/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-chaos.patch b/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-chaos.patch deleted file mode 100644 index 686b1ea..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-chaos.patch +++ /dev/null @@ -1,2172 +0,0 @@ - Documentation/Configure.help | 66 ++ - arch/alpha/defconfig | 7 - arch/alpha/kernel/entry.S | 12 - arch/arm/defconfig | 7 - arch/arm/kernel/calls.S | 24 - arch/i386/defconfig | 7 - arch/ia64/defconfig | 7 - arch/ia64/kernel/entry.S | 24 - arch/m68k/defconfig | 7 - arch/mips/defconfig | 7 - arch/mips64/defconfig | 7 - arch/ppc/defconfig | 14 - arch/ppc64/kernel/misc.S | 2 - arch/s390/defconfig | 7 - arch/s390/kernel/entry.S | 24 - arch/s390x/defconfig | 7 - arch/s390x/kernel/entry.S | 24 - arch/s390x/kernel/wrapper32.S | 92 +++ - arch/sparc/defconfig | 7 - arch/sparc/kernel/systbls.S | 10 - arch/sparc64/defconfig | 7 - arch/sparc64/kernel/systbls.S | 20 - fs/Config.in | 14 - fs/Makefile | 3 - fs/ext2/Makefile | 4 - fs/ext2/file.c | 5 - fs/ext2/ialloc.c | 2 - fs/ext2/inode.c | 34 - - fs/ext2/namei.c | 14 - fs/ext2/super.c | 29 - fs/ext2/symlink.c | 14 - fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++ - fs/ext2/xattr_user.c | 103 +++ - fs/ext3/Makefile | 10 - fs/ext3/file.c | 5 - fs/ext3/ialloc.c | 2 - fs/ext3/inode.c | 35 - - fs/ext3/namei.c | 21 - fs/ext3/super.c | 36 + - fs/ext3/symlink.c | 14 - fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++ - fs/ext3/xattr_user.c | 111 +++ - fs/jfs/jfs_xattr.h | 6 - fs/jfs/xattr.c | 6 - fs/mbcache.c | 648 ++++++++++++++++++++++ - include/asm-arm/unistd.h | 2 - include/asm-ia64/unistd.h | 13 - include/asm-ppc64/unistd.h | 2 - include/asm-s390/unistd.h | 15 - include/asm-s390x/unistd.h | 15 - include/asm-sparc/unistd.h | 24 - include/asm-sparc64/unistd.h | 24 - include/linux/cache_def.h | 15 - include/linux/errno.h | 4 - include/linux/ext2_fs.h | 31 - - include/linux/ext2_xattr.h | 157 +++++ - include/linux/ext3_fs.h | 31 - - include/linux/ext3_jbd.h | 8 - include/linux/ext3_xattr.h | 157 +++++ - include/linux/fs.h | 2 - include/linux/mbcache.h | 69 ++ - kernel/ksyms.c | 4 - mm/vmscan.c | 35 + - fs/ext3/ext3-exports.c | 14 + - 64 files changed, 4355 insertions(+), 195 deletions(-) - -Index: linux-2.4.21-chaos/Documentation/Configure.help -=================================================================== ---- linux-2.4.21-chaos.orig/Documentation/Configure.help 2003-10-04 01:18:57.000000000 +0400 -+++ linux-2.4.21-chaos/Documentation/Configure.help 2003-12-14 15:11:46.000000000 +0300 -@@ -15939,6 +15939,39 @@ - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. - -+Ext2 extended attributes -+CONFIG_EXT2_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext2 extended attribute block sharing -+CONFIG_EXT2_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext2 extended user attributes -+CONFIG_EXT2_FS_XATTR_USER -+ This option enables extended user attributes on ext2. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext2 trusted extended attributes -+CONFIG_EXT2_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext2 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Ext3 journalling file system support (EXPERIMENTAL) - CONFIG_EXT3_FS - This is the journalling version of the Second extended file system -@@ -16008,6 +16041,39 @@ - - If unsure, say N. - -+Ext3 extended attributes -+CONFIG_EXT3_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext3 extended attribute block sharing -+CONFIG_EXT3_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext3 extended user attributes -+CONFIG_EXT3_FS_XATTR_USER -+ This option enables extended user attributes on ext3. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext3 trusted extended attributes -+CONFIG_EXT3_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext3 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Journal Block Device support (JBD for ext3) (EXPERIMENTAL) - CONFIG_JBD - This is a generic journalling layer for block devices. It is -Index: linux-2.4.21-chaos/fs/Config.in -=================================================================== ---- linux-2.4.21-chaos.orig/fs/Config.in 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/Config.in 2003-12-14 15:11:46.000000000 +0300 -@@ -108,6 +108,11 @@ - tristate 'ROM file system support' CONFIG_ROMFS_FS - - tristate 'Second extended fs support' CONFIG_EXT2_FS -+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS -+dep_bool ' Ext2 extended attribute block sharing' \ -+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR -+dep_bool ' Ext2 extended user attributes' \ -+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR - - tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS - -@@ -196,6 +201,10 @@ - bool "POSIX ACL helper functions" CONFIG_FS_POSIX_ACL - fi - -+# Meta block cache for Extended Attributes (ext2/ext3) -+#tristate 'Meta block cache' CONFIG_FS_MBCACHE -+define_tristate CONFIG_FS_MBCACHE y -+ - mainmenu_option next_comment - comment 'Partition Types' - source fs/partitions/Config.in -Index: linux-2.4.21-chaos/fs/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/Makefile 2003-12-14 15:09:27.000000000 +0300 -+++ linux-2.4.21-chaos/fs/Makefile 2003-12-14 15:11:46.000000000 +0300 -@@ -95,6 +95,9 @@ - obj-$(CONFIG_NFS_ACL) += solaris_acl.o - obj-$(CONFIG_NFSD_ACL) += solaris_acl.o - -+export-objs += mbcache.o -+obj-$(CONFIG_FS_MBCACHE) += mbcache.o -+ - # persistent filesystems - obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) - -Index: linux-2.4.21-chaos/fs/ext2/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/Makefile 2002-05-08 01:53:46.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext2/Makefile 2003-12-14 15:11:46.000000000 +0300 -@@ -13,4 +13,8 @@ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) - -+export-objs += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make -Index: linux-2.4.21-chaos/fs/ext2/file.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/file.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext2/file.c 2003-12-14 15:11:46.000000000 +0300 -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - - /* -@@ -55,4 +56,8 @@ - - struct inode_operations ext2_file_inode_operations = { - truncate: ext2_truncate, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.21-chaos/fs/ext2/ialloc.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/ialloc.c 2003-07-15 02:09:35.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext2/ialloc.c 2003-12-14 15:11:46.000000000 +0300 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -167,6 +168,7 @@ - */ - if (!is_bad_inode(inode)) { - /* Quota is already initialized in iput() */ -+ ext2_xattr_delete_inode(inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - } -Index: linux-2.4.21-chaos/fs/ext2/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/inode.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext2/inode.c 2003-12-14 15:11:46.000000000 +0300 -@@ -53,9 +65,7 @@ - { - lock_kernel(); - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - inode->u.ext2_i.i_dtime = CURRENT_TIME; - mark_inode_dirty(inode); -@@ -802,6 +812,8 @@ - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; -+ if (ext2_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -904,8 +916,7 @@ - unsigned long offset; - struct ext2_group_desc * gdp; - -- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO && -- inode->i_ino != EXT2_ACL_DATA_INO && -+ if ((inode->i_ino != EXT2_ROOT_INO && - inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) { - ext2_error (inode->i_sb, "ext2_read_inode", -@@ -990,10 +1001,7 @@ - for (block = 0; block < EXT2_N_BLOCKS; block++) - inode->u.ext2_i.i_data[block] = raw_inode->i_block[block]; - -- if (inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext2_file_inode_operations; - inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; -@@ -1002,12 +1010,14 @@ - if (ext2_inode_is_fast_symlink(inode)) - inode->i_op = &ext2_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - } -- } else -+ } else { -+ inode->i_op = &ext2_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); -+ } - brelse (bh); - inode->i_attr_flags = 0; - ext2_set_inode_flags(inode); -Index: linux-2.4.21-chaos/fs/ext2/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/namei.c 2002-05-08 01:53:46.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext2/namei.c 2003-12-14 15:11:46.000000000 +0300 -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - - /* -@@ -136,7 +137,7 @@ - - if (l > sizeof (inode->u.ext2_i.i_data)) { - /* slow symlink */ -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); - if (err) -@@ -345,4 +346,15 @@ - rmdir: ext2_rmdir, - mknod: ext2_mknod, - rename: ext2_rename, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ -+struct inode_operations ext2_special_inode_operations = { -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.21-chaos/fs/ext2/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/super.c 2003-02-15 01:59:09.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext2/super.c 2003-12-14 15:11:46.000000000 +0300 -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -125,6 +126,7 @@ - int db_count; - int i; - -+ ext2_xattr_put_super(sb); - if (!(sb->s_flags & MS_RDONLY)) { - struct ext2_super_block *es = EXT2_SB(sb)->s_es; - -@@ -175,6 +177,13 @@ - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -424,6 +433,9 @@ - blocksize = BLOCK_SIZE; - - sb->u.ext2_sb.s_mount_opt = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */ -+#endif - if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, - &sb->u.ext2_sb.s_mount_opt)) { - return NULL; -@@ -813,12 +825,27 @@ - - static int __init init_ext2_fs(void) - { -- return register_filesystem(&ext2_fs_type); -+ int error = init_ext2_xattr(); -+ if (error) -+ return error; -+ error = init_ext2_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext2_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext2_xattr_user(); -+fail: -+ exit_ext2_xattr(); -+ return error; - } - - static void __exit exit_ext2_fs(void) - { - unregister_filesystem(&ext2_fs_type); -+ exit_ext2_xattr_user(); -+ exit_ext2_xattr(); - } - - EXPORT_NO_SYMBOLS; -Index: linux-2.4.21-chaos/fs/ext2/symlink.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/symlink.c 2002-05-08 01:53:46.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext2/symlink.c 2003-12-14 15:11:46.000000000 +0300 -@@ -19,6 +19,7 @@ - - #include - #include -+#include - - static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -32,7 +33,20 @@ - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext2_symlink_inode_operations = { -+ readlink: page_readlink, -+ follow_link: page_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ - struct inode_operations ext2_fast_symlink_inode_operations = { - readlink: ext2_readlink, - follow_link: ext2_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.21-chaos/fs/ext2/xattr.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/xattr.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext2/xattr.c 2003-12-14 15:11:46.000000000 +0300 -@@ -0,0 +1,1212 @@ -+/* -+ * linux/fs/ext2/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT2_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT2_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext2_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* These symbols may be needed by a module. */ -+EXPORT_SYMBOL(ext2_xattr_register); -+EXPORT_SYMBOL(ext2_xattr_unregister); -+EXPORT_SYMBOL(ext2_xattr_get); -+EXPORT_SYMBOL(ext2_xattr_list); -+EXPORT_SYMBOL(ext2_xattr_set); -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT2_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext2_xattr_set2(struct inode *, struct buffer_head *, -+ struct ext2_xattr_header *); -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+static int ext2_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext2_xattr_cache_find(struct inode *, -+ struct ext2_xattr_header *); -+static void ext2_xattr_cache_remove(struct buffer_head *); -+static void ext2_xattr_rehash(struct ext2_xattr_header *, -+ struct ext2_xattr_entry *); -+ -+static struct mb_cache *ext2_xattr_cache; -+ -+#else -+# define ext2_xattr_cache_insert(bh) 0 -+# define ext2_xattr_cache_find(inode, header) NULL -+# define ext2_xattr_cache_remove(bh) while(0) {} -+# define ext2_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext2_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext2_xattr_sem); -+ -+static inline int -+ext2_xattr_new_block(struct inode *inode, int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) + -+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext2_new_block(inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext2_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext2_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext2_xattr_free_block(struct inode * inode, unsigned long block) -+{ -+ ext2_free_blocks(inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext2_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext2_xattr_free_block(inode, block) \ -+ ext2_free_blocks(inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX]; -+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ if (!ext2_xattr_handlers[name_index-1]) { -+ ext2_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext2_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler) -+{ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ ext2_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext2_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static struct ext2_xattr_handler * -+ext2_xattr_resolve_name(const char **name) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext2_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext2_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext2_handler_lock); -+ return handler; -+} -+ -+static inline struct ext2_xattr_handler * -+ext2_xattr_handler(int name_index) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ read_lock(&ext2_handler_lock); -+ handler = ext2_xattr_handlers[name_index-1]; -+ read_unlock(&ext2_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext2_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext2_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT2_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT2_I(inode)->i_file_acl) -+ return 0; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext2_xattr_update_super_block(struct super_block *sb) -+{ -+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT2_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext2_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_header *header = NULL; -+ struct ext2_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT2_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext2_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(sb, "ext2_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext2_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT2_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT2_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT2_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext2_xattr_cache_remove(bh); -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT2_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT2_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext2_xattr_set2(inode, bh, NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT2_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT2_XATTR_PAD, 0, -+ EXT2_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext2_xattr_rehash(header, here); -+ -+ error = ext2_xattr_set2(inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext2_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext2_xattr_set(): Update the file system. -+ */ -+static int -+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, -+ struct ext2_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext2_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext2_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext2_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT2_I(inode)->i_file_acl != 0; -+ int block = ext2_xattr_new_block(inode, &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+ ext2_xattr_free_block(inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext2_xattr_cache_insert(new_bh); -+ -+ ext2_xattr_update_super_block(sb); -+ } -+ mark_buffer_dirty(new_bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &new_bh); -+ wait_on_buffer(new_bh); -+ error = -EIO; -+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh)) -+ goto cleanup; -+ } -+ } -+ -+ /* Update the inode. */ -+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ if (IS_SYNC(inode)) { -+ error = ext2_sync_inode (inode); -+ if (error) -+ goto cleanup; -+ } else -+ mark_inode_dirty(inode); -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext2_xattr_free_block(inode, old_bh->b_blocknr); -+ mark_buffer_clean(old_bh); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext2_xattr_quota_free(inode); -+ mark_buffer_dirty(old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT2_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext2_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext2_xattr_cache_remove(bh); -+ ext2_xattr_free_block(inode, block); -+ bforget(bh); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ mark_buffer_dirty(bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &bh); -+ wait_on_buffer(bh); -+ } -+ ext2_xattr_quota_free(inode); -+ } -+ EXT2_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext2_xattr_sem); -+} -+ -+/* -+ * ext2_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+/* -+ * ext2_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext2_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext2_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext2_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext2_xattr_cmp(struct ext2_xattr_header *header1, -+ struct ext2_xattr_header *header2) -+{ -+ struct ext2_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT2_XATTR_NEXT(entry1); -+ entry2 = EXT2_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext2_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT2_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT2_XATTR_REFCOUNT_MAX); -+ } else if (!ext2_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext2_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext2_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext2_xattr_rehash(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ struct ext2_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext2_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT2_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext2_xattr(void) -+{ -+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext2_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+ mb_cache_destroy(ext2_xattr_cache); -+} -+ -+#else /* CONFIG_EXT2_FS_XATTR_SHARING */ -+ -+int __init -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */ -Index: linux-2.4.21-chaos/fs/ext2/xattr_user.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext2/xattr_user.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext2/xattr_user.c 2003-12-14 15:11:46.000000000 +0300 -@@ -0,0 +1,103 @@ -+/* -+ * linux/fs/ext2/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext2_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext2_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext2_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, -+ value, size, flags); -+} -+ -+struct ext2_xattr_handler ext2_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext2_xattr_user_list, -+ get: ext2_xattr_user_get, -+ set: ext2_xattr_user_set, -+}; -+ -+int __init -+init_ext2_xattr_user(void) -+{ -+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -+ -+void -+exit_ext2_xattr_user(void) -+{ -+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -Index: linux-2.4.21-chaos/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/Makefile 2003-12-14 15:09:30.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/Makefile 2003-12-14 15:11:46.000000000 +0300 -@@ -9,10 +9,10 @@ - - O_TARGET := ext3.o - --export-objs := super.o inode.o -+export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o hash.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-14 15:09:30.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-14 15:11:46.000000000 +0300 -@@ -1944,9 +1944,6 @@ - unregister_filesystem(&ext3_fs_type); - } - --EXPORT_SYMBOL(ext3_force_commit); --EXPORT_SYMBOL(ext3_bread); -- - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); - MODULE_LICENSE("GPL"); -Index: linux-2.4.21-chaos/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ext3-exports.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ext3-exports.c 2003-12-14 15:11:46.000000000 +0300 -@@ -0,0 +1,14 @@ -+#include -+#include -+#include -+#include -+#include -+ -+EXPORT_SYMBOL(ext3_force_commit); -+EXPORT_SYMBOL(ext3_bread); -+EXPORT_SYMBOL(ext3_journal_abort_handle); -+EXPORT_SYMBOL(ext3_xattr_register); -+EXPORT_SYMBOL(ext3_xattr_unregister); -+EXPORT_SYMBOL(ext3_xattr_get); -+EXPORT_SYMBOL(ext3_xattr_list); -+EXPORT_SYMBOL(ext3_xattr_set); -Index: linux-2.4.21-chaos/fs/ext3/xattr_trusted.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr_trusted.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/xattr_trusted.c 2003-12-14 15:11:46.000000000 +0300 -@@ -50,7 +50,7 @@ - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; -- return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name, -+ return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_TRUSTED, name, - value, size, flags); - } - -Index: linux-2.4.21-chaos/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr.c 2003-07-30 04:11:55.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/xattr.c 2003-12-14 15:11:46.000000000 +0300 -@@ -868,7 +868,7 @@ - } - - /* -- * ext3_xattr_set() -+ * ext3_xattr_set_trans() - * - * Like ext3_xattr_set_handle, but start from an inode. This extended - * attribute modification is a filesystem transaction by itself. -@@ -876,7 +876,7 @@ - * Returns 0, or a negative error number on failure. - */ - int --ext3_xattr_set(struct inode *inode, int name_index, const char *name, -+ext3_xattr_set_trans(struct inode *inode, int name_index, const char *name, - const void *value, size_t value_len, int flags) - { - handle_t *handle; -@@ -895,6 +895,20 @@ - return error ? error : error2; - } - -+int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ int error; -+ -+ lock_kernel(); -+ error = ext3_xattr_set_handle(handle, inode, name_index, name, -+ value, value_len, flags); -+ unlock_kernel(); -+ return error; -+} -+ - /* - * ext3_xattr_delete_inode() - * -Index: linux-2.4.21-chaos/fs/ext3/xattr_user.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr_user.c 2003-07-30 04:11:55.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/xattr_user.c 2003-12-14 15:26:58.000000000 +0300 -@@ -70,7 +70,7 @@ - if (error) - return error; - -- return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name, -+ return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_USER, name, - value, size, flags); - } - -Index: linux-2.4.21-chaos/include/linux/errno.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/errno.h 2003-07-15 04:41:12.000000000 +0400 -+++ linux-2.4.21-chaos/include/linux/errno.h 2003-12-14 15:11:46.000000000 +0300 -@@ -26,4 +26,8 @@ - - #endif - -+/* Defined for extended attributes */ -+#define ENOATTR ENODATA /* No such attribute */ -+#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -+ - #endif -Index: linux-2.4.21-chaos/include/linux/ext2_fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext2_fs.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext2_fs.h 2003-12-14 15:13:54.000000000 +0300 -@@ -57,8 +57,6 @@ - */ - #define EXT2_BAD_INO 1 /* Bad blocks inode */ - #define EXT2_ROOT_INO 2 /* Root inode */ --#define EXT2_ACL_IDX_INO 3 /* ACL inode */ --#define EXT2_ACL_DATA_INO 4 /* ACL inode */ - #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ - -@@ -86,7 +84,6 @@ - #else - # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry)) - #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -121,28 +118,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext2_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext2_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext2_group_desc -@@ -314,6 +289,7 @@ - #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ - #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ - #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ -+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt - #define set_opt(o, opt) o |= EXT2_MOUNT_##opt -@@ -397,6 +373,7 @@ - - #ifdef __KERNEL__ - #define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -+#define EXT2_I(inode) (&((inode)->u.ext2_i)) - #else - /* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test -@@ -466,7 +443,7 @@ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 - #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - --#define EXT2_FEATURE_COMPAT_SUPP 0 -+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE - #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ -@@ -624,8 +601,10 @@ - - /* namei.c */ - extern struct inode_operations ext2_dir_inode_operations; -+extern struct inode_operations ext2_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext2_symlink_inode_operations; - extern struct inode_operations ext2_fast_symlink_inode_operations; - - #endif /* __KERNEL__ */ -Index: linux-2.4.21-chaos/include/linux/ext2_xattr.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext2_xattr.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext2_xattr.h 2003-12-14 15:13:54.000000000 +0300 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext2_xattr.h -+ -+ On-disk format of extended attributes for the ext2 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT2_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT2_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT2_XATTR_INDEX_MAX 10 -+#define EXT2_XATTR_INDEX_USER 1 -+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext2_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext2_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT2_XATTR_PAD_BITS 2 -+#define EXT2_XATTR_PAD (1<e_name_len)) ) -+#define EXT2_XATTR_SIZE(size) \ -+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT2_FS_XATTR -+ -+struct ext2_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext2_xattr_register(int, struct ext2_xattr_handler *); -+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *); -+ -+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); -+extern int ext2_removexattr(struct dentry *, const char *); -+ -+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext2_xattr_list(struct inode *, char *, size_t); -+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext2_xattr_delete_inode(struct inode *); -+extern void ext2_xattr_put_super(struct super_block *); -+ -+extern int init_ext2_xattr(void) __init; -+extern void exit_ext2_xattr(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR */ -+# define ext2_setxattr NULL -+# define ext2_getxattr NULL -+# define ext2_listxattr NULL -+# define ext2_removexattr NULL -+ -+static inline int -+ext2_xattr_get(struct inode *inode, int name_index, -+ const char *name, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+} -+ -+static inline void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR */ -+ -+# ifdef CONFIG_EXT2_FS_XATTR_USER -+ -+extern int init_ext2_xattr_user(void) __init; -+extern void exit_ext2_xattr_user(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+static inline int -+init_ext2_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr_user(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ -Index: linux-2.4.21-chaos/include/linux/ext3_xattr.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_xattr.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_xattr.h 2003-12-14 15:21:13.000000000 +0300 -@@ -82,8 +82,10 @@ - extern int ext3_xattr_list(struct inode *, char *, size_t); - extern int ext3_xattr_set_handle(handle_t *handle, struct inode *, int, - const char *, const void *, size_t, int); --extern int ext3_xattr_set(struct inode *, int, const char *, const void *, -+extern int ext3_xattr_set_trans(struct inode *, int, const char *, const void *, - size_t, int); -+extern int ext3_xattr_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); - - extern void ext3_xattr_delete_inode(handle_t *, struct inode *); - extern void ext3_xattr_put_super(struct super_block *); diff --git a/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse-171.patch b/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse-171.patch deleted file mode 100644 index f203b15..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse-171.patch +++ /dev/null @@ -1,276 +0,0 @@ - Documentation/Configure.help | 66 ++ - arch/alpha/defconfig | 7 - arch/alpha/kernel/entry.S | 12 - arch/arm/defconfig | 7 - arch/arm/kernel/calls.S | 24 - arch/i386/defconfig | 7 - arch/ia64/defconfig | 7 - arch/ia64/kernel/entry.S | 24 - arch/m68k/defconfig | 7 - arch/mips/defconfig | 7 - arch/mips64/defconfig | 7 - arch/ppc/defconfig | 14 - arch/ppc64/kernel/misc.S | 2 - arch/s390/defconfig | 7 - arch/s390/kernel/entry.S | 24 - arch/s390x/defconfig | 7 - arch/s390x/kernel/entry.S | 24 - arch/s390x/kernel/wrapper32.S | 92 +++ - arch/sparc/defconfig | 7 - arch/sparc/kernel/systbls.S | 10 - arch/sparc64/defconfig | 7 - arch/sparc64/kernel/systbls.S | 20 - fs/Config.in | 14 - fs/Makefile | 3 - fs/ext2/Makefile | 4 - fs/ext2/file.c | 5 - fs/ext2/ialloc.c | 2 - fs/ext2/inode.c | 34 - - fs/ext2/namei.c | 14 - fs/ext2/super.c | 29 - fs/ext2/symlink.c | 14 - fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++ - fs/ext2/xattr_user.c | 103 +++ - fs/ext3/Makefile | 10 - fs/ext3/file.c | 5 - fs/ext3/ialloc.c | 2 - fs/ext3/inode.c | 35 - - fs/ext3/namei.c | 21 - fs/ext3/super.c | 36 + - fs/ext3/symlink.c | 14 - fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++ - fs/ext3/xattr_user.c | 111 +++ - fs/jfs/jfs_xattr.h | 6 - fs/jfs/xattr.c | 6 - fs/mbcache.c | 648 ++++++++++++++++++++++ - include/asm-arm/unistd.h | 2 - include/asm-ia64/unistd.h | 13 - include/asm-ppc64/unistd.h | 2 - include/asm-s390/unistd.h | 15 - include/asm-s390x/unistd.h | 15 - include/asm-sparc/unistd.h | 24 - include/asm-sparc64/unistd.h | 24 - include/linux/cache_def.h | 15 - include/linux/errno.h | 4 - include/linux/ext2_fs.h | 31 - - include/linux/ext2_xattr.h | 157 +++++ - include/linux/ext3_fs.h | 31 - - include/linux/ext3_jbd.h | 8 - include/linux/ext3_xattr.h | 157 +++++ - include/linux/fs.h | 2 - include/linux/mbcache.h | 69 ++ - kernel/ksyms.c | 4 - mm/vmscan.c | 35 + - fs/ext3/ext3-exports.c | 14 + - 64 files changed, 4355 insertions(+), 195 deletions(-) - -Index: linux-2.4.21-241/Documentation/Configure.help -=================================================================== ---- linux-2.4.21-241.orig/Documentation/Configure.help 2004-10-03 17:37:47.000000000 -0400 -+++ linux-2.4.21-241/Documentation/Configure.help 2004-10-04 02:19:55.000000000 -0400 -@@ -16421,6 +16421,39 @@ - - If unsure, say N. - -+Ext3 extended attributes -+CONFIG_EXT3_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext3 extended attribute block sharing -+CONFIG_EXT3_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext3 extended user attributes -+CONFIG_EXT3_FS_XATTR_USER -+ This option enables extended user attributes on ext3. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext3 trusted extended attributes -+CONFIG_EXT3_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext3 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Journal Block Device support (JBD for ext3) (EXPERIMENTAL) - CONFIG_JBD - This is a generic journalling layer for block devices. It is -Index: linux-2.4.21-241/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/Makefile 2004-10-04 02:19:51.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/Makefile 2004-10-04 02:19:55.000000000 -0400 -@@ -9,10 +9,10 @@ - - O_TARGET := ext3.o - --export-objs := super.o inode.o -+export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o hash.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21-241/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/super.c 2004-10-04 02:19:51.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/super.c 2004-10-04 02:19:55.000000000 -0400 -@@ -1914,9 +1914,6 @@ - unregister_filesystem(&ext3_fs_type); - } - --EXPORT_SYMBOL(ext3_force_commit); --EXPORT_SYMBOL(ext3_bread); -- - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); - MODULE_LICENSE("GPL"); -Index: linux-2.4.21-241/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/ext3-exports.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.4.21-241/fs/ext3/ext3-exports.c 2004-10-04 02:19:55.000000000 -0400 -@@ -0,0 +1,14 @@ -+#include -+#include -+#include -+#include -+#include -+ -+EXPORT_SYMBOL(ext3_force_commit); -+EXPORT_SYMBOL(ext3_bread); -+EXPORT_SYMBOL(ext3_journal_abort_handle); -+EXPORT_SYMBOL(ext3_xattr_register); -+EXPORT_SYMBOL(ext3_xattr_unregister); -+EXPORT_SYMBOL(ext3_xattr_get); -+EXPORT_SYMBOL(ext3_xattr_list); -+EXPORT_SYMBOL(ext3_xattr_set); -Index: linux-2.4.21-241/fs/ext3/xattr_trusted.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/xattr_trusted.c 2004-10-03 17:37:47.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/xattr_trusted.c 2004-10-04 02:19:55.000000000 -0400 -@@ -50,7 +50,7 @@ - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; -- return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name, -+ return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_TRUSTED, name, - value, size, flags); - } - -Index: linux-2.4.21-241/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/xattr.c 2004-10-03 17:37:47.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/xattr.c 2004-10-04 02:23:13.000000000 -0400 -@@ -785,7 +785,7 @@ - * don't need to change the reference count. */ - new_bh = old_bh; - get_bh(new_bh); -- ext3_xattr_cache_insert(new_bh); -+ (void)ext3_xattr_cache_insert(new_bh); - } else { - /* We need to allocate a new block */ - int goal = le32_to_cpu(EXT3_SB(inode->i_sb)->s_es-> -@@ -814,7 +814,7 @@ - memcpy(new_bh->b_data, header, new_bh->b_size); - mark_buffer_uptodate(new_bh, 1); - unlock_buffer(new_bh); -- ext3_xattr_cache_insert(new_bh); -+ (void)ext3_xattr_cache_insert(new_bh); - - ext3_xattr_update_super_block(handle, sb); - } -@@ -870,7 +870,7 @@ - } - - /* -- * ext3_xattr_set() -+ * ext3_xattr_set_trans() - * - * Like ext3_xattr_set_handle, but start from an inode. This extended - * attribute modification is a filesystem transaction by itself. -@@ -878,7 +878,7 @@ - * Returns 0, or a negative error number on failure. - */ - int --ext3_xattr_set(struct inode *inode, int name_index, const char *name, -+ext3_xattr_set_trans(struct inode *inode, int name_index, const char *name, - const void *value, size_t value_len, int flags) - { - handle_t *handle; -@@ -900,6 +900,20 @@ - return error; - } - -+int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ int error; -+ -+ lock_kernel(); -+ error = ext3_xattr_set_handle(handle, inode, name_index, name, -+ value, value_len, flags); -+ unlock_kernel(); -+ return error; -+} -+ - /* - * ext3_xattr_delete_inode() - * -Index: linux-2.4.21-241/fs/ext3/xattr_user.c -=================================================================== ---- linux-2.4.21-241.orig/fs/ext3/xattr_user.c 2004-10-03 17:37:47.000000000 -0400 -+++ linux-2.4.21-241/fs/ext3/xattr_user.c 2004-10-04 02:19:55.000000000 -0400 -@@ -70,7 +70,7 @@ - if (error) - return error; - -- return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name, -+ return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_USER, name, - value, size, flags); - } - -Index: linux-2.4.21-241/include/linux/errno.h -=================================================================== ---- linux-2.4.21-241.orig/include/linux/errno.h 2004-10-03 17:37:47.000000000 -0400 -+++ linux-2.4.21-241/include/linux/errno.h 2004-10-04 02:19:55.000000000 -0400 -@@ -26,4 +26,8 @@ - - #endif - -+/* Defined for extended attributes */ -+#define ENOATTR ENODATA /* No such attribute */ -+#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -+ - #endif -Index: linux-2.4.21-241/include/linux/ext3_xattr.h -=================================================================== ---- linux-2.4.21-241.orig/include/linux/ext3_xattr.h 2004-10-03 17:37:47.000000000 -0400 -+++ linux-2.4.21-241/include/linux/ext3_xattr.h 2004-10-04 02:19:55.000000000 -0400 -@@ -80,8 +80,10 @@ - extern int ext3_xattr_list(struct inode *, char *, size_t); - extern int ext3_xattr_set_handle(handle_t *handle, struct inode *, int, - const char *, const void *, size_t, int); --extern int ext3_xattr_set(struct inode *, int, const char *, const void *, -+extern int ext3_xattr_set_trans(struct inode *, int, const char *, const void *, - size_t, int); -+extern int ext3_xattr_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); - - extern void ext3_xattr_delete_inode(handle_t *, struct inode *); - extern void ext3_xattr_put_super(struct super_block *); diff --git a/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse2.patch b/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse2.patch deleted file mode 100644 index 0a8891f..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.21-xattr-0.8.54-suse2.patch +++ /dev/null @@ -1,258 +0,0 @@ - Documentation/Configure.help | 66 ++ - arch/alpha/defconfig | 7 - arch/alpha/kernel/entry.S | 12 - arch/arm/defconfig | 7 - arch/arm/kernel/calls.S | 24 - arch/i386/defconfig | 7 - arch/ia64/defconfig | 7 - arch/ia64/kernel/entry.S | 24 - arch/m68k/defconfig | 7 - arch/mips/defconfig | 7 - arch/mips64/defconfig | 7 - arch/ppc/defconfig | 14 - arch/ppc64/kernel/misc.S | 2 - arch/s390/defconfig | 7 - arch/s390/kernel/entry.S | 24 - arch/s390x/defconfig | 7 - arch/s390x/kernel/entry.S | 24 - arch/s390x/kernel/wrapper32.S | 92 +++ - arch/sparc/defconfig | 7 - arch/sparc/kernel/systbls.S | 10 - arch/sparc64/defconfig | 7 - arch/sparc64/kernel/systbls.S | 20 - fs/Config.in | 14 - fs/Makefile | 3 - fs/ext2/Makefile | 4 - fs/ext2/file.c | 5 - fs/ext2/ialloc.c | 2 - fs/ext2/inode.c | 34 - - fs/ext2/namei.c | 14 - fs/ext2/super.c | 29 - fs/ext2/symlink.c | 14 - fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++ - fs/ext2/xattr_user.c | 103 +++ - fs/ext3/Makefile | 10 - fs/ext3/file.c | 5 - fs/ext3/ialloc.c | 2 - fs/ext3/inode.c | 35 - - fs/ext3/namei.c | 21 - fs/ext3/super.c | 36 + - fs/ext3/symlink.c | 14 - fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++ - fs/ext3/xattr_user.c | 111 +++ - fs/jfs/jfs_xattr.h | 6 - fs/jfs/xattr.c | 6 - fs/mbcache.c | 648 ++++++++++++++++++++++ - include/asm-arm/unistd.h | 2 - include/asm-ia64/unistd.h | 13 - include/asm-ppc64/unistd.h | 2 - include/asm-s390/unistd.h | 15 - include/asm-s390x/unistd.h | 15 - include/asm-sparc/unistd.h | 24 - include/asm-sparc64/unistd.h | 24 - include/linux/cache_def.h | 15 - include/linux/errno.h | 4 - include/linux/ext2_fs.h | 31 - - include/linux/ext2_xattr.h | 157 +++++ - include/linux/ext3_fs.h | 31 - - include/linux/ext3_jbd.h | 8 - include/linux/ext3_xattr.h | 157 +++++ - include/linux/fs.h | 2 - include/linux/mbcache.h | 69 ++ - kernel/ksyms.c | 4 - mm/vmscan.c | 35 + - fs/ext3/ext3-exports.c | 14 + - 64 files changed, 4355 insertions(+), 195 deletions(-) - -Index: linux-2.4.21-chaos/Documentation/Configure.help -=================================================================== ---- linux-2.4.21-chaos.orig/Documentation/Configure.help 2003-10-04 01:18:57.000000000 +0400 -+++ linux-2.4.21-chaos/Documentation/Configure.help 2003-12-14 15:11:46.000000000 +0300 -@@ -16008,6 +16041,39 @@ - - If unsure, say N. - -+Ext3 extended attributes -+CONFIG_EXT3_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext3 extended attribute block sharing -+CONFIG_EXT3_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext3 extended user attributes -+CONFIG_EXT3_FS_XATTR_USER -+ This option enables extended user attributes on ext3. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext3 trusted extended attributes -+CONFIG_EXT3_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext3 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Journal Block Device support (JBD for ext3) (EXPERIMENTAL) - CONFIG_JBD - This is a generic journalling layer for block devices. It is -Index: linux-2.4.21-chaos/fs/ext3/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/Makefile 2003-12-14 15:09:30.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/Makefile 2003-12-14 15:11:46.000000000 +0300 -@@ -9,10 +9,10 @@ - - O_TARGET := ext3.o - --export-objs := super.o inode.o -+export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o hash.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - - export-objs += xattr.o -Index: linux-2.4.21-chaos/fs/ext3/super.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/super.c 2003-12-14 15:09:30.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/super.c 2003-12-14 15:11:46.000000000 +0300 -@@ -1944,9 +1944,6 @@ - unregister_filesystem(&ext3_fs_type); - } - --EXPORT_SYMBOL(ext3_force_commit); --EXPORT_SYMBOL(ext3_bread); -- - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); - MODULE_LICENSE("GPL"); -Index: linux-2.4.21-chaos/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/ext3-exports.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.21-chaos/fs/ext3/ext3-exports.c 2003-12-14 15:11:46.000000000 +0300 -@@ -0,0 +1,14 @@ -+#include -+#include -+#include -+#include -+#include -+ -+EXPORT_SYMBOL(ext3_force_commit); -+EXPORT_SYMBOL(ext3_bread); -+EXPORT_SYMBOL(ext3_journal_abort_handle); -+EXPORT_SYMBOL(ext3_xattr_register); -+EXPORT_SYMBOL(ext3_xattr_unregister); -+EXPORT_SYMBOL(ext3_xattr_get); -+EXPORT_SYMBOL(ext3_xattr_list); -+EXPORT_SYMBOL(ext3_xattr_set); -Index: linux-2.4.21-chaos/fs/ext3/xattr_trusted.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr_trusted.c 2003-07-15 04:41:01.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/xattr_trusted.c 2003-12-14 15:11:46.000000000 +0300 -@@ -50,7 +50,7 @@ - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; -- return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name, -+ return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_TRUSTED, name, - value, size, flags); - } - -Index: linux-2.4.21-chaos/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr.c 2003-07-30 04:11:55.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/xattr.c 2003-12-14 15:11:46.000000000 +0300 -@@ -868,7 +868,7 @@ - } - - /* -- * ext3_xattr_set() -+ * ext3_xattr_set_trans() - * - * Like ext3_xattr_set_handle, but start from an inode. This extended - * attribute modification is a filesystem transaction by itself. -@@ -876,7 +876,7 @@ - * Returns 0, or a negative error number on failure. - */ - int --ext3_xattr_set(struct inode *inode, int name_index, const char *name, -+ext3_xattr_set_trans(struct inode *inode, int name_index, const char *name, - const void *value, size_t value_len, int flags) - { - handle_t *handle; -@@ -895,6 +895,20 @@ - return error ? error : error2; - } - -+int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, -+ int flags) -+{ -+ int error; -+ -+ lock_kernel(); -+ error = ext3_xattr_set_handle(handle, inode, name_index, name, -+ value, value_len, flags); -+ unlock_kernel(); -+ return error; -+} -+ - /* - * ext3_xattr_delete_inode() - * -Index: linux-2.4.21-chaos/fs/ext3/xattr_user.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/ext3/xattr_user.c 2003-07-30 04:11:55.000000000 +0400 -+++ linux-2.4.21-chaos/fs/ext3/xattr_user.c 2003-12-14 15:26:58.000000000 +0300 -@@ -70,7 +70,7 @@ - if (error) - return error; - -- return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name, -+ return ext3_xattr_set_trans(inode, EXT3_XATTR_INDEX_USER, name, - value, size, flags); - } - -Index: linux-2.4.21-chaos/include/linux/errno.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/errno.h 2003-07-15 04:41:12.000000000 +0400 -+++ linux-2.4.21-chaos/include/linux/errno.h 2003-12-14 15:11:46.000000000 +0300 -@@ -26,4 +26,8 @@ - - #endif - -+/* Defined for extended attributes */ -+#define ENOATTR ENODATA /* No such attribute */ -+#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -+ - #endif -Index: linux-2.4.21-chaos/include/linux/ext3_xattr.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/ext3_xattr.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/ext3_xattr.h 2003-12-14 15:21:13.000000000 +0300 -@@ -82,8 +82,10 @@ - extern int ext3_xattr_list(struct inode *, char *, size_t); - extern int ext3_xattr_set_handle(handle_t *handle, struct inode *, int, - const char *, const void *, size_t, int); --extern int ext3_xattr_set(struct inode *, int, const char *, const void *, -+extern int ext3_xattr_set_trans(struct inode *, int, const char *, const void *, - size_t, int); -+extern int ext3_xattr_set(handle_t *, struct inode *, int, const char *, -+ const void *, size_t, int); - - extern void ext3_xattr_delete_inode(handle_t *, struct inode *); - extern void ext3_xattr_put_super(struct super_block *); diff --git a/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO-rhel3.patch b/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO-rhel3.patch deleted file mode 100644 index bc66351..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO-rhel3.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -X /home/nikita/src/linux-git/linux-2.6.git/Documentation/dontdiff -rupbB linux-2.4.24.orig/fs/jbd/commit.c linux-2.4.24/fs/jbd/commit.c ---- linux-2.4.24.orig/fs/jbd/commit.c 2005-06-23 17:39:32.000000000 +0400 -+++ linux-2.4.24/fs/jbd/commit.c 2005-06-23 15:56:05.000000000 +0400 -@@ -505,6 +505,9 @@ start_journal_io: - goto wait_for_iobuf; - } - -+ if (unlikely(!buffer_uptodate(bh))) -+ err = -EIO; -+ - clear_bit(BH_JWrite, &jh2bh(jh)->b_state); - - JBUFFER_TRACE(jh, "ph4: unfile after journal write"); -@@ -566,6 +569,9 @@ start_journal_io: - goto wait_for_ctlbuf; - } - -+ if (unlikely(!buffer_uptodate(bh))) -+ err = -EIO; -+ - BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile"); - clear_bit(BH_JWrite, &bh->b_state); - journal_unfile_buffer(jh); diff --git a/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch b/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch deleted file mode 100644 index ff2991f..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.24-jbd-handle-EIO.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff -X /home/nikita/src/linux-git/linux-2.6.git/Documentation/dontdiff -rupbB linux-2.4.24.orig/fs/jbd/commit.c linux-2.4.24/fs/jbd/commit.c ---- linux-2.4.24.orig/fs/jbd/commit.c 2005-06-23 17:39:32.000000000 +0400 -+++ linux-2.4.24/fs/jbd/commit.c 2005-06-23 15:56:05.000000000 +0400 -@@ -47,7 +47,7 @@ void journal_commit_transaction(journal_ - struct buffer_head *wbuf[64]; - int bufs; - int flags; -- int err; -+ int err = 0; - unsigned long blocknr; - char *tagp = NULL; - journal_header_t *header; -@@ -505,6 +505,9 @@ start_journal_io: - goto wait_for_iobuf; - } - -+ if (unlikely(!buffer_uptodate(bh))) -+ err = -EIO; -+ - clear_bit(BH_JWrite, &jh2bh(jh)->b_state); - - JBUFFER_TRACE(jh, "ph4: unfile after journal write"); -@@ -566,6 +569,9 @@ start_journal_io: - goto wait_for_ctlbuf; - } - -+ if (unlikely(!buffer_uptodate(bh))) -+ err = -EIO; -+ - BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile"); - clear_bit(BH_JWrite, &bh->b_state); - journal_unfile_buffer(jh); -@@ -610,6 +616,8 @@ start_journal_io: - bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(WRITE, bh); - wait_on_buffer(bh); -+ if (unlikely(!buffer_uptodate(bh))) -+ err = -EIO; - put_bh(bh); /* One for getblk() */ - journal_unlock_journal_head(descriptor); - } -@@ -621,6 +629,9 @@ start_journal_io: - - skip_commit: /* The journal should be unlocked by now. */ - -+ if (err) -+ __journal_abort_hard(journal); -+ - /* Call any callbacks that had been registered for handles in this - * transaction. It is up to the callback to free any allocated - * memory. diff --git a/lustre/kernel_patches/patches/linux-2.4.24-xattr-0.8.54.patch b/lustre/kernel_patches/patches/linux-2.4.24-xattr-0.8.54.patch deleted file mode 100644 index 5bd7ac4..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.24-xattr-0.8.54.patch +++ /dev/null @@ -1,5474 +0,0 @@ - Documentation/Configure.help | 66 ++ - arch/alpha/defconfig | 7 - arch/alpha/kernel/entry.S | 12 - arch/arm/defconfig | 7 - arch/arm/kernel/calls.S | 24 - arch/i386/defconfig | 7 - arch/ia64/defconfig | 7 - arch/ia64/kernel/entry.S | 24 - arch/m68k/defconfig | 7 - arch/mips/defconfig | 7 - arch/mips64/defconfig | 7 - arch/ppc/defconfig | 14 - arch/ppc64/kernel/misc.S | 2 - arch/s390/defconfig | 7 - arch/s390/kernel/entry.S | 24 - arch/s390x/defconfig | 7 - arch/s390x/kernel/entry.S | 24 - arch/s390x/kernel/wrapper32.S | 92 +++ - arch/sparc/defconfig | 7 - arch/sparc/kernel/systbls.S | 10 - arch/sparc64/defconfig | 7 - arch/sparc64/kernel/systbls.S | 20 - fs/Config.in | 14 - fs/Makefile | 3 - fs/ext2/Makefile | 4 - fs/ext2/file.c | 5 - fs/ext2/ialloc.c | 2 - fs/ext2/inode.c | 34 - - fs/ext2/namei.c | 14 - fs/ext2/super.c | 29 - fs/ext2/symlink.c | 14 - fs/ext2/xattr.c | 1212 +++++++++++++++++++++++++++++++++++++++++ - fs/ext2/xattr_user.c | 103 +++ - fs/ext3/Makefile | 10 - fs/ext3/file.c | 5 - fs/ext3/ialloc.c | 2 - fs/ext3/inode.c | 35 - - fs/ext3/namei.c | 21 - fs/ext3/super.c | 36 + - fs/ext3/symlink.c | 14 - fs/ext3/xattr.c | 1225 ++++++++++++++++++++++++++++++++++++++++++ - fs/ext3/xattr_user.c | 111 +++ - fs/jfs/jfs_xattr.h | 6 - fs/jfs/xattr.c | 6 - fs/mbcache.c | 648 ++++++++++++++++++++++ - include/asm-arm/unistd.h | 2 - include/asm-ia64/unistd.h | 13 - include/asm-ppc64/unistd.h | 2 - include/asm-s390/unistd.h | 15 - include/asm-s390x/unistd.h | 15 - include/asm-sparc/unistd.h | 24 - include/asm-sparc64/unistd.h | 24 - include/linux/cache_def.h | 15 - include/linux/errno.h | 4 - include/linux/ext2_fs.h | 31 - - include/linux/ext2_xattr.h | 157 +++++ - include/linux/ext3_fs.h | 31 - - include/linux/ext3_jbd.h | 8 - include/linux/ext3_xattr.h | 157 +++++ - include/linux/fs.h | 2 - include/linux/mbcache.h | 69 ++ - kernel/ksyms.c | 4 - mm/vmscan.c | 35 + - fs/ext3/ext3-exports.c | 14 + - 64 files changed, 4355 insertions(+), 195 deletions(-) - -Index: linux-2.4.24-vanilla/Documentation/Configure.help -=================================================================== ---- linux-2.4.24-vanilla.orig/Documentation/Configure.help 2004-01-10 17:05:37.000000000 +0300 -+++ linux-2.4.24-vanilla/Documentation/Configure.help 2004-01-10 17:20:28.000000000 +0300 -@@ -16295,6 +16295,39 @@ - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. - -+Ext2 extended attributes -+CONFIG_EXT2_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext2 extended attribute block sharing -+CONFIG_EXT2_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext2 extended user attributes -+CONFIG_EXT2_FS_XATTR_USER -+ This option enables extended user attributes on ext2. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext2 trusted extended attributes -+CONFIG_EXT2_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext2 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Ext3 journalling file system support (EXPERIMENTAL) - CONFIG_EXT3_FS - This is the journalling version of the Second extended file system -@@ -16327,6 +16360,39 @@ - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this may be dangerous. - -+Ext3 extended attributes -+CONFIG_EXT3_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext3 extended attribute block sharing -+CONFIG_EXT3_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext3 extended user attributes -+CONFIG_EXT3_FS_XATTR_USER -+ This option enables extended user attributes on ext3. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext3 trusted extended attributes -+CONFIG_EXT3_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext3 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Journal Block Device support (JBD for ext3) (EXPERIMENTAL) - CONFIG_JBD - This is a generic journalling layer for block devices. It is -Index: linux-2.4.24-vanilla/arch/alpha/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/alpha/defconfig 2004-01-10 17:04:37.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/alpha/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_ALPHA=y - # CONFIG_UID16 is not set - # CONFIG_RWSEM_GENERIC_SPINLOCK is not set -Index: linux-2.4.24-vanilla/arch/alpha/kernel/entry.S -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/alpha/kernel/entry.S 2004-01-10 17:04:37.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/alpha/kernel/entry.S 2004-01-10 17:20:28.000000000 +0300 -@@ -1154,6 +1154,18 @@ - .quad sys_readahead - .quad sys_ni_syscall /* 380, sys_security */ - .quad sys_tkill -+ .quad sys_setxattr -+ .quad sys_lsetxattr -+ .quad sys_fsetxattr -+ .quad sys_getxattr /* 385 */ -+ .quad sys_lgetxattr -+ .quad sys_fgetxattr -+ .quad sys_listxattr -+ .quad sys_llistxattr -+ .quad sys_flistxattr /* 390 */ -+ .quad sys_removexattr -+ .quad sys_lremovexattr -+ .quad sys_fremovexattr - - /* Remember to update everything, kids. */ - .ifne (. - sys_call_table) - (NR_SYSCALLS * 8) -Index: linux-2.4.24-vanilla/arch/arm/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/arm/defconfig 2001-05-20 04:43:05.000000000 +0400 -+++ linux-2.4.24-vanilla/arch/arm/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_ARM=y - # CONFIG_EISA is not set - # CONFIG_SBUS is not set -Index: linux-2.4.24-vanilla/arch/arm/kernel/calls.S -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/arm/kernel/calls.S 2004-01-10 17:04:58.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/arm/kernel/calls.S 2004-01-10 17:20:28.000000000 +0300 -@@ -240,18 +240,18 @@ - .long SYMBOL_NAME(sys_ni_syscall) /* Security */ - .long SYMBOL_NAME(sys_gettid) - /* 225 */ .long SYMBOL_NAME(sys_readahead) -- .long SYMBOL_NAME(sys_ni_syscall) /* setxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* getxattr */ --/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* listxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* llistxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* flistxattr */ --/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* removexattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */ -+ .long SYMBOL_NAME(sys_setxattr) -+ .long SYMBOL_NAME(sys_lsetxattr) -+ .long SYMBOL_NAME(sys_fsetxattr) -+ .long SYMBOL_NAME(sys_getxattr) -+/* 230 */ .long SYMBOL_NAME(sys_lgetxattr) -+ .long SYMBOL_NAME(sys_fgetxattr) -+ .long SYMBOL_NAME(sys_listxattr) -+ .long SYMBOL_NAME(sys_llistxattr) -+ .long SYMBOL_NAME(sys_flistxattr) -+/* 235 */ .long SYMBOL_NAME(sys_removexattr) -+ .long SYMBOL_NAME(sys_lremovexattr) -+ .long SYMBOL_NAME(sys_fremovexattr) - .long SYMBOL_NAME(sys_tkill) - .long SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */ - /* 240 */ .long SYMBOL_NAME(sys_ni_syscall) /* futex */ -Index: linux-2.4.24-vanilla/arch/i386/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/i386/defconfig 2004-01-10 17:05:45.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/i386/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_X86=y - CONFIG_ISA=y - # CONFIG_SBUS is not set -Index: linux-2.4.24-vanilla/arch/ia64/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/ia64/defconfig 2004-01-10 17:05:52.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/ia64/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - - # - # Code maturity level options -Index: linux-2.4.24-vanilla/arch/m68k/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/m68k/defconfig 2004-01-10 17:05:52.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/m68k/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_UID16=y - - # -Index: linux-2.4.24-vanilla/arch/mips/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/mips/defconfig 2004-01-10 17:04:59.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/mips/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_MIPS=y - CONFIG_MIPS32=y - # CONFIG_MIPS64 is not set -Index: linux-2.4.24-vanilla/arch/mips64/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/mips64/defconfig 2004-01-10 17:05:52.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/mips64/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_MIPS=y - # CONFIG_MIPS32 is not set - CONFIG_MIPS64=y -Index: linux-2.4.24-vanilla/arch/s390/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/s390/defconfig 2004-01-10 17:05:52.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/s390/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - # CONFIG_ISA is not set - # CONFIG_EISA is not set - # CONFIG_MCA is not set -Index: linux-2.4.24-vanilla/arch/s390/kernel/entry.S -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/s390/kernel/entry.S 2004-01-10 17:04:39.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/s390/kernel/entry.S 2004-01-10 17:20:28.000000000 +0300 -@@ -558,18 +558,18 @@ - .long sys_fcntl64 - .long sys_readahead - .long sys_ni_syscall -- .long sys_ni_syscall /* 224 - reserved for setxattr */ -- .long sys_ni_syscall /* 225 - reserved for lsetxattr */ -- .long sys_ni_syscall /* 226 - reserved for fsetxattr */ -- .long sys_ni_syscall /* 227 - reserved for getxattr */ -- .long sys_ni_syscall /* 228 - reserved for lgetxattr */ -- .long sys_ni_syscall /* 229 - reserved for fgetxattr */ -- .long sys_ni_syscall /* 230 - reserved for listxattr */ -- .long sys_ni_syscall /* 231 - reserved for llistxattr */ -- .long sys_ni_syscall /* 232 - reserved for flistxattr */ -- .long sys_ni_syscall /* 233 - reserved for removexattr */ -- .long sys_ni_syscall /* 234 - reserved for lremovexattr */ -- .long sys_ni_syscall /* 235 - reserved for fremovexattr */ -+ .long sys_setxattr -+ .long sys_lsetxattr /* 225 */ -+ .long sys_fsetxattr -+ .long sys_getxattr -+ .long sys_lgetxattr -+ .long sys_fgetxattr -+ .long sys_listxattr /* 230 */ -+ .long sys_llistxattr -+ .long sys_flistxattr -+ .long sys_removexattr -+ .long sys_lremovexattr -+ .long sys_fremovexattr /* 235 */ - .long sys_gettid - .long sys_tkill - .rept 255-237 -Index: linux-2.4.24-vanilla/arch/s390x/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/s390x/defconfig 2004-01-10 17:05:52.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/s390x/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - # CONFIG_ISA is not set - # CONFIG_EISA is not set - # CONFIG_MCA is not set -Index: linux-2.4.24-vanilla/arch/s390x/kernel/entry.S -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/s390x/kernel/entry.S 2004-01-10 17:05:00.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/s390x/kernel/entry.S 2004-01-10 17:20:28.000000000 +0300 -@@ -591,18 +591,18 @@ - .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper) - .long SYSCALL(sys_readahead,sys32_readahead) - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */ -+ .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper) -+ .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */ -+ .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper) -+ .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper) -+ .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper) -+ .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper) -+ .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */ -+ .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper) -+ .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper) -+ .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper) -+ .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper) -+ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */ - .long SYSCALL(sys_gettid,sys_gettid) - .long SYSCALL(sys_tkill,sys_tkill) - .rept 255-237 -Index: linux-2.4.24-vanilla/arch/s390x/kernel/wrapper32.S -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/s390x/kernel/wrapper32.S 2004-01-10 17:05:00.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/s390x/kernel/wrapper32.S 2004-01-10 17:20:28.000000000 +0300 -@@ -1098,6 +1098,98 @@ - llgfr %r4,%r4 # long - jg sys32_fstat64 # branch to system call - -+ .globl sys32_setxattr_wrapper -+sys32_setxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ lgfr %r6,%r6 # int -+ jg sys_setxattr -+ -+ .globl sys32_lsetxattr_wrapper -+sys32_lsetxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ lgfr %r6,%r6 # int -+ jg sys_lsetxattr -+ -+ .globl sys32_fsetxattr_wrapper -+sys32_fsetxattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ lgfr %r6,%r6 # int -+ jg sys_fsetxattr -+ -+ .globl sys32_getxattr_wrapper -+sys32_getxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ jg sys_getxattr -+ -+ .globl sys32_lgetxattr_wrapper -+sys32_lgetxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ jg sys_lgetxattr -+ -+ .globl sys32_fgetxattr_wrapper -+sys32_fgetxattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ jg sys_fgetxattr -+ -+ .globl sys32_listxattr_wrapper -+sys32_listxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgfr %r4,%r4 # size_t -+ jg sys_listxattr -+ -+ .globl sys32_llistxattr_wrapper -+sys32_llistxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgfr %r4,%r4 # size_t -+ jg sys_llistxattr -+ -+ .globl sys32_flistxattr_wrapper -+sys32_flistxattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ llgfr %r4,%r4 # size_t -+ jg sys_flistxattr -+ -+ .globl sys32_removexattr_wrapper -+sys32_removexattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ jg sys_removexattr -+ -+ .globl sys32_lremovexattr_wrapper -+sys32_lremovexattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ jg sys_lremovexattr -+ -+ .globl sys32_fremovexattr_wrapper -+sys32_fremovexattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ jg sys_fremovexattr -+ -+ -+ - .globl sys32_stime_wrapper - sys32_stime_wrapper: - llgtr %r2,%r2 # int * -Index: linux-2.4.24-vanilla/arch/sparc64/defconfig -=================================================================== ---- linux-2.4.24-vanilla.orig/arch/sparc64/defconfig 2004-01-10 17:05:52.000000000 +0300 -+++ linux-2.4.24-vanilla/arch/sparc64/defconfig 2004-01-10 17:20:28.000000000 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - - # - # Code maturity level options -Index: linux-2.4.24-vanilla/fs/Config.in -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/Config.in 2004-01-10 17:05:55.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/Config.in 2004-01-10 17:20:28.000000000 +0300 -@@ -29,6 +29,11 @@ - dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL - - tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS -+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS -+dep_bool ' Ext3 extended attribute block sharing' \ -+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR -+dep_bool ' Ext3 extended user attributes' \ -+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR - # CONFIG_JBD could be its own option (even modular), but until there are - # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS - # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS -@@ -92,6 +97,11 @@ - tristate 'ROM file system support' CONFIG_ROMFS_FS - - tristate 'Second extended fs support' CONFIG_EXT2_FS -+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS -+dep_bool ' Ext2 extended attribute block sharing' \ -+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR -+dep_bool ' Ext2 extended user attributes' \ -+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR - - tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS - -@@ -164,6 +174,10 @@ - define_tristate CONFIG_ZISOFS_FS n - fi - -+# Meta block cache for Extended Attributes (ext2/ext3) -+#tristate 'Meta block cache' CONFIG_FS_MBCACHE -+define_tristate CONFIG_FS_MBCACHE y -+ - mainmenu_option next_comment - comment 'Partition Types' - source fs/partitions/Config.in -Index: linux-2.4.24-vanilla/fs/Makefile -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/Makefile 2004-01-10 17:11:48.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/Makefile 2004-01-10 17:20:28.000000000 +0300 -@@ -77,6 +77,9 @@ - - obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o - -+export-objs += mbcache.o -+obj-$(CONFIG_FS_MBCACHE) += mbcache.o -+ - # persistent filesystems - obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) - -Index: linux-2.4.24-vanilla/fs/ext2/Makefile -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/Makefile 2001-10-11 19:05:18.000000000 +0400 -+++ linux-2.4.24-vanilla/fs/ext2/Makefile 2004-01-10 17:20:28.000000000 +0300 -@@ -13,4 +13,8 @@ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) - -+export-objs += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make -Index: linux-2.4.24-vanilla/fs/ext2/file.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/file.c 2001-10-11 19:05:18.000000000 +0400 -+++ linux-2.4.24-vanilla/fs/ext2/file.c 2004-01-10 17:20:28.000000000 +0300 -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - - /* -@@ -51,4 +52,8 @@ - - struct inode_operations ext2_file_inode_operations = { - truncate: ext2_truncate, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.24-vanilla/fs/ext2/ialloc.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/ialloc.c 2004-01-10 17:04:42.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext2/ialloc.c 2004-01-10 17:20:28.000000000 +0300 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -167,6 +168,7 @@ - */ - if (!is_bad_inode(inode)) { - /* Quota is already initialized in iput() */ -+ ext2_xattr_delete_inode(inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - } -Index: linux-2.4.24-vanilla/fs/ext2/inode.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/inode.c 2004-01-10 17:04:42.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext2/inode.c 2004-01-10 17:20:28.000000000 +0300 -@@ -39,6 +39,18 @@ - static int ext2_update_inode(struct inode * inode, int do_sync); - - /* -+ * Test whether an inode is a fast symlink. -+ */ -+static inline int ext2_inode_is_fast_symlink(struct inode *inode) -+{ -+ int ea_blocks = inode->u.ext2_i.i_file_acl ? -+ (inode->i_sb->s_blocksize >> 9) : 0; -+ -+ return (S_ISLNK(inode->i_mode) && -+ inode->i_blocks - ea_blocks == 0); -+} -+ -+/* - * Called at each iput() - */ - void ext2_put_inode (struct inode * inode) -@@ -53,9 +65,7 @@ - { - lock_kernel(); - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - inode->u.ext2_i.i_dtime = CURRENT_TIME; - mark_inode_dirty(inode); -@@ -801,6 +811,8 @@ - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; -+ if (ext2_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -903,8 +915,7 @@ - unsigned long offset; - struct ext2_group_desc * gdp; - -- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO && -- inode->i_ino != EXT2_ACL_DATA_INO && -+ if ((inode->i_ino != EXT2_ROOT_INO && - inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) { - ext2_error (inode->i_sb, "ext2_read_inode", -@@ -989,10 +1000,7 @@ - for (block = 0; block < EXT2_N_BLOCKS; block++) - inode->u.ext2_i.i_data[block] = raw_inode->i_block[block]; - -- if (inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext2_file_inode_operations; - inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; -@@ -1001,15 +1009,17 @@ - inode->i_fop = &ext2_dir_operations; - inode->i_mapping->a_ops = &ext2_aops; - } else if (S_ISLNK(inode->i_mode)) { -- if (!inode->i_blocks) -+ if (ext2_inode_is_fast_symlink(inode)) - inode->i_op = &ext2_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - } -- } else -+ } else { -+ inode->i_op = &ext2_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); -+ } - brelse (bh); - inode->i_attr_flags = 0; - ext2_set_inode_flags(inode); -Index: linux-2.4.24-vanilla/fs/ext2/namei.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/namei.c 2001-10-04 09:57:36.000000000 +0400 -+++ linux-2.4.24-vanilla/fs/ext2/namei.c 2004-01-10 17:20:28.000000000 +0300 -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - - /* -@@ -136,7 +137,7 @@ - - if (l > sizeof (inode->u.ext2_i.i_data)) { - /* slow symlink */ -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); - if (err) -@@ -345,4 +346,15 @@ - rmdir: ext2_rmdir, - mknod: ext2_mknod, - rename: ext2_rename, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ -+struct inode_operations ext2_special_inode_operations = { -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.24-vanilla/fs/ext2/super.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/super.c 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.24-vanilla/fs/ext2/super.c 2004-01-10 17:20:28.000000000 +0300 -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -125,6 +126,7 @@ - int db_count; - int i; - -+ ext2_xattr_put_super(sb); - if (!(sb->s_flags & MS_RDONLY)) { - struct ext2_super_block *es = EXT2_SB(sb)->s_es; - -@@ -175,6 +177,13 @@ - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -424,6 +433,9 @@ - blocksize = BLOCK_SIZE; - - sb->u.ext2_sb.s_mount_opt = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */ -+#endif - if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, - &sb->u.ext2_sb.s_mount_opt)) { - return NULL; -@@ -813,12 +825,27 @@ - - static int __init init_ext2_fs(void) - { -- return register_filesystem(&ext2_fs_type); -+ int error = init_ext2_xattr(); -+ if (error) -+ return error; -+ error = init_ext2_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext2_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext2_xattr_user(); -+fail: -+ exit_ext2_xattr(); -+ return error; - } - - static void __exit exit_ext2_fs(void) - { - unregister_filesystem(&ext2_fs_type); -+ exit_ext2_xattr_user(); -+ exit_ext2_xattr(); - } - - EXPORT_NO_SYMBOLS; -Index: linux-2.4.24-vanilla/fs/ext2/symlink.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/symlink.c 2000-09-28 00:41:33.000000000 +0400 -+++ linux-2.4.24-vanilla/fs/ext2/symlink.c 2004-01-10 17:20:28.000000000 +0300 -@@ -19,6 +19,7 @@ - - #include - #include -+#include - - static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -32,7 +33,20 @@ - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext2_symlink_inode_operations = { -+ readlink: page_readlink, -+ follow_link: page_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ - struct inode_operations ext2_fast_symlink_inode_operations = { - readlink: ext2_readlink, - follow_link: ext2_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.24-vanilla/fs/ext2/xattr.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/xattr.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext2/xattr.c 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,1212 @@ -+/* -+ * linux/fs/ext2/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT2_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT2_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext2_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* These symbols may be needed by a module. */ -+EXPORT_SYMBOL(ext2_xattr_register); -+EXPORT_SYMBOL(ext2_xattr_unregister); -+EXPORT_SYMBOL(ext2_xattr_get); -+EXPORT_SYMBOL(ext2_xattr_list); -+EXPORT_SYMBOL(ext2_xattr_set); -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT2_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext2_xattr_set2(struct inode *, struct buffer_head *, -+ struct ext2_xattr_header *); -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+static int ext2_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext2_xattr_cache_find(struct inode *, -+ struct ext2_xattr_header *); -+static void ext2_xattr_cache_remove(struct buffer_head *); -+static void ext2_xattr_rehash(struct ext2_xattr_header *, -+ struct ext2_xattr_entry *); -+ -+static struct mb_cache *ext2_xattr_cache; -+ -+#else -+# define ext2_xattr_cache_insert(bh) 0 -+# define ext2_xattr_cache_find(inode, header) NULL -+# define ext2_xattr_cache_remove(bh) while(0) {} -+# define ext2_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext2_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext2_xattr_sem); -+ -+static inline int -+ext2_xattr_new_block(struct inode *inode, int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) + -+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext2_new_block(inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext2_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext2_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext2_xattr_free_block(struct inode * inode, unsigned long block) -+{ -+ ext2_free_blocks(inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext2_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext2_xattr_free_block(inode, block) \ -+ ext2_free_blocks(inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX]; -+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ if (!ext2_xattr_handlers[name_index-1]) { -+ ext2_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext2_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler) -+{ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ ext2_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext2_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static struct ext2_xattr_handler * -+ext2_xattr_resolve_name(const char **name) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext2_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext2_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext2_handler_lock); -+ return handler; -+} -+ -+static inline struct ext2_xattr_handler * -+ext2_xattr_handler(int name_index) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ read_lock(&ext2_handler_lock); -+ handler = ext2_xattr_handlers[name_index-1]; -+ read_unlock(&ext2_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext2_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext2_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT2_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT2_I(inode)->i_file_acl) -+ return 0; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext2_xattr_update_super_block(struct super_block *sb) -+{ -+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT2_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext2_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_header *header = NULL; -+ struct ext2_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT2_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext2_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(sb, "ext2_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext2_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT2_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT2_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT2_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext2_xattr_cache_remove(bh); -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT2_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT2_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext2_xattr_set2(inode, bh, NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT2_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT2_XATTR_PAD, 0, -+ EXT2_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext2_xattr_rehash(header, here); -+ -+ error = ext2_xattr_set2(inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext2_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext2_xattr_set(): Update the file system. -+ */ -+static int -+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, -+ struct ext2_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext2_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext2_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext2_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT2_I(inode)->i_file_acl != 0; -+ int block = ext2_xattr_new_block(inode, &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+ ext2_xattr_free_block(inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext2_xattr_cache_insert(new_bh); -+ -+ ext2_xattr_update_super_block(sb); -+ } -+ mark_buffer_dirty(new_bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &new_bh); -+ wait_on_buffer(new_bh); -+ error = -EIO; -+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh)) -+ goto cleanup; -+ } -+ } -+ -+ /* Update the inode. */ -+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ if (IS_SYNC(inode)) { -+ error = ext2_sync_inode (inode); -+ if (error) -+ goto cleanup; -+ } else -+ mark_inode_dirty(inode); -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext2_xattr_free_block(inode, old_bh->b_blocknr); -+ mark_buffer_clean(old_bh); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext2_xattr_quota_free(inode); -+ mark_buffer_dirty(old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT2_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext2_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext2_xattr_cache_remove(bh); -+ ext2_xattr_free_block(inode, block); -+ bforget(bh); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ mark_buffer_dirty(bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &bh); -+ wait_on_buffer(bh); -+ } -+ ext2_xattr_quota_free(inode); -+ } -+ EXT2_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext2_xattr_sem); -+} -+ -+/* -+ * ext2_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+/* -+ * ext2_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext2_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext2_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext2_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext2_xattr_cmp(struct ext2_xattr_header *header1, -+ struct ext2_xattr_header *header2) -+{ -+ struct ext2_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT2_XATTR_NEXT(entry1); -+ entry2 = EXT2_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext2_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT2_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT2_XATTR_REFCOUNT_MAX); -+ } else if (!ext2_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext2_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext2_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext2_xattr_rehash(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ struct ext2_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext2_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT2_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext2_xattr(void) -+{ -+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext2_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+ mb_cache_destroy(ext2_xattr_cache); -+} -+ -+#else /* CONFIG_EXT2_FS_XATTR_SHARING */ -+ -+int __init -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */ -Index: linux-2.4.24-vanilla/fs/ext2/xattr_user.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext2/xattr_user.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext2/xattr_user.c 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,103 @@ -+/* -+ * linux/fs/ext2/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext2_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext2_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext2_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, -+ value, size, flags); -+} -+ -+struct ext2_xattr_handler ext2_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext2_xattr_user_list, -+ get: ext2_xattr_user_get, -+ set: ext2_xattr_user_set, -+}; -+ -+int __init -+init_ext2_xattr_user(void) -+{ -+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -+ -+void -+exit_ext2_xattr_user(void) -+{ -+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -Index: linux-2.4.24-vanilla/fs/ext3/Makefile -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/Makefile 2004-01-10 17:11:50.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/Makefile 2004-01-10 17:20:28.000000000 +0300 -@@ -1,5 +1,5 @@ - # --# Makefile for the linux ext2-filesystem routines. -+# Makefile for the linux ext3-filesystem routines. - # - # Note! Dependencies are done automagically by 'make dep', which also - # removes any old dependencies. DON'T put your own dependencies here -@@ -9,10 +9,14 @@ - - O_TARGET := ext3.o - --export-objs := super.o inode.o -+export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o hash.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - -+export-objs += xattr.o -+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make -Index: linux-2.4.24-vanilla/fs/ext3/file.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/file.c 2004-01-10 17:11:50.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/file.c 2004-01-10 17:20:28.000000000 +0300 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -127,5 +128,9 @@ - struct inode_operations ext3_file_inode_operations = { - truncate: ext3_truncate, /* BKL held */ - setattr: ext3_setattr, /* BKL held */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; - -Index: linux-2.4.24-vanilla/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/ialloc.c 2004-01-10 17:04:42.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/ialloc.c 2004-01-10 17:20:28.000000000 +0300 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -216,6 +217,7 @@ - * as writing the quota to disk may need the lock as well. - */ - DQUOT_INIT(inode); -+ ext3_xattr_delete_inode(handle, inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - -Index: linux-2.4.24-vanilla/fs/ext3/inode.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/inode.c 2004-01-10 17:05:05.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/inode.c 2004-01-10 17:20:28.000000000 +0300 -@@ -39,6 +39,18 @@ - */ - #undef SEARCH_FROM_ZERO - -+/* -+ * Test whether an inode is a fast symlink. -+ */ -+static inline int ext3_inode_is_fast_symlink(struct inode *inode) -+{ -+ int ea_blocks = inode->u.ext3_i.i_file_acl ? -+ (inode->i_sb->s_blocksize >> 9) : 0; -+ -+ return (S_ISLNK(inode->i_mode) && -+ inode->i_blocks - ea_blocks == 0); -+} -+ - /* The ext3 forget function must perform a revoke if we are freeing data - * which has been journaled. Metadata (eg. indirect blocks) must be - * revoked in all cases. -@@ -48,7 +60,7 @@ - * still needs to be revoked. - */ - --static int ext3_forget(handle_t *handle, int is_metadata, -+int ext3_forget(handle_t *handle, int is_metadata, - struct inode *inode, struct buffer_head *bh, - int blocknr) - { -@@ -179,9 +191,7 @@ - { - handle_t *handle; - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT3_ACL_IDX_INO || -- inode->i_ino == EXT3_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - - lock_kernel(); -@@ -1870,6 +1880,8 @@ - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return; -+ if (ext3_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -2017,8 +2029,6 @@ - struct ext3_group_desc * gdp; - - if ((inode->i_ino != EXT3_ROOT_INO && -- inode->i_ino != EXT3_ACL_IDX_INO && -- inode->i_ino != EXT3_ACL_DATA_INO && - inode->i_ino != EXT3_JOURNAL_INO && - inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu( -@@ -2159,10 +2169,7 @@ - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); - -- if (inode->i_ino == EXT3_ACL_IDX_INO || -- inode->i_ino == EXT3_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; -@@ -2170,15 +2177,17 @@ - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; - } else if (S_ISLNK(inode->i_mode)) { -- if (!inode->i_blocks) -+ if (ext3_inode_is_fast_symlink(inode)) - inode->i_op = &ext3_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - } -- } else -+ } else { -+ inode->i_op = &ext3_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(iloc.raw_inode->i_block[0])); -+ } - brelse(iloc.bh); - ext3_set_inode_flags(inode); - return; -Index: linux-2.4.24-vanilla/fs/ext3/namei.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/namei.c 2004-01-10 17:11:50.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/namei.c 2004-01-10 17:20:28.000000000 +0300 -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1613,7 +1614,7 @@ - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFDIR); -+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -@@ -1621,7 +1622,6 @@ - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; - inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; -- inode->i_blocks = 0; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ -@@ -1648,9 +1648,6 @@ - BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, dir_block); - brelse (dir_block); -- inode->i_mode = S_IFDIR | mode; -- if (dir->i_mode & S_ISGID) -- inode->i_mode |= S_ISGID; - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); - if (err) { -@@ -2019,7 +2016,7 @@ - goto out_stop; - - if (l > sizeof (EXT3_I(inode)->i_data)) { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* - * block_symlink() calls back into ext3_prepare/commit_write. -@@ -2244,4 +2241,16 @@ - rmdir: ext3_rmdir, /* BKL held */ - mknod: ext3_mknod, /* BKL held */ - rename: ext3_rename, /* BKL held */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; -+ -+struct inode_operations ext3_special_inode_operations = { -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ -+}; -+ -Index: linux-2.4.24-vanilla/fs/ext3/super.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/super.c 2004-01-10 17:11:50.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/super.c 2004-01-10 17:20:28.000000000 +0300 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -406,6 +407,7 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+ ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { - EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -@@ -505,6 +507,7 @@ - int is_remount) - { - unsigned long *mount_options = &sbi->s_mount_opt; -+ - uid_t *resuid = &sbi->s_resuid; - gid_t *resgid = &sbi->s_resgid; - char * this_char; -@@ -517,6 +520,13 @@ - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT3_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -934,6 +944,12 @@ - sbi->s_mount_opt = 0; - sbi->s_resuid = EXT3_DEF_RESUID; - sbi->s_resgid = EXT3_DEF_RESGID; -+ -+ /* Default extended attribute flags */ -+#ifdef CONFIG_EXT3_FS_XATTR_USER -+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */ -+#endif -+ - if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) { - sb->s_dev = 0; - goto out_fail; -@@ -1822,22 +1838,35 @@ - - static int __init init_ext3_fs(void) - { -+ int error; - #ifdef CONFIG_QUOTA - init_dquot_operations(&ext3_qops); - old_sync_dquot = ext3_qops.sync_dquot; - ext3_qops.sync_dquot = ext3_sync_dquot; - #endif -- return register_filesystem(&ext3_fs_type); -+ error = init_ext3_xattr(); -+ if (error) -+ return error; -+ error = init_ext3_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext3_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext3_xattr_user(); -+fail: -+ exit_ext3_xattr(); -+ return error; - } - - static void __exit exit_ext3_fs(void) - { - unregister_filesystem(&ext3_fs_type); -+ exit_ext3_xattr_user(); -+ exit_ext3_xattr(); - } - --EXPORT_SYMBOL(ext3_force_commit); --EXPORT_SYMBOL(ext3_bread); -- - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); - MODULE_LICENSE("GPL"); -Index: linux-2.4.24-vanilla/fs/ext3/symlink.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/symlink.c 2001-11-10 01:25:04.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/symlink.c 2004-01-10 17:20:28.000000000 +0300 -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -33,7 +34,20 @@ - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext3_symlink_inode_operations = { -+ readlink: page_readlink, /* BKL not held. Don't need */ -+ follow_link: page_follow_link, /* BKL not held. Don't need */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ -+}; -+ - struct inode_operations ext3_fast_symlink_inode_operations = { - readlink: ext3_readlink, /* BKL not held. Don't need */ - follow_link: ext3_follow_link, /* BKL not held. Don't need */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; -Index: linux-2.4.24-vanilla/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/xattr.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/xattr.c 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,1225 @@ -+/* -+ * linux/fs/ext3/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Ext3 code with a lot of help from Eric Jarman . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT3_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define EXT3_EA_USER "user." -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT3_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *, -+ struct ext3_xattr_header *); -+ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ -+static int ext3_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext3_xattr_cache_find(struct inode *, -+ struct ext3_xattr_header *); -+static void ext3_xattr_cache_remove(struct buffer_head *); -+static void ext3_xattr_rehash(struct ext3_xattr_header *, -+ struct ext3_xattr_entry *); -+ -+static struct mb_cache *ext3_xattr_cache; -+ -+#else -+# define ext3_xattr_cache_insert(bh) 0 -+# define ext3_xattr_cache_find(inode, header) NULL -+# define ext3_xattr_cache_remove(bh) while(0) {} -+# define ext3_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext3_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext3_xattr_sem); -+ -+static inline int -+ext3_xattr_new_block(handle_t *handle, struct inode *inode, -+ int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) + -+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext3_new_block(handle, inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext3_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext3_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext3_xattr_free_block(handle_t *handle, struct inode * inode, -+ unsigned long block) -+{ -+ ext3_free_blocks(handle, inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext3_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext3_xattr_free_block(handle, inode, block) \ -+ ext3_free_blocks(handle, inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX]; -+rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) { -+ write_lock(&ext3_handler_lock); -+ if (!ext3_xattr_handlers[name_index-1]) { -+ ext3_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext3_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler) -+{ -+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) { -+ write_lock(&ext3_handler_lock); -+ ext3_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext3_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static inline struct ext3_xattr_handler * -+ext3_xattr_resolve_name(const char **name) -+{ -+ struct ext3_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext3_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext3_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext3_handler_lock); -+ return handler; -+} -+ -+static inline struct ext3_xattr_handler * -+ext3_xattr_handler(int name_index) -+{ -+ struct ext3_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) { -+ read_lock(&ext3_handler_lock); -+ handler = ext3_xattr_handlers[name_index-1]; -+ read_unlock(&ext3_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext3_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext3_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext3_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext3_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext3_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT3_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT3_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT3_I(inode)->i_file_acl) -+ return 0; -+ block = EXT3_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT3_XATTR_NEXT(entry)) { -+ struct ext3_xattr_handler *handler; -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext3_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT3_XATTR_NEXT(entry)) { -+ struct ext3_xattr_handler *handler; -+ -+ handler = ext3_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext3_xattr_update_super_block(handle_t *handle, -+ struct super_block *sb) -+{ -+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT3_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext3_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_header *header = NULL; -+ struct ext3_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT3_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext3_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(sb, "ext3_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT3_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT3_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT3_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext3_xattr_cache_remove(bh); -+ error = ext3_journal_get_write_access(handle, bh); -+ if (error) -+ goto cleanup; -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT3_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT3_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT3_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext3_xattr_set2(handle, inode, bh,NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT3_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT3_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT3_XATTR_PAD, 0, -+ EXT3_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext3_xattr_rehash(header, here); -+ -+ error = ext3_xattr_set2(handle, inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext3_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext3_xattr_set(): Update the file system. -+ */ -+static int -+ext3_xattr_set2(handle_t *handle, struct inode *inode, -+ struct buffer_head *old_bh, struct ext3_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext3_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext3_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ error = ext3_journal_get_write_access(handle, new_bh); -+ if (error) -+ goto cleanup; -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext3_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT3_I(inode)->i_file_acl != 0; -+ int block = ext3_xattr_new_block(handle, inode, -+ &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+getblk_failed: ext3_xattr_free_block(handle, inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ error = ext3_journal_get_create_access(handle, new_bh); -+ if (error) { -+ unlock_buffer(new_bh); -+ goto getblk_failed; -+ } -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext3_xattr_cache_insert(new_bh); -+ -+ ext3_xattr_update_super_block(handle, sb); -+ } -+ error = ext3_journal_dirty_metadata(handle, new_bh); -+ if (error) -+ goto cleanup; -+ } -+ -+ /* Update the inode. */ -+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ ext3_mark_inode_dirty(handle, inode); -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ error = ext3_journal_get_write_access(handle, old_bh); -+ if (error) -+ goto cleanup; -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext3_xattr_free_block(handle, inode, old_bh->b_blocknr); -+ -+ /* ext3_forget() calls bforget() for us, but we -+ let our caller release old_bh, so we need to -+ duplicate the handle before. */ -+ get_bh(old_bh); -+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext3_xattr_quota_free(inode); -+ ext3_journal_dirty_metadata(handle, old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT3_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext3_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ext3_journal_get_write_access(handle, bh); -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext3_xattr_cache_remove(bh); -+ ext3_xattr_free_block(handle, inode, block); -+ ext3_forget(handle, 1, inode, bh, block); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ ext3_journal_dirty_metadata(handle, bh); -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ ext3_xattr_quota_free(inode); -+ } -+ EXT3_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext3_xattr_sem); -+} -+ -+/* -+ * ext3_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext3_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ mb_cache_shrink(ext3_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ -+/* -+ * ext3_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext3_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext3_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext3_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext3_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext3_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext3_xattr_cmp(struct ext3_xattr_header *header1, -+ struct ext3_xattr_header *header2) -+{ -+ struct ext3_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT3_XATTR_NEXT(entry1); -+ entry2 = EXT3_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext3_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext3_error(inode->i_sb, "ext3_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT3_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT3_XATTR_REFCOUNT_MAX); -+ } else if (!ext3_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext3_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext3_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext3_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext3_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header, -+ struct ext3_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext3_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext3_xattr_rehash(struct ext3_xattr_header *header, -+ struct ext3_xattr_entry *entry) -+{ -+ struct ext3_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext3_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT3_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext3_xattr(void) -+{ -+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext3_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext3_xattr(void) -+{ -+ if (ext3_xattr_cache) -+ mb_cache_destroy(ext3_xattr_cache); -+ ext3_xattr_cache = NULL; -+} -+ -+#else /* CONFIG_EXT3_FS_XATTR_SHARING */ -+ -+int __init -+init_ext3_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext3_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT3_FS_XATTR_SHARING */ -Index: linux-2.4.24-vanilla/fs/ext3/xattr_user.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/xattr_user.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/xattr_user.c 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,111 @@ -+/* -+ * linux/fs/ext3/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext3_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext3_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+ error = ext3_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext3_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ handle_t *handle; -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+ error = ext3_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name, -+ value, size, flags); -+ ext3_journal_stop(handle, inode); -+ -+ return error; -+} -+ -+struct ext3_xattr_handler ext3_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext3_xattr_user_list, -+ get: ext3_xattr_user_get, -+ set: ext3_xattr_user_set, -+}; -+ -+int __init -+init_ext3_xattr_user(void) -+{ -+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER, -+ &ext3_xattr_user_handler); -+} -+ -+void -+exit_ext3_xattr_user(void) -+{ -+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, -+ &ext3_xattr_user_handler); -+} -Index: linux-2.4.24-vanilla/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/ext3/ext3-exports.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/ext3/ext3-exports.c 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,13 @@ -+#include -+#include -+#include -+#include -+#include -+ -+EXPORT_SYMBOL(ext3_force_commit); -+EXPORT_SYMBOL(ext3_bread); -+EXPORT_SYMBOL(ext3_xattr_register); -+EXPORT_SYMBOL(ext3_xattr_unregister); -+EXPORT_SYMBOL(ext3_xattr_get); -+EXPORT_SYMBOL(ext3_xattr_list); -+EXPORT_SYMBOL(ext3_xattr_set); -Index: linux-2.4.24-vanilla/fs/jfs/jfs_xattr.h -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/jfs/jfs_xattr.h 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.24-vanilla/fs/jfs/jfs_xattr.h 2004-01-10 17:20:28.000000000 +0300 -@@ -52,8 +52,10 @@ - #define END_EALIST(ealist) \ - ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) - --extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int); --extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int); -+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, -+ int); -+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, -+ int); - extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); - extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); - extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); -Index: linux-2.4.24-vanilla/fs/jfs/xattr.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/jfs/xattr.c 2004-01-10 17:05:55.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/jfs/xattr.c 2004-01-10 17:20:28.000000000 +0300 -@@ -648,7 +648,7 @@ - } - - static int can_set_xattr(struct inode *inode, const char *name, -- void *value, size_t value_len) -+ const void *value, size_t value_len) - { - if (IS_RDONLY(inode)) - return -EROFS; -@@ -667,7 +667,7 @@ - return permission(inode, MAY_WRITE); - } - --int __jfs_setxattr(struct inode *inode, const char *name, void *value, -+int __jfs_setxattr(struct inode *inode, const char *name, const void *value, - size_t value_len, int flags) - { - struct jfs_ea_list *ealist; -@@ -806,7 +806,7 @@ - return rc; - } - --int jfs_setxattr(struct dentry *dentry, const char *name, void *value, -+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t value_len, int flags) - { - if (value == NULL) { /* empty EA, do not remove */ -Index: linux-2.4.24-vanilla/fs/mbcache.c -=================================================================== ---- linux-2.4.24-vanilla.orig/fs/mbcache.c 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/fs/mbcache.c 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,648 @@ -+/* -+ * linux/fs/mbcache.c -+ * (C) 2001-2002 Andreas Gruenbacher, -+ */ -+ -+/* -+ * Filesystem Meta Information Block Cache (mbcache) -+ * -+ * The mbcache caches blocks of block devices that need to be located -+ * by their device/block number, as well as by other criteria (such -+ * as the block's contents). -+ * -+ * There can only be one cache entry in a cache per device and block number. -+ * Additional indexes need not be unique in this sense. The number of -+ * additional indexes (=other criteria) can be hardwired at compile time -+ * or specified at cache create time. -+ * -+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid' -+ * in the cache. A valid entry is in the main hash tables of the cache, -+ * and may also be in the lru list. An invalid entry is not in any hashes -+ * or lists. -+ * -+ * A valid cache entry is only in the lru list if no handles refer to it. -+ * Invalid cache entries will be freed when the last handle to the cache -+ * entry is released. Entries that cannot be freed immediately are put -+ * back on the lru list. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#ifdef MB_CACHE_DEBUG -+# define mb_debug(f...) do { \ -+ printk(KERN_DEBUG f); \ -+ printk("\n"); \ -+ } while (0) -+#define mb_assert(c) do { if (!(c)) \ -+ printk(KERN_ERR "assertion " #c " failed\n"); \ -+ } while(0) -+#else -+# define mb_debug(f...) do { } while(0) -+# define mb_assert(c) do { } while(0) -+#endif -+#define mb_error(f...) do { \ -+ printk(KERN_ERR f); \ -+ printk("\n"); \ -+ } while(0) -+ -+MODULE_AUTHOR("Andreas Gruenbacher "); -+MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_SYMBOL(mb_cache_create); -+EXPORT_SYMBOL(mb_cache_shrink); -+EXPORT_SYMBOL(mb_cache_destroy); -+EXPORT_SYMBOL(mb_cache_entry_alloc); -+EXPORT_SYMBOL(mb_cache_entry_insert); -+EXPORT_SYMBOL(mb_cache_entry_release); -+EXPORT_SYMBOL(mb_cache_entry_takeout); -+EXPORT_SYMBOL(mb_cache_entry_free); -+EXPORT_SYMBOL(mb_cache_entry_dup); -+EXPORT_SYMBOL(mb_cache_entry_get); -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+EXPORT_SYMBOL(mb_cache_entry_find_first); -+EXPORT_SYMBOL(mb_cache_entry_find_next); -+#endif -+ -+ -+/* -+ * Global data: list of all mbcache's, lru list, and a spinlock for -+ * accessing cache data structures on SMP machines. The lru list is -+ * global across all mbcaches. -+ */ -+ -+static LIST_HEAD(mb_cache_list); -+static LIST_HEAD(mb_cache_lru_list); -+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED; -+ -+static inline int -+mb_cache_indexes(struct mb_cache *cache) -+{ -+#ifdef MB_CACHE_INDEXES_COUNT -+ return MB_CACHE_INDEXES_COUNT; -+#else -+ return cache->c_indexes_count; -+#endif -+} -+ -+/* -+ * What the mbcache registers as to get shrunk dynamically. -+ */ -+ -+static void -+mb_cache_memory_pressure(int priority, unsigned int gfp_mask); -+ -+static struct cache_definition mb_cache_definition = { -+ "mb_cache", -+ mb_cache_memory_pressure -+}; -+ -+ -+static inline int -+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce) -+{ -+ return !list_empty(&ce->e_block_list); -+} -+ -+ -+static inline void -+__mb_cache_entry_unhash(struct mb_cache_entry *ce) -+{ -+ int n; -+ -+ if (__mb_cache_entry_is_hashed(ce)) { -+ list_del_init(&ce->e_block_list); -+ for (n=0; ne_cache); n++) -+ list_del(&ce->e_indexes[n].o_list); -+ } -+} -+ -+ -+static inline void -+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask) -+{ -+ struct mb_cache *cache = ce->e_cache; -+ -+ mb_assert(atomic_read(&ce->e_used) == 0); -+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) { -+ /* free failed -- put back on the lru list -+ for freeing later. */ -+ spin_lock(&mb_cache_spinlock); -+ list_add(&ce->e_lru_list, &mb_cache_lru_list); -+ spin_unlock(&mb_cache_spinlock); -+ } else { -+ kmem_cache_free(cache->c_entry_cache, ce); -+ atomic_dec(&cache->c_entry_count); -+ } -+} -+ -+ -+static inline void -+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce) -+{ -+ if (atomic_dec_and_test(&ce->e_used)) { -+ if (__mb_cache_entry_is_hashed(ce)) -+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list); -+ else { -+ spin_unlock(&mb_cache_spinlock); -+ __mb_cache_entry_forget(ce, GFP_KERNEL); -+ return; -+ } -+ } -+ spin_unlock(&mb_cache_spinlock); -+} -+ -+ -+/* -+ * mb_cache_memory_pressure() memory pressure callback -+ * -+ * This function is called by the kernel memory management when memory -+ * gets low. -+ * -+ * @priority: Amount by which to shrink the cache (0 = highes priority) -+ * @gfp_mask: (ignored) -+ */ -+static void -+mb_cache_memory_pressure(int priority, unsigned int gfp_mask) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ int count = 0; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &mb_cache_list) { -+ struct mb_cache *cache = -+ list_entry(l, struct mb_cache, c_cache_list); -+ mb_debug("cache %s (%d)", cache->c_name, -+ atomic_read(&cache->c_entry_count)); -+ count += atomic_read(&cache->c_entry_count); -+ } -+ mb_debug("trying to free %d of %d entries", -+ count / (priority ? priority : 1), count); -+ if (priority) -+ count /= priority; -+ while (count-- && !list_empty(&mb_cache_lru_list)) { -+ struct mb_cache_entry *ce = -+ list_entry(mb_cache_lru_list.next, -+ struct mb_cache_entry, e_lru_list); -+ list_del(&ce->e_lru_list); -+ __mb_cache_entry_unhash(ce); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ } -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), gfp_mask); -+ } -+} -+ -+ -+/* -+ * mb_cache_create() create a new cache -+ * -+ * All entries in one cache are equal size. Cache entries may be from -+ * multiple devices. If this is the first mbcache created, registers -+ * the cache with kernel memory management. Returns NULL if no more -+ * memory was available. -+ * -+ * @name: name of the cache (informal) -+ * @cache_op: contains the callback called when freeing a cache entry -+ * @entry_size: The size of a cache entry, including -+ * struct mb_cache_entry -+ * @indexes_count: number of additional indexes in the cache. Must equal -+ * MB_CACHE_INDEXES_COUNT if the number of indexes is -+ * hardwired. -+ * @bucket_count: number of hash buckets -+ */ -+struct mb_cache * -+mb_cache_create(const char *name, struct mb_cache_op *cache_op, -+ size_t entry_size, int indexes_count, int bucket_count) -+{ -+ int m=0, n; -+ struct mb_cache *cache = NULL; -+ -+ if(entry_size < sizeof(struct mb_cache_entry) + -+ indexes_count * sizeof(struct mb_cache_entry_index)) -+ return NULL; -+ -+ MOD_INC_USE_COUNT; -+ cache = kmalloc(sizeof(struct mb_cache) + -+ indexes_count * sizeof(struct list_head), GFP_KERNEL); -+ if (!cache) -+ goto fail; -+ cache->c_name = name; -+ cache->c_op.free = NULL; -+ if (cache_op) -+ cache->c_op.free = cache_op->free; -+ atomic_set(&cache->c_entry_count, 0); -+ cache->c_bucket_count = bucket_count; -+#ifdef MB_CACHE_INDEXES_COUNT -+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT); -+#else -+ cache->c_indexes_count = indexes_count; -+#endif -+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head), -+ GFP_KERNEL); -+ if (!cache->c_block_hash) -+ goto fail; -+ for (n=0; nc_block_hash[n]); -+ for (m=0; mc_indexes_hash[m] = kmalloc(bucket_count * -+ sizeof(struct list_head), -+ GFP_KERNEL); -+ if (!cache->c_indexes_hash[m]) -+ goto fail; -+ for (n=0; nc_indexes_hash[m][n]); -+ } -+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0, -+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL); -+ if (!cache->c_entry_cache) -+ goto fail; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_add(&cache->c_cache_list, &mb_cache_list); -+ spin_unlock(&mb_cache_spinlock); -+ return cache; -+ -+fail: -+ if (cache) { -+ while (--m >= 0) -+ kfree(cache->c_indexes_hash[m]); -+ if (cache->c_block_hash) -+ kfree(cache->c_block_hash); -+ kfree(cache); -+ } -+ MOD_DEC_USE_COUNT; -+ return NULL; -+} -+ -+ -+/* -+ * mb_cache_shrink() -+ * -+ * Removes all cache entires of a device from the cache. All cache entries -+ * currently in use cannot be freed, and thus remain in the cache. -+ * -+ * @cache: which cache to shrink -+ * @dev: which device's cache entries to shrink -+ */ -+void -+mb_cache_shrink(struct mb_cache *cache, kdev_t dev) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_lru_list); -+ if (ce->e_dev == dev) { -+ list_del(&ce->e_lru_list); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ __mb_cache_entry_unhash(ce); -+ } -+ } -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), GFP_KERNEL); -+ } -+} -+ -+ -+/* -+ * mb_cache_destroy() -+ * -+ * Shrinks the cache to its minimum possible size (hopefully 0 entries), -+ * and then destroys it. If this was the last mbcache, un-registers the -+ * mbcache from kernel memory management. -+ */ -+void -+mb_cache_destroy(struct mb_cache *cache) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ int n; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_lru_list); -+ if (ce->e_cache == cache) { -+ list_del(&ce->e_lru_list); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ __mb_cache_entry_unhash(ce); -+ } -+ } -+ list_del(&cache->c_cache_list); -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), GFP_KERNEL); -+ } -+ -+ if (atomic_read(&cache->c_entry_count) > 0) { -+ mb_error("cache %s: %d orphaned entries", -+ cache->c_name, -+ atomic_read(&cache->c_entry_count)); -+ } -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) -+ /* We don't have kmem_cache_destroy() in 2.2.x */ -+ kmem_cache_shrink(cache->c_entry_cache); -+#else -+ kmem_cache_destroy(cache->c_entry_cache); -+#endif -+ for (n=0; n < mb_cache_indexes(cache); n++) -+ kfree(cache->c_indexes_hash[n]); -+ kfree(cache->c_block_hash); -+ kfree(cache); -+ -+ MOD_DEC_USE_COUNT; -+} -+ -+ -+/* -+ * mb_cache_entry_alloc() -+ * -+ * Allocates a new cache entry. The new entry will not be valid initially, -+ * and thus cannot be looked up yet. It should be filled with data, and -+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL -+ * if no more memory was available. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_alloc(struct mb_cache *cache) -+{ -+ struct mb_cache_entry *ce; -+ -+ atomic_inc(&cache->c_entry_count); -+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL); -+ if (ce) { -+ INIT_LIST_HEAD(&ce->e_lru_list); -+ INIT_LIST_HEAD(&ce->e_block_list); -+ ce->e_cache = cache; -+ atomic_set(&ce->e_used, 1); -+ } -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_insert() -+ * -+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into -+ * the cache. After this, the cache entry can be looked up, but is not yet -+ * in the lru list as the caller still holds a handle to it. Returns 0 on -+ * success, or -EBUSY if a cache entry for that device + inode exists -+ * already (this may happen after a failed lookup, if another process has -+ * inserted the same cache entry in the meantime). -+ * -+ * @dev: device the cache entry belongs to -+ * @block: block number -+ * @keys: array of additional keys. There must be indexes_count entries -+ * in the array (as specified when creating the cache). -+ */ -+int -+mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev, -+ unsigned long block, unsigned int keys[]) -+{ -+ struct mb_cache *cache = ce->e_cache; -+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count; -+ struct list_head *l; -+ int error = -EBUSY, n; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &cache->c_block_hash[bucket]) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_block_list); -+ if (ce->e_dev == dev && ce->e_block == block) -+ goto out; -+ } -+ __mb_cache_entry_unhash(ce); -+ ce->e_dev = dev; -+ ce->e_block = block; -+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]); -+ for (n=0; ne_indexes[n].o_key = keys[n]; -+ bucket = keys[n] % cache->c_bucket_count; -+ list_add(&ce->e_indexes[n].o_list, -+ &cache->c_indexes_hash[n][bucket]); -+ } -+out: -+ spin_unlock(&mb_cache_spinlock); -+ return error; -+} -+ -+ -+/* -+ * mb_cache_entry_release() -+ * -+ * Release a handle to a cache entry. When the last handle to a cache entry -+ * is released it is either freed (if it is invalid) or otherwise inserted -+ * in to the lru list. -+ */ -+void -+mb_cache_entry_release(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ __mb_cache_entry_release_unlock(ce); -+} -+ -+ -+/* -+ * mb_cache_entry_takeout() -+ * -+ * Take a cache entry out of the cache, making it invalid. The entry can later -+ * be re-inserted using mb_cache_entry_insert(), or released using -+ * mb_cache_entry_release(). -+ */ -+void -+mb_cache_entry_takeout(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ mb_assert(list_empty(&ce->e_lru_list)); -+ __mb_cache_entry_unhash(ce); -+ spin_unlock(&mb_cache_spinlock); -+} -+ -+ -+/* -+ * mb_cache_entry_free() -+ * -+ * This is equivalent to the sequence mb_cache_entry_takeout() -- -+ * mb_cache_entry_release(). -+ */ -+void -+mb_cache_entry_free(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ mb_assert(list_empty(&ce->e_lru_list)); -+ __mb_cache_entry_unhash(ce); -+ __mb_cache_entry_release_unlock(ce); -+} -+ -+ -+/* -+ * mb_cache_entry_dup() -+ * -+ * Duplicate a handle to a cache entry (does not duplicate the cache entry -+ * itself). After the call, both the old and the new handle must be released. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_dup(struct mb_cache_entry *ce) -+{ -+ atomic_inc(&ce->e_used); -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_get() -+ * -+ * Get a cache entry by device / block number. (There can only be one entry -+ * in the cache per device and block.) Returns NULL if no such cache entry -+ * exists. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block) -+{ -+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &cache->c_block_hash[bucket]) { -+ ce = list_entry(l, struct mb_cache_entry, e_block_list); -+ if (ce->e_dev == dev && ce->e_block == block) { -+ if (!list_empty(&ce->e_lru_list)) -+ list_del_init(&ce->e_lru_list); -+ atomic_inc(&ce->e_used); -+ goto cleanup; -+ } -+ } -+ ce = NULL; -+ -+cleanup: -+ spin_unlock(&mb_cache_spinlock); -+ return ce; -+} -+ -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+ -+static struct mb_cache_entry * -+__mb_cache_entry_find(struct list_head *l, struct list_head *head, -+ int index, kdev_t dev, unsigned int key) -+{ -+ while (l != head) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, -+ e_indexes[index].o_list); -+ if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) { -+ if (!list_empty(&ce->e_lru_list)) -+ list_del_init(&ce->e_lru_list); -+ atomic_inc(&ce->e_used); -+ return ce; -+ } -+ l = l->next; -+ } -+ return NULL; -+} -+ -+ -+/* -+ * mb_cache_entry_find_first() -+ * -+ * Find the first cache entry on a given device with a certain key in -+ * an additional index. Additonal matches can be found with -+ * mb_cache_entry_find_next(). Returns NULL if no match was found. -+ * -+ * @cache: the cache to search -+ * @index: the number of the additonal index to search (0<=indexc_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ mb_assert(index < mb_cache_indexes(cache)); -+ spin_lock(&mb_cache_spinlock); -+ l = cache->c_indexes_hash[index][bucket].next; -+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket], -+ index, dev, key); -+ spin_unlock(&mb_cache_spinlock); -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_find_next() -+ * -+ * Find the next cache entry on a given device with a certain key in an -+ * additional index. Returns NULL if no match could be found. The previous -+ * entry is atomatically released, so that mb_cache_entry_find_next() can -+ * be called like this: -+ * -+ * entry = mb_cache_entry_find_first(); -+ * while (entry) { -+ * ... -+ * entry = mb_cache_entry_find_next(entry, ...); -+ * } -+ * -+ * @prev: The previous match -+ * @index: the number of the additonal index to search (0<=indexe_cache; -+ unsigned int bucket = key % cache->c_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ mb_assert(index < mb_cache_indexes(cache)); -+ spin_lock(&mb_cache_spinlock); -+ l = prev->e_indexes[index].o_list.next; -+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket], -+ index, dev, key); -+ __mb_cache_entry_release_unlock(prev); -+ return ce; -+} -+ -+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */ -+ -+static int __init init_mbcache(void) -+{ -+ register_cache(&mb_cache_definition); -+ return 0; -+} -+ -+static void __exit exit_mbcache(void) -+{ -+ unregister_cache(&mb_cache_definition); -+} -+ -+module_init(init_mbcache) -+module_exit(exit_mbcache) -+ -Index: linux-2.4.24-vanilla/include/asm-arm/unistd.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/asm-arm/unistd.h 2004-01-10 17:05:06.000000000 +0300 -+++ linux-2.4.24-vanilla/include/asm-arm/unistd.h 2004-01-10 17:20:28.000000000 +0300 -@@ -250,7 +250,6 @@ - #define __NR_security (__NR_SYSCALL_BASE+223) - #define __NR_gettid (__NR_SYSCALL_BASE+224) - #define __NR_readahead (__NR_SYSCALL_BASE+225) --#if 0 /* allocated in 2.5 */ - #define __NR_setxattr (__NR_SYSCALL_BASE+226) - #define __NR_lsetxattr (__NR_SYSCALL_BASE+227) - #define __NR_fsetxattr (__NR_SYSCALL_BASE+228) -@@ -263,7 +262,6 @@ - #define __NR_removexattr (__NR_SYSCALL_BASE+235) - #define __NR_lremovexattr (__NR_SYSCALL_BASE+236) - #define __NR_fremovexattr (__NR_SYSCALL_BASE+237) --#endif - #define __NR_tkill (__NR_SYSCALL_BASE+238) - #if 0 /* allocated in 2.5 */ - #define __NR_sendfile64 (__NR_SYSCALL_BASE+239) -Index: linux-2.4.24-vanilla/include/asm-ppc64/unistd.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/asm-ppc64/unistd.h 2004-01-10 17:05:59.000000000 +0300 -+++ linux-2.4.24-vanilla/include/asm-ppc64/unistd.h 2004-01-10 17:20:28.000000000 +0300 -@@ -218,6 +218,7 @@ - #define __NR_mincore 206 - #define __NR_gettid 207 - #define __NR_tkill 208 -+#endif - #define __NR_setxattr 209 - #define __NR_lsetxattr 210 - #define __NR_fsetxattr 211 -@@ -230,6 +231,7 @@ - #define __NR_removexattr 218 - #define __NR_lremovexattr 219 - #define __NR_fremovexattr 220 -+#if 0 /* Reserved syscalls */ - #define __NR_futex 221 - #define __NR_sched_setaffinity 222 - #define __NR_sched_getaffinity 223 -Index: linux-2.4.24-vanilla/include/asm-s390/unistd.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/asm-s390/unistd.h 2004-01-10 17:04:42.000000000 +0300 -+++ linux-2.4.24-vanilla/include/asm-s390/unistd.h 2004-01-10 17:20:28.000000000 +0300 -@@ -213,9 +213,18 @@ - #define __NR_getdents64 220 - #define __NR_fcntl64 221 - #define __NR_readahead 222 --/* -- * Numbers 224-235 are reserved for posix acl -- */ -+#define __NR_setxattr 224 -+#define __NR_lsetxattr 225 -+#define __NR_fsetxattr 226 -+#define __NR_getxattr 227 -+#define __NR_lgetxattr 228 -+#define __NR_fgetxattr 229 -+#define __NR_listxattr 230 -+#define __NR_llistxattr 231 -+#define __NR_flistxattr 232 -+#define __NR_removexattr 233 -+#define __NR_lremovexattr 234 -+#define __NR_fremovexattr 235 - #define __NR_gettid 236 - #define __NR_tkill 237 - -Index: linux-2.4.24-vanilla/include/asm-s390x/unistd.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/asm-s390x/unistd.h 2004-01-10 17:04:42.000000000 +0300 -+++ linux-2.4.24-vanilla/include/asm-s390x/unistd.h 2004-01-10 17:20:28.000000000 +0300 -@@ -181,9 +181,18 @@ - #define __NR_mincore 218 - #define __NR_madvise 219 - #define __NR_readahead 222 --/* -- * Numbers 224-235 are reserved for posix acl -- */ -+#define __NR_setxattr 224 -+#define __NR_lsetxattr 225 -+#define __NR_fsetxattr 226 -+#define __NR_getxattr 227 -+#define __NR_lgetxattr 228 -+#define __NR_fgetxattr 229 -+#define __NR_listxattr 230 -+#define __NR_llistxattr 231 -+#define __NR_flistxattr 232 -+#define __NR_removexattr 233 -+#define __NR_lremovexattr 234 -+#define __NR_fremovexattr 235 - #define __NR_gettid 236 - #define __NR_tkill 237 - -Index: linux-2.4.24-vanilla/include/linux/cache_def.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/cache_def.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/cache_def.h 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,15 @@ -+/* -+ * linux/cache_def.h -+ * Handling of caches defined in drivers, filesystems, ... -+ * -+ * Copyright (C) 2002 by Andreas Gruenbacher, -+ */ -+ -+struct cache_definition { -+ const char *name; -+ void (*shrink)(int, unsigned int); -+ struct list_head link; -+}; -+ -+extern void register_cache(struct cache_definition *); -+extern void unregister_cache(struct cache_definition *); -Index: linux-2.4.24-vanilla/include/linux/errno.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/errno.h 2001-02-10 01:46:13.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/errno.h 2004-01-10 17:20:28.000000000 +0300 -@@ -23,4 +23,8 @@ - - #endif - -+/* Defined for extended attributes */ -+#define ENOATTR ENODATA /* No such attribute */ -+#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -+ - #endif -Index: linux-2.4.24-vanilla/include/linux/ext2_fs.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/ext2_fs.h 2004-01-10 17:04:42.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/ext2_fs.h 2004-01-10 17:20:28.000000000 +0300 -@@ -57,8 +57,6 @@ - */ - #define EXT2_BAD_INO 1 /* Bad blocks inode */ - #define EXT2_ROOT_INO 2 /* Root inode */ --#define EXT2_ACL_IDX_INO 3 /* ACL inode */ --#define EXT2_ACL_DATA_INO 4 /* ACL inode */ - #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ - -@@ -86,7 +84,6 @@ - #else - # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry)) - #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -121,28 +118,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext2_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext2_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext2_group_desc -@@ -314,6 +289,7 @@ - #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ - #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ - #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ -+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt - #define set_opt(o, opt) o |= EXT2_MOUNT_##opt -@@ -397,6 +373,7 @@ - - #ifdef __KERNEL__ - #define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -+#define EXT2_I(inode) (&((inode)->u.ext2_i)) - #else - /* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test -@@ -466,7 +443,7 @@ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 - #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - --#define EXT2_FEATURE_COMPAT_SUPP 0 -+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE - #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ -@@ -624,8 +601,10 @@ - - /* namei.c */ - extern struct inode_operations ext2_dir_inode_operations; -+extern struct inode_operations ext2_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext2_symlink_inode_operations; - extern struct inode_operations ext2_fast_symlink_inode_operations; - - #endif /* __KERNEL__ */ -Index: linux-2.4.24-vanilla/include/linux/ext2_xattr.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/ext2_xattr.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/ext2_xattr.h 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext2_xattr.h -+ -+ On-disk format of extended attributes for the ext2 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT2_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT2_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT2_XATTR_INDEX_MAX 10 -+#define EXT2_XATTR_INDEX_USER 1 -+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext2_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext2_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT2_XATTR_PAD_BITS 2 -+#define EXT2_XATTR_PAD (1<e_name_len)) ) -+#define EXT2_XATTR_SIZE(size) \ -+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT2_FS_XATTR -+ -+struct ext2_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext2_xattr_register(int, struct ext2_xattr_handler *); -+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *); -+ -+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); -+extern int ext2_removexattr(struct dentry *, const char *); -+ -+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext2_xattr_list(struct inode *, char *, size_t); -+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext2_xattr_delete_inode(struct inode *); -+extern void ext2_xattr_put_super(struct super_block *); -+ -+extern int init_ext2_xattr(void) __init; -+extern void exit_ext2_xattr(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR */ -+# define ext2_setxattr NULL -+# define ext2_getxattr NULL -+# define ext2_listxattr NULL -+# define ext2_removexattr NULL -+ -+static inline int -+ext2_xattr_get(struct inode *inode, int name_index, -+ const char *name, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+} -+ -+static inline void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR */ -+ -+# ifdef CONFIG_EXT2_FS_XATTR_USER -+ -+extern int init_ext2_xattr_user(void) __init; -+extern void exit_ext2_xattr_user(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+static inline int -+init_ext2_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr_user(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ -Index: linux-2.4.24-vanilla/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/ext3_fs.h 2004-01-10 17:11:50.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/ext3_fs.h 2004-01-10 17:20:28.000000000 +0300 -@@ -63,8 +63,6 @@ - */ - #define EXT3_BAD_INO 1 /* Bad blocks inode */ - #define EXT3_ROOT_INO 2 /* Root inode */ --#define EXT3_ACL_IDX_INO 3 /* ACL inode */ --#define EXT3_ACL_DATA_INO 4 /* ACL inode */ - #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */ - #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */ -@@ -94,7 +92,6 @@ - #else - # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry)) - #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -129,28 +126,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext3_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext3_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext3_group_desc -@@ -344,6 +319,7 @@ - #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */ - #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ -+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -521,7 +497,7 @@ - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ - --#define EXT3_FEATURE_COMPAT_SUPP 0 -+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ - EXT3_FEATURE_INCOMPAT_RECOVER) - #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ -@@ -704,6 +680,7 @@ - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); - -@@ -773,8 +750,10 @@ - - /* namei.c */ - extern struct inode_operations ext3_dir_inode_operations; -+extern struct inode_operations ext3_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - - -Index: linux-2.4.24-vanilla/include/linux/ext3_jbd.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/ext3_jbd.h 2004-01-10 17:11:50.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/ext3_jbd.h 2004-01-10 17:20:28.000000000 +0300 -@@ -30,13 +30,19 @@ - - #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U - -+/* Extended attributes may touch two data buffers, two bitmap buffers, -+ * and two group and summaries. */ -+ -+#define EXT3_XATTR_TRANS_BLOCKS 8 -+ - /* Define the minimum size for a transaction which modifies data. This - * needs to take into account the fact that we may end up modifying two - * quota files too (one for the group, one for the user quota). The - * superblock only gets updated once, of course, so don't bother - * counting that again for the quota updates. */ - --#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2) -+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \ -+ EXT3_XATTR_TRANS_BLOCKS - 2) - - extern int ext3_writepage_trans_blocks(struct inode *inode); - -Index: linux-2.4.24-vanilla/include/linux/ext3_xattr.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/ext3_xattr.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/ext3_xattr.h 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext3_xattr.h -+ -+ On-disk format of extended attributes for the ext3 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT3_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT3_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT3_XATTR_INDEX_MAX 10 -+#define EXT3_XATTR_INDEX_USER 1 -+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext3_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext3_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT3_XATTR_PAD_BITS 2 -+#define EXT3_XATTR_PAD (1<e_name_len)) ) -+#define EXT3_XATTR_SIZE(size) \ -+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT3_FS_XATTR -+ -+struct ext3_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext3_xattr_register(int, struct ext3_xattr_handler *); -+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *); -+ -+extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); -+extern int ext3_removexattr(struct dentry *, const char *); -+ -+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext3_xattr_list(struct inode *, char *, size_t); -+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext3_xattr_delete_inode(handle_t *, struct inode *); -+extern void ext3_xattr_put_super(struct super_block *); -+ -+extern int init_ext3_xattr(void) __init; -+extern void exit_ext3_xattr(void); -+ -+# else /* CONFIG_EXT3_FS_XATTR */ -+# define ext3_setxattr NULL -+# define ext3_getxattr NULL -+# define ext3_listxattr NULL -+# define ext3_removexattr NULL -+ -+static inline int -+ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext3_xattr_list(struct inode *inode, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) -+{ -+} -+ -+static inline void -+ext3_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext3_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext3_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT3_FS_XATTR */ -+ -+# ifdef CONFIG_EXT3_FS_XATTR_USER -+ -+extern int init_ext3_xattr_user(void) __init; -+extern void exit_ext3_xattr_user(void); -+ -+# else /* CONFIG_EXT3_FS_XATTR_USER */ -+ -+static inline int -+init_ext3_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext3_xattr_user(void) -+{ -+} -+ -+#endif /* CONFIG_EXT3_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ -Index: linux-2.4.24-vanilla/include/linux/fs.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/fs.h 2004-01-10 17:11:45.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/fs.h 2004-01-10 17:20:28.000000000 +0300 -@@ -913,7 +913,7 @@ - int (*setattr) (struct dentry *, struct iattr *); - int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); -- int (*setxattr) (struct dentry *, const char *, void *, size_t, int); -+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); - ssize_t (*listxattr) (struct dentry *, char *, size_t); - int (*removexattr) (struct dentry *, const char *); -Index: linux-2.4.24-vanilla/include/linux/mbcache.h -=================================================================== ---- linux-2.4.24-vanilla.orig/include/linux/mbcache.h 2003-01-30 13:24:37.000000000 +0300 -+++ linux-2.4.24-vanilla/include/linux/mbcache.h 2004-01-10 17:20:28.000000000 +0300 -@@ -0,0 +1,69 @@ -+/* -+ File: linux/mbcache.h -+ -+ (C) 2001 by Andreas Gruenbacher, -+*/ -+ -+/* Hardwire the number of additional indexes */ -+#define MB_CACHE_INDEXES_COUNT 1 -+ -+struct mb_cache_entry; -+ -+struct mb_cache_op { -+ int (*free)(struct mb_cache_entry *, int); -+}; -+ -+struct mb_cache { -+ struct list_head c_cache_list; -+ const char *c_name; -+ struct mb_cache_op c_op; -+ atomic_t c_entry_count; -+ int c_bucket_count; -+#ifndef MB_CACHE_INDEXES_COUNT -+ int c_indexes_count; -+#endif -+ kmem_cache_t *c_entry_cache; -+ struct list_head *c_block_hash; -+ struct list_head *c_indexes_hash[0]; -+}; -+ -+struct mb_cache_entry_index { -+ struct list_head o_list; -+ unsigned int o_key; -+}; -+ -+struct mb_cache_entry { -+ struct list_head e_lru_list; -+ struct mb_cache *e_cache; -+ atomic_t e_used; -+ kdev_t e_dev; -+ unsigned long e_block; -+ struct list_head e_block_list; -+ struct mb_cache_entry_index e_indexes[0]; -+}; -+ -+/* Functions on caches */ -+ -+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t, -+ int, int); -+void mb_cache_shrink(struct mb_cache *, kdev_t); -+void mb_cache_destroy(struct mb_cache *); -+ -+/* Functions on cache entries */ -+ -+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *); -+int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long, -+ unsigned int[]); -+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]); -+void mb_cache_entry_release(struct mb_cache_entry *); -+void mb_cache_entry_takeout(struct mb_cache_entry *); -+void mb_cache_entry_free(struct mb_cache_entry *); -+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *); -+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t, -+ unsigned long); -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int, -+ kdev_t, unsigned int); -+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int, -+ kdev_t, unsigned int); -+#endif -Index: linux-2.4.24-vanilla/kernel/ksyms.c -=================================================================== ---- linux-2.4.24-vanilla.orig/kernel/ksyms.c 2004-01-10 17:11:43.000000000 +0300 -+++ linux-2.4.24-vanilla/kernel/ksyms.c 2004-01-10 17:20:28.000000000 +0300 -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -92,6 +93,7 @@ - EXPORT_SYMBOL(exit_files); - EXPORT_SYMBOL(exit_fs); - EXPORT_SYMBOL(exit_sighand); -+EXPORT_SYMBOL(copy_fs_struct); - - /* internal kernel memory management */ - EXPORT_SYMBOL(_alloc_pages); -@@ -109,6 +111,8 @@ - EXPORT_SYMBOL(kmem_cache_alloc); - EXPORT_SYMBOL(kmem_cache_free); - EXPORT_SYMBOL(kmem_cache_size); -+EXPORT_SYMBOL(register_cache); -+EXPORT_SYMBOL(unregister_cache); - EXPORT_SYMBOL(kmalloc); - EXPORT_SYMBOL(kfree); - EXPORT_SYMBOL(vfree); -Index: linux-2.4.24-vanilla/mm/vmscan.c -=================================================================== ---- linux-2.4.24-vanilla.orig/mm/vmscan.c 2004-01-10 17:06:00.000000000 +0300 -+++ linux-2.4.24-vanilla/mm/vmscan.c 2004-01-10 17:21:00.000000000 +0300 -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -34,6 +35,39 @@ - */ - int vm_passes = 60; - -+static DECLARE_MUTEX(other_caches_sem); -+static LIST_HEAD(cache_definitions); -+ -+void register_cache(struct cache_definition *cache) -+{ -+ down(&other_caches_sem); -+ list_add(&cache->link, &cache_definitions); -+ up(&other_caches_sem); -+} -+ -+void unregister_cache(struct cache_definition *cache) -+{ -+ down(&other_caches_sem); -+ list_del(&cache->link); -+ up(&other_caches_sem); -+} -+ -+static void shrink_other_caches(unsigned int priority, int gfp_mask) -+{ -+ struct list_head *p; -+ -+ if (down_trylock(&other_caches_sem)) -+ return; -+ -+ list_for_each_prev(p, &cache_definitions) { -+ struct cache_definition *cache = -+ list_entry(p, struct cache_definition, link); -+ -+ cache->shrink(priority, gfp_mask); -+ } -+ up(&other_caches_sem); -+} -+ - /* - * "vm_cache_scan_ratio" is how much of the inactive LRU queue we will scan - * in one go. A value of 6 for vm_cache_scan_ratio implies that we'll -@@ -523,6 +557,7 @@ - #ifdef CONFIG_QUOTA - shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask); - #endif -+ shrink_other_caches(vm_vfs_scan_ratio, gfp_mask); - - if (!*failed_swapout) - *failed_swapout = !swap_out(classzone); -@@ -645,6 +680,7 @@ - #ifdef CONFIG_QUOTA - shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask); - #endif -+ shrink_other_caches(vm_vfs_scan_ratio, gfp_mask); - if (!failed_swapout) - failed_swapout = !swap_out(classzone); - } while (--tries); diff --git a/lustre/kernel_patches/patches/linux-2.4.29-xattr-0.8.54.patch b/lustre/kernel_patches/patches/linux-2.4.29-xattr-0.8.54.patch deleted file mode 100644 index 8225ea3..0000000 --- a/lustre/kernel_patches/patches/linux-2.4.29-xattr-0.8.54.patch +++ /dev/null @@ -1,5362 +0,0 @@ -Index: linux-2.4.29/Documentation/Configure.help -=================================================================== ---- linux-2.4.29.orig/Documentation/Configure.help 2005-04-07 18:55:00.000000000 +0300 -+++ linux-2.4.29/Documentation/Configure.help 2005-05-03 17:59:40.363127040 +0300 -@@ -16679,6 +16679,39 @@ - be compiled as a module, and so this could be dangerous. Most - everyone wants to say Y here. - -+Ext2 extended attributes -+CONFIG_EXT2_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext2 extended attribute block sharing -+CONFIG_EXT2_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext2 extended user attributes -+CONFIG_EXT2_FS_XATTR_USER -+ This option enables extended user attributes on ext2. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext2 trusted extended attributes -+CONFIG_EXT2_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext2 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Ext3 journalling file system support (EXPERIMENTAL) - CONFIG_EXT3_FS - This is the journalling version of the Second extended file system -@@ -16711,6 +16744,39 @@ - of your root partition (the one containing the directory /) cannot - be compiled as a module, and so this may be dangerous. - -+Ext3 extended attributes -+CONFIG_EXT3_FS_XATTR -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ for details). -+ -+ If unsure, say N. -+ -+Ext3 extended attribute block sharing -+CONFIG_EXT3_FS_XATTR_SHARING -+ This options enables code for sharing identical extended attribute -+ blocks among multiple inodes. -+ -+ Usually, say Y. -+ -+Ext3 extended user attributes -+CONFIG_EXT3_FS_XATTR_USER -+ This option enables extended user attributes on ext3. Processes can -+ associate extended user attributes with inodes to store additional -+ information such as the character encoding of files, etc. (see the -+ attr(5) manual page, or visit for details). -+ -+ If unsure, say N. -+ -+Ext3 trusted extended attributes -+CONFIG_EXT3_FS_XATTR_TRUSTED -+ This option enables extended attributes on ext3 that are accessible -+ (and visible) only to users capable of CAP_SYS_ADMIN. Usually this -+ is only the super user. Trusted extended attributes are meant for -+ implementing system/security services. -+ -+ If unsure, say N. -+ - Journal Block Device support (JBD for ext3) (EXPERIMENTAL) - CONFIG_JBD - This is a generic journalling layer for block devices. It is -Index: linux-2.4.29/arch/alpha/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/alpha/defconfig 2005-04-07 18:53:42.000000000 +0300 -+++ linux-2.4.29/arch/alpha/defconfig 2005-05-03 17:59:40.365126736 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_ALPHA=y - # CONFIG_UID16 is not set - # CONFIG_RWSEM_GENERIC_SPINLOCK is not set -Index: linux-2.4.29/arch/alpha/kernel/entry.S -=================================================================== ---- linux-2.4.29.orig/arch/alpha/kernel/entry.S 2005-04-07 18:52:17.000000000 +0300 -+++ linux-2.4.29/arch/alpha/kernel/entry.S 2005-05-03 17:59:40.367126432 +0300 -@@ -1154,6 +1154,18 @@ - .quad sys_readahead - .quad sys_ni_syscall /* 380, sys_security */ - .quad sys_tkill -+ .quad sys_setxattr -+ .quad sys_lsetxattr -+ .quad sys_fsetxattr -+ .quad sys_getxattr /* 385 */ -+ .quad sys_lgetxattr -+ .quad sys_fgetxattr -+ .quad sys_listxattr -+ .quad sys_llistxattr -+ .quad sys_flistxattr /* 390 */ -+ .quad sys_removexattr -+ .quad sys_lremovexattr -+ .quad sys_fremovexattr - - /* Remember to update everything, kids. */ - .ifne (. - sys_call_table) - (NR_SYSCALLS * 8) -Index: linux-2.4.29/arch/arm/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/arm/defconfig 2005-04-07 18:53:03.000000000 +0300 -+++ linux-2.4.29/arch/arm/defconfig 2005-05-03 17:59:40.369126128 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_ARM=y - # CONFIG_EISA is not set - # CONFIG_SBUS is not set -Index: linux-2.4.29/arch/arm/kernel/calls.S -=================================================================== ---- linux-2.4.29.orig/arch/arm/kernel/calls.S 2005-04-07 18:55:23.000000000 +0300 -+++ linux-2.4.29/arch/arm/kernel/calls.S 2005-05-03 17:59:40.371125824 +0300 -@@ -240,18 +240,18 @@ - .long SYMBOL_NAME(sys_ni_syscall) /* Security */ - .long SYMBOL_NAME(sys_gettid) - /* 225 */ .long SYMBOL_NAME(sys_readahead) -- .long SYMBOL_NAME(sys_ni_syscall) /* setxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* lsetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* fsetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* getxattr */ --/* 230 */ .long SYMBOL_NAME(sys_ni_syscall) /* lgetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* fgetxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* listxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* llistxattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* flistxattr */ --/* 235 */ .long SYMBOL_NAME(sys_ni_syscall) /* removexattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* lremovexattr */ -- .long SYMBOL_NAME(sys_ni_syscall) /* fremovexattr */ -+ .long SYMBOL_NAME(sys_setxattr) -+ .long SYMBOL_NAME(sys_lsetxattr) -+ .long SYMBOL_NAME(sys_fsetxattr) -+ .long SYMBOL_NAME(sys_getxattr) -+/* 230 */ .long SYMBOL_NAME(sys_lgetxattr) -+ .long SYMBOL_NAME(sys_fgetxattr) -+ .long SYMBOL_NAME(sys_listxattr) -+ .long SYMBOL_NAME(sys_llistxattr) -+ .long SYMBOL_NAME(sys_flistxattr) -+/* 235 */ .long SYMBOL_NAME(sys_removexattr) -+ .long SYMBOL_NAME(sys_lremovexattr) -+ .long SYMBOL_NAME(sys_fremovexattr) - .long SYMBOL_NAME(sys_tkill) - .long SYMBOL_NAME(sys_ni_syscall) /* sendfile64 */ - /* 240 */ .long SYMBOL_NAME(sys_ni_syscall) /* futex */ -Index: linux-2.4.29/arch/i386/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/i386/defconfig 2005-04-07 18:52:37.000000000 +0300 -+++ linux-2.4.29/arch/i386/defconfig 2005-05-03 17:59:40.372125672 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_X86=y - # CONFIG_SBUS is not set - CONFIG_UID16=y -Index: linux-2.4.29/arch/ia64/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/ia64/defconfig 2005-04-07 18:52:32.000000000 +0300 -+++ linux-2.4.29/arch/ia64/defconfig 2005-05-03 17:59:40.374125368 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - - # - # Code maturity level options -Index: linux-2.4.29/arch/m68k/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/m68k/defconfig 2005-04-07 18:52:26.000000000 +0300 -+++ linux-2.4.29/arch/m68k/defconfig 2005-05-03 17:59:40.375125216 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_UID16=y - - # -Index: linux-2.4.29/arch/mips/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/mips/defconfig 2005-04-07 18:52:42.000000000 +0300 -+++ linux-2.4.29/arch/mips/defconfig 2005-05-03 17:59:40.376125064 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_MIPS=y - CONFIG_MIPS32=y - # CONFIG_MIPS64 is not set -Index: linux-2.4.29/arch/mips64/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/mips64/defconfig 2005-04-07 18:52:47.000000000 +0300 -+++ linux-2.4.29/arch/mips64/defconfig 2005-05-03 17:59:40.378124760 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - CONFIG_MIPS=y - # CONFIG_MIPS32 is not set - CONFIG_MIPS64=y -Index: linux-2.4.29/arch/s390/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/s390/defconfig 2005-04-07 18:54:49.000000000 +0300 -+++ linux-2.4.29/arch/s390/defconfig 2005-05-03 17:59:40.379124608 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - # CONFIG_ISA is not set - # CONFIG_EISA is not set - # CONFIG_MCA is not set -Index: linux-2.4.29/arch/s390/kernel/entry.S -=================================================================== ---- linux-2.4.29.orig/arch/s390/kernel/entry.S 2005-04-07 18:52:47.000000000 +0300 -+++ linux-2.4.29/arch/s390/kernel/entry.S 2005-05-03 17:59:40.381124304 +0300 -@@ -558,18 +558,18 @@ - .long sys_fcntl64 - .long sys_readahead - .long sys_ni_syscall -- .long sys_ni_syscall /* 224 - reserved for setxattr */ -- .long sys_ni_syscall /* 225 - reserved for lsetxattr */ -- .long sys_ni_syscall /* 226 - reserved for fsetxattr */ -- .long sys_ni_syscall /* 227 - reserved for getxattr */ -- .long sys_ni_syscall /* 228 - reserved for lgetxattr */ -- .long sys_ni_syscall /* 229 - reserved for fgetxattr */ -- .long sys_ni_syscall /* 230 - reserved for listxattr */ -- .long sys_ni_syscall /* 231 - reserved for llistxattr */ -- .long sys_ni_syscall /* 232 - reserved for flistxattr */ -- .long sys_ni_syscall /* 233 - reserved for removexattr */ -- .long sys_ni_syscall /* 234 - reserved for lremovexattr */ -- .long sys_ni_syscall /* 235 - reserved for fremovexattr */ -+ .long sys_setxattr -+ .long sys_lsetxattr /* 225 */ -+ .long sys_fsetxattr -+ .long sys_getxattr -+ .long sys_lgetxattr -+ .long sys_fgetxattr -+ .long sys_listxattr /* 230 */ -+ .long sys_llistxattr -+ .long sys_flistxattr -+ .long sys_removexattr -+ .long sys_lremovexattr -+ .long sys_fremovexattr /* 235 */ - .long sys_gettid - .long sys_tkill - .rept 255-237 -Index: linux-2.4.29/arch/s390x/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/s390x/defconfig 2005-04-07 18:52:17.000000000 +0300 -+++ linux-2.4.29/arch/s390x/defconfig 2005-05-03 17:59:40.382124152 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - # CONFIG_ISA is not set - # CONFIG_EISA is not set - # CONFIG_MCA is not set -Index: linux-2.4.29/arch/s390x/kernel/entry.S -=================================================================== ---- linux-2.4.29.orig/arch/s390x/kernel/entry.S 2005-04-07 18:52:58.000000000 +0300 -+++ linux-2.4.29/arch/s390x/kernel/entry.S 2005-05-03 17:59:40.384123848 +0300 -@@ -591,18 +591,18 @@ - .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper) - .long SYSCALL(sys_readahead,sys32_readahead) - .long SYSCALL(sys_ni_syscall,sys_ni_syscall) -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 224 - reserved for setxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 225 - reserved for lsetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 226 - reserved for fsetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 227 - reserved for getxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 228 - reserved for lgetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 229 - reserved for fgetxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 230 - reserved for listxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 231 - reserved for llistxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 232 - reserved for flistxattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 233 - reserved for removexattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 234 - reserved for lremovexattr */ -- .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 235 - reserved for fremovexattr */ -+ .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper) -+ .long SYSCALL(sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */ -+ .long SYSCALL(sys_fsetxattr,sys32_fsetxattr_wrapper) -+ .long SYSCALL(sys_getxattr,sys32_getxattr_wrapper) -+ .long SYSCALL(sys_lgetxattr,sys32_lgetxattr_wrapper) -+ .long SYSCALL(sys_fgetxattr,sys32_fgetxattr_wrapper) -+ .long SYSCALL(sys_listxattr,sys32_listxattr_wrapper) /* 230 */ -+ .long SYSCALL(sys_llistxattr,sys32_llistxattr_wrapper) -+ .long SYSCALL(sys_flistxattr,sys32_flistxattr_wrapper) -+ .long SYSCALL(sys_removexattr,sys32_removexattr_wrapper) -+ .long SYSCALL(sys_lremovexattr,sys32_lremovexattr_wrapper) -+ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper)/* 235 */ - .long SYSCALL(sys_gettid,sys_gettid) - .long SYSCALL(sys_tkill,sys_tkill) - .rept 255-237 -Index: linux-2.4.29/arch/s390x/kernel/wrapper32.S -=================================================================== ---- linux-2.4.29.orig/arch/s390x/kernel/wrapper32.S 2005-04-07 18:55:12.000000000 +0300 -+++ linux-2.4.29/arch/s390x/kernel/wrapper32.S 2005-05-03 17:59:40.386123544 +0300 -@@ -1098,6 +1098,98 @@ - llgfr %r4,%r4 # long - jg sys32_fstat64 # branch to system call - -+ .globl sys32_setxattr_wrapper -+sys32_setxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ lgfr %r6,%r6 # int -+ jg sys_setxattr -+ -+ .globl sys32_lsetxattr_wrapper -+sys32_lsetxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ lgfr %r6,%r6 # int -+ jg sys_lsetxattr -+ -+ .globl sys32_fsetxattr_wrapper -+sys32_fsetxattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ lgfr %r6,%r6 # int -+ jg sys_fsetxattr -+ -+ .globl sys32_getxattr_wrapper -+sys32_getxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ jg sys_getxattr -+ -+ .globl sys32_lgetxattr_wrapper -+sys32_lgetxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ jg sys_lgetxattr -+ -+ .globl sys32_fgetxattr_wrapper -+sys32_fgetxattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ llgtr %r4,%r4 # void * -+ llgfr %r5,%r5 # size_t -+ jg sys_fgetxattr -+ -+ .globl sys32_listxattr_wrapper -+sys32_listxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgfr %r4,%r4 # size_t -+ jg sys_listxattr -+ -+ .globl sys32_llistxattr_wrapper -+sys32_llistxattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ llgfr %r4,%r4 # size_t -+ jg sys_llistxattr -+ -+ .globl sys32_flistxattr_wrapper -+sys32_flistxattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ llgfr %r4,%r4 # size_t -+ jg sys_flistxattr -+ -+ .globl sys32_removexattr_wrapper -+sys32_removexattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ jg sys_removexattr -+ -+ .globl sys32_lremovexattr_wrapper -+sys32_lremovexattr_wrapper: -+ llgtr %r2,%r2 # char * -+ llgtr %r3,%r3 # char * -+ jg sys_lremovexattr -+ -+ .globl sys32_fremovexattr_wrapper -+sys32_fremovexattr_wrapper: -+ lgfr %r2,%r2 # int -+ llgtr %r3,%r3 # char * -+ jg sys_fremovexattr -+ -+ -+ - .globl sys32_stime_wrapper - sys32_stime_wrapper: - llgtr %r2,%r2 # int * -Index: linux-2.4.29/arch/sparc64/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/sparc64/defconfig 2005-04-07 18:53:09.000000000 +0300 -+++ linux-2.4.29/arch/sparc64/defconfig 2005-05-03 17:59:40.388123240 +0300 -@@ -1,6 +1,13 @@ - # - # Automatically generated make config: don't edit - # -+CONFIG_EXT3_FS_XATTR=y -+# CONFIG_EXT3_FS_XATTR_SHARING is not set -+# CONFIG_EXT3_FS_XATTR_USER is not set -+# CONFIG_EXT2_FS_XATTR is not set -+# CONFIG_EXT2_FS_XATTR_SHARING is not set -+# CONFIG_EXT2_FS_XATTR_USER is not set -+# CONFIG_FS_MBCACHE is not set - - # - # Code maturity level options -Index: linux-2.4.29/fs/Config.in -=================================================================== ---- linux-2.4.29.orig/fs/Config.in 2005-04-07 18:54:16.000000000 +0300 -+++ linux-2.4.29/fs/Config.in 2005-05-03 17:59:40.389123088 +0300 -@@ -29,6 +29,11 @@ - dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL - - tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS -+dep_mbool ' Ext3 extended attributes' CONFIG_EXT3_FS_XATTR $CONFIG_EXT3_FS -+dep_bool ' Ext3 extended attribute block sharing' \ -+ CONFIG_EXT3_FS_XATTR_SHARING $CONFIG_EXT3_FS_XATTR -+dep_bool ' Ext3 extended user attributes' \ -+ CONFIG_EXT3_FS_XATTR_USER $CONFIG_EXT3_FS_XATTR - # CONFIG_JBD could be its own option (even modular), but until there are - # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS - # dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS -@@ -92,6 +97,11 @@ - tristate 'ROM file system support' CONFIG_ROMFS_FS - - tristate 'Second extended fs support' CONFIG_EXT2_FS -+dep_mbool ' Ext2 extended attributes' CONFIG_EXT2_FS_XATTR $CONFIG_EXT2_FS -+dep_bool ' Ext2 extended attribute block sharing' \ -+ CONFIG_EXT2_FS_XATTR_SHARING $CONFIG_EXT2_FS_XATTR -+dep_bool ' Ext2 extended user attributes' \ -+ CONFIG_EXT2_FS_XATTR_USER $CONFIG_EXT2_FS_XATTR - - tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS - -@@ -171,6 +181,10 @@ - define_tristate CONFIG_ZISOFS_FS n - fi - -+# Meta block cache for Extended Attributes (ext2/ext3) -+#tristate 'Meta block cache' CONFIG_FS_MBCACHE -+define_tristate CONFIG_FS_MBCACHE y -+ - mainmenu_option next_comment - comment 'Partition Types' - source fs/partitions/Config.in -Index: linux-2.4.29/fs/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/Makefile 2005-05-03 17:23:53.969428480 +0300 -+++ linux-2.4.29/fs/Makefile 2005-05-03 17:59:40.390122936 +0300 -@@ -77,6 +77,9 @@ - - obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o - -+export-objs += mbcache.o -+obj-$(CONFIG_FS_MBCACHE) += mbcache.o -+ - # persistent filesystems - obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) - -Index: linux-2.4.29/fs/ext2/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/ext2/Makefile 2005-04-07 18:54:32.000000000 +0300 -+++ linux-2.4.29/fs/ext2/Makefile 2005-05-03 17:59:40.391122784 +0300 -@@ -13,4 +13,8 @@ - ioctl.o namei.o super.o symlink.o - obj-m := $(O_TARGET) - -+export-objs += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT2_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make -Index: linux-2.4.29/fs/ext2/file.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/file.c 2005-04-07 18:53:14.000000000 +0300 -+++ linux-2.4.29/fs/ext2/file.c 2005-05-03 17:59:40.392122632 +0300 -@@ -20,6 +20,7 @@ - - #include - #include -+#include - #include - - /* -@@ -51,4 +52,8 @@ - - struct inode_operations ext2_file_inode_operations = { - truncate: ext2_truncate, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.29/fs/ext2/ialloc.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/ialloc.c 2005-04-07 18:53:47.000000000 +0300 -+++ linux-2.4.29/fs/ext2/ialloc.c 2005-05-03 17:59:40.393122480 +0300 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -167,6 +168,7 @@ - */ - if (!is_bad_inode(inode)) { - /* Quota is already initialized in iput() */ -+ ext2_xattr_delete_inode(inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - } -Index: linux-2.4.29/fs/ext2/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/inode.c 2005-04-07 18:52:32.000000000 +0300 -+++ linux-2.4.29/fs/ext2/inode.c 2005-05-03 17:59:40.396122024 +0300 -@@ -64,9 +64,7 @@ - { - lock_kernel(); - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - inode->u.ext2_i.i_dtime = CURRENT_TIME; - mark_inode_dirty(inode); -@@ -815,6 +813,8 @@ - return; - if (ext2_inode_is_fast_symlink(inode)) - return; -+ if (ext2_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -917,8 +917,7 @@ - unsigned long offset; - struct ext2_group_desc * gdp; - -- if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO && -- inode->i_ino != EXT2_ACL_DATA_INO && -+ if ((inode->i_ino != EXT2_ROOT_INO && - inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) { - ext2_error (inode->i_sb, "ext2_read_inode", -@@ -1004,10 +1003,7 @@ - for (block = 0; block < EXT2_N_BLOCKS; block++) - inode->u.ext2_i.i_data[block] = raw_inode->i_block[block]; - -- if (inode->i_ino == EXT2_ACL_IDX_INO || -- inode->i_ino == EXT2_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext2_file_inode_operations; - inode->i_fop = &ext2_file_operations; - inode->i_mapping->a_ops = &ext2_aops; -@@ -1019,12 +1015,14 @@ - if (ext2_inode_is_fast_symlink(inode)) - inode->i_op = &ext2_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - } -- } else -+ } else { -+ inode->i_op = &ext2_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); -+ } - brelse (bh); - inode->i_attr_flags = 0; - ext2_set_inode_flags(inode); -Index: linux-2.4.29/fs/ext2/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/namei.c 2005-04-07 18:54:50.000000000 +0300 -+++ linux-2.4.29/fs/ext2/namei.c 2005-05-03 17:59:40.397121872 +0300 -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - - /* -@@ -136,7 +137,7 @@ - - if (l > sizeof (inode->u.ext2_i.i_data)) { - /* slow symlink */ -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext2_symlink_inode_operations; - inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); - if (err) -@@ -345,4 +346,15 @@ - rmdir: ext2_rmdir, - mknod: ext2_mknod, - rename: ext2_rename, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ -+struct inode_operations ext2_special_inode_operations = { -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.29/fs/ext2/super.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/super.c 2005-04-07 18:54:16.000000000 +0300 -+++ linux-2.4.29/fs/ext2/super.c 2005-05-03 17:59:40.400121416 +0300 -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -125,6 +126,7 @@ - int db_count; - int i; - -+ ext2_xattr_put_super(sb); - if (!(sb->s_flags & MS_RDONLY)) { - struct ext2_super_block *es = EXT2_SB(sb)->s_es; - -@@ -175,6 +177,13 @@ - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -446,6 +455,9 @@ - blocksize = BLOCK_SIZE; - - sb->u.ext2_sb.s_mount_opt = 0; -+#ifdef CONFIG_EXT2_FS_XATTR_USER -+ /* set_opt (sb->u.ext2_sb.s_mount_opt, XATTR_USER); */ -+#endif - if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, - &sb->u.ext2_sb.s_mount_opt)) { - return NULL; -@@ -840,12 +852,27 @@ - - static int __init init_ext2_fs(void) - { -- return register_filesystem(&ext2_fs_type); -+ int error = init_ext2_xattr(); -+ if (error) -+ return error; -+ error = init_ext2_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext2_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext2_xattr_user(); -+fail: -+ exit_ext2_xattr(); -+ return error; - } - - static void __exit exit_ext2_fs(void) - { - unregister_filesystem(&ext2_fs_type); -+ exit_ext2_xattr_user(); -+ exit_ext2_xattr(); - } - - EXPORT_NO_SYMBOLS; -Index: linux-2.4.29/fs/ext2/symlink.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/symlink.c 2005-04-07 18:52:53.000000000 +0300 -+++ linux-2.4.29/fs/ext2/symlink.c 2005-05-03 17:59:40.400121416 +0300 -@@ -19,6 +19,7 @@ - - #include - #include -+#include - - static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -32,7 +33,20 @@ - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext2_symlink_inode_operations = { -+ readlink: page_readlink, -+ follow_link: page_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, -+}; -+ - struct inode_operations ext2_fast_symlink_inode_operations = { - readlink: ext2_readlink, - follow_link: ext2_follow_link, -+ setxattr: ext2_setxattr, -+ getxattr: ext2_getxattr, -+ listxattr: ext2_listxattr, -+ removexattr: ext2_removexattr, - }; -Index: linux-2.4.29/fs/ext2/xattr.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/xattr.c 2005-05-03 17:59:40.233146800 +0300 -+++ linux-2.4.29/fs/ext2/xattr.c 2005-05-03 17:59:40.405120656 +0300 -@@ -0,0 +1,1212 @@ -+/* -+ * linux/fs/ext2/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT2_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT2_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext2_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* These symbols may be needed by a module. */ -+EXPORT_SYMBOL(ext2_xattr_register); -+EXPORT_SYMBOL(ext2_xattr_unregister); -+EXPORT_SYMBOL(ext2_xattr_get); -+EXPORT_SYMBOL(ext2_xattr_list); -+EXPORT_SYMBOL(ext2_xattr_set); -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT2_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext2_xattr_set2(struct inode *, struct buffer_head *, -+ struct ext2_xattr_header *); -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+static int ext2_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext2_xattr_cache_find(struct inode *, -+ struct ext2_xattr_header *); -+static void ext2_xattr_cache_remove(struct buffer_head *); -+static void ext2_xattr_rehash(struct ext2_xattr_header *, -+ struct ext2_xattr_entry *); -+ -+static struct mb_cache *ext2_xattr_cache; -+ -+#else -+# define ext2_xattr_cache_insert(bh) 0 -+# define ext2_xattr_cache_find(inode, header) NULL -+# define ext2_xattr_cache_remove(bh) while(0) {} -+# define ext2_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext2_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext2_xattr_sem); -+ -+static inline int -+ext2_xattr_new_block(struct inode *inode, int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) + -+ EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext2_new_block(inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext2_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext2_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext2_xattr_free_block(struct inode * inode, unsigned long block) -+{ -+ ext2_free_blocks(inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext2_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext2_xattr_free_block(inode, block) \ -+ ext2_free_blocks(inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX]; -+rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext2_xattr_register(int name_index, struct ext2_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ if (!ext2_xattr_handlers[name_index-1]) { -+ ext2_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext2_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext2_xattr_unregister(int name_index, struct ext2_xattr_handler *handler) -+{ -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ write_lock(&ext2_handler_lock); -+ ext2_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext2_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static struct ext2_xattr_handler * -+ext2_xattr_resolve_name(const char **name) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext2_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext2_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext2_handler_lock); -+ return handler; -+} -+ -+static inline struct ext2_xattr_handler * -+ext2_xattr_handler(int name_index) -+{ -+ struct ext2_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT2_XATTR_INDEX_MAX) { -+ read_lock(&ext2_handler_lock); -+ handler = ext2_xattr_handlers[name_index-1]; -+ read_unlock(&ext2_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext2_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext2_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext2_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext2_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext2_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT2_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT2_I(inode)->i_file_acl) -+ return 0; -+ block = EXT2_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(inode->i_sb, "ext2_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ struct ext2_xattr_entry *next = -+ EXT2_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext2_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT2_XATTR_NEXT(entry)) { -+ struct ext2_xattr_handler *handler; -+ -+ handler = ext2_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT2_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext2_xattr_update_super_block(struct super_block *sb) -+{ -+ if (EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT2_SB(sb)->s_feature_compat |= EXT2_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT2_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT2_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ mark_buffer_dirty(EXT2_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext2_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext2_xattr_header *header = NULL; -+ struct ext2_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT2_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext2_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext2_error(sb, "ext2_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext2_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT2_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT2_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT2_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext2_xattr_cache_remove(bh); -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT2_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT2_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext2_xattr_set2(inode, bh, NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT2_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT2_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT2_XATTR_PAD, 0, -+ EXT2_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext2_xattr_rehash(header, here); -+ -+ error = ext2_xattr_set2(inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext2_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext2_xattr_set(): Update the file system. -+ */ -+static int -+ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, -+ struct ext2_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext2_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext2_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext2_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT2_I(inode)->i_file_acl != 0; -+ int block = ext2_xattr_new_block(inode, &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+ ext2_xattr_free_block(inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext2_xattr_cache_insert(new_bh); -+ -+ ext2_xattr_update_super_block(sb); -+ } -+ mark_buffer_dirty(new_bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &new_bh); -+ wait_on_buffer(new_bh); -+ error = -EIO; -+ if (buffer_req(new_bh) && !buffer_uptodate(new_bh)) -+ goto cleanup; -+ } -+ } -+ -+ /* Update the inode. */ -+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ if (IS_SYNC(inode)) { -+ error = ext2_sync_inode (inode); -+ if (error) -+ goto cleanup; -+ } else -+ mark_inode_dirty(inode); -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext2_xattr_free_block(inode, old_bh->b_blocknr); -+ mark_buffer_clean(old_bh); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext2_xattr_quota_free(inode); -+ mark_buffer_dirty(old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext2_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT2_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext2_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT2_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext2_error(inode->i_sb, "ext2_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext2_xattr_cache_remove(bh); -+ ext2_xattr_free_block(inode, block); -+ bforget(bh); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ mark_buffer_dirty(bh); -+ if (IS_SYNC(inode)) { -+ ll_rw_block(WRITE, 1, &bh); -+ wait_on_buffer(bh); -+ } -+ ext2_xattr_quota_free(inode); -+ } -+ EXT2_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext2_xattr_sem); -+} -+ -+/* -+ * ext2_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ mb_cache_shrink(ext2_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT2_FS_XATTR_SHARING -+ -+/* -+ * ext2_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext2_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext2_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext2_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext2_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext2_xattr_cmp(struct ext2_xattr_header *header1, -+ struct ext2_xattr_header *header2) -+{ -+ struct ext2_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT2_XATTR_NEXT(entry1); -+ entry2 = EXT2_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext2_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext2_error(inode->i_sb, "ext2_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT2_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT2_XATTR_REFCOUNT_MAX); -+ } else if (!ext2_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext2_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext2_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext2_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext2_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext2_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext2_xattr_rehash(struct ext2_xattr_header *header, -+ struct ext2_xattr_entry *entry) -+{ -+ struct ext2_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext2_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT2_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext2_xattr(void) -+{ -+ ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext2_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+ mb_cache_destroy(ext2_xattr_cache); -+} -+ -+#else /* CONFIG_EXT2_FS_XATTR_SHARING */ -+ -+int __init -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext2_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT2_FS_XATTR_SHARING */ -Index: linux-2.4.29/fs/ext2/xattr_user.c -=================================================================== ---- linux-2.4.29.orig/fs/ext2/xattr_user.c 2005-05-03 17:59:40.233146800 +0300 -+++ linux-2.4.29/fs/ext2/xattr_user.c 2005-05-03 17:59:40.407120352 +0300 -@@ -0,0 +1,103 @@ -+/* -+ * linux/fs/ext2/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext2_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext2_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext2_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT2_FS_POSIX_ACL -+ error = ext2_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, -+ value, size, flags); -+} -+ -+struct ext2_xattr_handler ext2_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext2_xattr_user_list, -+ get: ext2_xattr_user_get, -+ set: ext2_xattr_user_set, -+}; -+ -+int __init -+init_ext2_xattr_user(void) -+{ -+ return ext2_xattr_register(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -+ -+void -+exit_ext2_xattr_user(void) -+{ -+ ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, -+ &ext2_xattr_user_handler); -+} -Index: linux-2.4.29/fs/ext3/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/ext3/Makefile 2005-05-03 17:23:54.093409632 +0300 -+++ linux-2.4.29/fs/ext3/Makefile 2005-05-03 17:59:40.408120200 +0300 -@@ -1,5 +1,5 @@ - # --# Makefile for the linux ext2-filesystem routines. -+# Makefile for the linux ext3-filesystem routines. - # - # Note! Dependencies are done automagically by 'make dep', which also - # removes any old dependencies. DON'T put your own dependencies here -@@ -9,10 +9,14 @@ - - O_TARGET := ext3.o - --export-objs := super.o inode.o -+export-objs := ext3-exports.o - - obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ -- ioctl.o namei.o super.o symlink.o hash.o -+ ioctl.o namei.o super.o symlink.o hash.o ext3-exports.o - obj-m := $(O_TARGET) - -+export-objs += xattr.o -+obj-$(CONFIG_EXT3_FS_XATTR) += xattr.o -+obj-$(CONFIG_EXT3_FS_XATTR_USER) += xattr_user.o -+ - include $(TOPDIR)/Rules.make -Index: linux-2.4.29/fs/ext3/file.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/file.c 2005-05-03 17:23:54.091409936 +0300 -+++ linux-2.4.29/fs/ext3/file.c 2005-05-03 17:59:40.410119896 +0300 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -127,5 +128,9 @@ - struct inode_operations ext3_file_inode_operations = { - truncate: ext3_truncate, /* BKL held */ - setattr: ext3_setattr, /* BKL held */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; - -Index: linux-2.4.29/fs/ext3/ialloc.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/ialloc.c 2005-04-07 18:53:42.000000000 +0300 -+++ linux-2.4.29/fs/ext3/ialloc.c 2005-05-03 17:59:40.411119744 +0300 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -216,6 +217,7 @@ - * as writing the quota to disk may need the lock as well. - */ - DQUOT_INIT(inode); -+ ext3_xattr_delete_inode(handle, inode); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - -Index: linux-2.4.29/fs/ext3/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/inode.c 2005-04-07 18:54:16.000000000 +0300 -+++ linux-2.4.29/fs/ext3/inode.c 2005-05-03 17:59:40.415119136 +0300 -@@ -60,7 +60,7 @@ - * still needs to be revoked. - */ - --static int ext3_forget(handle_t *handle, int is_metadata, -+int ext3_forget(handle_t *handle, int is_metadata, - struct inode *inode, struct buffer_head *bh, - int blocknr) - { -@@ -191,9 +191,7 @@ - { - handle_t *handle; - -- if (is_bad_inode(inode) || -- inode->i_ino == EXT3_ACL_IDX_INO || -- inode->i_ino == EXT3_ACL_DATA_INO) -+ if (is_bad_inode(inode)) - goto no_delete; - - lock_kernel(); -@@ -1885,6 +1883,8 @@ - return; - if (ext3_inode_is_fast_symlink(inode)) - return; -+ if (ext3_inode_is_fast_symlink(inode)) -+ return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return; - -@@ -2032,8 +2032,6 @@ - struct ext3_group_desc * gdp; - - if ((inode->i_ino != EXT3_ROOT_INO && -- inode->i_ino != EXT3_ACL_IDX_INO && -- inode->i_ino != EXT3_ACL_DATA_INO && - inode->i_ino != EXT3_JOURNAL_INO && - inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) || - inode->i_ino > le32_to_cpu( -@@ -2174,10 +2172,7 @@ - inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block]; - INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan); - -- if (inode->i_ino == EXT3_ACL_IDX_INO || -- inode->i_ino == EXT3_ACL_DATA_INO) -- /* Nothing to do */ ; -- else if (S_ISREG(inode->i_mode)) { -+ if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext3_file_inode_operations; - inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; -@@ -2188,12 +2183,14 @@ - if (ext3_inode_is_fast_symlink(inode)) - inode->i_op = &ext3_fast_symlink_inode_operations; - else { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - } -- } else -+ } else { -+ inode->i_op = &ext3_special_inode_operations; - init_special_inode(inode, inode->i_mode, - le32_to_cpu(iloc.raw_inode->i_block[0])); -+ } - brelse(iloc.bh); - ext3_set_inode_flags(inode); - return; -Index: linux-2.4.29/fs/ext3/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/namei.c 2005-05-03 17:23:54.101408416 +0300 -+++ linux-2.4.29/fs/ext3/namei.c 2005-05-03 17:59:40.419118528 +0300 -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1613,7 +1614,7 @@ - if (IS_SYNC(dir)) - handle->h_sync = 1; - -- inode = ext3_new_inode (handle, dir, S_IFDIR); -+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode); - err = PTR_ERR(inode); - if (IS_ERR(inode)) - goto out_stop; -@@ -1621,7 +1622,6 @@ - inode->i_op = &ext3_dir_inode_operations; - inode->i_fop = &ext3_dir_operations; - inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; -- inode->i_blocks = 0; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ -@@ -1648,9 +1648,6 @@ - BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata"); - ext3_journal_dirty_metadata(handle, dir_block); - brelse (dir_block); -- inode->i_mode = S_IFDIR | mode; -- if (dir->i_mode & S_ISGID) -- inode->i_mode |= S_ISGID; - ext3_mark_inode_dirty(handle, inode); - err = ext3_add_entry (handle, dentry, inode); - if (err) { -@@ -2019,7 +2016,7 @@ - goto out_stop; - - if (l > sizeof (EXT3_I(inode)->i_data)) { -- inode->i_op = &page_symlink_inode_operations; -+ inode->i_op = &ext3_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; - /* - * block_symlink() calls back into ext3_prepare/commit_write. -@@ -2248,4 +2245,16 @@ - rmdir: ext3_rmdir, /* BKL held */ - mknod: ext3_mknod, /* BKL held */ - rename: ext3_rename, /* BKL held */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; -+ -+struct inode_operations ext3_special_inode_operations = { -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ -+}; -+ -Index: linux-2.4.29/fs/ext3/super.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/super.c 2005-05-03 17:23:54.104407960 +0300 -+++ linux-2.4.29/fs/ext3/super.c 2005-05-03 18:00:16.805586944 +0300 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -406,6 +407,7 @@ - kdev_t j_dev = sbi->s_journal->j_dev; - int i; - -+ ext3_xattr_put_super(sb); - journal_destroy(sbi->s_journal); - if (!(sb->s_flags & MS_RDONLY)) { - EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); -@@ -504,6 +506,7 @@ - int is_remount) - { - unsigned long *mount_options = &sbi->s_mount_opt; -+ - uid_t *resuid = &sbi->s_resuid; - gid_t *resgid = &sbi->s_resgid; - char * this_char; -@@ -516,6 +519,13 @@ - this_char = strtok (NULL, ",")) { - if ((value = strchr (this_char, '=')) != NULL) - *value++ = 0; -+#ifdef CONFIG_EXT3_FS_XATTR_USER -+ if (!strcmp (this_char, "user_xattr")) -+ set_opt (*mount_options, XATTR_USER); -+ else if (!strcmp (this_char, "nouser_xattr")) -+ clear_opt (*mount_options, XATTR_USER); -+ else -+#endif - if (!strcmp (this_char, "bsddf")) - clear_opt (*mount_options, MINIX_DF); - else if (!strcmp (this_char, "nouid32")) { -@@ -954,6 +964,12 @@ - sbi->s_mount_opt = 0; - sbi->s_resuid = EXT3_DEF_RESUID; - sbi->s_resgid = EXT3_DEF_RESGID; -+ -+ /* Default extended attribute flags */ -+#ifdef CONFIG_EXT3_FS_XATTR_USER -+ /* set_opt(sbi->s_mount_opt, XATTR_USER); */ -+#endif -+ - if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) { - sb->s_dev = 0; - goto out_fail; -@@ -1838,22 +1854,35 @@ - - static int __init init_ext3_fs(void) - { -+ int error; - #ifdef CONFIG_QUOTA - init_dquot_operations(&ext3_qops); - old_write_dquot = ext3_qops.write_dquot; - ext3_qops.write_dquot = ext3_write_dquot; - #endif -- return register_filesystem(&ext3_fs_type); -+ error = init_ext3_xattr(); -+ if (error) -+ return error; -+ error = init_ext3_xattr_user(); -+ if (error) -+ goto fail; -+ error = register_filesystem(&ext3_fs_type); -+ if (!error) -+ return 0; -+ -+ exit_ext3_xattr_user(); -+fail: -+ exit_ext3_xattr(); -+ return error; - } - - static void __exit exit_ext3_fs(void) - { - unregister_filesystem(&ext3_fs_type); -+ exit_ext3_xattr_user(); -+ exit_ext3_xattr(); - } - --EXPORT_SYMBOL(ext3_force_commit); --EXPORT_SYMBOL(ext3_bread); -- - MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); - MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions"); - MODULE_LICENSE("GPL"); -Index: linux-2.4.29/fs/ext3/symlink.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/symlink.c 2005-04-07 18:53:53.000000000 +0300 -+++ linux-2.4.29/fs/ext3/symlink.c 2005-05-03 17:59:40.423117920 +0300 -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen) - { -@@ -33,7 +34,20 @@ - return vfs_follow_link(nd, s); - } - -+struct inode_operations ext3_symlink_inode_operations = { -+ readlink: page_readlink, /* BKL not held. Don't need */ -+ follow_link: page_follow_link, /* BKL not held. Don't need */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ -+}; -+ - struct inode_operations ext3_fast_symlink_inode_operations = { - readlink: ext3_readlink, /* BKL not held. Don't need */ - follow_link: ext3_follow_link, /* BKL not held. Don't need */ -+ setxattr: ext3_setxattr, /* BKL held */ -+ getxattr: ext3_getxattr, /* BKL held */ -+ listxattr: ext3_listxattr, /* BKL held */ -+ removexattr: ext3_removexattr, /* BKL held */ - }; -Index: linux-2.4.29/fs/ext3/xattr.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/xattr.c 2005-05-03 17:59:40.234146648 +0300 -+++ linux-2.4.29/fs/ext3/xattr.c 2005-05-03 17:59:40.428117160 +0300 -@@ -0,0 +1,1225 @@ -+/* -+ * linux/fs/ext3/xattr.c -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ * -+ * Fix by Harrison Xing . -+ * Ext3 code with a lot of help from Eric Jarman . -+ * Extended attributes for symlinks and special files added per -+ * suggestion of Luka Renko . -+ */ -+ -+/* -+ * Extended attributes are stored on disk blocks allocated outside of -+ * any inode. The i_file_acl field is then made to point to this allocated -+ * block. If all extended attributes of an inode are identical, these -+ * inodes may share the same extended attribute block. Such situations -+ * are automatically detected by keeping a cache of recent attribute block -+ * numbers and hashes over the block's contents in memory. -+ * -+ * -+ * Extended attribute block layout: -+ * -+ * +------------------+ -+ * | header | -+ * | entry 1 | | -+ * | entry 2 | | growing downwards -+ * | entry 3 | v -+ * | four null bytes | -+ * | . . . | -+ * | value 1 | ^ -+ * | value 3 | | growing upwards -+ * | value 2 | | -+ * +------------------+ -+ * -+ * The block header is followed by multiple entry descriptors. These entry -+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD -+ * byte boundaries. The entry descriptors are sorted by attribute name, -+ * so that two extended attribute blocks can be compared efficiently. -+ * -+ * Attribute values are aligned to the end of the block, stored in -+ * no specific order. They are also padded to EXT3_XATTR_PAD byte -+ * boundaries. No additional gaps are left between them. -+ * -+ * Locking strategy -+ * ---------------- -+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of -+ * the xattr inode operations are called, so we are guaranteed that only one -+ * processes accesses extended attributes of an inode at any time. -+ * -+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that -+ * only a single process is modifying an extended attribute block, even -+ * if the block is shared among inodes. -+ * -+ * Note for porting to 2.5 -+ * ----------------------- -+ * The BKL will no longer be held in the xattr inode operations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define EXT3_EA_USER "user." -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1) -+#endif -+ -+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data)) -+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr)) -+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1) -+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) -+ -+#ifdef EXT3_XATTR_DEBUG -+# define ea_idebug(inode, f...) do { \ -+ printk(KERN_DEBUG "inode %s:%ld: ", \ -+ kdevname(inode->i_dev), inode->i_ino); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+# define ea_bdebug(bh, f...) do { \ -+ printk(KERN_DEBUG "block %s:%ld: ", \ -+ kdevname(bh->b_dev), bh->b_blocknr); \ -+ printk(f); \ -+ printk("\n"); \ -+ } while (0) -+#else -+# define ea_idebug(f...) -+# define ea_bdebug(f...) -+#endif -+ -+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *, -+ struct ext3_xattr_header *); -+ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ -+static int ext3_xattr_cache_insert(struct buffer_head *); -+static struct buffer_head *ext3_xattr_cache_find(struct inode *, -+ struct ext3_xattr_header *); -+static void ext3_xattr_cache_remove(struct buffer_head *); -+static void ext3_xattr_rehash(struct ext3_xattr_header *, -+ struct ext3_xattr_entry *); -+ -+static struct mb_cache *ext3_xattr_cache; -+ -+#else -+# define ext3_xattr_cache_insert(bh) 0 -+# define ext3_xattr_cache_find(inode, header) NULL -+# define ext3_xattr_cache_remove(bh) while(0) {} -+# define ext3_xattr_rehash(header, entry) while(0) {} -+#endif -+ -+/* -+ * If a file system does not share extended attributes among inodes, -+ * we should not need the ext3_xattr_sem semaphore. However, the -+ * filesystem may still contain shared blocks, so we always take -+ * the lock. -+ */ -+ -+DECLARE_MUTEX(ext3_xattr_sem); -+ -+static inline int -+ext3_xattr_new_block(handle_t *handle, struct inode *inode, -+ int * errp, int force) -+{ -+ struct super_block *sb = inode->i_sb; -+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) + -+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb); -+ -+ /* How can we enforce the allocation? */ -+ int block = ext3_new_block(handle, inode, goal, 0, 0, errp); -+#ifdef OLD_QUOTAS -+ if (!*errp) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#endif -+ return block; -+} -+ -+static inline int -+ext3_xattr_quota_alloc(struct inode *inode, int force) -+{ -+ /* How can we enforce the allocation? */ -+#ifdef OLD_QUOTAS -+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1); -+ if (!error) -+ inode->i_blocks += inode->i_sb->s_blocksize >> 9; -+#else -+ int error = DQUOT_ALLOC_BLOCK(inode, 1); -+#endif -+ return error; -+} -+ -+#ifdef OLD_QUOTAS -+ -+static inline void -+ext3_xattr_quota_free(struct inode *inode) -+{ -+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+static inline void -+ext3_xattr_free_block(handle_t *handle, struct inode * inode, -+ unsigned long block) -+{ -+ ext3_free_blocks(handle, inode, block, 1); -+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9; -+} -+ -+#else -+# define ext3_xattr_quota_free(inode) \ -+ DQUOT_FREE_BLOCK(inode, 1) -+# define ext3_xattr_free_block(handle, inode, block) \ -+ ext3_free_blocks(handle, inode, block, 1) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) -+ -+static inline struct buffer_head * -+sb_bread(struct super_block *sb, int block) -+{ -+ return bread(sb->s_dev, block, sb->s_blocksize); -+} -+ -+static inline struct buffer_head * -+sb_getblk(struct super_block *sb, int block) -+{ -+ return getblk(sb->s_dev, block, sb->s_blocksize); -+} -+ -+#endif -+ -+struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX]; -+rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED; -+ -+int -+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler) -+{ -+ int error = -EINVAL; -+ -+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) { -+ write_lock(&ext3_handler_lock); -+ if (!ext3_xattr_handlers[name_index-1]) { -+ ext3_xattr_handlers[name_index-1] = handler; -+ error = 0; -+ } -+ write_unlock(&ext3_handler_lock); -+ } -+ return error; -+} -+ -+void -+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler) -+{ -+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) { -+ write_lock(&ext3_handler_lock); -+ ext3_xattr_handlers[name_index-1] = NULL; -+ write_unlock(&ext3_handler_lock); -+ } -+} -+ -+static inline const char * -+strcmp_prefix(const char *a, const char *a_prefix) -+{ -+ while (*a_prefix && *a == *a_prefix) { -+ a++; -+ a_prefix++; -+ } -+ return *a_prefix ? NULL : a; -+} -+ -+/* -+ * Decode the extended attribute name, and translate it into -+ * the name_index and name suffix. -+ */ -+static inline struct ext3_xattr_handler * -+ext3_xattr_resolve_name(const char **name) -+{ -+ struct ext3_xattr_handler *handler = NULL; -+ int i; -+ -+ if (!*name) -+ return NULL; -+ read_lock(&ext3_handler_lock); -+ for (i=0; iprefix); -+ if (n) { -+ handler = ext3_xattr_handlers[i]; -+ *name = n; -+ break; -+ } -+ } -+ } -+ read_unlock(&ext3_handler_lock); -+ return handler; -+} -+ -+static inline struct ext3_xattr_handler * -+ext3_xattr_handler(int name_index) -+{ -+ struct ext3_xattr_handler *handler = NULL; -+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) { -+ read_lock(&ext3_handler_lock); -+ handler = ext3_xattr_handlers[name_index-1]; -+ read_unlock(&ext3_handler_lock); -+ } -+ return handler; -+} -+ -+/* -+ * Inode operation getxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext3_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->get(inode, name, buffer, size); -+} -+ -+/* -+ * Inode operation listxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+ssize_t -+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ return ext3_xattr_list(dentry->d_inode, buffer, size); -+} -+ -+/* -+ * Inode operation setxattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext3_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, value, size, flags); -+} -+ -+/* -+ * Inode operation removexattr() -+ * -+ * dentry->d_inode->i_sem down -+ * BKL held [before 2.5.x] -+ */ -+int -+ext3_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct ext3_xattr_handler *handler; -+ struct inode *inode = dentry->d_inode; -+ -+ handler = ext3_xattr_resolve_name(&name); -+ if (!handler) -+ return -ENOTSUP; -+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE); -+} -+ -+/* -+ * ext3_xattr_get() -+ * -+ * Copy an extended attribute into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ unsigned int block, size; -+ char *end; -+ int name_len, error; -+ -+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", -+ name_index, name, buffer, (long)buffer_size); -+ -+ if (name == NULL) -+ return -EINVAL; -+ if (!EXT3_I(inode)->i_file_acl) -+ return -ENOATTR; -+ block = EXT3_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* find named attribute */ -+ name_len = strlen(name); -+ -+ error = -ERANGE; -+ if (name_len > 255) -+ goto cleanup; -+ entry = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (name_index == entry->e_name_index && -+ name_len == entry->e_name_len && -+ memcmp(name, entry->e_name, name_len) == 0) -+ goto found; -+ entry = next; -+ } -+ /* Check the remaining name entries */ -+ while (!IS_LAST_ENTRY(entry)) { -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ entry = next; -+ } -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ error = -ENOATTR; -+ goto cleanup; -+found: -+ /* check the buffer size */ -+ if (entry->e_value_block != 0) -+ goto bad_block; -+ size = le32_to_cpu(entry->e_value_size); -+ if (size > inode->i_sb->s_blocksize || -+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) -+ goto bad_block; -+ -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (buffer) { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ /* return value of attribute */ -+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), -+ size); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_list() -+ * -+ * Copy a list of attribute names into the buffer -+ * provided, or compute the buffer size required. -+ * Buffer is NULL to compute the size of the buffer required. -+ * -+ * Returns a negative error number on failure, or the number of bytes -+ * used / required on success. -+ */ -+int -+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) -+{ -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_entry *entry; -+ unsigned int block, size = 0; -+ char *buf, *end; -+ int error; -+ -+ ea_idebug(inode, "buffer=%p, buffer_size=%ld", -+ buffer, (long)buffer_size); -+ -+ if (!EXT3_I(inode)->i_file_acl) -+ return 0; -+ block = EXT3_I(inode)->i_file_acl; -+ ea_idebug(inode, "reading block %d", block); -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) -+ return -EIO; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount)); -+ end = bh->b_data + bh->b_size; -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* compute the size required for the list of attribute names */ -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT3_XATTR_NEXT(entry)) { -+ struct ext3_xattr_handler *handler; -+ struct ext3_xattr_entry *next = -+ EXT3_XATTR_NEXT(entry); -+ if ((char *)next >= end) -+ goto bad_block; -+ -+ handler = ext3_xattr_handler(entry->e_name_index); -+ if (handler) -+ size += handler->list(NULL, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ -+ if (ext3_xattr_cache_insert(bh)) -+ ea_idebug(inode, "cache insert failed"); -+ if (!buffer) { -+ error = size; -+ goto cleanup; -+ } else { -+ error = -ERANGE; -+ if (size > buffer_size) -+ goto cleanup; -+ } -+ -+ /* list the attribute names */ -+ buf = buffer; -+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry); -+ entry = EXT3_XATTR_NEXT(entry)) { -+ struct ext3_xattr_handler *handler; -+ -+ handler = ext3_xattr_handler(entry->e_name_index); -+ if (handler) -+ buf += handler->list(buf, inode, entry->e_name, -+ entry->e_name_len); -+ } -+ error = size; -+ -+cleanup: -+ brelse(bh); -+ -+ return error; -+} -+ -+/* -+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is -+ * not set, set it. -+ */ -+static void ext3_xattr_update_super_block(handle_t *handle, -+ struct super_block *sb) -+{ -+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR)) -+ return; -+ -+ lock_super(sb); -+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR; -+#endif -+ EXT3_SB(sb)->s_es->s_feature_compat |= -+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR); -+ sb->s_dirt = 1; -+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); -+ unlock_super(sb); -+} -+ -+/* -+ * ext3_xattr_set() -+ * -+ * Create, replace or remove an extended attribute for this inode. Buffer -+ * is NULL to remove an existing extended attribute, and non-NULL to -+ * either replace an existing extended attribute, or create a new extended -+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE -+ * specify that an extended attribute must exist and must not exist -+ * previous to the call, respectively. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t value_len, int flags) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *bh = NULL; -+ struct ext3_xattr_header *header = NULL; -+ struct ext3_xattr_entry *here, *last; -+ unsigned int name_len; -+ int block = EXT3_I(inode)->i_file_acl; -+ int min_offs = sb->s_blocksize, not_found = 1, free, error; -+ char *end; -+ -+ /* -+ * header -- Points either into bh, or to a temporarily -+ * allocated buffer. -+ * here -- The named entry found, or the place for inserting, within -+ * the block pointed to by header. -+ * last -- Points right after the last named entry within the block -+ * pointed to by header. -+ * min_offs -- The offset of the first value (values are aligned -+ * towards the end of the block). -+ * end -- Points right after the block pointed to by header. -+ */ -+ -+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld", -+ name_index, name, value, (long)value_len); -+ -+ if (IS_RDONLY(inode)) -+ return -EROFS; -+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -+ return -EPERM; -+ if (value == NULL) -+ value_len = 0; -+ if (name == NULL) -+ return -EINVAL; -+ name_len = strlen(name); -+ if (name_len > 255 || value_len > sb->s_blocksize) -+ return -ERANGE; -+ down(&ext3_xattr_sem); -+ -+ if (block) { -+ /* The inode already has an extended attribute block. */ -+ bh = sb_bread(sb, block); -+ error = -EIO; -+ if (!bh) -+ goto cleanup; -+ ea_bdebug(bh, "b_count=%d, refcount=%d", -+ atomic_read(&(bh->b_count)), -+ le32_to_cpu(HDR(bh)->h_refcount)); -+ header = HDR(bh); -+ end = bh->b_data + bh->b_size; -+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ header->h_blocks != cpu_to_le32(1)) { -+bad_block: ext3_error(sb, "ext3_xattr_set", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ /* Find the named attribute. */ -+ here = FIRST_ENTRY(bh); -+ while (!IS_LAST_ENTRY(here)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!here->e_value_block && here->e_value_size) { -+ int offs = le16_to_cpu(here->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ not_found = name_index - here->e_name_index; -+ if (!not_found) -+ not_found = name_len - here->e_name_len; -+ if (!not_found) -+ not_found = memcmp(name, here->e_name,name_len); -+ if (not_found <= 0) -+ break; -+ here = next; -+ } -+ last = here; -+ /* We still need to compute min_offs and last. */ -+ while (!IS_LAST_ENTRY(last)) { -+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last); -+ if ((char *)next >= end) -+ goto bad_block; -+ if (!last->e_value_block && last->e_value_size) { -+ int offs = le16_to_cpu(last->e_value_offs); -+ if (offs < min_offs) -+ min_offs = offs; -+ } -+ last = next; -+ } -+ -+ /* Check whether we have enough space left. */ -+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32); -+ } else { -+ /* We will use a new extended attribute block. */ -+ free = sb->s_blocksize - -+ sizeof(struct ext3_xattr_header) - sizeof(__u32); -+ here = last = NULL; /* avoid gcc uninitialized warning. */ -+ } -+ -+ if (not_found) { -+ /* Request to remove a nonexistent attribute? */ -+ error = -ENOATTR; -+ if (flags & XATTR_REPLACE) -+ goto cleanup; -+ error = 0; -+ if (value == NULL) -+ goto cleanup; -+ else -+ free -= EXT3_XATTR_LEN(name_len); -+ } else { -+ /* Request to create an existing attribute? */ -+ error = -EEXIST; -+ if (flags & XATTR_CREATE) -+ goto cleanup; -+ if (!here->e_value_block && here->e_value_size) { -+ unsigned int size = le32_to_cpu(here->e_value_size); -+ -+ if (le16_to_cpu(here->e_value_offs) + size > -+ sb->s_blocksize || size > sb->s_blocksize) -+ goto bad_block; -+ free += EXT3_XATTR_SIZE(size); -+ } -+ } -+ free -= EXT3_XATTR_SIZE(value_len); -+ error = -ENOSPC; -+ if (free < 0) -+ goto cleanup; -+ -+ /* Here we know that we can set the new attribute. */ -+ -+ if (header) { -+ if (header->h_refcount == cpu_to_le32(1)) { -+ ea_bdebug(bh, "modifying in-place"); -+ ext3_xattr_cache_remove(bh); -+ error = ext3_journal_get_write_access(handle, bh); -+ if (error) -+ goto cleanup; -+ } else { -+ int offset; -+ -+ ea_bdebug(bh, "cloning"); -+ header = kmalloc(bh->b_size, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memcpy(header, HDR(bh), bh->b_size); -+ header->h_refcount = cpu_to_le32(1); -+ offset = (char *)header - bh->b_data; -+ here = ENTRY((char *)here + offset); -+ last = ENTRY((char *)last + offset); -+ } -+ } else { -+ /* Allocate a buffer where we construct the new block. */ -+ header = kmalloc(sb->s_blocksize, GFP_KERNEL); -+ error = -ENOMEM; -+ if (header == NULL) -+ goto cleanup; -+ memset(header, 0, sb->s_blocksize); -+ end = (char *)header + sb->s_blocksize; -+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC); -+ header->h_blocks = header->h_refcount = cpu_to_le32(1); -+ last = here = ENTRY(header+1); -+ } -+ -+ if (not_found) { -+ /* Insert the new name. */ -+ int size = EXT3_XATTR_LEN(name_len); -+ int rest = (char *)last - (char *)here; -+ memmove((char *)here + size, here, rest); -+ memset(here, 0, size); -+ here->e_name_index = name_index; -+ here->e_name_len = name_len; -+ memcpy(here->e_name, name, name_len); -+ } else { -+ /* Remove the old value. */ -+ if (!here->e_value_block && here->e_value_size) { -+ char *first_val = (char *)header + min_offs; -+ int offs = le16_to_cpu(here->e_value_offs); -+ char *val = (char *)header + offs; -+ size_t size = EXT3_XATTR_SIZE( -+ le32_to_cpu(here->e_value_size)); -+ memmove(first_val + size, first_val, val - first_val); -+ memset(first_val, 0, size); -+ here->e_value_offs = 0; -+ min_offs += size; -+ -+ /* Adjust all value offsets. */ -+ last = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(last)) { -+ int o = le16_to_cpu(last->e_value_offs); -+ if (!last->e_value_block && o < offs) -+ last->e_value_offs = -+ cpu_to_le16(o + size); -+ last = EXT3_XATTR_NEXT(last); -+ } -+ } -+ if (value == NULL) { -+ /* Remove this attribute. */ -+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) { -+ /* This block is now empty. */ -+ error = ext3_xattr_set2(handle, inode, bh,NULL); -+ goto cleanup; -+ } else { -+ /* Remove the old name. */ -+ int size = EXT3_XATTR_LEN(name_len); -+ last = ENTRY((char *)last - size); -+ memmove(here, (char*)here + size, -+ (char*)last - (char*)here); -+ memset(last, 0, size); -+ } -+ } -+ } -+ -+ if (value != NULL) { -+ /* Insert the new value. */ -+ here->e_value_size = cpu_to_le32(value_len); -+ if (value_len) { -+ size_t size = EXT3_XATTR_SIZE(value_len); -+ char *val = (char *)header + min_offs - size; -+ here->e_value_offs = -+ cpu_to_le16((char *)val - (char *)header); -+ memset(val + size - EXT3_XATTR_PAD, 0, -+ EXT3_XATTR_PAD); /* Clear the pad bytes. */ -+ memcpy(val, value, value_len); -+ } -+ } -+ ext3_xattr_rehash(header, here); -+ -+ error = ext3_xattr_set2(handle, inode, bh, header); -+ -+cleanup: -+ brelse(bh); -+ if (!(bh && header == HDR(bh))) -+ kfree(header); -+ up(&ext3_xattr_sem); -+ -+ return error; -+} -+ -+/* -+ * Second half of ext3_xattr_set(): Update the file system. -+ */ -+static int -+ext3_xattr_set2(handle_t *handle, struct inode *inode, -+ struct buffer_head *old_bh, struct ext3_xattr_header *header) -+{ -+ struct super_block *sb = inode->i_sb; -+ struct buffer_head *new_bh = NULL; -+ int error; -+ -+ if (header) { -+ new_bh = ext3_xattr_cache_find(inode, header); -+ if (new_bh) { -+ /* -+ * We found an identical block in the cache. -+ * The old block will be released after updating -+ * the inode. -+ */ -+ ea_bdebug(old_bh, "reusing block %ld", -+ new_bh->b_blocknr); -+ -+ error = -EDQUOT; -+ if (ext3_xattr_quota_alloc(inode, 1)) -+ goto cleanup; -+ -+ error = ext3_journal_get_write_access(handle, new_bh); -+ if (error) -+ goto cleanup; -+ HDR(new_bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1); -+ ea_bdebug(new_bh, "refcount now=%d", -+ le32_to_cpu(HDR(new_bh)->h_refcount)); -+ } else if (old_bh && header == HDR(old_bh)) { -+ /* Keep this block. */ -+ new_bh = old_bh; -+ (void)ext3_xattr_cache_insert(new_bh); -+ } else { -+ /* We need to allocate a new block */ -+ int force = EXT3_I(inode)->i_file_acl != 0; -+ int block = ext3_xattr_new_block(handle, inode, -+ &error, force); -+ if (error) -+ goto cleanup; -+ ea_idebug(inode, "creating block %d", block); -+ -+ new_bh = sb_getblk(sb, block); -+ if (!new_bh) { -+getblk_failed: ext3_xattr_free_block(handle, inode, block); -+ error = -EIO; -+ goto cleanup; -+ } -+ lock_buffer(new_bh); -+ error = ext3_journal_get_create_access(handle, new_bh); -+ if (error) { -+ unlock_buffer(new_bh); -+ goto getblk_failed; -+ } -+ memcpy(new_bh->b_data, header, new_bh->b_size); -+ mark_buffer_uptodate(new_bh, 1); -+ unlock_buffer(new_bh); -+ (void)ext3_xattr_cache_insert(new_bh); -+ -+ ext3_xattr_update_super_block(handle, sb); -+ } -+ error = ext3_journal_dirty_metadata(handle, new_bh); -+ if (error) -+ goto cleanup; -+ } -+ -+ /* Update the inode. */ -+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; -+ inode->i_ctime = CURRENT_TIME; -+ ext3_mark_inode_dirty(handle, inode); -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ -+ error = 0; -+ if (old_bh && old_bh != new_bh) { -+ /* -+ * If there was an old block, and we are not still using it, -+ * we now release the old block. -+ */ -+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount); -+ -+ error = ext3_journal_get_write_access(handle, old_bh); -+ if (error) -+ goto cleanup; -+ if (refcount == 1) { -+ /* Free the old block. */ -+ ea_bdebug(old_bh, "freeing"); -+ ext3_xattr_free_block(handle, inode, old_bh->b_blocknr); -+ -+ /* ext3_forget() calls bforget() for us, but we -+ let our caller release old_bh, so we need to -+ duplicate the handle before. */ -+ get_bh(old_bh); -+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr); -+ } else { -+ /* Decrement the refcount only. */ -+ refcount--; -+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount); -+ ext3_xattr_quota_free(inode); -+ ext3_journal_dirty_metadata(handle, old_bh); -+ ea_bdebug(old_bh, "refcount now=%d", refcount); -+ } -+ } -+ -+cleanup: -+ if (old_bh != new_bh) -+ brelse(new_bh); -+ -+ return error; -+} -+ -+/* -+ * ext3_xattr_delete_inode() -+ * -+ * Free extended attribute resources associated with this inode. This -+ * is called immediately before an inode is freed. -+ */ -+void -+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) -+{ -+ struct buffer_head *bh; -+ unsigned int block = EXT3_I(inode)->i_file_acl; -+ -+ if (!block) -+ return; -+ down(&ext3_xattr_sem); -+ -+ bh = sb_bread(inode->i_sb, block); -+ if (!bh) { -+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode", -+ "inode %ld: block %d read error", inode->i_ino, block); -+ goto cleanup; -+ } -+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count))); -+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || -+ HDR(bh)->h_blocks != cpu_to_le32(1)) { -+ ext3_error(inode->i_sb, "ext3_xattr_delete_inode", -+ "inode %ld: bad block %d", inode->i_ino, block); -+ goto cleanup; -+ } -+ ext3_journal_get_write_access(handle, bh); -+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) { -+ ext3_xattr_cache_remove(bh); -+ ext3_xattr_free_block(handle, inode, block); -+ ext3_forget(handle, 1, inode, bh, block); -+ bh = NULL; -+ } else { -+ HDR(bh)->h_refcount = cpu_to_le32( -+ le32_to_cpu(HDR(bh)->h_refcount) - 1); -+ ext3_journal_dirty_metadata(handle, bh); -+ if (IS_SYNC(inode)) -+ handle->h_sync = 1; -+ ext3_xattr_quota_free(inode); -+ } -+ EXT3_I(inode)->i_file_acl = 0; -+ -+cleanup: -+ brelse(bh); -+ up(&ext3_xattr_sem); -+} -+ -+/* -+ * ext3_xattr_put_super() -+ * -+ * This is called when a file system is unmounted. -+ */ -+void -+ext3_xattr_put_super(struct super_block *sb) -+{ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ mb_cache_shrink(ext3_xattr_cache, sb->s_dev); -+#endif -+} -+ -+#ifdef CONFIG_EXT3_FS_XATTR_SHARING -+ -+/* -+ * ext3_xattr_cache_insert() -+ * -+ * Create a new entry in the extended attribute cache, and insert -+ * it unless such an entry is already in the cache. -+ * -+ * Returns 0, or a negative error number on failure. -+ */ -+static int -+ext3_xattr_cache_insert(struct buffer_head *bh) -+{ -+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash); -+ struct mb_cache_entry *ce; -+ int error; -+ -+ ce = mb_cache_entry_alloc(ext3_xattr_cache); -+ if (!ce) -+ return -ENOMEM; -+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash); -+ if (error) { -+ mb_cache_entry_free(ce); -+ if (error == -EBUSY) { -+ ea_bdebug(bh, "already in cache (%d cache entries)", -+ atomic_read(&ext3_xattr_cache->c_entry_count)); -+ error = 0; -+ } -+ } else { -+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash, -+ atomic_read(&ext3_xattr_cache->c_entry_count)); -+ mb_cache_entry_release(ce); -+ } -+ return error; -+} -+ -+/* -+ * ext3_xattr_cmp() -+ * -+ * Compare two extended attribute blocks for equality. -+ * -+ * Returns 0 if the blocks are equal, 1 if they differ, and -+ * a negative error number on errors. -+ */ -+static int -+ext3_xattr_cmp(struct ext3_xattr_header *header1, -+ struct ext3_xattr_header *header2) -+{ -+ struct ext3_xattr_entry *entry1, *entry2; -+ -+ entry1 = ENTRY(header1+1); -+ entry2 = ENTRY(header2+1); -+ while (!IS_LAST_ENTRY(entry1)) { -+ if (IS_LAST_ENTRY(entry2)) -+ return 1; -+ if (entry1->e_hash != entry2->e_hash || -+ entry1->e_name_len != entry2->e_name_len || -+ entry1->e_value_size != entry2->e_value_size || -+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len)) -+ return 1; -+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0) -+ return -EIO; -+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs), -+ (char *)header2 + le16_to_cpu(entry2->e_value_offs), -+ le32_to_cpu(entry1->e_value_size))) -+ return 1; -+ -+ entry1 = EXT3_XATTR_NEXT(entry1); -+ entry2 = EXT3_XATTR_NEXT(entry2); -+ } -+ if (!IS_LAST_ENTRY(entry2)) -+ return 1; -+ return 0; -+} -+ -+/* -+ * ext3_xattr_cache_find() -+ * -+ * Find an identical extended attribute block. -+ * -+ * Returns a pointer to the block found, or NULL if such a block was -+ * not found or an error occurred. -+ */ -+static struct buffer_head * -+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header) -+{ -+ __u32 hash = le32_to_cpu(header->h_hash); -+ struct mb_cache_entry *ce; -+ -+ if (!header->h_hash) -+ return NULL; /* never share */ -+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); -+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash); -+ while (ce) { -+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block); -+ -+ if (!bh) { -+ ext3_error(inode->i_sb, "ext3_xattr_cache_find", -+ "inode %ld: block %ld read error", -+ inode->i_ino, ce->e_block); -+ } else if (le32_to_cpu(HDR(bh)->h_refcount) > -+ EXT3_XATTR_REFCOUNT_MAX) { -+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block, -+ le32_to_cpu(HDR(bh)->h_refcount), -+ EXT3_XATTR_REFCOUNT_MAX); -+ } else if (!ext3_xattr_cmp(header, HDR(bh))) { -+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count))); -+ mb_cache_entry_release(ce); -+ return bh; -+ } -+ brelse(bh); -+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash); -+ } -+ return NULL; -+} -+ -+/* -+ * ext3_xattr_cache_remove() -+ * -+ * Remove the cache entry of a block from the cache. Called when a -+ * block becomes invalid. -+ */ -+static void -+ext3_xattr_cache_remove(struct buffer_head *bh) -+{ -+ struct mb_cache_entry *ce; -+ -+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr); -+ if (ce) { -+ ea_bdebug(bh, "removing (%d cache entries remaining)", -+ atomic_read(&ext3_xattr_cache->c_entry_count)-1); -+ mb_cache_entry_free(ce); -+ } else -+ ea_bdebug(bh, "no cache entry"); -+} -+ -+#define NAME_HASH_SHIFT 5 -+#define VALUE_HASH_SHIFT 16 -+ -+/* -+ * ext3_xattr_hash_entry() -+ * -+ * Compute the hash of an extended attribute. -+ */ -+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header, -+ struct ext3_xattr_entry *entry) -+{ -+ __u32 hash = 0; -+ char *name = entry->e_name; -+ int n; -+ -+ for (n=0; n < entry->e_name_len; n++) { -+ hash = (hash << NAME_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ -+ *name++; -+ } -+ -+ if (entry->e_value_block == 0 && entry->e_value_size != 0) { -+ __u32 *value = (__u32 *)((char *)header + -+ le16_to_cpu(entry->e_value_offs)); -+ for (n = (le32_to_cpu(entry->e_value_size) + -+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) { -+ hash = (hash << VALUE_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ -+ le32_to_cpu(*value++); -+ } -+ } -+ entry->e_hash = cpu_to_le32(hash); -+} -+ -+#undef NAME_HASH_SHIFT -+#undef VALUE_HASH_SHIFT -+ -+#define BLOCK_HASH_SHIFT 16 -+ -+/* -+ * ext3_xattr_rehash() -+ * -+ * Re-compute the extended attribute hash value after an entry has changed. -+ */ -+static void ext3_xattr_rehash(struct ext3_xattr_header *header, -+ struct ext3_xattr_entry *entry) -+{ -+ struct ext3_xattr_entry *here; -+ __u32 hash = 0; -+ -+ ext3_xattr_hash_entry(header, entry); -+ here = ENTRY(header+1); -+ while (!IS_LAST_ENTRY(here)) { -+ if (!here->e_hash) { -+ /* Block is not shared if an entry's hash value == 0 */ -+ hash = 0; -+ break; -+ } -+ hash = (hash << BLOCK_HASH_SHIFT) ^ -+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ -+ le32_to_cpu(here->e_hash); -+ here = EXT3_XATTR_NEXT(here); -+ } -+ header->h_hash = cpu_to_le32(hash); -+} -+ -+#undef BLOCK_HASH_SHIFT -+ -+int __init -+init_ext3_xattr(void) -+{ -+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, -+ sizeof(struct mb_cache_entry) + -+ sizeof(struct mb_cache_entry_index), 1, 61); -+ if (!ext3_xattr_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void -+exit_ext3_xattr(void) -+{ -+ if (ext3_xattr_cache) -+ mb_cache_destroy(ext3_xattr_cache); -+ ext3_xattr_cache = NULL; -+} -+ -+#else /* CONFIG_EXT3_FS_XATTR_SHARING */ -+ -+int __init -+init_ext3_xattr(void) -+{ -+ return 0; -+} -+ -+void -+exit_ext3_xattr(void) -+{ -+} -+ -+#endif /* CONFIG_EXT3_FS_XATTR_SHARING */ -Index: linux-2.4.29/fs/ext3/xattr_user.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/xattr_user.c 2005-05-03 17:59:40.234146648 +0300 -+++ linux-2.4.29/fs/ext3/xattr_user.c 2005-05-03 17:59:40.429117008 +0300 -@@ -0,0 +1,111 @@ -+/* -+ * linux/fs/ext3/xattr_user.c -+ * Handler for extended user attributes. -+ * -+ * Copyright (C) 2001 by Andreas Gruenbacher, -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+# include -+#endif -+ -+#define XATTR_USER_PREFIX "user." -+ -+static size_t -+ext3_xattr_user_list(char *list, struct inode *inode, -+ const char *name, int name_len) -+{ -+ const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; -+ -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return 0; -+ -+ if (list) { -+ memcpy(list, XATTR_USER_PREFIX, prefix_len); -+ memcpy(list+prefix_len, name, name_len); -+ list[prefix_len + name_len] = '\0'; -+ } -+ return prefix_len + name_len + 1; -+} -+ -+static int -+ext3_xattr_user_get(struct inode *inode, const char *name, -+ void *buffer, size_t size) -+{ -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+ error = ext3_permission_locked(inode, MAY_READ); -+#else -+ error = permission(inode, MAY_READ); -+#endif -+ if (error) -+ return error; -+ -+ return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, -+ buffer, size); -+} -+ -+static int -+ext3_xattr_user_set(struct inode *inode, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ handle_t *handle; -+ int error; -+ -+ if (strcmp(name, "") == 0) -+ return -EINVAL; -+ if (!test_opt(inode->i_sb, XATTR_USER)) -+ return -ENOTSUP; -+ if ( !S_ISREG(inode->i_mode) && -+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) -+ return -EPERM; -+#ifdef CONFIG_EXT3_FS_POSIX_ACL -+ error = ext3_permission_locked(inode, MAY_WRITE); -+#else -+ error = permission(inode, MAY_WRITE); -+#endif -+ if (error) -+ return error; -+ -+ handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ error = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_USER, name, -+ value, size, flags); -+ ext3_journal_stop(handle, inode); -+ -+ return error; -+} -+ -+struct ext3_xattr_handler ext3_xattr_user_handler = { -+ prefix: XATTR_USER_PREFIX, -+ list: ext3_xattr_user_list, -+ get: ext3_xattr_user_get, -+ set: ext3_xattr_user_set, -+}; -+ -+int __init -+init_ext3_xattr_user(void) -+{ -+ return ext3_xattr_register(EXT3_XATTR_INDEX_USER, -+ &ext3_xattr_user_handler); -+} -+ -+void -+exit_ext3_xattr_user(void) -+{ -+ ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, -+ &ext3_xattr_user_handler); -+} -Index: linux-2.4.29/fs/ext3/ext3-exports.c -=================================================================== ---- linux-2.4.29.orig/fs/ext3/ext3-exports.c 2005-05-03 17:59:40.234146648 +0300 -+++ linux-2.4.29/fs/ext3/ext3-exports.c 2005-05-03 18:00:08.195895816 +0300 -@@ -0,0 +1,13 @@ -+#include -+#include -+#include -+#include -+#include -+ -+EXPORT_SYMBOL(ext3_force_commit); -+EXPORT_SYMBOL(ext3_bread); -+EXPORT_SYMBOL(ext3_xattr_register); -+EXPORT_SYMBOL(ext3_xattr_unregister); -+EXPORT_SYMBOL(ext3_xattr_get); -+EXPORT_SYMBOL(ext3_xattr_list); -+EXPORT_SYMBOL(ext3_xattr_set); -Index: linux-2.4.29/fs/jfs/jfs_xattr.h -=================================================================== ---- linux-2.4.29.orig/fs/jfs/jfs_xattr.h 2005-04-07 18:53:29.000000000 +0300 -+++ linux-2.4.29/fs/jfs/jfs_xattr.h 2005-05-03 17:59:40.431116704 +0300 -@@ -52,8 +52,10 @@ - #define END_EALIST(ealist) \ - ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) - --extern int __jfs_setxattr(struct inode *, const char *, void *, size_t, int); --extern int jfs_setxattr(struct dentry *, const char *, void *, size_t, int); -+extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, -+ int); -+extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, -+ int); - extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); - extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t); - extern ssize_t jfs_listxattr(struct dentry *, char *, size_t); -Index: linux-2.4.29/fs/jfs/xattr.c -=================================================================== ---- linux-2.4.29.orig/fs/jfs/xattr.c 2005-04-07 18:52:32.000000000 +0300 -+++ linux-2.4.29/fs/jfs/xattr.c 2005-05-03 17:59:40.433116400 +0300 -@@ -649,7 +649,7 @@ - } - - static int can_set_xattr(struct inode *inode, const char *name, -- void *value, size_t value_len) -+ const void *value, size_t value_len) - { - if (IS_RDONLY(inode)) - return -EROFS; -@@ -668,7 +668,7 @@ - return permission(inode, MAY_WRITE); - } - --int __jfs_setxattr(struct inode *inode, const char *name, void *value, -+int __jfs_setxattr(struct inode *inode, const char *name, const void *value, - size_t value_len, int flags) - { - struct jfs_ea_list *ealist; -@@ -807,7 +807,7 @@ - return rc; - } - --int jfs_setxattr(struct dentry *dentry, const char *name, void *value, -+int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t value_len, int flags) - { - if (value == NULL) { /* empty EA, do not remove */ -Index: linux-2.4.29/fs/mbcache.c -=================================================================== ---- linux-2.4.29.orig/fs/mbcache.c 2005-05-03 17:59:40.235146496 +0300 -+++ linux-2.4.29/fs/mbcache.c 2005-05-03 17:59:40.436115944 +0300 -@@ -0,0 +1,648 @@ -+/* -+ * linux/fs/mbcache.c -+ * (C) 2001-2002 Andreas Gruenbacher, -+ */ -+ -+/* -+ * Filesystem Meta Information Block Cache (mbcache) -+ * -+ * The mbcache caches blocks of block devices that need to be located -+ * by their device/block number, as well as by other criteria (such -+ * as the block's contents). -+ * -+ * There can only be one cache entry in a cache per device and block number. -+ * Additional indexes need not be unique in this sense. The number of -+ * additional indexes (=other criteria) can be hardwired at compile time -+ * or specified at cache create time. -+ * -+ * Each cache entry is of fixed size. An entry may be `valid' or `invalid' -+ * in the cache. A valid entry is in the main hash tables of the cache, -+ * and may also be in the lru list. An invalid entry is not in any hashes -+ * or lists. -+ * -+ * A valid cache entry is only in the lru list if no handles refer to it. -+ * Invalid cache entries will be freed when the last handle to the cache -+ * entry is released. Entries that cannot be freed immediately are put -+ * back on the lru list. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#ifdef MB_CACHE_DEBUG -+# define mb_debug(f...) do { \ -+ printk(KERN_DEBUG f); \ -+ printk("\n"); \ -+ } while (0) -+#define mb_assert(c) do { if (!(c)) \ -+ printk(KERN_ERR "assertion " #c " failed\n"); \ -+ } while(0) -+#else -+# define mb_debug(f...) do { } while(0) -+# define mb_assert(c) do { } while(0) -+#endif -+#define mb_error(f...) do { \ -+ printk(KERN_ERR f); \ -+ printk("\n"); \ -+ } while(0) -+ -+MODULE_AUTHOR("Andreas Gruenbacher "); -+MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -+MODULE_LICENSE("GPL"); -+#endif -+ -+EXPORT_SYMBOL(mb_cache_create); -+EXPORT_SYMBOL(mb_cache_shrink); -+EXPORT_SYMBOL(mb_cache_destroy); -+EXPORT_SYMBOL(mb_cache_entry_alloc); -+EXPORT_SYMBOL(mb_cache_entry_insert); -+EXPORT_SYMBOL(mb_cache_entry_release); -+EXPORT_SYMBOL(mb_cache_entry_takeout); -+EXPORT_SYMBOL(mb_cache_entry_free); -+EXPORT_SYMBOL(mb_cache_entry_dup); -+EXPORT_SYMBOL(mb_cache_entry_get); -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+EXPORT_SYMBOL(mb_cache_entry_find_first); -+EXPORT_SYMBOL(mb_cache_entry_find_next); -+#endif -+ -+ -+/* -+ * Global data: list of all mbcache's, lru list, and a spinlock for -+ * accessing cache data structures on SMP machines. The lru list is -+ * global across all mbcaches. -+ */ -+ -+static LIST_HEAD(mb_cache_list); -+static LIST_HEAD(mb_cache_lru_list); -+static spinlock_t mb_cache_spinlock = SPIN_LOCK_UNLOCKED; -+ -+static inline int -+mb_cache_indexes(struct mb_cache *cache) -+{ -+#ifdef MB_CACHE_INDEXES_COUNT -+ return MB_CACHE_INDEXES_COUNT; -+#else -+ return cache->c_indexes_count; -+#endif -+} -+ -+/* -+ * What the mbcache registers as to get shrunk dynamically. -+ */ -+ -+static void -+mb_cache_memory_pressure(int priority, unsigned int gfp_mask); -+ -+static struct cache_definition mb_cache_definition = { -+ "mb_cache", -+ mb_cache_memory_pressure -+}; -+ -+ -+static inline int -+__mb_cache_entry_is_hashed(struct mb_cache_entry *ce) -+{ -+ return !list_empty(&ce->e_block_list); -+} -+ -+ -+static inline void -+__mb_cache_entry_unhash(struct mb_cache_entry *ce) -+{ -+ int n; -+ -+ if (__mb_cache_entry_is_hashed(ce)) { -+ list_del_init(&ce->e_block_list); -+ for (n=0; ne_cache); n++) -+ list_del(&ce->e_indexes[n].o_list); -+ } -+} -+ -+ -+static inline void -+__mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask) -+{ -+ struct mb_cache *cache = ce->e_cache; -+ -+ mb_assert(atomic_read(&ce->e_used) == 0); -+ if (cache->c_op.free && cache->c_op.free(ce, gfp_mask)) { -+ /* free failed -- put back on the lru list -+ for freeing later. */ -+ spin_lock(&mb_cache_spinlock); -+ list_add(&ce->e_lru_list, &mb_cache_lru_list); -+ spin_unlock(&mb_cache_spinlock); -+ } else { -+ kmem_cache_free(cache->c_entry_cache, ce); -+ atomic_dec(&cache->c_entry_count); -+ } -+} -+ -+ -+static inline void -+__mb_cache_entry_release_unlock(struct mb_cache_entry *ce) -+{ -+ if (atomic_dec_and_test(&ce->e_used)) { -+ if (__mb_cache_entry_is_hashed(ce)) -+ list_add_tail(&ce->e_lru_list, &mb_cache_lru_list); -+ else { -+ spin_unlock(&mb_cache_spinlock); -+ __mb_cache_entry_forget(ce, GFP_KERNEL); -+ return; -+ } -+ } -+ spin_unlock(&mb_cache_spinlock); -+} -+ -+ -+/* -+ * mb_cache_memory_pressure() memory pressure callback -+ * -+ * This function is called by the kernel memory management when memory -+ * gets low. -+ * -+ * @priority: Amount by which to shrink the cache (0 = highes priority) -+ * @gfp_mask: (ignored) -+ */ -+static void -+mb_cache_memory_pressure(int priority, unsigned int gfp_mask) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ int count = 0; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &mb_cache_list) { -+ struct mb_cache *cache = -+ list_entry(l, struct mb_cache, c_cache_list); -+ mb_debug("cache %s (%d)", cache->c_name, -+ atomic_read(&cache->c_entry_count)); -+ count += atomic_read(&cache->c_entry_count); -+ } -+ mb_debug("trying to free %d of %d entries", -+ count / (priority ? priority : 1), count); -+ if (priority) -+ count /= priority; -+ while (count-- && !list_empty(&mb_cache_lru_list)) { -+ struct mb_cache_entry *ce = -+ list_entry(mb_cache_lru_list.next, -+ struct mb_cache_entry, e_lru_list); -+ list_del(&ce->e_lru_list); -+ __mb_cache_entry_unhash(ce); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ } -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), gfp_mask); -+ } -+} -+ -+ -+/* -+ * mb_cache_create() create a new cache -+ * -+ * All entries in one cache are equal size. Cache entries may be from -+ * multiple devices. If this is the first mbcache created, registers -+ * the cache with kernel memory management. Returns NULL if no more -+ * memory was available. -+ * -+ * @name: name of the cache (informal) -+ * @cache_op: contains the callback called when freeing a cache entry -+ * @entry_size: The size of a cache entry, including -+ * struct mb_cache_entry -+ * @indexes_count: number of additional indexes in the cache. Must equal -+ * MB_CACHE_INDEXES_COUNT if the number of indexes is -+ * hardwired. -+ * @bucket_count: number of hash buckets -+ */ -+struct mb_cache * -+mb_cache_create(const char *name, struct mb_cache_op *cache_op, -+ size_t entry_size, int indexes_count, int bucket_count) -+{ -+ int m=0, n; -+ struct mb_cache *cache = NULL; -+ -+ if(entry_size < sizeof(struct mb_cache_entry) + -+ indexes_count * sizeof(struct mb_cache_entry_index)) -+ return NULL; -+ -+ MOD_INC_USE_COUNT; -+ cache = kmalloc(sizeof(struct mb_cache) + -+ indexes_count * sizeof(struct list_head), GFP_KERNEL); -+ if (!cache) -+ goto fail; -+ cache->c_name = name; -+ cache->c_op.free = NULL; -+ if (cache_op) -+ cache->c_op.free = cache_op->free; -+ atomic_set(&cache->c_entry_count, 0); -+ cache->c_bucket_count = bucket_count; -+#ifdef MB_CACHE_INDEXES_COUNT -+ mb_assert(indexes_count == MB_CACHE_INDEXES_COUNT); -+#else -+ cache->c_indexes_count = indexes_count; -+#endif -+ cache->c_block_hash = kmalloc(bucket_count * sizeof(struct list_head), -+ GFP_KERNEL); -+ if (!cache->c_block_hash) -+ goto fail; -+ for (n=0; nc_block_hash[n]); -+ for (m=0; mc_indexes_hash[m] = kmalloc(bucket_count * -+ sizeof(struct list_head), -+ GFP_KERNEL); -+ if (!cache->c_indexes_hash[m]) -+ goto fail; -+ for (n=0; nc_indexes_hash[m][n]); -+ } -+ cache->c_entry_cache = kmem_cache_create(name, entry_size, 0, -+ 0 /*SLAB_POISON | SLAB_RED_ZONE*/, NULL, NULL); -+ if (!cache->c_entry_cache) -+ goto fail; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_add(&cache->c_cache_list, &mb_cache_list); -+ spin_unlock(&mb_cache_spinlock); -+ return cache; -+ -+fail: -+ if (cache) { -+ while (--m >= 0) -+ kfree(cache->c_indexes_hash[m]); -+ if (cache->c_block_hash) -+ kfree(cache->c_block_hash); -+ kfree(cache); -+ } -+ MOD_DEC_USE_COUNT; -+ return NULL; -+} -+ -+ -+/* -+ * mb_cache_shrink() -+ * -+ * Removes all cache entires of a device from the cache. All cache entries -+ * currently in use cannot be freed, and thus remain in the cache. -+ * -+ * @cache: which cache to shrink -+ * @dev: which device's cache entries to shrink -+ */ -+void -+mb_cache_shrink(struct mb_cache *cache, kdev_t dev) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_lru_list); -+ if (ce->e_dev == dev) { -+ list_del(&ce->e_lru_list); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ __mb_cache_entry_unhash(ce); -+ } -+ } -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), GFP_KERNEL); -+ } -+} -+ -+ -+/* -+ * mb_cache_destroy() -+ * -+ * Shrinks the cache to its minimum possible size (hopefully 0 entries), -+ * and then destroys it. If this was the last mbcache, un-registers the -+ * mbcache from kernel memory management. -+ */ -+void -+mb_cache_destroy(struct mb_cache *cache) -+{ -+ LIST_HEAD(free_list); -+ struct list_head *l, *ltmp; -+ int n; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &mb_cache_lru_list) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_lru_list); -+ if (ce->e_cache == cache) { -+ list_del(&ce->e_lru_list); -+ list_add_tail(&ce->e_lru_list, &free_list); -+ __mb_cache_entry_unhash(ce); -+ } -+ } -+ list_del(&cache->c_cache_list); -+ spin_unlock(&mb_cache_spinlock); -+ list_for_each_safe(l, ltmp, &free_list) { -+ __mb_cache_entry_forget(list_entry(l, struct mb_cache_entry, -+ e_lru_list), GFP_KERNEL); -+ } -+ -+ if (atomic_read(&cache->c_entry_count) > 0) { -+ mb_error("cache %s: %d orphaned entries", -+ cache->c_name, -+ atomic_read(&cache->c_entry_count)); -+ } -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) -+ /* We don't have kmem_cache_destroy() in 2.2.x */ -+ kmem_cache_shrink(cache->c_entry_cache); -+#else -+ kmem_cache_destroy(cache->c_entry_cache); -+#endif -+ for (n=0; n < mb_cache_indexes(cache); n++) -+ kfree(cache->c_indexes_hash[n]); -+ kfree(cache->c_block_hash); -+ kfree(cache); -+ -+ MOD_DEC_USE_COUNT; -+} -+ -+ -+/* -+ * mb_cache_entry_alloc() -+ * -+ * Allocates a new cache entry. The new entry will not be valid initially, -+ * and thus cannot be looked up yet. It should be filled with data, and -+ * then inserted into the cache using mb_cache_entry_insert(). Returns NULL -+ * if no more memory was available. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_alloc(struct mb_cache *cache) -+{ -+ struct mb_cache_entry *ce; -+ -+ atomic_inc(&cache->c_entry_count); -+ ce = kmem_cache_alloc(cache->c_entry_cache, GFP_KERNEL); -+ if (ce) { -+ INIT_LIST_HEAD(&ce->e_lru_list); -+ INIT_LIST_HEAD(&ce->e_block_list); -+ ce->e_cache = cache; -+ atomic_set(&ce->e_used, 1); -+ } -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_insert() -+ * -+ * Inserts an entry that was allocated using mb_cache_entry_alloc() into -+ * the cache. After this, the cache entry can be looked up, but is not yet -+ * in the lru list as the caller still holds a handle to it. Returns 0 on -+ * success, or -EBUSY if a cache entry for that device + inode exists -+ * already (this may happen after a failed lookup, if another process has -+ * inserted the same cache entry in the meantime). -+ * -+ * @dev: device the cache entry belongs to -+ * @block: block number -+ * @keys: array of additional keys. There must be indexes_count entries -+ * in the array (as specified when creating the cache). -+ */ -+int -+mb_cache_entry_insert(struct mb_cache_entry *ce, kdev_t dev, -+ unsigned long block, unsigned int keys[]) -+{ -+ struct mb_cache *cache = ce->e_cache; -+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count; -+ struct list_head *l; -+ int error = -EBUSY, n; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &cache->c_block_hash[bucket]) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, e_block_list); -+ if (ce->e_dev == dev && ce->e_block == block) -+ goto out; -+ } -+ __mb_cache_entry_unhash(ce); -+ ce->e_dev = dev; -+ ce->e_block = block; -+ list_add(&ce->e_block_list, &cache->c_block_hash[bucket]); -+ for (n=0; ne_indexes[n].o_key = keys[n]; -+ bucket = keys[n] % cache->c_bucket_count; -+ list_add(&ce->e_indexes[n].o_list, -+ &cache->c_indexes_hash[n][bucket]); -+ } -+out: -+ spin_unlock(&mb_cache_spinlock); -+ return error; -+} -+ -+ -+/* -+ * mb_cache_entry_release() -+ * -+ * Release a handle to a cache entry. When the last handle to a cache entry -+ * is released it is either freed (if it is invalid) or otherwise inserted -+ * in to the lru list. -+ */ -+void -+mb_cache_entry_release(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ __mb_cache_entry_release_unlock(ce); -+} -+ -+ -+/* -+ * mb_cache_entry_takeout() -+ * -+ * Take a cache entry out of the cache, making it invalid. The entry can later -+ * be re-inserted using mb_cache_entry_insert(), or released using -+ * mb_cache_entry_release(). -+ */ -+void -+mb_cache_entry_takeout(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ mb_assert(list_empty(&ce->e_lru_list)); -+ __mb_cache_entry_unhash(ce); -+ spin_unlock(&mb_cache_spinlock); -+} -+ -+ -+/* -+ * mb_cache_entry_free() -+ * -+ * This is equivalent to the sequence mb_cache_entry_takeout() -- -+ * mb_cache_entry_release(). -+ */ -+void -+mb_cache_entry_free(struct mb_cache_entry *ce) -+{ -+ spin_lock(&mb_cache_spinlock); -+ mb_assert(list_empty(&ce->e_lru_list)); -+ __mb_cache_entry_unhash(ce); -+ __mb_cache_entry_release_unlock(ce); -+} -+ -+ -+/* -+ * mb_cache_entry_dup() -+ * -+ * Duplicate a handle to a cache entry (does not duplicate the cache entry -+ * itself). After the call, both the old and the new handle must be released. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_dup(struct mb_cache_entry *ce) -+{ -+ atomic_inc(&ce->e_used); -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_get() -+ * -+ * Get a cache entry by device / block number. (There can only be one entry -+ * in the cache per device and block.) Returns NULL if no such cache entry -+ * exists. -+ */ -+struct mb_cache_entry * -+mb_cache_entry_get(struct mb_cache *cache, kdev_t dev, unsigned long block) -+{ -+ unsigned int bucket = (HASHDEV(dev) + block) % cache->c_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ spin_lock(&mb_cache_spinlock); -+ list_for_each(l, &cache->c_block_hash[bucket]) { -+ ce = list_entry(l, struct mb_cache_entry, e_block_list); -+ if (ce->e_dev == dev && ce->e_block == block) { -+ if (!list_empty(&ce->e_lru_list)) -+ list_del_init(&ce->e_lru_list); -+ atomic_inc(&ce->e_used); -+ goto cleanup; -+ } -+ } -+ ce = NULL; -+ -+cleanup: -+ spin_unlock(&mb_cache_spinlock); -+ return ce; -+} -+ -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+ -+static struct mb_cache_entry * -+__mb_cache_entry_find(struct list_head *l, struct list_head *head, -+ int index, kdev_t dev, unsigned int key) -+{ -+ while (l != head) { -+ struct mb_cache_entry *ce = -+ list_entry(l, struct mb_cache_entry, -+ e_indexes[index].o_list); -+ if (ce->e_dev == dev && ce->e_indexes[index].o_key == key) { -+ if (!list_empty(&ce->e_lru_list)) -+ list_del_init(&ce->e_lru_list); -+ atomic_inc(&ce->e_used); -+ return ce; -+ } -+ l = l->next; -+ } -+ return NULL; -+} -+ -+ -+/* -+ * mb_cache_entry_find_first() -+ * -+ * Find the first cache entry on a given device with a certain key in -+ * an additional index. Additonal matches can be found with -+ * mb_cache_entry_find_next(). Returns NULL if no match was found. -+ * -+ * @cache: the cache to search -+ * @index: the number of the additonal index to search (0<=indexc_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ mb_assert(index < mb_cache_indexes(cache)); -+ spin_lock(&mb_cache_spinlock); -+ l = cache->c_indexes_hash[index][bucket].next; -+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket], -+ index, dev, key); -+ spin_unlock(&mb_cache_spinlock); -+ return ce; -+} -+ -+ -+/* -+ * mb_cache_entry_find_next() -+ * -+ * Find the next cache entry on a given device with a certain key in an -+ * additional index. Returns NULL if no match could be found. The previous -+ * entry is atomatically released, so that mb_cache_entry_find_next() can -+ * be called like this: -+ * -+ * entry = mb_cache_entry_find_first(); -+ * while (entry) { -+ * ... -+ * entry = mb_cache_entry_find_next(entry, ...); -+ * } -+ * -+ * @prev: The previous match -+ * @index: the number of the additonal index to search (0<=indexe_cache; -+ unsigned int bucket = key % cache->c_bucket_count; -+ struct list_head *l; -+ struct mb_cache_entry *ce; -+ -+ mb_assert(index < mb_cache_indexes(cache)); -+ spin_lock(&mb_cache_spinlock); -+ l = prev->e_indexes[index].o_list.next; -+ ce = __mb_cache_entry_find(l, &cache->c_indexes_hash[index][bucket], -+ index, dev, key); -+ __mb_cache_entry_release_unlock(prev); -+ return ce; -+} -+ -+#endif /* !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) */ -+ -+static int __init init_mbcache(void) -+{ -+ register_cache(&mb_cache_definition); -+ return 0; -+} -+ -+static void __exit exit_mbcache(void) -+{ -+ unregister_cache(&mb_cache_definition); -+} -+ -+module_init(init_mbcache) -+module_exit(exit_mbcache) -+ -Index: linux-2.4.29/include/asm-arm/unistd.h -=================================================================== ---- linux-2.4.29.orig/include/asm-arm/unistd.h 2005-04-07 18:55:01.000000000 +0300 -+++ linux-2.4.29/include/asm-arm/unistd.h 2005-05-03 17:59:40.438115640 +0300 -@@ -250,7 +250,6 @@ - #define __NR_security (__NR_SYSCALL_BASE+223) - #define __NR_gettid (__NR_SYSCALL_BASE+224) - #define __NR_readahead (__NR_SYSCALL_BASE+225) --#if 0 /* allocated in 2.5 */ - #define __NR_setxattr (__NR_SYSCALL_BASE+226) - #define __NR_lsetxattr (__NR_SYSCALL_BASE+227) - #define __NR_fsetxattr (__NR_SYSCALL_BASE+228) -@@ -263,7 +262,6 @@ - #define __NR_removexattr (__NR_SYSCALL_BASE+235) - #define __NR_lremovexattr (__NR_SYSCALL_BASE+236) - #define __NR_fremovexattr (__NR_SYSCALL_BASE+237) --#endif - #define __NR_tkill (__NR_SYSCALL_BASE+238) - #if 0 /* allocated in 2.5 */ - #define __NR_sendfile64 (__NR_SYSCALL_BASE+239) -Index: linux-2.4.29/include/asm-ppc64/unistd.h -=================================================================== ---- linux-2.4.29.orig/include/asm-ppc64/unistd.h 2005-04-07 18:52:47.000000000 +0300 -+++ linux-2.4.29/include/asm-ppc64/unistd.h 2005-05-03 17:59:40.439115488 +0300 -@@ -218,6 +218,7 @@ - #define __NR_mincore 206 - #define __NR_gettid 207 - #define __NR_tkill 208 -+#endif - #define __NR_setxattr 209 - #define __NR_lsetxattr 210 - #define __NR_fsetxattr 211 -@@ -230,6 +231,7 @@ - #define __NR_removexattr 218 - #define __NR_lremovexattr 219 - #define __NR_fremovexattr 220 -+#if 0 /* Reserved syscalls */ - #define __NR_futex 221 - #define __NR_sched_setaffinity 222 - #define __NR_sched_getaffinity 223 -Index: linux-2.4.29/include/asm-s390/unistd.h -=================================================================== ---- linux-2.4.29.orig/include/asm-s390/unistd.h 2005-04-07 18:55:23.000000000 +0300 -+++ linux-2.4.29/include/asm-s390/unistd.h 2005-05-03 17:59:40.440115336 +0300 -@@ -213,9 +213,18 @@ - #define __NR_getdents64 220 - #define __NR_fcntl64 221 - #define __NR_readahead 222 --/* -- * Numbers 224-235 are reserved for posix acl -- */ -+#define __NR_setxattr 224 -+#define __NR_lsetxattr 225 -+#define __NR_fsetxattr 226 -+#define __NR_getxattr 227 -+#define __NR_lgetxattr 228 -+#define __NR_fgetxattr 229 -+#define __NR_listxattr 230 -+#define __NR_llistxattr 231 -+#define __NR_flistxattr 232 -+#define __NR_removexattr 233 -+#define __NR_lremovexattr 234 -+#define __NR_fremovexattr 235 - #define __NR_gettid 236 - #define __NR_tkill 237 - -Index: linux-2.4.29/include/asm-s390x/unistd.h -=================================================================== ---- linux-2.4.29.orig/include/asm-s390x/unistd.h 2005-04-07 18:54:22.000000000 +0300 -+++ linux-2.4.29/include/asm-s390x/unistd.h 2005-05-03 17:59:40.441115184 +0300 -@@ -181,9 +181,18 @@ - #define __NR_mincore 218 - #define __NR_madvise 219 - #define __NR_readahead 222 --/* -- * Numbers 224-235 are reserved for posix acl -- */ -+#define __NR_setxattr 224 -+#define __NR_lsetxattr 225 -+#define __NR_fsetxattr 226 -+#define __NR_getxattr 227 -+#define __NR_lgetxattr 228 -+#define __NR_fgetxattr 229 -+#define __NR_listxattr 230 -+#define __NR_llistxattr 231 -+#define __NR_flistxattr 232 -+#define __NR_removexattr 233 -+#define __NR_lremovexattr 234 -+#define __NR_fremovexattr 235 - #define __NR_gettid 236 - #define __NR_tkill 237 - -Index: linux-2.4.29/include/linux/cache_def.h -=================================================================== ---- linux-2.4.29.orig/include/linux/cache_def.h 2005-05-03 17:59:40.235146496 +0300 -+++ linux-2.4.29/include/linux/cache_def.h 2005-05-03 17:59:40.442115032 +0300 -@@ -0,0 +1,15 @@ -+/* -+ * linux/cache_def.h -+ * Handling of caches defined in drivers, filesystems, ... -+ * -+ * Copyright (C) 2002 by Andreas Gruenbacher, -+ */ -+ -+struct cache_definition { -+ const char *name; -+ void (*shrink)(int, unsigned int); -+ struct list_head link; -+}; -+ -+extern void register_cache(struct cache_definition *); -+extern void unregister_cache(struct cache_definition *); -Index: linux-2.4.29/include/linux/errno.h -=================================================================== ---- linux-2.4.29.orig/include/linux/errno.h 2005-04-07 18:54:43.000000000 +0300 -+++ linux-2.4.29/include/linux/errno.h 2005-05-03 17:59:40.443114880 +0300 -@@ -23,4 +23,8 @@ - - #endif - -+/* Defined for extended attributes */ -+#define ENOATTR ENODATA /* No such attribute */ -+#define ENOTSUP EOPNOTSUPP /* Operation not supported */ -+ - #endif -Index: linux-2.4.29/include/linux/ext2_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext2_fs.h 2005-04-07 18:52:37.000000000 +0300 -+++ linux-2.4.29/include/linux/ext2_fs.h 2005-05-03 17:59:40.445114576 +0300 -@@ -57,8 +57,6 @@ - */ - #define EXT2_BAD_INO 1 /* Bad blocks inode */ - #define EXT2_ROOT_INO 2 /* Root inode */ --#define EXT2_ACL_IDX_INO 3 /* ACL inode */ --#define EXT2_ACL_DATA_INO 4 /* ACL inode */ - #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ - -@@ -86,7 +84,6 @@ - #else - # define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry)) - #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -121,28 +118,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext2_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext2_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext2_group_desc -@@ -314,6 +289,7 @@ - #define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ - #define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ - #define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ -+#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - #define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt - #define set_opt(o, opt) o |= EXT2_MOUNT_##opt -@@ -410,6 +386,7 @@ - - #ifdef __KERNEL__ - #define EXT2_SB(sb) (&((sb)->u.ext2_sb)) -+#define EXT2_I(inode) (&((inode)->u.ext2_i)) - #else - /* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test -@@ -480,7 +457,7 @@ - #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 - #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - --#define EXT2_FEATURE_COMPAT_SUPP 0 -+#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ - EXT2_FEATURE_INCOMPAT_META_BG) - #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ -@@ -650,8 +627,10 @@ - - /* namei.c */ - extern struct inode_operations ext2_dir_inode_operations; -+extern struct inode_operations ext2_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext2_symlink_inode_operations; - extern struct inode_operations ext2_fast_symlink_inode_operations; - - #endif /* __KERNEL__ */ -Index: linux-2.4.29/include/linux/ext2_xattr.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext2_xattr.h 2005-05-03 17:59:40.236146344 +0300 -+++ linux-2.4.29/include/linux/ext2_xattr.h 2005-05-03 17:59:40.446114424 +0300 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext2_xattr.h -+ -+ On-disk format of extended attributes for the ext2 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT2_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT2_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT2_XATTR_INDEX_MAX 10 -+#define EXT2_XATTR_INDEX_USER 1 -+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext2_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext2_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT2_XATTR_PAD_BITS 2 -+#define EXT2_XATTR_PAD (1<e_name_len)) ) -+#define EXT2_XATTR_SIZE(size) \ -+ (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT2_FS_XATTR -+ -+struct ext2_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext2_xattr_register(int, struct ext2_xattr_handler *); -+extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *); -+ -+extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t); -+extern int ext2_removexattr(struct dentry *, const char *); -+ -+extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext2_xattr_list(struct inode *, char *, size_t); -+extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext2_xattr_delete_inode(struct inode *); -+extern void ext2_xattr_put_super(struct super_block *); -+ -+extern int init_ext2_xattr(void) __init; -+extern void exit_ext2_xattr(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR */ -+# define ext2_setxattr NULL -+# define ext2_getxattr NULL -+# define ext2_listxattr NULL -+# define ext2_removexattr NULL -+ -+static inline int -+ext2_xattr_get(struct inode *inode, int name_index, -+ const char *name, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_list(struct inode *inode, char *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext2_xattr_set(struct inode *inode, int name_index, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext2_xattr_delete_inode(struct inode *inode) -+{ -+} -+ -+static inline void -+ext2_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext2_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR */ -+ -+# ifdef CONFIG_EXT2_FS_XATTR_USER -+ -+extern int init_ext2_xattr_user(void) __init; -+extern void exit_ext2_xattr_user(void); -+ -+# else /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+static inline int -+init_ext2_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext2_xattr_user(void) -+{ -+} -+ -+# endif /* CONFIG_EXT2_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ -Index: linux-2.4.29/include/linux/ext3_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_fs.h 2005-05-03 17:23:54.107407504 +0300 -+++ linux-2.4.29/include/linux/ext3_fs.h 2005-05-03 17:59:40.448114120 +0300 -@@ -63,8 +63,6 @@ - */ - #define EXT3_BAD_INO 1 /* Bad blocks inode */ - #define EXT3_ROOT_INO 2 /* Root inode */ --#define EXT3_ACL_IDX_INO 3 /* ACL inode */ --#define EXT3_ACL_DATA_INO 4 /* ACL inode */ - #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */ - #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */ - #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */ -@@ -94,7 +92,6 @@ - #else - # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size) - #endif --#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry)) - #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32)) - #ifdef __KERNEL__ - # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) -@@ -129,28 +126,6 @@ - #endif - - /* -- * ACL structures -- */ --struct ext3_acl_header /* Header of Access Control Lists */ --{ -- __u32 aclh_size; -- __u32 aclh_file_count; -- __u32 aclh_acle_count; -- __u32 aclh_first_acle; --}; -- --struct ext3_acl_entry /* Access Control List Entry */ --{ -- __u32 acle_size; -- __u16 acle_perms; /* Access permissions */ -- __u16 acle_type; /* Type of entry */ -- __u16 acle_tag; /* User or group identity */ -- __u16 acle_pad1; -- __u32 acle_next; /* Pointer on next entry for the */ -- /* same inode or on next free entry */ --}; -- --/* - * Structure of a blocks group descriptor - */ - struct ext3_group_desc -@@ -344,6 +319,7 @@ - #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */ - #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */ - #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */ -+#define EXT3_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */ - - /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */ - #ifndef _LINUX_EXT2_FS_H -@@ -524,7 +500,7 @@ - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ - #define EXT3_FEATURE_INCOMPAT_META_BG 0x0010 - --#define EXT3_FEATURE_COMPAT_SUPP 0 -+#define EXT3_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \ - EXT3_FEATURE_INCOMPAT_RECOVER| \ - EXT3_FEATURE_INCOMPAT_META_BG) -@@ -718,6 +694,7 @@ - extern unsigned long ext3_count_free (struct buffer_head *, unsigned); - - /* inode.c */ -+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int); - extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *); - extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *); - -@@ -787,8 +764,10 @@ - - /* namei.c */ - extern struct inode_operations ext3_dir_inode_operations; -+extern struct inode_operations ext3_special_inode_operations; - - /* symlink.c */ -+extern struct inode_operations ext3_symlink_inode_operations; - extern struct inode_operations ext3_fast_symlink_inode_operations; - - -Index: linux-2.4.29/include/linux/ext3_jbd.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_jbd.h 2005-05-03 17:23:54.109407200 +0300 -+++ linux-2.4.29/include/linux/ext3_jbd.h 2005-05-03 17:59:40.449113968 +0300 -@@ -30,13 +30,19 @@ - - #define EXT3_SINGLEDATA_TRANS_BLOCKS 8U - -+/* Extended attributes may touch two data buffers, two bitmap buffers, -+ * and two group and summaries. */ -+ -+#define EXT3_XATTR_TRANS_BLOCKS 8 -+ - /* Define the minimum size for a transaction which modifies data. This - * needs to take into account the fact that we may end up modifying two - * quota files too (one for the group, one for the user quota). The - * superblock only gets updated once, of course, so don't bother - * counting that again for the quota updates. */ - --#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2) -+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \ -+ EXT3_XATTR_TRANS_BLOCKS - 2) - - extern int ext3_writepage_trans_blocks(struct inode *inode); - -Index: linux-2.4.29/include/linux/ext3_xattr.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ext3_xattr.h 2005-05-03 17:59:40.236146344 +0300 -+++ linux-2.4.29/include/linux/ext3_xattr.h 2005-05-03 17:59:40.451113664 +0300 -@@ -0,0 +1,157 @@ -+/* -+ File: linux/ext3_xattr.h -+ -+ On-disk format of extended attributes for the ext3 filesystem. -+ -+ (C) 2001 Andreas Gruenbacher, -+*/ -+ -+#include -+#include -+#include -+ -+/* Magic value in attribute blocks */ -+#define EXT3_XATTR_MAGIC 0xEA020000 -+ -+/* Maximum number of references to one attribute block */ -+#define EXT3_XATTR_REFCOUNT_MAX 1024 -+ -+/* Name indexes */ -+#define EXT3_XATTR_INDEX_MAX 10 -+#define EXT3_XATTR_INDEX_USER 1 -+#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 -+#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -+ -+struct ext3_xattr_header { -+ __u32 h_magic; /* magic number for identification */ -+ __u32 h_refcount; /* reference count */ -+ __u32 h_blocks; /* number of disk blocks used */ -+ __u32 h_hash; /* hash value of all attributes */ -+ __u32 h_reserved[4]; /* zero right now */ -+}; -+ -+struct ext3_xattr_entry { -+ __u8 e_name_len; /* length of name */ -+ __u8 e_name_index; /* attribute name index */ -+ __u16 e_value_offs; /* offset in disk block of value */ -+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */ -+ __u32 e_value_size; /* size of attribute value */ -+ __u32 e_hash; /* hash value of name and value */ -+ char e_name[0]; /* attribute name */ -+}; -+ -+#define EXT3_XATTR_PAD_BITS 2 -+#define EXT3_XATTR_PAD (1<e_name_len)) ) -+#define EXT3_XATTR_SIZE(size) \ -+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND) -+ -+#ifdef __KERNEL__ -+ -+# ifdef CONFIG_EXT3_FS_XATTR -+ -+struct ext3_xattr_handler { -+ char *prefix; -+ size_t (*list)(char *list, struct inode *inode, const char *name, -+ int name_len); -+ int (*get)(struct inode *inode, const char *name, void *buffer, -+ size_t size); -+ int (*set)(struct inode *inode, const char *name, const void *buffer, -+ size_t size, int flags); -+}; -+ -+extern int ext3_xattr_register(int, struct ext3_xattr_handler *); -+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *); -+ -+extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int); -+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t); -+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); -+extern int ext3_removexattr(struct dentry *, const char *); -+ -+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); -+extern int ext3_xattr_list(struct inode *, char *, size_t); -+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, const void *, size_t, int); -+ -+extern void ext3_xattr_delete_inode(handle_t *, struct inode *); -+extern void ext3_xattr_put_super(struct super_block *); -+ -+extern int init_ext3_xattr(void) __init; -+extern void exit_ext3_xattr(void); -+ -+# else /* CONFIG_EXT3_FS_XATTR */ -+# define ext3_setxattr NULL -+# define ext3_getxattr NULL -+# define ext3_listxattr NULL -+# define ext3_removexattr NULL -+ -+static inline int -+ext3_xattr_get(struct inode *inode, int name_index, const char *name, -+ void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext3_xattr_list(struct inode *inode, void *buffer, size_t size) -+{ -+ return -ENOTSUP; -+} -+ -+static inline int -+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index, -+ const char *name, const void *value, size_t size, int flags) -+{ -+ return -ENOTSUP; -+} -+ -+static inline void -+ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) -+{ -+} -+ -+static inline void -+ext3_xattr_put_super(struct super_block *sb) -+{ -+} -+ -+static inline int -+init_ext3_xattr(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext3_xattr(void) -+{ -+} -+ -+# endif /* CONFIG_EXT3_FS_XATTR */ -+ -+# ifdef CONFIG_EXT3_FS_XATTR_USER -+ -+extern int init_ext3_xattr_user(void) __init; -+extern void exit_ext3_xattr_user(void); -+ -+# else /* CONFIG_EXT3_FS_XATTR_USER */ -+ -+static inline int -+init_ext3_xattr_user(void) -+{ -+ return 0; -+} -+ -+static inline void -+exit_ext3_xattr_user(void) -+{ -+} -+ -+#endif /* CONFIG_EXT3_FS_XATTR_USER */ -+ -+#endif /* __KERNEL__ */ -+ -Index: linux-2.4.29/include/linux/fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs.h 2005-05-03 17:23:53.736463896 +0300 -+++ linux-2.4.29/include/linux/fs.h 2005-05-03 17:59:40.453113360 +0300 -@@ -915,7 +915,7 @@ - int (*setattr) (struct dentry *, struct iattr *); - int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); -- int (*setxattr) (struct dentry *, const char *, void *, size_t, int); -+ int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); - ssize_t (*listxattr) (struct dentry *, char *, size_t); - int (*removexattr) (struct dentry *, const char *); -Index: linux-2.4.29/include/linux/mbcache.h -=================================================================== ---- linux-2.4.29.orig/include/linux/mbcache.h 2005-05-03 17:59:40.236146344 +0300 -+++ linux-2.4.29/include/linux/mbcache.h 2005-05-03 17:59:40.454113208 +0300 -@@ -0,0 +1,69 @@ -+/* -+ File: linux/mbcache.h -+ -+ (C) 2001 by Andreas Gruenbacher, -+*/ -+ -+/* Hardwire the number of additional indexes */ -+#define MB_CACHE_INDEXES_COUNT 1 -+ -+struct mb_cache_entry; -+ -+struct mb_cache_op { -+ int (*free)(struct mb_cache_entry *, int); -+}; -+ -+struct mb_cache { -+ struct list_head c_cache_list; -+ const char *c_name; -+ struct mb_cache_op c_op; -+ atomic_t c_entry_count; -+ int c_bucket_count; -+#ifndef MB_CACHE_INDEXES_COUNT -+ int c_indexes_count; -+#endif -+ kmem_cache_t *c_entry_cache; -+ struct list_head *c_block_hash; -+ struct list_head *c_indexes_hash[0]; -+}; -+ -+struct mb_cache_entry_index { -+ struct list_head o_list; -+ unsigned int o_key; -+}; -+ -+struct mb_cache_entry { -+ struct list_head e_lru_list; -+ struct mb_cache *e_cache; -+ atomic_t e_used; -+ kdev_t e_dev; -+ unsigned long e_block; -+ struct list_head e_block_list; -+ struct mb_cache_entry_index e_indexes[0]; -+}; -+ -+/* Functions on caches */ -+ -+struct mb_cache * mb_cache_create(const char *, struct mb_cache_op *, size_t, -+ int, int); -+void mb_cache_shrink(struct mb_cache *, kdev_t); -+void mb_cache_destroy(struct mb_cache *); -+ -+/* Functions on cache entries */ -+ -+struct mb_cache_entry *mb_cache_entry_alloc(struct mb_cache *); -+int mb_cache_entry_insert(struct mb_cache_entry *, kdev_t, unsigned long, -+ unsigned int[]); -+void mb_cache_entry_rehash(struct mb_cache_entry *, unsigned int[]); -+void mb_cache_entry_release(struct mb_cache_entry *); -+void mb_cache_entry_takeout(struct mb_cache_entry *); -+void mb_cache_entry_free(struct mb_cache_entry *); -+struct mb_cache_entry *mb_cache_entry_dup(struct mb_cache_entry *); -+struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *, kdev_t, -+ unsigned long); -+#if !defined(MB_CACHE_INDEXES_COUNT) || (MB_CACHE_INDEXES_COUNT > 0) -+struct mb_cache_entry *mb_cache_entry_find_first(struct mb_cache *cache, int, -+ kdev_t, unsigned int); -+struct mb_cache_entry *mb_cache_entry_find_next(struct mb_cache_entry *, int, -+ kdev_t, unsigned int); -+#endif -Index: linux-2.4.29/kernel/ksyms.c -=================================================================== ---- linux-2.4.29.orig/kernel/ksyms.c 2005-04-07 19:14:06.000000000 +0300 -+++ linux-2.4.29/kernel/ksyms.c 2005-05-03 17:59:40.456112904 +0300 -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -92,6 +93,7 @@ - EXPORT_SYMBOL(exit_files); - EXPORT_SYMBOL(exit_fs); - EXPORT_SYMBOL(exit_sighand); -+EXPORT_SYMBOL(copy_fs_struct); - - /* internal kernel memory management */ - EXPORT_SYMBOL(_alloc_pages); -@@ -109,6 +111,8 @@ - EXPORT_SYMBOL(kmem_cache_alloc); - EXPORT_SYMBOL(kmem_cache_free); - EXPORT_SYMBOL(kmem_cache_size); -+EXPORT_SYMBOL(register_cache); -+EXPORT_SYMBOL(unregister_cache); - EXPORT_SYMBOL(kmalloc); - EXPORT_SYMBOL(kfree); - EXPORT_SYMBOL(vfree); -Index: linux-2.4.29/mm/vmscan.c -=================================================================== ---- linux-2.4.29.orig/mm/vmscan.c 2005-04-07 18:52:37.000000000 +0300 -+++ linux-2.4.29/mm/vmscan.c 2005-05-03 17:59:40.458112600 +0300 -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -34,6 +35,39 @@ - */ - int vm_passes = 60; - -+static DECLARE_MUTEX(other_caches_sem); -+static LIST_HEAD(cache_definitions); -+ -+void register_cache(struct cache_definition *cache) -+{ -+ down(&other_caches_sem); -+ list_add(&cache->link, &cache_definitions); -+ up(&other_caches_sem); -+} -+ -+void unregister_cache(struct cache_definition *cache) -+{ -+ down(&other_caches_sem); -+ list_del(&cache->link); -+ up(&other_caches_sem); -+} -+ -+static void shrink_other_caches(unsigned int priority, int gfp_mask) -+{ -+ struct list_head *p; -+ -+ if (down_trylock(&other_caches_sem)) -+ return; -+ -+ list_for_each_prev(p, &cache_definitions) { -+ struct cache_definition *cache = -+ list_entry(p, struct cache_definition, link); -+ -+ cache->shrink(priority, gfp_mask); -+ } -+ up(&other_caches_sem); -+} -+ - /* - * "vm_cache_scan_ratio" is how much of the inactive LRU queue we will scan - * in one go. A value of 6 for vm_cache_scan_ratio implies that we'll -@@ -544,6 +578,7 @@ - #ifdef CONFIG_QUOTA - shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask); - #endif -+ shrink_other_caches(vm_vfs_scan_ratio, gfp_mask); - - if (!*failed_swapout) - *failed_swapout = !swap_out(classzone); -@@ -666,6 +701,7 @@ - #ifdef CONFIG_QUOTA - shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask); - #endif -+ shrink_other_caches(vm_vfs_scan_ratio, gfp_mask); - if (!failed_swapout) - failed_swapout = !swap_out(classzone); - } while (--tries); diff --git a/lustre/kernel_patches/patches/listman-2.4.20.patch b/lustre/kernel_patches/patches/listman-2.4.20.patch deleted file mode 100644 index 1e4508b..0000000 --- a/lustre/kernel_patches/patches/listman-2.4.20.patch +++ /dev/null @@ -1,22 +0,0 @@ -Index: linux-2.4.20/include/linux/list.h -=================================================================== ---- linux-2.4.20.orig/include/linux/list.h 2003-10-17 23:56:26.000000000 +0400 -+++ linux-2.4.20/include/linux/list.h 2003-10-22 14:02:22.000000000 +0400 -@@ -227,6 +227,17 @@ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -+/* 2.5 uses hlists for some things, like the d_hash. we'll treat them -+ * as 2.5 and let macros drop back.. */ -+#define hlist_entry list_entry -+#define hlist_head list_head -+#define hlist_node list_head -+#define HLIST_HEAD LIST_HEAD -+#define INIT_HLIST_HEAD INIT_LIST_HEAD -+#define hlist_del_init list_del_init -+#define hlist_add_head list_add -+#define hlist_for_each_safe list_for_each_safe -+ - #endif /* __KERNEL__ || _LVM_H_INCLUDE */ - - #endif diff --git a/lustre/kernel_patches/patches/listman-2.4.21-chaos.patch b/lustre/kernel_patches/patches/listman-2.4.21-chaos.patch deleted file mode 100644 index 6c85e492..0000000 --- a/lustre/kernel_patches/patches/listman-2.4.21-chaos.patch +++ /dev/null @@ -1,26 +0,0 @@ -Index: linux-2.4.21-chaos/include/linux/list.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/list.h 2003-12-05 16:54:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/list.h 2003-12-12 16:08:20.000000000 +0300 -@@ -241,6 +241,21 @@ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -+#ifndef list_for_each_entry_safe -+/** -+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry -+ * @pos: the type * to use as a loop counter. -+ * @n: another type * to use as temporary storage -+ * @head: the head for your list. -+ * @member: the name of the list_struct within the struct. -+ */ -+#define list_for_each_entry_safe(pos, n, head, member) \ -+ for (pos = list_entry((head)->next, typeof(*pos), member), \ -+ n = list_entry(pos->member.next, typeof(*pos), member); \ -+ &pos->member != (head); \ -+ pos = n, n = list_entry(n->member.next, typeof(*n), member)) -+#endif -+ - #define list_first(head) (((head)->next != (head)) ? (head)->next: (struct list_head *) 0) - - #endif /* __KERNEL__ || _LVM_H_INCLUDE */ diff --git a/lustre/kernel_patches/patches/llnl-frame-pointer-walk-2.4.21-rhel.patch b/lustre/kernel_patches/patches/llnl-frame-pointer-walk-2.4.21-rhel.patch deleted file mode 100644 index 4d234af..0000000 --- a/lustre/kernel_patches/patches/llnl-frame-pointer-walk-2.4.21-rhel.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff -X dontdiff -urp kern_oldest/arch/i386/kernel/traps.c kern_fix/arch/i386/kernel/traps.c ---- kern_oldest/arch/i386/kernel/traps.c 2006-05-01 11:56:31.000000000 -0700 -+++ kern_fix/arch/i386/kernel/traps.c 2006-05-01 14:56:40.000000000 -0700 -@@ -133,6 +133,80 @@ static inline int kernel_text_address(un - - #endif - -+#if CONFIG_FRAME_POINTER -+void show_stack_frame_params (int param_count, unsigned long params[]) -+{ -+ int i; -+ unsigned long *p, task_addr, stack_base; -+ -+ if (param_count <= 0) -+ return; -+ -+ task_addr = (unsigned long) current; -+ stack_base = task_addr + THREAD_SIZE - 1; -+ -+ printk(" ("); -+ -+ for (i = 0, p = params; -+ ((param_count - i) > 1) && (p >= task_addr) && (p <= stack_base); -+ i++, p++) { -+ printk("0x%x, ", *p); -+ -+ if ((i % 4) == 3) -+ printk("\n "); -+ } -+ -+ if ((p >= task_addr) && (p <= stack_base)) -+ printk("0x%x)\n", *p); -+} -+ -+void frame_pointer_walk(unsigned long *stack) -+{ -+ int i; -+ unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr, -+ eip, stack_base; -+ /* static to not take up stackspace; if we race here too bad */ -+ static char buffer[512]; -+ -+ addr = (unsigned long) stack; -+ task_addr = (unsigned long) current; -+ stack_base = task_addr + THREAD_SIZE - 1; -+ -+ /* Simply return if we are doing a stack trace for any task other -+ * than the currently executing task. To trace another task, we -+ * would need an %ebp register value for that task. -+ */ -+ if (((addr < task_addr) || (addr > stack_base))) { -+ return; -+ } -+ -+ frame_ptr = (unsigned long *) (&stack - 2); -+ -+ for (; ; ) { -+ next_frame_ptr = (unsigned long *) (*frame_ptr); -+ addr = (unsigned long) next_frame_ptr; -+ -+ /* Stop when we reach a frame pointer that points to a -+ * location clearly outside our own kernel stack. -+ */ -+ if ((addr < task_addr) || (addr > stack_base)) -+ break; -+ -+ eip_ptr = frame_ptr + 1; -+ eip = *eip_ptr; -+ -+ if (kernel_text_address(eip)) { -+ lookup_symbol(eip, buffer, 512); -+ show_stack_frame_params(4, frame_ptr + 2); -+ printk("[<%08lx>] %s (0x%x)\n", eip, buffer, -+ eip_ptr); -+ } -+ -+ frame_ptr = next_frame_ptr; -+ } -+} -+#endif -+ - void show_trace(unsigned long * stack) - { - #if !CONFIG_FRAME_POINTER -@@ -151,16 +225,7 @@ void show_trace(unsigned long * stack) - * a 100% exact backtrace, up until the entry frame: - */ - #if CONFIG_FRAME_POINTER --#define DO(n) \ -- addr = (int)__builtin_return_address(n); \ -- if (!kernel_text_address(addr)) \ -- goto out; \ -- lookup_symbol(addr, buffer, 512); \ -- printk("[<%08lx>] %s\n", addr, buffer); -- -- DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(7); DO(8); DO(9); -- DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); DO(17); DO(18); DO(19); --out: -+ frame_pointer_walk(stack); - #else - i = 1; - limit = ((unsigned long)stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE - 3; -@@ -168,7 +233,7 @@ out: - addr = *stack++; - if (kernel_text_address(addr)) { - lookup_symbol(addr, buffer, 512); -- printk("[<%08lx>] %s (0x%p)\n", addr,buffer,stack-1); -+ printk("[<%08lx>] %s (0x%x)\n", addr,buffer,stack-1); - i++; - } - } -@@ -244,7 +309,7 @@ void show_registers(struct pt_regs *regs - lookup_symbol(regs->eip, buffer, 512); - printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n", - smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags); -- printk("\nEIP is at %s (" UTS_RELEASE ARCHIT ")\n",buffer); -+ printk("\nEIP is at %s (" UTS_RELEASE ")\n",buffer); - 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 esp: %08lx\n", diff --git a/lustre/kernel_patches/patches/llnl-frame-pointer-walk-fix-2.4.21-rhel.patch b/lustre/kernel_patches/patches/llnl-frame-pointer-walk-fix-2.4.21-rhel.patch deleted file mode 100644 index 64d652a..0000000 --- a/lustre/kernel_patches/patches/llnl-frame-pointer-walk-fix-2.4.21-rhel.patch +++ /dev/null @@ -1,249 +0,0 @@ -Index: kernel/arch/i386/kernel/traps.c -=================================================================== ---- kernel.orig/arch/i386/kernel/traps.c 2006-05-26 16:12:28.000000000 -0700 -+++ kernel/arch/i386/kernel/traps.c 2006-05-26 16:15:54.000000000 -0700 -@@ -133,6 +133,30 @@ - - #endif - -+void scan_stack (unsigned long *stack) -+{ -+ int i; -+ unsigned long addr; -+ /* static to not take up stackspace */ -+ static char buffer[NR_CPUS][512], *bufp; -+ -+ bufp = buffer[smp_processor_id()]; -+ -+ /* -+ * If we have frame pointers then use them to get -+ * a 100% exact backtrace, up until the entry frame: -+ */ -+ i = 1; -+ while (((long) stack & (THREAD_SIZE-1)) != 0) { -+ addr = *stack++; -+ if (kernel_text_address(addr)) { -+ lookup_symbol(addr, bufp, 512); -+ printk("[<%08lx>] %s (0x%p)\n", addr,bufp,stack-1); -+ i++; -+ } -+ } -+} -+ - #if CONFIG_FRAME_POINTER - void show_stack_frame_params (int param_count, unsigned long params[]) - { -@@ -160,27 +184,23 @@ - printk("0x%x)\n", *p); - } - --void frame_pointer_walk(unsigned long *stack) -+/* Display a stack trace for the currently executing task. The 'dummy' -+ * parameter serves a purpose although its value is unused. We use the -+ * address of 'dummy' as a reference point for finding the saved %ebp register -+ * value on the stack. -+ */ -+void frame_pointer_walk (void *dummy) - { - int i; - unsigned long addr, task_addr, *frame_ptr, *next_frame_ptr, *eip_ptr, - eip, stack_base; -- /* static to not take up stackspace; if we race here too bad */ -- static char buffer[512]; -+ /* static to not take up stackspace */ -+ static char buffer[NR_CPUS][512], *bufp; - -- addr = (unsigned long) stack; -+ bufp = buffer[smp_processor_id()]; - task_addr = (unsigned long) current; - stack_base = task_addr + THREAD_SIZE - 1; -- -- /* Simply return if we are doing a stack trace for any task other -- * than the currently executing task. To trace another task, we -- * would need an %ebp register value for that task. -- */ -- if (((addr < task_addr) || (addr > stack_base))) { -- return; -- } -- -- frame_ptr = (unsigned long *) (&stack - 2); -+ frame_ptr = (unsigned long *) (&dummy - 2); - - for (; ; ) { - next_frame_ptr = (unsigned long *) (*frame_ptr); -@@ -196,9 +216,9 @@ - eip = *eip_ptr; - - if (kernel_text_address(eip)) { -- lookup_symbol(eip, buffer, 512); -+ lookup_symbol(eip, bufp, 512); - show_stack_frame_params(4, frame_ptr + 2); -- printk("[<%08lx>] %s (0x%x)\n", eip, buffer, -+ printk("[<%08lx>] %s (0x%x)\n", eip, bufp, - eip_ptr); - } - -@@ -207,40 +227,49 @@ - } - #endif - -+typedef void (*stack_trace_fn_t) (unsigned long *stack); -+ -+#if CONFIG_FRAME_POINTER - void show_trace(unsigned long * stack) - { --#if !CONFIG_FRAME_POINTER -- int i; --#endif -- unsigned long addr, limit; -- /* static to not take up stackspace; if we race here too bad */ -- static char buffer[512]; -+ static const stack_trace_fn_t trace_fn_vector[] = -+ { scan_stack, frame_pointer_walk }; -+ unsigned long addr, task_addr, stack_base; -+ int task_is_current; - - if (!stack) - stack = (unsigned long*)&stack; - - printk("Call Trace: "); -- /* -- * If we have frame pointers then use them to get -- * a 100% exact backtrace, up until the entry frame: -- */ --#if CONFIG_FRAME_POINTER -- frame_pointer_walk(stack); --#else -- i = 1; -- limit = ((unsigned long)stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE - 3; -- while ((unsigned long)stack < limit) { -- addr = *stack++; -- if (kernel_text_address(addr)) { -- lookup_symbol(addr, buffer, 512); -- printk("[<%08lx>] %s (0x%x)\n", addr,buffer,stack-1); -- i++; -- } -- } --#endif -+ addr = (unsigned long) stack; -+ task_addr = (unsigned long) current; -+ stack_base = task_addr + THREAD_SIZE - 1; -+ task_is_current = (addr >= task_addr) && (addr <= stack_base); -+ -+ /* We may use frame pointers to do a stack trace only if the current -+ * task is being traced. Tracing some other task in this manner -+ * would require a saved %ebp register value. Perhaps in the future -+ * I'll consider providing a means of obtaining this. -+ */ -+ trace_fn_vector[task_is_current](stack); -+ -+ printk("\n"); -+} -+ -+#else /* CONFIG_FRAME_POINTER */ -+ -+void show_trace(unsigned long * stack) -+{ -+ if (!stack) -+ stack = (unsigned long*)&stack; -+ -+ printk("Call Trace:\n"); -+ scan_stack(stack); - printk("\n"); - } - -+#endif /* CONFIG_FRAME_POINTER */ -+ - void show_trace_task(struct task_struct *tsk) - { - unsigned long esp = tsk->thread.esp; -Index: kernel/include/asm-i386/hw_irq.h -=================================================================== ---- kernel.orig/include/asm-i386/hw_irq.h 2006-05-26 16:11:33.000000000 -0700 -+++ kernel/include/asm-i386/hw_irq.h 2006-05-26 16:13:51.000000000 -0700 -@@ -153,6 +153,9 @@ - /* there is a second layer of macro just to get the symbolic - name for the vector evaluated. This change is for RTLinux */ - #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v) -+ -+#if CONFIG_X86_HIGH_ENTRY -+ - #define XBUILD_SMP_INTERRUPT(x,v)\ - asmlinkage void x(void); \ - asmlinkage void call_##x(void); \ -@@ -165,7 +168,26 @@ - "movl $"SYMBOL_NAME_STR(smp_##x)", %ebp; call *%ebp\n\t" \ - "jmp ret_from_intr; .previous\n"); - -+#else -+ -+#define XBUILD_SMP_INTERRUPT(x,v)\ -+asmlinkage void x(void); \ -+asmlinkage void call_##x(void); \ -+__asm__( \ -+".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \ -+SYMBOL_NAME_STR(x) ":\n\t" \ -+ "pushl $"#v"-256\n\t" \ -+ SAVE_ALL_SWITCH \ -+ SYMBOL_NAME_STR(call_##x)":\n\t" \ -+ "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ -+ "jmp ret_from_intr; .previous\n"); -+ -+#endif -+ - #define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v) -+ -+#if CONFIG_X86_HIGH_ENTRY -+ - #define XBUILD_SMP_TIMER_INTERRUPT(x,v) \ - asmlinkage void x(struct pt_regs * regs); \ - asmlinkage void call_##x(void); \ -@@ -181,6 +203,27 @@ - "addl $4,%esp\n\t" \ - "jmp ret_from_intr; .previous\n"); - -+#else -+ -+#define XBUILD_SMP_TIMER_INTERRUPT(x,v) \ -+asmlinkage void x(struct pt_regs * regs); \ -+asmlinkage void call_##x(void); \ -+__asm__( \ -+".section .entry.text,\"ax\"\n"__ALIGN_STR"\n" \ -+SYMBOL_NAME_STR(x) ":\n\t" \ -+ "pushl $"#v"-256\n\t" \ -+ SAVE_ALL_SWITCH \ -+ "movl %esp,%eax\n\t" \ -+ "pushl %eax\n\t" \ -+ SYMBOL_NAME_STR(call_##x)":\n\t" \ -+ "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ -+ "addl $4,%esp\n\t" \ -+ "jmp ret_from_intr; .previous\n"); -+ -+#endif -+ -+#if CONFIG_X86_HIGH_ENTRY -+ - #define BUILD_COMMON_IRQ() \ - asmlinkage void call_do_IRQ(void); \ - __asm__( \ -@@ -191,6 +234,20 @@ - "movl $"SYMBOL_NAME_STR(do_IRQ)", %ebp; call *%ebp\n\t" \ - "jmp ret_from_intr; .previous\n"); - -+#else -+ -+#define BUILD_COMMON_IRQ() \ -+asmlinkage void call_do_IRQ(void); \ -+__asm__( \ -+ ".section .entry.text,\"ax\"\n" __ALIGN_STR"\n" \ -+ "common_interrupt:\n\t" \ -+ SAVE_ALL_SWITCH \ -+ SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \ -+ "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ -+ "jmp ret_from_intr; .previous\n"); -+ -+#endif -+ - /* - * subtle. orig_eax is used by the signal code to distinct between - * system calls and interrupted 'random user-space'. Thus we have diff --git a/lustre/kernel_patches/patches/lookup-stack-symbols-2.4.21-suse-171.patch b/lustre/kernel_patches/patches/lookup-stack-symbols-2.4.21-suse-171.patch deleted file mode 100644 index fd3d054..0000000 --- a/lustre/kernel_patches/patches/lookup-stack-symbols-2.4.21-suse-171.patch +++ /dev/null @@ -1,234 +0,0 @@ -Index: linux-2.4.21-273/arch/i386/kernel/process.c -=================================================================== ---- linux-2.4.21-273.orig/arch/i386/kernel/process.c 2005-01-17 07:08:16.000000000 -0500 -+++ linux-2.4.21-273/arch/i386/kernel/process.c 2005-04-05 20:11:38.391253492 -0400 -@@ -36,6 +36,7 @@ - #ifdef CONFIG_KDB - #include - #endif /* CONFIG_KDB */ -+#include - - #include - #include -@@ -772,10 +773,14 @@ - void show_regs(struct pt_regs * regs) - { - unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; -+ static char buffer[512]; -+ -+ lookup_symbol(regs->eip, buffer, 512); - - printk("\n"); - printk("Pid: %d, comm: %20s\n", current->pid, current->comm); - printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id()); -+ printk("\nEIP is at %s (" UTS_RELEASE ")\n", buffer); - if (regs->xcs & 3) - printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); - printk(" EFLAGS: %08lx %s\n",regs->eflags, print_tainted()); -Index: linux-2.4.21-273/arch/i386/kernel/traps.c -=================================================================== ---- linux-2.4.21-273.orig/arch/i386/kernel/traps.c 2005-04-05 20:11:27.381848523 -0400 -+++ linux-2.4.21-273/arch/i386/kernel/traps.c 2005-04-05 20:11:38.392253347 -0400 -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include - -@@ -275,7 +276,8 @@ - { - int i; - unsigned long addr; -- unsigned long *prev = NULL; -+ /* static to not take up stackspace; if we race here too bad */ -+ static char buffer[512]; - - if (!stack) - stack = (unsigned long*)&stack; -@@ -285,17 +287,12 @@ - while (((long) stack & (THREAD_SIZE-1)) != 0) { - addr = *stack++; - if (kernel_text_address(addr)) { -- if (prev) -- printk(" (%02d)", (stack-prev)*sizeof(*stack)); -- prev = stack; -- if ((i % 4) == 0) -- printk("\n "); -- printk(" [<%08lx>]", addr); -+ lookup_symbol(addr, buffer, 512); -+ printk(" [<%08lx>] %s (0x%p)\n", -+ addr, buffer, stack - 1); - i++; - } - } -- if (prev) -- printk(" (%02d)", (stack-prev)*sizeof(*stack)); - printk("\n"); - } - -@@ -341,12 +338,19 @@ - printk("Code: <0>\n"); /* tell ksymoops trace ends here */ - } - -+#ifdef CONFIG_MK7 -+#define ARCHIT "/athlon" -+#else -+#define ARCHIT "/i686" -+#endif -+ - void show_registers(struct pt_regs *regs) - { - int i; - int in_kernel = 1; - unsigned long esp; - unsigned short ss; -+ static char buffer[512]; - - esp = (unsigned long) (®s->esp); - ss = __KERNEL_DS; -@@ -355,10 +359,13 @@ - esp = regs->esp; - ss = regs->xss & 0xffff; - } -+ print_modules(); -+ lookup_symbol(regs->eip, buffer, 512); - module_oops_tracking_init(); - kernel_text_address(regs->eip); - printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n", - smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags); -+ printk("\nEIP is at %s (" UTS_RELEASE ARCHIT ")\n", buffer); - 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 esp: %08lx\n", -@@ -420,6 +427,7 @@ - (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) - file = ""; - -+ printk("-----------[ cut here ]------------\n"); - printk("kernel BUG at %s:%d!\n", file, line); - - no_bug: -Index: linux-2.4.21-273/include/linux/kernel.h -=================================================================== ---- linux-2.4.21-273.orig/include/linux/kernel.h 2005-01-17 07:09:09.000000000 -0500 -+++ linux-2.4.21-273/include/linux/kernel.h 2005-04-05 20:11:38.393253203 -0400 -@@ -132,6 +132,9 @@ - - extern void dump_stack(void); - -+extern int lookup_symbol(unsigned long address, char *buffer, int buflen); -+extern void print_modules(void); -+ - extern char *oops_id; - - #if DEBUG -Index: linux-2.4.21-273/kernel/Makefile -=================================================================== ---- linux-2.4.21-273.orig/kernel/Makefile 2005-01-17 07:08:59.000000000 -0500 -+++ linux-2.4.21-273/kernel/Makefile 2005-04-05 20:12:04.410483855 -0400 -@@ -11,12 +11,13 @@ - - export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \ - printk.o cpufreq.o rcupdate.o syscall_ksyms.o fork.o hook.o \ -- rashooks.o module.o -+ rashooks.o module.o kksymoops.o - - obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ - module.o exit.o itimer.o info.o time.o softirq.o resource.o \ - sysctl.o acct.o capability.o ptrace.o timer.o user.o \ -- signal.o sys.o kmod.o context.o rcupdate.o futex.o syscall_ksyms.o -+ signal.o sys.o kmod.o context.o rcupdate.o futex.o \ -+ syscall_ksyms.o kksymoops.o - - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += ksyms.o -Index: linux-2.4.21-273/kernel/kksymoops.c -=================================================================== ---- linux-2.4.21-273.orig/kernel/kksymoops.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.4.21-273/kernel/kksymoops.c 2005-04-05 20:11:38.394253058 -0400 -@@ -0,0 +1,83 @@ -+#include -+#include -+#include -+#include -+#include -+#ifdef CONFIG_KALLSYMS -+#include -+#endif -+ -+ -+ -+int lookup_symbol(unsigned long address, char *buffer, int buflen) -+{ -+ struct module *this_mod; -+ unsigned long bestsofar; -+ -+ const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL; -+ unsigned long mod_start,mod_end,sec_start,sec_end,sym_start,sym_end; -+ -+ if (!buffer) -+ return -EFAULT; -+ -+ if (buflen<256) -+ return -ENOMEM; -+ -+ memset(buffer,0,buflen); -+ -+#ifdef CONFIG_KALLSYMS -+ if (!kallsyms_address_to_symbol(address,&mod_name,&mod_start,&mod_end,&sec_name, -+ &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) { -+ /* kallsyms doesn't have a clue; lets try harder */ -+ bestsofar = 0; -+ snprintf(buffer,buflen-1,"[unresolved]"); -+ -+ this_mod = module_list; -+ -+ while (this_mod != NULL) { -+ int i; -+ /* walk the symbol list of this module. Only symbols -+ who's address is smaller than the searched for address -+ are relevant; and only if it's better than the best so far */ -+ for (i=0; i< this_mod->nsyms; i++) -+ if ((this_mod->syms[i].value<=address) && -+ (bestsofarsyms[i].value)) { -+ snprintf(buffer,buflen-1,"%s [%s] 0x%x", -+ this_mod->syms[i].name, -+ this_mod->name, -+ (unsigned int)(address - this_mod->syms[i].value)); -+ bestsofar = this_mod->syms[i].value; -+ } -+ this_mod = this_mod->next; -+ } -+ -+ } else { /* kallsyms success */ -+ snprintf(buffer,buflen-1,"%s [%s] 0x%x",sym_name,mod_name,(unsigned int)(address-sym_start)); -+ } -+#endif -+ return strlen(buffer); -+} -+EXPORT_SYMBOL(lookup_symbol); -+ -+static char modlist[4096]; -+/* this function isn't smp safe but that's not really a problem; it's called from -+ * oops context only and any locking could actually prevent the oops from going out; -+ * the line that is generated is informational only and should NEVER prevent the real oops -+ * from going out. -+ */ -+void print_modules(void) -+{ -+ struct module *this_mod; -+ int pos = 0, i; -+ memset(modlist,0,4096); -+ -+#ifdef CONFIG_KALLSYMS -+ this_mod = module_list; -+ while (this_mod != NULL) { -+ if (this_mod->name != NULL) -+ pos +=snprintf(modlist+pos,160-pos-1,"%s ",this_mod->name); -+ this_mod = this_mod->next; -+ } -+ printk("%s\n",modlist); -+#endif -+} diff --git a/lustre/kernel_patches/patches/loop-sync-2.4.21-suse.patch b/lustre/kernel_patches/patches/loop-sync-2.4.21-suse.patch deleted file mode 100644 index 5d18ad3..0000000 --- a/lustre/kernel_patches/patches/loop-sync-2.4.21-suse.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux/drivers/block/loop.c.bu 2004-05-11 16:27:23.000000000 -0700 -+++ linux/drivers/block/loop.c 2004-05-11 16:28:50.000000000 -0700 -@@ -978,7 +978,7 @@ static int lo_release(struct inode *inod - - lo = &loop_dev[dev]; - -- if (!(lo->lo_flags & LO_FLAGS_READ_ONLY)) { -+ if (!(lo->lo_flags & LO_FLAGS_READ_ONLY) && lo->lo_device != 0) { - fsync_dev(lo->lo_device); - invalidate_buffers(lo->lo_device); - } diff --git a/lustre/kernel_patches/patches/netconsole-2.4.24-ppc.patch b/lustre/kernel_patches/patches/netconsole-2.4.24-ppc.patch deleted file mode 100644 index 701c56a..0000000 --- a/lustre/kernel_patches/patches/netconsole-2.4.24-ppc.patch +++ /dev/null @@ -1,489 +0,0 @@ -Index: linux-2.4.24/drivers/net/netconsole.c -=================================================================== -Index: bglio/drivers/net/netconsole.c -=================================================================== ---- bglio.orig/drivers/net/netconsole.c 2004-05-07 15:50:22.000000000 -0700 -+++ bglio/drivers/net/netconsole.c 2004-05-07 17:15:28.000000000 -0700 -@@ -12,6 +12,8 @@ - * - * 2001-09-17 started by Ingo Molnar. - * 2002-03-14 simultaneous syslog packet option by Michael K. Johnson -+ * 2003-10-30 Add sysrq command processing by Wangdi -+ * - */ - - /**************************************************************** -@@ -51,6 +53,7 @@ - #include - #include - #include -+#include "netconsole.h" - - static struct net_device *netconsole_dev; - static u16 source_port, netdump_target_port, netlog_target_port, syslog_target_port; -@@ -62,12 +65,11 @@ - static unsigned int mhz = 500, idle_timeout; - static unsigned long long mhz_cycles, jiffy_cycles; - --#include "netconsole.h" - - #define MAX_UDP_CHUNK 1460 - #define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN) - --#define DEBUG 0 -+#define DEBUG 0 - #if DEBUG - # define Dprintk(x...) printk(KERN_INFO x) - #else -@@ -187,6 +189,22 @@ - } - } - } -+void (*irqfunc)(int, void *, struct pt_regs *); -+ -+static void netdump_poll(struct net_device *dev) -+{ -+ int budget = 1; -+ -+ disable_irq(dev->irq); -+ -+ irqfunc(dev->irq, dev, 0); -+ -+ if(dev->poll && test_bit(__LINK_STATE_RX_SCHED, &dev->state)) -+ dev->poll(dev, &budget); -+ -+ enable_irq(dev->irq); -+ -+} - - static struct sk_buff * alloc_netconsole_skb(struct net_device *dev, int len, int reserve) - { -@@ -209,7 +227,7 @@ - once = 0; - } - Dprintk("alloc skb: polling controller ...\n"); -- dev->poll_controller(dev); -+ netdump_poll(dev); - goto repeat; - } - } -@@ -231,7 +249,7 @@ - spin_unlock(&dev->xmit_lock); - - Dprintk("xmit skb: polling controller ...\n"); -- dev->poll_controller(dev); -+ netdump_poll(dev); - zap_completion_queue(); - goto repeat_poll; - } -@@ -426,18 +444,79 @@ - static spinlock_t sequence_lock = SPIN_LOCK_UNLOCKED; - static unsigned int log_offset; - -+static int thread_stopped = 0; -+/*Interrupt function for netdump */ -+static int sysrq_mode = 0; -+static int stop_sysrq_thread = 0; -+#define Set_Sysrq_mode() (sysrq_mode = 1) -+#define Clear_Sysrq_mode() (sysrq_mode = 0) -+static char send_cache[MAX_PRINT_CHUNK]; -+static unsigned int send_cache_pos = 0; -+wait_queue_head_t sysrq_thread_queue; -+wait_queue_head_t sysrq_thread_waiter_queue; -+ -+#define SEND_MSG_BUFFER(buf, len) \ -+do \ -+{ \ -+ reply_t reply; \ -+ unsigned int flags; \ -+ __save_flags(flags); \ -+ __cli(); \ -+ reply.code = REPLY_LOG; \ -+ reply.nr = 0; \ -+ reply.info = 0; \ -+ spin_lock(&sequence_lock); \ -+ send_netlog_skb(dev, buf, len, &reply); \ -+ spin_unlock(&sequence_lock); \ -+ __restore_flags(flags); \ -+}while(0); -+ -+void netconsole_do_sysrq(req_t *req) -+{ -+ struct pt_regs regs; -+ struct net_device *dev = netconsole_dev; -+ -+ if (!dev) -+ return; -+ Set_Sysrq_mode(); -+ get_current_regs(®s); -+ handle_sysrq((int)req->from, ®s, NULL); -+ -+ if (send_cache_pos != 0){ -+ SEND_MSG_BUFFER(send_cache, send_cache_pos); -+ memset(send_cache, 0, MAX_PRINT_CHUNK); -+ send_cache_pos = 0; -+ } -+ -+ Clear_Sysrq_mode(); -+} - static void write_netconsole_msg(struct console *con, const char *msg0, unsigned int msg_len) - { - int len, left, i; - struct net_device *dev; - const char *msg = msg0; - reply_t reply; -- -+ - dev = netconsole_dev; - if (!dev || netdump_mode) - return; -- -- if (dev->poll_controller && netif_running(dev)) { -+ if (sysrq_mode){ -+ unsigned long total_len = send_cache_pos + msg_len; -+ unsigned long left_len = msg_len; -+ while (total_len >= MAX_PRINT_CHUNK){ -+ unsigned long send_len = MAX_PRINT_CHUNK - send_cache_pos; -+ memcpy(send_cache + send_cache_pos, msg, send_len); -+ SEND_MSG_BUFFER(send_cache, MAX_PRINT_CHUNK); -+ send_cache_pos = 0; -+ total_len -= MAX_PRINT_CHUNK; -+ left_len -= send_len; -+ } -+ if (left_len > 0){ -+ memcpy(send_cache + send_cache_pos, msg + (msg_len -left_len), left_len); -+ send_cache_pos += left_len; -+ } -+ return; -+ }else if (netif_running(dev)) { - unsigned long flags; - - __save_flags(flags); -@@ -567,8 +646,6 @@ - req_t *req; - struct net_device *dev; - -- if (!netdump_mode) -- return NET_RX_SUCCESS; - #if DEBUG - { - static int packet_count; -@@ -722,8 +799,16 @@ - Dprintk("... netdump from: %08x.\n", req->from); - Dprintk("... netdump to: %08x.\n", req->to); - -- add_new_req(req); -+ if (netdump_mode) -+ add_new_req(req); -+ else if (req->command == COMM_SYSRQ){ -+ add_new_req(req); -+ wake_up(&sysrq_thread_queue); -+ return NET_RX_DROP; -+ } - out: -+ if (!netdump_mode) -+ return NET_RX_SUCCESS; - return NET_RX_DROP; - } - -@@ -763,6 +848,7 @@ - kunmap_atomic(kaddr, KM_NETDUMP); - } - -+ - /* - * This function waits for the client to acknowledge the receipt - * of the netdump startup reply, with the possibility of packets -@@ -792,7 +878,7 @@ - // wait 1 sec. - udelay(100); - Dprintk("handshake: polling controller ...\n"); -- dev->poll_controller(dev); -+ netdump_poll(dev); - zap_completion_queue(); - req = get_new_req(); - if (req) -@@ -884,6 +970,7 @@ - */ - spin_lock_init(&dev->xmit_lock); - -+#ifdef __i386__ - esp = (unsigned long) ((char *)regs + sizeof (struct pt_regs)); - ss = __KERNEL_DS; - if (regs->xcs & 3) { -@@ -893,6 +980,7 @@ - myregs = *regs; - myregs.esp = esp; - myregs.xss = (myregs.xss & 0xffff0000) | ss; -+#endif - - rdtscll(t0); - -@@ -904,7 +992,7 @@ - while (netdump_mode) { - __cli(); - Dprintk("main netdump loop: polling controller ...\n"); -- dev->poll_controller(dev); -+ netdump_poll(dev); - zap_completion_queue(); - #if !CLI - __sti(); -@@ -1009,6 +1097,32 @@ - printk("NETDUMP END!\n"); - __restore_flags(flags); - } -+static int netconsole_sysrq_schedule(void *arg) -+{ -+ struct task_struct *tsk = current; -+ -+ sprintf(tsk->comm, "sysrq_schedule"); -+ sigfillset(&tsk->blocked); -+ -+ /* main loop */ -+ thread_stopped = 0; -+ for (;;) { -+ wait_event_interruptible(sysrq_thread_queue, -+ !list_empty(&request_list) || stop_sysrq_thread); -+ while (!list_empty(&request_list)) { -+ req_t *req = get_new_req(); -+ if (req->command == COMM_SYSRQ) -+ netconsole_do_sysrq(req); -+ } -+ if (stop_sysrq_thread) -+ break; -+ wake_up(&sysrq_thread_waiter_queue); -+ } -+ thread_stopped = 1; -+ wake_up(&sysrq_thread_waiter_queue); -+ return 0; -+} -+ - - static char *dev; - static int netdump_target_eth_byte0 = 255; -@@ -1087,11 +1201,12 @@ - - static struct console netconsole = - { flags: CON_ENABLED, write: write_netconsole_msg }; -- - static int init_netconsole(void) - { - struct net_device *ndev = NULL; - struct in_device *in_dev; -+ struct irqaction *action; -+ int rc = 0; - - printk(KERN_INFO "netlog: using network device <%s>\n", dev); - // this will be valid once the device goes up. -@@ -1101,10 +1216,6 @@ - printk(KERN_ERR "netlog: network device %s does not exist, aborting.\n", dev); - return -1; - } -- if (!ndev->poll_controller) { -- printk(KERN_ERR "netlog: %s's network driver does not implement netlogging yet, aborting.\n", dev); -- return -1; -- } - in_dev = in_dev_get(ndev); - if (!in_dev) { - printk(KERN_ERR "netlog: network device %s is not an IP protocol device, aborting.\n", dev); -@@ -1137,8 +1248,6 @@ - if (!netdump_target_ip && !netlog_target_ip && !syslog_target_ip) { - printk(KERN_ERR "netlog: target_ip parameter not specified, aborting.\n"); - return -1; -- } -- if (netdump_target_ip) { - #define IP(x) ((unsigned char *)&netdump_target_ip)[x] - printk(KERN_INFO "netlog: using netdump target IP %u.%u.%u.%u\n", - IP(3), IP(2), IP(1), IP(0)); -@@ -1214,12 +1323,27 @@ - - mhz_cycles = (unsigned long long)mhz * 1000000ULL; - jiffy_cycles = (unsigned long long)mhz * (1000000/HZ); -- -- INIT_LIST_HEAD(&request_list); -- -+ - ndev->rx_hook = netconsole_rx_hook; - netdump_func = netconsole_netdump; - netconsole_dev = ndev; -+ /* find irq function of the ndev*/ -+ action=find_irq_action(ndev->irq, ndev); -+ if (!action) { -+ printk(KERN_ERR "couldn't find irq handler for <%s>", dev); -+ return -1; -+ } -+ irqfunc = action->handler; -+ -+ stop_sysrq_thread = 0; -+ INIT_LIST_HEAD(&request_list); -+ init_waitqueue_head(&sysrq_thread_queue); -+ init_waitqueue_head(&sysrq_thread_waiter_queue); -+ if ((rc = kernel_thread(netconsole_sysrq_schedule, NULL, 0)) < 0 ){ -+ printk(KERN_ERR "Can not start netconsole sysrq thread: rc %d\n", rc); -+ return -1; -+ } -+ - #define STARTUP_MSG "[...network console startup...]\n" - write_netconsole_msg(NULL, STARTUP_MSG, strlen(STARTUP_MSG)); - -@@ -1230,7 +1354,11 @@ - - static void cleanup_netconsole(void) - { -- printk(KERN_INFO "netlog: network logging shut down.\n"); -+ stop_sysrq_thread = 1; -+ -+ wake_up(&sysrq_thread_queue); -+ wait_event(sysrq_thread_waiter_queue, thread_stopped); -+ printk(KERN_INFO"netlog: network logging shut down.\n"); - unregister_console(&netconsole); - - #define SHUTDOWN_MSG "[...network console shutdown...]\n" -Index: bglio/drivers/net/netconsole.h -=================================================================== ---- bglio.orig/drivers/net/netconsole.h 2004-05-07 15:50:22.000000000 -0700 -+++ bglio/drivers/net/netconsole.h 2004-05-07 17:11:01.000000000 -0700 -@@ -29,7 +29,7 @@ - * - ****************************************************************/ - --#define NETCONSOLE_VERSION 0x04 -+#define NETCONSOLE_VERSION 0x03 - - enum netdump_commands { - COMM_NONE = 0, -@@ -42,6 +42,8 @@ - COMM_START_NETDUMP_ACK = 7, - COMM_GET_REGS = 8, - COMM_SHOW_STATE = 9, -+ COMM_START_WRITE_NETDUMP_ACK = 10, -+ COMM_SYSRQ = 11, - }; - - #define NETDUMP_REQ_SIZE (8+4*4) -@@ -69,6 +71,7 @@ - REPLY_REGS = 10, - REPLY_MAGIC = 11, - REPLY_SHOW_STATE = 12, -+ REPLY_SYSRQ = 13, - }; - - typedef struct netdump_reply_s { -@@ -78,4 +81,24 @@ - } reply_t; - - #define HEADER_LEN (1 + sizeof(reply_t)) -- -+/* for netconsole */ -+static inline void get_current_regs(struct pt_regs *regs) -+{ -+#ifdef __i386__ -+ __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx)); -+ __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx)); -+ __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx)); -+ __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi)); -+ __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi)); -+ __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp)); -+ __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax)); -+ __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp)); -+ __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss)); -+ __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs)); -+ __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds)); -+ __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes)); -+ __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags)); -+ regs->eip = (unsigned long)current_text_addr(); -+#endif -+} -+ -Index: bglio/arch/i386/kernel/irq.c -=================================================================== ---- bglio.orig/arch/i386/kernel/irq.c 2004-05-07 15:50:17.000000000 -0700 -+++ bglio/arch/i386/kernel/irq.c 2004-05-07 17:11:01.000000000 -0700 -@@ -182,7 +182,20 @@ - - return 0; - } -+struct irqaction *find_irq_action(unsigned int irq, void *dev_id) -+{ -+ struct irqaction *a, *r=0; - -+ spin_lock_irq(&irq_desc[irq].lock); -+ for(a=irq_desc[irq].action; a; a=a->next) { -+ if(a->dev_id == dev_id) { -+ r=a; -+ break; -+ } -+ } -+ spin_unlock_irq(&irq_desc[irq].lock); -+ return r; -+} - - /* - * Global interrupt locks for SMP. Allow interrupts to come in on any -Index: bglio/arch/i386/kernel/i386_ksyms.c -=================================================================== ---- bglio.orig/arch/i386/kernel/i386_ksyms.c 2004-05-07 15:50:22.000000000 -0700 -+++ bglio/arch/i386/kernel/i386_ksyms.c 2004-05-07 17:11:01.000000000 -0700 -@@ -66,6 +66,7 @@ - EXPORT_SYMBOL(iounmap); - EXPORT_SYMBOL(enable_irq); - EXPORT_SYMBOL(disable_irq); -+EXPORT_SYMBOL(find_irq_action); - EXPORT_SYMBOL(disable_irq_nosync); - EXPORT_SYMBOL(probe_irq_mask); - EXPORT_SYMBOL(kernel_thread); -@@ -186,7 +187,6 @@ - EXPORT_SYMBOL(edd); - EXPORT_SYMBOL(eddnr); - #endif -- - EXPORT_SYMBOL_GPL(show_mem); - EXPORT_SYMBOL_GPL(show_state); - EXPORT_SYMBOL_GPL(show_regs); -Index: bglio/net/core/dev.c -=================================================================== ---- bglio.orig/net/core/dev.c 2004-05-07 15:50:22.000000000 -0700 -+++ bglio/net/core/dev.c 2004-05-07 17:11:01.000000000 -0700 -@@ -1476,6 +1476,16 @@ - - skb_bond(skb); - -+ if (unlikely(skb->dev->rx_hook != NULL)) { -+ int ret; -+ -+ ret = skb->dev->rx_hook(skb); -+ if (ret == NET_RX_DROP){ -+ kfree_skb(skb); -+ return ret; -+ } -+ } -+ - netdev_rx_stat[smp_processor_id()].total++; - - #ifdef CONFIG_NET_FASTROUTE -Index: bglio/include/asm-i386/irq.h -=================================================================== ---- bglio.orig/include/asm-i386/irq.h 2004-05-07 15:25:28.000000000 -0700 -+++ bglio/include/asm-i386/irq.h 2004-05-07 17:11:01.000000000 -0700 -@@ -38,7 +38,7 @@ - extern void disable_irq_nosync(unsigned int); - extern void enable_irq(unsigned int); - extern void release_x86_irqs(struct task_struct *); -- -+extern struct irqaction *find_irq_action(unsigned int irq, void *dev_id); - #ifdef CONFIG_X86_LOCAL_APIC - #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ - #endif -Index: bglio/kernel/panic.c -=================================================================== ---- bglio.orig/kernel/panic.c 2004-05-07 15:50:22.000000000 -0700 -+++ bglio/kernel/panic.c 2004-05-07 17:11:01.000000000 -0700 -@@ -66,8 +66,6 @@ - vsprintf(buf, fmt, args); - va_end(args); - printk(KERN_EMERG "Kernel panic: %s\n",buf); -- if (netdump_func) -- BUG(); - if (in_interrupt()) - printk(KERN_EMERG "In interrupt handler - not syncing\n"); - else if (!current->pid) diff --git a/lustre/kernel_patches/patches/nfs-cifs-intent-2.6.12.patch b/lustre/kernel_patches/patches/nfs-cifs-intent-2.6.12.patch deleted file mode 100644 index ff06d68..0000000 --- a/lustre/kernel_patches/patches/nfs-cifs-intent-2.6.12.patch +++ /dev/null @@ -1,128 +0,0 @@ -Index: linux-2.6.12-rc6/fs/nfs/dir.c -=================================================================== ---- linux-2.6.12-rc6.orig/fs/nfs/dir.c 2005-06-14 14:22:14.585699648 +0200 -+++ linux-2.6.12-rc6/fs/nfs/dir.c 2005-06-14 14:26:39.884524523 +0200 -@@ -727,7 +727,7 @@ - return 0; - if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) - return 0; -- return (nd->intent.open.flags & O_EXCL) != 0; -+ return (nd->intent.it_flags & O_EXCL) != 0; - } - - static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) -@@ -783,7 +783,7 @@ - if (nd->flags & LOOKUP_DIRECTORY) - return 0; - /* Are we trying to write to a read only partition? */ -- if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) -+ if (IS_RDONLY(dir) && (nd->intent.it_flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) - return 0; - return 1; - } -@@ -805,7 +805,7 @@ - dentry->d_op = NFS_PROTO(dir)->dentry_ops; - - /* Let vfs_create() deal with O_EXCL */ -- if (nd->intent.open.flags & O_EXCL) -+ if (nd->intent.it_flags & O_EXCL) - goto no_entry; - - /* Open the file on the server */ -@@ -817,7 +817,7 @@ - goto out; - } - -- if (nd->intent.open.flags & O_CREAT) { -+ if (nd->intent.it_flags & O_CREAT) { - nfs_begin_data_update(dir); - inode = nfs4_atomic_open(dir, dentry, nd); - nfs_end_data_update(dir); -@@ -833,7 +833,7 @@ - break; - /* This turned out not to be a regular file */ - case -ELOOP: -- if (!(nd->intent.open.flags & O_NOFOLLOW)) -+ if (!(nd->intent.it_flags & O_NOFOLLOW)) - goto no_open; - /* case -EISDIR: */ - /* case -EINVAL: */ -@@ -874,7 +874,7 @@ - /* NFS only supports OPEN on regular files */ - if (!S_ISREG(inode->i_mode)) - goto no_open; -- openflags = nd->intent.open.flags; -+ openflags = nd->intent.it_flags; - /* We cannot do exclusive creation on a positive dentry */ - if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) - goto no_open; -@@ -1028,7 +1028,7 @@ - attr.ia_valid = ATTR_MODE; - - if (nd && (nd->flags & LOOKUP_CREATE)) -- open_flags = nd->intent.open.flags; -+ open_flags = nd->intent.it_flags; - - lock_kernel(); - nfs_begin_data_update(dir); -Index: linux-2.6.12-rc6/fs/nfs/nfs4proc.c -=================================================================== ---- linux-2.6.12-rc6.orig/fs/nfs/nfs4proc.c 2005-06-06 17:22:29.000000000 +0200 -+++ linux-2.6.12-rc6/fs/nfs/nfs4proc.c 2005-06-14 14:30:18.499756220 +0200 -@@ -877,19 +877,19 @@ - struct nfs4_state *state; - - if (nd->flags & LOOKUP_CREATE) { -- attr.ia_mode = nd->intent.open.create_mode; -+ attr.ia_mode = nd->intent.it_create_mode; - attr.ia_valid = ATTR_MODE; - if (!IS_POSIXACL(dir)) - attr.ia_mode &= ~current->fs->umask; - } else { - attr.ia_valid = 0; -- BUG_ON(nd->intent.open.flags & O_CREAT); -+ BUG_ON(nd->intent.it_flags & O_CREAT); - } - - cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); - if (IS_ERR(cred)) - return (struct inode *)cred; -- state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); -+ state = nfs4_do_open(dir, dentry, nd->intent.it_flags, &attr, cred); - put_rpccred(cred); - if (IS_ERR(state)) - return (struct inode *)state; -Index: linux-2.6.12-rc6/fs/cifs/dir.c -=================================================================== ---- linux-2.6.12-rc6.orig/fs/cifs/dir.c 2005-06-06 17:22:29.000000000 +0200 -+++ linux-2.6.12-rc6/fs/cifs/dir.c 2005-06-14 14:26:39.915774522 +0200 -@@ -146,23 +146,23 @@ - } - - if(nd) { -- if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY) -+ if ((nd->intent.it_flags & O_ACCMODE) == O_RDONLY) - desiredAccess = GENERIC_READ; -- else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) { -+ else if ((nd->intent.it_flags & O_ACCMODE) == O_WRONLY) { - desiredAccess = GENERIC_WRITE; - write_only = TRUE; -- } else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) { -+ } else if ((nd->intent.it_flags & O_ACCMODE) == O_RDWR) { - /* GENERIC_ALL is too much permission to request */ - /* can cause unnecessary access denied on create */ - /* desiredAccess = GENERIC_ALL; */ - desiredAccess = GENERIC_READ | GENERIC_WRITE; - } - -- if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) -+ if((nd->intent.it_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) - disposition = FILE_CREATE; -- else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) -+ else if((nd->intent.it_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) - disposition = FILE_OVERWRITE_IF; -- else if((nd->intent.open.flags & O_CREAT) == O_CREAT) -+ else if((nd->intent.it_flags & O_CREAT) == O_CREAT) - disposition = FILE_OPEN_IF; - else { - cFYI(1,("Create flag not set in create function")); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch deleted file mode 100644 index be3c31a..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.20-hp.patch +++ /dev/null @@ -1,740 +0,0 @@ - fs/Makefile | 3 - fs/file_table.c | 11 ++ - fs/inode.c | 23 ++++- - fs/namei.c | 12 ++ - fs/nfsd/export.c | 5 + - fs/nfsd/nfsfh.c | 65 +++++++++++++- - fs/nfsd/vfs.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++----- - include/linux/fs.h | 10 ++ - kernel/ksyms.c | 2 - 9 files changed, 337 insertions(+), 34 deletions(-) - ---- linux-2.4.20-hp4-pnnl13/fs/file_table.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/file_table.c 2003-10-08 10:54:08.000000000 +0400 -@@ -82,7 +82,8 @@ struct file * get_empty_filp(void) - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. - */ --int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - memset(filp, 0, sizeof(*filp)); - filp->f_mode = mode; -@@ -90,12 +91,20 @@ int init_private_file(struct file *filp, - filp->f_dentry = dentry; - filp->f_uid = current->fsuid; - filp->f_gid = current->fsgid; -+ if (it) -+ filp->f_it = it; - filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; - } -+EXPORT_SYMBOL(init_private_file_it); -+ -+int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+{ -+ return init_private_file_it(filp, dentry, mode, NULL); -+} - - void fput(struct file * file) - { ---- linux-2.4.20-hp4-pnnl13/fs/inode.c~nfs_export_kernel-2.4.20-hp 2003-09-14 17:34:20.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/inode.c 2003-10-08 11:38:11.000000000 +0400 -@@ -964,9 +964,10 @@ struct inode *igrab(struct inode *inode) - return inode; - } - --struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) -+struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) - { -- struct list_head * head = inode_hashtable + hash(sb,ino); - struct inode * inode; - - spin_lock(&inode_lock); -@@ -979,6 +980,24 @@ struct inode *iget4_locked(struct super_ - } - spin_unlock(&inode_lock); - -+ return NULL; -+} -+ -+struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ return ifind(sb, ino, head, find_actor, opaque); -+} -+ -+struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque); -+ if (inode) -+ return inode; -+ - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. ---- linux-2.4.20-hp4-pnnl13/fs/Makefile~nfs_export_kernel-2.4.20-hp 2003-09-14 17:34:22.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/Makefile 2003-10-08 10:54:37.000000000 +0400 -@@ -7,7 +7,8 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \ -+ namei.o file_table.o - mod-subdirs := nls xfs - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ ---- linux-2.4.20-hp4-pnnl13/fs/namei.c~nfs_export_kernel-2.4.20-hp 2003-09-14 17:34:20.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/namei.c 2003-10-08 10:54:08.000000000 +0400 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -100,6 +101,7 @@ void intent_release(struct lookup_intent - it->it_op_release(it); - - } -+EXPORT_SYMBOL(intent_release); - - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the -@@ -917,7 +919,8 @@ struct dentry * lookup_hash(struct qstr - - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) - { - unsigned long hash; - struct qstr this; -@@ -937,11 +940,16 @@ struct dentry * lookup_one_len(const cha - } - this.hash = end_name_hash(hash); - -- return lookup_hash_it(&this, base, NULL); -+ return lookup_hash_it(&this, base, it); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * ---- linux-2.4.20-hp4-pnnl13/fs/nfsd/export.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/export.c 2003-10-08 10:54:08.000000000 +0400 -@@ -222,6 +222,11 @@ exp_export(struct nfsctl_export *nxp) - inode = nd.dentry->d_inode; - dev = inode->i_dev; - ino = inode->i_ino; -+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && -+ !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; -+ } - err = -EINVAL; - - exp = exp_get(clp, dev, ino); ---- linux-2.4.20-hp4-pnnl13/fs/nfsd/nfsfh.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/nfsfh.c 2003-10-08 10:54:08.000000000 +0400 -@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { - int sequence; /* sequence counter */ - }; - -+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) -+{ -+ if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ return inode->i_op->lookup(inode, dentry); -+} -+ - /* - * A rather strange filldir function to capture - * the name matching the specified inode number. -@@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry * - int error; - struct file file; - struct nfsd_getdents_callback buffer; -+ struct lookup_intent it; -+ struct file *filp = NULL; - - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry * - /* - * Open the directory ... - */ -- error = init_private_file(&file, dentry, FMODE_READ); -- if (error) -+ if (dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && -+ (dentry->d_parent == dentry) ) { -+ it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulate init_private_file without -+ * f_op->open for disconnected dentry as we don't have -+ * actual dentry->d_name to revalidate in revalidate_it() -+ */ -+ filp = &file; -+ memset(filp, 0, sizeof(*filp)); -+ filp->f_mode = FMODE_READ; -+ atomic_set(&filp->f_count, 1); -+ filp->f_dentry = dentry; -+ filp->f_uid = current->fsuid; -+ filp->f_gid = current->fsgid; -+ filp->f_op = dentry->d_inode->i_fop; -+ error = 0; -+ } else { -+ intent_init(&it, IT_OPEN, FMODE_READ); -+ error = revalidate_it(dentry, &it); -+ if (error) -+ goto out; -+ error = init_private_file_it(&file, dentry, FMODE_READ, &it); -+ } -+ } else { -+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL); -+ } -+ if (error) - goto out; -+ - error = -EINVAL; - if (!file.f_op->readdir) - goto out_close; -@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * - } - - out_close: -- if (file.f_op->release) -+ if (file.f_op->release && !filp) - file.f_op->release(dir, &file); - out: -+ if (dentry->d_op && dentry->d_op->d_revalidate_it && -+ it.it_op_release && !filp) -+ intent_release(&it); - return error; - } - -@@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de - * it is well connected. But nobody returns different dentrys do they? - */ - down(&child->d_inode->i_sem); -- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); -+ pdentry = lookup_it(child->d_inode, tdentry); - up(&child->d_inode->i_sem); - d_drop(tdentry); /* we never want ".." hashed */ - if (!pdentry && tdentry->d_inode == NULL) { -@@ -306,6 +349,8 @@ struct dentry *nfsd_findparent(struct de - igrab(tdentry->d_inode); - pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - } -+ if (child->d_op && child->d_op->d_revalidate_it) -+ pdentry->d_op = child->d_op; - } - if (pdentry == NULL) - pdentry = ERR_PTR(-ENOMEM); -@@ -463,6 +508,8 @@ find_fh_dentry(struct super_block *sb, _ - struct dentry *pdentry; - struct inode *parent; - -+ if (result->d_op && result->d_op->d_revalidate_it) -+ dentry->d_op = result->d_op; - pdentry = nfsd_findparent(dentry); - err = PTR_ERR(pdentry); - if (IS_ERR(pdentry)) -@@ -662,6 +709,10 @@ fh_verify(struct svc_rqst *rqstp, struct - - inode = dentry->d_inode; - -+ /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) -+ inode->i_op->revalidate_it(dentry, NULL); -+ - /* Type check. The correct error return for type mismatches - * does not seem to be generally agreed upon. SunOS seems to - * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -900,8 +952,9 @@ out_negative: - dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - out_uptodate: -- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -- dentry->d_parent->d_name.name, dentry->d_name.name); -+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) -+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - } - ---- linux-2.4.20-hp4-pnnl13/fs/nfsd/vfs.c~nfs_export_kernel-2.4.20-hp 2002-11-29 02:53:15.000000000 +0300 -+++ linux-2.4.20-hp4-pnnl13-alexey/fs/nfsd/vfs.c 2003-10-08 10:54:08.000000000 +0400 -@@ -77,6 +77,130 @@ struct raparms { - static struct raparms * raparml; - static struct raparms * raparm_cache; - -+static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = dold }; -+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->link_raw(&old_nd, &nd); -+ igrab(dold->d_inode); -+ d_instantiate(dnew, dold->d_inode); -+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) -+ dold->d_inode->i_op->revalidate_it(dnew, NULL); -+ -+ return err; -+} -+ -+static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->unlink_raw(&nd); -+ if (!err) -+ d_delete(rdentry); -+ -+ return err; -+} -+ -+static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->rmdir_raw(&nd); -+ if (!err) { -+ rdentry->d_inode->i_flags |= S_DEAD; -+ d_delete(rdentry); -+ } -+ -+ return err; -+} -+ -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->symlink_raw(&nd, path); -+ -+ return err; -+} -+ -+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mkdir_raw(&nd, mode); -+ -+ return err; -+} -+ -+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mknod_raw(&nd, mode, dev); -+ -+ return err; -+} -+ -+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name}; -+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name}; -+ struct inode_operations *op = old_nd.dentry->d_inode->i_op; -+ err = op->rename_raw(&old_nd, &new_nd); -+ d_move(odentry, ndentry); -+ -+ return err; -+} -+ -+#ifndef O_OWNER_OVERRIDE -+#define O_OWNER_OVERRIDE 0200000000 -+#endif -+static int setattr_raw(struct inode *inode, struct iattr *iap) -+{ -+ int err; -+ -+ iap->ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, iap); -+ -+ return err; -+} -+ -+int revalidate_it(struct dentry *dentry, struct lookup_intent *it) -+{ -+ int err = 0; -+ -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) && -+ !d_invalidate(dentry)) { -+ err = -EINVAL; -+ return err; -+ } -+ } -+ -+ return err; -+} -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -300,7 +422,12 @@ nfsd_setattr(struct svc_rqst *rqstp, str - } - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime) { -- err = notify_change(dentry, iap); -+ if (dentry->d_inode->i_op &&dentry->d_inode->i_op->setattr_raw){ -+ if (accmode & MAY_OWNER_OVERRIDE) -+ iap->ia_valid & O_OWNER_OVERRIDE; -+ err = setattr_raw(dentry->d_inode, iap); -+ } else -+ err = notify_change(dentry, iap); - err = nfserrno(err); - } - if (size_change) { -@@ -427,6 +552,7 @@ nfsd_open(struct svc_rqst *rqstp, struct - { - struct dentry *dentry; - struct inode *inode; -+ struct lookup_intent it; - int err; - - /* If we get here, then the client has already done an "open", and (hopefully) -@@ -473,6 +599,15 @@ nfsd_open(struct svc_rqst *rqstp, struct - filp->f_mode = FMODE_READ; - } - -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | -+ O_OWNER_OVERRIDE); -+ -+ err = revalidate_it(dentry, &it); -+ if (err) -+ goto out_nfserr; -+ -+ filp->f_it = ⁢ -+ - err = 0; - if (filp->f_op && filp->f_op->open) { - err = filp->f_op->open(inode, filp); -@@ -487,6 +621,9 @@ nfsd_open(struct svc_rqst *rqstp, struct - } - } - out_nfserr: -+ if (it.it_op_release) -+ intent_release(&it); -+ - if (err) - err = nfserrno(err); - out: -@@ -818,7 +956,7 @@ nfsd_create(struct svc_rqst *rqstp, stru - { - struct dentry *dentry, *dchild; - struct inode *dirp; -- int err; -+ int err, error = -EOPNOTSUPP; - - err = nfserr_perm; - if (!flen) -@@ -834,20 +972,47 @@ nfsd_create(struct svc_rqst *rqstp, stru - dentry = fhp->fh_dentry; - dirp = dentry->d_inode; - -+ switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); -+ } -+ if (error && error != -EOPNOTSUPP) { -+ err = error; -+ goto out_nfserr; -+ } -+ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - /* - * Check whether the response file handle has been verified yet. - * If it has, the parent directory should already be locked. - */ -- if (!resfhp->fh_dentry) { -- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ -- fh_lock(fhp); -+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { -+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ * and nfsd_proc_create in case of lustre */ -+ if (!resfhp->fh_dentry) -+ fh_lock(fhp); - dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); - if (IS_ERR(dchild)) - goto out_nfserr; -+ resfhp->fh_dentry = NULL; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); - if (err) - goto out; -@@ -868,10 +1030,12 @@ nfsd_create(struct svc_rqst *rqstp, stru - * Make sure the child dentry is still negative ... - */ - err = nfserr_exist; -- if (dchild->d_inode) { -- dprintk("nfsd_create: dentry %s/%s not negative!\n", -- dentry->d_name.name, dchild->d_name.name); -- goto out; -+ if (error == -EOPNOTSUPP) { -+ if (dchild->d_inode) { -+ dprintk("nfsd_create: dentry %s/%s not negative!\n", -+ dentry->d_name.name, dchild->d_name.name); -+ goto out; -+ } - } - - if (!(iap->ia_valid & ATTR_MODE)) -@@ -884,16 +1048,19 @@ nfsd_create(struct svc_rqst *rqstp, stru - err = nfserr_perm; - switch (type) { - case S_IFREG: -- err = vfs_create(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_create(dirp, dchild, iap->ia_mode); - break; - case S_IFDIR: -- err = vfs_mkdir(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mkdir(dirp, dchild, iap->ia_mode); - break; - case S_IFCHR: - case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: -- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); - break; - default: - printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -962,7 +1129,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s - /* Get all the sanity checks out of the way before - * we lock the parent. */ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (dirp->i_op->mknod_raw) { -+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); -+ if (err && err != -EOPNOTSUPP) -+ goto out_nfserr; -+ } -+ -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - fh_lock(fhp); - -@@ -1013,6 +1186,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s - case NFS3_CREATE_GUARDED: - err = nfserr_exist; - } -+ if (dirp->i_op->mknod_raw) -+ err = 0; - goto out; - } - -@@ -1119,7 +1294,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str - struct iattr *iap) - { - struct dentry *dentry, *dnew; -- int err, cerr; -+ int err, cerr, error = -EOPNOTSUPP; - - err = nfserr_noent; - if (!flen || !plen) -@@ -1133,12 +1308,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str - goto out; - fh_lock(fhp); - dentry = fhp->fh_dentry; -+ -+ if (dentry->d_inode->i_op->symlink_raw) -+ error = symlink_raw(dentry, fname, flen, path); -+ - dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); - if (IS_ERR(dnew)) - goto out_nfserr; - -- err = vfs_symlink(dentry->d_inode, dnew, path); -+ err = error; -+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw) -+ err = vfs_symlink(dentry->d_inode, dnew, path); - if (!err) { - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); -@@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str - iap->ia_valid |= ATTR_CTIME; - iap->ia_mode = (iap->ia_mode&S_IALLUGO) - | S_IFLNK; -- err = notify_change(dnew, iap); -+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dnew->d_inode, iap); -+ else -+ err = notify_change(dnew, iap); - if (!err && EX_ISSYNC(fhp->fh_export)) - write_inode_now(dentry->d_inode, 1); - } -@@ -1206,7 +1390,10 @@ nfsd_link(struct svc_rqst *rqstp, struct - dold = tfhp->fh_dentry; - dest = dold->d_inode; - -- err = vfs_link(dold, dirp, dnew); -+ if (dirp->i_op->link_raw) -+ err = link_raw(dold, ddir, dnew); -+ else -+ err = vfs_link(dold, dirp, dnew); - if (!err) { - if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); -@@ -1291,7 +1478,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if (fdir->i_op->rename_raw) -+ err = rename_raw(fdentry, tdentry, odentry, ndentry); -+ else -+ err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); -@@ -1312,7 +1502,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru - fill_post_wcc(tfhp); - double_up(&tdir->i_sem, &fdir->i_sem); - ffhp->fh_locked = tfhp->fh_locked = 0; -- -+ - out: - return err; - } -@@ -1358,9 +1548,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru - err = nfserr_perm; - } else - #endif -- err = vfs_unlink(dirp, rdentry); -+ if (dirp->i_op->unlink_raw) -+ err = unlink_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_unlink(dirp, rdentry); - } else { /* It's RMDIR */ -- err = vfs_rmdir(dirp, rdentry); -+ if (dirp->i_op->rmdir_raw) -+ err = rmdir_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_rmdir(dirp, rdentry); - } - - dput(rdentry); ---- linux-2.4.20-hp4-pnnl13/include/linux/fs.h~nfs_export_kernel-2.4.20-hp 2003-09-14 17:34:24.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/include/linux/fs.h 2003-10-08 11:39:07.000000000 +0400 -@@ -93,6 +93,8 @@ extern int leases_enable, dir_notify_ena - #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ - #define FS_NOMOUNT 16 /* Never mount from userland */ - #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. */ - #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon - * as nfs_rename() will be cleaned up - */ -@@ -1116,6 +1119,9 @@ extern int open_namei_it(const char *fil - struct nameidata *nd, struct lookup_intent *it); - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); -+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1386,6 +1392,8 @@ extern void path_release(struct nameidat - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1403,6 +1411,8 @@ typedef int (*find_inode_t)(struct inode - - extern struct inode * iget4_locked(struct super_block *, unsigned long, - find_inode_t, void *); -+extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); - - static inline struct inode *iget4(struct super_block *sb, unsigned long ino, - find_inode_t find_actor, void *opaque) ---- linux-2.4.20-hp4-pnnl13/kernel/ksyms.c~nfs_export_kernel-2.4.20-hp 2003-09-14 17:34:22.000000000 +0400 -+++ linux-2.4.20-hp4-pnnl13-alexey/kernel/ksyms.c 2003-10-08 11:39:42.000000000 +0400 -@@ -169,6 +169,7 @@ EXPORT_SYMBOL(fget); - EXPORT_SYMBOL(igrab); - EXPORT_SYMBOL(iunique); - EXPORT_SYMBOL(iget4_locked); -+EXPORT_SYMBOL(ilookup4); - EXPORT_SYMBOL(unlock_new_inode); - EXPORT_SYMBOL(iput); - EXPORT_SYMBOL(inode_init_once); -@@ -181,6 +182,7 @@ EXPORT_SYMBOL(path_walk); - EXPORT_SYMBOL(path_release); - EXPORT_SYMBOL(__user_walk); - EXPORT_SYMBOL(lookup_one_len); -+EXPORT_SYMBOL(lookup_one_len_it); - EXPORT_SYMBOL(lookup_hash); - EXPORT_SYMBOL(sys_close); - EXPORT_SYMBOL(dcache_lock); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch deleted file mode 100644 index db293ca..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-chaos.patch +++ /dev/null @@ -1,756 +0,0 @@ - fs/Makefile | 3 - fs/file_table.c | 11 ++ - fs/inode.c | 23 ++++- - fs/namei.c | 12 ++ - fs/nfsd/export.c | 5 + - fs/nfsd/nfsfh.c | 65 +++++++++++++- - fs/nfsd/vfs.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++----- - include/linux/fs.h | 11 ++ - kernel/ksyms.c | 2 - 9 files changed, 333 insertions(+), 34 deletions(-) - -Index: linux-2.4.21-chaos/fs/file_table.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/file_table.c 2003-07-15 04:41:00.000000000 +0400 -+++ linux-2.4.21-chaos/fs/file_table.c 2003-12-12 16:19:25.000000000 +0300 -@@ -82,7 +82,8 @@ struct file * get_empty_filp(void) - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. - */ --int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - memset(filp, 0, sizeof(*filp)); - filp->f_mode = mode; -@@ -90,12 +91,20 @@ int init_private_file(struct file *filp, - filp->f_dentry = dentry; - filp->f_uid = current->fsuid; - filp->f_gid = current->fsgid; -+ if (it) -+ filp->f_it = it; - filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; - } -+EXPORT_SYMBOL(init_private_file_it); -+ -+int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+{ -+ return init_private_file_it(filp, dentry, mode, NULL); -+} - - void fput(struct file * file) - { -Index: linux-2.4.21-chaos/fs/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/inode.c 2003-12-12 16:18:15.000000000 +0300 -+++ linux-2.4.21-chaos/fs/inode.c 2003-12-12 16:19:25.000000000 +0300 -@@ -1054,9 +1054,10 @@ struct inode *igrab(struct inode *inode) - return inode; - } - --struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) -+struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) - { -- struct list_head * head = inode_hashtable + hash(sb,ino); - struct inode * inode; - - spin_lock(&inode_lock); -@@ -1069,6 +1070,24 @@ struct inode *iget4_locked(struct super_ - } - spin_unlock(&inode_lock); - -+ return NULL; -+} -+ -+struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ return ifind(sb, ino, head, find_actor, opaque); -+} -+ -+struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque); -+ if (inode) -+ return inode; -+ - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. -Index: linux-2.4.21-chaos/fs/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/Makefile 2003-12-12 16:18:36.000000000 +0300 -+++ linux-2.4.21-chaos/fs/Makefile 2003-12-12 16:19:25.000000000 +0300 -@@ -9,7 +9,8 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o dcookies.o inode.o \ -+ namei.o file_table.o - mod-subdirs := nls - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.21-chaos/fs/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/namei.c 2003-12-12 16:18:06.000000000 +0300 -+++ linux-2.4.21-chaos/fs/namei.c 2003-12-12 16:19:25.000000000 +0300 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -100,6 +101,7 @@ void intent_release(struct lookup_intent - it->it_op_release(it); - - } -+EXPORT_SYMBOL(intent_release); - - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the -@@ -910,7 +912,8 @@ struct dentry * lookup_hash(struct qstr - - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) - { - unsigned long hash; - struct qstr this; -@@ -930,11 +933,16 @@ struct dentry * lookup_one_len(const cha - } - this.hash = end_name_hash(hash); - -- return lookup_hash_it(&this, base, NULL); -+ return lookup_hash_it(&this, base, it); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * -Index: linux-2.4.21-chaos/fs/nfsd/export.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/nfsd/export.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/nfsd/export.c 2003-12-12 16:19:25.000000000 +0300 -@@ -223,6 +223,11 @@ exp_export(struct nfsctl_export *nxp) - inode = nd.dentry->d_inode; - dev = inode->i_dev; - ino = inode->i_ino; -+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && -+ !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; -+ } - err = -EINVAL; - - exp = exp_get(clp, dev, ino); -Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/nfsd/nfsfh.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/nfsd/nfsfh.c 2003-12-12 16:19:25.000000000 +0300 -@@ -36,6 +36,13 @@ struct nfsd_getdents_callback { - int sequence; /* sequence counter */ - }; - -+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) -+{ -+ if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ return inode->i_op->lookup(inode, dentry); -+} -+ - /* - * A rather strange filldir function to capture - * the name matching the specified inode number. -@@ -75,6 +84,8 @@ static int nfsd_get_name(struct dentry * - int error; - struct file file; - struct nfsd_getdents_callback buffer; -+ struct lookup_intent it; -+ struct file *filp = NULL; - - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +96,37 @@ static int nfsd_get_name(struct dentry * - /* - * Open the directory ... - */ -- error = init_private_file(&file, dentry, FMODE_READ); -- if (error) -+ if (dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && -+ (dentry->d_parent == dentry) ) { -+ it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulate init_private_file without -+ * f_op->open for disconnected dentry as we don't have -+ * actual dentry->d_name to revalidate in revalidate_it() -+ */ -+ filp = &file; -+ memset(filp, 0, sizeof(*filp)); -+ filp->f_mode = FMODE_READ; -+ atomic_set(&filp->f_count, 1); -+ filp->f_dentry = dentry; -+ filp->f_uid = current->fsuid; -+ filp->f_gid = current->fsgid; -+ filp->f_op = dentry->d_inode->i_fop; -+ error = 0; -+ } else { -+ intent_init(&it, IT_OPEN, FMODE_READ); -+ error = revalidate_it(dentry, &it); -+ if (error) -+ goto out; -+ error = init_private_file_it(&file, dentry, FMODE_READ, &it); -+ } -+ } else { -+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL); -+ } -+ if (error) - goto out; -+ - error = -EINVAL; - if (!file.f_op->readdir) - goto out_close; -@@ -113,9 +152,12 @@ static int nfsd_get_name(struct dentry * - } - - out_close: -- if (file.f_op->release) -+ if (file.f_op->release && !filp) - file.f_op->release(dir, &file); - out: -+ if (dentry->d_op && dentry->d_op->d_revalidate_it && -+ it.it_op_release && !filp) -+ intent_release(&it); - return error; - } - -@@ -274,7 +317,7 @@ struct dentry *nfsd_findparent(struct de - * it is well connected. But nobody returns different dentrys do they? - */ - down(&child->d_inode->i_sem); -- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); -+ pdentry = lookup_it(child->d_inode, tdentry); - up(&child->d_inode->i_sem); - d_drop(tdentry); /* we never want ".." hashed */ - if (!pdentry && tdentry->d_inode == NULL) { -@@ -306,6 +350,8 @@ struct dentry *nfsd_findparent(struct de - pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - pdentry->d_op = child->d_op; - } -+ if (child->d_op && child->d_op->d_revalidate_it) -+ pdentry->d_op = child->d_op; - } - if (pdentry == NULL) - pdentry = ERR_PTR(-ENOMEM); -@@ -464,6 +509,8 @@ find_fh_dentry(struct super_block *sb, _ - struct dentry *pdentry; - struct inode *parent; - -+ if (result->d_op && result->d_op->d_revalidate_it) -+ dentry->d_op = result->d_op; - pdentry = nfsd_findparent(dentry); - err = PTR_ERR(pdentry); - if (IS_ERR(pdentry)) -@@ -672,6 +719,10 @@ fh_verify(struct svc_rqst *rqstp, struct - - inode = dentry->d_inode; - -+ /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) -+ inode->i_op->revalidate_it(dentry, NULL); -+ - /* Type check. The correct error return for type mismatches - * does not seem to be generally agreed upon. SunOS seems to - * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -905,8 +957,9 @@ out_negative: - dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - out_uptodate: -- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -- dentry->d_parent->d_name.name, dentry->d_name.name); -+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) -+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - } - -Index: linux-2.4.21-chaos/fs/nfsd/vfs.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/nfsd/vfs.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/nfsd/vfs.c 2003-12-12 16:19:25.000000000 +0300 -@@ -78,6 +78,127 @@ - static struct raparms * raparml; - static struct raparms * raparm_cache; - -+static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = dold }; -+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->link_raw(&old_nd, &nd); -+ igrab(dold->d_inode); -+ d_instantiate(dnew, dold->d_inode); -+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) -+ dold->d_inode->i_op->revalidate_it(dnew, NULL); -+ -+ return err; -+} -+ -+static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->unlink_raw(&nd); -+ if (!err) -+ d_delete(rdentry); -+ -+ return err; -+} -+ -+static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->rmdir_raw(&nd); -+ if (!err) { -+ rdentry->d_inode->i_flags |= S_DEAD; -+ d_delete(rdentry); -+ } -+ -+ return err; -+} -+ -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->symlink_raw(&nd, path); -+ -+ return err; -+} -+ -+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mkdir_raw(&nd, mode); -+ -+ return err; -+} -+ -+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mknod_raw(&nd, mode, dev); -+ -+ return err; -+} -+ -+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name}; -+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name}; -+ struct inode_operations *op = old_nd.dentry->d_inode->i_op; -+ err = op->rename_raw(&old_nd, &new_nd); -+ d_move(odentry, ndentry); -+ -+ return err; -+} -+ -+static int setattr_raw(struct inode *inode, struct iattr *iap) -+{ -+ int err; -+ -+ iap->ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, iap); -+ -+ return err; -+} -+ -+int revalidate_it(struct dentry *dentry, struct lookup_intent *it) -+{ -+ int err = 0; -+ -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) && -+ !d_invalidate(dentry)) { -+ err = -EINVAL; -+ return err; -+ } -+ } -+ -+ return err; -+} -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -303,7 +425,10 @@ nfsd_setattr(struct svc_rqst *rqstp, str - } - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime) { -- err = notify_change(dentry, iap); -+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dentry->d_inode, iap); -+ else -+ err = notify_change(dentry, iap); - err = nfserrno(err); - } - if (size_change) { -@@ -430,6 +555,7 @@ nfsd_open(struct svc_rqst *rqstp, struct - { - struct dentry *dentry; - struct inode *inode; -+ struct lookup_intent it; - int err; - - /* If we get here, then the client has already done an "open", and (hopefully) -@@ -476,6 +602,18 @@ nfsd_open(struct svc_rqst *rqstp, struct - filp->f_mode = FMODE_READ; - } - -+#ifndef O_OWNER_OVERRIDE -+#define O_OWNER_OVERRIDE 0200000000 -+#endif -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | -+ O_OWNER_OVERRIDE); -+ -+ err = revalidate_it(dentry, &it); -+ if (err) -+ goto out_nfserr; -+ -+ filp->f_it = ⁢ -+ - err = 0; - if (filp->f_op && filp->f_op->open) { - err = filp->f_op->open(inode, filp); -@@ -490,6 +624,9 @@ nfsd_open(struct svc_rqst *rqstp, struct - } - } - out_nfserr: -+ if (it.it_op_release) -+ intent_release(&it); -+ - if (err) - err = nfserrno(err); - out: -@@ -821,7 +959,7 @@ nfsd_create(struct svc_rqst *rqstp, stru - { - struct dentry *dentry, *dchild; - struct inode *dirp; -- int err; -+ int err, error = -EOPNOTSUPP; - - err = nfserr_perm; - if (!flen) -@@ -837,20 +975,47 @@ nfsd_create(struct svc_rqst *rqstp, stru - dentry = fhp->fh_dentry; - dirp = dentry->d_inode; - -+ switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); -+ } -+ if (error && error != -EOPNOTSUPP) { -+ err = error; -+ goto out_nfserr; -+ } -+ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - /* - * Check whether the response file handle has been verified yet. - * If it has, the parent directory should already be locked. - */ -- if (!resfhp->fh_dentry) { -- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ -- fh_lock(fhp); -+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { -+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ * and nfsd_proc_create in case of lustre */ -+ if (!resfhp->fh_dentry) -+ fh_lock(fhp); - dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); - if (IS_ERR(dchild)) - goto out_nfserr; -+ resfhp->fh_dentry = NULL; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); - if (err) - goto out; -@@ -871,10 +1033,12 @@ nfsd_create(struct svc_rqst *rqstp, stru - * Make sure the child dentry is still negative ... - */ - err = nfserr_exist; -- if (dchild->d_inode) { -- dprintk("nfsd_create: dentry %s/%s not negative!\n", -- dentry->d_name.name, dchild->d_name.name); -- goto out; -+ if (error == -EOPNOTSUPP) { -+ if (dchild->d_inode) { -+ dprintk("nfsd_create: dentry %s/%s not negative!\n", -+ dentry->d_name.name, dchild->d_name.name); -+ goto out; -+ } - } - - if (!(iap->ia_valid & ATTR_MODE)) -@@ -887,16 +1051,19 @@ nfsd_create(struct svc_rqst *rqstp, stru - err = nfserr_perm; - switch (type) { - case S_IFREG: -- err = vfs_create(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_create(dirp, dchild, iap->ia_mode); - break; - case S_IFDIR: -- err = vfs_mkdir(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mkdir(dirp, dchild, iap->ia_mode); - break; - case S_IFCHR: - case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: -- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); - break; - default: - printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -965,7 +1132,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s - /* Get all the sanity checks out of the way before - * we lock the parent. */ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (dirp->i_op->mknod_raw) { -+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); -+ if (err && err != -EOPNOTSUPP) -+ goto out_nfserr; -+ } -+ -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - fh_lock(fhp); - -@@ -1016,6 +1189,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s - case NFS3_CREATE_GUARDED: - err = nfserr_exist; - } -+ if (dirp->i_op->mknod_raw) -+ err = 0; - goto out; - } - -@@ -1122,7 +1297,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str - struct iattr *iap) - { - struct dentry *dentry, *dnew; -- int err, cerr; -+ int err, cerr, error = -EOPNOTSUPP; - - err = nfserr_noent; - if (!flen || !plen) -@@ -1136,12 +1311,18 @@ nfsd_symlink(struct svc_rqst *rqstp, str - goto out; - fh_lock(fhp); - dentry = fhp->fh_dentry; -+ -+ if (dentry->d_inode->i_op->symlink_raw) -+ error = symlink_raw(dentry, fname, flen, path); -+ - dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); - if (IS_ERR(dnew)) - goto out_nfserr; - -- err = vfs_symlink(dentry->d_inode, dnew, path); -+ err = error; -+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw) -+ err = vfs_symlink(dentry->d_inode, dnew, path); - if (!err) { - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); -@@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str - iap->ia_valid |= ATTR_CTIME; - iap->ia_mode = (iap->ia_mode&S_IALLUGO) - | S_IFLNK; -- err = notify_change(dnew, iap); -+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dnew->d_inode, iap); -+ else -+ err = notify_change(dnew, iap); - if (err) - err = nfserrno(err); - else if (EX_ISSYNC(fhp->fh_export)) -@@ -1211,7 +1392,10 @@ nfsd_link(struct svc_rqst *rqstp, struct - dold = tfhp->fh_dentry; - dest = dold->d_inode; - -- err = vfs_link(dold, dirp, dnew); -+ if (dirp->i_op->link_raw) -+ err = link_raw(dold, ddir, dnew); -+ else -+ err = vfs_link(dold, dirp, dnew); - if (!err) { - if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); -@@ -1296,7 +1480,10 @@ nfsd_rename(struct svc_rqst *rqstp, stru - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if (fdir->i_op->rename_raw) -+ err = rename_raw(fdentry, tdentry, odentry, ndentry); -+ else -+ err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); -@@ -1317,7 +1504,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru - fill_post_wcc(tfhp); - double_up(&tdir->i_sem, &fdir->i_sem); - ffhp->fh_locked = tfhp->fh_locked = 0; -- -+ - out: - return err; - } -@@ -1363,9 +1550,15 @@ nfsd_unlink(struct svc_rqst *rqstp, stru - err = nfserr_perm; - } else - #endif -- err = vfs_unlink(dirp, rdentry); -+ if (dirp->i_op->unlink_raw) -+ err = unlink_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_unlink(dirp, rdentry); - } else { /* It's RMDIR */ -- err = vfs_rmdir(dirp, rdentry); -+ if (dirp->i_op->rmdir_raw) -+ err = rmdir_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_rmdir(dirp, rdentry); - } - - dput(rdentry); -Index: linux-2.4.21-chaos/include/linux/fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/fs.h 2003-12-12 16:19:23.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/fs.h 2003-12-12 16:19:25.000000000 +0300 -@@ -93,6 +93,8 @@ - #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ - #define FS_NOMOUNT 16 /* Never mount from userland */ - #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. */ - #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon - * as nfs_rename() will be cleaned up - */ -@@ -1159,6 +1162,9 @@ extern int open_namei_it(const char *fil - struct nameidata *nd, struct lookup_intent *it); - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); -+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1458,6 +1464,8 @@ extern void path_release(struct nameidat - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1477,6 +1485,8 @@ typedef int (*find_inode_t)(struct inode - - extern struct inode * iget4_locked(struct super_block *, unsigned long, - find_inode_t, void *); -+extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); - - static inline struct inode *iget4(struct super_block *sb, unsigned long ino, - find_inode_t find_actor, void *opaque) -Index: linux-2.4.21-chaos/kernel/ksyms.c -=================================================================== ---- linux-2.4.21-chaos.orig/kernel/ksyms.c 2003-12-12 16:18:36.000000000 +0300 -+++ linux-2.4.21-chaos/kernel/ksyms.c 2003-12-12 16:19:25.000000000 +0300 -@@ -178,6 +178,7 @@ EXPORT_SYMBOL(fget); - EXPORT_SYMBOL(igrab); - EXPORT_SYMBOL(iunique); - EXPORT_SYMBOL(iget4_locked); -+EXPORT_SYMBOL(ilookup4); - EXPORT_SYMBOL(unlock_new_inode); - EXPORT_SYMBOL(iput); - EXPORT_SYMBOL(inode_init_once); -@@ -191,6 +192,7 @@ EXPORT_SYMBOL(path_walk); - EXPORT_SYMBOL(path_release); - EXPORT_SYMBOL(__user_walk); - EXPORT_SYMBOL(lookup_one_len); -+EXPORT_SYMBOL(lookup_one_len_it); - EXPORT_SYMBOL(lookup_hash); - - EXPORT_SYMBOL(sys_close); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch deleted file mode 100644 index 74744ec..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.21-suse2.patch +++ /dev/null @@ -1,756 +0,0 @@ - fs/Makefile | 3 - fs/file_table.c | 11 ++ - fs/inode.c | 23 ++++- - fs/namei.c | 12 ++ - fs/nfsd/export.c | 5 + - fs/nfsd/nfsfh.c | 65 +++++++++++++- - fs/nfsd/vfs.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++----- - include/linux/fs.h | 11 ++ - kernel/ksyms.c | 2 - 9 files changed, 333 insertions(+), 34 deletions(-) - -Index: linux-2.4.21-chaos/fs/file_table.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/file_table.c 2003-07-15 04:41:00.000000000 +0400 -+++ linux-2.4.21-chaos/fs/file_table.c 2003-12-12 16:19:25.000000000 +0300 -@@ -82,7 +82,8 @@ - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. - */ --int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - memset(filp, 0, sizeof(*filp)); - filp->f_mode = mode; -@@ -90,12 +91,20 @@ - filp->f_dentry = dentry; - filp->f_uid = current->fsuid; - filp->f_gid = current->fsgid; -+ if (it) -+ filp->f_it = it; - filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; - } -+EXPORT_SYMBOL(init_private_file_it); -+ -+int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+{ -+ return init_private_file_it(filp, dentry, mode, NULL); -+} - - void fput(struct file * file) - { -Index: linux-2.4.21-chaos/fs/inode.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/inode.c 2003-12-12 16:18:15.000000000 +0300 -+++ linux-2.4.21-chaos/fs/inode.c 2003-12-12 16:19:25.000000000 +0300 -@@ -1054,9 +1054,10 @@ - return inode; - } - --struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) -+struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) - { -- struct list_head * head = inode_hashtable + hash(sb,ino); - struct inode * inode; - - spin_lock(&inode_lock); -@@ -1069,6 +1070,24 @@ - } - spin_unlock(&inode_lock); - -+ return NULL; -+} -+ -+struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ return ifind(sb, ino, head, find_actor, opaque); -+} -+ -+struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque); -+ if (inode) -+ return inode; -+ - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. -Index: linux-2.4.21-chaos/fs/Makefile -=================================================================== ---- linux-2.4.21-chaos.orig/fs/Makefile 2003-12-12 16:18:36.000000000 +0300 -+++ linux-2.4.21-chaos/fs/Makefile 2003-12-12 16:19:25.000000000 +0300 -@@ -9,7 +9,8 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \ -+ namei.o file_table.o - mod-subdirs := nls xfs - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.21-chaos/fs/namei.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/namei.c 2003-12-12 16:18:06.000000000 +0300 -+++ linux-2.4.21-chaos/fs/namei.c 2003-12-12 16:19:25.000000000 +0300 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -100,6 +101,7 @@ - it->it_op_release(it); - - } -+EXPORT_SYMBOL(intent_release); - - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the -@@ -910,7 +912,8 @@ - - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) - { - unsigned long hash; - struct qstr this; -@@ -930,11 +933,16 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash_it(&this, base, NULL); -+ return lookup_hash_it(&this, base, it); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * -Index: linux-2.4.21-chaos/fs/nfsd/export.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/nfsd/export.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/nfsd/export.c 2003-12-12 16:19:25.000000000 +0300 -@@ -223,6 +223,11 @@ - inode = nd.dentry->d_inode; - dev = inode->i_dev; - ino = inode->i_ino; -+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && -+ !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; -+ } - err = -EINVAL; - - exp = exp_get(clp, dev, ino); -Index: linux-2.4.21-chaos/fs/nfsd/nfsfh.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/nfsd/nfsfh.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/nfsd/nfsfh.c 2003-12-12 16:19:25.000000000 +0300 -@@ -36,6 +36,13 @@ - int sequence; /* sequence counter */ - }; - -+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) -+{ -+ if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ return inode->i_op->lookup(inode, dentry); -+} -+ - /* - * A rather strange filldir function to capture - * the name matching the specified inode number. -@@ -75,6 +84,8 @@ - int error; - struct file file; - struct nfsd_getdents_callback buffer; -+ struct lookup_intent it; -+ struct file *filp = NULL; - - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +96,37 @@ - /* - * Open the directory ... - */ -- error = init_private_file(&file, dentry, FMODE_READ); -- if (error) -+ if (dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && -+ (dentry->d_parent == dentry) ) { -+ it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulate init_private_file without -+ * f_op->open for disconnected dentry as we don't have -+ * actual dentry->d_name to revalidate in revalidate_it() -+ */ -+ filp = &file; -+ memset(filp, 0, sizeof(*filp)); -+ filp->f_mode = FMODE_READ; -+ atomic_set(&filp->f_count, 1); -+ filp->f_dentry = dentry; -+ filp->f_uid = current->fsuid; -+ filp->f_gid = current->fsgid; -+ filp->f_op = dentry->d_inode->i_fop; -+ error = 0; -+ } else { -+ intent_init(&it, IT_OPEN, FMODE_READ); -+ error = revalidate_it(dentry, &it); -+ if (error) -+ goto out; -+ error = init_private_file_it(&file, dentry, FMODE_READ, &it); -+ } -+ } else { -+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL); -+ } -+ if (error) - goto out; -+ - error = -EINVAL; - if (!file.f_op->readdir) - goto out_close; -@@ -113,9 +152,12 @@ - } - - out_close: -- if (file.f_op->release) -+ if (file.f_op->release && !filp) - file.f_op->release(dir, &file); - out: -+ if (dentry->d_op && dentry->d_op->d_revalidate_it && -+ it.it_op_release && !filp) -+ intent_release(&it); - return error; - } - -@@ -274,7 +317,7 @@ - * it is well connected. But nobody returns different dentrys do they? - */ - down(&child->d_inode->i_sem); -- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); -+ pdentry = lookup_it(child->d_inode, tdentry); - up(&child->d_inode->i_sem); - d_drop(tdentry); /* we never want ".." hashed */ - if (!pdentry && tdentry->d_inode == NULL) { -@@ -307,6 +350,8 @@ - pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - pdentry->d_op = child->d_op; - } -+ if (child->d_op && child->d_op->d_revalidate_it) -+ pdentry->d_op = child->d_op; - } - if (pdentry == NULL) - pdentry = ERR_PTR(-ENOMEM); -@@ -464,6 +509,8 @@ - struct dentry *pdentry; - struct inode *parent; - -+ if (result->d_op && result->d_op->d_revalidate_it) -+ dentry->d_op = result->d_op; - pdentry = nfsd_findparent(dentry); - err = PTR_ERR(pdentry); - if (IS_ERR(pdentry)) -@@ -672,6 +719,10 @@ - - inode = dentry->d_inode; - -+ /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) -+ inode->i_op->revalidate_it(dentry, NULL); -+ - /* Type check. The correct error return for type mismatches - * does not seem to be generally agreed upon. SunOS seems to - * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -905,8 +957,9 @@ - dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - out_uptodate: -- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -- dentry->d_parent->d_name.name, dentry->d_name.name); -+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) -+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - } - -Index: linux-2.4.21-chaos/fs/nfsd/vfs.c -=================================================================== ---- linux-2.4.21-chaos.orig/fs/nfsd/vfs.c 2003-09-19 03:49:54.000000000 +0400 -+++ linux-2.4.21-chaos/fs/nfsd/vfs.c 2003-12-12 16:19:25.000000000 +0300 -@@ -78,6 +78,127 @@ - static struct raparms * raparml; - static struct raparms * raparm_cache; - -+static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = dold }; -+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->link_raw(&old_nd, &nd); -+ igrab(dold->d_inode); -+ d_instantiate(dnew, dold->d_inode); -+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) -+ dold->d_inode->i_op->revalidate_it(dnew, NULL); -+ -+ return err; -+} -+ -+static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->unlink_raw(&nd); -+ if (!err) -+ d_delete(rdentry); -+ -+ return err; -+} -+ -+static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->rmdir_raw(&nd); -+ if (!err) { -+ rdentry->d_inode->i_flags |= S_DEAD; -+ d_delete(rdentry); -+ } -+ -+ return err; -+} -+ -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->symlink_raw(&nd, path); -+ -+ return err; -+} -+ -+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mkdir_raw(&nd, mode); -+ -+ return err; -+} -+ -+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mknod_raw(&nd, mode, dev); -+ -+ return err; -+} -+ -+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name}; -+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name}; -+ struct inode_operations *op = old_nd.dentry->d_inode->i_op; -+ err = op->rename_raw(&old_nd, &new_nd); -+ d_move(odentry, ndentry); -+ -+ return err; -+} -+ -+static int setattr_raw(struct inode *inode, struct iattr *iap) -+{ -+ int err; -+ -+ iap->ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, iap); -+ -+ return err; -+} -+ -+int revalidate_it(struct dentry *dentry, struct lookup_intent *it) -+{ -+ int err = 0; -+ -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) && -+ !d_invalidate(dentry)) { -+ err = -EINVAL; -+ return err; -+ } -+ } -+ -+ return err; -+} -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -303,7 +425,10 @@ - } - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime) { -- err = notify_change(dentry, iap); -+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dentry->d_inode, iap); -+ else -+ err = notify_change(dentry, iap); - err = nfserrno(err); - } - if (size_change) { -@@ -430,6 +555,7 @@ - { - struct dentry *dentry; - struct inode *inode; -+ struct lookup_intent it; - int err; - - /* If we get here, then the client has already done an "open", and (hopefully) -@@ -476,6 +602,18 @@ - filp->f_mode = FMODE_READ; - } - -+#ifndef O_OWNER_OVERRIDE -+#define O_OWNER_OVERRIDE 0200000000 -+#endif -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | -+ O_OWNER_OVERRIDE); -+ -+ err = revalidate_it(dentry, &it); -+ if (err) -+ goto out_nfserr; -+ -+ filp->f_it = ⁢ -+ - err = 0; - if (filp->f_op && filp->f_op->open) { - err = filp->f_op->open(inode, filp); -@@ -490,6 +624,9 @@ - } - } - out_nfserr: -+ if (it.it_op_release) -+ intent_release(&it); -+ - if (err) - err = nfserrno(err); - out: -@@ -821,7 +959,7 @@ - { - struct dentry *dentry, *dchild; - struct inode *dirp; -- int err; -+ int err, error = -EOPNOTSUPP; - - err = nfserr_perm; - if (!flen) -@@ -837,20 +975,47 @@ - dentry = fhp->fh_dentry; - dirp = dentry->d_inode; - -+ switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); -+ } -+ if (error && error != -EOPNOTSUPP) { -+ err = error; -+ goto out_nfserr; -+ } -+ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - /* - * Check whether the response file handle has been verified yet. - * If it has, the parent directory should already be locked. - */ -- if (!resfhp->fh_dentry) { -- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ -- fh_lock(fhp); -+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { -+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ * and nfsd_proc_create in case of lustre */ -+ if (!resfhp->fh_dentry) -+ fh_lock(fhp); - dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); - if (IS_ERR(dchild)) - goto out_nfserr; -+ resfhp->fh_dentry = NULL; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); - if (err) - goto out; -@@ -871,10 +1033,12 @@ - * Make sure the child dentry is still negative ... - */ - err = nfserr_exist; -- if (dchild->d_inode) { -- dprintk("nfsd_create: dentry %s/%s not negative!\n", -- dentry->d_name.name, dchild->d_name.name); -- goto out; -+ if (error == -EOPNOTSUPP) { -+ if (dchild->d_inode) { -+ dprintk("nfsd_create: dentry %s/%s not negative!\n", -+ dentry->d_name.name, dchild->d_name.name); -+ goto out; -+ } - } - - if (!(iap->ia_valid & ATTR_MODE)) -@@ -887,16 +1051,19 @@ - err = nfserr_perm; - switch (type) { - case S_IFREG: -- err = vfs_create(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_create(dirp, dchild, iap->ia_mode); - break; - case S_IFDIR: -- err = vfs_mkdir(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mkdir(dirp, dchild, iap->ia_mode); - break; - case S_IFCHR: - case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: -- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); - break; - default: - printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -965,7 +1132,13 @@ - /* Get all the sanity checks out of the way before - * we lock the parent. */ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (dirp->i_op->mknod_raw) { -+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); -+ if (err && err != -EOPNOTSUPP) -+ goto out_nfserr; -+ } -+ -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - fh_lock(fhp); - -@@ -1016,6 +1189,8 @@ - case NFS3_CREATE_GUARDED: - err = nfserr_exist; - } -+ if (dirp->i_op->mknod_raw) -+ err = 0; - goto out; - } - -@@ -1122,7 +1297,7 @@ - struct iattr *iap) - { - struct dentry *dentry, *dnew; -- int err, cerr; -+ int err, cerr, error = -EOPNOTSUPP; - - err = nfserr_noent; - if (!flen || !plen) -@@ -1136,12 +1311,18 @@ - goto out; - fh_lock(fhp); - dentry = fhp->fh_dentry; -+ -+ if (dentry->d_inode->i_op->symlink_raw) -+ error = symlink_raw(dentry, fname, flen, path); -+ - dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); - if (IS_ERR(dnew)) - goto out_nfserr; - -- err = vfs_symlink(dentry->d_inode, dnew, path); -+ err = error; -+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw) -+ err = vfs_symlink(dentry->d_inode, dnew, path); - if (!err) { - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); -@@ -1148,7 +1329,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str - iap->ia_valid |= ATTR_CTIME; - iap->ia_mode = (iap->ia_mode&S_IALLUGO) - | S_IFLNK; -- err = notify_change(dnew, iap); -+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dnew->d_inode, iap); -+ else -+ err = notify_change(dnew, iap); - if (err) - err = nfserrno(err); - else if (EX_ISSYNC(fhp->fh_export)) -@@ -1211,7 +1392,10 @@ - dold = tfhp->fh_dentry; - dest = dold->d_inode; - -- err = vfs_link(dold, dirp, dnew); -+ if (dirp->i_op->link_raw) -+ err = link_raw(dold, ddir, dnew); -+ else -+ err = vfs_link(dold, dirp, dnew); - if (!err) { - if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); -@@ -1296,7 +1480,10 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if (fdir->i_op->rename_raw) -+ err = rename_raw(fdentry, tdentry, odentry, ndentry); -+ else -+ err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); -@@ -1317,7 +1504,7 @@ - fill_post_wcc(tfhp); - double_up(&tdir->i_sem, &fdir->i_sem); - ffhp->fh_locked = tfhp->fh_locked = 0; -- -+ - out: - return err; - } -@@ -1363,9 +1550,15 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_unlink(dirp, rdentry); -+ if (dirp->i_op->unlink_raw) -+ err = unlink_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_unlink(dirp, rdentry); - } else { /* It's RMDIR */ -- err = vfs_rmdir(dirp, rdentry); -+ if (dirp->i_op->rmdir_raw) -+ err = rmdir_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_rmdir(dirp, rdentry); - } - - dput(rdentry); -Index: linux-2.4.21-chaos/include/linux/fs.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/fs.h 2003-12-12 16:19:23.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/fs.h 2003-12-12 16:19:25.000000000 +0300 -@@ -93,6 +93,8 @@ - #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ - #define FS_NOMOUNT 16 /* Never mount from userland */ - #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. */ - #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon - * as nfs_rename() will be cleaned up - */ -@@ -1159,6 +1162,9 @@ - struct nameidata *nd, struct lookup_intent *it); - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); -+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1458,6 +1464,8 @@ - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); - extern struct dentry * __lookup_hash(struct qstr *, struct dentry *); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) -@@ -1477,6 +1485,8 @@ - - extern struct inode * iget4_locked(struct super_block *, unsigned long, - find_inode_t, void *); -+extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); - - static inline struct inode *iget4(struct super_block *sb, unsigned long ino, - find_inode_t find_actor, void *opaque) -Index: linux-2.4.21-chaos/kernel/ksyms.c -=================================================================== ---- linux-2.4.21-chaos.orig/kernel/ksyms.c 2003-12-12 16:18:36.000000000 +0300 -+++ linux-2.4.21-chaos/kernel/ksyms.c 2003-12-12 16:19:25.000000000 +0300 -@@ -178,6 +178,7 @@ - EXPORT_SYMBOL(igrab); - EXPORT_SYMBOL(iunique); - EXPORT_SYMBOL(iget4_locked); -+EXPORT_SYMBOL(ilookup4); - EXPORT_SYMBOL(unlock_new_inode); - EXPORT_SYMBOL(iput); - EXPORT_SYMBOL(inode_init_once); -@@ -191,6 +192,7 @@ - EXPORT_SYMBOL(path_release); - EXPORT_SYMBOL(__user_walk); - EXPORT_SYMBOL(lookup_one_len); -+EXPORT_SYMBOL(lookup_one_len_it); - EXPORT_SYMBOL(lookup_hash); - - EXPORT_SYMBOL(sys_close); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch deleted file mode 100644 index 0747db2..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.22.patch +++ /dev/null @@ -1,745 +0,0 @@ -Index: linux-2.4.22-vanilla/fs/Makefile -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/Makefile 2003-11-03 23:41:40.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/Makefile 2003-11-03 23:45:07.000000000 +0300 -@@ -7,7 +7,8 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \ -+ namei.o file_table.o - mod-subdirs := nls - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.22-vanilla/fs/file_table.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/file_table.c 2003-05-16 05:29:12.000000000 +0400 -+++ linux-2.4.22-vanilla/fs/file_table.c 2003-11-03 23:44:38.000000000 +0300 -@@ -82,7 +82,8 @@ - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. - */ --int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - memset(filp, 0, sizeof(*filp)); - filp->f_mode = mode; -@@ -90,12 +91,20 @@ - filp->f_dentry = dentry; - filp->f_uid = current->fsuid; - filp->f_gid = current->fsgid; -+ if (it) -+ filp->f_it = it; - filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; - } -+EXPORT_SYMBOL(init_private_file_it); -+ -+int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+{ -+ return init_private_file_it(filp, dentry, mode, NULL); -+} - - void fput(struct file * file) - { -Index: linux-2.4.22-vanilla/fs/inode.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/inode.c 2003-11-03 23:25:33.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/inode.c 2003-11-03 23:44:38.000000000 +0300 -@@ -970,9 +970,10 @@ - } - - --struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) -+static inline struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) - { -- struct list_head * head = inode_hashtable + hash(sb,ino); - struct inode * inode; - - spin_lock(&inode_lock); -@@ -985,6 +986,24 @@ - } - spin_unlock(&inode_lock); - -+ return NULL; -+} -+ -+struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ return ifind(sb, ino, head, find_actor, opaque); -+} -+ -+struct inode *iget4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque); -+ if (inode) -+ return inode; -+ - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. -Index: linux-2.4.22-vanilla/fs/namei.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/namei.c 2003-11-03 23:22:22.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/namei.c 2003-11-03 23:44:38.000000000 +0300 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -100,6 +101,7 @@ - it->it_op_release(it); - - } -+EXPORT_SYMBOL(intent_release); - - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the -@@ -902,7 +904,8 @@ - - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) - { - unsigned long hash; - struct qstr this; -@@ -922,11 +925,16 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash_it(&this, base, NULL); -+ return lookup_hash_it(&this, base, it); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * -Index: linux-2.4.22-vanilla/fs/nfsd/export.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/nfsd/export.c 2003-11-03 23:22:11.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/nfsd/export.c 2003-11-03 23:44:38.000000000 +0300 -@@ -223,6 +223,11 @@ - inode = nd.dentry->d_inode; - dev = inode->i_dev; - ino = inode->i_ino; -+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && -+ !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; -+ } - err = -EINVAL; - - exp = exp_get(clp, dev, ino); -Index: linux-2.4.22-vanilla/fs/nfsd/nfsfh.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/nfsd/nfsfh.c 2003-11-03 23:22:11.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/nfsd/nfsfh.c 2003-11-03 23:44:38.000000000 +0300 -@@ -36,6 +36,13 @@ - int sequence; /* sequence counter */ - }; - -+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) -+{ -+ if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ return inode->i_op->lookup(inode, dentry); -+} -+ - /* - * A rather strange filldir function to capture - * the name matching the specified inode number. -@@ -75,6 +84,8 @@ - int error; - struct file file; - struct nfsd_getdents_callback buffer; -+ struct lookup_intent it; -+ struct file *filp = NULL; - - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +96,37 @@ - /* - * Open the directory ... - */ -- error = init_private_file(&file, dentry, FMODE_READ); -- if (error) -+ if (dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && -+ (dentry->d_parent == dentry) ) { -+ it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulate init_private_file without -+ * f_op->open for disconnected dentry as we don't have -+ * actual dentry->d_name to revalidate in revalidate_it() -+ */ -+ filp = &file; -+ memset(filp, 0, sizeof(*filp)); -+ filp->f_mode = FMODE_READ; -+ atomic_set(&filp->f_count, 1); -+ filp->f_dentry = dentry; -+ filp->f_uid = current->fsuid; -+ filp->f_gid = current->fsgid; -+ filp->f_op = dentry->d_inode->i_fop; -+ error = 0; -+ } else { -+ intent_init(&it, IT_OPEN, FMODE_READ); -+ error = revalidate_it(dentry, &it); -+ if (error) -+ goto out; -+ error = init_private_file_it(&file, dentry, FMODE_READ, &it); -+ } -+ } else { -+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL); -+ } -+ if (error) - goto out; -+ - error = -EINVAL; - if (!file.f_op->readdir) - goto out_close; -@@ -113,9 +152,12 @@ - } - - out_close: -- if (file.f_op->release) -+ if (file.f_op->release && !filp) - file.f_op->release(dir, &file); - out: -+ if (dentry->d_op && dentry->d_op->d_revalidate_it && -+ it.it_op_release && !filp) -+ intent_release(&it); - return error; - } - -@@ -274,7 +317,7 @@ - * it is well connected. But nobody returns different dentrys do they? - */ - down(&child->d_inode->i_sem); -- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); -+ pdentry = lookup_it(child->d_inode, tdentry); - up(&child->d_inode->i_sem); - d_drop(tdentry); /* we never want ".." hashed */ - if (!pdentry && tdentry->d_inode == NULL) { -@@ -306,6 +349,8 @@ - igrab(tdentry->d_inode); - pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - } -+ if (child->d_op && child->d_op->d_revalidate_it) -+ pdentry->d_op = child->d_op; - } - if (pdentry == NULL) - pdentry = ERR_PTR(-ENOMEM); -@@ -463,6 +508,8 @@ - struct dentry *pdentry; - struct inode *parent; - -+ if (result->d_op && result->d_op->d_revalidate_it) -+ dentry->d_op = result->d_op; - pdentry = nfsd_findparent(dentry); - err = PTR_ERR(pdentry); - if (IS_ERR(pdentry)) -@@ -669,6 +716,10 @@ - - inode = dentry->d_inode; - -+ /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) -+ inode->i_op->revalidate_it(dentry, NULL); -+ - /* Type check. The correct error return for type mismatches - * does not seem to be generally agreed upon. SunOS seems to - * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -902,8 +954,9 @@ - dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - out_uptodate: -- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -- dentry->d_parent->d_name.name, dentry->d_name.name); -+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) -+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - } - -Index: linux-2.4.22-vanilla/fs/nfsd/vfs.c -=================================================================== ---- linux-2.4.22-vanilla.orig/fs/nfsd/vfs.c 2003-11-03 23:22:11.000000000 +0300 -+++ linux-2.4.22-vanilla/fs/nfsd/vfs.c 2003-11-03 23:47:41.000000000 +0300 -@@ -77,6 +77,127 @@ - static struct raparms * raparml; - static struct raparms * raparm_cache; - -+static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = dold }; -+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->link_raw(&old_nd, &nd); -+ igrab(dold->d_inode); -+ d_instantiate(dnew, dold->d_inode); -+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) -+ dold->d_inode->i_op->revalidate_it(dnew, NULL); -+ -+ return err; -+} -+ -+static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->unlink_raw(&nd); -+ if (!err) -+ d_delete(rdentry); -+ -+ return err; -+} -+ -+static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->rmdir_raw(&nd); -+ if (!err) { -+ rdentry->d_inode->i_flags |= S_DEAD; -+ d_delete(rdentry); -+ } -+ -+ return err; -+} -+ -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->symlink_raw(&nd, path); -+ -+ return err; -+} -+ -+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mkdir_raw(&nd, mode); -+ -+ return err; -+} -+ -+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mknod_raw(&nd, mode, dev); -+ -+ return err; -+} -+ -+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name}; -+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name}; -+ struct inode_operations *op = old_nd.dentry->d_inode->i_op; -+ err = op->rename_raw(&old_nd, &new_nd); -+ d_move(odentry, ndentry); -+ -+ return err; -+} -+ -+static int setattr_raw(struct inode *inode, struct iattr *iap) -+{ -+ int err; -+ -+ iap->ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, iap); -+ -+ return err; -+} -+ -+int revalidate_it(struct dentry *dentry, struct lookup_intent *it) -+{ -+ int err = 0; -+ -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) && -+ !d_invalidate(dentry)) { -+ err = -EINVAL; -+ return err; -+ } -+ } -+ -+ return err; -+} -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -302,7 +424,10 @@ - } - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime) { -- err = notify_change(dentry, iap); -+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dentry->d_inode, iap); -+ else -+ err = notify_change(dentry, iap); - err = nfserrno(err); - } - if (size_change) { -@@ -429,6 +554,7 @@ - { - struct dentry *dentry; - struct inode *inode; -+ struct lookup_intent it; - int err; - - /* If we get here, then the client has already done an "open", and (hopefully) -@@ -475,6 +601,18 @@ - filp->f_mode = FMODE_READ; - } - -+#ifndef O_OWNER_OVERRIDE -+#define O_OWNER_OVERRIDE 0200000000 -+#endif -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | -+ O_OWNER_OVERRIDE); -+ -+ err = revalidate_it(dentry, &it); -+ if (err) -+ goto out_nfserr; -+ -+ filp->f_it = ⁢ -+ - err = 0; - if (filp->f_op && filp->f_op->open) { - err = filp->f_op->open(inode, filp); -@@ -489,6 +623,9 @@ - } - } - out_nfserr: -+ if (it.it_op_release) -+ intent_release(&it); -+ - if (err) - err = nfserrno(err); - out: -@@ -820,7 +958,7 @@ - { - struct dentry *dentry, *dchild; - struct inode *dirp; -- int err; -+ int err, error = -EOPNOTSUPP; - - err = nfserr_perm; - if (!flen) -@@ -836,20 +974,47 @@ - dentry = fhp->fh_dentry; - dirp = dentry->d_inode; - -+ switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); -+ } -+ if (error && error != -EOPNOTSUPP) { -+ err = error; -+ goto out_nfserr; -+ } -+ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - /* - * Check whether the response file handle has been verified yet. - * If it has, the parent directory should already be locked. - */ -- if (!resfhp->fh_dentry) { -- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ -- fh_lock(fhp); -+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { -+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ * and nfsd_proc_create in case of lustre */ -+ if (!resfhp->fh_dentry) -+ fh_lock(fhp); - dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); - if (IS_ERR(dchild)) - goto out_nfserr; -+ resfhp->fh_dentry = NULL; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); - if (err) - goto out; -@@ -870,10 +1032,12 @@ - * Make sure the child dentry is still negative ... - */ - err = nfserr_exist; -- if (dchild->d_inode) { -- dprintk("nfsd_create: dentry %s/%s not negative!\n", -- dentry->d_name.name, dchild->d_name.name); -- goto out; -+ if (error == -EOPNOTSUPP) { -+ if (dchild->d_inode) { -+ dprintk("nfsd_create: dentry %s/%s not negative!\n", -+ dentry->d_name.name, dchild->d_name.name); -+ goto out; -+ } - } - - if (!(iap->ia_valid & ATTR_MODE)) -@@ -886,16 +1050,19 @@ - err = nfserr_perm; - switch (type) { - case S_IFREG: -- err = vfs_create(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_create(dirp, dchild, iap->ia_mode); - break; - case S_IFDIR: -- err = vfs_mkdir(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mkdir(dirp, dchild, iap->ia_mode); - break; - case S_IFCHR: - case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: -- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); - break; - default: - printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -964,7 +1131,13 @@ - /* Get all the sanity checks out of the way before - * we lock the parent. */ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (dirp->i_op->mknod_raw) { -+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); -+ if (err && err != -EOPNOTSUPP) -+ goto out_nfserr; -+ } -+ -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - fh_lock(fhp); - -@@ -1015,6 +1188,8 @@ - case NFS3_CREATE_GUARDED: - err = nfserr_exist; - } -+ if (dirp->i_op->mknod_raw) -+ err = 0; - goto out; - } - -@@ -1121,7 +1296,7 @@ - struct iattr *iap) - { - struct dentry *dentry, *dnew; -- int err, cerr; -+ int err, cerr, error = -EOPNOTSUPP; - - err = nfserr_noent; - if (!flen || !plen) -@@ -1135,12 +1310,18 @@ - goto out; - fh_lock(fhp); - dentry = fhp->fh_dentry; -+ -+ if (dentry->d_inode->i_op->symlink_raw) -+ error = symlink_raw(dentry, fname, flen, path); -+ - dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); - if (IS_ERR(dnew)) - goto out_nfserr; - -- err = vfs_symlink(dentry->d_inode, dnew, path); -+ err = error; -+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw) -+ err = vfs_symlink(dentry->d_inode, dnew, path); - if (!err) { - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); -@@ -1150,7 +1331,10 @@ - iap->ia_valid |= ATTR_CTIME; - iap->ia_mode = (iap->ia_mode&S_IALLUGO) - | S_IFLNK; -- err = notify_change(dnew, iap); -+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dnew->d_inode, iap); -+ else -+ err = notify_change(dnew, iap); - if (err) - err = nfserrno(err); - else if (EX_ISSYNC(fhp->fh_export)) -@@ -1210,7 +1394,10 @@ - dold = tfhp->fh_dentry; - dest = dold->d_inode; - -- err = vfs_link(dold, dirp, dnew); -+ if (dirp->i_op->link_raw) -+ err = link_raw(dold, ddir, dnew); -+ else -+ err = vfs_link(dold, dirp, dnew); - if (!err) { - if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); -@@ -1295,7 +1482,10 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if (fdir->i_op->rename_raw) -+ err = rename_raw(fdentry, tdentry, odentry, ndentry); -+ else -+ err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); -@@ -1316,7 +1506,7 @@ - fill_post_wcc(tfhp); - double_up(&tdir->i_sem, &fdir->i_sem); - ffhp->fh_locked = tfhp->fh_locked = 0; -- -+ - out: - return err; - } -@@ -1362,9 +1552,15 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_unlink(dirp, rdentry); -+ if (dirp->i_op->unlink_raw) -+ err = unlink_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_unlink(dirp, rdentry); - } else { /* It's RMDIR */ -- err = vfs_rmdir(dirp, rdentry); -+ if (dirp->i_op->rmdir_raw) -+ err = rmdir_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_rmdir(dirp, rdentry); - } - - dput(rdentry); -Index: linux-2.4.22-vanilla/include/linux/fs.h -=================================================================== ---- linux-2.4.22-vanilla.orig/include/linux/fs.h 2003-11-03 23:41:40.000000000 +0300 -+++ linux-2.4.22-vanilla/include/linux/fs.h 2003-11-03 23:44:38.000000000 +0300 -@@ -93,6 +93,8 @@ - #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ - #define FS_NOMOUNT 16 /* Never mount from userland */ - #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. */ - #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon - * as nfs_rename() will be cleaned up - */ -@@ -1115,6 +1118,9 @@ - struct nameidata *nd, struct lookup_intent *it); - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); -+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1411,6 +1417,8 @@ - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1425,6 +1433,8 @@ - - typedef int (*find_inode_t)(struct inode *, unsigned long, void *); - extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); -+extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); - static inline struct inode *iget(struct super_block *sb, unsigned long ino) - { - return iget4(sb, ino, NULL, NULL); -Index: linux-2.4.22-vanilla/kernel/ksyms.c -=================================================================== ---- linux-2.4.22-vanilla.orig/kernel/ksyms.c 2003-11-03 23:41:40.000000000 +0300 -+++ linux-2.4.22-vanilla/kernel/ksyms.c 2003-11-03 23:44:38.000000000 +0300 -@@ -149,6 +149,7 @@ - EXPORT_SYMBOL(igrab); - EXPORT_SYMBOL(iunique); - EXPORT_SYMBOL(iget4); -+EXPORT_SYMBOL(ilookup4); - EXPORT_SYMBOL(iput); - EXPORT_SYMBOL(inode_init_once); - EXPORT_SYMBOL(force_delete); -@@ -160,6 +161,7 @@ - EXPORT_SYMBOL(path_release); - EXPORT_SYMBOL(__user_walk); - EXPORT_SYMBOL(lookup_one_len); -+EXPORT_SYMBOL(lookup_one_len_it); - EXPORT_SYMBOL(lookup_hash); - EXPORT_SYMBOL(sys_close); - EXPORT_SYMBOL(dcache_lock); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch deleted file mode 100644 index f2766d3..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch +++ /dev/null @@ -1,744 +0,0 @@ -Index: linux-2.4.29/fs/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/Makefile 2005-05-03 18:16:44.000000000 +0300 -+++ linux-2.4.29/fs/Makefile 2005-05-03 18:46:09.301144016 +0300 -@@ -7,7 +7,8 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \ -+ namei.o file_table.o - mod-subdirs := nls - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.29/fs/file_table.c -=================================================================== ---- linux-2.4.29.orig/fs/file_table.c 2005-05-03 16:28:21.000000000 +0300 -+++ linux-2.4.29/fs/file_table.c 2005-05-03 18:46:09.303143712 +0300 -@@ -82,7 +82,8 @@ - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. - */ --int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - memset(filp, 0, sizeof(*filp)); - filp->f_mode = mode; -@@ -90,12 +91,20 @@ - filp->f_dentry = dentry; - filp->f_uid = current->fsuid; - filp->f_gid = current->fsgid; -+ if (it) -+ filp->f_it = it; - filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; - } -+EXPORT_SYMBOL(init_private_file_it); -+ -+int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+{ -+ return init_private_file_it(filp, dentry, mode, NULL); -+} - - void fastcall fput(struct file * file) - { -Index: linux-2.4.29/fs/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/inode.c 2005-05-03 18:16:44.000000000 +0300 -+++ linux-2.4.29/fs/inode.c 2005-05-03 18:51:36.389419040 +0300 -@@ -1139,9 +1139,10 @@ - return inode; - } - --struct inode *iget4_locked(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) -+static inline struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) - { -- struct list_head * head = inode_hashtable + hash(sb,ino); - struct inode * inode; - - spin_lock(&inode_lock); -@@ -1154,6 +1155,24 @@ - } - spin_unlock(&inode_lock); - -+ return NULL; -+} -+ -+struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ return ifind(sb, ino, head, find_actor, opaque); -+} -+ -+struct inode *iget4_locked(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque); -+ if (inode) -+ return inode; -+ - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. -Index: linux-2.4.29/fs/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/namei.c 2005-05-03 18:16:43.000000000 +0300 -+++ linux-2.4.29/fs/namei.c 2005-05-03 18:46:09.310142648 +0300 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -100,6 +101,7 @@ - it->it_op_release(it); - - } -+EXPORT_SYMBOL(intent_release); - - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the -@@ -910,7 +912,8 @@ - - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) - { - unsigned long hash; - struct qstr this; -@@ -930,11 +933,16 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash_it(&this, base, NULL); -+ return lookup_hash_it(&this, base, it); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * -Index: linux-2.4.29/fs/nfsd/export.c -=================================================================== ---- linux-2.4.29.orig/fs/nfsd/export.c 2005-05-03 16:28:21.000000000 +0300 -+++ linux-2.4.29/fs/nfsd/export.c 2005-05-03 18:46:09.312142344 +0300 -@@ -223,6 +223,11 @@ - inode = nd.dentry->d_inode; - dev = inode->i_dev; - ino = inode->i_ino; -+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && -+ !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; -+ } - err = -EINVAL; - - exp = exp_get(clp, dev, ino); -Index: linux-2.4.29/fs/nfsd/nfsfh.c -=================================================================== ---- linux-2.4.29.orig/fs/nfsd/nfsfh.c 2005-05-03 16:28:21.000000000 +0300 -+++ linux-2.4.29/fs/nfsd/nfsfh.c 2005-05-03 18:46:09.315141888 +0300 -@@ -36,6 +36,13 @@ - int sequence; /* sequence counter */ - }; - -+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) -+{ -+ if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ return inode->i_op->lookup(inode, dentry); -+} -+ - /* - * A rather strange filldir function to capture - * the name matching the specified inode number. -@@ -75,6 +82,8 @@ - int error; - struct file file; - struct nfsd_getdents_callback buffer; -+ struct lookup_intent it; -+ struct file *filp = NULL; - - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +94,37 @@ - /* - * Open the directory ... - */ -- error = init_private_file(&file, dentry, FMODE_READ); -+ if (dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && -+ (dentry->d_parent == dentry) ) { -+ it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulate init_private_file without -+ * f_op->open for disconnected dentry as we don't have -+ * actual dentry->d_name to revalidate in revalidate_it() -+ */ -+ filp = &file; -+ memset(filp, 0, sizeof(*filp)); -+ filp->f_mode = FMODE_READ; -+ atomic_set(&filp->f_count, 1); -+ filp->f_dentry = dentry; -+ filp->f_uid = current->fsuid; -+ filp->f_gid = current->fsgid; -+ filp->f_op = dentry->d_inode->i_fop; -+ error = 0; -+ } else { -+ intent_init(&it, IT_OPEN, FMODE_READ); -+ error = revalidate_it(dentry, &it); -+ if (error) -+ goto out; -+ error = init_private_file_it(&file, dentry, FMODE_READ, &it); -+ } -+ } else { -+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL); -+ } - if (error) - goto out; -+ - error = -EINVAL; - if (!file.f_op->readdir) - goto out_close; -@@ -113,9 +150,12 @@ - } - - out_close: -- if (file.f_op->release) -+ if (file.f_op->release && !filp) - file.f_op->release(dir, &file); - out: -+ if (dentry->d_op && dentry->d_op->d_revalidate_it && -+ it.it_op_release && !filp) -+ intent_release(&it); - return error; - } - -@@ -274,7 +314,7 @@ - * it is well connected. But nobody returns different dentrys do they? - */ - down(&child->d_inode->i_sem); -- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); -+ pdentry = lookup_it(child->d_inode, tdentry); - up(&child->d_inode->i_sem); - d_drop(tdentry); /* we never want ".." hashed */ - if (!pdentry && tdentry->d_inode == NULL) { -@@ -307,6 +347,8 @@ - pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - pdentry->d_op = child->d_op; - } -+ if (child->d_op && child->d_op->d_revalidate_it) -+ pdentry->d_op = child->d_op; - } - if (pdentry == NULL) - pdentry = ERR_PTR(-ENOMEM); -@@ -464,6 +506,8 @@ - struct dentry *pdentry; - struct inode *parent; - -+ if (result->d_op && result->d_op->d_revalidate_it) -+ dentry->d_op = result->d_op; - pdentry = nfsd_findparent(dentry); - err = PTR_ERR(pdentry); - if (IS_ERR(pdentry)) -@@ -670,6 +714,10 @@ - - inode = dentry->d_inode; - -+ /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) -+ inode->i_op->revalidate_it(dentry, NULL); -+ - /* Type check. The correct error return for type mismatches - * does not seem to be generally agreed upon. SunOS seems to - * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -903,8 +951,9 @@ - dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - out_uptodate: -- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -- dentry->d_parent->d_name.name, dentry->d_name.name); -+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) -+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - } - -Index: linux-2.4.29/fs/nfsd/vfs.c -=================================================================== ---- linux-2.4.29.orig/fs/nfsd/vfs.c 2005-05-03 16:28:21.000000000 +0300 -+++ linux-2.4.29/fs/nfsd/vfs.c 2005-05-03 18:46:09.372133224 +0300 -@@ -77,6 +77,127 @@ - static struct raparms * raparml; - static struct raparms * raparm_cache; - -+static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = dold }; -+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->link_raw(&old_nd, &nd); -+ igrab(dold->d_inode); -+ d_instantiate(dnew, dold->d_inode); -+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) -+ dold->d_inode->i_op->revalidate_it(dnew, NULL); -+ -+ return err; -+} -+ -+static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->unlink_raw(&nd); -+ if (!err) -+ d_delete(rdentry); -+ -+ return err; -+} -+ -+static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->rmdir_raw(&nd); -+ if (!err) { -+ rdentry->d_inode->i_flags |= S_DEAD; -+ d_delete(rdentry); -+ } -+ -+ return err; -+} -+ -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->symlink_raw(&nd, path); -+ -+ return err; -+} -+ -+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mkdir_raw(&nd, mode); -+ -+ return err; -+} -+ -+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mknod_raw(&nd, mode, dev); -+ -+ return err; -+} -+ -+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name}; -+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name}; -+ struct inode_operations *op = old_nd.dentry->d_inode->i_op; -+ err = op->rename_raw(&old_nd, &new_nd); -+ d_move(odentry, ndentry); -+ -+ return err; -+} -+ -+static int setattr_raw(struct inode *inode, struct iattr *iap) -+{ -+ int err; -+ -+ iap->ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, iap); -+ -+ return err; -+} -+ -+int revalidate_it(struct dentry *dentry, struct lookup_intent *it) -+{ -+ int err = 0; -+ -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) && -+ !d_invalidate(dentry)) { -+ err = -EINVAL; -+ return err; -+ } -+ } -+ -+ return err; -+} -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -302,7 +422,10 @@ - } - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime) { -- err = notify_change(dentry, iap); -+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dentry->d_inode, iap); -+ else -+ err = notify_change(dentry, iap); - err = nfserrno(err); - } - if (size_change) { -@@ -429,6 +552,7 @@ - { - struct dentry *dentry; - struct inode *inode; -+ struct lookup_intent it; - int err; - - /* If we get here, then the client has already done an "open", and (hopefully) -@@ -475,6 +599,18 @@ - filp->f_mode = FMODE_READ; - } - -+#ifndef O_OWNER_OVERRIDE -+#define O_OWNER_OVERRIDE 0200000000 -+#endif -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | -+ O_OWNER_OVERRIDE); -+ -+ err = revalidate_it(dentry, &it); -+ if (err) -+ goto out_nfserr; -+ -+ filp->f_it = ⁢ -+ - err = 0; - if (filp->f_op && filp->f_op->open) { - err = filp->f_op->open(inode, filp); -@@ -490,6 +626,9 @@ - } - } - out_nfserr: -+ if (it.it_op_release) -+ intent_release(&it); -+ - if (err) - err = nfserrno(err); - out: -@@ -837,7 +976,7 @@ - { - struct dentry *dentry, *dchild; - struct inode *dirp; -- int err; -+ int err, error = -EOPNOTSUPP; - - err = nfserr_perm; - if (!flen) -@@ -853,20 +992,47 @@ - dentry = fhp->fh_dentry; - dirp = dentry->d_inode; - -+ switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); -+ } -+ if (error && error != -EOPNOTSUPP) { -+ err = error; -+ goto out_nfserr; -+ } -+ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - /* - * Check whether the response file handle has been verified yet. - * If it has, the parent directory should already be locked. - */ -- if (!resfhp->fh_dentry) { -- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ -- fh_lock(fhp); -+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { -+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ * and nfsd_proc_create in case of lustre */ -+ if (!resfhp->fh_dentry) -+ fh_lock(fhp); - dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); - if (IS_ERR(dchild)) - goto out_nfserr; -+ resfhp->fh_dentry = NULL; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); - if (err) - goto out; -@@ -887,10 +1053,12 @@ - * Make sure the child dentry is still negative ... - */ - err = nfserr_exist; -- if (dchild->d_inode) { -- dprintk("nfsd_create: dentry %s/%s not negative!\n", -- dentry->d_name.name, dchild->d_name.name); -- goto out; -+ if (error == -EOPNOTSUPP) { -+ if (dchild->d_inode) { -+ dprintk("nfsd_create: dentry %s/%s not negative!\n", -+ dentry->d_name.name, dchild->d_name.name); -+ goto out; -+ } - } - - if (!(iap->ia_valid & ATTR_MODE)) -@@ -903,16 +1071,19 @@ - err = nfserr_perm; - switch (type) { - case S_IFREG: -- err = vfs_create(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_create(dirp, dchild, iap->ia_mode); - break; - case S_IFDIR: -- err = vfs_mkdir(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mkdir(dirp, dchild, iap->ia_mode); - break; - case S_IFCHR: - case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: -- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); - break; - default: - printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -981,7 +1152,13 @@ - /* Get all the sanity checks out of the way before - * we lock the parent. */ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (dirp->i_op->mknod_raw) { -+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); -+ if (err && err != -EOPNOTSUPP) -+ goto out_nfserr; -+ } -+ -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - fh_lock(fhp); - -@@ -1032,6 +1209,8 @@ - case NFS3_CREATE_GUARDED: - err = nfserr_exist; - } -+ if (dirp->i_op->mknod_raw) -+ err = 0; - goto out; - } - -@@ -1138,7 +1317,7 @@ - struct iattr *iap) - { - struct dentry *dentry, *dnew; -- int err, cerr; -+ int err, cerr, error = -EOPNOTSUPP; - - err = nfserr_noent; - if (!flen || !plen) -@@ -1152,12 +1331,18 @@ - goto out; - fh_lock(fhp); - dentry = fhp->fh_dentry; -+ -+ if (dentry->d_inode->i_op->symlink_raw) -+ error = symlink_raw(dentry, fname, flen, path); -+ - dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); - if (IS_ERR(dnew)) - goto out_nfserr; - -- err = vfs_symlink(dentry->d_inode, dnew, path); -+ err = error; -+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw) -+ err = vfs_symlink(dentry->d_inode, dnew, path); - if (!err) { - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); -@@ -1167,7 +1352,10 @@ - iap->ia_valid |= ATTR_CTIME; - iap->ia_mode = (iap->ia_mode&S_IALLUGO) - | S_IFLNK; -- err = notify_change(dnew, iap); -+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dnew->d_inode, iap); -+ else -+ err = notify_change(dnew, iap); - if (err) - err = nfserrno(err); - else if (EX_ISSYNC(fhp->fh_export)) -@@ -1227,7 +1415,10 @@ - dold = tfhp->fh_dentry; - dest = dold->d_inode; - -- err = vfs_link(dold, dirp, dnew); -+ if (dirp->i_op->link_raw) -+ err = link_raw(dold, ddir, dnew); -+ else -+ err = vfs_link(dold, dirp, dnew); - if (!err) { - if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); -@@ -1312,7 +1503,10 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if (fdir->i_op->rename_raw) -+ err = rename_raw(fdentry, tdentry, odentry, ndentry); -+ else -+ err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); -@@ -1333,7 +1527,7 @@ - fill_post_wcc(tfhp); - double_up(&tdir->i_sem, &fdir->i_sem); - ffhp->fh_locked = tfhp->fh_locked = 0; -- -+ - out: - return err; - } -@@ -1379,9 +1573,15 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_unlink(dirp, rdentry); -+ if (dirp->i_op->unlink_raw) -+ err = unlink_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_unlink(dirp, rdentry); - } else { /* It's RMDIR */ -- err = vfs_rmdir(dirp, rdentry); -+ if (dirp->i_op->rmdir_raw) -+ err = rmdir_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_rmdir(dirp, rdentry); - } - - dput(rdentry); -Index: linux-2.4.29/include/linux/fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs.h 2005-05-03 18:16:44.000000000 +0300 -+++ linux-2.4.29/include/linux/fs.h 2005-05-03 18:52:56.016313912 +0300 -@@ -93,6 +93,8 @@ - #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ - #define FS_NOMOUNT 16 /* Never mount from userland */ - #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. */ - #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon - * as nfs_rename() will be cleaned up - */ -@@ -1124,6 +1126,9 @@ - struct nameidata *nd, struct lookup_intent *it); - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); -+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1423,6 +1428,8 @@ - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1443,6 +1450,8 @@ - - extern struct inode * iget4_locked(struct super_block *, unsigned long, - find_inode_t, void *); -+ extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); - - static inline struct inode *iget4(struct super_block *sb, unsigned long ino, - find_inode_t find_actor, void *opaque) -Index: linux-2.4.29/kernel/ksyms.c -=================================================================== ---- linux-2.4.29.orig/kernel/ksyms.c 2005-05-03 18:16:44.000000000 +0300 -+++ linux-2.4.29/kernel/ksyms.c 2005-05-03 18:52:05.377012256 +0300 -@@ -150,6 +150,7 @@ - EXPORT_SYMBOL(iunique); - EXPORT_SYMBOL(ilookup); - EXPORT_SYMBOL(iget4_locked); -+EXPORT_SYMBOL(ilookup4); - EXPORT_SYMBOL(unlock_new_inode); - EXPORT_SYMBOL(iput); - EXPORT_SYMBOL(inode_init_once); -@@ -164,6 +165,7 @@ - EXPORT_SYMBOL(path_release); - EXPORT_SYMBOL(__user_walk); - EXPORT_SYMBOL(lookup_one_len); -+EXPORT_SYMBOL(lookup_one_len_it); - EXPORT_SYMBOL(lookup_hash); - EXPORT_SYMBOL(sys_close); - EXPORT_SYMBOL(dcache_lock); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch-1 b/lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch-1 deleted file mode 100644 index 6b254ec..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-2.4.29.patch-1 +++ /dev/null @@ -1,730 +0,0 @@ -Index: linux-2.4.29/fs/Makefile -=================================================================== ---- linux-2.4.29.orig/fs/Makefile 2005-04-07 19:31:00.000000000 +0300 -+++ linux-2.4.29/fs/Makefile 2005-05-03 15:59:07.943621928 +0300 -@@ -7,7 +7,8 @@ - - O_TARGET := fs.o - --export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o -+export-objs := filesystems.o open.o dcache.o buffer.o dquot.o inode.o \ -+ namei.o file_table.o - mod-subdirs := nls - - obj-y := open.o read_write.o devices.o file_table.o buffer.o \ -Index: linux-2.4.29/fs/file_table.c -=================================================================== ---- linux-2.4.29.orig/fs/file_table.c 2005-04-07 18:52:26.000000000 +0300 -+++ linux-2.4.29/fs/file_table.c 2005-05-03 15:59:07.945621624 +0300 -@@ -82,7 +82,8 @@ - * and call the open function (if any). The caller must verify that - * inode->i_fop is not NULL. - */ --int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+int init_private_file_it(struct file *filp, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - memset(filp, 0, sizeof(*filp)); - filp->f_mode = mode; -@@ -90,12 +91,20 @@ - filp->f_dentry = dentry; - filp->f_uid = current->fsuid; - filp->f_gid = current->fsgid; -+ if (it) -+ filp->f_it = it; - filp->f_op = dentry->d_inode->i_fop; - if (filp->f_op->open) - return filp->f_op->open(dentry->d_inode, filp); - else - return 0; - } -+EXPORT_SYMBOL(init_private_file_it); -+ -+int init_private_file(struct file *filp, struct dentry *dentry, int mode) -+{ -+ return init_private_file_it(filp, dentry, mode, NULL); -+} - - void fastcall fput(struct file * file) - { -Index: linux-2.4.29/fs/inode.c -=================================================================== ---- linux-2.4.29.orig/fs/inode.c 2005-04-07 19:18:51.000000000 +0300 -+++ linux-2.4.29/fs/inode.c 2005-05-03 16:02:40.198354304 +0300 -@@ -1154,6 +1154,24 @@ - } - spin_unlock(&inode_lock); - -+ return NULL; -+} -+ -+struct inode *ilookup4(struct super_block *sb, unsigned long ino, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct list_head * head = inode_hashtable + hash(sb,ino); -+ return ifind(sb, ino, head, find_actor, opaque); -+} -+ -+static inline struct inode *ifind(struct super_block *sb, unsigned long ino, -+ struct list_head *head, -+ find_inode_t find_actor, void *opaque) -+{ -+ struct inode *inode = ifind(sb, ino, head, find_actor, opaque); -+ if (inode) -+ return inode; -+ - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. -Index: linux-2.4.29/fs/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/namei.c 2005-04-07 19:14:06.000000000 +0300 -+++ linux-2.4.29/fs/namei.c 2005-05-03 15:59:07.953620408 +0300 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -100,6 +101,7 @@ - it->it_op_release(it); - - } -+EXPORT_SYMBOL(intent_release); - - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the -@@ -910,7 +912,8 @@ - - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, -+ int len, struct lookup_intent *it) - { - unsigned long hash; - struct qstr this; -@@ -930,11 +933,16 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash_it(&this, base, NULL); -+ return lookup_hash_it(&this, base, it); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * -Index: linux-2.4.29/fs/nfsd/export.c -=================================================================== ---- linux-2.4.29.orig/fs/nfsd/export.c 2005-04-07 18:53:59.000000000 +0300 -+++ linux-2.4.29/fs/nfsd/export.c 2005-05-03 15:59:07.955620104 +0300 -@@ -223,6 +223,11 @@ - inode = nd.dentry->d_inode; - dev = inode->i_dev; - ino = inode->i_ino; -+ if ((inode->i_sb->s_type->fs_flags & FS_NFSEXP_FSID) && -+ !(nxp->ex_flags & NFSEXP_FSID)) { -+ nxp->ex_dev = inode->i_sb->s_dev; -+ nxp->ex_flags |= NFSEXP_FSID; -+ } - err = -EINVAL; - - exp = exp_get(clp, dev, ino); -Index: linux-2.4.29/fs/nfsd/nfsfh.c -=================================================================== ---- linux-2.4.29.orig/fs/nfsd/nfsfh.c 2005-04-07 18:53:14.000000000 +0300 -+++ linux-2.4.29/fs/nfsd/nfsfh.c 2005-05-03 15:59:07.958619648 +0300 -@@ -36,6 +36,13 @@ - int sequence; /* sequence counter */ - }; - -+static struct dentry *lookup_it(struct inode *inode, struct dentry * dentry) -+{ -+ if (inode->i_op->lookup_it) -+ return inode->i_op->lookup_it(inode, dentry, NULL, 0); -+ return inode->i_op->lookup(inode, dentry); -+} -+ - /* - * A rather strange filldir function to capture - * the name matching the specified inode number. -@@ -75,6 +82,8 @@ - int error; - struct file file; - struct nfsd_getdents_callback buffer; -+ struct lookup_intent it; -+ struct file *filp = NULL; - - error = -ENOTDIR; - if (!dir || !S_ISDIR(dir->i_mode)) -@@ -85,9 +94,37 @@ - /* - * Open the directory ... - */ -- error = init_private_file(&file, dentry, FMODE_READ); -+ if (dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if ((dentry->d_flags & DCACHE_NFSD_DISCONNECTED) && -+ (dentry->d_parent == dentry) ) { -+ it.it_op_release = NULL; -+ /* -+ * XXX Temporary Hack: Simulate init_private_file without -+ * f_op->open for disconnected dentry as we don't have -+ * actual dentry->d_name to revalidate in revalidate_it() -+ */ -+ filp = &file; -+ memset(filp, 0, sizeof(*filp)); -+ filp->f_mode = FMODE_READ; -+ atomic_set(&filp->f_count, 1); -+ filp->f_dentry = dentry; -+ filp->f_uid = current->fsuid; -+ filp->f_gid = current->fsgid; -+ filp->f_op = dentry->d_inode->i_fop; -+ error = 0; -+ } else { -+ intent_init(&it, IT_OPEN, FMODE_READ); -+ error = revalidate_it(dentry, &it); -+ if (error) -+ goto out; -+ error = init_private_file_it(&file, dentry, FMODE_READ, &it); -+ } -+ } else { -+ error = init_private_file_it(&file, dentry, FMODE_READ, NULL); -+ } - if (error) - goto out; -+ - error = -EINVAL; - if (!file.f_op->readdir) - goto out_close; -@@ -113,9 +150,12 @@ - } - - out_close: -- if (file.f_op->release) -+ if (file.f_op->release && !filp) - file.f_op->release(dir, &file); - out: -+ if (dentry->d_op && dentry->d_op->d_revalidate_it && -+ it.it_op_release && !filp) -+ intent_release(&it); - return error; - } - -@@ -274,7 +314,7 @@ - * it is well connected. But nobody returns different dentrys do they? - */ - down(&child->d_inode->i_sem); -- pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry); -+ pdentry = lookup_it(child->d_inode, tdentry); - up(&child->d_inode->i_sem); - d_drop(tdentry); /* we never want ".." hashed */ - if (!pdentry && tdentry->d_inode == NULL) { -@@ -307,6 +347,8 @@ - pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED; - pdentry->d_op = child->d_op; - } -+ if (child->d_op && child->d_op->d_revalidate_it) -+ pdentry->d_op = child->d_op; - } - if (pdentry == NULL) - pdentry = ERR_PTR(-ENOMEM); -@@ -464,6 +506,8 @@ - struct dentry *pdentry; - struct inode *parent; - -+ if (result->d_op && result->d_op->d_revalidate_it) -+ dentry->d_op = result->d_op; - pdentry = nfsd_findparent(dentry); - err = PTR_ERR(pdentry); - if (IS_ERR(pdentry)) -@@ -670,6 +714,10 @@ - - inode = dentry->d_inode; - -+ /* cache coherency for non-device filesystems */ -+ if (inode->i_op && inode->i_op->revalidate_it) -+ inode->i_op->revalidate_it(dentry, NULL); -+ - /* Type check. The correct error return for type mismatches - * does not seem to be generally agreed upon. SunOS seems to - * use EISDIR if file isn't S_IFREG; a comment in the NFSv3 -@@ -903,8 +951,9 @@ - dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - out_uptodate: -- printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -- dentry->d_parent->d_name.name, dentry->d_name.name); -+ if (!dentry->d_parent->d_inode->i_op->mkdir_raw) -+ printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", -+ dentry->d_parent->d_name.name, dentry->d_name.name); - goto out; - } - -Index: linux-2.4.29/fs/nfsd/vfs.c -=================================================================== ---- linux-2.4.29.orig/fs/nfsd/vfs.c 2005-04-07 18:53:19.000000000 +0300 -+++ linux-2.4.29/fs/nfsd/vfs.c 2005-05-03 15:59:07.965618584 +0300 -@@ -77,6 +77,126 @@ - static struct raparms * raparml; - static struct raparms * raparm_cache; - -+static int link_raw(struct dentry *dold, struct dentry *ddir, -+ struct dentry *dnew) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = dold }; -+ struct nameidata nd = { .dentry = ddir, .last = dnew->d_name }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->link_raw(&old_nd, &nd); -+ d_instantiate(dnew, dold->d_inode); -+ if (dold->d_inode->i_op && dold->d_inode->i_op->revalidate_it) -+ dold->d_inode->i_op->revalidate_it(dnew, NULL); -+ -+ return err; -+} -+ -+static int unlink_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->unlink_raw(&nd); -+ if (!err) -+ d_delete(rdentry); -+ -+ return err; -+} -+ -+static int rmdir_raw(struct dentry *dentry, char *fname, int flen, -+ struct dentry *rdentry) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->rmdir_raw(&nd); -+ if (!err) { -+ rdentry->d_inode->i_flags |= S_DEAD; -+ d_delete(rdentry); -+ } -+ -+ return err; -+} -+ -+static int symlink_raw(struct dentry *dentry, char *fname, int flen, -+ char *path) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->symlink_raw(&nd, path); -+ -+ return err; -+} -+ -+static int mkdir_raw(struct dentry *dentry, char *fname, int flen, int mode) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mkdir_raw(&nd, mode); -+ -+ return err; -+} -+ -+static int mknod_raw(struct dentry *dentry, char *fname, int flen, int mode, -+ dev_t dev) -+{ -+ int err; -+ struct qstr last = { .name = fname, .len = flen }; -+ struct nameidata nd = { .dentry = dentry, .last = last }; -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ err = op->mknod_raw(&nd, mode, dev); -+ -+ return err; -+} -+ -+static int rename_raw(struct dentry *fdentry, struct dentry *tdentry, -+ struct dentry *odentry, struct dentry *ndentry) -+{ -+ int err; -+ -+ struct nameidata old_nd = { .dentry = fdentry, .last = odentry->d_name}; -+ struct nameidata new_nd = { .dentry = tdentry, .last = ndentry->d_name}; -+ struct inode_operations *op = old_nd.dentry->d_inode->i_op; -+ err = op->rename_raw(&old_nd, &new_nd); -+ d_move(odentry, ndentry); -+ -+ return err; -+} -+ -+static int setattr_raw(struct inode *inode, struct iattr *iap) -+{ -+ int err; -+ -+ iap->ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, iap); -+ -+ return err; -+} -+ -+int revalidate_it(struct dentry *dentry, struct lookup_intent *it) -+{ -+ int err = 0; -+ -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it) && -+ !d_invalidate(dentry)) { -+ err = -EINVAL; -+ return err; -+ } -+ } -+ -+ return err; -+} -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -302,7 +422,10 @@ - } - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime) { -- err = notify_change(dentry, iap); -+ if (dentry->d_inode->i_op && dentry->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dentry->d_inode, iap); -+ else -+ err = notify_change(dentry, iap); - err = nfserrno(err); - } - if (size_change) { -@@ -429,6 +552,7 @@ - { - struct dentry *dentry; - struct inode *inode; -+ struct lookup_intent it; - int err; - - /* If we get here, then the client has already done an "open", and (hopefully) -@@ -475,6 +599,18 @@ - filp->f_mode = FMODE_READ; - } - -+#ifndef O_OWNER_OVERRIDE -+#define O_OWNER_OVERRIDE 0200000000 -+#endif -+ intent_init(&it, IT_OPEN, (filp->f_flags & ~O_ACCMODE) | filp->f_mode | -+ O_OWNER_OVERRIDE); -+ -+ err = revalidate_it(dentry, &it); -+ if (err) -+ goto out_nfserr; -+ -+ filp->f_it = ⁢ -+ - err = 0; - if (filp->f_op && filp->f_op->open) { - err = filp->f_op->open(inode, filp); -@@ -490,6 +626,9 @@ - } - } - out_nfserr: -+ if (it.it_op_release) -+ intent_release(&it); -+ - if (err) - err = nfserrno(err); - out: -@@ -837,7 +976,7 @@ - { - struct dentry *dentry, *dchild; - struct inode *dirp; -- int err; -+ int err, error = -EOPNOTSUPP; - - err = nfserr_perm; - if (!flen) -@@ -853,20 +992,47 @@ - dentry = fhp->fh_dentry; - dirp = dentry->d_inode; - -+ switch (type) { -+ case S_IFDIR: -+ if (dirp->i_op->mkdir_raw) -+ error = mkdir_raw(dentry, fname, flen, iap->ia_mode); -+ break; -+ case S_IFCHR: -+ case S_IFBLK: -+ case S_IFIFO: -+ case S_IFSOCK: -+ case S_IFREG: -+ if (dirp->i_op->mknod_raw) { -+ if (type == S_IFREG) -+ rdev = 0; -+ error = mknod_raw(dentry, fname,flen,iap->ia_mode,rdev); -+ } -+ break; -+ default: -+ printk("nfsd: bad file type %o in nfsd_create\n", type); -+ } -+ if (error && error != -EOPNOTSUPP) { -+ err = error; -+ goto out_nfserr; -+ } -+ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - /* - * Check whether the response file handle has been verified yet. - * If it has, the parent directory should already be locked. - */ -- if (!resfhp->fh_dentry) { -- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ -- fh_lock(fhp); -+ if (!resfhp->fh_dentry || dirp->i_op->lookup_it) { -+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create -+ * and nfsd_proc_create in case of lustre */ -+ if (!resfhp->fh_dentry) -+ fh_lock(fhp); - dchild = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dchild); - if (IS_ERR(dchild)) - goto out_nfserr; -+ resfhp->fh_dentry = NULL; - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); - if (err) - goto out; -@@ -887,10 +1053,12 @@ - * Make sure the child dentry is still negative ... - */ - err = nfserr_exist; -- if (dchild->d_inode) { -- dprintk("nfsd_create: dentry %s/%s not negative!\n", -- dentry->d_name.name, dchild->d_name.name); -- goto out; -+ if (error == -EOPNOTSUPP) { -+ if (dchild->d_inode) { -+ dprintk("nfsd_create: dentry %s/%s not negative!\n", -+ dentry->d_name.name, dchild->d_name.name); -+ goto out; -+ } - } - - if (!(iap->ia_valid & ATTR_MODE)) -@@ -903,16 +1071,19 @@ - err = nfserr_perm; - switch (type) { - case S_IFREG: -- err = vfs_create(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_create(dirp, dchild, iap->ia_mode); - break; - case S_IFDIR: -- err = vfs_mkdir(dirp, dchild, iap->ia_mode); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mkdir(dirp, dchild, iap->ia_mode); - break; - case S_IFCHR: - case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: -- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); -+ if (error == -EOPNOTSUPP) -+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); - break; - default: - printk("nfsd: bad file type %o in nfsd_create\n", type); -@@ -981,7 +1152,13 @@ - /* Get all the sanity checks out of the way before - * we lock the parent. */ - err = nfserr_notdir; -- if(!dirp->i_op || !dirp->i_op->lookup) -+ if (dirp->i_op->mknod_raw) { -+ err = mknod_raw(dentry, fname, flen, iap->ia_mode, 0); -+ if (err && err != -EOPNOTSUPP) -+ goto out_nfserr; -+ } -+ -+ if (!dirp->i_op || !(dirp->i_op->lookup || dirp->i_op->lookup_it)) - goto out; - fh_lock(fhp); - -@@ -1032,6 +1209,8 @@ - case NFS3_CREATE_GUARDED: - err = nfserr_exist; - } -+ if (dirp->i_op->mknod_raw) -+ err = 0; - goto out; - } - -@@ -1138,7 +1317,7 @@ - struct iattr *iap) - { - struct dentry *dentry, *dnew; -- int err, cerr; -+ int err, cerr, error = -EOPNOTSUPP; - - err = nfserr_noent; - if (!flen || !plen) -@@ -1152,12 +1331,18 @@ - goto out; - fh_lock(fhp); - dentry = fhp->fh_dentry; -+ -+ if (dentry->d_inode->i_op->symlink_raw) -+ error = symlink_raw(dentry, fname, flen, path); -+ - dnew = lookup_one_len(fname, dentry, flen); - err = PTR_ERR(dnew); - if (IS_ERR(dnew)) - goto out_nfserr; - -- err = vfs_symlink(dentry->d_inode, dnew, path); -+ err = error; -+ if (err == -EOPNOTSUPP || !dentry->d_inode->i_op->symlink_raw) -+ err = vfs_symlink(dentry->d_inode, dnew, path); - if (!err) { - if (EX_ISSYNC(fhp->fh_export)) - nfsd_sync_dir(dentry); -@@ -1167,7 +1352,10 @@ - iap->ia_valid |= ATTR_CTIME; - iap->ia_mode = (iap->ia_mode&S_IALLUGO) - | S_IFLNK; -- err = notify_change(dnew, iap); -+ if (dnew->d_inode->i_op && dnew->d_inode->i_op->setattr_raw) -+ err = setattr_raw(dnew->d_inode, iap); -+ else -+ err = notify_change(dnew, iap); - if (err) - err = nfserrno(err); - else if (EX_ISSYNC(fhp->fh_export)) -@@ -1227,7 +1415,10 @@ - dold = tfhp->fh_dentry; - dest = dold->d_inode; - -- err = vfs_link(dold, dirp, dnew); -+ if (dirp->i_op->link_raw) -+ err = link_raw(dold, ddir, dnew); -+ else -+ err = vfs_link(dold, dirp, dnew); - if (!err) { - if (EX_ISSYNC(ffhp->fh_export)) { - nfsd_sync_dir(ddir); -@@ -1312,7 +1503,10 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_rename(fdir, odentry, tdir, ndentry); -+ if (fdir->i_op->rename_raw) -+ err = rename_raw(fdentry, tdentry, odentry, ndentry); -+ else -+ err = vfs_rename(fdir, odentry, tdir, ndentry); - if (!err && EX_ISSYNC(tfhp->fh_export)) { - nfsd_sync_dir(tdentry); - nfsd_sync_dir(fdentry); -@@ -1333,7 +1527,7 @@ - fill_post_wcc(tfhp); - double_up(&tdir->i_sem, &fdir->i_sem); - ffhp->fh_locked = tfhp->fh_locked = 0; -- -+ - out: - return err; - } -@@ -1379,9 +1573,15 @@ - err = nfserr_perm; - } else - #endif -- err = vfs_unlink(dirp, rdentry); -+ if (dirp->i_op->unlink_raw) -+ err = unlink_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_unlink(dirp, rdentry); - } else { /* It's RMDIR */ -- err = vfs_rmdir(dirp, rdentry); -+ if (dirp->i_op->rmdir_raw) -+ err = rmdir_raw(dentry, fname, flen, rdentry); -+ else -+ err = vfs_rmdir(dirp, rdentry); - } - - dput(rdentry); -Index: linux-2.4.29/include/linux/fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs.h 2005-04-07 19:31:00.000000000 +0300 -+++ linux-2.4.29/include/linux/fs.h 2005-05-03 16:05:36.094614008 +0300 -@@ -93,6 +93,8 @@ - #define FS_SINGLE 8 /* Filesystem that can have only one superblock */ - #define FS_NOMOUNT 16 /* Never mount from userland */ - #define FS_LITTER 32 /* Keeps the tree in dcache */ -+#define FS_NFSEXP_FSID 64 /* Use file system specific fsid for -+ * exporting non device filesystems. */ - #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon - * as nfs_rename() will be cleaned up - */ -@@ -1118,6 +1120,9 @@ - struct nameidata *nd, struct lookup_intent *it); - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); -+extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, -+ struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1417,6 +1422,8 @@ - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -+extern struct dentry * lookup_one_len_it(const char *, struct dentry *, int, -+ struct lookup_intent *); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -@@ -1437,6 +1444,8 @@ - - extern struct inode * iget4_locked(struct super_block *, unsigned long, - find_inode_t, void *); -+extern struct inode * ilookup4(struct super_block *, unsigned long, -+ find_inode_t, void *); - - static inline struct inode *iget4(struct super_block *sb, unsigned long ino, - find_inode_t find_actor, void *opaque) -Index: linux-2.4.29/kernel/ksyms.c -=================================================================== ---- linux-2.4.29.orig/kernel/ksyms.c 2005-04-07 19:31:00.000000000 +0300 -+++ linux-2.4.29/kernel/ksyms.c 2005-05-03 16:04:09.445786632 +0300 -@@ -151,6 +151,7 @@ - EXPORT_SYMBOL(ilookup); - EXPORT_SYMBOL(iget4_locked); - EXPORT_SYMBOL(unlock_new_inode); -+EXPORT_SYMBOL(ilookup4); - EXPORT_SYMBOL(iput); - EXPORT_SYMBOL(inode_init_once); - EXPORT_SYMBOL(__inode_init_once); -@@ -164,6 +165,7 @@ - EXPORT_SYMBOL(path_release); - EXPORT_SYMBOL(__user_walk); - EXPORT_SYMBOL(lookup_one_len); -+EXPORT_SYMBOL(lookup_one_len_it); - EXPORT_SYMBOL(lookup_hash); - EXPORT_SYMBOL(sys_close); - EXPORT_SYMBOL(dcache_lock); diff --git a/lustre/kernel_patches/patches/nfs_export_kernel-getattr_on_lookup-2.4.patch b/lustre/kernel_patches/patches/nfs_export_kernel-getattr_on_lookup-2.4.patch deleted file mode 100644 index 2becbc4..0000000 --- a/lustre/kernel_patches/patches/nfs_export_kernel-getattr_on_lookup-2.4.patch +++ /dev/null @@ -1,64 +0,0 @@ ---- linux-2.4.24orig/include/linux/fs.h.orig 2006-07-21 13:03:15.000000000 +0300 -+++ linux-2.4.24/include/linux/fs.h 2006-07-21 13:03:46.000000000 +0300 -@@ -1128,6 +1128,8 @@ extern int open_namei_it(const char *fil - extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct lookup_intent *it); - extern int revalidate_it(struct dentry *dentry, struct lookup_intent *it); -+struct dentry * lookup_one_len_getattr(const char * name, struct dentry * base, -+ int len); - extern int init_private_file_it(struct file *, struct dentry *dentry, int mode, - struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); ---- linux-2.4.24orig/fs/nfsd/vfs.c.orig 2006-07-21 12:52:07.000000000 +0300 -+++ linux-2.4.24/fs/nfsd/vfs.c 2006-07-21 13:28:15.000000000 +0300 -@@ -198,6 +198,30 @@ int revalidate_it(struct dentry *dentry, - return err; - } - -+struct dentry * lookup_one_len_getattr(const char * name, struct dentry * base, -+ int len) -+{ -+ struct lookup_intent it; -+ struct dentry *de; -+ -+ intent_init(&it, IT_GETATTR, 0); -+ -+ de = lookup_one_len_it(name, base, len, NULL); -+ -+ if (!IS_ERR(de) && de->d_inode) { -+ if (de->d_inode->i_op && de->d_inode->i_op->revalidate_it) -+ de->d_inode->i_op->revalidate_it(de, &it); -+ else if (de->d_inode->i_op && de->d_inode->i_op->revalidate) -+ de->d_inode->i_op->revalidate(de); -+ } -+ -+ if (it.it_op_release) -+ intent_release(&it); -+ -+ return de; -+} -+ -+ - /* - * Look up one component of a pathname. - * N.B. After this call _both_ fhp and resfh need an fh_put -@@ -263,7 +287,7 @@ nfsd_lookup(struct svc_rqst *rqstp, stru - } - } else { - fh_lock(fhp); -- dentry = lookup_one_len(name, dparent, len); -+ dentry = lookup_one_len_getattr(name, dparent, len); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - goto out_nfserr; ---- linux-2.4.24orig/fs/nfsd/nfs3xdr.c.orig 2006-07-21 13:02:18.000000000 +0300 -+++ linux-2.4.24/fs/nfsd/nfs3xdr.c 2006-07-21 13:02:29.000000000 +0300 -@@ -715,7 +715,7 @@ encode_entry(struct readdir_cd *cd, cons - dchild = dchild->d_parent; - dchild = dget(dchild); - } else -- dchild = lookup_one_len(name, dparent,namlen); -+ dchild = lookup_one_len_getattr(name, dparent,namlen); - if (IS_ERR(dchild)) - goto noexec; - if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode) diff --git a/lustre/kernel_patches/patches/nfs_statfs-toomanyfiles-rhel-2.4.patch b/lustre/kernel_patches/patches/nfs_statfs-toomanyfiles-rhel-2.4.patch deleted file mode 100644 index 4bb8892..0000000 --- a/lustre/kernel_patches/patches/nfs_statfs-toomanyfiles-rhel-2.4.patch +++ /dev/null @@ -1,30 +0,0 @@ -Index: linux-2.4.21/fs/nfs/inode.c -=================================================================== ---- linux-2.4.21.orig/fs/nfs/inode.c 2005-06-01 22:51:55.000000000 -0400 -+++ linux-2.4.21/fs/nfs/inode.c 2005-06-01 23:38:54.883239912 -0400 -@@ -679,14 +679,21 @@ - goto too_big; - if (TOOBIG(((res.abytes + blockres) >> blockbits))) - goto too_big; -- if (TOOBIG(res.tfiles) || TOOBIG(res.afiles)) -- goto too_big; - - buf->f_blocks = (res.tbytes + blockres) >> blockbits; - buf->f_bfree = (res.fbytes + blockres) >> blockbits; - buf->f_bavail = (res.abytes + blockres) >> blockbits; -- buf->f_files = res.tfiles; -- buf->f_ffree = res.afiles; -+ -+ if (TOOBIG(res.tfiles)) -+ buf->f_files = -1; -+ else -+ buf->f_files = res.tfiles; -+ -+ if (TOOBIG(res.afiles)) -+ buf->f_ffree = -1; -+ else -+ buf->f_ffree = res.afiles; -+ - return 0; - - too_big: diff --git a/lustre/kernel_patches/patches/nfsd_iallocsem.patch b/lustre/kernel_patches/patches/nfsd_iallocsem.patch deleted file mode 100644 index 96b9c71..0000000 --- a/lustre/kernel_patches/patches/nfsd_iallocsem.patch +++ /dev/null @@ -1,19 +0,0 @@ -===== fs/nfsd/vfs.c 1.20 vs edited ===== ---- 1.20/fs/nfsd/vfs.c 2005-02-08 16:35:28 +02:00 -+++ edited/fs/nfsd/vfs.c 2005-05-29 00:46:44 +03:00 -@@ -297,6 +297,7 @@ - iap->ia_valid |= ATTR_CTIME; - - if (iap->ia_valid & ATTR_SIZE) { -+ down_write(&inode->i_alloc_sem); - fh_lock(fhp); - size_change = 1; - } -@@ -307,6 +308,7 @@ - } - if (size_change) { - fh_unlock(fhp); -+ up_write(&inode->i_alloc_sem); - put_write_access(inode); - } - if (!err) diff --git a/lustre/kernel_patches/patches/pagecache-lock-2.4.21-chaos.patch b/lustre/kernel_patches/patches/pagecache-lock-2.4.21-chaos.patch deleted file mode 100644 index 88f951b9..0000000 --- a/lustre/kernel_patches/patches/pagecache-lock-2.4.21-chaos.patch +++ /dev/null @@ -1,21 +0,0 @@ -Index: linux-2.4.21-chaos/include/linux/swap.h -=================================================================== ---- linux-2.4.21-chaos.orig/include/linux/swap.h 2003-12-12 16:24:33.000000000 +0300 -+++ linux-2.4.21-chaos/include/linux/swap.h 2003-12-12 16:41:15.000000000 +0300 -@@ -95,7 +95,7 @@ - extern atomic_t page_cache_size; - extern atomic_t buffermem_pages; - --#if 1 -+#if 0 - - static inline void - lock_pagecache(void) { br_write_lock(BR_PAGECACHE_LOCK); } -@@ -110,6 +110,7 @@ - - extern spinlock_cacheline_t pagecache_lock_cacheline; - #define __pagecache_lock (pagecache_lock_cacheline.lock) -+#define pagecache_lock (pagecache_lock_cacheline.lock) - - static inline void - lock_pagecache(void) { spin_lock(&__pagecache_lock); } diff --git a/lustre/kernel_patches/patches/procfs-ndynamic-2.4.21-suse2.patch b/lustre/kernel_patches/patches/procfs-ndynamic-2.4.21-suse2.patch deleted file mode 100644 index 65f4926..0000000 --- a/lustre/kernel_patches/patches/procfs-ndynamic-2.4.21-suse2.patch +++ /dev/null @@ -1,16 +0,0 @@ -Index: linux-2.4.21-suse2/include/linux/proc_fs.h -=================================================================== ---- linux-2.4.21-suse2.orig/include/linux/proc_fs.h 2004-01-12 09:56:51.000000000 +0300 -+++ linux-2.4.21-suse2/include/linux/proc_fs.h 2004-01-12 20:25:55.000000000 +0300 -@@ -25,11 +25,7 @@ - /* Finally, the dynamically allocatable proc entries are reserved: */ - - #define PROC_DYNAMIC_FIRST 4096 --#ifdef CONFIG_PPC64 - #define PROC_NDYNAMIC 16384 --#else --#define PROC_NDYNAMIC 4096 --#endif - - #define PROC_SUPER_MAGIC 0x9fa0 - diff --git a/lustre/kernel_patches/patches/procfs-ndynamic-2.4.patch b/lustre/kernel_patches/patches/procfs-ndynamic-2.4.patch deleted file mode 100644 index bff6c7e..0000000 --- a/lustre/kernel_patches/patches/procfs-ndynamic-2.4.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: linux-2.4.18-chaos/include/linux/proc_fs.h -=================================================================== ---- linux-2.4.18-chaos.orig/include/linux/proc_fs.h 2003-07-28 17:52:18.000000000 +0400 -+++ linux-2.4.18-chaos/include/linux/proc_fs.h 2004-01-12 20:12:38.000000000 +0300 -@@ -25,7 +25,7 @@ - /* Finally, the dynamically allocatable proc entries are reserved: */ - - #define PROC_DYNAMIC_FIRST 4096 --#define PROC_NDYNAMIC 4096 -+#define PROC_NDYNAMIC 16384 - - #define PROC_SUPER_MAGIC 0x9fa0 - diff --git a/lustre/kernel_patches/patches/qsnet-rhel-2.4.patch b/lustre/kernel_patches/patches/qsnet-rhel-2.4.patch deleted file mode 100644 index 6f53041..0000000 --- a/lustre/kernel_patches/patches/qsnet-rhel-2.4.patch +++ /dev/null @@ -1,93733 +0,0 @@ -Index: linux-2.4.21/arch/i386/kernel/i386_ksyms.c -=================================================================== ---- linux-2.4.21.orig/arch/i386/kernel/i386_ksyms.c 2005-06-01 22:51:51.000000000 -0400 -+++ linux-2.4.21/arch/i386/kernel/i386_ksyms.c 2005-06-01 23:12:54.521450960 -0400 -@@ -220,3 +220,12 @@ - EXPORT_SYMBOL_GPL(__PAGE_KERNEL); - extern unsigned long long __supported_pte_mask; - EXPORT_SYMBOL_GPL(__supported_pte_mask); -+ -+extern asmlinkage long sys_open(const char *, int, int); -+EXPORT_SYMBOL(sys_open); -+extern asmlinkage off_t sys_lseek(unsigned int, off_t, unsigned int); -+EXPORT_SYMBOL(sys_lseek); -+extern asmlinkage long sys_poll(struct pollfd *, unsigned int, long); -+EXPORT_SYMBOL(sys_poll); -+extern asmlinkage long sys_kill(int, int); -+EXPORT_SYMBOL(sys_kill); -Index: linux-2.4.21/arch/ia64/kernel/ia64_ksyms.c -=================================================================== ---- linux-2.4.21.orig/arch/ia64/kernel/ia64_ksyms.c 2005-06-01 22:51:59.000000000 -0400 -+++ linux-2.4.21/arch/ia64/kernel/ia64_ksyms.c 2005-06-01 23:14:43.773842072 -0400 -@@ -207,3 +207,13 @@ - EXPORT_SYMBOL_GPL(show_state); - EXPORT_SYMBOL_GPL(show_regs); - EXPORT_SYMBOL(pm_power_off); -+ -+#define __KERNEL_SYSCALLS__ 1 -+#include -+EXPORT_SYMBOL(sys_open); -+extern asmlinkage off_t sys_lseek(unsigned int, off_t, unsigned int); -+EXPORT_SYMBOL(sys_lseek); -+extern asmlinkage long sys_poll(struct pollfd *, unsigned int, long); -+EXPORT_SYMBOL(sys_poll); -+extern asmlinkage long sys_kill(int, int); -+EXPORT_SYMBOL(sys_kill); -Index: linux-2.4.21/arch/x86_64/kernel/x8664_ksyms.c -=================================================================== ---- linux-2.4.21.orig/arch/x86_64/kernel/x8664_ksyms.c 2005-06-01 22:51:51.000000000 -0400 -+++ linux-2.4.21/arch/x86_64/kernel/x8664_ksyms.c 2005-06-01 23:12:54.522450808 -0400 -@@ -215,6 +215,10 @@ - EXPORT_SYMBOL(sys_exit); - EXPORT_SYMBOL(sys_open); - EXPORT_SYMBOL(sys_lseek); -+extern asmlinkage long sys_poll(struct pollfd *, unsigned int, long); -+EXPORT_SYMBOL(sys_poll); -+extern asmlinkage long sys_kill(int, int); -+EXPORT_SYMBOL(sys_kill); - EXPORT_SYMBOL(sys_delete_module); - EXPORT_SYMBOL(sys_sync); - EXPORT_SYMBOL(sys_pause); -Index: linux-2.4.21/Documentation/Configure.help -=================================================================== ---- linux-2.4.21.orig/Documentation/Configure.help 2005-06-01 23:12:39.856680344 -0400 -+++ linux-2.4.21/Documentation/Configure.help 2005-06-01 23:12:54.547447008 -0400 -@@ -28030,6 +28030,54 @@ - kernel tree does. Such modules that use library CRC32 functions - require M here. - -+ -+Enable support for Quadrics QsNet (QSNET) -+CONFIG_QSNET -+ Quadrics QsNet is a high bandwidth, ultra low latency cluster -+ interconnect which provides both user and kernel programmers with -+ secure, direct access to the Quadrics network. -+ -+Elan 3 device driver (ELAN3) -+CONFIG_ELAN3 -+ This is the main device driver for the Quadrics QsNet (Elan3) PCI -+ device. This is a high bandwidth, ultra low latency interconnect -+ which provides both user and kernel programmers with secure, direct -+ access to the Quadrics network. -+ -+Elan 3 Kernel Comms (EP3) -+CONFIG_EP3 -+ This modules implements the QsNet kernel communications layer. This -+ is used to layer kernel level facilities on top of the basic Elan3 -+ device driver. These can be used to implement subsystems such as -+ TCP/IP and remote filing systems over the QsNet interconnect. -+ -+Elan IP device (EIP) -+CONFIG_EIP -+ This is a network IP device driver for the Quadrics QsNet device. -+ It allows the TCP/IP protocol to be run over the Quadrics interconnect. -+ -+Elan 4 device driver (ELAN4) -+CONFIG_ELAN4 -+ This is the main device driver for the Quadrics QsNetII (Elan4) PCI-X -+ device. This is a high bandwidth, ultra low latency interconnect which -+ provides both user and kernel programmers with secure, direct access to -+ the Quadrics network. -+Resource Management System support (RMS) -+CONFIG_RMS -+ This is a support module for the Quadrics RMS resource manager. It -+ provides kernel services for monitoring and controlling user job -+ execution, termination and cleanup. -+ -+Switch monitoring (JTAG) -+CONFIG_JTAG -+ The jtag interface is used to allow processes to send and retrieve jtag -+ information to a Quadrics QsNet Elite switch via the parallel port. -+ The module requires a /dev/jtag[0-3] entry (usually there is only a -+ /dev/jtag0) device and a particular device only allows one process at a -+ time to access this resource. -+ For more information about JTag interface, please refer to the IEEE -+ document on http://www.ieee.org -+ - # - # A couple of things I keep forgetting: - # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, -Index: linux-2.4.21/drivers/net/Config.in -=================================================================== ---- linux-2.4.21.orig/drivers/net/Config.in 2005-06-01 22:52:03.000000000 -0400 -+++ linux-2.4.21/drivers/net/Config.in 2005-06-01 23:12:54.549446704 -0400 -@@ -272,6 +272,9 @@ - - endmenu - -+# Quadrics QsNet -+source drivers/net/qsnet/Config.in -+ - if [ "$CONFIG_PPC_ISERIES" = "y" ]; then - dep_tristate 'iSeries Virtual Ethernet driver support' CONFIG_VETH $CONFIG_PPC_ISERIES - fi -Index: linux-2.4.21/drivers/net/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/Makefile 2005-06-01 22:52:03.000000000 -0400 -+++ linux-2.4.21/drivers/net/Makefile 2005-06-01 23:12:54.550446552 -0400 -@@ -8,7 +8,7 @@ - obj-n := - obj- := - --mod-subdirs := appletalk arcnet fc irda tokenring pcmcia wireless wireless_old wan -+mod-subdirs := appletalk arcnet fc irda tokenring pcmcia wireless wireless_old wan qsnet - - O_TARGET := net.o - -@@ -48,6 +48,7 @@ - subdir-$(CONFIG_DEV_APPLETALK) += appletalk - subdir-$(CONFIG_SK98LIN) += sk98lin - subdir-$(CONFIG_SKFP) += skfp -+subdir-$(CONFIG_QSNET) += qsnet - subdir-$(CONFIG_E100) += e100 - subdir-$(CONFIG_E1000) += e1000 - subdir-$(CONFIG_BONDING) += bonding -Index: linux-2.4.21/drivers/net/qsnet/Config.in -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/Config.in 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/Config.in 2005-06-01 23:12:54.550446552 -0400 -@@ -0,0 +1,25 @@ -+# -+# Config.in for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/Config.in -+# -+ -+mainmenu_option next_comment -+comment "Quadrics QsNet device support" -+ -+dep_tristate "Enable support for Quadrics QsNet" CONFIG_QSNET $CONFIG_PCI -+ -+dep_tristate "Elan 3 device driver" CONFIG_ELAN3 $CONFIG_QSNET -+dep_tristate "Elan 4 device driver" CONFIG_ELAN4 $CONFIG_QSNET -+ -+if [ "$CONFIG_ELAN3" = "$CONFIG_QSNET" ] || [ "$CONFIG_ELAN4" = "$CONFIG_QSNET" ]; then -+ dep_tristate "Elan Kernel Comms" CONFIG_EP $CONFIG_QSNET -+fi -+dep_tristate "Elan IP device" CONFIG_EIP $CONFIG_NET $CONFIG_EP -+ -+dep_tristate "Resource Management System support" CONFIG_RMS $CONFIG_QSNET -+dep_tristate "Switch monitoring" CONFIG_JTAG $CONFIG_QSNET -+ -+endmenu -Index: linux-2.4.21/drivers/net/qsnet/eip/eip_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/eip_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/eip_linux.c 2005-06-01 23:12:54.553446096 -0400 -@@ -0,0 +1,1565 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: eip_linux.c,v 1.89.2.3 2004/12/20 16:54:05 mike Exp $" -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#undef ASSERT -+#include -+#include -+ -+ -+ -+#include -+#include -+ -+#include "eip_linux.h" -+#include "eip_stats.h" -+ -+#ifdef UNUSED -+static void eip_skb_display(struct sk_buff *); -+#endif -+static void eip_iph_display(struct iphdr *); -+#ifdef UNUSED -+static void eip_eiph_display(EIP_HEADER *); -+static void eip_packet_display(unsigned char *); -+#endif -+static void eip_tmd_display(EIP_TMD *); -+static void eip_tmd_head_display(EIP_TMD_HEAD *); -+static void eip_rmd_display(EIP_RMD *); -+static void eip_rmd_head_display(EIP_RMD_HEAD *); -+ -+static void eip_rmd_reclaim(EIP_RMD *); -+ -+static inline EP_NMH *eip_dma_reserve(int, int); -+static inline void __eip_tmd_load(EIP_TMD *, EP_RAILMASK *); -+static inline void __eip_tmd_unload(EIP_TMD *); -+static inline unsigned long eip_buff_alloc(int, int); -+static inline void eip_buff_free(unsigned long, int); -+static struct iphdr *eip_ipfrag_get(char *); -+static inline void eip_rmd_free(EIP_RMD *); -+static inline void eip_skb_load(EIP_RMD *); -+static inline void eip_skb_unload(EIP_RMD *); -+static inline void eip_rmd_requeue(EIP_RMD *); -+static EIP_RMD *eip_rmd_alloc(int, int); -+static int eip_rmd_alloc_replace(EIP_RMD *, int, int); -+static int eip_rmd_alloc_queue(int, int, int, int); -+static int eip_rmds_alloc(void); -+static void eip_rxhandler(EP_RXD *); -+static void eip_rx_tasklet(unsigned long); -+static inline void eip_tmd_init(EIP_TMD *, unsigned long, EIP_TMD_HEAD *, unsigned long, int); -+static inline EIP_TMD *eip_tmd_get(int); -+static inline void eip_tmd_put(EIP_TMD *); -+static inline void eip_tmd_load(EIP_TMD *); -+static inline void eip_tmd_unload(EIP_TMD *); -+static inline EIP_TMD *eip_tmd_alloc_queue(EIP_TMD *, EIP_TMD_HEAD *, int); -+static inline EIP_TMD *eip_tmd_alloc_queue_copybreak(EIP_TMD_HEAD *, int); -+static inline EIP_TMD *eip_tmd_alloc_queue_aggreg(EIP_TMD_HEAD *, int); -+static int eip_tmds_alloc(void); -+int eip_hard_start_xmit(struct sk_buff *, struct net_device *); -+static inline int eip_do_xmit(EIP_TMD *, EP_NMD *i, EP_PAYLOAD *); -+static void eip_txhandler(EP_TXD *, void *, EP_STATUS); -+static void eip_tx_tasklet(unsigned long); -+void eip_stop_queue(void); -+void eip_start_queue(void); -+static int eip_open(struct net_device *); -+static int eip_close(struct net_device *); -+static struct net_device_stats *eip_get_stats(struct net_device *); -+static int eip_change_mtu(struct net_device *, int); -+ -+static int eip_rx_dropping = 0; -+static int eip_rx_tasklet_locked = 1; -+ -+/* Global */ -+struct timer_list eip_rx_tasklet_timer; -+ -+EIP_RX *eip_rx = NULL; -+EIP_TX *eip_tx = NULL; -+int eip_checksum_state=CHECKSUM_NONE; -+ -+int tmd_max = EIP_TMD_MAX_NR; -+int rmd_max = EIP_RMD_MAX_NR; -+int rx_envelope_nr = EIP_RX_ENVELOPE_NR; -+int rx_granularity = EIP_RX_GRANULARITY; -+int tx_copybreak_max = EIP_TX_COPYBREAK_MAX; -+EP_RAILMASK tx_railmask = EP_RAILMASK_ALL; -+int eipdebug = 0; -+ -+#ifdef UNUSED -+static void eip_skb_display(struct sk_buff *skb) -+{ -+ if (skb) { -+ __EIP_DBG_PRINTF("SKB [%p] : len %d truesize %d proto %x pkt type %x cloned %d users %d summed %d\n", -+ skb, skb->len, skb->truesize, skb->protocol, skb->pkt_type, skb->cloned, atomic_read(&skb->users), skb->ip_summed); -+ __EIP_DBG_PRINTF("SKB [%p] : skb_shinfo dataref %d nr_frags %d frag_list[%p] (device %p)\n", skb, -+ atomic_read(&skb_shinfo(skb)->dataref), skb_shinfo(skb)->nr_frags, skb_shinfo(skb)->frag_list, skb->dev); -+ __EIP_DBG_PRINTF("SKB [%p] : head[%p] data[%p] tail [%p] end [%p] data_len [%d]\n", skb, skb->head, skb->data, -+ skb->tail, skb->end, skb->data_len); -+ __EIP_DBG_PRINTF("SKB [%p] : Transport Layer h.(th, uh, icmph, raw)[%p]\n", skb, skb->h.th); -+ __EIP_DBG_PRINTF("SKB [%p] : Network Layer nh.(iph, arph, raw)[%p]\n", skb, skb->nh.iph); -+ __EIP_DBG_PRINTF("SKB [%p] : Link Layer mac.(ethernet, raw)[%p]\n", skb, skb->mac.ethernet); -+ return; -+ } -+ EIP_ERR_PRINTF("SKB IS NULL - NO SKB TO DISPLAY\n"); -+} -+#endif -+static void eip_iph_display(struct iphdr *iph) -+{ -+ if (iph) { -+ __EIP_DBG_PRINTF("IPH [%p] : version %d header len %d TOS 0x%x Total len %d\n", -+ iph, iph->version, iph->ihl, htons(iph->tos), htons(iph->tot_len)); -+ __EIP_DBG_PRINTF("IPH [%p] : id %d frag flags 0x%x offset %d\n", -+ iph, htons(iph->id), (iph->frag_off & htons(IP_CE | IP_DF | IP_MF)) >> 4, -+ (htons(iph->frag_off) << 3) & IP_OFFSET); -+ __EIP_DBG_PRINTF("IPH [%p] : TTL %d proto %d header checksum 0x%x\n", iph, iph->ttl, iph->protocol, iph->check); -+ __EIP_DBG_PRINTF("IPH [%p] : IP src %u.%u.%u.%u dest %u.%u.%u.%u\n", iph, -+ ((unsigned char *)&(iph->saddr))[0],((unsigned char *)&(iph->saddr))[1], ((unsigned char *)&(iph->saddr))[2],((unsigned char *)&(iph->saddr))[3], -+ ((unsigned char *)&(iph->daddr))[0],((unsigned char *)&(iph->daddr))[1], ((unsigned char *)&(iph->daddr))[2],((unsigned char *)&(iph->daddr))[3]); -+ return; -+ } -+ EIP_ERR_PRINTF("IPH IS NULL - NO IPH TO DISPLAY\n"); -+} -+#ifdef UNUSED -+static void eip_eiph_display(EIP_HEADER * eiph) -+{ -+ if (eiph) { -+ __EIP_DBG_PRINTF("EIPH [%p] : dhost %04x.%04x.%04x sap %x\n", eiph, eiph->h_dhost.ip_bcast, eiph->h_dhost.ip_inst, -+ eiph->h_dhost.ip_addr, eiph->h_sap); -+ __EIP_DBG_PRINTF("EIPH [%p] : shost %04x.%04x.%04x \n", eiph, eiph->h_shost.ip_bcast, eiph->h_shost.ip_inst, -+ eiph->h_shost.ip_addr); -+ return; -+ } -+ EIP_ERR_PRINTF("EIPH IS NULL - NO EIPH TO DISPLAY\n"); -+} -+static void eip_packet_display(unsigned char *data) -+{ -+ eip_eiph_display((EIP_HEADER *) data); -+ eip_iph_display((struct iphdr *) (data + EIP_HEADER_PAD + ETH_HLEN)); -+} -+#endif -+static void eip_tmd_display(EIP_TMD * tmd) -+{ -+ if (tmd) { -+ __EIP_DBG_PRINTF("\t\tTMD [%p] : next[%p] skb[%p] DVMA[%d]\n", tmd, tmd->chain.next, tmd->skb, tmd->dvma_idx); -+ if (tmd->dma_base) -+ __EIP_DBG_PRINTF("TMD [%p] : head[%p] *data 0x%lx\n", tmd, tmd->head, *((unsigned long *) tmd->dma_base)); -+ else -+ __EIP_DBG_PRINTF("TMD [%p] : head[%p] NO DATA !!!\n", tmd, tmd->head); -+ __EIP_DBG_PRINTF("TMD [%p] : DMA(%lx,%d,%d) ebase[%x]\n",tmd, tmd->dma_base, tmd->dma_len, tmd->nmd.nmd_len, -+ tmd->nmd.nmd_addr); -+ return; -+ } -+ EIP_ERR_PRINTF("TMD IS NULL - NO TMD TO DISPLAY\n"); -+ -+} -+static void eip_ipf_display(EIP_IPFRAG * ipf) -+{ -+ if (ipf) { -+ __EIP_DBG_PRINTF("IPF[%p] : datagram len %d dma correction %d uts %lx frag_nr %d\n", ipf, ipf->datagram_len, -+ ipf->dma_correction, ipf->timestamp.tv_usec, ipf->frag_nr); -+ eip_tmd_display((EIP_TMD *) ipf); -+ return; -+ } -+ EIP_ERR_PRINTF("IPF IS NULL - NO IPF TO DISPLAY\n"); -+} -+ -+static void eip_tmd_head_display(EIP_TMD_HEAD * head) -+{ -+ if (head) { -+ __EIP_DBG_PRINTF("TMD HEAD [%p] : handle[%p] tmds[%p] %3.3d/%3.3d/%3.3d\n", head, head->handle, head->tmd, -+ EIP_STAT_QUEUED_GET(&head->stats), EIP_STAT_ALLOC_GET(&head->stats), -+ eip_tx->tmd_max_nr); -+ return; -+ } -+ EIP_ERR_PRINTF("TMD HEAD IS NULL - NO TMD HEAD TO DISPLAY\n"); -+} -+static void eip_rmd_display(EIP_RMD * rmd) -+{ -+ if (rmd) { -+ __EIP_DBG_PRINTF("RMD [%p] : next[%p] rxd[%p] DVMA[%d]\n", rmd, rmd->chain.next, rmd->rxd, rmd->dvma_idx); -+ __EIP_DBG_PRINTF("RMD [%p] : head[%p]\n", rmd, rmd->head); -+ __EIP_DBG_PRINTF("RMD [%p] : ebase[%x]\n", rmd, rmd->nmd.nmd_addr); -+ return; -+ } -+ EIP_ERR_PRINTF("RMD IS NULL - NO RMD TO DISPLAY\n"); -+} -+static void eip_rmd_head_display(EIP_RMD_HEAD * head) -+{ -+ if (head) { -+ __EIP_DBG_PRINTF("RMD HEAD [%p] : rcvr[%p] handle[%p] busy list[%p]\n", head, head->rcvr, head->handle, head->busy_list); -+ __EIP_DBG_PRINTF("RMD HEAD [%p] : %3.3d/%3.3d/%3.3d\n", head, -+ EIP_STAT_QUEUED_GET(&head->stats), EIP_STAT_ALLOC_GET(&head->stats), eip_rx->rmd_max_nr); -+ return; -+ } -+ EIP_ERR_PRINTF("RMD HEAD IS NULL - NO RMD HEAD TO DISPLAY\n"); -+} -+ -+/* END - DISPLAY FUNCTIONS */ -+static inline EP_NMH *eip_dma_reserve(int pages_nr, int perm) -+{ -+ EP_NMH *handle = ep_dvma_reserve(eip_tx->ep_system, pages_nr, perm); -+ -+ if (handle) -+ EIP_DBG_PRINTF(EIP_DBG_EP_DVMA, "HANDLE [%p] %d pages of elan address space reserved\n", -+ handle, pages_nr); -+ else -+ EIP_ERR_PRINTF("cannot reserve %d page(s) of elan address space\n", pages_nr); -+ -+ return handle; -+} -+ -+static inline void __eip_tmd_load(EIP_TMD * tmd, EP_RAILMASK *rmask) -+{ -+ EIP_ASSERT(tmd->nmd.nmd_len > 0); -+ -+ ep_dvma_load(eip_tx->ep_system, NULL, (caddr_t) tmd->dma_base, tmd->nmd.nmd_len, tmd->head->handle, -+ tmd->dvma_idx, rmask, &tmd->nmd); -+} -+ -+static inline void __eip_tmd_unload(EIP_TMD * tmd) -+{ -+ EIP_ASSERT(tmd->nmd.nmd_addr && tmd->head->handle); -+ -+ ep_dvma_unload(eip_tx->ep_system, tmd->head->handle, &tmd->nmd); -+ tmd->nmd.nmd_addr = 0; -+} -+static inline unsigned long eip_buff_alloc(int buff_len, int gfp) -+{ -+ unsigned long buff_base = (buff_len < PAGE_SIZE) ? -+ (unsigned long) kmalloc(buff_len, gfp) : -+ __get_dma_pages(gfp, get_order(buff_len)); -+ -+ if (likely(buff_base)) -+ return buff_base; -+ -+ EIP_ERR_PRINTF("cannot allocate %db of memory\n", buff_len); -+ return 0; -+} -+static inline void eip_buff_free(unsigned long buff_base, int buff_len) -+{ -+ (buff_len < PAGE_SIZE) ? kfree((void *) buff_base) : -+ free_pages(buff_base, get_order(buff_len)); -+} -+static struct iphdr *eip_ipfrag_get(char *data) -+{ -+ struct ethhdr *eh = (struct ethhdr *) (data); -+ struct iphdr *iph; -+ -+ if (eh->h_proto == htons(ETH_P_IP)) { -+ iph = (struct iphdr *) ((char *) eh + ETH_HLEN); -+ -+ /* EIP_DBG(eip_iph_display(iph)); */ -+ -+ if ((iph->frag_off & htons(IP_MF | IP_OFFSET))) -+ return iph; -+ } -+ return NULL; -+} -+ -+static inline void eip_rmd_free(EIP_RMD * rmd) -+{ -+ EIP_ASSERT2(rmd->nmd.nmd_addr == 0, eip_rmd_display, rmd); -+ -+ if ( rmd->skb != NULL) -+ kfree_skb (rmd->skb); -+ -+ kfree(rmd); -+ -+ EIP_DBG_PRINTF(EIP_DBG_MEMFREE, "RMD [%p] : FREED\n", rmd); -+} -+static inline void eip_skb_load(EIP_RMD * rmd) -+{ -+ EP_RAILMASK rmask = rmd->rxd ? ep_rxd_railmask (rmd->rxd) : 0; -+ -+ EIP_ASSERT(skb_tailroom(rmd->skb) > 0); -+ -+ ep_dvma_load(eip_tx->ep_system, NULL, (caddr_t) rmd->skb->data, skb_tailroom(rmd->skb), rmd->head->handle, -+ rmd->dvma_idx, &rmask, &rmd->nmd); -+ -+ EIP_DBG_PRINTF(EIP_DBG_RMD_EP_DVMA, "RMD [%p] : LOADED\n", rmd); -+} -+static inline void eip_skb_unload(EIP_RMD * rmd) -+{ -+ EIP_ASSERT(rmd->nmd.nmd_addr && rmd->head->handle); -+ -+ ep_dvma_unload(eip_tx->ep_system, rmd->head->handle, &rmd->nmd); -+ rmd->nmd.nmd_addr = 0; -+ -+ EIP_DBG_PRINTF(EIP_DBG_RMD_EP_DVMA, "RMD [%p] : UNLOADED\n", rmd); -+} -+static inline void eip_rmd_requeue(EIP_RMD * rmd) -+{ -+ EIP_ASSERT(rmd->rxd); -+ -+ rmd->chain.next = NULL; -+ -+ ep_requeue_receive(rmd->rxd, eip_rxhandler, rmd, &rmd->nmd, EP_NO_ALLOC|EP_NO_SLEEP ); -+ -+ atomic_inc(&rmd->head->stats); -+ -+ EIP_DBG_PRINTF(EIP_DBG_RMD_QUEUE, "RMD [%p] : REQUEUED\n", rmd); -+} -+static EIP_RMD * eip_rmd_alloc(int svc, int gfp) -+{ -+ int buff_len = EIP_SVC_SMALLEST_LEN << svc; -+ EIP_RMD *rmd; -+ struct sk_buff *skb; -+ -+ if (!(skb = alloc_skb((buff_len - EIP_EXTRA), gfp))) -+ return NULL; -+ -+ skb_reserve(skb, 2); -+ -+ if (!(rmd = (EIP_RMD *) kmalloc(buff_len, gfp))) { -+ kfree_skb(skb); -+ return NULL; -+ } -+ -+ rmd->skb = skb; -+ -+ rmd->chain.next = NULL; -+ rmd->rxd = NULL; -+ rmd->head = &eip_rx->head[svc]; -+ -+ return rmd; -+} -+ -+static int eip_rmd_alloc_replace(EIP_RMD *rmd, int svc, int gfp) -+{ -+ struct sk_buff *skb,*old; -+ int buff_len = EIP_SVC_SMALLEST_LEN << svc; -+ -+ if (!(skb = alloc_skb(buff_len, gfp))) -+ return 1; -+ -+ skb_reserve(skb, 2); -+ -+ eip_skb_unload(rmd); -+ -+ old = rmd->skb; -+ rmd->skb = skb; -+ -+ eip_skb_load(rmd); -+ -+ eip_rmd_requeue(rmd); -+ -+ kfree_skb(old); -+ -+ return 0; -+} -+ -+static int eip_rmd_alloc_queue(int svc, int dvma_idx, int gfp, int attr) -+{ -+ EIP_RMD * rmd = eip_rmd_alloc(svc, gfp); -+ -+ if (!rmd) -+ return 1; -+ -+ EIP_STAT_ALLOC_ADD(&rmd->head->stats, 1); -+ -+ rmd->dvma_idx = dvma_idx; -+ eip_skb_load(rmd); -+ -+ EIP_DBG2(EIP_DBG_RMD, eip_rmd_display, rmd, "RMD [%p] : ALLOCATED for SVC 0x%x\n", rmd, svc); -+ -+ if (ep_queue_receive(rmd->head->rcvr, eip_rxhandler, (void *) rmd, &rmd->nmd, attr) == ESUCCESS) { -+ atomic_inc(&rmd->head->stats); -+ EIP_DBG_PRINTF(EIP_DBG_RMD_QUEUE, "RMD [%p] : QUEUED on SVC 0x%x\n", rmd, svc); -+ return 0; -+ } -+ -+ EIP_ERR_PRINTF("RMD [%p] : couldn't be QUEUED on SVC 0x%x\n", rmd, svc); -+ -+ EIP_STAT_ALLOC_SUB(&rmd->head->stats, 1); -+ -+ eip_skb_unload(rmd); -+ eip_rmd_free(rmd); -+ -+ return 1; -+} -+ -+static int eip_rmds_alloc(void) -+{ -+ int idx, svc; -+ -+ eip_rx->irq_list = NULL; -+ eip_rx->irq_list_nr = 0; -+ -+ for (svc = 0; svc < EIP_SVC_NR; svc++) { -+ eip_rx->head[svc].rcvr = ep_alloc_rcvr(eip_tx->ep_system, EIP_SVC_EP(svc), rx_envelope_nr); -+ if (!eip_rx->head[svc].rcvr) { -+ EIP_ERR_PRINTF("Cannot install receiver for SVC 0x%x - maybe cable is disconnected\n", svc); -+ return -EAGAIN; -+ } -+ -+ eip_rx->head[svc].handle = -+ eip_dma_reserve(EIP_DVMA_PAGES((EIP_SVC_SMALLEST_LEN << svc)) * eip_rx->rmd_max_nr, -+ EP_PERM_WRITE); -+ if (!eip_rx->head[svc].handle) -+ return -ENOMEM; -+ -+ EIP_DBG(EIP_DBG_RMD_HEAD, eip_rmd_head_display, &eip_rx->head[svc]); -+ -+ for (idx = 0; idx < EIP_RMD_NR; idx++) { -+ if (eip_rmd_alloc_queue(svc, idx * EIP_DVMA_PAGES((EIP_SVC_SMALLEST_LEN << svc)), -+ GFP_KERNEL, EP_NO_SLEEP)) -+ return -ENOMEM; -+ } -+ } -+ return 0; -+} -+static void eip_rmds_free(void) -+{ -+ unsigned long flags; -+ EIP_RMD *rmd; -+ int svc; -+ -+ spin_lock_irqsave(&eip_rx->lock, flags); -+ rmd = eip_rx->irq_list; -+ eip_rx->irq_list = NULL; -+ eip_rx->irq_list_nr = 0; -+ spin_unlock_irqrestore(&eip_rx->lock, flags); -+ -+ eip_rmd_reclaim(rmd); -+ -+ for (svc = 0; svc < EIP_SVC_NR ; svc++) { -+ -+ while ((rmd = eip_rx->head[svc].busy_list)) { -+ eip_rx->head[svc].busy_list = NULL; -+ eip_rmd_reclaim(rmd); -+ if (eip_rx->head[svc].busy_list) { -+ EIP_DBG_PRINTF(EIP_DBG_RMD_QUEUE, "Still RMD [%p] on BUSY list SVC 0x%d - Scheduling\n", rmd, svc); -+ schedule(); -+ } -+ } -+ -+ EIP_ASSERT(EIP_STAT_QUEUED_GET(&eip_rx->head[svc].stats) == EIP_STAT_ALLOC_GET(&eip_rx->head[svc].stats)); -+ -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "HEAD[%p] : FREEING RCVR [%p]\n", &eip_rx->head[svc], -+ eip_rx->head[svc].rcvr); -+ -+ ep_free_rcvr(eip_rx->head[svc].rcvr); -+ -+ EIP_DBG_PRINTF(EIP_DBG_EP_DVMA, "HEAD[%p] : RELEASING DVMA [%p]\n", &eip_rx->head[svc], -+ eip_rx->head[svc].handle); -+ -+ ep_dvma_release(eip_tx->ep_system, eip_rx->head[svc].handle); -+ } -+ -+} -+static int eip_rx_queues_low (void) { -+ int svc; -+ for (svc = 0; svc < EIP_SVC_NR; svc++) -+ if (EIP_STAT_QUEUED_GET(&eip_rx->head[svc].stats) < EIP_RMD_ALLOC_THRESH) -+ return (1); -+ return (0); -+} -+static void eip_rxhandler(EP_RXD * rxd) -+{ -+ EIP_RMD *rmd = (EIP_RMD *) ep_rxd_arg(rxd); -+ EP_STATUS ret = ep_rxd_status(rxd); -+ EP_PAYLOAD * payload = ep_rxd_payload(rxd); -+ unsigned long data = (unsigned long) rmd->skb->data; -+ int frag_nr = 0; -+ int len; -+ -+ struct sk_buff *skb; -+ static char count = 0; -+ -+ atomic_dec(&rmd->head->stats); -+ rmd->rxd = rxd; -+ -+ if (likely(ret == EP_SUCCESS)) { -+ -+ rmd->head->dma++; -+ -+ if ( eip_rx_dropping) { -+ eip_rmd_requeue(rmd); -+ return; -+ } -+ -+ len = (payload) ? payload->Data[frag_nr++] : ep_rxd_len(rxd); -+ -+ EIP_DBG(EIP_DBG_RMD, eip_rmd_display, rmd); -+ -+again: -+ if ( (skb = skb_clone(rmd->skb, GFP_ATOMIC)) ) { -+ unsigned int off = (data - (unsigned long) rmd->skb->data); -+ -+ /* have to set the length before calling -+ * skb pull as it will not allow you to -+ * pull past the end */ -+ -+ skb_put (skb, off + len); -+ skb_pull (skb, off); -+ -+ skb->protocol = eth_type_trans(skb, eip_rx->net_device); -+ skb->ip_summed = eip_checksum_state; -+ skb->dev = eip_rx->net_device; -+ -+ /* Fabien/David/Mike this is a hack/fix to allow aggrigation of packets to work. -+ * The problem is ip_frag looks at the truesize to see if it is caching too much space. -+ * As we are reusing a large skb (cloned) for a number of small fragments, they appear to take up alot of space. -+ * so ip_frag dropped them after 4 frags (not good). So we lie and set the truesize to just bigger than the data. -+ */ -+ if (payload) -+ skb->truesize = SKB_DATA_ALIGN(skb->len + EIP_HEADER_PAD) +sizeof(struct sk_buff); -+ -+ } -+ if ( (skb) && -+ (netif_rx(skb) != NET_RX_DROP)){ -+ -+ eip_rx->bytes += len; -+ -+ if (payload && payload->Data[frag_nr] ) { -+ data += EIP_IP_ALIGN(len); -+ len = payload->Data[frag_nr++]; -+ goto again; -+ } -+ eip_rx->packets += ++frag_nr; -+ } else if ( (eip_rx->dropped++ % 20) == 0) -+ __EIP_DBG_PRINTK("Packet dropped by the TCP/IP stack - increase /proc/sys/net/core/netdev_max_backlog\n"); -+ } else if (ret == EP_SHUTDOWN ) { -+ EIP_DBG2(EIP_DBG_RMD, eip_rmd_display, rmd, "ABORTING\n"); -+ ep_complete_receive(rxd); -+ eip_skb_unload(rmd); -+ EIP_STAT_ALLOC_SUB(&rmd->head->stats, 1); -+ eip_rmd_free(rmd); -+ return; -+ } else { -+ EP_ENVELOPE *env = ep_rxd_envelope(rxd); -+ EP_NMD *nmd ; -+ -+ EIP_ERR_PRINTF("RMD[%p] : RECEIVE ret = %d\n", rmd, ret); -+ -+ for (len = 0 ; len < env->nFrags ; len++) { -+ nmd = &env->Frags[len]; -+ EIP_ERR_PRINTF("RMD[%p] : ep_frag #%d nmd_addr [%x] nmd_len %d\n", rmd, len, -+ (unsigned int) nmd->nmd_addr, nmd->nmd_len); -+ } -+ eip_rx->errors++; -+ EIP_ASSERT2(atomic_read(&skb_shinfo(rmd->skb)->dataref) == 1, eip_rmd_display, rmd); -+ } -+ -+ /* data is used to store the irq flags */ -+ spin_lock_irqsave(&eip_rx->lock, data); -+ rmd->chain.next = eip_rx->irq_list; -+ eip_rx->irq_list = rmd; -+ eip_rx->irq_list_nr++; -+ spin_unlock_irqrestore(&eip_rx->lock, data); -+ -+ if ( !timer_pending (&eip_rx_tasklet_timer) /* the timer not already set */ -+ && ( (count++ % eip_rx->sysctl_granularity) /* and either we have passed up a number of them */ -+ || eip_rx_queues_low() )) /* or we are low */ -+ mod_timer (&eip_rx_tasklet_timer, lbolt + 1); -+} -+ -+/* dest ; if the buffer still reference on it mocve the rmd to the dest list */ -+static void eip_rmd_reclaim(EIP_RMD *rmd) -+{ -+ EIP_RMD *rmd_next = rmd; -+ int dataref; -+ -+ while (rmd_next) { -+ rmd = rmd_next; -+ rmd_next = rmd_next->chain.next; -+ -+ dataref = atomic_read(&skb_shinfo(rmd->skb)->dataref); -+ EIP_ASSERT(dataref > 0); -+ -+ if (dataref == 1) { -+ eip_rmd_requeue(rmd); -+ } else { -+ rmd->chain.next = rmd->head->busy_list; -+ rmd->head->busy_list = rmd; -+ } -+ } -+} -+static void eip_rx_tasklet(unsigned long arg) -+{ -+ EIP_RMD *rmd, *rmd_next; -+ unsigned long flags; -+ short svc, queued; -+ int needs_reschedule; -+ -+ if (eip_rx_tasklet_locked) /* we dont want the tasklet to do anything when we are finishing */ -+ return; -+ -+ for (svc = 0; svc < EIP_SVC_NR; svc++) { -+ rmd = eip_rx->head[svc].busy_list; -+ eip_rx->head[svc].busy_list = NULL; -+ eip_rmd_reclaim(rmd); -+ } -+ -+ spin_lock_irqsave(&eip_rx->lock, flags); -+ rmd = eip_rx->irq_list; -+ eip_rx->irq_list = NULL; -+ eip_rx->irq_list_nr = 0; -+ spin_unlock_irqrestore(&eip_rx->lock, flags); -+ -+ eip_rmd_reclaim(rmd); -+ -+ needs_reschedule = 0; -+ -+ for (svc = 0; svc < EIP_SVC_NR; svc++) { -+ /* the plan is : allocate some more if possible or steall some dvma space from those on the EIP_BUSY_LIST */ -+ queued = EIP_STAT_QUEUED_GET(&eip_rx->head[svc].stats); -+ -+ EIP_ASSERT(queued >= 0 && queued <= EIP_RMD_MAX_NR); -+ -+ if (queued < EIP_RMD_ALLOC_THRESH) { -+ short allocated = EIP_STAT_ALLOC_GET(&eip_rx->head[svc].stats); -+ short how_many; -+ -+ EIP_ASSERT(allocated >= 0 && allocated <= EIP_RMD_MAX_NR); -+ -+ if (likely(allocated < eip_rx->rmd_max_nr)) { -+ -+ how_many = (((allocated / EIP_RMD_ALLOC_STEP) + 1) * EIP_RMD_ALLOC_STEP); -+ if (how_many > eip_rx->rmd_max_nr) -+ how_many = eip_rx->rmd_max_nr; -+ -+ for (; allocated < how_many && -+ (eip_rmd_alloc_queue(svc, allocated * EIP_DVMA_PAGES((EIP_SVC_SMALLEST_LEN << svc)), -+ GFP_ATOMIC, EP_NO_ALLOC|EP_NO_SLEEP) == 0) ; allocated++); -+ if ( allocated != how_many ) { -+ eip_rx->reschedule++; -+ needs_reschedule = 1; -+ } -+ } else { -+ /* steal how_many rmds and put them on the aside list */ -+ how_many = EIP_RMD_ALLOC_THRESH - queued; -+ -+ EIP_ASSERT(how_many >= 0 && how_many <= EIP_RMD_ALLOC_THRESH); -+ -+ rmd_next = eip_rx->head[svc].busy_list; -+ eip_rx->head[svc].busy_list = NULL; -+ -+ while (how_many-- && rmd_next) { -+ rmd = rmd_next; -+ rmd_next = rmd_next->chain.next; -+ -+ if (eip_rmd_alloc_replace(rmd, svc, GFP_ATOMIC)) { -+ rmd_next = rmd; -+ break; -+ } -+ } -+ eip_rx->head[svc].busy_list = rmd_next; -+ if ( how_many ) -+ needs_reschedule = 1; -+ } -+ } -+ } -+ -+ if ( needs_reschedule && ( !timer_pending (&eip_rx_tasklet_timer))) -+ mod_timer (&eip_rx_tasklet_timer, lbolt + 2); -+} -+ -+static inline void eip_tmd_init(EIP_TMD * tmd, unsigned long buff_base, EIP_TMD_HEAD * head, unsigned long buff_len, -+ int dvma_idx) -+{ -+ tmd->dvma_idx = dvma_idx; -+ tmd->dma_base = buff_base; -+ tmd->dma_len = -1; -+ tmd->skb = NULL; -+ tmd->head = head; -+ tmd->chain.next = NULL; -+ -+ if (tmd->head != &eip_tx->head[EIP_TMD_STD]) { -+ tmd->nmd.nmd_len = buff_len; -+ eip_tmd_load(tmd); -+ } else { -+ tmd->nmd.nmd_len = -1; -+ tmd->nmd.nmd_addr = 0; -+ } -+} -+ -+static inline EIP_TMD *eip_tmd_get(int id) -+{ -+ unsigned long flags; -+ EIP_TMD *tmd = NULL; -+ spin_lock_irqsave(&eip_tx->lock, flags); -+ while ((tmd = eip_tx->head[id].tmd) == NULL) { -+ spin_unlock_irqrestore(&eip_tx->lock, flags); -+ if (ep_enable_txcallbacks(eip_tx->xmtr) == 0) { -+ -+ spin_lock_irqsave (&eip_tx->lock, flags); -+ if (eip_tx->head[id].tmd == NULL) { -+ __EIP_DBG_PRINTF("Cannot get a TMD on head %d ... stopping queue\n", id); -+ -+ eip_stop_queue (); -+ -+ spin_unlock_irqrestore (&eip_tx->lock, flags); -+ -+ return NULL; -+ } -+ spin_unlock_irqrestore (&eip_tx->lock, flags); -+ } -+ -+ ep_disable_txcallbacks(eip_tx->xmtr); -+ spin_lock_irqsave(&eip_tx->lock, flags); -+ } -+ eip_tx->head[id].tmd = tmd->chain.next; -+ spin_unlock_irqrestore(&eip_tx->lock, flags); -+ atomic_dec(&tmd->head->stats); -+ return tmd; -+} -+ -+static inline void eip_tmd_put(EIP_TMD * tmd) -+{ -+ unsigned long flags; -+ -+ tmd->skb = NULL; -+ -+ spin_lock_irqsave(&eip_tx->lock, flags); -+ tmd->chain.next = tmd->head->tmd; -+ tmd->head->tmd = tmd; -+ spin_unlock_irqrestore(&eip_tx->lock, flags); -+ atomic_inc(&tmd->head->stats); -+ -+ eip_start_queue(); -+ -+ EIP_DBG_PRINTF(EIP_DBG_TMD_QUEUE, "TMD [%p] : REQUEUED\n", tmd); -+} -+static inline void eip_tmd_load(EIP_TMD * tmd) -+{ -+ EP_RAILMASK rmask = tx_railmask; -+ -+ __eip_tmd_load(tmd, &rmask); -+ -+ EIP_DBG_PRINTF(EIP_DBG_EP_DVMA, "TMD [%p] : LOADED\n", tmd); -+} -+static inline void eip_tmd_unload(EIP_TMD * tmd) -+{ -+ __eip_tmd_unload(tmd); -+ -+ EIP_DBG_PRINTF(EIP_DBG_EP_DVMA, "TMD [%p] : UNLOADED\n", tmd); -+} -+static inline void eip_tmd_free(EIP_TMD * tmd) -+{ -+ eip_buff_free(tmd->dma_base, tmd->nmd.nmd_len); -+ -+ EIP_DBG_PRINTF(EIP_DBG_MEMFREE, "TMD [%p] : FREED\n", tmd); -+ -+ EIP_STAT_ALLOC_SUB(&tmd->head->stats, 1); -+} -+ -+/* tmd on a separate block */ -+static inline EIP_TMD *eip_tmd_alloc_queue(EIP_TMD * tmd, EIP_TMD_HEAD * head, int dvma_idx) -+{ -+ eip_tmd_init(tmd, 0, head, -1, dvma_idx); -+ -+ eip_tmd_put(tmd); -+ -+ EIP_STAT_ALLOC_ADD(&tmd->head->stats, 1); -+ EIP_DBG(EIP_DBG_TMD, eip_tmd_display, tmd); -+ return tmd; -+} -+/* tmd on the buffer */ -+static inline EIP_TMD *eip_tmd_alloc_queue_copybreak(EIP_TMD_HEAD * head, int dvma_idx) -+{ -+ EIP_TMD *tmd; -+ unsigned long buff_base; -+ -+ if (!(buff_base = eip_buff_alloc(tx_copybreak_max + sizeof(EIP_TMD), GFP_KERNEL))) -+ return NULL; -+ -+ tmd = (EIP_TMD *) (buff_base + tx_copybreak_max); -+ eip_tmd_init(tmd, buff_base, head, tx_copybreak_max, dvma_idx); -+ -+ eip_tmd_put(tmd); -+ EIP_STAT_ALLOC_ADD(&tmd->head->stats, 1); -+ EIP_DBG(EIP_DBG_TMD, eip_tmd_display, tmd); -+ return tmd; -+} -+ -+/* ipf are on the buffer */ -+static inline EIP_TMD *eip_tmd_alloc_queue_aggreg(EIP_TMD_HEAD * head, int dvma_idx) -+{ -+ EIP_TMD *tmd; -+ unsigned long buff_base; -+ -+ if (!(buff_base = eip_buff_alloc(EIP_SVC_BIGGEST_LEN, GFP_KERNEL))) -+ return NULL; -+ -+ tmd = (EIP_TMD *) (buff_base + EIP_SVC_BIGGEST_LEN - sizeof(EIP_IPFRAG)); -+ eip_tmd_init(tmd, buff_base, head, EIP_SVC_BIGGEST_LEN - sizeof(EIP_IPFRAG), dvma_idx); -+ -+ eip_tmd_put(tmd); -+ EIP_STAT_ALLOC_ADD(&tmd->head->stats, 1); -+ EIP_DBG(EIP_DBG_TMD, eip_tmd_display, tmd); -+ return tmd; -+} -+ -+static int eip_tmds_alloc() -+{ -+ int i; -+ int page_nr; -+ EIP_TMD *tmd; -+ -+ page_nr = EIP_DVMA_PAGES(tx_copybreak_max); -+ -+ eip_tx->head[EIP_TMD_COPYBREAK].handle = eip_dma_reserve(page_nr * eip_tx->tmd_max_nr, EP_PERM_READ); -+ -+ EIP_DBG(EIP_DBG_TMD_HEAD, eip_tmd_head_display, &eip_tx->head[EIP_TMD_COPYBREAK]); -+ -+ for (i = 0; i < EIP_TMD_NR; i++) { -+ if (!eip_tmd_alloc_queue_copybreak(&eip_tx->head[EIP_TMD_COPYBREAK], i * page_nr)) -+ return -ENOMEM; -+ } -+ -+ eip_tx->head[EIP_TMD_STD].handle = -+ eip_dma_reserve(EIP_DVMA_PAGES(EIP_SVC_BIGGEST_LEN) * eip_tx->tmd_max_nr, EP_PERM_READ); -+ -+ EIP_DBG(EIP_DBG_TMD_HEAD, eip_tmd_head_display, &eip_tx->head[EIP_TMD_STD]); -+ -+ tmd = kmalloc(sizeof(EIP_TMD) * EIP_TMD_NR, GFP_KERNEL); -+ if (!tmd) { -+ EIP_ERR_PRINTF("Cannot ALLOCATE %d of tmds\n", (int) sizeof(EIP_TMD) * EIP_TMD_NR); -+ return -ENOMEM; -+ } -+ -+ page_nr = EIP_DVMA_PAGES(EIP_SVC_BIGGEST_LEN); -+ -+ for (i = 0; i < EIP_TMD_NR; i++, tmd++) { -+ if (!eip_tmd_alloc_queue(tmd, &eip_tx->head[EIP_TMD_STD], i * page_nr)) -+ return -ENOMEM; -+ } -+ -+ page_nr = EIP_DVMA_PAGES(EIP_SVC_BIGGEST_LEN); -+ -+ eip_tx->head[EIP_TMD_AGGREG].handle = eip_dma_reserve(page_nr * eip_tx->tmd_max_nr, EP_PERM_READ); -+ EIP_DBG(EIP_DBG_TMD_HEAD, eip_tmd_head_display, &eip_tx->head[EIP_TMD_AGGREG]); -+ -+ for (i = 0; i < EIP_TMD_NR; i++) { -+ if (!eip_tmd_alloc_queue_aggreg(&eip_tx->head[EIP_TMD_AGGREG], i * page_nr)) -+ return -ENOMEM; -+ } -+ return 0; -+} -+ -+static void eip_tmds_free(void) -+{ -+ EIP_TMD *tmd; -+ EIP_TMD *tmd_next; -+ int i; -+ -+ ep_poll_transmits(eip_tx->xmtr); -+ -+ for (i = 0 ; i < 3 ; i++) { -+again: -+ if (EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats) < EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats)) { -+ EIP_DBG_PRINTF(EIP_DBG_TMD, "Polling XMTR [%p]\n", eip_tx->xmtr); -+ ep_poll_transmits(eip_tx->xmtr); -+ goto again; -+ } -+ } -+ /* everything should be queued */ -+ if ((tmd = eip_tx->head[EIP_TMD_COPYBREAK].tmd)) { -+ do { -+ tmd_next = tmd->chain.next; -+ eip_tmd_unload(tmd); -+ -+ EIP_DBG(EIP_DBG_TMD, eip_tmd_display, tmd); -+ -+ eip_tmd_free(tmd); -+ } while (tmd_next && (tmd = tmd_next)); -+ } -+ -+ EIP_DBG_PRINTF(EIP_DBG_TMD_EP_DVMA, "HEAD[EIP_TMD_COPYBREAK] release DVMA [%p]\n", -+ eip_tx->head[EIP_TMD_COPYBREAK].handle); -+ -+ ep_dvma_release(eip_tx->ep_system, eip_tx->head[EIP_TMD_COPYBREAK].handle); -+ -+ /* these ones have been allocated as a block */ -+ if ((tmd = eip_tx->head[EIP_TMD_STD].tmd)) { -+ do { -+ if (tmd->dvma_idx == 0 ) { -+ kfree(tmd); -+ /* eip_tmd_free(tmd); */ -+ EIP_STAT_ALLOC_SUB(&tmd->head->stats, EIP_TMD_NR); -+ tmd_next = NULL; -+ EIP_DBG_PRINTF(EIP_DBG_TMD_EP_DVMA, "TMD HEAD[%p] : [EIP_TMD_STD] BLOCK FREED\n", tmd); -+ } else -+ tmd_next = tmd->chain.next; -+ } while (tmd_next && (tmd = tmd_next)); -+ } -+ EIP_DBG_PRINTF(EIP_DBG_TMD_EP_DVMA, "HEAD[EIP_TMD_STD] release DVMA [%p]\n", -+ eip_tx->head[EIP_TMD_STD].handle); -+ -+ ep_dvma_release(eip_tx->ep_system, eip_tx->head[EIP_TMD_STD].handle); -+ -+ if ((tmd = eip_tx->head[EIP_TMD_AGGREG].tmd)) { -+ do { -+ tmd_next = tmd->chain.next; -+ -+ EIP_DBG(EIP_DBG_TMD, eip_tmd_display, tmd); -+ -+ eip_tmd_unload(tmd); -+ eip_tmd_free(tmd); -+ } while (tmd_next && (tmd = tmd_next)); -+ } -+ EIP_DBG_PRINTF(EIP_DBG_TMD_EP_DVMA, "TMD HEAD[%p] : [EIP_TMD_AGGREG] release DVMA\n", -+ eip_tx->head[EIP_TMD_AGGREG].handle); -+ -+ ep_dvma_release(eip_tx->ep_system, eip_tx->head[EIP_TMD_AGGREG].handle); -+ -+ ep_free_xmtr(eip_tx->xmtr); -+ EIP_DBG_PRINTF(EIP_DBG_TMD, "XMTR[%p] : FREED\n", eip_tx->xmtr); -+} -+ -+static inline void eip_ipf_skb_add(EIP_IPFRAG * ipf, struct sk_buff *skb) -+{ -+ int align = EIP_IP_ALIGN(skb->len); -+ -+ -+ if (ipf->dma_len == -1) { /* like a virgin; touched for the very first time */ -+ do_gettimeofday(&ipf->timestamp); -+ /* FIXE ME put that in release tmd code */ -+ ipf->frag_nr = 0; -+ ipf->dma_len = 0; -+ ipf->datagram_len = -1; -+ ipf->dma_correction = 0; -+ } -+ -+ memcpy((void *) (ipf->dma_base + ipf->dma_len), skb->data, skb->len); -+ -+ if (ipf->datagram_len == -1) { -+ struct iphdr * iph = skb->nh.iph; -+ int offset = ntohs(iph->frag_off); -+ -+ /* last one ? ; offset & ~IP_OFFSET = IP fragment flags */ -+ if (((offset & ~IP_OFFSET) & IP_MF) == 0) { -+ offset &= IP_OFFSET; -+ offset <<= 3; -+ ipf->datagram_len = offset + htons(iph->tot_len) - sizeof(struct iphdr); -+ } -+ } -+ -+ skb->next = ipf->skb; -+ ipf->skb = skb; -+ ipf->payload.Data[ipf->frag_nr] = skb->len; -+ ipf->dma_len += align; -+ ipf->dma_correction += align - skb->len + ETH_HLEN + sizeof(struct iphdr); -+ /* FIXME ; Count got wrong if ip header has options */ -+ -+ ipf->frag_nr++; -+ -+ EIP_DBG2(EIP_DBG_TMD, eip_ipf_display, ipf, "ADDED skb[%p] len %db ALIGNED(%db)\n", skb, skb->len, EIP_IP_ALIGN(skb->len)); -+} -+ -+#define eip_ipf_hasroom(ipf, skb) ((ipf->dma_len + EIP_IP_ALIGN(skb->len) < eip_tx->sysctl_ipfrag_copybreak)) -+int eip_hard_start_xmit(struct sk_buff *skb, struct net_device *devnet) -+{ -+ -+ EIP_TMD *tmd; -+ EP_NMD nmd; -+ struct iphdr *iph; -+ int j; -+ -+ if (skb->destructor){ -+ atomic_inc(&eip_tx->destructor); -+ tasklet_schedule(&eip_tx->tasklet); -+ } -+ -+ if (!(iph = eip_ipfrag_get(skb->data)) || (eip_tx->sysctl_aggregation == 0)) { /* not ip fragment */ -+no_aggreg: -+ j = (skb->len < eip_tx->sysctl_copybreak) ? EIP_TMD_COPYBREAK : EIP_TMD_STD; /* j = head id */ -+ -+ if (!(tmd = eip_tmd_get(j))) { -+ if (skb->destructor) -+ atomic_dec(&eip_tx->destructor); -+ return 1; -+ } -+ -+ tmd->dma_len = skb->len; -+ tmd->skb = skb; -+ tmd->skb->next = NULL; -+ tmd->chain.next = NULL; -+ -+ if (j == EIP_TMD_COPYBREAK) { -+ memcpy((void *) tmd->dma_base, skb->data, skb->len); -+ -+ ep_nmd_subset(&nmd, &tmd->nmd, 0, skb->len); -+#ifdef EIP_MORE_STATS -+ eip_tx->sent_copybreak++; -+#endif -+ return eip_do_xmit(tmd, &nmd, NULL); -+ } -+ tmd->dma_base = (unsigned long) skb->data; -+ tmd->nmd.nmd_len = skb->len; -+ eip_tmd_load(tmd); -+ -+#ifdef EIP_MORE_STATS -+ eip_tx->sent_std++; -+#endif -+ return eip_do_xmit(tmd, &tmd->nmd, NULL); -+ } else if ( skb->len > EIP_SVC_BIGGEST_LEN/2 ) { -+ /* don't aggregate when we have a full mtu of data */ -+ /* or more than 32k ; in this case it is cheaper */ -+ /* to just map the buffer and send it */ -+ goto no_aggreg; -+ } else { -+ EIP_IPFRAG *ipf = NULL; -+ unsigned long flags; -+ struct list_head *l; -+ struct iphdr *iph2; -+ int i; -+ __u16 id = iph->id; -+ __u32 saddr = iph->saddr; -+ __u32 daddr = iph->daddr; -+ __u8 protocol = iph->protocol; -+ -+ EIP_DBG(EIP_DBG_IPH, eip_iph_display, iph); -+ -+ j = 0; -+ -+ /* here we can't have full mtu size aggregated packet */ -+ EIP_ASSERT_RET(skb->len < eip_tx->sysctl_ipfrag_copybreak, 0); -+ -+ spin_lock_irqsave(&eip_tx->ipfraglock, flags); -+ list_for_each(l, &eip_tx->ipfrag) { -+ ipf = list_entry(l, EIP_IPFRAG, list); -+ iph2 = eip_ipfrag_get((char *) ipf->dma_base); -+ -+ EIP_ASSERT(iph2); -+ -+ if ((iph2->id == id) && -+ (get_unaligned(&iph2->saddr) == saddr) && -+ (get_unaligned(&iph2->daddr) == daddr) && -+ (iph2->protocol == protocol)) { -+ /* || timeout */ -+ if (eip_ipf_hasroom(ipf, skb)) { -+ -+ eip_ipf_skb_add(ipf, skb); -+ -+ if ((ipf->datagram_len != -1) && -+ (ipf->dma_len == (ipf->datagram_len + ipf->dma_correction) || -+ ipf->frag_nr == (128 / sizeof(uint32_t)))) { -+send_aggreg: -+ ipf->payload.Data[ipf->frag_nr] = 0; -+ list_del(&ipf->list); -+ eip_tx->ipfrag_count--; -+ spin_unlock_irqrestore(&eip_tx->ipfraglock, flags); -+ -+ ep_nmd_subset(&nmd, &ipf->nmd, 0, ipf->dma_len); -+ -+#ifdef EIP_MORE_STATS -+ eip_tx->sent_aggreg++; -+#endif -+ if ((i = eip_do_xmit((EIP_TMD *) ipf, &nmd, &ipf->payload)) != EP_SUCCESS) -+ return i; -+ if (j) -+ goto new; -+ return 0; -+ } -+ -+ spin_unlock_irqrestore(&eip_tx->ipfraglock, flags); -+ tasklet_schedule(&eip_tx->tasklet); -+ return 0; -+ } else { -+ EIP_DBG_PRINTF(EIP_DBG_TMD, "IPF[%p] : FULL %db full - sending it\n", ipf, ipf->dma_len); -+ j = 1; -+ goto send_aggreg; -+ } -+ } -+ } -+ spin_unlock_irqrestore(&eip_tx->ipfraglock, flags); -+new: -+ if (!(ipf = (EIP_IPFRAG *) eip_tmd_get(EIP_TMD_AGGREG))) -+ goto no_aggreg; -+ -+ eip_ipf_skb_add(ipf, skb); -+ -+ spin_lock_irqsave(&eip_tx->ipfraglock, flags); -+ list_add_tail(&ipf->list, &eip_tx->ipfrag); -+ eip_tx->ipfrag_count++; -+ spin_unlock_irqrestore(&eip_tx->ipfraglock, flags); -+ tasklet_schedule(&eip_tx->tasklet); -+ } -+ return 0; -+} -+static int eip_do_xmit(EIP_TMD * tmd, EP_NMD *nmd, EP_PAYLOAD *payload) -+{ -+ EIP_HEADER *eiph = (EIP_HEADER *) tmd->dma_base; -+ int attr = EP_SET_DATA((EP_NO_SLEEP | EP_NO_INTERRUPT | EP_NO_FAILOVER), EP_TYPE_SVC_INDICATOR, EP_SVC_EIP); -+ unsigned long flags; -+ int svc, rnum; -+ -+ SIZE_TO_SVC(nmd->nmd_len, svc); -+ -+ EIP_DBG(EIP_DBG_TMD, eip_tmd_display, tmd); -+ /* EIP_DBG(eip_eiph_display(eiph)); */ -+ -+ if (unlikely (eiph->h_dhost.ip_bcast)) -+ rnum = ep_pickRail (EP_NMD_RAILMASK (nmd) & tx_railmask & ep_xmtr_availrails(eip_tx->xmtr)); -+ else -+ rnum = ep_pickRail (EP_NMD_RAILMASK (nmd) & tx_railmask & ep_xmtr_noderails(eip_tx->xmtr, ntohs(eiph->h_dhost.ip_addr))); -+ -+ if (rnum >= 0) -+ attr = EP_SET_PREFRAIL(attr, rnum); -+ -+ /* add to inuse list */ -+ spin_lock_irqsave (&eip_tx->lock, flags); -+ list_add_tail (&tmd->chain.link, &eip_tx->inuse); -+ spin_unlock_irqrestore (&eip_tx->lock, flags); -+ -+ /* ENOMEM EINVAL ECONNREFUSED ESUCCESS */ -+ svc = (unlikely(eiph->h_dhost.ip_bcast)) ? -+ ep_multicast_message(eip_tx->xmtr, -1, -1, NULL, EIP_SVC_EP(svc), attr | EP_NOT_MYSELF, eip_txhandler, tmd, payload, nmd, 1) : -+ -+ ep_transmit_message(eip_tx->xmtr, ntohs(eiph->h_dhost.ip_addr), EIP_SVC_EP(svc), attr, eip_txhandler, tmd, payload, nmd, 1); -+ -+ if (likely(svc == EP_SUCCESS)) -+ return 0; -+ else if (svc == ENOMEM) { -+ EIP_ERR_PRINTF("%s", "Memory allocation error ...\n"); -+ eip_tx->errors++; -+ } -+ else -+ { -+ /* EP_EINVAL occurs when the svc has a bad value or the iovec has too many frag; */ -+ /* we don't use the latter option here */ -+ __EIP_DBG_PRINTF("TMD [%p] : DROPPED skb[%p] status = %d from ep_?_message\n", tmd, tmd->skb, svc); -+ -+ eip_tx->dropped++; -+ } -+ -+ eip_txhandler(NULL, tmd, -99); -+ -+ /* Quadrics GNAT sw-elan/4397 - since we will "never" be able to send this packet to the */ -+ /* destination node, we drop it and feign success - this has the same behaviour as an */ -+ /* ethernet where it sticks the packet on the wire, but no-one receives it. */ -+ return 0; -+} -+ -+static void eip_txhandler(EP_TXD * txd, void *arg, EP_STATUS status) -+{ -+ EIP_TMD *tmd = (EIP_TMD *) arg; -+ struct sk_buff *skb_next; -+ unsigned long flags; -+ int svc = 0; -+ -+ if (likely(status == EP_SUCCESS)) { -+ SIZE_TO_SVC(tmd->dma_len, svc); -+ eip_tx->dma[svc]++; -+ eip_tx->bytes += tmd->dma_len; -+ -+ if (tmd->head == &eip_tx->head[EIP_TMD_AGGREG]) { -+ EIP_IPFRAG *ipf = (EIP_IPFRAG *) tmd; -+ eip_tx->packets += ipf->frag_nr; -+ } else -+ eip_tx->packets++; -+ } else { -+ if (tmd->head == &eip_tx->head[EIP_TMD_AGGREG]) { -+ EIP_IPFRAG *ipf = (EIP_IPFRAG *) tmd; -+ eip_tx->dropped += ipf->frag_nr; -+ EIP_DBG_PRINTF(EIP_DBG_TMD, "txhandler aggreg packet dropped status = %d\n", status); -+ } else { -+ eip_tx->dropped++; -+ EIP_DBG_PRINTF(EIP_DBG_TMD, "txhandler packet dropped status = %d\n", status); -+ } -+ } -+ -+ if (tmd->head == &eip_tx->head[EIP_TMD_STD]) { -+ eip_tmd_unload(tmd); -+ tmd->dma_base = 0; -+ tmd->nmd.nmd_len = -1; -+ } -+ -+ tmd->dma_len = -1; -+ -+ svc = 0; -+ while (tmd->skb) { -+ svc++; -+ -+ if (tmd->skb->destructor) -+ atomic_dec(&eip_tx->destructor); -+ -+ skb_next = tmd->skb->next; -+ dev_kfree_skb_any(tmd->skb); -+ tmd->skb = skb_next; -+ } -+ EIP_DBG_PRINTF(EIP_DBG_TMD, "IPF/TMD [%p] : %d skb RELEASE/FREED\n", tmd, svc); -+ -+ /* remove from inuse list */ -+ spin_lock_irqsave (&eip_tx->lock, flags); -+ list_del (&tmd->chain.link); -+ spin_unlock_irqrestore (&eip_tx->lock, flags); -+ -+ eip_tmd_put(tmd); -+} -+ -+static void eip_tx_tasklet(unsigned long arg) -+{ -+ struct timeval now; -+ unsigned long flags; -+ EIP_IPFRAG *ipf, *ipfq = NULL; -+ EP_NMD nmd; -+ struct list_head *list; -+ struct list_head *tmp; -+ char resched = 0; -+ char poll = 1; -+ -+ do_gettimeofday(&now); -+ -+ spin_lock_irqsave(&eip_tx->ipfraglock, flags); -+ if (eip_tx->ipfrag_count) { -+ list_for_each_safe(list, tmp, &eip_tx->ipfrag) { -+ ipf = list_entry(list, EIP_IPFRAG, list); -+ /* delta = (((now.tv_sec - ipf->timestamp.tv_sec) * 1000000UL) + now.tv_usec) - ipf->timestamp.tv_usec; */ -+ if (((((now.tv_sec - ipf->timestamp.tv_sec) * 1000000UL) + now.tv_usec) - -+ ipf->timestamp.tv_usec) >= (1000UL * eip_tx->sysctl_ipfrag_to)) { -+ list_del(&ipf->list); -+ eip_tx->ipfrag_count--; -+ ipf->chain.next = (EIP_TMD *) ipfq; -+ ipfq = ipf; -+ } -+ } -+ } -+ if (eip_tx->ipfrag_count) -+ resched = 1; -+ spin_unlock_irqrestore(&eip_tx->ipfraglock, flags); -+ -+ while (ipfq) { -+ poll = 0; -+ -+ ep_nmd_subset(&nmd, &ipfq->nmd, 0, ipfq->dma_len); -+ -+ ipfq->payload.Data[ipfq->frag_nr] = 0; -+ -+#ifdef EIP_MORE_STATS -+ eip_tx->sent_aggreg++; -+#endif -+ ipf = (EIP_IPFRAG *) ipfq->chain.next; -+ eip_do_xmit((EIP_TMD *) ipfq, &nmd, &ipfq->payload); -+ ipfq = ipf; -+ } -+ -+ if (poll) -+ ep_poll_transmits(eip_tx->xmtr); -+ -+ if (atomic_read(&eip_tx->destructor) || resched ) -+ tasklet_schedule(&eip_tx->tasklet); -+} -+void eip_start_queue() -+{ -+ if (netif_queue_stopped(eip_tx->net_device)) { -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "Waking up %s queue\n", eip_tx->net_device->name); -+ netif_wake_queue(eip_tx->net_device); -+ } -+} -+void eip_stop_queue() -+{ -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "Stopping %s queue\n", eip_tx->net_device->name); -+ netif_stop_queue(eip_tx->net_device); -+} -+ -+static int eip_open(struct net_device *devnet) -+{ -+ if (devnet->flags & IFF_PROMISC) -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "%s entering in promiscuous mode\n", devnet->name); -+ -+ netif_start_queue(devnet); -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "iface %s MAC %02x:%02x:%02x:%02x:%02x:%02x up\n", -+ devnet->name, (devnet->dev_addr[0]) & 0xff, -+ (devnet->dev_addr[1]) & 0xff, (devnet->dev_addr[2]) & 0xff, (devnet->dev_addr[3]) & 0xff, -+ (devnet->dev_addr[4]) & 0xff, (devnet->dev_addr[5]) & 0xff); -+ return 0; -+} -+ -+static int eip_close(struct net_device *devnet) -+{ -+ if (devnet->flags & IFF_PROMISC) -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "%s leaving promiscuous mode\n", devnet->name); -+ -+ netif_stop_queue(devnet); -+ -+ eip_rx_tasklet(0); -+ -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "iface %s MAC %02x:%02x:%02x:%02x:%02x:%02x down\n", -+ devnet->name, (devnet->dev_addr[0]) & 0xff, -+ (devnet->dev_addr[1]) & 0xff, (devnet->dev_addr[2]) & 0xff, (devnet->dev_addr[3]) & 0xff, -+ (devnet->dev_addr[4]) & 0xff, (devnet->dev_addr[5]) & 0xff); -+ return 0; -+} -+ -+static struct net_device_stats *eip_get_stats(struct net_device *devnet) -+{ -+ static struct net_device_stats stats; -+ -+ stats.rx_packets = eip_rx->packets; -+ stats.rx_bytes = eip_rx->bytes; -+ stats.rx_errors = eip_rx->errors; -+ stats.rx_dropped = eip_rx->dropped; -+ -+ stats.tx_packets = eip_tx->packets; -+ stats.tx_bytes = eip_tx->bytes; -+ stats.tx_errors = eip_tx->errors; -+ stats.tx_dropped = eip_tx->dropped; -+ return &stats; -+} -+ -+static int eip_change_mtu(struct net_device *devnet, int mtu) -+{ -+ if (mtu <= EIP_MTU_MAX) { -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "MTU size changed from %d to %d\n", devnet->mtu, mtu); -+ devnet->mtu = mtu; -+ } -+ return 0; -+} -+ -+#ifdef MODULE -+int eip_init(void) -+{ -+ struct net_device *devnet; -+ int errno = 0; -+ -+ eip_rx_dropping = 0; -+ eip_rx_tasklet_locked = 1; -+ -+ /* timer up but not started */ -+ init_timer (&eip_rx_tasklet_timer); -+ eip_rx_tasklet_timer.function = eip_rx_tasklet; -+ eip_rx_tasklet_timer.data = (unsigned long) 0; -+ eip_rx_tasklet_timer.expires = lbolt + hz; -+ -+ devnet = alloc_etherdev(sizeof(EIP_RX) + sizeof(EIP_TX)); -+ if (!devnet) { -+ EIP_ERR_PRINTF("Unable to ALLOCATE etherdev structure\n"); -+ return -ENOMEM; -+ } -+ strcpy (devnet->name, "eip0"); -+ -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "Enabling aggregation code\n"); -+ devnet->change_mtu = eip_change_mtu; -+ devnet->mtu = EIP_MTU_MAX; -+ devnet->open = eip_open; -+ devnet->stop = eip_close; -+ devnet->hard_start_xmit = eip_hard_start_xmit; -+ devnet->get_stats = eip_get_stats; -+ -+ /* devnet->features |= (NETIF_F_DYNALLOC); */ -+ /* devnet->features = (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA); */ -+ /* devnet->features |= (NETIF_F_SG|NETIF_F_FRAGLIST|NETIF_F_HIGHDMA|NETIF_F_HW_CSUM); */ -+ -+ eip_rx = (EIP_RX *) devnet->priv; -+ eip_tx = (EIP_TX *) (eip_rx + 1); -+ -+ /* instance 0 */ -+ eip_tx->ep_system = ep_system(); -+ if (eip_tx->ep_system == NULL) { -+ EIP_ERR_PRINTF("kernel comms for iface %s does not exist\n", devnet->name); -+ errno = -ENXIO; -+ goto out; -+ } -+ if (ep_waitfor_nodeid(eip_tx->ep_system) == ELAN_INVALID_NODE) { -+ EIP_ERR_PRINTF("network position not found\n"); -+ errno = -EAGAIN; -+ goto out; -+ } -+ eip_tx->xmtr = ep_alloc_xmtr(eip_tx->ep_system); -+ if (!eip_tx->xmtr) { -+ EIP_ERR_PRINTF("Cannot create allocated transmitter - maybe cable is disconnected\n"); -+ errno = -EAGAIN; -+ goto out; -+ } -+ /* assign MAC address */ -+ *((int *) &devnet->dev_addr[4]) = htons(ep_nodeid(eip_tx->ep_system)); -+ eip_rx->net_device = devnet; -+ eip_tx->net_device = devnet; -+ -+ atomic_set(&eip_tx->destructor, 0); -+ -+ if ((tmd_max >= EIP_TMD_MIN_NR) && (tmd_max <= EIP_TMD_MAX_NR)) { -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "Setting tmd_max_nr to %d\n", tmd_max); -+ eip_tx->tmd_max_nr = tmd_max; -+ } else { -+ EIP_ERR_PRINTF("parameter error : %d <= tmd_max(%d) <= %d using default %d\n", -+ EIP_TMD_MIN_NR, tmd_max, EIP_TMD_MAX_NR, EIP_TMD_MAX_NR); -+ eip_tx->tmd_max_nr = EIP_TMD_MAX_NR; -+ } -+ -+ if ((rmd_max >= EIP_RMD_MIN_NR) && (rmd_max <= EIP_RMD_MAX_NR)) { -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "Setting rmd_max_nr to %d\n", rmd_max); -+ eip_rx->rmd_max_nr = rmd_max; -+ } else { -+ EIP_ERR_PRINTF("parameter error : %d <= rmd_max(%d) <= %d using default %d\n", EIP_RMD_MIN_NR, -+ rmd_max, EIP_RMD_MAX_NR, EIP_RMD_MAX_NR); -+ eip_rx->rmd_max_nr = EIP_RMD_MAX_NR; -+ } -+ -+ if ((rx_envelope_nr > 0) && (rx_envelope_nr <= 1024)) { /* > 1024 don't be silly */ -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "Setting rx_envelope_nr to %d\n", rx_envelope_nr); -+ } else { -+ EIP_ERR_PRINTF("parameter error : 0 < rx_envelope_nr(%d) <= 1024 using default %d\n", -+ rx_envelope_nr, EIP_RX_ENVELOPE_NR); -+ rx_envelope_nr = EIP_RX_ENVELOPE_NR; -+ } -+ -+ if (tx_copybreak_max <= EIP_TX_COPYBREAK_MAX) { -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "Setting tx_copybreak_max to %d\n", tx_copybreak_max); -+ } else { -+ EIP_ERR_PRINTF("parameter error : tx_copybreak_max > %d using default %d\n", -+ EIP_TX_COPYBREAK_MAX, EIP_TX_COPYBREAK_MAX); -+ tx_copybreak_max = EIP_TX_COPYBREAK_MAX; -+ } -+#ifdef EIP_MORE_STATS -+ eip_tx->sent_copybreak = 0; -+ eip_tx->sent_std = 0; -+ eip_tx->sent_aggreg = 0; -+#endif -+ -+ eip_tx->ipfrag_count = 0; -+ eip_aggregation_set(1); -+ eip_rx_granularity_set(rx_granularity); -+ eip_tx_copybreak_set(EIP_TX_COPYBREAK); -+ eip_ipfrag_to_set(EIP_IPFRAG_TO); -+ eip_ipfrag_copybreak_set(EIP_IPFRAG_COPYBREAK); -+ -+ spin_lock_init(&eip_tx->lock); -+ spin_lock_init(&eip_tx->ipfraglock); -+ spin_lock_init(&eip_rx->lock); -+ tasklet_init(&eip_rx->tasklet, eip_rx_tasklet, 0); -+ tasklet_init(&eip_tx->tasklet, eip_tx_tasklet, 0); -+ INIT_LIST_HEAD(&eip_tx->ipfrag); -+ INIT_LIST_HEAD(&eip_tx->inuse); -+ -+ /* if we fail here cannot do much yet; waiting for rcvr remove code in ep. */ -+ errno = eip_tmds_alloc(); -+ if (errno) -+ goto out; -+ -+ errno = eip_rmds_alloc(); -+ if (errno) -+ goto out; -+ -+ errno = eip_stats_init(); -+ if (errno) -+ goto out; -+ -+ if (ep_svc_indicator_set(eip_tx->ep_system, EP_SVC_EIP) != EP_SUCCESS) { -+ EIP_ERR_PRINTF("Cannot set the service indicator\n"); -+ errno = -EINVAL; -+ goto out; -+ } -+ -+ eip_rx_tasklet_locked = 0; -+ tasklet_schedule(&eip_rx->tasklet); -+ -+ SET_MODULE_OWNER(eip_tx->net_device); -+ -+ if (register_netdev(devnet)) { -+ printk("eip: failed to register netdev\n"); -+ goto out; -+ } -+ -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "iface %s MAC %02x:%02x:%02x:%02x:%02x:%02x ready\n", -+ devnet->name, (devnet->dev_addr[0]) & 0xff, -+ (devnet->dev_addr[1]) & 0xff, (devnet->dev_addr[2]) & 0xff, (devnet->dev_addr[3]) & 0xff, -+ (devnet->dev_addr[4]) & 0xff, (devnet->dev_addr[5]) & 0xff); -+ -+ return 0; -+ out: -+ unregister_netdev(devnet); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 25) -+ kfree(devnet); -+#else -+ free_netdev(devnet); -+#endif -+ -+ return errno; -+} -+void eip_exit(void) -+{ -+ int i; -+ -+ eip_rx_dropping = 1; /* means that new messages wont be sent to tcp stack */ -+ eip_rx_tasklet_locked = 1; -+ -+ netif_stop_queue(eip_tx->net_device); -+ -+ if (ep_svc_indicator_clear(eip_tx->ep_system, EP_SVC_EIP) != EP_SUCCESS) { -+ EIP_ERR_PRINTF("Cannot unset the service indicator\n"); -+ } -+ -+ schedule_timeout(10); -+ -+ del_timer_sync (&eip_rx_tasklet_timer); -+ -+ tasklet_disable(&eip_rx->tasklet); -+ tasklet_disable(&eip_tx->tasklet); -+ -+ tasklet_kill(&eip_tx->tasklet); -+ tasklet_kill(&eip_rx->tasklet); -+ -+ eip_rmds_free(); -+ eip_tmds_free(); -+ -+ /* that things freed */ -+ for (i = 0 ; i < EIP_SVC_NR ; i++) { -+ if ( EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats) != 0 ) -+ EIP_ERR_PRINTF("%d RMDs not FREED on SVC[%d]\n", EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), i); -+ } -+ for (i = 0 ; i < 3 ; i++) { -+ if ( EIP_STAT_ALLOC_GET(&eip_tx->head[i].stats) != 0 ) -+ EIP_ERR_PRINTF("%d TMDs not freed on TX HEAD[%d]\n", EIP_STAT_ALLOC_GET(&eip_tx->head[i].stats), i); -+ -+ } -+ unregister_netdev(eip_tx->net_device); -+ kfree(eip_tx->net_device); -+ -+ eip_stats_cleanup(); -+} -+ -+module_init(eip_init); -+module_exit(eip_exit); -+ -+MODULE_PARM(eipdebug, "i"); -+MODULE_PARM_DESC(eipdebug, "Set debug flags"); -+ -+MODULE_PARM(rx_envelope_nr, "i"); -+MODULE_PARM_DESC(rx_enveloppe_nr, "Number of allocated enveloppe on the rx side"); -+ -+MODULE_PARM(tx_copybreak_max, "i"); -+MODULE_PARM_DESC(tx_copybreak_max, "Maximum size of the tx copybreak limit (default 512)"); -+ -+MODULE_PARM(tmd_max, "i"); -+MODULE_PARM(rmd_max, "i"); -+MODULE_PARM_DESC(tmd_max, "Maximun number of transmit buffers (default 64)"); -+MODULE_PARM_DESC(rmd_max, "Maximun number of receive buffers (default 64)"); -+ -+MODULE_PARM(tx_railmask, "i"); -+MODULE_PARM_DESC(tx_railmask, "Mask of which rails transmits can be queued on"); -+ -+MODULE_AUTHOR("Quadrics Ltd."); -+MODULE_DESCRIPTION("Elan IP driver"); -+MODULE_LICENSE("GPL"); -+#endif /* MODULE */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/eip/eip_linux.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/eip_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/eip_linux.h 2005-06-01 23:12:54.554445944 -0400 -@@ -0,0 +1,399 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: eip_linux.h,v 1.46.2.1 2004/10/01 10:49:38 mike Exp $" -+ -+#ifndef __EIP_LINUX_H -+#define __EIP_LINUX_H -+ -+#define EIP_WATERMARK (0xfab1e) -+ -+#define EIP_PAGES(s) (((s - 1) >> PAGE_SHIFT) + 1) -+#define EIP_DVMA_PAGES(s) ((s < PAGE_SIZE) ? EIP_PAGES(s) + 1 : EIP_PAGES(s)) -+ -+#define EIP_SVC_SMALLEST_LEN (1 << 9) /* 512 */ -+#define EIP_SVC_BIGGEST_LEN (1 << 16) /* 64k */ -+ -+#define EIP_SVC_SMALLEST (0) -+#define EIP_SVC_BIGGEST (7) -+ -+#define EIP_SVC_NR (8) -+#define EIP_SVC_EP(s) (s + EP_MSG_SVC_EIP512) -+ -+#define EIP_STAT_ALLOC_SHIFT (8) -+#define EIP_STAT_ALLOC_GET(atomicp) ((int) atomic_read(atomicp) >> EIP_STAT_ALLOC_SHIFT) -+#define EIP_STAT_ALLOC_ADD(atomicp, v) (atomic_add((v << EIP_STAT_ALLOC_SHIFT), atomicp)) -+#define EIP_STAT_ALLOC_SUB(atomicp, v) (atomic_sub((v << EIP_STAT_ALLOC_SHIFT), atomicp)) -+ -+#define EIP_STAT_QUEUED_MASK (0xff) -+#define EIP_STAT_QUEUED_GET(atomicp) ((int) atomic_read(atomicp) & EIP_STAT_QUEUED_MASK) -+ -+#define EIP_RMD_NR (8) -+#define EIP_RMD_MIN_NR (8) -+#define EIP_RMD_MAX_NR (64) /* should be < than (1 << EIP_STAT_ALLOC_SHIFT) */ -+ -+#define EIP_RMD_ALLOC_STEP (8) -+#define EIP_RMD_ALLOC_THRESH (16) -+ -+#define EIP_RMD_ALLOC (1) -+#define EIP_RMD_REPLACE (0) -+ -+#define EIP_TMD_NR (64) -+#define EIP_TMD_MIN_NR (16) -+#define EIP_TMD_MAX_NR (64) /* should be < than (1 << EIP_STAT_ALLOC_SHIFT) */ -+ -+#define EIP_TMD_TYPE_NR (3) -+#define EIP_TMD_COPYBREAK (0x0) -+#define EIP_TMD_STD (0x1) -+#define EIP_TMD_AGGREG (0x2) -+ -+#define EIP_TX_COPYBREAK (512) -+#define EIP_TX_COPYBREAK_MAX (1024) -+ -+#define EIP_IPFRAG_TO (50) /* time out before a frag is sent in msec */ -+#define EIP_IPFRAG_COPYBREAK (EIP_SVC_BIGGEST_LEN - sizeof(EIP_IPFRAG) - EIP_HEADER_PAD) -+ -+#define EIP_RX_ENVELOPE_NR ((EIP_RMD_MAX_NR*EIP_SVC_NR)/2) -+#define EIP_RX_GRANULARITY (1) -+ -+#define EIP_IP_ALIGN(X) (((X) + (15)) & ~(15)) -+#define EIP_EXTRA roundup (sizeof(EIP_RMD), 256) -+#define EIP_RCV_DMA_LEN(s) (s - EIP_EXTRA - EIP_HEADER_PAD) -+#define EIP_MTU_MAX (EIP_RCV_DMA_LEN(EIP_SVC_BIGGEST_LEN) - (ETH_HLEN)) -+ -+#define SIZE_TO_SVC(s, svc) \ -+ do { \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 9))) {svc = 0;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 10))) {svc = 1;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 11))) {svc = 2;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 12))) {svc = 3;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 13))) {svc = 4;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 14))) {svc = 5;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 15))) {svc = 6;break;} \ -+ if (s <= EIP_RCV_DMA_LEN((1 << 16))) {svc = 7;break;} \ -+ svc = -666; \ -+ EIP_ASSERT(1 == 0); \ -+ } while (0) -+ -+extern int eipdebug; -+#define EIP_ASSERT_ON -+/* #define NO_DEBUG */ -+ -+ -+/* ######################## */ -+#ifdef NO_DEBUG -+#define __EIP_DBG_PRINTF(fmt, args...) -+#define EIP_DBG_PRINTF(flag, fmt, args...) -+#else -+ -+#define EIP_DBG_RMD 0x1 -+#define EIP_DBG_TMD 0x2 -+#define EIP_DBG_RMD_HEAD 0x4 -+#define EIP_DBG_TMD_HEAD 0x8 -+#define EIP_DBG_EIPH 0x10 -+#define EIP_DBG_IPH 0x20 -+#define EIP_DBG_RMD_EP_DVMA 0x40 -+#define EIP_DBG_TMD_EP_DVMA 0x80 -+#define EIP_DBG_EP_DVMA (EIP_DBG_RMD_EP_DVMA|EIP_DBG_TMD_EP_DVMA) -+#define EIP_DBG_MEMALLOC 0x100 -+#define EIP_DBG_MEMFREE 0x200 -+#define EIP_DBG_RMD_QUEUE 0x400 -+#define EIP_DBG_TMD_QUEUE 0x800 -+#define EIP_DBG_GEN 0x1000 -+#define EIP_DBG_DEBUG 0x2000 -+ -+#define __EIP_DBG_PRINTF(fmt, args...) (qsnet_debugf (QSNET_DEBUG_BUFFER, " CPU #%d %s: " fmt, smp_processor_id(), __func__, ## args)) -+#define EIP_DBG_PRINTF(flag, fmt, args...) (unlikely(eipdebug & flag) ? __EIP_DBG_PRINTF(fmt, ## args):(void)0) -+ -+#define __EIP_DBG_PRINTK(fmt, args...) (qsnet_debugf (QSNET_DEBUG_BUF_CON, " CPU #%d %s: " fmt, smp_processor_id(), __func__, ## args)) -+#define EIP_DBG_PRINTK(flag, fmt, args...) (unlikely(eipdebug & flag) ? __EIP_DBG_PRINTF(fmt, ## args):(void)0) -+ -+#define EIP_ERR_PRINTF(fmt, args...) __EIP_DBG_PRINTK("!!! ERROR !!! - " fmt, ## args) -+ -+ -+#define EIP_DBG2(flag, fn, fn_arg, fmt, args...) \ -+ if (unlikely(eipdebug & flag)) { \ -+ qsnet_debugf (QSNET_DEBUG_BUFFER, "+CPU #%d %s: " fmt, smp_processor_id(), __func__, ##args); \ -+ (void)(fn)(fn_arg); \ -+ qsnet_debugf (QSNET_DEBUG_BUFFER, "-CPU #%d %s: " fmt, smp_processor_id(), __func__, ##args); \ -+ } -+ -+ -+#define EIP_DBG(flag, fn, args...) \ -+ if (unlikely(eipdebug & flag)) { \ -+ qsnet_debugf (QSNET_DEBUG_BUFFER, "+CPU #%d %s\n", smp_processor_id(), __func__); \ -+ (void)(fn)(args); \ -+ qsnet_debugf (QSNET_DEBUG_BUFFER, "-CPU #%d %s :\n", smp_processor_id(), __func__); \ -+ } -+#endif /* NO_DEBUG */ -+ -+ -+#ifdef EIP_ASSERT_ON -+ -+#define __EIP_ASSERT_PRINT(exp) \ -+ eipdebug = 0xffff; \ -+ EIP_ERR_PRINTF("ASSERT : %s, %s::%d\n", \ -+ #exp, __BASE_FILE__, __LINE__); -+ -+#define EIP_ASSERT(exp) \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ netif_stop_queue(eip_tx->net_device); \ -+ } -+ -+#define EIP_ASSERT2(exp, f, arg) \ -+ do { \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ f(arg); \ -+ } \ -+ } while (0) -+ -+#define EIP_ASSERT_BUG(exp) \ -+ do { \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ BUG(); \ -+ } \ -+ } while (0) -+ -+#define EIP_ASSERT_GOTO(exp, label, f, arg) \ -+ do { \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ f(arg); \ -+ goto label; \ -+ } \ -+ } while (0) -+ -+#define EIP_ASSERT_RET(exp, ret) \ -+ do { \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ return ret; \ -+ } \ -+ } while (0) -+ -+#define EIP_ASSERT_RETURN(exp, f, arg) \ -+ do { \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ f(arg); \ -+ return; \ -+ } \ -+ } while (0) -+ -+#define EIP_ASSERT_RETNULL(exp, f, arg) \ -+ do { \ -+ if (!(exp)) { \ -+ __EIP_ASSERT_PRINT(exp); \ -+ f(arg); \ -+ return NULL; \ -+ } \ -+ } while (0) -+ -+#else -+ -+#define EIP_ASSERT(exp) do {} while(0) -+#define EIP_ASSERT_OUT(exp) do {} while(0) -+#define EIP_ASSERT_RETURN(exp) do {} while(0) -+#define EIP_ASSERT_RETNULL(exp) do {} while(0) -+#define EIP_ASSERT_BUG(exp) do {} while(0) -+ -+#endif /* EIP_ASSERT */ -+ -+ -+ -+typedef struct { -+ u_short ip_bcast; -+ u_short ip_inst; -+ u_short ip_addr; -+} EIP_ADDRESS; -+ -+typedef struct { -+ EIP_ADDRESS h_dhost; -+ EIP_ADDRESS h_shost; -+ u_short h_sap; -+} EIP_HEADER; -+#define EIP_HEADER_PAD (2) -+ -+typedef struct eip_proc_fs { -+ const char *name; -+ struct proc_dir_entry **parent; -+ read_proc_t *read; -+ write_proc_t *write; -+ unsigned char allocated; -+ struct proc_dir_entry *entry; -+} EIP_PROC_FS; -+ -+#define EIP_PROC_ROOT_DIR "eip" -+ -+#define EIP_PROC_DEBUG_DIR "debug" -+#define EIP_PROC_DEBUG_RX_FLUSH "rx_flush" -+#define EIP_PROC_DEBUG_TX_FLUSH "tx_flush" -+ -+#define EIP_PROC_AGGREG_DIR "aggregation" -+#define EIP_PROC_AGGREG_ONOFF "enable" -+#define EIP_PROC_AGGREG_TO "timeout" -+#define EIP_PROC_AGGREG_COPYBREAK "copybreak" -+ -+#define EIP_PROC_TX_COPYBREAK "tx_copybreak" -+#define EIP_PROC_STATS "stats" -+#define EIP_PROC_RX_GRAN "rx_granularity" -+#define EIP_PROC_TX_RAILMASK "tx_railmask" -+#define EIP_PROC_TMD_INUSE "tmd_inuse" -+#define EIP_PROC_EIPDEBUG "eipdebug" -+#define EIP_PROC_CHECKSUM "checksum" -+ -+/* RX */ -+/* dma_len is used to keep the len of a received packet */ -+/* nmd.nmd_len is the max dma that can be received */ -+/* */ -+struct eip_rmd { -+ struct sk_buff *skb; -+ -+ EP_NMD nmd; -+ u16 dvma_idx; -+ -+ EP_RXD *rxd; -+ struct eip_rmd_head *head; -+ union { -+ struct list_head link; /* when on "busy" list */ -+ struct eip_rmd *next; /* all other lists */ -+ } chain; -+}; -+typedef struct eip_rmd EIP_RMD; -+struct eip_rmd_head { -+ EP_NMH *handle; -+ -+ EP_RCVR *rcvr; -+ EIP_RMD *busy_list; -+ -+ /* stats */ -+ atomic_t stats; -+ unsigned long dma; -+}; -+ -+typedef struct eip_rmd_head EIP_RMD_HEAD; -+typedef struct eip_rx { -+ struct eip_rmd_head head[EIP_SVC_NR]; -+ -+ EIP_RMD *irq_list; -+ short irq_list_nr; -+ -+ /* stats */ -+ unsigned long packets; -+ unsigned long bytes; -+ unsigned long errors; -+ unsigned long dropped; -+ unsigned long reschedule; -+ -+ spinlock_t lock; -+ struct tasklet_struct tasklet; -+ unsigned char rmd_max_nr; -+ unsigned char sysctl_granularity; -+ struct net_device *net_device; -+} EIP_RX; -+ -+/* TX */ -+/* dma_len_max is the maximum len for a given DMA */ -+/* where mnd.nmd_len is the len of the packet to send ~> than skb->len */ -+typedef struct eip_ipfrag_handle { -+ /* common with tmd */ -+ unsigned long dma_base; -+ int dma_len; -+ EP_NMD nmd; -+ u16 dvma_idx; -+ -+ struct sk_buff *skb; -+ struct eip_tmd_head *head; -+ union { -+ struct list_head link; /* when on "busy" list */ -+ struct eip_tmd *next; /* all other lists */ -+ } chain; -+ -+ /* private */ -+ struct list_head list; -+ struct timeval timestamp; -+ unsigned int frag_nr; -+ int datagram_len; /* Ip data */ -+ int dma_correction; -+ EP_PAYLOAD payload; -+} EIP_IPFRAG; -+ -+struct eip_tmd { -+ unsigned long dma_base; -+ int dma_len; -+ EP_NMD nmd; -+ u16 dvma_idx; -+ -+ struct sk_buff *skb; -+ struct eip_tmd_head *head; -+ union { -+ struct list_head link; /* when on "busy" list */ -+ struct eip_tmd *next; /* all other lists */ -+ } chain; -+}; -+ -+struct eip_tmd_head { -+ EP_NMH *handle; -+ -+ struct eip_tmd *tmd; -+ atomic_t stats; -+}; -+ -+typedef struct eip_tmd EIP_TMD; -+typedef struct eip_tmd_head EIP_TMD_HEAD; -+ -+/* #define EIP_MORE_STATS */ -+ -+typedef struct eip_tx { -+ struct net_device *net_device; -+ EP_XMTR *xmtr; -+ EP_SYS *ep_system; -+ -+ struct eip_tmd_head head[EIP_TMD_TYPE_NR]; -+ struct list_head inuse; -+ atomic_t destructor; -+ -+ /* stats */ -+ unsigned long packets; -+ unsigned long bytes; -+ unsigned long errors; -+ unsigned long dropped; -+ unsigned long dma[EIP_SVC_NR]; -+ -+#ifdef EIP_MORE_STATS -+ unsigned long sent_copybreak; -+ unsigned long sent_std; -+ unsigned long sent_aggreg; -+#endif -+ -+ unsigned char tmd_max_nr; -+ -+ unsigned short sysctl_copybreak; -+ unsigned short sysctl_ipfrag_to; -+ unsigned short sysctl_ipfrag_copybreak; -+ unsigned short sysctl_aggregation; -+ -+ unsigned short ipfrag_count; -+ struct list_head ipfrag; -+ spinlock_t ipfraglock; -+ -+ spinlock_t lock; -+ struct tasklet_struct tasklet; -+} EIP_TX; -+ -+/* =============================================== */ -+ /* unsigned long multicast; */ -+#endif /* __EIP_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/eip/eip_stats.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/eip_stats.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/eip_stats.c 2005-06-01 23:12:54.555445792 -0400 -@@ -0,0 +1,374 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* -+ * $Id: eip_stats.c,v 1.34.2.1 2005/01/26 14:31:56 mike Exp $ -+ * $Source: /cvs/master/quadrics/eipmod/eip_stats.c,v $ -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+ -+#include "eip_linux.h" -+#include "eip_stats.h" -+ -+extern EIP_RX *eip_rx; -+extern EIP_TX *eip_tx; -+extern int tx_copybreak_max; -+extern EP_RAILMASK tx_railmask; -+extern int eip_checksum_state; -+extern void eip_stop_queue(void); -+extern void eip_start_queue(void); -+ -+static int eip_stats_read(char *buf, char **start, off_t off, int count, int *eof, void *data) -+{ -+ int i, outlen = 0; -+ -+ *buf = '\0'; -+ strcat(buf, "\n"); -+ strcat(buf, "--------------------------------------------+------------+-----------------+\n"); -+ strcat(buf, " SKB/DMA | | Rx | Tx | TMD TYPE |\n"); -+ strcat(buf, "--------------------------------------------+------------|-----------------+\n"); -+ -+ i = 0; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld | #1[%3.3d/%3.3d/%3.3d] |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i], -+ EIP_STAT_QUEUED_GET(&eip_tx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_tx->head[i].stats), -+ eip_tx->tmd_max_nr); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld | #2[%3.3d/%3.3d/%3.3d] |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i], -+ EIP_STAT_QUEUED_GET(&eip_tx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_tx->head[i].stats), -+ eip_tx->tmd_max_nr); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld | #3[%3.3d/%3.3d/%3.3d] |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i], -+ EIP_STAT_QUEUED_GET(&eip_tx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_tx->head[i].stats), -+ eip_tx->tmd_max_nr); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld +-----------------+\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i]); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i]); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i]); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i]); -+ -+ i++; -+ sprintf(buf + strlen(buf), " [%5d/%5d] | [%3.3d/%3.3d/%3.3d] | %10ld | %10ld |\n", -+ EIP_SVC_SMALLEST_LEN << i, (int) EIP_RCV_DMA_LEN((EIP_SVC_SMALLEST_LEN << i)), -+ EIP_STAT_QUEUED_GET(&eip_rx->head[i].stats), EIP_STAT_ALLOC_GET(&eip_rx->head[i].stats), -+ eip_rx->rmd_max_nr, eip_rx->head[i].dma, eip_tx->dma[i]); -+ -+ strcat(buf, "--------------------------------------------+------------+\n"); -+ sprintf(buf + strlen(buf), " RMD IRQ %4.4d %10lu | %10lu |\n", -+ eip_rx->irq_list_nr, -+ eip_rx->packets, eip_tx->packets); -+ strcat(buf, "--------------------------------------------+------------+\n"); -+ -+#ifdef EIP_MORE_STATS -+ strcat(buf, "\n"); -+ sprintf(buf + strlen(buf), " Copybreak %10ld Std %10ld Aggreg %10ld\n", -+ eip_tx->sent_copybreak, eip_tx->sent_std, eip_tx->sent_aggreg); -+#endif -+ -+ -+ strcat(buf, "\n"); -+ sprintf(buf + strlen(buf), "Rx bytes: %lu (%lu Mb) errors: %lu dropped: %lu reschedule: %lu\n", -+ eip_rx->bytes, eip_rx->bytes / (1024 * 1024), eip_rx->errors, eip_rx->dropped, eip_rx->reschedule); -+ sprintf(buf + strlen(buf), "Tx bytes: %lu (%lu Mb) errors: %lu dropped: %lu\n", -+ eip_tx->bytes, eip_tx->bytes / (1024 * 1024), eip_tx->errors, eip_tx->dropped); -+ strcat(buf, "\n"); -+ -+ outlen = strlen(buf); -+ ASSERT(outlen < PAGE_SIZE); -+ *eof = 1; -+ return outlen; -+} -+ -+void eip_stats_dump(void) -+{ -+ int eof; -+ -+ char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ -+ if (buf == NULL) -+ { -+ printk("no memory to produce eip_stats\n"); -+ return; -+ } -+ -+ eip_stats_read(buf, NULL, 0, 0, &eof, NULL); -+ -+ printk(buf); -+ -+ kfree(buf); -+} -+ -+static int eip_stats_write(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ int i; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&eip_rx->lock, flags); -+ eip_rx->packets = 0; -+ eip_rx->bytes = 0; -+ eip_rx->errors = 0; -+ eip_rx->dropped = 0; -+ eip_rx->reschedule = 0; -+ for (i = 0; i < EIP_SVC_NR; eip_rx->head[i].dma = 0, i++); -+ spin_unlock_irqrestore(&eip_rx->lock, flags); -+ -+ spin_lock_irqsave(&eip_tx->lock, flags); -+ eip_tx->packets = 0; -+ eip_tx->bytes = 0; -+ eip_tx->errors = 0; -+ eip_tx->dropped = 0; -+#ifdef EIP_MORE_STATS -+ eip_tx->sent_copybreak = 0; -+ eip_tx->sent_std = 0; -+ eip_tx->sent_aggreg = 0; -+#endif -+ for (i = 0; i < EIP_SVC_NR; eip_tx->dma[i] = 0, i++); -+ spin_unlock_irqrestore(&eip_tx->lock, flags); -+ -+ return count; -+} -+ -+#define eip_stats_var_write(name) \ -+static int eip_stats_##name##_write(struct file *file, const char *buf, unsigned long count, void *data) \ -+{ \ -+ char * b = (char *) buf; \ -+ *(b + count) = '\0'; \ -+ eip_##name##_set((int) simple_strtoul(b, NULL, 10)); \ -+ return count; \ -+} -+ -+#define eip_stats_var_read(name, var) \ -+static int eip_stats_##name##_read(char *buf, char **start, off_t off, int count, int *eof, void *data) \ -+{ \ -+ sprintf(buf, "%d\n", var); \ -+ *eof = 1; \ -+ return strlen(buf); \ -+} -+ -+ -+#define eip_stats_var_set(name, min, max, default, var) \ -+void eip_##name##_set(int i) \ -+{ \ -+ if ( (i >= min) && (i <= max)) { \ -+ EIP_DBG_PRINTK(EIP_DBG_GEN, "Setting " #name " to %d\n", i); \ -+ var =(unsigned short) i; \ -+ } \ -+ else { \ -+ EIP_ERR_PRINTF("parameter error : %d <= " #name "(%d) <= %d using default %d\n", min, i, (int) max, (int) default); \ -+ } \ -+} -+ -+eip_stats_var_set(tx_copybreak, 0, tx_copybreak_max, EIP_TX_COPYBREAK, eip_tx->sysctl_copybreak); -+eip_stats_var_set(rx_granularity, 1, EIP_RMD_MIN_NR, EIP_RX_GRANULARITY, eip_rx->sysctl_granularity); -+eip_stats_var_set(tx_railmask, 0, EP_RAILMASK_ALL, EP_RAILMASK_ALL, tx_railmask); -+eip_stats_var_set(ipfrag_to, 0, (1 << 16), EIP_IPFRAG_TO, eip_tx->sysctl_ipfrag_to); -+eip_stats_var_set(aggregation, 0, 1, 1, eip_tx->sysctl_aggregation); -+eip_stats_var_set(ipfrag_copybreak, 0, EIP_IPFRAG_COPYBREAK, EIP_IPFRAG_COPYBREAK, eip_tx->sysctl_ipfrag_copybreak); -+/* eip_stats_var_set(eipdebug, 0, , 0, eipdebug); */ -+ -+eip_stats_var_read(aggregation, eip_tx->sysctl_aggregation); -+eip_stats_var_read(ipfrag_count, eip_tx->ipfrag_count); -+eip_stats_var_read(ipfrag_to, eip_tx->sysctl_ipfrag_to); -+eip_stats_var_read(ipfrag_copybreak, eip_tx->sysctl_ipfrag_copybreak); -+eip_stats_var_read(tx_copybreak, eip_tx->sysctl_copybreak); -+eip_stats_var_read(rx_granularity, eip_rx->sysctl_granularity); -+eip_stats_var_read(tx_railmask, tx_railmask); -+ -+eip_stats_var_write(aggregation); -+eip_stats_var_write(ipfrag_to); -+eip_stats_var_write(ipfrag_copybreak); -+eip_stats_var_write(tx_copybreak); -+eip_stats_var_write(rx_granularity); -+eip_stats_var_write(tx_railmask); -+ -+ -+static int eip_checksum_write(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ char * b = (char *) buf; -+ int value; -+ -+ *(b + count) = '\0'; -+ -+ value = (int) simple_strtoul(b, NULL, 10); -+ if ((value >= CHECKSUM_NONE) && (value <= CHECKSUM_UNNECESSARY)) -+ eip_checksum_state = value; -+ else -+ EIP_ERR_PRINTF("%d <= checksum(%d) <= %d using old value %d\n", CHECKSUM_NONE, value, CHECKSUM_UNNECESSARY, eip_checksum_state); -+ -+ return count; -+} -+ -+static int eip_checksum_read(char *buf, char **start, off_t off, int count, int *eof, void *data) -+{ -+ switch ( eip_checksum_state ) -+ { -+ case 0 : sprintf(buf, "0 CHECKSUM_NONE\n"); break; -+ case 1 : sprintf(buf, "1 CHECKSUM_HW\n"); break; -+ case 2 : sprintf(buf, "2 CHECKSUM_UNNECESSARY\n"); break; -+ default : sprintf(buf, "%d INVALID VALUE\n", eip_checksum_state); break; -+ } -+ *eof = 1; -+ return strlen(buf); -+} -+ -+static int eip_stats_eipdebug_read(char *buf, char **start, off_t off, int count, int *eof, void *data) -+{ -+ *buf = '\0'; -+ sprintf(buf + strlen(buf), "0x%x\n", eipdebug); -+ *eof = 1; -+ return strlen(buf); -+} -+static int eip_stats_eipdebug_write(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ char * p = (char *) buf; -+ *(p + count - 1) = '\0'; -+ eipdebug = simple_strtoul(p, NULL, 0); -+ __EIP_DBG_PRINTK("Setting eipdebug to 0x%x\n", eipdebug); -+ return count; -+} -+ -+static int eip_stats_tmd_inuse_read(char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ struct list_head *lp; -+ unsigned long flags; -+ unsigned int len = 0; -+ -+ spin_lock_irqsave(&eip_tx->lock, flags); -+ list_for_each (lp, &eip_tx->inuse) { -+ EIP_TMD *tmd = list_entry (lp, EIP_TMD, chain.link); -+ EIP_HEADER *eiph = (EIP_HEADER *) tmd->dma_base; -+ -+ len += sprintf(page+len, "tmd=%p id=%d len=%d\n", -+ tmd, eiph ? ntohs(eiph->h_dhost.ip_addr) : -1, -+ tmd->dma_len); -+ -+ if (len + 40 >= count) -+ break; -+ } -+ spin_unlock_irqrestore(&eip_tx->lock, flags); -+ -+ return qsnet_proc_calc_metrics (page, start, off, count, eof, len); -+} -+ -+static int eip_stats_debug_rx_flush(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "Flushing rx ...\n"); -+ tasklet_schedule(&eip_rx->tasklet); -+ return count; -+} -+static int eip_stats_debug_tx_flush(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "Flushing tx ... %d tmds reclaimed\n", ep_enable_txcallbacks(eip_tx->xmtr)); -+ ep_disable_txcallbacks(eip_tx->xmtr); -+ tasklet_schedule(&eip_tx->tasklet); -+ return count; -+} -+ -+#define EIP_PROC_PARENT_NR (3) -+/* NOTE : the parents should be declared b4 the children */ -+static EIP_PROC_FS eip_procs[] = { -+ /* {name, parent, read fn, write fn, allocated, entry}, */ -+ {EIP_PROC_ROOT_DIR, &qsnet_procfs_root, NULL, NULL, 0, NULL}, -+ {EIP_PROC_DEBUG_DIR, &eip_procs[0].entry, NULL, NULL, 0, NULL}, -+ {EIP_PROC_AGGREG_DIR, &eip_procs[0].entry, NULL, NULL, 0, NULL}, /* end of parents */ -+ {EIP_PROC_STATS, &eip_procs[0].entry, eip_stats_read, eip_stats_write, 0, NULL}, -+ {EIP_PROC_TX_COPYBREAK, &eip_procs[0].entry, eip_stats_tx_copybreak_read, eip_stats_tx_copybreak_write, 0, NULL}, -+ {EIP_PROC_RX_GRAN, &eip_procs[0].entry, eip_stats_rx_granularity_read, eip_stats_rx_granularity_write, 0, NULL}, -+ {EIP_PROC_TX_RAILMASK, &eip_procs[0].entry, eip_stats_tx_railmask_read, eip_stats_tx_railmask_write, 0, NULL}, -+ {EIP_PROC_TMD_INUSE, &eip_procs[0].entry, eip_stats_tmd_inuse_read, NULL, 0, NULL}, -+ {EIP_PROC_EIPDEBUG, &eip_procs[0].entry, eip_stats_eipdebug_read, eip_stats_eipdebug_write, 0, NULL}, -+ {EIP_PROC_CHECKSUM, &eip_procs[0].entry, eip_checksum_read, eip_checksum_write, 0, NULL}, -+ {EIP_PROC_DEBUG_RX_FLUSH, &eip_procs[1].entry, NULL, eip_stats_debug_rx_flush, 0, NULL}, -+ {EIP_PROC_DEBUG_TX_FLUSH, &eip_procs[1].entry, NULL, eip_stats_debug_tx_flush, 0, NULL}, -+ {"ipfrag_count", &eip_procs[2].entry, eip_stats_ipfrag_count_read, NULL, 0, NULL}, -+ {EIP_PROC_AGGREG_TO, &eip_procs[2].entry, eip_stats_ipfrag_to_read, eip_stats_ipfrag_to_write, 0, NULL}, -+ {EIP_PROC_AGGREG_ONOFF, &eip_procs[2].entry, eip_stats_aggregation_read, eip_stats_aggregation_write, 0, NULL}, -+ {EIP_PROC_AGGREG_COPYBREAK, &eip_procs[2].entry, eip_stats_ipfrag_copybreak_read, eip_stats_ipfrag_copybreak_write, 0, NULL}, -+ {NULL, NULL, NULL, NULL, 1, NULL}, -+}; -+ -+int eip_stats_init(void) -+{ -+ int p; -+ -+ for (p = 0; !eip_procs[p].allocated; p++) { -+ if (p < EIP_PROC_PARENT_NR) -+ eip_procs[p].entry = proc_mkdir(eip_procs[p].name, *eip_procs[p].parent); -+ else -+ eip_procs[p].entry = create_proc_entry(eip_procs[p].name, 0, *eip_procs[p].parent); -+ -+ if (!eip_procs[p].entry) { -+ EIP_ERR_PRINTF("%s\n", "Cannot allocate proc entry"); -+ eip_stats_cleanup(); -+ return -ENOMEM; -+ } -+ -+ eip_procs[p].entry->owner = THIS_MODULE; -+ eip_procs[p].entry->write_proc = eip_procs[p].write; -+ eip_procs[p].entry->read_proc = eip_procs[p].read; -+ eip_procs[p].allocated = 1; -+ } -+ eip_procs[p].allocated = 0; -+ return 0; -+} -+ -+void eip_stats_cleanup(void) -+{ -+ int p; -+ for (p = 0; eip_procs[p].allocated; p++) { -+ EIP_DBG_PRINTF(EIP_DBG_GEN, "Removing %s from proc\n", eip_procs[p].name); -+ remove_proc_entry(eip_procs[p].name, *eip_procs[p].parent); -+ } -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/eip/eip_stats.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/eip_stats.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/eip_stats.h 2005-06-01 23:12:54.555445792 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: eip_stats.h,v 1.14 2004/05/10 14:47:47 daniel Exp $" -+ -+#ifndef __EIP_STATS_H -+#define __EIP_STATS_H -+ -+int eip_stats_init(void); -+void eip_stats_cleanup(void); -+void eip_rx_granularity_set(int); -+void eip_tx_copybreak_set(int); -+void eip_ipfrag_to_set(int); -+void eip_aggregation_set(int); -+void eip_ipfrag_copybreak_set(int); -+void eip_stats_dump(void); -+ -+#endif /* __EIP_STATS_H */ -Index: linux-2.4.21/drivers/net/qsnet/eip/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/Makefile 2005-06-01 23:12:54.555445792 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/eip/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/eip/Makefile -+# -+ -+list-multi := eip.o -+eip-objs := eip_linux.o eip_stats.o -+export-objs := -+obj-$(CONFIG_EIP) := eip.o -+ -+eip.o : $(eip-objs) -+ $(LD) -r -o $@ $(eip-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/eip/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/Makefile.conf 2005-06-01 23:12:54.555445792 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = eip.o -+MODULENAME = eip -+KOBJFILES = eip_linux.o eip_stats.o -+EXPORT_KOBJS = -+CONFIG_NAME = CONFIG_EIP -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/eip/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/eip/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/eip/quadrics_version.h 2005-06-01 23:12:54.556445640 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/elan/bitmap.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/bitmap.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/bitmap.c 2005-06-01 23:12:54.556445640 -0400 -@@ -0,0 +1,287 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: bitmap.c,v 1.5 2004/01/20 17:32:17 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/shared/bitmap.c,v $*/ -+ -+#if defined(__KERNEL__) -+#include -+#endif -+#include -+#include -+ -+/* -+ * Return the index of the first available bit in the -+ * bitmap , or -1 for failure -+ */ -+int -+bt_freebit (bitmap_t *bitmap, int nbits) -+{ -+ int last = (--nbits) >> BT_ULSHIFT; -+ int maxbit; -+ int i, j; -+ -+ /* look for a word with a bit off */ -+ for (i = 0; i <= last; i++) -+ if (bitmap[i] != ~((bitmap_t) 0)) -+ break; -+ -+ if (i <= last) -+ { -+ /* found an word with a bit off, now see which bit it is */ -+ maxbit = (i == last) ? (nbits & BT_ULMASK) : (BT_NBIPUL-1); -+ for (j = 0; j <= maxbit; j++) -+ if ((bitmap[i] & (1 << j)) == 0) -+ return ((i << BT_ULSHIFT) | j); -+ } -+ return (-1); -+ -+} -+ -+/* -+ * bt_lowbit: -+ * Return the index of the lowest set bit in the -+ * bitmap, or -1 for failure. -+ */ -+int -+bt_lowbit (bitmap_t *bitmap, int nbits) -+{ -+ int last = (--nbits) >> BT_ULSHIFT; -+ int maxbit; -+ int i, j; -+ -+ /* look for a word with a bit on */ -+ for (i = 0; i <= last; i++) -+ if (bitmap[i] != 0) -+ break; -+ if (i <= last) -+ { -+ /* found a word bit a bit on, now see which bit it is */ -+ maxbit = (i == last) ? (nbits & BT_ULMASK) : (BT_NBIPUL-1); -+ for (j = 0; j <= maxbit; j++) -+ if (bitmap[i] & (1 << j)) -+ return ((i << BT_ULSHIFT) | j); -+ } -+ -+ return (-1); -+} -+ -+/* -+ * Return the index of the first available bit in the -+ * bitmap , or -1 for failure -+ */ -+int -+bt_nextbit (bitmap_t *bitmap, int nbits, int last, int isset) -+{ -+ int first = ((last+1) + BT_NBIPUL-1) >> BT_ULSHIFT; -+ int end = (--nbits) >> BT_ULSHIFT; -+ int maxbit; -+ int i, j; -+ -+ /* look for bits before the first whole word */ -+ if (((last+1) & BT_ULMASK) != 0) -+ { -+ maxbit = ((first-1) == last) ? (nbits & BT_ULMASK) : (BT_NBIPUL-1); -+ for (j = ((last+1) & BT_ULMASK); j <= maxbit; j++) -+ if ((bitmap[first-1] & (1 << j)) == (isset << j)) -+ return (((first-1) << BT_ULSHIFT) | j); -+ } -+ -+ /* look for a word with a bit off */ -+ for (i = first; i <= end; i++) -+ if (bitmap[i] != (isset ? 0 : ~((bitmap_t) 0))) -+ break; -+ -+ if (i <= end) -+ { -+ /* found an word with a bit off, now see which bit it is */ -+ maxbit = (i == end) ? (nbits & BT_ULMASK) : (BT_NBIPUL-1); -+ for (j = 0; j <= maxbit; j++) -+ if ((bitmap[i] & (1 << j)) == (isset << j)) -+ return ((i << BT_ULSHIFT) | j); -+ } -+ return (-1); -+} -+ -+void -+bt_copy (bitmap_t *a, bitmap_t *b, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ b[i] = a[i]; -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ if (BT_TEST(a, i)) -+ BT_SET(b,i); -+ else -+ BT_CLEAR(b,i); -+} -+ -+void -+bt_zero (bitmap_t *bitmap, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ bitmap[i] = 0; -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ BT_CLEAR(bitmap,i); -+} -+ -+void -+bt_fill (bitmap_t *bitmap, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ bitmap[i] = ~((bitmap_t) 0); -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ BT_SET(bitmap,i); -+} -+ -+int -+bt_cmp (bitmap_t *a, bitmap_t *b, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ if (a[i] != b[i]) -+ return (1); -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ if (BT_TEST (a, i) != BT_TEST(b, i)) -+ return (1); -+ return (0); -+} -+ -+void -+bt_intersect (bitmap_t *a, bitmap_t *b, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ a[i] &= b[i]; -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ if (BT_TEST (a, i) && BT_TEST (b, i)) -+ BT_SET (a, i); -+ else -+ BT_CLEAR (a, i); -+} -+ -+void -+bt_remove (bitmap_t *a, bitmap_t *b, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ a[i] &= ~b[i]; -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ if (BT_TEST (b, i)) -+ BT_CLEAR (a, i); -+} -+ -+void -+bt_add (bitmap_t *a, bitmap_t *b, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < (nbits>>BT_ULSHIFT); i++) -+ a[i] |= b[i]; -+ -+ for (i <<= BT_ULSHIFT; i < nbits; i++) -+ if (BT_TEST(b, i)) -+ BT_SET (a, i); -+} -+ -+/* -+ * bt_spans : partition a spans partition b -+ * == all bits set in 'b' are set in 'a' -+ */ -+int -+bt_spans (bitmap_t *a, bitmap_t *b, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < nbits; i++) -+ if (BT_TEST (b, i) && !BT_TEST (a, i)) -+ return (0); -+ return (1); -+} -+ -+/* -+ * bt_subset: copy [base,base+nbits-1] from 'a' to 'b' -+ */ -+void -+bt_subset (bitmap_t *a, bitmap_t *b, int base, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < nbits; i++) -+ { -+ if (BT_TEST (a, base+i)) -+ BT_SET(b,i); -+ else -+ BT_CLEAR (b,i); -+ } -+} -+ -+void -+bt_up (bitmap_t *a, bitmap_t *b, bitmap_t *c, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < nbits; i++) -+ { -+ if (!BT_TEST (a, i) && BT_TEST (b, i)) -+ { -+ BT_SET (c, i); -+ } -+ else -+ { -+ BT_CLEAR (c, i); -+ } -+ } -+} -+ -+void -+bt_down (bitmap_t *a, bitmap_t *b, bitmap_t *c, int nbits) -+{ -+ int i; -+ -+ for (i = 0; i < nbits; i++) -+ { -+ if (BT_TEST (a, i) && !BT_TEST (b, i)) -+ { -+ BT_SET (c, i); -+ } -+ else -+ { -+ BT_CLEAR (c, i); -+ } -+ } -+} -+ -+int -+bt_nbits (bitmap_t *a, int nbits) -+{ -+ int i, c; -+ for (i = 0, c = 0; i < nbits; i++) -+ if (BT_TEST (a, i)) -+ c++; -+ return (c); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/capability.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/capability.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/capability.c 2005-06-01 23:12:54.557445488 -0400 -@@ -0,0 +1,628 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: capability.c,v 1.13 2004/07/20 10:15:33 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/capability.c,v $ */ -+ -+ -+#include -+#include -+ -+static LIST_HEAD(elan_cap_list); -+ -+typedef struct elan_vp_struct -+{ -+ struct list_head list; -+ ELAN_CAPABILITY vp; -+} ELAN_VP_NODE_STRUCT; -+ -+ -+typedef struct elan_attached_struct -+{ -+ void *cb_args; -+ ELAN_DESTROY_CB cb_func; -+} ELAN_ATTACHED_STRUCT; -+ -+typedef struct elan_cap_node_struct -+{ -+ struct list_head list; -+ ELAN_CAP_STRUCT node; -+ ELAN_ATTACHED_STRUCT *attached[ELAN_MAX_RAILS]; -+ struct list_head vp_list; -+} ELAN_CAP_NODE_STRUCT; -+ -+ -+ELAN_CAP_NODE_STRUCT * -+find_cap_node(ELAN_CAPABILITY *cap) -+{ -+ struct list_head *tmp; -+ ELAN_CAP_NODE_STRUCT *ptr=NULL; -+ -+ list_for_each(tmp, &elan_cap_list) { -+ ptr = list_entry(tmp, ELAN_CAP_NODE_STRUCT , list); -+ /* is it an exact match */ -+ if ( ELAN_CAP_TYPE_MATCH(&ptr->node.cap,cap) -+ && ELAN_CAP_GEOM_MATCH(&ptr->node.cap,cap)) { -+ return ptr; -+ } -+ } -+ return ptr; -+}; -+ -+ELAN_VP_NODE_STRUCT * -+find_vp_node( ELAN_CAP_NODE_STRUCT *cap_node,ELAN_CAPABILITY *map) -+{ -+ struct list_head * tmp; -+ ELAN_VP_NODE_STRUCT * ptr = NULL; -+ -+ list_for_each(tmp, &cap_node->vp_list) { -+ ptr = list_entry(tmp, ELAN_VP_NODE_STRUCT , list); -+ /* is it an exact match */ -+ if ( ELAN_CAP_TYPE_MATCH(&ptr->vp,map) -+ && ELAN_CAP_GEOM_MATCH(&ptr->vp,map)){ -+ return ptr; -+ } -+ } -+ return ptr; -+} -+ -+int -+elan_validate_cap(ELAN_CAPABILITY *cap) -+{ -+ char space[127]; -+ -+ ELAN_DEBUG1 (ELAN_DBG_VP,"elan_validate_cap %s\n",elan_capability_string(cap,space)); -+ -+ /* check versions */ -+ if (cap->cap_version != ELAN_CAP_VERSION_NUMBER) -+ { -+ ELAN_DEBUG2 (ELAN_DBG_VP,"elan_validate_cap: (cap->Version != ELAN_CAP_VERSION) %d %d\n", cap->cap_version, ELAN_CAP_VERSION_NUMBER); -+ return (EINVAL); -+ } -+ -+ /* check its not HWTEST */ -+ if ( cap->cap_type & ELAN_CAP_TYPE_HWTEST ) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_cap: failed type = ELAN_CAP_TYPE_HWTEST \n"); -+ return (EINVAL); -+ } -+ -+ /* check its type */ -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_KERNEL : -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_cap: failed type = ELAN_CAP_TYPE_KERNEL \n"); -+ return (EINVAL); -+ -+ /* check it has a valid type */ -+ case ELAN_CAP_TYPE_BLOCK: -+ case ELAN_CAP_TYPE_CYCLIC: -+ break; -+ -+ /* all others are failed as well */ -+ default: -+ ELAN_DEBUG1 (ELAN_DBG_VP,"elan_validate_cap: failed unknown type = %x \n", (cap->cap_type & ELAN_CAP_TYPE_MASK)); -+ return (EINVAL); -+ } -+ -+ if ((cap->cap_lowcontext == ELAN_CAP_UNINITIALISED) || (cap->cap_highcontext == ELAN_CAP_UNINITIALISED) -+ || (cap->cap_lownode == ELAN_CAP_UNINITIALISED) || (cap->cap_highnode == ELAN_CAP_UNINITIALISED)) -+ { -+ -+ ELAN_DEBUG4 (ELAN_DBG_VP,"elan_validate_cap: ELAN_CAP_UNINITIALISED LowNode %d HighNode %d LowContext %d highContext %d\n", -+ cap->cap_lownode , cap->cap_highnode, -+ cap->cap_lowcontext , cap->cap_highcontext); -+ return (EINVAL); -+ } -+ -+ if (cap->cap_lowcontext > cap->cap_highcontext) -+ { -+ ELAN_DEBUG2 (ELAN_DBG_VP,"elan_validate_cap: (cap->cap_lowcontext > cap->cap_highcontext) %d %d\n",cap->cap_lowcontext , cap->cap_highcontext); -+ return (EINVAL); -+ } -+ -+ if (cap->cap_lownode > cap->cap_highnode) -+ { -+ ELAN_DEBUG2 (ELAN_DBG_VP,"elan_validate_cap: (cap->cap_lownode > cap->cap_highnode) %d %d\n",cap->cap_lownode, cap->cap_highnode); -+ return (EINVAL); -+ } -+ -+ if (cap->cap_mycontext != ELAN_CAP_UNINITIALISED) -+ { -+ ELAN_DEBUG1 (ELAN_DBG_VP,"elan_validate_cap: failed cap->cap_mycontext is set %d \n", cap->cap_mycontext); -+ return (EINVAL); -+ } -+ -+ -+ if ((ELAN_CAP_NUM_NODES(cap) * ELAN_CAP_NUM_CONTEXTS(cap)) > ELAN_MAX_VPS) -+ { -+ ELAN_DEBUG6 (ELAN_DBG_VP,"elan_validate_cap: too many vps LowNode %d HighNode %d LowContext %d highContext %d, %d >% d\n", -+ cap->cap_lownode , cap->cap_highnode, -+ cap->cap_lowcontext , cap->cap_highcontext, -+ (ELAN_CAP_NUM_NODES(cap) * ELAN_CAP_NUM_CONTEXTS(cap)), -+ ELAN_MAX_VPS); -+ -+ return (EINVAL); -+ } -+ -+ return (ESUCCESS); -+} -+ -+int -+elan_validate_map(ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map) -+{ -+ ELAN_CAP_NODE_STRUCT * ptr = NULL; -+ ELAN_VP_NODE_STRUCT * vptr = NULL; -+ char space[256]; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_map \n"); -+ ELAN_DEBUG1 (ELAN_DBG_VP,"elan_validate_map cap = %s \n",elan_capability_string(cap,space)); -+ ELAN_DEBUG1 (ELAN_DBG_VP,"elan_validate_map map = %s \n",elan_capability_string(map,space)); -+ -+ /* does cap exist */ -+ ptr = find_cap_node(cap); -+ if ( ptr == NULL ) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_map: cap not found \n"); -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ /* is it active */ -+ if ( ! ptr->node.active ) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_map: cap not active \n"); -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ /* are they the same */ -+ if ( ELAN_CAP_TYPE_MATCH(cap,map) -+ && ELAN_CAP_GEOM_MATCH(cap,map)) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_map: cap == map passed\n"); -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ -+ /* is map in map list */ -+ vptr = find_vp_node(ptr, map); -+ if ( vptr == NULL ) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_map: map not found\n"); -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ ELAN_DEBUG0 (ELAN_DBG_VP,"elan_validate_map: map passed\n"); -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+int -+elan_create_cap(ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap) -+{ -+ char space[127]; -+ struct list_head * tmp; -+ ELAN_CAP_NODE_STRUCT * ptr = NULL; -+ int i, rail; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG1 (ELAN_DBG_VP,"elan_create_cap %s\n",elan_capability_string(cap,space)); -+ -+ /* need to check that the cap does not over lap another one -+ or is an exact match with only the userkey changing */ -+ list_for_each(tmp, &elan_cap_list) { -+ ptr = list_entry(tmp, ELAN_CAP_NODE_STRUCT , list); -+ -+ /* is it an exact match */ -+ if ( ELAN_CAP_TYPE_MATCH(&ptr->node.cap,cap) -+ && ELAN_CAP_GEOM_MATCH(&ptr->node.cap,cap) -+ && (&ptr->node.owner == owner)) { -+ if ( ptr->node.active ) { -+ /* dont inc attached count as its like a create */ -+ ptr->node.cap.cap_userkey = cap->cap_userkey; -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ else -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ } -+ -+ /* does it overlap, even with ones being destroyed */ -+ if (elan_cap_overlap(&ptr->node.cap,cap)) -+ { -+ kmutex_unlock(&elan_mutex); -+ return EACCES; -+ } -+ } -+ -+ /* create it */ -+ KMEM_ALLOC(ptr, ELAN_CAP_NODE_STRUCT *, sizeof(ELAN_CAP_NODE_STRUCT), 1); -+ if (ptr == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return ENOMEM; -+ } -+ -+ /* create space for the attached array */ -+ for(rail=0;railattached[rail]=NULL; -+ if ( ELAN_CAP_IS_RAIL_SET(cap,rail) ) -+ { -+ KMEM_ALLOC(ptr->attached[rail], ELAN_ATTACHED_STRUCT *, sizeof(ELAN_ATTACHED_STRUCT) * ELAN_CAP_NUM_CONTEXTS(cap), 1); -+ if (ptr->attached[rail] == NULL) -+ { -+ for(;rail>=0;rail--) -+ if ( ptr->attached[rail] ) -+ KMEM_FREE(ptr->attached[rail], sizeof(ELAN_ATTACHED_STRUCT) * ELAN_CAP_NUM_CONTEXTS(cap)); -+ -+ KMEM_FREE(ptr, sizeof(ELAN_CAP_NODE_STRUCT)); -+ kmutex_unlock(&elan_mutex); -+ return ENOMEM; -+ } -+ /* blank the attached array */ -+ for(i=0;iattached[rail][i].cb_func = NULL; -+ } -+ } -+ -+ ptr->node.owner = owner; -+ ptr->node.cap = *cap; -+ ptr->node.attached = 1; /* creator counts as attached */ -+ ptr->node.active = 1; -+ ptr->vp_list.next = &(ptr->vp_list); -+ ptr->vp_list.prev = &(ptr->vp_list); -+ -+ list_add_tail(&ptr->list, &elan_cap_list); -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+void -+elan_destroy_cap_test(ELAN_CAP_NODE_STRUCT *cap_ptr) -+{ -+ /* called by someone holding the mutex */ -+ struct list_head * vp_tmp; -+ ELAN_VP_NODE_STRUCT * vp_ptr = NULL; -+ int rail; -+ -+ /* check to see if it can be deleted now */ -+ if ( cap_ptr->node.attached == 0 ) { -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_destroy_cap_test: attached == 0\n"); -+ -+ /* delete the vp list */ -+ list_for_each(vp_tmp, &(cap_ptr->vp_list)) { -+ vp_ptr = list_entry(vp_tmp, ELAN_VP_NODE_STRUCT , list); -+ list_del(&vp_ptr->list); -+ KMEM_FREE( vp_ptr, sizeof(ELAN_VP_NODE_STRUCT)); -+ } -+ -+ list_del(&cap_ptr->list); -+ -+ /* delete space for the attached array */ -+ for(rail=0;railattached[rail]) -+ KMEM_FREE(cap_ptr->attached[rail], sizeof(ELAN_ATTACHED_STRUCT) * ELAN_CAP_NUM_CONTEXTS(&(cap_ptr->node.cap))); -+ -+ KMEM_FREE(cap_ptr, sizeof(ELAN_CAP_NODE_STRUCT)); -+ } -+} -+ -+int -+elan_destroy_cap(ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap) -+{ -+ char space[127]; -+ struct list_head * el; -+ struct list_head * nel; -+ ELAN_CAP_NODE_STRUCT * ptr = NULL; -+ int i, rail; -+ int found = 0; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG1 (ELAN_DBG_CAP,"elan_destroy_cap %s\n",elan_capability_string(cap,space)); -+ -+ list_for_each_safe (el, nel, &elan_cap_list) { -+ ptr = list_entry(el, ELAN_CAP_NODE_STRUCT , list); -+ -+ /* is it an exact match */ -+ if ( (ptr->node.owner == owner ) -+ && ( (cap == NULL) -+ || (ELAN_CAP_TYPE_MATCH(&ptr->node.cap,cap) && ELAN_CAP_GEOM_MATCH(&ptr->node.cap,cap)))) { -+ -+ if ( ptr->node.active ) { -+ -+ /* mark as in active and dec attached count */ -+ ptr->node.active = 0; -+ ptr->node.attached--; -+ ptr->node.owner = 0; /* no one own's it now */ -+ -+ /* need to tell any one who was attached that this has been destroy'd */ -+ for(rail=0;railnode.cap), rail)) { -+ for(i=0;i< ELAN_CAP_NUM_CONTEXTS(&(ptr->node.cap));i++) -+ if ( ptr->attached[rail][i].cb_func != NULL) -+ ptr->attached[rail][i].cb_func(ptr->attached[rail][i].cb_args, cap, NULL); -+ } -+ -+ /* now try to destroy it */ -+ elan_destroy_cap_test(ptr); -+ -+ /* found it */ -+ found = 1; -+ } -+ } -+ } -+ -+ if ( found ) -+ { -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ -+ /* failed */ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_destroy_cap: didnt find it \n"); -+ -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+} -+ -+int -+elan_get_caps(uint *number_of_results, uint array_size, ELAN_CAP_STRUCT *caps) -+{ -+ uint results = 0; -+ struct list_head * tmp; -+ ELAN_CAP_NODE_STRUCT * ptr = NULL; -+ -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_get_caps\n"); -+ -+ list_for_each(tmp, &elan_cap_list) { -+ ptr = list_entry(tmp, ELAN_CAP_NODE_STRUCT , list); -+ -+ copyout(&ptr->node, &caps[results], sizeof (ELAN_CAP_STRUCT)); -+ -+ results++; -+ -+ if ( results >= array_size ) -+ { -+ copyout(&results, number_of_results, sizeof(uint)); -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ } -+ -+ copyout(&results, number_of_results, sizeof(uint)); -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+int -+elan_create_vp(ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map) -+{ -+ ELAN_CAP_NODE_STRUCT * cap_ptr = NULL; -+ ELAN_VP_NODE_STRUCT * vp_ptr = NULL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_create_vp\n"); -+ -+ /* the railmasks must match */ -+ if ( cap->cap_railmask != map->cap_railmask) -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ /* does the cap exist */ -+ cap_ptr = find_cap_node(cap); -+ if ((cap_ptr == NULL) || ( cap_ptr->node.owner != owner ) || (! cap_ptr->node.active) ) -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ /* is there already a mapping */ -+ vp_ptr = find_vp_node(cap_ptr,map); -+ if ( vp_ptr != NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ /* create space for mapping */ -+ KMEM_ALLOC(vp_ptr, ELAN_VP_NODE_STRUCT *, sizeof(ELAN_VP_NODE_STRUCT), 1); -+ if (vp_ptr == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return ENOMEM; -+ } -+ -+ /* copy map */ -+ vp_ptr->vp = *map; -+ list_add_tail(&vp_ptr->list, &(cap_ptr->vp_list)); -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+int -+elan_destroy_vp(ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map) -+{ -+ ELAN_CAP_NODE_STRUCT * cap_ptr = NULL; -+ ELAN_VP_NODE_STRUCT * vp_ptr = NULL; -+ int i, rail; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_destroy_vp\n"); -+ -+ cap_ptr = find_cap_node(cap); -+ if ((cap_ptr!=NULL) && (cap_ptr->node.owner == owner) && ( cap_ptr->node.active)) -+ { -+ vp_ptr = find_vp_node( cap_ptr, map ); -+ if ( vp_ptr != NULL ) -+ { -+ list_del(&vp_ptr->list); -+ KMEM_FREE(vp_ptr, sizeof(ELAN_VP_NODE_STRUCT)); -+ -+ /* need to tell those who are attached that map is nolonger in use */ -+ for(rail=0;railnode.cap));i++) -+ if ( cap_ptr->attached[rail][i].cb_func != NULL) -+ cap_ptr->attached[rail][i].cb_func( cap_ptr->attached[rail][i].cb_args, cap, map); -+ } -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ } -+ -+ /* didnt find it */ -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+} -+ -+int -+elan_attach_cap(ELAN_CAPABILITY *cap, unsigned int rail, void *args, ELAN_DESTROY_CB func) -+{ -+ char space[127]; -+ struct list_head *el; -+ -+ ELAN_DEBUG1 (ELAN_DBG_CAP,"elan_attach_cap %s\n",elan_capability_string(cap,space)); -+ -+ /* currently must provide a call back, as null mean something */ -+ if ( func == NULL) -+ return (EINVAL); -+ -+ /* mycontext must be set and correct */ -+ if ( ! ELAN_CAP_VALID_MYCONTEXT(cap)) -+ return (EINVAL); -+ -+ /* rail must be one of the rails in railmask */ -+ if (((1 << rail) & cap->cap_railmask) == 0) -+ return (EINVAL); -+ -+ kmutex_lock(&elan_mutex); -+ -+ list_for_each(el, &elan_cap_list) { -+ ELAN_CAP_NODE_STRUCT *cap_ptr = list_entry(el, ELAN_CAP_NODE_STRUCT , list); -+ -+ /* is it an exact match */ -+ if (ELAN_CAP_MATCH(&cap_ptr->node.cap,cap) && cap_ptr->node.active) { -+ unsigned int attached_index = cap->cap_mycontext - cap->cap_lowcontext; -+ -+ if ( cap_ptr->attached[rail][attached_index].cb_func != NULL ) /* only one per ctx per rail */ -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ /* keep track of who attached as we might need to tell them when */ -+ /* cap or maps get destroyed */ -+ cap_ptr->attached[rail][ attached_index ].cb_func = func; -+ cap_ptr->attached[rail][ attached_index ].cb_args = args; -+ cap_ptr->node.attached++; -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_attach_cap: passed\n"); -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ } -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_attach_cap: failed to find \n"); -+ -+ /* didnt find one */ -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+} -+ -+int -+elan_detach_cap(ELAN_CAPABILITY *cap, unsigned int rail) -+{ -+ struct list_head *el, *nel; -+ char space[256]; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG1(ELAN_DBG_CAP,"elan_detach_cap %s\n",elan_capability_string(cap,space)); -+ list_for_each_safe (el, nel, &elan_cap_list) { -+ ELAN_CAP_NODE_STRUCT *ptr = list_entry (el, ELAN_CAP_NODE_STRUCT, list); -+ -+ /* is it an exact match */ -+ if (ELAN_CAP_TYPE_MATCH(&ptr->node.cap,cap) && -+ ELAN_CAP_GEOM_MATCH(&ptr->node.cap,cap) && -+ (ptr->node.cap.cap_railmask & cap->cap_railmask) == cap->cap_railmask) { -+ -+ unsigned int attached_index = cap->cap_mycontext - cap->cap_lowcontext; -+ -+ if ( ptr->attached[rail][ attached_index ].cb_func == NULL ) -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elanmod_detach_cap already removed \n"); -+ -+ ptr->attached[rail][ attached_index ].cb_func = NULL; -+ ptr->attached[rail][ attached_index ].cb_args = (void *)0; -+ -+ ptr->node.attached--; -+ -+ ELAN_DEBUG1(ELAN_DBG_CAP,"elanmod_detach_cap new attach count%d \n", ptr->node.attached); -+ -+ elan_destroy_cap_test(ptr); -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_detach_cap: success\n"); -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+ } -+ } -+ -+ ELAN_DEBUG0(ELAN_DBG_CAP,"elan_detach_cap: failed to find\n"); -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+} -+ -+int -+elan_cap_dump() -+{ -+ struct list_head * tmp; -+ ELAN_CAP_NODE_STRUCT * ptr = NULL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ list_for_each(tmp, &elan_cap_list) { -+ ptr = list_entry(tmp, ELAN_CAP_NODE_STRUCT , list); -+ -+ ELAN_DEBUG2 (ELAN_DBG_ALL, "cap dump: owner %p type %x\n", ptr->node.owner, ptr->node.cap.cap_type); -+ -+ ELAN_DEBUG5 (ELAN_DBG_ALL, "cap dump: LowNode %d HighNode %d LowContext %d mycontext %d highContext %d\n", -+ ptr->node.cap.cap_lownode , ptr->node.cap.cap_highnode, -+ ptr->node.cap.cap_lowcontext , ptr->node.cap.cap_mycontext, ptr->node.cap.cap_highcontext); -+ -+ } -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/capability_general.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/capability_general.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/capability_general.c 2005-06-01 23:12:54.558445336 -0400 -@@ -0,0 +1,446 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: capability_general.c,v 1.10 2004/02/25 13:47:59 daniel Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/shared/capability_general.c,v $ */ -+ -+#if defined(__KERNEL__) -+ -+#include -+ -+#else -+ -+#include -+#include -+#include -+ -+#endif -+ -+#include -+ -+ -+void -+elan_nullcap (ELAN_CAPABILITY *cap) -+{ -+ register int i; -+ -+ for (i = 0; i < sizeof (cap->cap_userkey)/sizeof(cap->cap_userkey.key_values[0]); i++) -+ cap->cap_userkey.key_values[i] = ELAN_CAP_UNINITIALISED; -+ -+ cap->cap_lowcontext = ELAN_CAP_UNINITIALISED; -+ cap->cap_highcontext = ELAN_CAP_UNINITIALISED; -+ cap->cap_mycontext = ELAN_CAP_UNINITIALISED; -+ cap->cap_lownode = ELAN_CAP_UNINITIALISED; -+ cap->cap_highnode = ELAN_CAP_UNINITIALISED; -+ cap->cap_railmask = ELAN_CAP_UNINITIALISED; -+ cap->cap_type = ELAN_CAP_UNINITIALISED; -+ cap->cap_spare = 0; -+ cap->cap_version = ELAN_CAP_VERSION_NUMBER; -+ -+ for (i = 0; i < sizeof (cap->cap_bitmap)/sizeof (cap->cap_bitmap[0]); i++) -+ cap->cap_bitmap[i] = 0; -+} -+ -+char * -+elan_capability_string (ELAN_CAPABILITY *cap, char *str) -+{ -+ if (cap == NULL) -+ sprintf (str, "[-.-.-.-] cap = NULL\n"); -+ else -+ sprintf (str, "[%x.%x.%x.%x] Version %x Type %x \n" -+ "Context %x.%x.%x Node %x.%x\n", -+ cap->cap_userkey.key_values[0], cap->cap_userkey.key_values[1], -+ cap->cap_userkey.key_values[2], cap->cap_userkey.key_values[3], -+ cap->cap_version, cap->cap_type, -+ cap->cap_lowcontext, cap->cap_mycontext, cap->cap_highcontext, -+ cap->cap_lownode, cap->cap_highnode); -+ -+ return (str); -+} -+ -+ELAN_LOCATION -+elan_vp2location (u_int process, ELAN_CAPABILITY *cap) -+{ -+ ELAN_LOCATION location; -+ int i, vp, node, context, nnodes, nctxs; -+ -+ vp = 0; -+ -+ location.loc_node = ELAN_INVALID_NODE; -+ location.loc_context = -1; -+ -+ nnodes = cap->cap_highnode - cap->cap_lownode + 1; -+ nctxs = cap->cap_highcontext - cap->cap_lowcontext + 1; -+ -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ for (node = 0, i = 0; node < nnodes; node++) -+ { -+ for (context = 0; context < nctxs; context++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, context + (node * nctxs))) -+ { -+ if (vp == process) -+ { -+ /* Return relative indices within the capability box */ -+ location.loc_node = node; -+ location.loc_context = context; -+ -+ return (location); -+ } -+ -+ vp++; -+ } -+ } -+ } -+ break; -+ -+ case ELAN_CAP_TYPE_CYCLIC: -+ for (context = 0, i = 0; context < nctxs; context++) -+ { -+ for (node = 0; node < nnodes; node++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, node + (context * nnodes))) -+ { -+ if (vp == process) -+ { -+ location.loc_node = node; -+ location.loc_context = context; -+ -+ return (location); -+ } -+ -+ vp++; -+ } -+ } -+ } -+ break; -+ } -+ -+ return( location ); -+} -+ -+int -+elan_location2vp (ELAN_LOCATION location, ELAN_CAPABILITY *cap) -+{ -+ int vp, node, context, nnodes, nctxs; -+ -+ nnodes = cap->cap_highnode - cap->cap_lownode + 1; -+ nctxs = cap->cap_highcontext - cap->cap_lowcontext + 1; -+ -+ vp = 0; -+ -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ for (node = 0 ; node < nnodes ; node++) -+ { -+ for (context = 0; context < nctxs; context++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, context + (node * nctxs))) -+ { -+ if ((location.loc_node == node) && (location.loc_context == context)) -+ { -+ /* Found it ! */ -+ return( vp ); -+ } -+ -+ vp++; -+ } -+ } -+ } -+ break; -+ -+ case ELAN_CAP_TYPE_CYCLIC: -+ for (context = 0; context < nctxs; context++) -+ { -+ for (node = 0; node < nnodes; node++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, node + (context * nnodes))) -+ { -+ if ((location.loc_node == node) && (location.loc_context == context)) -+ { -+ /* Found it ! */ -+ return( vp ); -+ } -+ -+ vp++; -+ } -+ } -+ } -+ break; -+ } -+ -+ /* Failed to find it */ -+ return( -1 ); -+} -+ -+/* Return the number of processes as described by a capability */ -+int -+elan_nvps (ELAN_CAPABILITY *cap) -+{ -+ int i, c, nbits = ELAN_CAP_BITMAPSIZE(cap); -+ -+ if (cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) -+ return (nbits); -+ -+ for (i = 0, c = 0; i < nbits; i++) -+ if (BT_TEST (cap->cap_bitmap, i)) -+ c++; -+ -+ return (c); -+} -+ -+/* Return the number of local processes on a given node as described by a capability */ -+int -+elan_nlocal (int node, ELAN_CAPABILITY *cap) -+{ -+ int vp; -+ ELAN_LOCATION loc; -+ int nLocal = 0; -+ -+ for (vp = 0; vp < elan_nvps(cap); vp++) -+ { -+ loc = elan_vp2location(vp, cap); -+ if (loc.loc_node == node) -+ nLocal++; -+ } -+ -+ return (nLocal); -+} -+ -+/* Return the maximum number of local processes on any node as described by a capability */ -+int -+elan_maxlocal (ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_highcontext - cap->cap_lowcontext + 1); -+} -+ -+/* Return the vps of the local processes on a given node as described by a capability */ -+int -+elan_localvps (int node, ELAN_CAPABILITY *cap, int *vps, int size) -+{ -+ int context; -+ ELAN_LOCATION loc; -+ int nLocal = 0; -+ -+ loc.loc_node = node; -+ -+ for (context = 0; context < MIN(size, elan_maxlocal(cap)); context++) -+ { -+ loc.loc_context = context; -+ -+ /* Should return -1 if none found */ -+ if ( (vps[context] = elan_location2vp( loc, cap )) != -1) -+ nLocal++; -+ } -+ -+ return (nLocal); -+} -+ -+/* Return the number of rails that this capability utilises */ -+int -+elan_nrails (ELAN_CAPABILITY *cap) -+{ -+ int nrails = 0; -+ unsigned int railmask; -+ -+ /* Test for a multi-rail capability */ -+ if (cap->cap_type & ELAN_CAP_TYPE_MULTI_RAIL) -+ { -+ /* Grab rail bitmask from capability */ -+ railmask = cap->cap_railmask; -+ -+ while (railmask) -+ { -+ if (railmask & 1) -+ nrails++; -+ -+ railmask >>= 1; -+ } -+ } -+ else -+ /* Default to just one rail */ -+ nrails = 1; -+ -+ return (nrails); -+} -+ -+/* Fill out an array giving the physical rail numbers utilised by a capability */ -+int -+elan_rails (ELAN_CAPABILITY *cap, int *rails) -+{ -+ int nrails, rail; -+ unsigned int railmask; -+ -+ /* Test for a multi-rail capability */ -+ if (cap->cap_type & ELAN_CAP_TYPE_MULTI_RAIL) -+ { -+ /* Grab rail bitmask from capability */ -+ railmask = cap->cap_railmask; -+ -+ nrails = rail = 0; -+ while (railmask) -+ { -+ if (railmask & 1) -+ rails[nrails++] = rail; -+ -+ rail++; -+ railmask >>= 1; -+ } -+ } -+ else -+ { -+ /* Default to just one rail */ -+ rails[0] = 0; -+ nrails = 1; -+ } -+ -+ return( nrails ); -+} -+ -+int -+elan_cap_overlap(ELAN_CAPABILITY *cap1, ELAN_CAPABILITY *cap2) -+{ -+ /* by context */ -+ if ( cap1->cap_highcontext < cap2->cap_lowcontext ) return (0); -+ if ( cap1->cap_lowcontext > cap2->cap_highcontext) return (0); -+ -+ /* by node */ -+ if ( cap1->cap_highnode < cap2->cap_lownode ) return (0); -+ if ( cap1->cap_lownode > cap2->cap_highnode) return (0); -+ -+ /* by rail */ -+ /* they overlap if they have a rail in common */ -+ return (cap1->cap_railmask & cap2->cap_railmask); -+} -+ -+#if !defined(__KERNEL__) -+ -+/* Fill out an array that hints at the best use of the rails on a -+ * per process basis. The library user can then decide whether or not -+ * to take this into account (e.g. TPORTs) -+ * All processes calling this fn will be returned the same information. -+ */ -+int -+elan_prefrails(ELAN_CAPABILITY *cap, int *pref, int nvp) -+{ -+ int i; -+ int nrails = elan_nrails(cap); -+ int maxlocal = elan_maxlocal(cap); -+ -+ /* Test for a multi-rail capability */ -+ if (! (cap->cap_type & ELAN_CAP_TYPE_MULTI_RAIL)) -+ { -+ /* Default to just one rail */ -+ for (i = 0; i < nvp; i++) -+ pref[i] = 0; -+ -+ return( 0 ); -+ } -+ -+ /* -+ * We allocate rails on a per node basis sharing our the rails -+ * equally amongst the local processes. However, if there is only -+ * one process per node and multiple rails, then we use a different -+ * algorithm where rails are allocated across all the processes in -+ * a round-robin fashion -+ */ -+ -+ if (maxlocal == 1) -+ { -+ /* Allocate rails in a round-robin manner */ -+ for (i = 0; i < nvp; i++) -+ *pref++ = i % nrails; -+ } -+ else -+ { -+ int node; -+ int *vps; -+ int nnodes = cap->cap_highnode - cap->cap_lownode + 1; -+ -+ vps = (int *) malloc(sizeof(int)*maxlocal); -+ -+ /* Grab the local process info for each node and allocate -+ * rails to those vps on an equal basis -+ */ -+ for (node = 0; node < nnodes; node++) -+ { -+ int nlocal; -+ int pprail; -+ -+ /* Grab an array of local vps */ -+ nlocal = elan_localvps(node, cap, vps, maxlocal); -+ -+ /* Calculate the number processes per rail */ -+ if ((pprail = nlocal/nrails) == 0) -+ pprail = 1; -+ -+ /* Allocate processes to rails */ -+ for (i = 0; i < nlocal; i++) -+ { -+ pref[vps[i]] = (i / pprail) % nrails; -+ } -+ } -+ -+ free(vps); -+ } -+ -+ return( 0 ); -+} -+ -+void -+elan_get_random_key(ELAN_USERKEY *key) -+{ -+ int i; -+ for (i = 0; i < sizeof(key->key_values) / sizeof(key->key_values[0]); i++) -+ key->key_values[i] = lrand48(); -+} -+ -+int elan_lowcontext(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_lowcontext); -+} -+ -+int elan_mycontext(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_mycontext); -+} -+ -+int elan_highcontext(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_highcontext); -+} -+ -+int elan_lownode(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_lownode); -+} -+ -+int elan_highnode(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_highnode); -+} -+ -+int elan_captype(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_type); -+} -+ -+int elan_railmask(ELAN_CAPABILITY *cap) -+{ -+ return(cap->cap_railmask); -+} -+ -+#endif -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/device.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/device.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/device.c 2005-06-01 23:12:54.559445184 -0400 -@@ -0,0 +1,147 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: device.c,v 1.5 2003/09/24 13:55:37 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/device.c,v $*/ -+ -+#include -+#include -+ -+static LIST_HEAD(elan_dev_list); -+ -+ELAN_DEV_STRUCT * -+elan_dev_find (ELAN_DEV_IDX devidx) -+{ -+ struct list_head *tmp; -+ ELAN_DEV_STRUCT *ptr=NULL; -+ -+ list_for_each(tmp, &elan_dev_list) { -+ ptr = list_entry(tmp, ELAN_DEV_STRUCT , node); -+ if (ptr->devidx == devidx) -+ return ptr; -+ if (ptr->devidx > devidx) -+ return ERR_PTR(-ENXIO); -+ } -+ -+ return ERR_PTR(-EINVAL); -+} -+ -+ELAN_DEV_STRUCT * -+elan_dev_find_byrail (unsigned short deviceid, unsigned rail) -+{ -+ struct list_head *tmp; -+ ELAN_DEV_STRUCT *ptr=NULL; -+ -+ list_for_each(tmp, &elan_dev_list) { -+ ptr = list_entry(tmp, ELAN_DEV_STRUCT , node); -+ -+ ELAN_DEBUG5 (ELAN_DBG_ALL,"elan_dev_find_byrail devidx %d - %04x %04x, %d %d \n", ptr->devidx, -+ ptr->devinfo->dev_device_id, deviceid, ptr->devinfo->dev_rail, rail); -+ -+ if (ptr->devinfo->dev_device_id == deviceid && ptr->devinfo->dev_rail == rail) -+ return ptr; -+ } -+ -+ return NULL; -+} -+ -+ELAN_DEV_IDX -+elan_dev_register (ELAN_DEVINFO *devinfo, ELAN_DEV_OPS *ops, void * user_data) -+{ -+ ELAN_DEV_STRUCT *ptr; -+ ELAN_DEV_IDX devidx = 0; -+ struct list_head *tmp; -+ -+ kmutex_lock(&elan_mutex); -+ -+ /* is it already registered */ -+ if ((ptr = elan_dev_find_byrail(devinfo->dev_device_id, devinfo->dev_rail)) != NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ /* find a free device idx */ -+ list_for_each (tmp, &elan_dev_list) { -+ if (list_entry (tmp, ELAN_DEV_STRUCT, node)->devidx != devidx) -+ break; -+ devidx++; -+ } -+ -+ /* create it and add */ -+ KMEM_ALLOC(ptr, ELAN_DEV_STRUCT *, sizeof(ELAN_DEV_STRUCT), 1); -+ if (ptr == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return ENOMEM; -+ } -+ -+ ptr->devidx = devidx; -+ ptr->ops = ops; -+ ptr->devinfo = devinfo; -+ ptr->user_data = user_data; -+ -+ /* insert this entry *before* the last entry we've found */ -+ list_add_tail(&ptr->node, tmp); -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+int -+elan_dev_deregister (ELAN_DEVINFO *devinfo) -+{ -+ ELAN_DEV_STRUCT *target; -+ -+ kmutex_lock(&elan_mutex); -+ -+ if ((target = elan_dev_find_byrail (devinfo->dev_device_id, devinfo->dev_rail)) == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return EINVAL; -+ } -+ -+ list_del(&target->node); -+ -+ /* delete target entry */ -+ KMEM_FREE(target, sizeof(ELAN_DEV_STRUCT)); -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+int -+elan_dev_dump () -+{ -+ struct list_head *tmp; -+ ELAN_DEV_STRUCT *ptr=NULL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ list_for_each(tmp, &elan_dev_list) { -+ ptr = list_entry(tmp, ELAN_DEV_STRUCT , node); -+ -+ ELAN_DEBUG3 (ELAN_DBG_ALL,"dev dump: index %u rail %u elan%c\n", -+ ptr->devidx, ptr->devinfo->dev_rail, '3' + ptr->devinfo->dev_device_id); -+ ELAN_DEBUG5 (ELAN_DBG_ALL,"dev dump: Vid %x Did %x Rid %x DR %d DVal %x\n", -+ ptr->devinfo->dev_vendor_id, -+ ptr->devinfo->dev_device_id, -+ ptr->devinfo->dev_revision_id, -+ ptr->devinfo->dev_driver_version, -+ ptr->devinfo->dev_num_down_links_value); -+ -+ } -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/devinfo.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/devinfo.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/devinfo.c 2005-06-01 23:12:54.559445184 -0400 -@@ -0,0 +1,78 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: devinfo.c,v 1.5 2003/09/24 13:55:37 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/devinfo.c,v $*/ -+ -+#include -+#include -+ -+int -+elan_get_devinfo(ELAN_DEV_IDX devidx, ELAN_DEVINFO *devinfo) -+{ -+ ELAN_DEV_STRUCT *target; -+ int res; -+ -+ kmutex_lock(&elan_mutex); -+ -+ target = elan_dev_find (devidx); -+ -+ if (IS_ERR (target)) -+ res = PTR_ERR(target); -+ else -+ { -+ copyout(target->devinfo, devinfo, sizeof(ELAN_DEVINFO)); -+ res = ESUCCESS; -+ } -+ -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+int -+elan_get_position(ELAN_DEV_IDX devidx, ELAN_POSITION *position) -+{ -+ ELAN_DEV_STRUCT *target; -+ int res; -+ -+ kmutex_lock(&elan_mutex); -+ -+ target = elan_dev_find(devidx); -+ -+ if (IS_ERR (target)) -+ res = PTR_ERR(target); -+ else -+ res = target->ops->get_position(target->user_data, position); -+ -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+int -+elan_set_position(ELAN_DEV_IDX devidx, unsigned short nodeId, unsigned short numNodes) -+{ -+ ELAN_DEV_STRUCT *target; -+ int res; -+ -+ kmutex_lock(&elan_mutex); -+ -+ target = elan_dev_find(devidx); -+ -+ if (IS_ERR (target)) -+ res = PTR_ERR (target); -+ else -+ res = target->ops->set_position(target->user_data, nodeId, numNodes); -+ -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/elanmod.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/elanmod.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/elanmod.c 2005-06-01 23:12:54.559445184 -0400 -@@ -0,0 +1,149 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+#ident "@(#)$Id: elanmod.c,v 1.11 2004/06/18 09:28:16 mike Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/elanmod.c,v $*/ -+ -+#include -+#include -+ -+kmutex_t elan_mutex; -+ -+int -+elan_init() -+{ -+ kmutex_init(&elan_mutex); -+ return (ESUCCESS); -+} -+ -+int -+elan_fini() -+{ -+ kmutex_destroy(&elan_mutex); -+ return (ESUCCESS); -+} -+ -+int -+elanmod_classify_cap (ELAN_POSITION *position, ELAN_CAPABILITY *cap, unsigned use) -+{ -+ if (cap->cap_version != ELAN_CAP_VERSION_NUMBER) -+ { -+ ELAN_DEBUG2 (ELAN_DBG_VP, "elanmod_classify_cap: (cap->Version != ELAN_CAP_VERSION) %d %d\n", cap->cap_version, ELAN_CAP_VERSION_NUMBER); -+ return (-EINVAL); -+ } -+ -+ if (cap->cap_lowcontext == ELAN_CAP_UNINITIALISED || cap->cap_highcontext == ELAN_CAP_UNINITIALISED) -+ { -+ ELAN_DEBUG3 (ELAN_DBG_VP, "elanmod_classify_cap: LowContext %d HighContext %d MyContext %d\n", -+ cap->cap_lowcontext , cap->cap_highcontext, cap->cap_mycontext); -+ return (-EINVAL); -+ } -+ -+ if (cap->cap_lowcontext > cap->cap_highcontext) -+ { -+ ELAN_DEBUG2 (ELAN_DBG_VP, "elanmod_classify_cap: (cap->cap_lowcontext > cap->cap_highcontext) %d %d\n",cap->cap_lowcontext , cap->cap_highcontext); -+ return (-EINVAL); -+ } -+ -+ -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ case ELAN_CAP_TYPE_CYCLIC: -+ if (position->pos_mode == ELAN_POS_UNKNOWN) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP, "elanmod_classify_cap: Position Unknown \n"); -+ return (-EAGAIN); -+ } -+ -+ if ( ! ( ELAN_USER_CONTEXT(cap->cap_lowcontext) && ELAN_USER_CONTEXT(cap->cap_highcontext))) -+ { -+ ELAN_DEBUG4 (ELAN_DBG_VP, "elanmod_classify_cap: USER_BASE_CONTEXT %d %d %d %d \n" , ELAN_USER_BASE_CONTEXT_NUM,cap->cap_lowcontext, cap->cap_highcontext ,ELAN_USER_TOP_CONTEXT_NUM); -+ return (-EINVAL); -+ } -+ if (cap->cap_lownode == ELAN_CAP_UNINITIALISED) -+ cap->cap_lownode = position->pos_nodeid; -+ if (cap->cap_highnode == ELAN_CAP_UNINITIALISED) -+ cap->cap_highnode = position->pos_nodeid; -+ -+ if (cap->cap_lownode < 0 || cap->cap_highnode >= position->pos_nodes || cap->cap_lownode > cap->cap_highnode) -+ { -+ ELAN_DEBUG3 ( ELAN_DBG_VP,"elanmod_classify_cap: low %d high %d pos %d \n" , cap->cap_lownode ,cap->cap_highnode, position->pos_nodes); -+ -+ return (-EINVAL); -+ } -+ -+ if ((cap->cap_highnode < position->pos_nodeid) || (cap->cap_lownode > position->pos_nodeid)) -+ { -+ ELAN_DEBUG3 (ELAN_DBG_VP, "elanmod_classify_cap: node not i range low %d high %d this %d\n", -+ cap->cap_lownode, cap->cap_highnode, position->pos_nodeid); -+ return (-EINVAL); -+ } -+ -+ break; -+ default: -+ ELAN_DEBUG1 (ELAN_DBG_VP, "elanmod_classify_cap: cant decode type %x \n", cap->cap_type & ELAN_CAP_TYPE_MASK); -+ return (-EINVAL); -+ -+ } -+ -+ switch (use) -+ { -+ case ELAN_USER_ATTACH: -+ case ELAN_USER_DETACH: -+ if (cap->cap_mycontext == ELAN_CAP_UNINITIALISED) -+ { -+ ELAN_DEBUG0 (ELAN_DBG_VP, "elanmod_classify_cap: cap->cap_mycontext == ELAN_CAP_UNINITIALISED"); -+ return (-EINVAL); -+ } -+ -+ if ((cap->cap_mycontext != ELAN_CAP_UNINITIALISED) && -+ (cap->cap_mycontext < cap->cap_lowcontext || cap->cap_mycontext > cap->cap_highcontext)) -+ { -+ ELAN_DEBUG3 (ELAN_DBG_VP, "elanmod_classify_cap: cap->cap_mycontext out of range %d %d %d \n", cap->cap_lowcontext,cap->cap_mycontext,cap->cap_highcontext); -+ return (-EINVAL); -+ } -+ break; -+ -+ case ELAN_USER_P2P: -+ break; -+ -+ case ELAN_USER_BROADCAST: -+ if (! (cap->cap_type & ELAN_CAP_TYPE_BROADCASTABLE)) { -+ ELAN_DEBUG0 (ELAN_DBG_VP, "elanmod_classify_cap: use ELAN_USER_BROADCAST but cap not ELAN_CAP_TYPE_BROADCASTABLE\n"); -+ return (-EINVAL); -+ } -+ break; -+ -+ default: -+ ELAN_DEBUG1 (ELAN_DBG_VP, "elanmod_classify_cap: unknown use (%d)\n",use); -+ return (-EINVAL); -+ } -+ -+ -+ -+ /* is any ctxt an rms one ?? */ -+ if (ELAN_RMS_CONTEXT(cap->cap_lowcontext) || ELAN_RMS_CONTEXT(cap->cap_highcontext)) -+ { -+ /* so both low and high must be */ -+ if (!(ELAN_RMS_CONTEXT(cap->cap_lowcontext) && ELAN_RMS_CONTEXT(cap->cap_highcontext))) -+ { -+ ELAN_DEBUG2 (ELAN_DBG_VP, "elanmod_classify_cap: not rms ctxt %x %x\n",cap->cap_lowcontext,cap->cap_highcontext ); -+ return (-EINVAL); -+ } -+ ELAN_DEBUG0 (ELAN_DBG_VP, "elanmod_classify_cap: returning ELAN_CAP_RMS\n"); -+ return (ELAN_CAP_RMS); -+ } -+ -+ ELAN_DEBUG0 (ELAN_DBG_VP, "elanmod_classify_cap: returning ELAN_CAP_OK\n"); -+ return (ELAN_CAP_OK); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/elanmod_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/elanmod_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/elanmod_linux.c 2005-06-01 23:12:54.560445032 -0400 -@@ -0,0 +1,410 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elanmod_linux.c,v 1.16 2004/06/14 15:45:37 mike Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/elanmod_linux.c,v $*/ -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+MODULE_AUTHOR("Quadrics Ltd."); -+MODULE_DESCRIPTION("Elan support module"); -+ -+MODULE_LICENSE("GPL"); -+ -+/* elanmod.c */ -+EXPORT_SYMBOL(elanmod_classify_cap); -+ -+/* bitmap.c */ -+#include -+ -+EXPORT_SYMBOL(bt_freebit); -+EXPORT_SYMBOL(bt_lowbit); -+EXPORT_SYMBOL(bt_nextbit); -+EXPORT_SYMBOL(bt_copy); -+EXPORT_SYMBOL(bt_zero); -+EXPORT_SYMBOL(bt_fill); -+EXPORT_SYMBOL(bt_cmp); -+EXPORT_SYMBOL(bt_intersect); -+EXPORT_SYMBOL(bt_remove); -+EXPORT_SYMBOL(bt_add); -+EXPORT_SYMBOL(bt_spans); -+EXPORT_SYMBOL(bt_subset); -+EXPORT_SYMBOL(bt_up); -+EXPORT_SYMBOL(bt_down); -+EXPORT_SYMBOL(bt_nbits); -+ -+/* capability.c */ -+EXPORT_SYMBOL(elan_nullcap); -+EXPORT_SYMBOL(elan_detach_cap); -+EXPORT_SYMBOL(elan_attach_cap); -+EXPORT_SYMBOL(elan_validate_map); -+ -+/* stats.c */ -+EXPORT_SYMBOL(elan_stats_register); -+EXPORT_SYMBOL(elan_stats_deregister); -+ -+/* device.c */ -+EXPORT_SYMBOL(elan_dev_deregister); -+EXPORT_SYMBOL(elan_dev_register); -+ -+/* debug */ -+int elan_debug_mode = QSNET_DEBUG_BUFFER; -+int elan_debug_mask; -+ -+static struct proc_dir_entry *elan_procfs_root; -+ -+extern void elan_procfs_init(void); -+extern void elan_procfs_fini(void); -+ -+static int elan_open (struct inode *ino, struct file *fp); -+static int elan_release (struct inode *ino, struct file *fp); -+static int elan_ioctl (struct inode *ino, struct file *fp, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations elan_fops = -+{ -+ ioctl: elan_ioctl, -+ open: elan_open, -+ release: elan_release, -+}; -+ -+static int __init elan_start(void) -+{ -+ int res; -+ -+ elan_procfs_init(); -+ -+ if ((res = elan_init()) != ESUCCESS) -+ { -+ elan_procfs_fini(); -+ return (-res); -+ } -+ -+ return (0); -+} -+ -+static void __exit elan_exit(void) -+{ -+ elan_fini(); -+ elan_procfs_fini(); -+} -+ -+ -+/* Declare the module init and exit functions */ -+void -+elan_procfs_init() -+{ -+ struct proc_dir_entry *p; -+ -+ elan_procfs_root = proc_mkdir("elan", qsnet_procfs_root); -+ -+ qsnet_proc_register_hex(elan_procfs_root, "debug_mask", &elan_debug_mask, 0); -+ qsnet_proc_register_hex(elan_procfs_root, "debug_mode", &elan_debug_mode, 0); -+ -+ if ((p = create_proc_entry ("ioctl", 0, elan_procfs_root)) != NULL) -+ { -+ p->proc_fops = &elan_fops; -+ p->data = 0; -+ p->owner = THIS_MODULE; -+ } -+} -+ -+void -+elan_procfs_fini() -+{ -+ remove_proc_entry ("debug_mask", elan_procfs_root); -+ remove_proc_entry ("debug_mode", elan_procfs_root); -+ -+ remove_proc_entry ("ioctl", elan_procfs_root); -+ remove_proc_entry ("version", elan_procfs_root); -+ -+ remove_proc_entry ("elan", qsnet_procfs_root); -+} -+ -+module_init(elan_start); -+module_exit(elan_exit); -+ -+static int -+elan_open (struct inode *inode, struct file *fp) -+{ -+ MOD_INC_USE_COUNT; -+ fp->private_data = NULL; -+ return (0); -+} -+ -+static int -+elan_release (struct inode *inode, struct file *fp) -+{ -+ /* mark all caps owned by fp to be destroyed */ -+ elan_destroy_cap(fp,NULL); -+ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static int -+elan_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, unsigned long arg) -+{ -+ int rep = 0; -+ -+ switch (cmd) -+ { -+ case ELANCTRL_STATS_GET_NEXT : -+ { -+ ELANCTRL_STATS_GET_NEXT_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_STATS_GET_NEXT_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_stats_get_next_index(args.statidx, args.next_statidx) != 0 ) -+ return (-EINVAL); -+ -+ break; -+ } -+ case ELANCTRL_STATS_FIND_INDEX : -+ { -+ ELANCTRL_STATS_FIND_INDEX_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_STATS_FIND_INDEX_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_stats_find_index(args.block_name, args.statidx, args.num_entries) != 0 ) -+ return (-EINVAL); -+ -+ break; -+ } -+ case ELANCTRL_STATS_GET_BLOCK_INFO : -+ { -+ ELANCTRL_STATS_GET_BLOCK_INFO_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_STATS_GET_BLOCK_INFO_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_stats_get_block_info(args.statidx, args.block_name, args.num_entries) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_STATS_GET_INDEX_NAME : -+ { -+ ELANCTRL_STATS_GET_INDEX_NAME_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_STATS_GET_INDEX_NAME_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_stats_get_index_name(args.statidx, args.index, args.name) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_STATS_CLEAR_BLOCK : -+ { -+ ELANCTRL_STATS_CLEAR_BLOCK_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_STATS_CLEAR_BLOCK_STRUCT))) -+ return (-EFAULT); -+ -+ /* statidx is not a pointer */ -+ if (elan_stats_clear_block(args.statidx) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_STATS_GET_BLOCK : -+ { -+ ELANCTRL_STATS_GET_BLOCK_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_STATS_GET_BLOCK_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_stats_get_block(args.statidx, args.entries, args.values) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_GET_DEVINFO : -+ { -+ ELANCTRL_GET_DEVINFO_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_GET_DEVINFO_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_get_devinfo(args.devidx, args.devinfo) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_GET_POSITION : -+ { -+ ELANCTRL_GET_POSITION_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_GET_POSITION_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_get_position(args.devidx, args.position) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_SET_POSITION : -+ { -+ ELANCTRL_SET_POSITION_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_SET_POSITION_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_set_position(args.devidx, args.nodeId, args.numNodes) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_CREATE_CAP : -+ { -+ ELANCTRL_CREATE_CAP_STRUCT *args; -+ -+ /* get space for args */ -+ KMEM_ALLOC(args, ELANCTRL_CREATE_CAP_STRUCT *, sizeof(ELANCTRL_CREATE_CAP_STRUCT), 1); -+ if (args == NULL) -+ return(-ENOMEM); -+ -+ /* copy them */ -+ if (copy_from_user (args, (void *) arg, sizeof (ELANCTRL_CREATE_CAP_STRUCT))) -+ return (-EFAULT); -+ else -+ { -+ if ((elan_validate_cap(&args->cap) != 0) || (elan_create_cap(fp,&args->cap) != 0 )) -+ rep = (-EINVAL); -+ } -+ -+ /* free the space */ -+ KMEM_FREE(args, sizeof(ELANCTRL_CREATE_CAP_STRUCT)); -+ -+ break; -+ } -+ case ELANCTRL_DESTROY_CAP : -+ { -+ ELANCTRL_DESTROY_CAP_STRUCT *args; -+ -+ /* get space for args */ -+ KMEM_ALLOC(args, ELANCTRL_DESTROY_CAP_STRUCT *, sizeof(ELANCTRL_DESTROY_CAP_STRUCT), 1); -+ if (args == NULL) -+ return(-ENOMEM); -+ -+ /* copy them */ -+ if (copy_from_user (args, (void *) arg, sizeof (ELANCTRL_DESTROY_CAP_STRUCT))) -+ rep = (-EFAULT); -+ else -+ { -+ if (elan_destroy_cap(fp, &args->cap) != 0 ) -+ rep = (-EINVAL); -+ } -+ -+ /* free the space */ -+ KMEM_FREE(args, sizeof(ELANCTRL_DESTROY_CAP_STRUCT)); -+ -+ break; -+ } -+ case ELANCTRL_CREATE_VP : -+ { -+ ELANCTRL_CREATE_VP_STRUCT *args; -+ -+ /* get space for args */ -+ KMEM_ALLOC(args, ELANCTRL_CREATE_VP_STRUCT *, sizeof(ELANCTRL_CREATE_VP_STRUCT), 1); -+ if (args == NULL) -+ return(-ENOMEM); -+ -+ /* copy them */ -+ if (copy_from_user (args, (void *) arg, sizeof (ELANCTRL_CREATE_VP_STRUCT))) -+ return (-EFAULT); -+ else -+ { -+ if ((elan_validate_cap( &args->map) != 0) || (elan_create_vp(fp, &args->cap, &args->map) != 0 )) -+ rep = (-EINVAL); -+ } -+ -+ KMEM_FREE(args, sizeof(ELANCTRL_CREATE_VP_STRUCT )); -+ -+ break; -+ } -+ case ELANCTRL_DESTROY_VP : -+ { -+ ELANCTRL_DESTROY_VP_STRUCT *args; -+ -+ /* get space for args */ -+ KMEM_ALLOC(args, ELANCTRL_DESTROY_VP_STRUCT *, sizeof(ELANCTRL_DESTROY_VP_STRUCT), 1); -+ if (args == NULL) -+ return(-ENOMEM); -+ -+ /* copy them */ -+ if (copy_from_user (args, (void *) arg, sizeof (ELANCTRL_DESTROY_VP_STRUCT))) -+ rep = (-EFAULT); -+ else -+ { -+ if (elan_destroy_vp(fp, &args->cap, &args->map) != 0 ) -+ rep = (-EINVAL); -+ } -+ -+ KMEM_FREE(args, sizeof(ELANCTRL_DESTROY_VP_STRUCT )); -+ -+ break; -+ } -+ -+ case ELANCTRL_GET_CAPS : -+ { -+ ELANCTRL_GET_CAPS_STRUCT args; -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_GET_CAPS_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if (elan_get_caps(args.number_of_results, args.array_size, args.caps) != 0 ) -+ return (-EINVAL); -+ break; -+ } -+ case ELANCTRL_DEBUG_DUMP : -+ { -+ elan_cap_dump(); -+ elan_dev_dump(); -+ -+ break; -+ } -+ case ELANCTRL_DEBUG_BUFFER : -+ { -+ ELANCTRL_DEBUG_BUFFER_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELANCTRL_DEBUG_BUFFER_STRUCT))) -+ return (-EFAULT); -+ -+ /* uses copyin/copyout */ -+ if ((args.size = qsnet_debug_buffer (args.buffer, args.size)) != -1 && -+ copy_to_user ((void *) arg, &args, sizeof (ELANCTRL_DEBUG_BUFFER_STRUCT))) -+ return (-EFAULT); -+ break; -+ } -+ default: -+ return (-EINVAL); -+ break; -+ } -+ -+ return (rep); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/Makefile 2005-06-01 23:12:54.560445032 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/elan/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/elan/Makefile -+# -+ -+list-multi := elan.o -+elan-objs := elanmod.o device.o stats.o devinfo.o capability.o elanmod_linux.o capability_general.o bitmap.o -+export-objs := elanmod_linux.o -+obj-$(CONFIG_QSNET) := elan.o -+ -+elan.o : $(elan-objs) -+ $(LD) -r -o $@ $(elan-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/elan/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/Makefile.conf 2005-06-01 23:12:54.561444880 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = elan.o -+MODULENAME = elan -+KOBJFILES = elanmod.o device.o stats.o devinfo.o capability.o elanmod_linux.o capability_general.o bitmap.o -+EXPORT_KOBJS = elanmod_linux.o -+CONFIG_NAME = CONFIG_QSNET -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/elan/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/quadrics_version.h 2005-06-01 23:12:54.561444880 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/elan/stats.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan/stats.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan/stats.c 2005-06-01 23:12:54.562444728 -0400 -@@ -0,0 +1,277 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: stats.c,v 1.6 2003/09/24 13:55:37 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/stats.c,v $*/ -+ -+#include -+#include -+ -+static LIST_HEAD(elan_stats_list); -+static ELAN_STATS_IDX elan_next_statidx=0; -+ -+ELAN_STATS_STRUCT * -+elan_stats_find(ELAN_STATS_IDX statidx) -+{ -+ struct list_head *tmp; -+ ELAN_STATS_STRUCT *ptr=NULL; -+ -+ list_for_each(tmp, &elan_stats_list) { -+ ptr = list_entry(tmp, ELAN_STATS_STRUCT , node); -+ if ( ptr->statidx == statidx ) -+ return ptr; -+ } -+ -+ ELAN_DEBUG1 (ELAN_DBG_CTRL, "elan_stats_find failed %d\n", statidx); -+ return NULL; -+} -+ -+ELAN_STATS_STRUCT * -+elan_stats_find_by_name(caddr_t block_name) -+{ -+ struct list_head *tmp; -+ ELAN_STATS_STRUCT *ptr=NULL; -+ -+ list_for_each(tmp, &elan_stats_list) { -+ ptr = list_entry(tmp, ELAN_STATS_STRUCT , node); -+ if (!strcmp(ptr->block_name, block_name)) -+ { -+ ELAN_DEBUG3 (ELAN_DBG_CTRL, "elan_stats_find_by_name found %s (%d,%d)\n", block_name, ptr->statidx, ptr->num_entries); -+ return ptr; -+ } -+ } -+ -+ ELAN_DEBUG1 (ELAN_DBG_CTRL, "elan_stats_find_by_name failed %s\n", block_name); -+ return NULL; -+} -+ -+ELAN_STATS_STRUCT * -+elan_stats_find_next(ELAN_STATS_IDX statidx) -+{ -+ struct list_head *tmp; -+ ELAN_STATS_STRUCT *ptr=NULL; -+ -+ list_for_each(tmp, &elan_stats_list) { -+ ptr = list_entry(tmp, ELAN_STATS_STRUCT , node); -+ -+ if ( ptr->statidx > statidx ) -+ return ptr; -+ } -+ -+ return NULL; -+} -+ -+int -+elan_stats_get_next_index (ELAN_STATS_IDX statidx, ELAN_STATS_IDX *next_block) -+{ -+ ELAN_STATS_STRUCT *target; -+ ELAN_STATS_IDX next = 0; -+ -+ kmutex_lock(&elan_mutex); -+ -+ if ((target = elan_stats_find_next(statidx)) != NULL) -+ next = target->statidx; -+ -+ copyout(&next, next_block, sizeof(ELAN_STATS_IDX) ); -+ -+ kmutex_unlock(&elan_mutex); -+ return 0; -+} -+ -+int -+elan_stats_find_index (caddr_t block_name, ELAN_STATS_IDX *statidx, uint *num_entries) -+ -+{ -+ ELAN_STATS_STRUCT *target; -+ ELAN_STATS_IDX index = 0; -+ uint entries = 0; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG1(ELAN_DBG_CTRL, "elan_stats_find_index %s \n", block_name); -+ -+ if ((target = elan_stats_find_by_name(block_name)) != NULL) -+ { -+ index = target->statidx; -+ entries = target->num_entries; -+ } -+ -+ ELAN_DEBUG3(ELAN_DBG_CTRL, "elan_stats_find_index found %d %d (target=%p)\n", index, entries, target); -+ -+ copyout(&index, statidx, sizeof(ELAN_STATS_IDX)); -+ copyout(&entries, num_entries, sizeof(uint)); -+ -+ kmutex_unlock(&elan_mutex); -+ return ESUCCESS; -+} -+ -+int -+elan_stats_get_block_info (ELAN_STATS_IDX statidx, caddr_t block_name, uint *num_entries) -+{ -+ ELAN_STATS_STRUCT *target; -+ int res=EINVAL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG1(ELAN_DBG_CTRL, "elan_stats_get_block_info statidx %d\n",statidx); -+ -+ if ((target = elan_stats_find(statidx)) != NULL) -+ { -+ ELAN_DEBUG2(ELAN_DBG_CTRL, "elan_stats_get_block_info name %s entries %d\n",block_name, *num_entries); -+ -+ copyout( target->block_name, block_name, ELAN_STATS_NAME_MAX_LEN); -+ copyout(&target->num_entries, num_entries, sizeof(uint)); -+ -+ res = ESUCCESS; -+ } -+ -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+int -+elan_stats_get_index_name (ELAN_STATS_IDX statidx, uint index, caddr_t name) -+{ -+ ELAN_STATS_STRUCT *target; -+ int res=EINVAL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ ELAN_DEBUG2(ELAN_DBG_CTRL, "elan_stats_get_index_name statidx %d index %d\n",statidx, index); -+ -+ if ((target = elan_stats_find(statidx)) != NULL) -+ { -+ if ( target->ops->elan_stats_get_name== NULL) -+ { -+ ELAN_DEBUG0(ELAN_DBG_CTRL, "elan_stats_get_index_name no callback\n"); -+ kmutex_unlock(&elan_mutex); -+ return res; -+ } -+ -+ if ((res = target->ops->elan_stats_get_name(target->arg, index, name)) == 0) -+ ELAN_DEBUG1(ELAN_DBG_CTRL, "elan_stats_get_index_name name %s\n",name); -+ -+ } -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+int -+elan_stats_get_block (ELAN_STATS_IDX statidx, uint entries, ulong *values) -+{ -+ ELAN_STATS_STRUCT *target; -+ int res=EINVAL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ -+ if ((target = elan_stats_find(statidx)) != NULL) -+ { -+ if ( target->ops->elan_stats_get_block == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return res; -+ } -+ -+ res = target->ops->elan_stats_get_block(target->arg, entries, values); -+ } -+ -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+int -+elan_stats_clear_block (ELAN_STATS_IDX statidx) -+{ -+ ELAN_STATS_STRUCT *target; -+ int res=EINVAL; -+ -+ kmutex_lock(&elan_mutex); -+ -+ if ((target = elan_stats_find(statidx)) != NULL) -+ { -+ if ( target->ops->elan_stats_clear_block == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return res; -+ } -+ -+ res = target->ops->elan_stats_clear_block(target->arg); -+ } -+ kmutex_unlock(&elan_mutex); -+ return res; -+} -+ -+void -+elan_stats_next_statidx(void) -+{ -+ /* XXXXX need to put not in use check here incase we loop MRH */ -+ /* tho its a bigish loop :) */ -+ elan_next_statidx++; -+ if (!elan_next_statidx) -+ elan_next_statidx++; -+} -+ -+int -+elan_stats_register (ELAN_STATS_IDX *statidx, -+ char *block_name, -+ uint num_entries, -+ ELAN_STATS_OPS *ops, -+ void *arg) -+{ -+ ELAN_STATS_STRUCT *target; -+ -+ kmutex_lock(&elan_mutex); -+ -+ /* create it and add */ -+ KMEM_ALLOC(target, ELAN_STATS_STRUCT *, sizeof(ELAN_STATS_STRUCT), 1); -+ if (target == NULL) -+ { -+ kmutex_unlock(&elan_mutex); -+ return ENOMEM; -+ } -+ -+ elan_stats_next_statidx(); -+ -+ *statidx = elan_next_statidx; -+ -+ target->statidx = elan_next_statidx; -+ target->num_entries = num_entries; -+ target->ops = ops; -+ target->arg = arg; -+ strcpy(target->block_name, block_name); -+ -+ list_add_tail(&target->node, &elan_stats_list); -+ -+ kmutex_unlock(&elan_mutex); -+ return 0; -+} -+ -+int -+elan_stats_deregister (ELAN_STATS_IDX statidx) -+{ -+ ELAN_STATS_STRUCT *target; -+ -+ kmutex_lock(&elan_mutex); -+ if ((target = elan_stats_find(statidx)) != NULL) -+ { -+ -+ list_del(&target->node); -+ -+ /* delete target entry */ -+ KMEM_FREE(target, sizeof(ELAN_STATS_STRUCT)); -+ } -+ kmutex_unlock(&elan_mutex); -+ -+ return target == NULL ? EINVAL : 0; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/context.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/context.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/context.c 2005-06-01 23:12:54.565444272 -0400 -@@ -0,0 +1,2101 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: context.c,v 1.116.2.1 2004/11/12 14:24:18 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/context.c,v $ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+/* -+ * Global variables configurable from /etc/system file -+ * (OR /etc/sysconfigtab on Digital UNIX) -+ */ -+int ntrapped_threads = 64; -+int ntrapped_dmas = 64; -+int ntrapped_events = E3_NonSysCntxQueueSize + 128; -+int ntrapped_commands = 64; -+int noverflow_commands = 1024; -+int nswapped_threads = 64; -+int nswapped_dmas = 64; -+ -+#define NUM_HALTOPS 8 -+ -+void *SwapListsLockInfo; -+void *CmdLockInfo; -+ -+static void HaltSwapContext (ELAN3_DEV *dev, void *arg); -+ -+static char *OthersStateStrings[] = {"others_running", "others_halting", "others_swapping", -+ "others_halting_more", "others_swapping_more", "others_swapped"}; -+ -+ELAN3_CTXT * -+elan3_alloc (ELAN3_DEV *dev, int kernel) -+{ -+ ELAN3_CTXT *ctxt; -+ int i; -+ unsigned long flags; -+ -+ PRINTF1 (DBG_DEVICE, DBG_FN, "elan3_alloc: %s\n", kernel ? "kernel" : "user"); -+ -+ KMEM_ZALLOC (ctxt, ELAN3_CTXT *, sizeof (ELAN3_CTXT), TRUE); -+ -+ if (ctxt == NULL) -+ return (NULL); -+ -+ elan_nullcap (&ctxt->Capability); -+ -+ ctxt->Device = dev; -+ ctxt->OthersState = CTXT_OTHERS_SWAPPED; -+ ctxt->RefCnt = 1; -+ ctxt->Position = dev->Position; -+ -+ if (kernel) -+ ctxt->Status = CTXT_DETACHED | CTXT_SWAPPED_OUT | CTXT_KERNEL; -+ else -+ ctxt->Status = CTXT_DETACHED | CTXT_SWAPPED_OUT | CTXT_NO_LWPS; -+ -+ ctxt->Elan3mmu = elan3mmu_alloc (ctxt); -+ -+ kcondvar_init (&ctxt->Wait); -+ kcondvar_init (&ctxt->CommandPortWait); -+ kcondvar_init (&ctxt->LwpWait); -+ kcondvar_init (&ctxt->HaltWait); -+ -+ spin_lock_init (&ctxt->InputFaultLock); -+ -+ kmutex_init (&ctxt->SwapListsLock); -+ kmutex_init (&ctxt->CmdPortLock); -+ kmutex_init (&ctxt->NetworkErrorLock); -+ kmutex_init (&ctxt->CmdLock); -+ -+ krwlock_init (&ctxt->VpLock); -+ -+ KMEM_GETPAGES (ctxt->FlagPage, ELAN3_FLAGSTATS *, 1, TRUE); -+ if (!ctxt->FlagPage) -+ goto error; -+ bzero ((char *) ctxt->FlagPage, PAGESIZE); -+ -+ KMEM_ZALLOC (ctxt->CommandTraps, COMMAND_TRAP *, sizeof (COMMAND_TRAP) * ntrapped_commands, TRUE); -+ if (!ctxt->CommandTraps) -+ goto error; -+ -+ KMEM_ZALLOC (ctxt->ThreadTraps, THREAD_TRAP *, sizeof (THREAD_TRAP) * ntrapped_threads, TRUE); -+ if (!ctxt->ThreadTraps) -+ goto error; -+ -+ KMEM_ZALLOC (ctxt->DmaTraps, DMA_TRAP *, sizeof (DMA_TRAP) * ntrapped_dmas, TRUE); -+ if (!ctxt->DmaTraps) -+ goto error; -+ -+ KMEM_ZALLOC (ctxt->EventCookies, EVENT_COOKIE *, sizeof (EVENT_COOKIE) * ntrapped_events, TRUE); -+ if (!ctxt->EventCookies) -+ goto error; -+ -+ KMEM_ZALLOC (ctxt->Commands, CProcTrapBuf_BE *, sizeof (CProcTrapBuf_BE) * noverflow_commands,TRUE); -+ if (!ctxt->Commands) -+ goto error; -+ -+ KMEM_ZALLOC (ctxt->SwapThreads, E3_Addr *, sizeof (E3_Addr) * nswapped_threads, TRUE); -+ if (!ctxt->SwapThreads) -+ goto error; -+ -+ KMEM_ZALLOC (ctxt->SwapDmas, E3_DMA_BE *, sizeof (E3_DMA_BE) * nswapped_dmas, TRUE); -+ if (!ctxt->SwapDmas) -+ goto error; -+ -+ /* -+ * "slop" is defined as follows : -+ * number of entries REQUIRED to be left spare to consume all other traps -+ * up until the time that the context can be swapped out. -+ * -+ * CommandTrapQ : 1 command issued by main + 1 issued by the thread processor per elan -+ * ThreadTrapQ : 2 from command + 2 input -+ * DmaTrapQ : 2 from command + 2 input -+ * EventTrapQ : 2 from command + 1 thread + 1 dma + 2 input + E3_NonSysCntxQueueSize -+ */ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ ELAN3_QUEUE_INIT (ctxt->CommandTrapQ, ntrapped_commands, 2); -+ ELAN3_QUEUE_INIT (ctxt->ThreadTrapQ, ntrapped_threads, 4); -+ ELAN3_QUEUE_INIT (ctxt->DmaTrapQ, ntrapped_dmas, 4); -+ ELAN3_QUEUE_INIT (ctxt->EventCookieQ, ntrapped_events, MIN(E3_NonSysCntxQueueSize + 6, ntrapped_events - 6)); -+ ELAN3_QUEUE_INIT (ctxt->CommandQ, noverflow_commands, 0); -+ ELAN3_QUEUE_INIT (ctxt->SwapThreadQ, nswapped_threads, 0); -+ ELAN3_QUEUE_INIT (ctxt->SwapDmaQ, nswapped_dmas, 0); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+#if defined(DIGITAL_UNIX) -+ /* Allocate the segelan for the command port */ -+ if (! kernel && elan3_segelan3_create (ctxt) == NULL) -+ { -+ elan3_detach(ctxt); -+ elan3_free (ctxt); -+ return ((ELAN3_CTXT *) NULL); -+ } -+#endif -+ -+ /* -+ * Initialise the Input Fault list -+ */ -+ spin_lock (&ctxt->InputFaultLock); -+ for (i = 0; i < NUM_INPUT_FAULT_SAVE; i++) -+ ctxt->InputFaults[i].Next = (i == (NUM_INPUT_FAULT_SAVE-1)) ? NULL : &ctxt->InputFaults[i+1]; -+ ctxt->InputFaultList = &ctxt->InputFaults[0]; -+ spin_unlock (&ctxt->InputFaultLock); -+ -+ ReserveHaltOperations (dev, NUM_HALTOPS, TRUE); -+ -+ if ((ctxt->RouteTable = AllocateRouteTable (ctxt->Device, ELAN3_MAX_VPS)) == NULL) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_FN, "elan3_alloc: cannot map route table\n"); -+ elan3_detach(ctxt); -+ elan3_free (ctxt); -+ return ((ELAN3_CTXT *) NULL); -+ } -+ -+ return (ctxt); -+ -+ -+ error: -+ -+ elan3_detach(ctxt); -+ elan3_free (ctxt); -+ if (ctxt->FlagPage) -+ KMEM_FREEPAGES ((void *) ctxt->FlagPage, 1); -+ if (ctxt->CommandTraps) -+ KMEM_FREE ((void *) ctxt->CommandTraps, sizeof (COMMAND_TRAP) * ntrapped_commands); -+ if (ctxt->ThreadTraps) -+ KMEM_FREE ((void *) ctxt->ThreadTraps, sizeof (THREAD_TRAP) * ntrapped_threads); -+ if (ctxt->DmaTraps) -+ KMEM_FREE ((void *) ctxt->DmaTraps, sizeof (DMA_TRAP) * ntrapped_dmas); -+ if (ctxt->EventCookies) -+ KMEM_FREE ((void *) ctxt->EventCookies, sizeof (EVENT_COOKIE) * ntrapped_events); -+ if (ctxt->Commands) -+ KMEM_FREE ((void *) ctxt->Commands, sizeof (CProcTrapBuf_BE) * noverflow_commands); -+ if (ctxt->SwapThreads) -+ KMEM_FREE ((void *) ctxt->SwapThreads, sizeof (E3_Addr) * nswapped_threads); -+ if (ctxt->SwapDmas) -+ KMEM_FREE ((void *) ctxt->SwapDmas, sizeof (E3_DMA_BE) * nswapped_dmas); -+ -+ kcondvar_destroy (&ctxt->Wait); -+ kcondvar_destroy (&ctxt->CommandPortWait); -+ kcondvar_destroy (&ctxt->LwpWait); -+ kcondvar_destroy (&ctxt->HaltWait); -+ -+ kmutex_destroy (&ctxt->SwapListsLock); -+ kmutex_destroy (&ctxt->CmdLock); -+ kmutex_destroy (&ctxt->NetworkErrorLock); -+ spin_lock_destroy (&ctxt->InputFaultLock); -+ -+ krwlock_destroy (&ctxt->VpLock); -+ -+ KMEM_FREE (ctxt, sizeof (ELAN3_CTXT)); -+ -+ return (NULL); -+} -+ -+void -+elan3_free (ELAN3_CTXT *ctxt) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ NETERR_FIXUP *nef; -+ -+ PRINTF1 (ctxt, DBG_FN, "elan3_free: %p \n", ctxt); -+ -+ elan3_removevp (ctxt, ELAN3_INVALID_PROCESS); /* Remove any virtual process mappings */ -+ -+#if defined(DIGITAL_UNIX) -+ WaitForContext (ctxt); /* wait for all references to this context to go away */ -+#endif -+ -+ if (ctxt->RouteTable) -+ FreeRouteTable (dev, ctxt->RouteTable); -+ ctxt->RouteTable = NULL; -+ -+ elan3mmu_free (ctxt->Elan3mmu); /* free of our Elan3mmu */ -+ -+ if (ctxt->Private) /* Call back to "user" to free off */ -+ ELAN3_OP_FREE_PRIVATE (ctxt); /* private data */ -+ -+#if defined(DIGITAL_UNIX) -+ if (! CTXT_IS_KERNEL(ctxt)) -+ elan3_segelan3_destroy (ctxt); /* Unmap the command port from the users address space. */ -+#endif -+ -+ ReleaseHaltOperations (dev, NUM_HALTOPS); -+ -+ if (ctxt->Input0Resolver) -+ CancelNetworkErrorResolver (ctxt->Input0Resolver); -+ -+ if (ctxt->Input1Resolver) -+ CancelNetworkErrorResolver (ctxt->Input1Resolver); -+ -+ while ((nef = ctxt->NetworkErrorFixups) != NULL) -+ { -+ ctxt->NetworkErrorFixups = nef->Next; -+ -+ CompleteNetworkErrorFixup (ctxt, nef, ESRCH); -+ } -+ -+ KMEM_FREEPAGES ((void *) ctxt->FlagPage, 1); -+ -+ KMEM_FREE ((void *) ctxt->CommandTraps, sizeof (COMMAND_TRAP) * ntrapped_commands); -+ KMEM_FREE ((void *) ctxt->ThreadTraps, sizeof (THREAD_TRAP) * ntrapped_threads); -+ KMEM_FREE ((void *) ctxt->DmaTraps, sizeof (DMA_TRAP) * ntrapped_dmas); -+ KMEM_FREE ((void *) ctxt->EventCookies, sizeof (EVENT_COOKIE) * ntrapped_events); -+ KMEM_FREE ((void *) ctxt->Commands, sizeof (CProcTrapBuf_BE) * noverflow_commands); -+ KMEM_FREE ((void *) ctxt->SwapThreads, sizeof (E3_Addr) * nswapped_threads); -+ KMEM_FREE ((void *) ctxt->SwapDmas, sizeof (E3_DMA_BE) * nswapped_dmas); -+ -+ kcondvar_destroy (&ctxt->Wait); -+ kcondvar_destroy (&ctxt->CommandPortWait); -+ kcondvar_destroy (&ctxt->LwpWait); -+ kcondvar_destroy (&ctxt->HaltWait); -+ -+ kmutex_destroy (&ctxt->SwapListsLock); -+ kmutex_destroy (&ctxt->CmdLock); -+ kmutex_destroy (&ctxt->NetworkErrorLock); -+ spin_lock_destroy (&ctxt->InputFaultLock); -+ -+ krwlock_destroy (&ctxt->VpLock); -+ -+ KMEM_FREE (ctxt, sizeof (ELAN3_CTXT)); -+} -+ -+int -+elan3_doattach(ELAN3_CTXT *ctxt, ELAN_CAPABILITY *cap) -+{ -+ unsigned long pgnum = ((cap->cap_mycontext & MAX_ROOT_CONTEXT_MASK) * sizeof (E3_CommandPort)) / PAGE_SIZE; -+ unsigned long pgoff = ((cap->cap_mycontext & MAX_ROOT_CONTEXT_MASK) * sizeof (E3_CommandPort)) & (PAGE_SIZE-1); -+ ELAN3_DEV *dev = ctxt->Device; -+ int res = ESUCCESS; -+ unsigned long flags; -+ -+ /* Map in the command port for this context */ -+ if (MapDeviceRegister (dev, ELAN3_BAR_COMMAND_PORT, &ctxt->CommandPage, pgnum * PAGE_SIZE, PAGE_SIZE, &ctxt->CommandPageHandle) != ESUCCESS) -+ { -+ PRINTF0 (ctxt, DBG_FN, "elan3_doattach: MapDeviceRegister failed"); -+ return (EINVAL); -+ } -+ -+ ctxt->CommandPort = ctxt->CommandPage + pgoff; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ res = 0; -+ if (ELAN3_DEV_CTX_TABLE(dev,cap->cap_mycontext) != NULL) -+ res = EBUSY; -+ else -+ { -+ if ((res = elan3mmu_attach (ctxt->Device, cap->cap_mycontext, ctxt->Elan3mmu, -+ ctxt->RouteTable->Table, ctxt->RouteTable->Size-1)) == 0) -+ { -+ ELAN3_DEV_CTX_TABLE(dev,cap->cap_mycontext) = ctxt; -+ ctxt->Capability = *cap; -+ } -+ } -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ if (res == ESUCCESS) -+ elan3_swapin (ctxt, CTXT_DETACHED); -+ else -+ { -+ UnmapDeviceRegister (dev, &ctxt->CommandPageHandle); -+ ctxt->CommandPage = (ioaddr_t) 0; -+ ctxt->CommandPort = (ioaddr_t) 0; -+ } -+ -+ return (res); -+} -+ -+void -+elan3_destroy_callback( void * args, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map) -+{ -+ if (map == NULL) -+ { -+ /* the cap is being destroyed */ -+ PRINTF0 (NULL, DBG_VP, "elan3_destroy_callback: the cap is being destroyed \n"); -+ } -+ else -+ { -+ /* the map is being destroyed */ -+ PRINTF0 (NULL, DBG_VP, "elan3_destroy_callback: the map is being destroyed \n"); -+ } -+} -+ -+int -+elan3_attach (ELAN3_CTXT *ctxt, ELAN_CAPABILITY *cap) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int type; -+ int res; -+ -+ switch (type = elan3_validate_cap (dev, cap, ELAN_USER_ATTACH)) -+ { -+ case ELAN_CAP_OK: -+ /* nothing */ -+ break; -+ -+ case ELAN_CAP_RMS: -+ if ((res = elan_attach_cap(cap, dev->Devinfo.dev_rail, ctxt, elan3_destroy_callback)) != 0) -+ return res; -+ break; -+ -+ default: -+ return (EINVAL); -+ } -+ -+ if (((res = elan3_doattach(ctxt,cap)) != ESUCCESS) && (type == ELAN_CAP_RMS)) -+ elan_detach_cap(cap, dev->Devinfo.dev_rail); -+ -+ return res; -+} -+ -+void -+elan3_detach ( ELAN3_CTXT *ctxt ) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int need_to_call_elanmod_detach = 0; -+ unsigned long flags; -+ -+ PRINTF1 (ctxt, DBG_FN, "elan3_detach: %p \n", ctxt ); -+ -+ if (ctxt->Capability.cap_mycontext == ELAN_CAP_UNINITIALISED) -+ { -+ PRINTF0 (ctxt, DBG_FN, "elan3_detach: context not attached \n"); -+ return ; -+ } -+ -+ /* must you be in the ctx_table ?? */ -+ -+ switch (ctxt->Capability.cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ case ELAN_CAP_TYPE_CYCLIC: -+ { -+ if (ELAN3_SYSTEM_CONTEXT (ctxt->Capability.cap_mycontext)) -+ return ; -+ -+ if (! (ctxt->Capability.cap_type & ELAN_CAP_TYPE_HWTEST)) -+ need_to_call_elanmod_detach = 1; -+ -+ break; -+ } -+ default: -+ return ; -+ } -+ -+ elan3_swapout (ctxt, CTXT_DETACHED); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ elan3mmu_detach (dev, ctxt->Capability.cap_mycontext); -+ ELAN3_DEV_CTX_TABLE(dev,ctxt->Capability.cap_mycontext) = NULL; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ if (ctxt->CommandPage) -+ { -+ UnmapDeviceRegister (dev, &ctxt->CommandPageHandle); -+ ctxt->CommandPage = (ioaddr_t) 0; -+ } -+ -+ if (need_to_call_elanmod_detach) -+ elan_detach_cap(&ctxt->Capability, dev->Devinfo.dev_rail); -+ -+ elan_nullcap (&ctxt->Capability); -+ -+} -+ -+void -+elan3_dodetach ( ELAN3_CTXT *ctxt ) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ unsigned long flags; -+ -+ PRINTF1 (ctxt, DBG_FN, "elan3_dodetach: %p \n", ctxt ); -+ -+ if (ctxt->Capability.cap_mycontext == ELAN_CAP_UNINITIALISED) -+ { -+ PRINTF0 (ctxt, DBG_FN, "elan3_dodetach: context not attached \n"); -+ return ; -+ } -+ -+ elan3_swapout (ctxt, CTXT_DETACHED); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ elan3mmu_detach (dev, ctxt->Capability.cap_mycontext); -+ ELAN3_DEV_CTX_TABLE(dev,ctxt->Capability.cap_mycontext) = NULL; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ if (ctxt->CommandPage) -+ { -+ UnmapDeviceRegister (dev, &ctxt->CommandPageHandle); -+ ctxt->CommandPage = (ioaddr_t) 0; -+ } -+ -+ elan_nullcap (&ctxt->Capability); -+} -+ -+void -+elan3_swapin (ELAN3_CTXT *ctxt, int reason) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ ASSERT (ctxt->Status & CTXT_SWAPPED_REASONS); -+ -+ PRINTF3 (ctxt, DBG_SWAP, "elan3_swapin: status %x State %s reason %x\n", -+ ctxt->Status, OthersStateStrings[ctxt->OthersState], reason); -+ -+ while (ctxt->Status & CTXT_SWAPPING_OUT) /* In transition */ -+ kcondvar_wait (&ctxt->LwpWait, &dev->IntrLock, &flags); -+ -+ if (reason == CTXT_NO_LWPS && ctxt->LwpCount++ != 0) /* Added another LWP */ -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return; -+ } -+ -+ if ((ctxt->Status & ~reason) & CTXT_SWAPPED_REASONS) -+ ctxt->Status &= ~reason; -+ else -+ { -+ ASSERT (ctxt->Status & CTXT_SWAPPED_OUT); -+ ASSERT (ctxt->OthersState == CTXT_OTHERS_SWAPPED); -+ -+ /* -+ * Will not be swapped out anymore, so ask the "user" to perform -+ * any swapping in he needs before letting the context run again. -+ */ -+ -+ ctxt->Status &= ~(CTXT_SWAPPED_OUT | CTXT_QUEUES_EMPTY | reason); -+ ctxt->OthersState = CTXT_OTHERS_RUNNING; -+ -+ if (ctxt->Input0Trap.State == CTXT_STATE_OK && ctxt->Input1Trap.State == CTXT_STATE_OK) -+ SetInputterStateForContext (ctxt, 0, NULL); -+ -+ kcondvar_wakeupall (&ctxt->Wait, &dev->IntrLock); -+ } -+ -+ PRINTF2 (ctxt, DBG_SWAP, "elan3_swapin: all done - status %x state %s\n", -+ ctxt->Status, OthersStateStrings[ctxt->OthersState]); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+ -+void -+elan3_swapout (ELAN3_CTXT *ctxt, int reason) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int cansleep; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ PRINTF3 (ctxt, DBG_SWAP, "elan3_swapout: status %x state %s reason %x\n", -+ ctxt->Status, OthersStateStrings[ctxt->OthersState], reason); -+ -+ if (reason == CTXT_NO_LWPS) -+ { -+ if (--ctxt->LwpCount != 0) /* Still other LWPs running */ -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return; -+ } -+ -+ kcondvar_wakeupall (&ctxt->LwpWait, &dev->IntrLock); /* Wakeup anyone waiting on LwpCount */ -+ } -+ -+ ctxt->Status |= reason; -+ -+ while (ctxt->Status & CTXT_SWAPPING_OUT) /* wait for someone else to finish swapping */ -+ kcondvar_wait (&ctxt->LwpWait, &dev->IntrLock, &flags); /* out */ -+ -+ if (ctxt->Status & CTXT_SWAPPED_OUT) -+ { -+ if (reason == CTXT_NO_LWPS) /* Wakeup other thread waiting on LWP exit */ -+ kcondvar_wakeupall (&ctxt->LwpWait, &dev->IntrLock); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return; -+ } -+ -+ /* -+ * mark the context as swapping out. -+ */ -+ ctxt->Status |= CTXT_SWAPPING_OUT; -+ -+ if (reason != CTXT_FIXUP_NETERR) -+ { -+ /* -+ * Stop all of the lwps. -+ */ -+ while (ctxt->LwpCount) -+ { -+ kcondvar_wakeupall (&ctxt->Wait, &dev->IntrLock); /* Wake up any lwps */ -+ kcondvar_wait (&ctxt->LwpWait, &dev->IntrLock, &flags); /* then wait for them to enter elan3_swapout */ -+ } -+ } -+ -+ StartSwapoutContext (ctxt, 0, NULL); -+ for (;;) -+ { -+ PRINTF0 (ctxt, DBG_SWAP, "elan3_swapout: HandleExceptions\n"); -+ -+ cansleep = (HandleExceptions(ctxt, &flags) == ESUCCESS); -+ -+ PRINTF2 (ctxt, DBG_SWAP, "elan3_swapout: OthersState=%d cansleep=%d\n", ctxt->OthersState, cansleep); -+ -+ if (ctxt->OthersState == CTXT_OTHERS_SWAPPED) -+ break; -+ -+ if (cansleep) -+ kcondvar_wait (&ctxt->Wait, &dev->IntrLock, &flags); -+ } -+ PRINTF0 (ctxt, DBG_SWAP, "elan3_swapout: swapped out\n"); -+ -+ ASSERT (ELAN3_QUEUE_EMPTY (ctxt->DmaTrapQ)); -+ ASSERT (ELAN3_QUEUE_EMPTY (ctxt->ThreadTrapQ)); -+ -+ ctxt->Status |= CTXT_SWAPPED_OUT; -+ ctxt->Status &= ~CTXT_SWAPPING_OUT; -+ -+ kcondvar_wakeupall (&ctxt->LwpWait, &dev->IntrLock); -+ -+ PRINTF2 (ctxt, DBG_SWAP, "elan3_swapout: all done - status %x state %s\n", -+ ctxt->Status, OthersStateStrings[ctxt->OthersState]); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+int -+elan3_pagefault (ELAN3_CTXT *ctxt, E3_FaultSave_BE *FaultSave, int npages) -+{ -+ E3_Addr elanAddr = FaultSave->s.FaultAddress; -+ int writeable; -+ int res; -+ -+ PRINTF3 (ctxt, DBG_FAULT, "elan3_pagefault: elanAddr %08x FSR %08x : %s\n", elanAddr, FaultSave->s.FSR.Status, -+ FaultSave->s.FSR.s.ProtFault ? "protection fault" : "pte invalid"); -+ -+ /* Look at the FSR to determine the fault type etc */ -+ -+ if (FaultSave->s.FSR.Status == 0) /* this is a target abort/parity error, so look */ -+ { /* at the PCI config space registers to determine */ -+ ElanBusError (ctxt->Device); -+ return (EFAULT); -+ } -+ -+ if (FaultSave->s.FSR.s.AlignmentErr) /* Alignment errors are always fatal. */ -+ { -+ PRINTF0 (ctxt, DBG_FAULT, "elan3_pagefault: Alignment error\n"); -+ return (EFAULT); -+ } -+ -+ if (FaultSave->s.FSR.s.WalkBadData) /* Memory ECC error during a walk */ -+ { -+ PRINTF0 (ctxt, DBG_FAULT, "elan3_pagefault: Memory ECC error during walk\n"); -+ return (EFAULT); -+ } -+ -+ if (!FaultSave->s.FSR.s.ProtFault && /* DMA memory type changed */ -+ !FaultSave->s.FSR.s.Walking) -+ { -+ PRINTF0 (ctxt, DBG_FAULT, "elan3_pagefault: DMA memory type changed\n"); -+ return (EFAULT); -+ } -+ -+ ASSERT (FaultSave->s.FSR.s.ProtFault ? /* protection errors, should always have a valid pte */ -+ (!FaultSave->s.FSR.s.Walking || !(FaultSave->s.FSR.s.Level==3) || FaultSave->s.FSR.s.FaultPte == ELAN3_ET_PTE) : -+ FaultSave->s.FSR.s.FaultPte == ELAN3_ET_INVALID); /* otherwise it must be an invalid pte */ -+ -+ /* -+ * Determine whether to fault for a 'write' from the access permissions we need, and not -+ * from the access type (WrAcc). -+ */ -+ writeable = (FaultSave->s.FSR.s.AccTypePerm & (1 << FSR_WritePermBit)); -+ -+ /* Check that we have the right permissions for this access type. */ -+ if ((res = elan3mmu_checkperm (ctxt->Elan3mmu, (elanAddr&PAGEMASK), npages*PAGESIZE, FaultSave->s.FSR.s.AccTypePerm)) != 0) -+ { -+ PRINTF1 (ctxt, DBG_FAULT, "elan3_pagefault: %s\n", (res == ENOMEM) ? "no protection mapping" : "protection error"); -+ -+ return (res); -+ } -+ -+ res = LoadElanTranslation (ctxt, (elanAddr&PAGEMASK), npages*PAGESIZE, FaultSave->s.FSR.s.ProtFault, writeable); -+ -+ if (res == ESUCCESS) -+ { -+ BumpStat (ctxt->Device, PageFaults); -+ BumpUserStat (ctxt, PageFaults); -+ } -+ -+ PRINTF1 (ctxt, DBG_FAULT, "elan3_pagefault: -> %d\n", res); -+ -+ return (res); -+} -+ -+void -+elan3_block_inputter (ELAN3_CTXT *ctxt, int block) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ if (block) -+ ctxt->Status |= CTXT_USER_FILTERING; -+ else -+ ctxt->Status &= ~CTXT_USER_FILTERING; -+ -+ if (ctxt->Capability.cap_mycontext != ELAN_CAP_UNINITIALISED) -+ SetInputterStateForContext (ctxt, 0, NULL); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+int -+FixupNetworkErrors (ELAN3_CTXT *ctxt, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ NETERR_FIXUP *nef; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ if (ctxt->NetworkErrorFixups == NULL) -+ return (ESUCCESS); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ -+ kmutex_lock (&ctxt->NetworkErrorLock); /* single thread while fixing up errors */ -+ elan3_swapout (ctxt, CTXT_FIXUP_NETERR); -+ -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ while ((nef = ctxt->NetworkErrorFixups) != NULL) -+ { -+ ctxt->NetworkErrorFixups = nef->Next; -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ -+ if (ELAN3_OP_FIXUP_NETWORK_ERROR (ctxt, nef) == OP_FAILED) -+ CompleteNetworkErrorFixup (ctxt, nef, EINVAL); -+ -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ -+ elan3_swapin (ctxt, CTXT_FIXUP_NETERR); -+ -+ kmutex_unlock (&ctxt->NetworkErrorLock); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+} -+ -+int -+CompleteNetworkErrorResolver (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, NETERR_RESOLVER *rvp) -+{ -+ int state; -+ -+ switch (rvp->Status) -+ { -+ case ESUCCESS: -+ /* -+ * the item still existed at the source - if it's a wait for EOP transaction -+ * then the source will retry - otherwise the remote event will have been -+ * cleared and we should execute it -+ */ -+ PRINTF1 (ctxt, DBG_NETERR, "CompleteNetworkErrorResolver: ESUCCESS zero WaitForEopTransaction %p\n", trap->WaitForEopTransaction); -+ -+ state = trap->WaitForEopTransaction ? CTXT_STATE_OK : CTXT_STATE_NEEDS_RESTART; -+ -+ break; -+ -+ case ESRCH: -+ /* -+ * the item was not found at the source - we should always execute the transaction -+ * since it will never be resent -+ */ -+ PRINTF1 (ctxt, DBG_NETERR, "CompleteNetworkErrorResolver: ESRCH execute WaitForEopTransaction %p\n", trap->WaitForEopTransaction); -+ state = CTXT_STATE_NEEDS_RESTART; -+ break; -+ -+ default: /* other errors */ -+ PRINTF1 (ctxt, DBG_NETERR, "CompleteNetworkErrorResolver: %d\n", rvp->Status); -+ if (ElanException (ctxt, EXCEPTION_NETWORK_ERROR, INPUT_PROC, trap, &rvp) == OP_HANDLED) -+ state = CTXT_STATE_NEEDS_RESTART; -+ else -+ state = CTXT_STATE_OK; -+ break; -+ } -+ -+ FreeNetworkErrorResolver (rvp); -+ -+ return (state); -+} -+ -+int -+HandleExceptions (ELAN3_CTXT *ctxt, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ THREAD_TRAP tproc; -+ DMA_TRAP dproc; -+ NETERR_RESOLVER *rvp; -+ int state; -+ -+ if (ctxt->Status & CTXT_COMMAND_OVERFLOW_ERROR) -+ { -+ ctxt->Status &= ~CTXT_COMMAND_OVERFLOW_ERROR; -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ElanException (ctxt, EXCEPTION_COMMAND_OVERFLOW, COMMAND_PROC, NULL); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if (! ELAN3_QUEUE_BACK_EMPTY (ctxt->CommandTrapQ)) -+ { -+ /* XXXX: unmap translations to the command port */ -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ResolveCProcTrap (ctxt); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if (ctxt->Input0Trap.State == CTXT_STATE_TRAPPED) -+ { -+ ctxt->Input0Trap.State = CTXT_STATE_RESOLVING; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ResolveIProcTrap (ctxt, &ctxt->Input0Trap, &ctxt->Input0Resolver); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if (ctxt->Input1Trap.State == CTXT_STATE_TRAPPED) -+ { -+ ctxt->Input1Trap.State = CTXT_STATE_RESOLVING; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ResolveIProcTrap (ctxt, &ctxt->Input1Trap, &ctxt->Input1Resolver); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if ((rvp = ctxt->Input0Resolver) != NULL && rvp->Completed) -+ { -+ ASSERT (ctxt->Input0Trap.State == CTXT_STATE_NETWORK_ERROR); -+ -+ ctxt->Input0Resolver = NULL; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ state = CompleteNetworkErrorResolver (ctxt, &ctxt->Input0Trap, rvp); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ ctxt->Input0Trap.State = state; -+ return (EAGAIN); -+ } -+ -+ if ((rvp = ctxt->Input1Resolver) != NULL && rvp->Completed) -+ { -+ ASSERT (ctxt->Input1Trap.State == CTXT_STATE_NETWORK_ERROR); -+ -+ ctxt->Input1Resolver = NULL; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ state = CompleteNetworkErrorResolver (ctxt,&ctxt->Input1Trap, rvp); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ ctxt->Input1Trap.State = state; -+ return (EAGAIN); -+ } -+ -+ if (NextTProcTrap (ctxt, &tproc)) -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ResolveTProcTrap (ctxt, &tproc); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ ctxt->Status &= ~CTXT_THREAD_QUEUE_FULL; -+ -+ if (NextDProcTrap (ctxt, &dproc)) -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ResolveDProcTrap (ctxt, &dproc); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ ctxt->Status &= ~CTXT_DMA_QUEUE_FULL; -+ -+ /* Handle all event interrupts. */ -+ if (! ELAN3_QUEUE_EMPTY (ctxt->EventCookieQ)) -+ { -+ while (! ELAN3_QUEUE_EMPTY (ctxt->EventCookieQ)) -+ { -+ E3_uint32 cookie = *ELAN3_QUEUE_FRONT (ctxt->EventCookieQ, ctxt->EventCookies); -+ -+ ELAN3_QUEUE_REMOVE (ctxt->EventCookieQ); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ if (ELAN3_OP_EVENT (ctxt, cookie, OP_LWP) != OP_DEFER) -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ else -+ { -+ spin_lock_irqsave (&dev->IntrLock, *flags); /* place the cookie back on the queue. */ -+ /* note we place it on the front to ensure */ -+ ELAN3_QUEUE_ADD_FRONT (ctxt->EventCookieQ); /* event ordering. */ -+ *ELAN3_QUEUE_FRONT (ctxt->EventCookieQ, ctxt->EventCookies) = cookie; -+ } -+ } -+ return (EAGAIN); -+ } -+ ctxt->Status &= ~CTXT_EVENT_QUEUE_FULL; -+ -+ if (! ELAN3_QUEUE_EMPTY (ctxt->SwapDmaQ)) -+ { -+ while (! ELAN3_QUEUE_EMPTY (ctxt->SwapDmaQ)) -+ { -+ E3_DMA_BE DmaDesc = *ELAN3_QUEUE_FRONT (ctxt->SwapDmaQ, ctxt->SwapDmas); -+ -+ ELAN3_QUEUE_REMOVE (ctxt->SwapDmaQ); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ RestartDmaDesc (ctxt, &DmaDesc); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ } -+ return (EAGAIN); -+ } -+ -+ if (! ELAN3_QUEUE_EMPTY (ctxt->SwapThreadQ)) -+ { -+ while (! ELAN3_QUEUE_EMPTY (ctxt->SwapThreadQ)) -+ { -+ E3_Addr StackPointer = *ELAN3_QUEUE_FRONT (ctxt->SwapThreadQ, ctxt->SwapThreads); -+ -+ ELAN3_QUEUE_REMOVE (ctxt->SwapThreadQ); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ ReissueStackPointer (ctxt, StackPointer); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ } -+ return (EAGAIN); -+ } -+ -+ switch (ctxt->OthersState) -+ { -+ case CTXT_OTHERS_SWAPPING: -+ if (! (ctxt->Status & CTXT_OTHERS_REASONS)) -+ ctxt->OthersState = CTXT_OTHERS_RUNNING; -+ else -+ ctxt->OthersState = CTXT_OTHERS_SWAPPED; -+ -+ PRINTF1 (ctxt, DBG_LWP, "HandleExceptions: OthersState : swapping -> %s\n", OthersStateStrings[ctxt->OthersState]); -+ -+ break; -+ -+ case CTXT_OTHERS_SWAPPING_MORE: -+ ctxt->OthersState = CTXT_OTHERS_HALTING_MORE; -+ QueueHaltOperation (dev, 0, NULL, INT_DProcHalted | INT_TProcHalted, HaltSwapContext, ctxt); -+ -+ PRINTF1 (ctxt, DBG_LWP, "HandleExceptions: OthersState : swapping_more -> %s\n", OthersStateStrings[ctxt->OthersState]); -+ break; -+ } -+ return (ESUCCESS); -+} -+ -+int -+RestartContext (ELAN3_CTXT *ctxt, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ PRINTF1 (ctxt, DBG_LWP, "RestartContext: status %x\n", ctxt->Status); -+ -+ if (! (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ if (! ELAN3_QUEUE_FRONT_EMPTY (ctxt->CommandTrapQ) || ! ELAN3_QUEUE_EMPTY(ctxt->CommandQ)) -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ RestartCProcTrap (ctxt); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if (ctxt->Input0Trap.State == CTXT_STATE_NEEDS_RESTART) -+ { -+ ctxt->Input0Trap.State = CTXT_STATE_EXECUTING; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ res = RestartIProcTrap (ctxt, &ctxt->Input0Trap); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ -+ if (res == ESUCCESS) -+ ctxt->Input0Trap.State = CTXT_STATE_OK; -+ else -+ ctxt->Input0Trap.State = CTXT_STATE_NEEDS_RESTART; -+ return (EAGAIN); -+ } -+ -+ if (ctxt->Input1Trap.State == CTXT_STATE_NEEDS_RESTART) -+ { -+ ctxt->Input1Trap.State = CTXT_STATE_EXECUTING; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ res = RestartIProcTrap (ctxt, &ctxt->Input1Trap); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ -+ if (res == ESUCCESS) -+ ctxt->Input1Trap.State = CTXT_STATE_OK; -+ else -+ ctxt->Input1Trap.State = CTXT_STATE_NEEDS_RESTART; -+ return (EAGAIN); -+ } -+ -+ if (SetEventsNeedRestart (ctxt)) -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ RestartSetEvents (ctxt); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ SetInputterStateForContext (ctxt, 0, NULL); -+ -+ if (TProcNeedsRestart (ctxt)) -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ -+ LoadCommandPortTranslation (ctxt); -+ RestartTProcItems (ctxt); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if (DProcNeedsRestart (ctxt)) -+ { -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ RestartDProcItems (ctxt); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ return (EAGAIN); -+ } -+ -+ if (ELAN3_QUEUE_EMPTY (ctxt->CommandTrapQ)) -+ { -+ PRINTF1 (ctxt, DBG_LWP, "RestartContext: setting Command Flag at %p to 0\n", &ctxt->FlagPage->CommandFlag); -+ -+ ctxt->FlagPage->CommandFlag = 0; -+ -+ if (ctxt->Status & CTXT_WAITING_COMMAND) -+ { -+ PRINTF0 (ctxt, DBG_LWP, "RestartContext: waking up threads waiting for commandport\n"); -+ -+ ctxt->Status &= ~CTXT_WAITING_COMMAND; -+ -+ kcondvar_wakeupall (&ctxt->CommandPortWait, &dev->IntrLock); -+ } -+ } -+ } -+ -+ return (ESUCCESS); -+} -+ -+static void -+HaltSwapContext (ELAN3_DEV *dev, void *arg) -+{ -+ ELAN3_CTXT *ctxt = (ELAN3_CTXT *) arg; -+ int SysCntx = (ctxt->Capability.cap_mycontext & SYS_CONTEXT_BIT); -+ E3_ThreadQueue_BE thread; -+ E3_DMA_BE dma; -+ sdramaddr_t FPtr, BPtr; -+ sdramaddr_t Base, Top; -+ u_int *runCount; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ ASSERT (ctxt->OthersState == CTXT_OTHERS_HALTING || ctxt->OthersState == CTXT_OTHERS_HALTING_MORE); -+ -+ PRINTF2 (ctxt, DBG_SWAP, "HaltSwapContext: status %x state %s\n", ctxt->Status, OthersStateStrings[ctxt->OthersState]); -+ -+ if (! (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ if (ctxt->OthersState == CTXT_OTHERS_HALTING_MORE) -+ { -+ runCount = SysCntx ? &dev->HaltAllCount : &dev->HaltNonContext0Count; -+ -+ if (--(*runCount) == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ } -+ ctxt->OthersState = CTXT_OTHERS_RUNNING; -+ -+ PRINTF0 (ctxt, DBG_SWAP, "HaltSwapContext: no more reason to swap -> others_running\n"); -+ -+ kcondvar_wakeupall (&ctxt->Wait, &dev->IntrLock); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return; -+ } -+ -+ /* -+ * Capture all other processors since we're not being responsive to -+ * the command processor interrupt. -+ */ -+ CAPTURE_CPUS(); -+ -+ if (SysCntx) -+ { -+ FPtr = read_reg32 (dev, TProc_SysCntx_FPtr); -+ BPtr = read_reg32 (dev, TProc_SysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxThreadQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxThreadQueue[E3_SysCntxQueueSize-1]); -+ } -+ else -+ { -+ FPtr = read_reg32 (dev, TProc_NonSysCntx_FPtr); -+ BPtr = read_reg32 (dev, TProc_NonSysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxThreadQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxThreadQueue[E3_NonSysCntxQueueSize-1]); -+ } -+ -+ while (FPtr != BPtr) -+ { -+ elan3_sdram_copyq_from_sdram (dev, FPtr, (void *) &thread, sizeof (E3_ThreadQueue_BE)); -+ -+ if (thread.s.Context == ctxt->Capability.cap_mycontext) -+ { -+ if (ELAN3_QUEUE_FULL (ctxt->SwapThreadQ)) -+ break; -+ -+ *ELAN3_QUEUE_BACK(ctxt->SwapThreadQ, ctxt->SwapThreads) = thread.s.Thread; -+ ELAN3_QUEUE_ADD (ctxt->SwapThreadQ); -+ -+ /* -+ * Remove this entry from the queue by replacing it with -+ * the "magic" thread value. -+ * -+ * NOTE: we must preserve the SYS_CONTEXT_BIT since the Elan uses this -+ * to mark the approriate run queue as empty. -+ */ -+ thread.s.Context = SysCntx ? SYS_CONTEXT_BIT : 0; -+ thread.s.Thread = VanishingStackPointer; -+ -+ elan3_sdram_copyq_to_sdram (dev, (void *) &thread, FPtr, sizeof (E3_ThreadQueue_BE)); -+ } -+ -+ FPtr = (FPtr == Top) ? Base : FPtr + sizeof (E3_ThreadQueue); -+ } -+ -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc.s.FSR)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData1.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData2.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData3.s.FSR.Status)) == 0); -+ -+ if (SysCntx) -+ { -+ FPtr = read_reg32 (dev, DProc_SysCntx_FPtr); -+ BPtr = read_reg32 (dev, DProc_SysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[E3_SysCntxQueueSize-1]); -+ } -+ else -+ { -+ FPtr = read_reg32 (dev, DProc_NonSysCntx_FPtr); -+ BPtr = read_reg32 (dev, DProc_NonSysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxDmaQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxDmaQueue[E3_NonSysCntxQueueSize-1]); -+ } -+ -+ while (FPtr != BPtr) -+ { -+ elan3_sdram_copyq_from_sdram (dev, FPtr, &dma, sizeof (E3_DMA_BE)); -+ -+ if (dma.s.dma_u.s.Context == ctxt->Capability.cap_mycontext) -+ { -+ if (ELAN3_QUEUE_FULL (ctxt->SwapDmaQ)) -+ break; -+ -+ *ELAN3_QUEUE_BACK (ctxt->SwapDmaQ, ctxt->SwapDmas) = dma; -+ ELAN3_QUEUE_ADD (ctxt->SwapDmaQ); -+ -+ /* -+ * Remove the DMA from the queue by replacing it with one with -+ * zero size and no events. -+ * -+ * NOTE: we must preserve the SYS_CONTEXT_BIT since the Elan uses this -+ * to mark the approriate run queue as empty. -+ */ -+ dma.s.dma_type = ((SysCntx ? SYS_CONTEXT_BIT : 0) << 16); -+ dma.s.dma_size = 0; -+ dma.s.dma_source = (E3_Addr) 0; -+ dma.s.dma_dest = (E3_Addr) 0; -+ dma.s.dma_destCookieVProc = (E3_Addr) 0; -+ dma.s.dma_srcEvent = (E3_Addr) 0; -+ dma.s.dma_srcCookieVProc = (E3_Addr) 0; -+ -+ elan3_sdram_copyq_to_sdram (dev, &dma, FPtr, sizeof (E3_DMA_BE)); -+ } -+ -+ FPtr = (FPtr == Top) ? Base : FPtr + sizeof (E3_DMA); -+ } -+ -+ /* -+ * Release the other processors now before signalling the LWP. -+ */ -+ RELEASE_CPUS(); -+ -+ if (! ELAN3_QUEUE_FULL (ctxt->SwapDmaQ) && !ELAN3_QUEUE_FULL (ctxt->SwapThreadQ)) -+ { -+ /* -+ * We've compleletly emptied the elan queues of items in this -+ * context, so we now mark it as fully swapped out. -+ */ -+ if (ctxt->OthersState == CTXT_OTHERS_HALTING_MORE) -+ { -+ runCount = SysCntx ? &dev->HaltAllCount : &dev->HaltNonContext0Count; -+ -+ if (--(*runCount) == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ } -+ PRINTF0 (ctxt, DBG_SWAP, "HaltSwapContext: queues emptied -> others_swapping\n"); -+ -+ ctxt->OthersState = CTXT_OTHERS_SWAPPING; -+ kcondvar_wakeupall (&ctxt->Wait, &dev->IntrLock); -+ } -+ else -+ { -+ if (ctxt->OthersState == CTXT_OTHERS_HALTING) -+ { -+ runCount = SysCntx ? &dev->HaltAllCount : &dev->HaltNonContext0Count; -+ -+ if ((*runCount)++ == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ } -+ PRINTF0 (ctxt, DBG_SWAP, "HaltSwapContext: queues not emptied -> others_swapping_more\n"); -+ -+ ctxt->OthersState = CTXT_OTHERS_SWAPPING_MORE; -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+void -+UnloadCommandPageMapping (ELAN3_CTXT *ctxt) -+{ -+ /* -+ * Unload the Elan translations, and flag the main processor to stall after -+ * issueing its next command. -+ */ -+ if (ctxt->CommandPageMapping != NULL && (ctxt->Status & CTXT_COMMAND_MAPPED_ELAN)) -+ { -+ ELAN3MMU_RGN *rgn = elan3mmu_rgnat_main (ctxt->Elan3mmu, ctxt->CommandPageMapping); -+ -+ if (rgn != NULL) -+ { -+ E3_Addr eaddr = rgn->rgn_ebase + (ctxt->CommandPageMapping - rgn->rgn_mbase); -+ -+ PRINTF1 (ctxt, DBG_INTR, "UnloadCommandPageMapping: unmapping command port at addr %08x\n", eaddr); -+ -+ elan3mmu_unload (ctxt->Elan3mmu, eaddr, PAGESIZE, PTE_UNLOAD); -+ } -+ -+ ctxt->Status &= ~CTXT_COMMAND_MAPPED_ELAN; -+ } -+} -+ -+void -+StartSwapoutContext (ELAN3_CTXT *ctxt, E3_uint32 Pend, E3_uint32 *Maskp) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int SysCntx = (ctxt->Capability.cap_mycontext & SYS_CONTEXT_BIT); -+ u_int *runCount; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ PRINTF2 (ctxt, DBG_SWAP, "StartSwapoutContext: Status %x OthersState %s\n", -+ ctxt->Status, OthersStateStrings [ctxt->OthersState]); -+ /* -+ * Disable the inputters, we should already have a reason for it. -+ */ -+ SetInputterStateForContext (ctxt, Pend, Maskp); -+ -+ UnloadCommandPageMapping (ctxt); -+ -+ /* -+ * Flag main processor to stall after issueing next command -+ */ -+ PRINTF1 (ctxt, DBG_SWAP, "StartSwapoutContext: setting Command Flag at %p to 1\n", &ctxt->FlagPage->CommandFlag); -+ -+ ctxt->FlagPage->CommandFlag = 1; -+ -+ PRINTF1 (ctxt, DBG_SWAP, "StartSwapoutContext: OthersState=%d\n", ctxt->OthersState); -+ -+ /* -+ * And queue a haltop to stop the queues and clear it out. -+ */ -+ switch (ctxt->OthersState) -+ { -+ case CTXT_OTHERS_RUNNING: -+ PRINTF0 (ctxt, DBG_SWAP, "StartSwapoutContext: -> others_halting\n"); -+ -+ ctxt->OthersState = CTXT_OTHERS_HALTING; -+ -+ QueueHaltOperation (dev, Pend, Maskp, INT_DProcHalted | INT_TProcHalted, HaltSwapContext, ctxt); -+ break; -+ -+ case CTXT_OTHERS_SWAPPING: -+ PRINTF0 (ctxt, DBG_SWAP, "StartSwapoutContext: -> others_swapping_more\n"); -+ ctxt->OthersState = CTXT_OTHERS_SWAPPING_MORE; -+ -+ runCount = SysCntx ? &dev->HaltAllCount : &dev->HaltNonContext0Count; -+ -+ if ((*runCount)++ == 0) -+ SetSchedStatusRegister (dev, Pend, Maskp); -+ break; -+ default: -+ PRINTF1 (ctxt, DBG_SWAP, "StartSwapoutContext: OthersState=%d\n", ctxt->OthersState); -+ break; -+ } -+} -+ -+#if defined(DIGITAL_UNIX) -+/* temporary tweaks to priority bump */ -+int lwp_do_prio = 1; -+int lwp_do_nxm = 1; -+int lwp_prio = BASEPRI_USER-1; -+#elif defined(LINUX) -+/* This is the default nice level for the helper LWP */ -+int LwpNice = -1; -+#endif -+ -+int -+elan3_lwp (ELAN3_CTXT *ctxt) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ unsigned long flags; -+ -+ PRINTF1 (ctxt, DBG_LWP, "elan3_lwp: started, context 0x%x\n", ctxt->Capability.cap_mycontext); -+ -+#if defined(DIGITAL_UNIX) -+ { -+ thread_t mythread = current_thread(); -+ if (lwp_do_prio && (lwp_do_nxm || !IS_NXM_TASK(mythread->task))) -+ { -+ mythread->priority = mythread->sched_pri = lwp_prio; -+ mythread->max_priority = BASEPRI_HIGHEST; -+ (void) thread_priority(mythread, lwp_prio, 0, 1); -+ } -+ } -+#elif defined(LINUX) -+ { -+ /* Do the priority trick for the helper LWP so that it -+ * runs in preferance to the user threads which may be -+ * burning CPU waiting for a trap to be fixed up -+ */ -+#ifdef NO_O1_SCHED -+ if (LwpNice >= -20 && LwpNice < 20) -+ current->nice = LwpNice; -+#else -+ set_user_nice(current, LwpNice); -+#endif -+ } -+#endif -+ -+ elan3_swapin (ctxt, CTXT_NO_LWPS); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ /* If we're swapped out, and not detached (or exiting) then wait until we're swapped back in */ -+ /* since otherwise we could "spin" forever continually calling elan3_lwp() */ -+ if ((ctxt->Status & CTXT_SWAPPED_REASONS) && ! (ctxt->Status & (CTXT_DETACHED|CTXT_EXITING))) -+ kcondvar_waitsig (&ctxt->Wait, &dev->IntrLock, &flags); -+ -+ for (;;) -+ { -+#if defined(DIGITAL_UNIX) -+ if (thread_should_halt(current_thread()) || -+ CURSIG_CHECK(task_to_proc(current_thread()->task), u.np_uthread)) -+ { -+ PRINTF1 (ctxt, DBG_LWP, "elan3_lwp: exiting on %s\n", -+ thread_should_halt(current_thread()) ? "halt" : "signal"); -+ break; -+ } -+#endif -+ -+ if (ctxt->Status & CTXT_SWAPPED_REASONS) -+ { -+ PRINTF0 (ctxt, DBG_LWP, "elan3_lwp: exiting on swapped reasons\n"); -+ break; -+ } -+ -+ if (! (ctxt->inhibit)) -+ { -+ if (FixupNetworkErrors (ctxt, &flags) == ESUCCESS && -+ HandleExceptions (ctxt, &flags) == ESUCCESS && -+ RestartContext (ctxt, &flags) == ESUCCESS) -+ { -+ if (kcondvar_waitsig (&ctxt->Wait, &dev->IntrLock, &flags) == 0) -+ { -+ PRINTF0 (ctxt, DBG_LWP, "elan3_lwp: exiting by kcondvar_wait_sig()\n"); -+ break; -+ } -+ } -+ } -+ else -+ { -+ printk("elan3_lwp :: skipping as inhibited\n"); -+ if (kcondvar_waitsig (&ctxt->Wait, &dev->IntrLock, &flags) == 0) -+ { -+ PRINTF0 (ctxt, DBG_LWP, "elan3_lwp: exiting by kcondvar_wait_sig()\n"); -+ break; -+ } -+ } -+ -+ } -+ -+ /* Return EINVAL to elan3_syscall_lwp() when we want it to exit */ -+ res = (ctxt->Status & (CTXT_DETACHED|CTXT_EXITING)) ? EINVAL : 0; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ elan3_swapout (ctxt, CTXT_NO_LWPS); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ FixupNetworkErrors (ctxt, &flags); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+void -+SetInputterStateForContext (ELAN3_CTXT *ctxt, E3_uint32 Pend, E3_uint32 *Maskp) -+{ -+ ELAN3_DEV *dev = NULL; -+ int new_disabled = 0; -+ int ctxnum; -+ -+ ASSERT (ctxt != NULL); -+ dev = ctxt->Device; -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ new_disabled = (ctxt->Input0Trap.State != CTXT_STATE_OK || -+ ctxt->Input1Trap.State != CTXT_STATE_OK || -+ (ctxt->Status & CTXT_INPUTTER_REASONS) != 0); -+ -+ -+ ctxnum = ctxt->Capability.cap_mycontext; -+ -+#ifndef __lock_lint -+ PRINTF2 (ctxt , DBG_IPROC, "SetInputterState: ctxnum %x %s attached\n", ctxnum, ctxt->Disabled ? "disabled " : ""); -+#endif /* __lock_lint */ -+ -+ if (ctxt->Disabled != new_disabled) -+ { -+ PRINTF2 (ctxt, DBG_IPROC, "SetInputterState: ctxnum %x change %s\n", ctxnum, new_disabled ? "enabled to disabled" : "disabled to enabled"); -+ -+ ctxt->Disabled = new_disabled; -+ -+ /* synchronize the context filter for this context */ -+ elan3mmu_set_context_filter (dev, ctxnum, new_disabled, Pend, Maskp); -+ } -+} -+ -+int -+CheckCommandQueueFlushed (ELAN3_CTXT *ctxt, E3_uint32 cflags, int how, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int delay = 1; -+ int i, SeenComQueueEmpty; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ ASSERT (cflags != DmaComQueueNotEmpty || dev->HaltDmaDequeueCount != 0); -+ -+ /* -+ * Flush the command processor queues and poll the queue to see it it empties. -+ */ -+ if (dev->FlushCommandCount++ == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ /* -+ * Ensure previous writes have been flushed through the write buffers -+ */ -+ wmb(); mmiob(); -+ -+ /* -+ * If the command processor traps, or it's taking too long to observe -+ * the queue as emtpy, then we need to force the interrupt handler to -+ * run for us. So queue a halt operation for the dma processor. -+ */ -+ SeenComQueueEmpty = !(read_reg32 (dev, ComQueueStatus) & cflags); -+ for (i = 20; i > 0 || (how & ISSUE_COMMAND_CANT_WAIT); i--) -+ { -+ if (SeenComQueueEmpty || (read_reg32 (dev, Exts.InterruptReg) & (INT_CProc | INT_ComQueue))) -+ break; -+ -+ mb(); -+ DELAY (delay); -+ -+ if ((delay <<= 1) == 0) delay = 1; -+ -+ SeenComQueueEmpty = !(read_reg32 (dev, ComQueueStatus) & cflags); -+ } -+ -+ if (--dev->FlushCommandCount == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ /* -+ * If we've seen the command queue that we're interested in with nothing in it -+ * and the command processor has not trapped then the commands we've -+ * issued have been successfully processed. -+ */ -+ if (SeenComQueueEmpty && ! (read_reg32 (dev, Exts.InterruptReg) & (INT_CProc | INT_ComQueue))) -+ { -+ PRINTF0 (ctxt, DBG_CMD, "CheckCommandQueueFlushed: observed dma queue empty and command proc not trapped\n"); -+ -+ if (cflags == DmaComQueueNotEmpty && --dev->HaltDmaDequeueCount == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ return (ISSUE_COMMAND_OK); -+ } -+ -+ if ((how & ISSUE_COMMAND_CANT_WAIT) != 0) -+ return (ISSUE_COMMAND_WAIT); -+ -+ /* -+ * Halt the dma processor and wait for it to halt, if the command we've issued has -+ * trapped then the interrupt handler will have moved it to the context structure. -+ */ -+ PRINTF0 (ctxt, DBG_CMD, "CheckCommandQueueFlushed: waiting for dproc to halt\n"); -+ QueueHaltOperation (dev, 0, NULL, INT_DProcHalted, WakeupLwp, ctxt); -+ while (! ctxt->Halted) -+ { -+ PRINTF1 (ctxt, DBG_CMD, "CheckCommandQueueFlushed: waiting for Halted - %d\n", ctxt->Halted); -+ -+ kcondvar_wait (&ctxt->HaltWait, &dev->IntrLock, flags); -+ -+ PRINTF1 (ctxt, DBG_CMD, "CheckCommandQueueFlushed: woken for Halted - %d\n", ctxt->Halted); -+ } -+ ctxt->Halted = 0; -+ -+ PRINTF0 (ctxt, DBG_CMD, "CheckCommandQueueFlushed: dproc halted, checking for trap\n"); -+ -+ if (cflags == DmaComQueueNotEmpty && --dev->HaltDmaDequeueCount == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ return (ELAN3_QUEUE_BACK_EMPTY (ctxt->CommandTrapQ) ? ISSUE_COMMAND_OK : ISSUE_COMMAND_TRAPPED); -+} -+ -+int -+WaitForCommandPort (ELAN3_CTXT *ctxt) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ if (ctxt->Status & CTXT_DETACHED) -+ res = EINVAL; -+ else -+ { -+ if (! ELAN3_QUEUE_EMPTY (ctxt->CommandTrapQ) || (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ ctxt->Status |= CTXT_WAITING_COMMAND; -+ if (CTXT_IS_KERNEL(ctxt)) -+ kcondvar_wait (&ctxt->CommandPortWait, &dev->IntrLock, &flags); -+ else -+ kcondvar_waitsig (&ctxt->CommandPortWait, &dev->IntrLock, &flags); -+ } -+ -+ res = (!ELAN3_QUEUE_EMPTY(ctxt->CommandTrapQ) || (ctxt->Status & CTXT_OTHERS_REASONS)) ? EAGAIN : 0; -+ } -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+static char * -+CommandName (int offset) -+{ -+ switch (offset) -+ { -+ case offsetof (E3_CommandPort, PutDma): return ("PutDma"); -+ case offsetof (E3_CommandPort, GetDma): return ("GetDma"); -+ case offsetof (E3_CommandPort, RunThread): return ("RunThread"); -+ case offsetof (E3_CommandPort, WaitEvent0): return ("WaitEvent0"); -+ case offsetof (E3_CommandPort, WaitEvent1): return ("WaitEvent1"); -+ case offsetof (E3_CommandPort, SetEvent): return ("SetEvent"); -+ default: return ("Bad Command"); -+ } -+} -+ -+int -+IssueCommand (ELAN3_CTXT *ctxt, unsigned cmdoff, E3_Addr value, int cflags) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ if ((! (cflags & ISSUE_COMMAND_FOR_CPROC) && !ELAN3_QUEUE_EMPTY (ctxt->CommandTrapQ)) || (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ /* -+ * Cannot issue commands for non-cproc traps if command port is trapped, -+ * nor if the dma/thread trap queues are full, or we're swapping out -+ */ -+ PRINTF2 (ctxt, DBG_CMD, "IssueCommand: %s %08x -> ISSUE_COMMAND_RETRY\n", -+ CommandName (cmdoff), value); -+ -+ res = ISSUE_COMMAND_RETRY; -+ } -+ else -+ { -+ PRINTF2 (ctxt, DBG_CMD, "IssueCommand: %s %08x -> ISSUE_COMMAND_OK\n", -+ CommandName (cmdoff), value); -+ -+ mb(); /* ensure writes to main memory completed */ -+ writel (value, ctxt->CommandPort + cmdoff); /* issue command */ -+ mmiob(); /* and flush through IO writes */ -+ -+ res = ISSUE_COMMAND_OK; -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+int -+IssueDmaCommand (ELAN3_CTXT *ctxt, E3_Addr value, void *item, int how) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ unsigned long flags; -+ -+ /* -+ * Since we may be issuing a command that could trap, and we're interested in -+ * the outcome, the command port trap resolving code must be locked out. -+ */ -+ kmutex_lock (&ctxt->CmdLock); -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ if ((! (how & ISSUE_COMMAND_FOR_CPROC) && !ELAN3_QUEUE_EMPTY (ctxt->CommandTrapQ)) || (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ PRINTF2 (ctxt, DBG_CMD, "IssueDmaCommand: PutDma %08x [%p] -> ISSUE_COMMAND_RETRY\n", value, item); -+ -+ /* -+ * Cannot issue commands for non-cproc traps if command port is trapped, -+ * nor if the dma/thread trap queues are full, or we're swapping out -+ */ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ kmutex_unlock (&ctxt->CmdLock); -+ return (ISSUE_COMMAND_RETRY); -+ } -+ -+ ASSERT (item == NULL || ctxt->CommandPortItem == NULL); -+ -+ /* -+ * Stop the DMA processor from removing entries from the -+ * command port, and force the command processor to do this. -+ * This means that if a trap occurs then it will be the command -+ * processor that traps. -+ */ -+ if (dev->HaltDmaDequeueCount++ == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ PRINTF2 (ctxt, DBG_CMD, "IssueDmaCommand: PutDma %08x [%p]\n", value, item); -+ -+ /* -+ * Always issue the DMA to the 'write' command, since we've asserted HaltDmaDequeue -+ * the command processor will read the descriptor and transfer it to the run queue. -+ * The command processor looks at the dma_direction field to determine whether it is -+ * a read or a write and whether to alter the dma_souce of the descriptr on the run -+ * queue -+ */ -+ mb(); /* ensure writes to main memory ccompleted */ -+ writel (value, ctxt->CommandPort + offsetof (E3_CommandPort, PutDma)); -+ mmiob(); /* and flush through IO writes */ -+ -+ res = CheckCommandQueueFlushed (ctxt, DmaComQueueNotEmpty, how, &flags); -+ -+ if (res == ISSUE_COMMAND_TRAPPED) -+ { -+ PRINTF2 (ctxt, DBG_CMD, "IssueDmaCommand: PutDma %08x [%p] -> ISSUE_COMMAND_TRAPPED\n", value, item); -+ /* -+ * Remember the item we're issueing so that if the command port traps the item will not -+ * get freed off until the descriptor has been read after the command trap has been fixed -+ * up. -+ */ -+ if (item != NULL) -+ ctxt->CommandPortItem = item; -+ } -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ kmutex_unlock (&ctxt->CmdLock); -+ -+ return (res); -+} -+ -+int -+WaitForDmaCommand (ELAN3_CTXT *ctxt, void *item, int how) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ res = CheckCommandQueueFlushed (ctxt, DmaComQueueNotEmpty, how, &flags); -+ -+ if (res == ISSUE_COMMAND_TRAPPED && item != NULL) -+ ctxt->CommandPortItem = item; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+void -+FixupEventTrap (ELAN3_CTXT *ctxt, int proc, void *trap, E3_uint32 TrapType, E3_FaultSave_BE *FaultSaveArea, int flags) -+{ -+ ASSERT (! CTXT_IS_KERNEL (ctxt)); -+ -+ /* -+ * This code re-issues the part of the set event that trapped. -+ */ -+ switch (TrapType) -+ { -+ case MI_ChainedEventError: -+ ElanException (ctxt, EXCEPTION_CHAINED_EVENT, proc, trap, FaultSaveArea->s.EventAddress); -+ break; -+ -+ -+ case MI_SetEventReadWait: -+ /* -+ * Fault occured on the read for the event location. Just re-issue -+ * setevent using EventAddress in E3_FaultSave -+ */ -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_SetEventReadWait: re-issuing setevent %08x\n", -+ FaultSaveArea->s.EventAddress); -+ -+ ReissueEvent (ctxt, (E3_Addr) FaultSaveArea->s.EventAddress, flags); -+ break; -+ -+ case MI_DoSetEvent: -+ { -+ /* -+ * Fault occured because the block write of a block copy event trapped. -+ * Must grab the event type, source and dest then simulate the block copy and then -+ * perform the set. Once the block copy is started the event location cannot be read -+ * again. -+ */ -+ E3_Event *EventPtr = (E3_Event *) elan3mmu_mainaddr (ctxt->Elan3mmu, FaultSaveArea->s.EventAddress); -+ E3_uint32 EventType = fuword (&EventPtr->ev_Type); -+ -+ /* -+ * Check that the event has the block copy bit -+ * set in it, since we couldn't trap here if it -+ * didn't -+ */ -+ if ((EventType & EV_TYPE_BCOPY) != EV_TYPE_BCOPY) -+ { -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_DoSetEvent: Unexpected type=%x\n", EventType); -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_DoSetEvent: RunEventType %x\n", EventType); -+ -+ if (RunEventType (ctxt, FaultSaveArea, EventType)) -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ -+ break; -+ } -+ -+ case MI_ThreadUpdateNonSysCntxBack: -+ case MI_ThreadUpdateSysCntxBack: -+ { -+ /* -+ * Fault occured because the block write of a block copy event trapped. -+ * Must grab the event type, source and dest then simulate the block copy and then -+ * run the thread. Once the block copy is started the event location cannot be read -+ * again. -+ */ -+ E3_Event *EventPtr = (E3_Event *) elan3mmu_mainaddr (ctxt->Elan3mmu, FaultSaveArea->s.EventAddress); -+ E3_uint32 EventType = fuword (&EventPtr->ev_Type); -+ -+ /* -+ * Check for the correct EventPtr type -+ */ -+ if ((EventType & (EV_TYPE_MASK_THREAD|EV_TYPE_MASK_BCOPY)) != (EV_TYPE_BCOPY | EV_TYPE_THREAD)) -+ { -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_ThreadUpdateCntx0Back: Unexpected type=%x for setevent trap. Should be thread\n", EventType); -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_ThreadUpdateCntx0Back: RunEventType %x\n", EventType); -+ if (RunEventType (ctxt, FaultSaveArea, EventType)) -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ case MI_EventIntUpdateBPtr: -+ { -+ /* -+ * Fault occured because the block write of a block copy event trapped. -+ * Must grab the event type, source and dest then simulate the block copy and then -+ * run the dma. Once the block copy is started the event location cannot be read -+ * again. -+ */ -+ E3_Event *EventPtr = (E3_Event *) elan3mmu_mainaddr (ctxt->Elan3mmu, FaultSaveArea->s.EventAddress); -+ E3_uint32 EventType = fuword (&EventPtr->ev_Type); -+ -+ /* -+ * Check for the correct EventPtr type -+ */ -+ if ((EventType & (EV_TYPE_MASK_EVIRQ|EV_TYPE_MASK_BCOPY)) != (EV_TYPE_BCOPY | EV_TYPE_EVIRQ)) -+ { -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_EventIntUpdateBPtr: Unexpected type=%x\n", EventType); -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_EventIntUpdateBPtr: RunEventType %x\n", EventType); -+ if (RunEventType(ctxt, FaultSaveArea, EventType)) -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ case MI_RunDmaDesc: -+ { -+ /* -+ * Fault occured because the block write of a block copy event trapped. -+ * Must grab the event type, source and dest then simulate the block copy and then -+ * run the dma. Once the block copy is started the event location cannot be read -+ * again. -+ */ -+ E3_Event *EventPtr = (E3_Event *) elan3mmu_mainaddr (ctxt->Elan3mmu, FaultSaveArea->s.EventAddress); -+ E3_uint32 EventType = fuword (&EventPtr->ev_Type); -+ -+ /* -+ * Check for the correct EventPtr type -+ */ -+ if ((EventType & (EV_TYPE_MASK_DMA|EV_TYPE_MASK_BCOPY)) != (EV_TYPE_BCOPY | EV_TYPE_DMA)) -+ { -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_RunDmaDesc: Unexpected type=%x\n", EventType); -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_RunDmaDesc: RunEventType %x\n", EventType); -+ if (RunEventType(ctxt, FaultSaveArea, EventType)) -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ case MI_WaitForCntxDmaDescRead: -+ case MI_WaitForNonCntxDmaDescRead: -+ /* -+ * Fault occured on the read of the dma descriptor. Run dma using the -+ * Fault Address in FaultSave. -+ */ -+ PRINTF1 (ctxt, DBG_EVENT, "FixupEventTrap: MI_WaitForCntxDmaDescRead: re-issue dma at %08x\n", FaultSaveArea->s.FaultAddress); -+ -+ RestartDmaPtr (ctxt, FaultSaveArea->s.FaultAddress); -+ break; -+ -+ case MI_FinishedSetEvent: -+ /* -+ * Fault occured because the block write of a block copy event trapped. -+ * Simulate the block copy. -+ */ -+ if (SimulateBlockCopy (ctxt, FaultSaveArea->s.EventAddress)) -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ -+ case MI_BlockCopyEvent: -+ case MI_BlockCopyWaitForReadData: -+ { -+ /* -+ * Fault occured on the read or write of the data for a block copy -+ * event. Simulate the block copy using EventAddress in E3_FaultSave. Must also sample -+ * the event type and then perform a run. -+ */ -+ E3_Event *EventPtr = (E3_Event *) elan3mmu_mainaddr (ctxt->Elan3mmu, FaultSaveArea->s.EventAddress); -+ E3_uint32 EventType = fuword (&EventPtr->ev_Type); -+ -+ PRINTF0 (ctxt, DBG_EVENT, "FixupEventTrap: MI_BlockCopyWaitForReadData: BCopy read fault in BCopy event. Simulating BCopy.\n"); -+ -+ if (RunEventType(ctxt, FaultSaveArea, EventType)) -+ ElanException (ctxt, EXCEPTION_BAD_EVENT, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+ -+ case MI_EventQueueOverflow: -+ case MI_ThreadQueueOverflow: -+ case MI_DmaQueueOverflow: -+ /* XXXX: should handle queue overflow */ -+ PRINTF0 (ctxt, DBG_EVENT, "FixupEventTrap: Queue overflow\n"); -+ -+ ElanException (ctxt, EXCEPTION_QUEUE_OVERFLOW, proc, trap, FaultSaveArea, TrapType); -+ break; -+ -+ default: -+ ElanException (ctxt, EXCEPTION_BUS_ERROR, proc, trap, FaultSaveArea, TrapType); -+ break; -+ } -+} -+ -+int -+SimulateBlockCopy (ELAN3_CTXT *ctxt, E3_Addr EventAddress) -+{ -+ E3_Addr SourcePtrElan; -+ E3_Addr DestPtrElan; -+ unsigned DataType; -+ int i; -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ ElanException (ctxt, EXCEPTION_FAULTED, EVENT_PROC, NULL, EventAddress); -+ return (TRUE); -+ } -+ -+ SourcePtrElan = ELAN3_OP_LOAD32 (ctxt, EventAddress + offsetof (E3_BlockCopyEvent, ev_Source)); -+ DestPtrElan = ELAN3_OP_LOAD32 (ctxt, EventAddress + offsetof (E3_BlockCopyEvent, ev_Dest)); -+ DataType = DestPtrElan & EV_BCOPY_DTYPE_MASK; -+ DestPtrElan &= ~EV_BCOPY_DTYPE_MASK; -+ -+ -+ PRINTF3 (ctxt, DBG_EVENT, "SimulateBlockCopy: Event %08x SourcePtr %08x DestPtr %08x\n", -+ EventAddress, SourcePtrElan, DestPtrElan); -+ -+ if (SourcePtrElan & EV_WCOPY) -+ ELAN3_OP_STORE32 (ctxt, DestPtrElan, SourcePtrElan); -+ else -+ { -+ /* -+ * NOTE: since the block copy could be to sdram, we issue the writes backwards, -+ * except we MUST ensure that the last item in the block is written last. -+ */ -+#if defined(__LITTLE_ENDIAN__) -+ /* -+ * For little endian cpu's we don't need to worry about the data type. -+ */ -+ for (i = E3_BLK_SIZE-(2*sizeof (E3_uint64)); i >= 0; i -= sizeof (E3_uint64)) -+ ELAN3_OP_STORE64 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD64 (ctxt, SourcePtrElan + i)); -+ -+ i = E3_BLK_SIZE - sizeof (E3_uint64); -+ ELAN3_OP_STORE64 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD64 (ctxt, SourcePtrElan + i)); -+#else -+ switch (DataType) -+ { -+ case EV_TYPE_BCOPY_BYTE: -+ for (i = E3_BLK_SIZE-(2*sizeof (E3_uint8)); i >= 0; i -= sizeof (E3_uint8)) -+ ELAN3_OP_STORE8 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD8 (ctxt, SourcePtrElan + i)); -+ -+ i = E3_BLK_SIZE - sizeof (E3_uint8); -+ ELAN3_OP_STORE8 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD8 (ctxt, SourcePtrElan + i)); -+ break; -+ -+ case EV_TYPE_BCOPY_HWORD: -+ for (i = E3_BLK_SIZE-(2*sizeof (E3_uint16)); i >= 0; i -= sizeof (E3_uint16)) -+ ELAN3_OP_STORE16 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD16 (ctxt, SourcePtrElan + i)); -+ -+ i = E3_BLK_SIZE - sizeof (E3_uint16); -+ ELAN3_OP_STORE16 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD16 (ctxt, SourcePtrElan + i)); -+ break; -+ -+ case EV_TYPE_BCOPY_WORD: -+ for (i = E3_BLK_SIZE-(2*sizeof (E3_uint32)); i >= 0; i -= sizeof (E3_uint32)) -+ ELAN3_OP_STORE32 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD32 (ctxt, SourcePtrElan + i)); -+ -+ i = E3_BLK_SIZE - sizeof (E3_uint32); -+ ELAN3_OP_STORE32 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD32 (ctxt, SourcePtrElan + i)); -+ break; -+ -+ case EV_TYPE_BCOPY_DWORD: -+ for (i = E3_BLK_SIZE-(2*sizeof (E3_uint64)); i >= 0; i -= sizeof (E3_uint64)) -+ ELAN3_OP_STORE64 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD64 (ctxt, SourcePtrElan + i)); -+ -+ i = E3_BLK_SIZE - sizeof (E3_uint64); -+ ELAN3_OP_STORE64 (ctxt, DestPtrElan + i, ELAN3_OP_LOAD64 (ctxt, SourcePtrElan + i)); -+ break; -+ } -+#endif -+ } -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ return (FALSE); -+} -+ -+void -+ReissueEvent (ELAN3_CTXT *ctxt, E3_Addr addr, int flags) -+{ -+ PRINTF1 (ctxt, DBG_CMD, "ReissueEvent : Event=%08x\n", addr); -+ -+ if (IssueCommand (ctxt, offsetof (E3_CommandPort, SetEvent), addr, flags) == ISSUE_COMMAND_RETRY) -+ { -+ PRINTF1 (ctxt, DBG_CMD, "ReissueEvent: queue event %08x\n", addr); -+ -+ kmutex_lock (&ctxt->SwapListsLock); -+ ctxt->ItemCount[LIST_SETEVENT]++; -+ ELAN3_OP_PUT_WORD_ITEM (ctxt, LIST_SETEVENT, addr); -+ kmutex_unlock (&ctxt->SwapListsLock); -+ } -+} -+ -+int -+SetEventsNeedRestart (ELAN3_CTXT *ctxt) -+{ -+ return (ctxt->ItemCount[LIST_SETEVENT] != 0); -+} -+ -+void -+RestartSetEvents (ELAN3_CTXT *ctxt) -+{ -+ void *item; -+ E3_uint32 EventPointer; -+ -+ kmutex_lock (&ctxt->SwapListsLock); -+ -+ while (ctxt->ItemCount[LIST_SETEVENT]) -+ { -+ if (! ELAN3_OP_GET_WORD_ITEM (ctxt, LIST_SETEVENT, &item, &EventPointer)) -+ ctxt->ItemCount[LIST_SETEVENT] = 0; -+ else -+ { -+ if (IssueCommand (ctxt, offsetof (E3_CommandPort, SetEvent), EventPointer, FALSE) == ISSUE_COMMAND_RETRY) -+ { -+ ELAN3_OP_PUTBACK_ITEM (ctxt, LIST_SETEVENT, item); -+ kmutex_unlock (&ctxt->SwapListsLock); -+ return; -+ } -+ -+ ctxt->ItemCount[LIST_SETEVENT]--; -+ ELAN3_OP_FREE_WORD_ITEM (ctxt, item); -+ } -+ } -+ kmutex_unlock (&ctxt->SwapListsLock); -+} -+ -+int -+RunEventType(ELAN3_CTXT *ctxt, E3_FaultSave_BE *FaultSaveArea, E3_uint32 EventType) -+{ -+ int failed = FALSE; -+ -+ if ((EventType & EV_TYPE_BCOPY) != 0) -+ failed = SimulateBlockCopy(ctxt, FaultSaveArea->s.EventAddress); -+ -+ if ((EventType & EV_TYPE_MASK) == EV_TYPE_THREAD) -+ ReissueStackPointer (ctxt, EventType & ~(EV_TYPE_MASK_THREAD|EV_TYPE_MASK_BCOPY)); -+ else if ((EventType & EV_TYPE_MASK) == EV_TYPE_DMA) -+ RestartDmaPtr (ctxt, EventType & ~(EV_TYPE_MASK_DMA|EV_TYPE_MASK_BCOPY)); -+ else if ((EventType & EV_TYPE_EVIRQ) != 0) -+ QueueEventInterrupt (ctxt, EventType & ~(EV_TYPE_MASK_EVIRQ|EV_TYPE_MASK_BCOPY)); -+ else /* Chained event */ -+ { -+ if ((EventType & ~EV_TYPE_BCOPY) != 0) /* not null setevent */ -+ ReissueEvent (ctxt, EventType & ~(EV_TYPE_MASK_CHAIN|EV_TYPE_MASK_BCOPY), FALSE); -+ } -+ -+ return (failed); -+} -+ -+void -+WakeupLwp (ELAN3_DEV *dev, void *arg) -+{ -+ ELAN3_CTXT *ctxt = (ELAN3_CTXT *) arg; -+ unsigned long flags; -+ -+ PRINTF1 (ctxt, DBG_INTR, "WakeupLwp: %d\n", SPINLOCK_HELD (&dev->IntrLock)); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ ctxt->Halted = 1; -+ kcondvar_wakeupone (&ctxt->HaltWait, &dev->IntrLock); -+ -+ PRINTF0 (ctxt, DBG_INTR, "WakeupLwp: woken up context\n"); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+void -+QueueEventInterrupt (ELAN3_CTXT *ctxt, E3_uint32 cookie) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ unsigned long flags; -+ -+ PRINTF1 (ctxt, DBG_EVENT, "QueueEventInterrupt: cookie %08x\n", cookie); -+ -+ if (ELAN3_OP_EVENT (ctxt, cookie, OP_INTR) == OP_DEFER) -+ { -+ spin_lock_irqsave (&ctxt->Device->IntrLock, flags); -+ -+ if (ELAN3_QUEUE_REALLY_FULL (ctxt->EventCookieQ)) -+ { -+ ctxt->Status |= CTXT_COMMAND_OVERFLOW_ERROR; -+ StartSwapoutContext (ctxt, 0, NULL); -+ } -+ else -+ { -+ *(ELAN3_QUEUE_BACK (ctxt->EventCookieQ, ctxt->EventCookies)) = cookie; -+ -+ ELAN3_QUEUE_ADD (ctxt->EventCookieQ); -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ if (ELAN3_QUEUE_FULL (ctxt->EventCookieQ)) -+ { -+ ctxt->Status |= CTXT_EVENT_QUEUE_FULL; -+ StartSwapoutContext (ctxt, 0, NULL); -+ } -+ } -+ spin_unlock_irqrestore (&ctxt->Device->IntrLock, flags); -+ } -+} -+ -+int -+ElanException (ELAN3_CTXT *ctxt, int type, int proc, void *trap, ...) -+{ -+ int res; -+ va_list ap; -+ -+ va_start (ap, trap); -+ -+ PRINTF2 (ctxt, DBG_FN, "ElanException: proc %d type %d\n", proc, type); -+ -+ res = ELAN3_OP_EXCEPTION (ctxt, type, proc, trap, ap); -+ -+ va_end (ap); -+ -+ return (res); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/context_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/context_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/context_linux.c 2005-06-01 23:12:54.566444120 -0400 -@@ -0,0 +1,228 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: context_linux.c,v 1.28.2.2 2004/10/28 11:54:56 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/context_linux.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int -+LoadElanTranslation (ELAN3_CTXT *ctxt, E3_Addr addr, int len, int protFault, int writeable) -+{ -+ ELAN3MMU *elan3mmu = ctxt->Elan3mmu; -+ ELAN3MMU_RGN *rgn; -+ caddr_t mainAddr; -+ int perm; -+ unsigned int off; -+ unsigned long flags; -+ -+ ASSERT (PAGE_ALIGNED (addr) && PAGE_ALIGNED (len)); -+ -+ PRINTF (ctxt, DBG_FAULT, "LoadElanTranslation: addr %08x len %08x%s%s\n", -+ addr, len, protFault ? " prot fault" : "", writeable ? " writeable" : ""); -+ -+ /* Ensure there's enough elan mmu tables for us to use */ -+ elan3mmu_expand (elan3mmu, addr, len, PTBL_LEVEL_3, 0); -+ -+ while (len > 0) -+ { -+ /* -+ * Retrieve permission region and calculate main address -+ */ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ -+ rgn = elan3mmu_rgnat_elan (elan3mmu, addr); -+ if (rgn == NULL) { -+ PRINTF (ctxt, DBG_FAULT, "LoadElanTranslation: no permission region at %lx %p\n", -+ (u_long) addr, rgn); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ return (EFAULT); -+ } -+ mainAddr = rgn->rgn_mbase + (addr - rgn->rgn_ebase); -+ -+ ASSERT (PAGE_ALIGNED ((unsigned long)mainAddr)); -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ /* -+ * If we're tying to load a translation to the elan command port, -+ * then don't do it now, but mark the context to have it reloaded -+ * just before we restart any threads. We do this because we don't -+ * want to call into the segment driver since we could then block -+ * waiting for the command port to become available. -+ */ -+ if (mainAddr == ctxt->CommandPageMapping) -+ { -+ PRINTF (ctxt, DBG_FAULT, "LoadElanTranslation: addr=%08x maps command port\n", addr); -+ -+ spin_lock_irqsave (&ctxt->Device->IntrLock, flags); -+ UnloadCommandPageMapping (ctxt); -+ spin_unlock_irqrestore (&ctxt->Device->IntrLock, flags); -+ } -+ else -+ { -+ struct vm_area_struct *area; -+ struct mm_struct *mm = current->mm; -+ pte_t *ptep_ptr; -+ pte_t ptep_value; -+ -+ down_read (¤t->mm->mmap_sem); -+ -+ if ((area = find_vma_intersection(mm, (unsigned long)mainAddr, (unsigned long)mainAddr + PAGESIZE)) == NULL) -+ { -+ PRINTF (ctxt, DBG_FAULT, "LoadElanTranslation: %p no vma\n", mainAddr); -+ up_read (¤t->mm->mmap_sem); -+ return EFAULT; -+ } -+ -+ if (writeable && !(area->vm_flags & VM_WRITE)) -+ { -+ PRINTF (ctxt, DBG_FAULT, "LoadElanTranslation: %p not writeable\n", mainAddr); -+ up_read (¤t->mm->mmap_sem); -+ return EFAULT; -+ } -+ -+ spin_lock (&mm->page_table_lock); -+ -+ /* dont deference the pointer after the unmap */ -+ ptep_ptr = find_pte_map (mm, (unsigned long)mainAddr); -+ if (ptep_ptr) { -+ ptep_value = *ptep_ptr; -+ pte_unmap(ptep_ptr); -+ } -+ -+ PRINTF (ctxt, DBG_FAULT, "LoadElanTranslation: %p %s %s\n", -+ mainAddr, writeable ? "writeable" : "readonly", -+ !ptep_ptr ? "invalid" : pte_none(ptep_value) ? "none " : !pte_present(ptep_value) ? "swapped " : -+ writeable && !pte_write(ptep_value) ? "COW" : "OK"); -+ -+ if (!ptep_ptr || pte_none(ptep_value) || !pte_present(ptep_value) || (writeable && !pte_write(ptep_value))) -+ { -+ spin_unlock (&mm->page_table_lock); -+ -+ make_pages_present((unsigned long)mainAddr, (unsigned long)mainAddr + PAGE_SIZE); -+ -+ spin_lock (&mm->page_table_lock); -+ -+ /* dont deference the pointer after the unmap */ -+ ptep_ptr = find_pte_map (mm, (unsigned long)mainAddr); -+ if (ptep_ptr) { -+ ptep_value = *ptep_ptr; -+ pte_unmap(ptep_ptr); -+ } -+ -+ if (!ptep_ptr || pte_none(ptep_value) || !pte_present(ptep_value) || (writeable && !pte_write(ptep_value))) -+ { -+ spin_unlock (&mm->page_table_lock); -+ up_read (¤t->mm->mmap_sem); -+ return EFAULT; -+ } -+ } -+ -+ /* don't allow user write access to kernel pages if not kernel */ -+ if (!pte_read(ptep_value)) -+ { -+ spin_unlock (&mm->page_table_lock); -+ up_read (¤t->mm->mmap_sem); -+ return EFAULT; -+ } -+ -+ if (writeable) -+ pte_mkdirty(ptep_value); -+ pte_mkyoung (ptep_value); -+ -+ /* now load the elan pte */ -+ if (writeable) -+ perm = rgn->rgn_perm; -+ else -+ perm = ELAN3_PERM_READONLY(rgn->rgn_perm & ELAN3_PTE_PERM_MASK) | (rgn->rgn_perm & ~ELAN3_PTE_PERM_MASK); -+ -+ for (off = 0; off < PAGE_SIZE; off += ELAN3_PAGE_SIZE) -+ elan3mmu_pteload (elan3mmu, PTBL_LEVEL_3, addr + off, pte_phys(ptep_value) + off, perm, PTE_LOAD | PTE_NO_SLEEP); -+ -+ spin_unlock (&mm->page_table_lock); -+ up_read (¤t->mm->mmap_sem); -+ } -+ -+ len -= PAGESIZE; -+ addr += PAGESIZE; -+ } -+ return (ESUCCESS); -+} -+ -+ -+/* -+ * LoadCommandPortTranslation: -+ * explicitly load an elan translation to the command port. -+ * but only do it if the command port is accessible. -+ * -+ * we call this function just after we have restarted -+ * and trapped commands, since when a command traps -+ * the elan translation to the command port is unloaded. -+ */ -+void -+LoadCommandPortTranslation (ELAN3_CTXT *ctxt) -+{ -+ ELAN3MMU *elan3mmu = ctxt->Elan3mmu; -+ ELAN3MMU_RGN *rgn; -+ E3_Addr addr; -+ int perm; -+ physaddr_t phys; -+ unsigned int off; -+ unsigned long flags; -+ -+ PRINTF (ctxt, DBG_FAULT, "LoadCommandPortTranslation: SegAddr=%p Status=%x\n", ctxt->CommandPageMapping, ctxt->Status); -+ -+ if (ctxt->CommandPageMapping != NULL && !(ctxt->Status & CTXT_COMMAND_MAPPED_ELAN)) -+ { -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ -+ rgn = elan3mmu_rgnat_main (elan3mmu, ctxt->CommandPageMapping); -+ if (rgn == (ELAN3MMU_RGN *) NULL) -+ { -+ PRINTF(ctxt, DBG_FAULT, "LoadCommandPortTranslation: no permission for command port\n"); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ return; -+ } -+ -+ addr = rgn->rgn_ebase + (ctxt->CommandPageMapping - rgn->rgn_mbase); -+ perm = rgn->rgn_perm; -+ phys = kmem_to_phys((caddr_t) ctxt->CommandPage); -+ -+ spin_lock_irqsave (&ctxt->Device->IntrLock, flags); -+ if (ELAN3_QUEUE_EMPTY(ctxt->CommandTrapQ) && !(ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ PRINTF(ctxt, DBG_FAULT, "LoadCommandPortTranslation: load xlation addr=%08x phys=%llx perm=%d\n", -+ addr, (unsigned long long)phys, perm); -+ -+ ctxt->Status |= CTXT_COMMAND_MAPPED_ELAN; -+ -+ for (off = 0; off < PAGESIZE; off += ELAN3_PAGE_SIZE) -+ elan3mmu_pteload (elan3mmu, PTBL_LEVEL_3, addr + off, phys + off, perm, PTE_LOAD | PTE_NO_SLEEP); -+ } -+ spin_unlock_irqrestore (&ctxt->Device->IntrLock, flags); -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ } -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/cproc.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/cproc.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/cproc.c 2005-06-01 23:12:54.567443968 -0400 -@@ -0,0 +1,539 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: cproc.c,v 1.46 2004/02/10 15:05:10 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/cproc.c,v $ */ -+ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+void -+HandleCProcTrap (ELAN3_DEV *dev, E3_uint32 Pend, E3_uint32 *Maskp) -+{ -+ E3_FaultSave_BE FaultSave; -+ CProcTrapBuf_BE TrapBuf; -+ COMMAND_TRAP *trap; -+ ELAN3_CTXT *ctxt; -+ sdramaddr_t CurrTrap; -+ sdramaddr_t LastTrapAddr; -+ int NTrapEntries; -+ int NewPend; -+ unsigned long flags; -+ -+ /* -+ * Temporarily mask out the command processor interrupt, since -+ * we may cause it be re-asserted when we re-issue the commands -+ * from the overflow queue area. -+ */ -+ DISABLE_INT_MASK (dev, INT_CProc | INT_ComQueue); -+ -+ NewPend = read_reg32 (dev, Exts.InterruptReg); -+ -+ do { -+ if (NewPend & INT_ComQueue) -+ { -+ if ((read_reg32 (dev, ComQueueStatus) & ComQueueError) != 0) -+ { -+ printk ("elan%d: InterruptReg=%x ComQueueStatus=%x\n", dev->Instance, -+ read_reg32 (dev, Exts.InterruptReg), read_reg32 (dev, ComQueueStatus)); -+ panic ("elan: command queue has overflowed !!"); -+ /* NOTREACHED */ -+ } -+ -+ BumpStat (dev, ComQueueHalfFull); -+ -+ /* -+ * Capture the other cpus and stop the threads processor then -+ * allow the command processor to eagerly flush the command queue. -+ */ -+ dev->FlushCommandCount++; dev->HaltThreadCount++; -+ SetSchedStatusRegister (dev, Pend, Maskp); -+ -+ CAPTURE_CPUS(); -+ -+ while ((read_reg32 (dev, ComQueueStatus) & ComQueueNotEmpty) != 0) -+ mb(); -+ -+ /* -+ * Let the threads processor run again, and release the cross call. -+ */ -+ RELEASE_CPUS(); -+ -+ dev->FlushCommandCount--; dev->HaltThreadCount--; -+ SetSchedStatusRegister (dev, Pend, Maskp); -+ -+ /* -+ * Re-sample the interrupt register to see if the command processor -+ * has trapped while flushing the queue. Preserve the INT_ComQueue -+ * bit, so we can clear the ComQueueStatus register later. -+ */ -+ NewPend = (read_reg32 (dev, Exts.InterruptReg) | INT_ComQueue); -+ } -+ -+ CurrTrap = dev->CommandPortTraps[dev->CurrentCommandPortTrap]; -+ -+ if (NewPend & INT_CProc) -+ { -+ BumpStat (dev, CProcTraps); -+ -+ /* -+ * Copy the MMU Fault Save area and zero it out for future traps. -+ */ -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, CProc), &FaultSave, sizeof (E3_FaultSave)); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, CProc), sizeof (E3_FaultSave)); -+ -+ /* -+ * First entry in the cproc trap save area is the value of Areg and Breg for the -+ * uWord before the address fault. -+ */ -+ TrapBuf.Align64 = elan3_sdram_readq (dev, CurrTrap); CurrTrap += sizeof (TrapBuf.Align64); -+ -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, (TrapBuf.r.Breg >> 16)); -+ if (ctxt == NULL) -+ { -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "HandleCProcTrap: context invalid [%08x.%08x]\n", TrapBuf.r.Areg, TrapBuf.r.Breg); -+ BumpStat (dev, InvalidContext); -+ } -+ else -+ { -+ if (ELAN3_QUEUE_REALLY_FULL (ctxt->CommandTrapQ)) -+ { -+ if ((ctxt->Status & CTXT_COMMAND_OVERFLOW_ERROR) == 0) -+ { -+ ctxt->Status |= CTXT_COMMAND_OVERFLOW_ERROR; -+ StartSwapoutContext (ctxt, Pend, Maskp); -+ } -+ } -+ else -+ { -+ trap = ELAN3_QUEUE_BACK (ctxt->CommandTrapQ, ctxt->CommandTraps); -+ -+ trap->FaultSave = FaultSave; -+ trap->Status.Status = read_reg32 (dev, Exts.CProcStatus.Status); -+ trap->TrapBuf = TrapBuf; -+ -+ /* -+ * The command processor does not stop after it has trapped. It will continue -+ * to save commands for other contexts into the commands port save area. -+ * The valid context for the trap is held in FaultSave. As some of this -+ * trap code uses the context in the status register the local copy must be -+ * updated with the trap context. -+ */ -+ trap->Status.s.Context = (TrapBuf.r.Breg >> 16); -+ -+ PRINTF4 (ctxt, DBG_INTR, "HandleCProcTrap: WakeupFnt=%x Cntx=%x SuspAddr=%x TrapType=%s\n", -+ trap->Status.s.WakeupFunction, trap->Status.s.Context, -+ trap->Status.s.SuspendAddr, MiToName(trap->Status.s.TrapType)); -+ PRINTF2 (ctxt, DBG_INTR, "HandleCProcTrap: Areg=%08x Breg=%08x\n", -+ trap->TrapBuf.r.Areg, trap->TrapBuf.r.Breg); -+ -+ if (ELAN3_OP_CPROC_TRAP (ctxt, trap) == OP_DEFER) -+ { -+ ELAN3_QUEUE_ADD (ctxt->CommandTrapQ); -+ -+ PRINTF1 (ctxt, DBG_INTR, "HandleCProcTrap: setting Command Flag at %p to 1\n", &ctxt->FlagPage->CommandFlag); -+ -+ ctxt->FlagPage->CommandFlag = 1; -+ -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ } -+ } -+ -+ UnloadCommandPageMapping (ctxt); -+ } -+ } -+ -+ /* -+ * Now change the CommandPortTrap queue. -+ * Must stop the command processor, wait for it to stop, find the final -+ * entry in the current cproc trap save area, reset the comm port -+ * trap save address to the other queue, clear the command port interrupt and -+ * set it running normally again, and then let it go again. This is not very -+ * time critical but it would be a good idea to prevent a higher priority -+ * interrupt from slowing down the process to prevent to fifos filling. -+ */ -+ spin_lock_irqsave (&dev->CProcLock, flags); -+ -+ SET_SCHED_STATUS (dev, CProcStop); -+ -+ while ((read_reg32 (dev, Exts.SchCntReg) & CProcStopped) == 0) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "HandleCProcTrap: waiting for command processor to stop\n"); -+ mb(); -+ } -+ -+ /* -+ * Remember how many entries are in the saved command queue, and -+ * re-initialise it, before restarting the command processor. -+ */ -+ NTrapEntries = (read_reg32 (dev, CProc_TrapSave_Addr) - dev->CommandPortTraps[dev->CurrentCommandPortTrap])/sizeof (E3_uint64); -+ LastTrapAddr = dev->CommandPortTraps[dev->CurrentCommandPortTrap] + NTrapEntries*sizeof (TrapBuf); -+ -+ dev->CurrentCommandPortTrap ^= 1; -+ write_reg32 (dev, CProc_TrapSave_Addr, dev->CommandPortTraps[dev->CurrentCommandPortTrap]); -+ -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "HandleCProcTrap: command trap queue has %d entries\n", NTrapEntries); -+ -+ if (NTrapEntries > ELAN3_COMMAND_TRAP_SIZE/sizeof (E3_uint64)) -+ panic ("HandleCProcTrap: command trap queue has overflowed\n"); -+ -+ if (NewPend & INT_CProc) -+ { -+ /* -+ * Clear the CProc interrupt and set it running normally again. Nothing should -+ * be running now that could issue commands apart from this trap handler. -+ */ -+ PULSE_SCHED_STATUS (dev, RestartCProc); -+ } -+ -+ if (NewPend & INT_ComQueue) -+ { -+ /* -+ * Write any value here to clear out the half full and error bits of the command -+ * overflow queues. This will also remove the overflow interrupt. -+ */ -+ write_reg32 (dev, ComQueueStatus, 0); -+ } -+ -+ /* -+ * And let the command processor start again -+ */ -+ CLEAR_SCHED_STATUS (dev, CProcStop); -+ -+ /* -+ * Now re-issue all the commands that were issued after the command port trapped. -+ * Should halt the dma processor and force command sto be put onto the run queues -+ * to ensure that a remote re-issued command is handled correctly. NOTE it is -+ * not necessary to wait for the dma processor to stop and this will reduce the -+ * performance impact. As CProcHalt is asserted all commands will be flushed -+ * to the queues. -+ */ -+ dev->HaltDmaDequeueCount++; dev->FlushCommandCount++; -+ SetSchedStatusRegister (dev, Pend, Maskp); -+ -+ /* -+ * XXXX: should we do a capture/release if the trap overflow -+ * area has a "large" number of commands in it, since -+ * we will just stuff them all back in, together with -+ * all those issued by the other cpus/thread processors. -+ */ -+ while (CurrTrap != LastTrapAddr) -+ { -+ /* Read the next saved (but not trapped) command */ -+ TrapBuf.Align64 = elan3_sdram_readq (dev, CurrTrap); CurrTrap += sizeof (TrapBuf); -+ -+ -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, (TrapBuf.s.ContextType >> 16)); -+ -+ if (ctxt == NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "HandleCProcTrap: context %x invalid\n", TrapBuf.s.ContextType >> 16); -+ BumpStat (dev, InvalidContext); -+ } -+ else -+ { -+ if (!ELAN3_QUEUE_EMPTY (ctxt->CommandTrapQ) || (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ PRINTF3 (ctxt, DBG_INTR, "HandleCProcTrap: save command %x context %x - %08x\n", -+ (TrapBuf.s.ContextType>>3) & 0x3ff, TrapBuf.s.ContextType >> 17, TrapBuf.s.Addr); -+ -+ if (ELAN3_QUEUE_REALLY_FULL (ctxt->CommandQ)) -+ { -+ ctxt->Status |= CTXT_COMMAND_OVERFLOW_ERROR; -+ StartSwapoutContext (ctxt, Pend, Maskp); -+ } -+ else -+ { -+ *ELAN3_QUEUE_BACK(ctxt->CommandQ, ctxt->Commands) = TrapBuf; -+ -+ ELAN3_QUEUE_ADD (ctxt->CommandQ); -+ } -+ continue; -+ } -+ -+ /* Reissue the command to the command port for this context */ -+ PRINTF2 (ctxt, DBG_INTR, "HandleCProcTrap: re-issue command %x - %08x\n", -+ (TrapBuf.s.ContextType>>5) & 0xff, TrapBuf.s.Addr); -+ -+ mb(); -+ if (ELAN3_OP_CPROC_REISSUE(ctxt, &TrapBuf) != OP_HANDLED) -+ ((E3_uint32 *) ctxt->CommandPort)[(TrapBuf.s.ContextType>>5) & 0xff] = TrapBuf.s.Addr; -+ mmiob(); -+ } -+ } -+ -+ while ((read_reg32 (dev, ComQueueStatus) & ComQueueNotEmpty) != 0) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "HandleCProcTrap: waiting for queues to empty after reissueing commands\n"); -+ mb(); -+ } -+ -+ dev->HaltDmaDequeueCount--; dev->FlushCommandCount--; -+ SetSchedStatusRegister (dev, Pend, Maskp); -+ -+ spin_unlock_irqrestore (&dev->CProcLock, flags); -+ -+ /* -+ * Re-read the interrupt register and see if we've got another command -+ * port interrupt -+ */ -+ NewPend = read_reg32 (dev, Exts.InterruptReg); -+ } while ((NewPend & (INT_CProc | INT_ComQueue)) != 0); -+ -+ -+ /* -+ * Re-enable the command processor interrupt as we've finished -+ * polling it. -+ */ -+ ENABLE_INT_MASK (dev, INT_CProc | INT_ComQueue); -+} -+ -+void -+ResolveCProcTrap (ELAN3_CTXT *ctxt) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ COMMAND_TRAP *trap; -+ int res; -+ unsigned long flags; -+ -+ kmutex_lock (&ctxt->CmdLock); -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ while (! ELAN3_QUEUE_BACK_EMPTY (ctxt->CommandTrapQ)) -+ { -+ trap = ELAN3_QUEUE_MIDDLE(ctxt->CommandTrapQ, ctxt->CommandTraps); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ switch (trap->Status.s.TrapType) -+ { -+ case MI_EventIntUpdateBPtr: -+ case MI_ChainedEventError: -+ case MI_EventQueueOverflow: -+ case MI_ThreadQueueOverflow: -+ case MI_DmaQueueOverflow: -+ PRINTF1 (ctxt, DBG_CPROC, "ResolveCProcTrap: %s\n", MiToName (trap->Status.s.TrapType)); -+ break; -+ -+ default: -+ /* All other traps are MMU related, we should have a fault address and FSR */ -+ if ((res = elan3_pagefault (ctxt, &trap->FaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_CPROC, "ResolveCProcTrap: elan3_pagefault failed for address %08x\n", -+ trap->FaultSave.s.FaultAddress); -+ ElanException (ctxt, EXCEPTION_INVALID_ADDR, COMMAND_PROC, trap, &trap->FaultSave, res); -+ -+ /* Set the trap type to 0 so the command does not get re-issued */ -+ trap->Status.s.TrapType = 0; -+ } -+ break; -+ } -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ ELAN3_QUEUE_CONSUME (ctxt->CommandTrapQ); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ kmutex_unlock (&ctxt->CmdLock); -+} -+ -+int -+RestartCProcTrap (ELAN3_CTXT *ctxt) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ COMMAND_TRAP trap; -+ void *item; -+ int res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ while (! ELAN3_QUEUE_FRONT_EMPTY (ctxt->CommandTrapQ)) -+ { -+ trap = (*ELAN3_QUEUE_FRONT (ctxt->CommandTrapQ, ctxt->CommandTraps)); -+ ELAN3_QUEUE_REMOVE (ctxt->CommandTrapQ); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ BumpUserStat (ctxt, CProcTraps); -+ -+ switch (trap.Status.s.TrapType) -+ { -+ case 0: -+ res = ISSUE_COMMAND_OK; -+ break; -+ -+ case MI_WaitForWaitEventDesc: -+ /* -+ * Fault occured on the read of wait event descriptor for wait event type 0. -+ * Fault already fixed. Just re-issue the wait command. Wait event descriptor addr -+ * is in the Areg save value. -+ */ -+ PRINTF1 (ctxt, DBG_CPROC, "RestartCProcTrap: WaitEvent type0 desc read fault %08x\n", -+ trap.TrapBuf.r.Areg); -+ -+ res = IssueCommand (ctxt, offsetof (E3_CommandPort, WaitEvent0), trap.TrapBuf.r.Areg, ISSUE_COMMAND_FOR_CPROC); -+ break; -+ -+ case MI_WaitForEventReadTy0: -+ /* -+ * Fault occured on the read of event location for wait event type 0. -+ * Fault already fixed. Just re-issue the wait command. Wait event descriptor addr -+ * is in the Areg save value. -+ */ -+ PRINTF1 (ctxt, DBG_CPROC, "RestartCProcTrap: WaitEvent type0 event loc fault %08x\n", -+ trap.TrapBuf.r.Areg); -+ -+ res = IssueCommand (ctxt, offsetof (E3_CommandPort, WaitEvent0), trap.TrapBuf.r.Areg, ISSUE_COMMAND_FOR_CPROC); -+ break; -+ -+ case MI_WaitForEventReadTy1: -+ /* -+ * Fault occured on the read of the event location for wait event type 1. -+ * Areg has the original ptr and count. -+ * Fault already fixed. Just re-issue the wait command using Areg and context. -+ */ -+ PRINTF1 (ctxt, DBG_CPROC, "RestartCProcTrap: WaitEvent type1 event location read fault %08x\n", -+ trap.TrapBuf.r.Areg); -+ res = IssueCommand (ctxt, offsetof (E3_CommandPort, WaitEvent1), trap.TrapBuf.r.Areg, ISSUE_COMMAND_FOR_CPROC); -+ break; -+ -+ case MI_WaitForCntxDmaDescRead: -+ case MI_WaitForNonCntxDmaDescRead: -+ /* -+ * Fault occured on the read of the dma descriptor. Run dma using the -+ * Fault Address in FaultSave. -+ */ -+ PRINTF1 (ctxt, DBG_CPROC, "RestartCProcTrap: MI_WaitForCntxDmaDescRead: re-issue dma at %08x\n", -+ trap.FaultSave.s.FaultAddress); -+ -+ res = IssueDmaCommand (ctxt, trap.FaultSave.s.FaultAddress, NULL, ISSUE_COMMAND_FOR_CPROC); -+ break; -+ -+ default: -+ /* -+ * Assume the fault will be fixed by FixupEventTrap. -+ */ -+ FixupEventTrap (ctxt, COMMAND_PROC, &trap, trap.Status.s.TrapType, &trap.FaultSave, ISSUE_COMMAND_FOR_CPROC); -+ -+ res = ISSUE_COMMAND_OK; -+ break; -+ } -+ -+ switch (res) -+ { -+ case ISSUE_COMMAND_OK: /* command re-issued ok*/ -+ break; -+ -+ case ISSUE_COMMAND_TRAPPED: /* command trapped, it will have been copied */ -+ return (EAGAIN); /* to the back of the trap queue */ -+ -+ case ISSUE_COMMAND_RETRY: /* didn't issue command, so place back at front for */ -+ spin_lock_irqsave (&dev->IntrLock, flags); /* later (after resolving other traps */ -+ -+ if (ELAN3_QUEUE_REALLY_FULL (ctxt->CommandTrapQ)) -+ ctxt->Status |= CTXT_COMMAND_OVERFLOW_ERROR; -+ else -+ { -+ ELAN3_QUEUE_ADD_FRONT(ctxt->CommandTrapQ); -+ (*ELAN3_QUEUE_FRONT (ctxt->CommandTrapQ, ctxt->CommandTraps)) = trap; -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return (EAGAIN); -+ -+ default: -+ return (EINVAL); -+ } -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ } -+ -+ /* -+ * GNAT 5409 - if CommandPortItem was not NULL, but other reasons were set, -+ * then we'd not free the CommandPortItem even though we'd re- -+ * issued all trapped and overflowed commands. Hence only return -+ * without clearing CommandPortItem if we will be called again as -+ * either CommandTrapQ or CommandQ is not empty. -+ */ -+ -+ /* Now run the overflowed commands for this context */ -+ if (! ELAN3_QUEUE_EMPTY (ctxt->CommandQ)) -+ { -+ if (! ELAN3_QUEUE_EMPTY (ctxt->CommandTrapQ) || (ctxt->Status & CTXT_OTHERS_REASONS)) -+ { -+ PRINTF0 (ctxt, DBG_CPROC, "RestartCProcTrap: cannot issue overflowed commands\n"); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return (EAGAIN); -+ } -+ -+ /* -+ * Just re-issue the commands, if one traps then the remainder will -+ * just get placed in the overflow queue again and the interrupt handler -+ * will copy them back in here. -+ * -+ * Stop the dma processor from taking commands, since one of the commands -+ * could be a re-issued remote dma, which must be processed by the command -+ * processor. -+ */ -+ -+ if (dev->HaltDmaDequeueCount++ == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ -+ while (! ELAN3_QUEUE_EMPTY (ctxt->CommandQ)) -+ { -+ CProcTrapBuf_BE *TrapBuf = ELAN3_QUEUE_FRONT (ctxt->CommandQ, ctxt->Commands); -+ -+ PRINTF2 (ctxt, DBG_CPROC, "RestartCProcTrap: re-issue command %x - %08x\n", -+ (TrapBuf->s.ContextType>>5) & 0xff, TrapBuf->s.Addr); -+ mb(); /* ensure writes to main memory completed */ -+ ((E3_uint32 *) ctxt->CommandPort)[(TrapBuf->s.ContextType>>5) & 0xff] = TrapBuf->s.Addr; -+ mmiob(); /* and flush through IO writes */ -+ -+ ELAN3_QUEUE_REMOVE (ctxt->CommandQ); -+ } -+ -+ /* observe the command processor having halted */ -+ res = CheckCommandQueueFlushed (ctxt, DmaComQueueNotEmpty, 0, &flags); -+ -+ if (res != ISSUE_COMMAND_OK) -+ { -+ PRINTF0 (ctxt, DBG_CPROC, "RestartCProcTrap: trapped after issueing overflowed commands\n"); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return (EAGAIN); -+ } -+ } -+ -+ /* remove the command port item, while holding the lock */ -+ item = ctxt->CommandPortItem; -+ ctxt->CommandPortItem = NULL; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ if (item != NULL) /* Free of any item that may have been stored */ -+ { /* because of the commandport trap */ -+ PRINTF1 (ctxt, DBG_CPROC, "RestartCProcTrap: commandPortItem %p\n", item); -+ -+ kmutex_lock (&ctxt->SwapListsLock); -+ ELAN3_OP_FREE_BLOCK_ITEM (ctxt, item); -+ kmutex_unlock (&ctxt->SwapListsLock); -+ } -+ -+ return (ESUCCESS); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/dproc.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/dproc.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/dproc.c 2005-06-01 23:12:54.568443816 -0400 -@@ -0,0 +1,553 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: dproc.c,v 1.52 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/dproc.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DMA_RETRY_FAIL_COUNT 8 -+ -+static void PrintUserDma (ELAN3_CTXT *ctxt, E3_Addr addr); -+ -+int -+HandleDProcTrap (ELAN3_DEV *dev, E3_uint32 *RestartBits) -+{ -+ DMA_TRAP *trap = dev->DmaTrap; -+ -+ ASSERT(SPINLOCK_HELD (&dev->IntrLock)); -+ -+ /* Scoop out the trap information, before restarting the Elan */ -+ trap->Status.Status = read_reg32 (dev, Exts.DProcStatus.Status); -+ -+ ASSERT(trap->Status.s.WakeupFunction == WakeupNever); -+ -+ /* copy the normal dma access fault type */ -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc), &trap->FaultSave, sizeof (E3_FaultSave_BE)); -+ -+ /* copy all 4 of the dma data fault type */ -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0), &trap->Data0, 4*sizeof (E3_FaultSave_BE)); -+ -+ /* Copy the DMA descriptor */ -+ copy_dma_regs (dev, &trap->Desc); -+ -+ /* Copy the packet info */ -+ trap->PacketInfo.Value = read_reg32 (dev, Exts.Dmas.DmaRds.DMA_PacketInfo.Value); -+ -+ /* update device statistics */ -+ BumpStat (dev, DProcTraps); -+ switch (trap->Status.s.TrapType) -+ { -+ case MI_DmaPacketTimedOutOrPacketError: -+ if (trap->PacketInfo.s.PacketTimeout) -+ BumpStat (dev, DmaOutputTimeouts); -+ else if (trap->PacketInfo.s.PacketAckValue == C_ACK_ERROR) -+ BumpStat (dev, DmaPacketAckErrors); -+ break; -+ -+ case MI_DmaFailCountError: -+ BumpStat (dev, DmaRetries); -+ break; -+ } -+ -+ /* Must now zero all the FSRs so that a subsequent fault can be seen */ -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc), sizeof (E3_FaultSave)); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0), 4*sizeof (E3_FaultSave)); -+ -+ *RestartBits |= RestartDProc; -+ return (TRUE); -+} -+ -+void -+DeliverDProcTrap (ELAN3_DEV *dev, DMA_TRAP *dmaTrap, E3_uint32 Pend) -+{ -+ ELAN3_CTXT *ctxt; -+ E3_FaultSave_BE *FaultArea; -+ DMA_TRAP *trap; -+ register int i; -+ -+ ASSERT(SPINLOCK_HELD (&dev->IntrLock)); -+ -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, dmaTrap->Status.s.Context); -+ -+ if (ctxt == NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "DeliverDProcTrap: context %x invalid\n", dmaTrap->Status.s.Context); -+ BumpStat (dev, InvalidContext); -+ } -+ else -+ { -+ if (ELAN3_OP_DPROC_TRAP (ctxt, dmaTrap) == OP_DEFER) -+ { -+ if (ELAN3_QUEUE_REALLY_FULL (ctxt->DmaTrapQ)) -+ { -+ ctxt->Status |= CTXT_COMMAND_OVERFLOW_ERROR; -+ StartSwapoutContext (ctxt, Pend, NULL); -+ } -+ else -+ { -+ trap = ELAN3_QUEUE_BACK (ctxt->DmaTrapQ, ctxt->DmaTraps); -+ -+ bcopy (dmaTrap, trap, sizeof (DMA_TRAP)); -+ -+ PRINTF5 (ctxt, DBG_INTR, "DeliverDProcTrap: WakeupFnt=%x Cntx=%x SuspAddr=%x PacketInfo=%x TrapType=%s\n", -+ trap->Status.s.WakeupFunction, trap->Status.s.Context, -+ trap->Status.s.SuspendAddr, trap->PacketInfo.Value, MiToName (trap->Status.s.TrapType)); -+ PRINTF3 (ctxt, DBG_INTR, " FaultAddr=%x EventAddr=%x FSR=%x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, -+ trap->FaultSave.s.FSR.Status); -+ for (i = 0, FaultArea = &trap->Data0; i < 4; i++, FaultArea++) -+ PRINTF4 (ctxt, DBG_INTR, " %d FaultAddr=%x EventAddr=%x FSR=%x\n", i, -+ FaultArea->s.FaultAddress, FaultArea->s.EventAddress, FaultArea->s.FSR.Status); -+ -+ PRINTF4 (ctxt, DBG_INTR, " type %08x size %08x source %08x dest %08x\n", -+ trap->Desc.s.dma_type, trap->Desc.s.dma_size, trap->Desc.s.dma_source, trap->Desc.s.dma_dest); -+ PRINTF2 (ctxt, DBG_INTR, " Dest event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_destEvent, trap->Desc.s.dma_destCookieVProc); -+ PRINTF2 (ctxt, DBG_INTR, " Source event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_srcEvent, trap->Desc.s.dma_srcCookieVProc); -+ ELAN3_QUEUE_ADD (ctxt->DmaTrapQ); -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ -+ if (ELAN3_QUEUE_FULL (ctxt->DmaTrapQ)) -+ { -+ PRINTF0 (ctxt, DBG_INTR, "DeliverDProcTrap: dma queue full, must swap out\n"); -+ ctxt->Status |= CTXT_DMA_QUEUE_FULL; -+ -+ StartSwapoutContext (ctxt, Pend, NULL); -+ } -+ } -+ } -+ } -+} -+ -+int -+NextDProcTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ if (ELAN3_QUEUE_EMPTY (ctxt->DmaTrapQ)) -+ return (0); -+ -+ *trap = *ELAN3_QUEUE_FRONT (ctxt->DmaTrapQ, ctxt->DmaTraps); -+ ELAN3_QUEUE_REMOVE (ctxt->DmaTrapQ); -+ -+ return (1); -+} -+ -+void -+ResolveDProcTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap) -+{ -+ E3_FaultSave_BE *FaultArea; -+ int FaultHandled = 0; -+ int res; -+ register int i; -+ -+ PRINTF4 (ctxt, DBG_DPROC, "ResolveDProcTrap: WakeupFnt=%x Cntx=%x SuspAddr=%x TrapType=%s\n", -+ trap->Status.s.WakeupFunction, trap->Status.s.Context, -+ trap->Status.s.SuspendAddr, MiToName (trap->Status.s.TrapType)); -+ PRINTF3 (ctxt, DBG_DPROC, " FaultAddr=%x EventAddr=%x FSR=%x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, -+ trap->FaultSave.s.FSR.Status); -+ for (i = 0, FaultArea = &trap->Data0; i < 4; i++, FaultArea++) -+ PRINTF4 (ctxt, DBG_DPROC, " %d FaultAddr=%x EventAddr=%x FSR=%x\n", i, -+ FaultArea->s.FaultAddress, FaultArea->s.EventAddress, FaultArea->s.FSR.Status); -+ -+ PRINTF4 (ctxt, DBG_DPROC, " type %08x size %08x source %08x dest %08x\n", -+ trap->Desc.s.dma_type, trap->Desc.s.dma_size, trap->Desc.s.dma_source, trap->Desc.s.dma_dest); -+ PRINTF2 (ctxt, DBG_DPROC, " Dest event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_destEvent, trap->Desc.s.dma_destCookieVProc); -+ PRINTF2 (ctxt, DBG_DPROC, " Source event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_srcEvent, trap->Desc.s.dma_srcCookieVProc); -+ -+ BumpUserStat (ctxt, DProcTraps); -+ -+ switch (trap->Status.s.TrapType) -+ { -+ case MI_DmaPacketTimedOutOrPacketError: -+ /* -+ * Faulted due to packet timeout or a PAckError. -+ * Reset fail count and reissue the same desc. -+ */ -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: got a PAckError or the output timed out. Rescheduling dma.\n"); -+ if (ElanException (ctxt, EXCEPTION_PACKET_TIMEOUT, DMA_PROC, trap) == OP_IGNORE) -+ { -+ BumpUserStat (ctxt, DmaRetries); -+ -+ trap->Desc.s.dma_failCount = DMA_RETRY_FAIL_COUNT; -+ -+ RestartDmaTrap (ctxt, trap); -+ } -+ return; -+ -+ case MI_DmaFailCountError: -+ /* -+ * Faulted due to dma fail count. -+ * Reset fail count and reissue the same desc. -+ */ -+ PRINTF1 (ctxt, DBG_DPROC, "ResolveDProcTrap: Reset dma fail count to %d\n", DMA_RETRY_FAIL_COUNT); -+ -+ if (ElanException (ctxt, EXCEPTION_DMA_RETRY_FAIL, DMA_PROC, trap) == OP_IGNORE) -+ { -+ BumpUserStat (ctxt, DmaRetries); -+ -+ trap->Desc.s.dma_failCount = DMA_RETRY_FAIL_COUNT; -+ -+ RestartDmaTrap (ctxt, trap); -+ } -+ return; -+ -+ case MI_TimesliceDmaQueueOverflow: -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: dma timeslice queue overflow\n"); -+ RestartDmaTrap (ctxt, trap); -+ return; -+ -+ case MI_UnimplementedError: -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: unimplemented dma trap\n"); -+ if (ElanException (ctxt, EXCEPTION_UNIMPLEMENTED, DMA_PROC, trap) == OP_IGNORE) -+ RestartDmaTrap (ctxt, trap); -+ return; -+ -+ case MI_EventQueueOverflow: -+ case MI_ThreadQueueOverflow: -+ case MI_DmaQueueOverflow: -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: trapped on a write set event.\n"); -+ FixupEventTrap (ctxt, DMA_PROC, trap, trap->Status.s.TrapType, &trap->FaultSave, 0); -+ return; -+ -+ case MI_RemoteDmaCommand: -+ case MI_RunDmaCommand: -+ case MI_DequeueNonSysCntxDma: -+ case MI_DequeueSysCntxDma: -+ /* -+ * The DMA processor has trapped due to outstanding prefetches from the previous -+ * dma. The "current" dma has not been consumed, so we just ignore the trap -+ */ -+ return; -+ -+ case MI_WaitForRemoteDescRead2: -+ case MI_ExecuteDmaDescriptorForRun: -+ /* -+ * The DMA processor has trapped while fetching the dma descriptor, so -+ * zero it out to not confuse the user on an error -+ */ -+ bzero (&trap->Desc, sizeof (trap->Desc)); -+ break; -+ } -+ -+ /* -+ * All other uWords will have updated one of the fault areas, so fix -+ * any faults found in them. If there were no faults found then it -+ * must have been a bus error -+ */ -+ for (i = 0, FaultArea = &trap->Data0; i < 4; i++, FaultArea++) -+ { -+ if (FaultArea->s.FSR.Status != 0) -+ { -+ FaultHandled++; -+ -+ ASSERT ((FaultArea->s.FSR.Status & FSR_SizeMask) == FSR_Block64 || -+ (FaultArea->s.FSR.Status & FSR_SizeMask) == FSR_Block32); -+ -+ ASSERT (FaultArea->s.FaultContext == trap->Status.s.Context); -+ -+ if (((trap->Desc.s.dma_source & PAGEOFFSET) >= (PAGESIZE-E3_BLK_SIZE)) && -+ ((trap->Desc.s.dma_source & PAGEMASK) != ((trap->Desc.s.dma_source + trap->Desc.s.dma_size-1) & PAGEMASK))) -+ { -+ /* XXXX: dma started within last 64 bytes of the page -+ * terminate the process if it has pagefaulted */ -+ if (FaultArea->s.FaultAddress == (trap->Desc.s.dma_source & ~(E3_BLK_SIZE-1))) -+ { -+ printk ("elan%d: invalid dma - context=%x source=%x\n", ctxt->Device->Instance, -+ ctxt->Capability.cap_mycontext, trap->Desc.s.dma_source); -+ -+ if (ElanException (ctxt, EXCEPTION_BAD_DMA, DMA_PROC, trap, NULL, 0) != OP_IGNORE) -+ return; -+ } -+ } -+ -+ if (trap->Desc.s.dma_size != 0 && (res = elan3_pagefault (ctxt, FaultArea, 1)) != ESUCCESS) -+ { -+ /* XXXX: Rev B Elans can prefetch data passed the end of the dma descriptor */ -+ /* if the fault relates to this, then just ignore it */ -+ if (FaultArea->s.FaultAddress < (trap->Desc.s.dma_source+trap->Desc.s.dma_size) || -+ FaultArea->s.FaultAddress > (trap->Desc.s.dma_source+trap->Desc.s.dma_size+E3_BLK_SIZE*2)) -+ { -+ PRINTF1 (ctxt, DBG_DPROC, "ResolveDProcTrap: elan3_pagefault failed for address %x\n", -+ FaultArea->s.FaultAddress); -+ -+ if (ElanException (ctxt, EXCEPTION_INVALID_ADDR, DMA_PROC, trap, FaultArea, res) != OP_IGNORE) -+ return; -+ } -+ } -+ } -+ } -+ -+ if (trap->FaultSave.s.FSR.Status != 0) -+ { -+ FaultHandled++; -+ -+ ASSERT (trap->FaultSave.s.FaultContext == trap->Status.s.Context); -+ -+ if ((trap->FaultSave.s.FSR.Status & FSR_SizeMask) == FSR_RouteFetch) -+ { -+ res = ResolveVirtualProcess (ctxt, trap->FaultSave.s.FaultAddress & 0xffff); /* mask out cookie */ -+ -+ switch (res) -+ { -+ default: -+ if (ElanException (ctxt, EXCEPTION_INVALID_PROCESS, DMA_PROC, trap, trap->FaultSave.s.FaultAddress, res) != OP_IGNORE) -+ return; -+ -+ case EAGAIN: -+ /* XXXX; wait on trail blazing code */ -+ -+ case 0: -+ break; -+ } -+ } -+ else -+ { -+ if ((res = elan3_pagefault (ctxt, &trap->FaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_DPROC, "ResolveDProcTrap: elan3_pagefault failed for address %x\n", -+ trap->FaultSave.s.FaultAddress); -+ -+ if (ElanException (ctxt, EXCEPTION_INVALID_ADDR, DMA_PROC, trap, &trap->FaultSave, res) != OP_IGNORE) -+ return; -+ } -+ } -+ } -+ -+ if (! FaultHandled) -+ { -+ ElanBusError (ctxt->Device); -+ -+ if (ElanException (ctxt, EXCEPTION_INVALID_ADDR, DMA_PROC, trap, &trap->FaultSave, EFAULT) != OP_IGNORE) -+ return; -+ } -+ -+ switch (trap->Status.s.TrapType) -+ { -+ case MI_WaitForRemoteDescRead2: -+ /* -+ * Faulted while trying to read the dma descriptor for a read dma. -+ * Fix fault and re-issue using FaultAddress. -+ */ -+ PRINTF1 (ctxt, DBG_DPROC, "ResolveDProcTrap: trapped reading a remote dma descriptor at %x.\n", -+ trap->FaultSave.s.FaultAddress); -+ -+ RestartDmaPtr (ctxt, trap->FaultSave.s.FaultAddress); -+ break; -+ -+ case MI_ExecuteDmaDescriptorForRun: -+ /* -+ * Faulted while trying to read the dma descriptor for a write dma. -+ * Fix fault and re-issue using FaultAddress. -+ */ -+ PRINTF1 (ctxt, DBG_DPROC, "ResolveDProcTrap: trapped reading a write dma descriptor at %x.\n", -+ trap->FaultSave.s.FaultAddress); -+ -+ RestartDmaPtr (ctxt, trap->FaultSave.s.FaultAddress); -+ break; -+ -+ case MI_WaitForRemoteRoutes1: -+ case MI_WaitForRemoteRoutes2: -+ case MI_SendRemoteDmaDesc: -+ case MI_SendDmaIdentify: -+ case MI_SendRemoteDmaRoutes2: -+ case MI_WaitForDmaRoutes1: -+ case MI_DmaLoop: -+ case MI_ExitDmaLoop: -+ case MI_GetDestEventValue: -+ case MI_SendFinalUnlockTrans: -+ case MI_SendNullSetEvent: -+ case MI_SendFinalSetEvent: -+ case MI_SendDmaEOP: -+ /* -+ * Faulted either fetching routes or fetching dma data. -+ * Fix fault and re-issue using FaultAddress. -+ */ -+ -+ case MI_SendEOPforRemoteDma: -+ case MI_LookAtRemoteAck: -+ case MI_FailedAckIfCCis0: -+ /* -+ * Possible fault when reading the remote desc into the dma data buffers -+ */ -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: trapped reading a dma data or fetching a route\n"); -+ RestartDmaTrap (ctxt, trap); -+ break; -+ -+ case MI_DequeueSysCntxDma: -+ case MI_DequeueNonSysCntxDma: -+ case MI_RemoteDmaCommand: -+ case MI_RunDmaCommand: -+ /* -+ * It is possible that a dma can get back onto the queue while outstanding dma -+ * have not finished trapping. In this case the trap can be ignored as the dma -+ * state has been saved. It might trap again the next time it comes to the front -+ * of the queue and be fixed then. -+ */ -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: trap after dma has finished. ignored\n"); -+ break; -+ -+ default: -+ PRINTF0 (ctxt, DBG_DPROC, "ResolveDProcTrap: trapped on a write set event.\n"); -+ FixupEventTrap (ctxt, DMA_PROC, trap, trap->Status.s.TrapType, &trap->FaultSave, 0); -+ break; -+ } -+} -+ -+int -+DProcNeedsRestart (ELAN3_CTXT *ctxt) -+{ -+ return (ctxt->ItemCount[LIST_DMA_PTR] != 0 || -+ ctxt->ItemCount[LIST_DMA_DESC] != 0); -+} -+ -+void -+RestartDProcItems (ELAN3_CTXT *ctxt) -+{ -+ void *item; -+ E3_Addr value; -+ int res; -+ -+ kmutex_lock (&ctxt->SwapListsLock); -+ while (ctxt->ItemCount[LIST_DMA_PTR]) -+ { -+ if (! ELAN3_OP_GET_WORD_ITEM (ctxt, LIST_DMA_PTR, &item, &value)) -+ ctxt->ItemCount[LIST_DMA_PTR] = 0; -+ else -+ { -+ PRINTF1 (ctxt, DBG_DPROC, "RestartDProc: issue write dma at %x\n", value); -+ PrintUserDma (ctxt, value); -+ -+ res = IssueDmaCommand (ctxt, value, NULL, 0); -+ -+ if (res == ISSUE_COMMAND_RETRY) -+ { -+ ELAN3_OP_PUTBACK_ITEM (ctxt, LIST_DMA_PTR, item); -+ kmutex_unlock (&ctxt->SwapListsLock); -+ return; -+ } -+ -+ ctxt->ItemCount[LIST_DMA_PTR]--; -+ ELAN3_OP_FREE_WORD_ITEM (ctxt, item); -+ } -+ } -+ -+ while (ctxt->ItemCount[LIST_DMA_DESC]) -+ { -+ if (! ELAN3_OP_GET_BLOCK_ITEM (ctxt, LIST_DMA_DESC, &item, &value)) -+ ctxt->ItemCount[LIST_DMA_DESC] = 0; -+ else -+ { -+ PRINTF1 (ctxt, DBG_DPROC, "RestartDProc: issue dma desc at %x\n", value); -+ PrintUserDma (ctxt, value); -+ -+ res = IssueDmaCommand (ctxt, value, item, 0); -+ -+ switch (res) -+ { -+ case ISSUE_COMMAND_OK: -+ ctxt->ItemCount[LIST_DMA_DESC]--; -+ ELAN3_OP_FREE_BLOCK_ITEM (ctxt, item); -+ break; -+ -+ case ISSUE_COMMAND_RETRY: -+ ELAN3_OP_PUTBACK_ITEM (ctxt, LIST_DMA_DESC, item); -+ kmutex_unlock (&ctxt->SwapListsLock); -+ return; -+ -+ case ISSUE_COMMAND_TRAPPED: -+ ctxt->ItemCount[LIST_DMA_DESC]--; -+ /* The item will be freed off when the command port trap */ -+ /* fixed up and the command successfully re-issued */ -+ break; -+ } -+ } -+ } -+ -+ kmutex_unlock (&ctxt->SwapListsLock); -+} -+ -+void -+RestartDmaDesc(ELAN3_CTXT *ctxt, E3_DMA_BE *desc) -+{ -+ kmutex_lock (&ctxt->SwapListsLock); -+ if (desc->s.dma_direction != DMA_WRITE) -+ desc->s.dma_direction = (desc->s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ -+ ELAN3_OP_PUT_BLOCK_ITEM (ctxt, LIST_DMA_DESC, (E3_uint32 *) desc); -+ ctxt->ItemCount[LIST_DMA_DESC]++; -+ -+ kmutex_unlock (&ctxt->SwapListsLock); -+} -+ -+void -+RestartDmaTrap(ELAN3_CTXT *ctxt, DMA_TRAP *trap) -+{ -+ /* Negative length DMAs are illegal, since they hangup the dma processor, -+ * if they got generated then they will have been spotted by PollForDmahungup, -+ * and delivered to us with a Dequeue suspend address, -+ * -+ * GNAT sw-elan3/3908: Moved this check into this new function to avoid -+ * it sampling old or invalid register state -+ */ -+ if (trap->Desc.s.dma_size > E3_MAX_DMA_SIZE) -+ ElanException (ctxt, EXCEPTION_BAD_DMA, DMA_PROC, trap, NULL, 0); -+ else -+ RestartDmaDesc (ctxt, &trap->Desc); -+} -+ -+void -+RestartDmaPtr (ELAN3_CTXT *ctxt, E3_Addr ptr) -+{ -+ kmutex_lock (&ctxt->SwapListsLock); -+ ELAN3_OP_PUT_WORD_ITEM (ctxt, LIST_DMA_PTR, ptr); -+ ctxt->ItemCount[LIST_DMA_PTR]++; -+ kmutex_unlock (&ctxt->SwapListsLock); -+} -+ -+static void -+PrintUserDma (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ E3_DMA *dma; -+ -+ /* Dont call a function which takes locks unless we need to */ -+ if (!(elan3_debug & DBG_DPROC)) -+ return; -+ -+ dma = (E3_DMA *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ PRINTF4 (ctxt, DBG_DPROC, "DMA: type %08x size %08x source %08x dest %08x\n", -+ fuword ((int *) &dma->dma_type), fuword ((int *) &dma->dma_size), -+ fuword ((int *) &dma->dma_source), fuword ((int *) &dma->dma_dest)); -+ PRINTF4 (ctxt, DBG_DPROC, "DMA: Dest %08x %08x Local %08x %08x\n", -+ fuword ((int *) &dma->dma_destEvent), fuword ((int *) &dma->dma_destCookieProc), -+ fuword ((int *) &dma->dma_srcEvent), fuword ((int *) &dma->dma_srcCookieProc)); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elan3mmu_generic.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elan3mmu_generic.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elan3mmu_generic.c 2005-06-01 23:12:54.573443056 -0400 -@@ -0,0 +1,3255 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elan3mmu_generic.c,v 1.75.2.1 2004/12/14 10:19:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/vm/elan3mmu_generic.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_MPSAS -+# define zero_all_ptbls -+#endif -+ -+/* -+ * Debugging -+ */ -+int elan3mmu_debug = 0; -+ -+#define N_L3PTBL_MTX (0x20) -+#define N_L2PTBL_MTX (0x40) -+#define N_L1PTBL_MTX (0x20) -+ -+#define L3PTBL_MTX_HASH(p) \ -+ ((((uintptr_t)(p) >> 12) ^ ((uintptr_t)(p) >> 2)) & (N_L3PTBL_MTX - 1)) -+static spinlock_t l3ptbl_lock[N_L3PTBL_MTX]; -+ -+#define L2PTBL_MTX_HASH(p) \ -+ ((((uintptr_t)(p) >> 12) ^ ((uintptr_t)(p) >> 2)) & (N_L2PTBL_MTX - 1)) -+static spinlock_t l2ptbl_lock[N_L2PTBL_MTX]; -+ -+#define L1PTBL_MTX_HASH(p) \ -+ ((((uintptr_t)(p) >> 12) ^ ((uintptr_t)(p) >> 2)) & (N_L1PTBL_MTX - 1)) -+static spinlock_t l1ptbl_lock[N_L1PTBL_MTX]; -+ -+ -+#define BASE2VA(p) ((E3_Addr)((p)->ptbl_base << 16)) -+#define VA2BASE(v) ((u_short)(((uintptr_t)(v)) >> 16)) -+ -+ELAN3MMU_GLOBAL_STATS elan3mmu_global_stats; -+ -+static void elan3mmu_flush_context_filter (ELAN3_DEV *dev, void *); -+static void elan3mmu_unload_loop (ELAN3MMU *elan3mmu, ELAN3_PTBL *ptbl, int first_valid, int nptes, int flags); -+ -+static ELAN3_PTBL *elan3mmu_create_ptbls (ELAN3_DEV *dev, int level, int attr, int keep); -+static ELAN3_PTBL *elan3mmu_ta_to_ptbl (ELAN3MMU *elan3mmu, ELAN3_PTP *ptp); -+ -+static ELAN3_PTBL *elan3mmu_alloc_pte (ELAN3_DEV *dev, ELAN3MMU *elan3mmu, int *idx); -+void elan3mmu_free_lXptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl); -+ -+void elan3mmu_free_pte (ELAN3_DEV *dev, ELAN3MMU *elan3mmu, ELAN3_PTBL *ptbl_ptr, int idx); -+ -+static ELAN3_PTBL *elan3mmu_alloc_l1ptbl (ELAN3_DEV *dev, int attr, ELAN3MMU *elan3mmu); -+static ELAN3_PTBL *elan3mmu_alloc_l2ptbl (ELAN3_DEV *dev, int attr, ELAN3_PTBL *parent, ELAN3MMU *elan3mmu, -+ E3_Addr base, spinlock_t **plock, unsigned long *flags); -+static ELAN3_PTBL *elan3mmu_alloc_l3ptbl (ELAN3_DEV *dev, int attr, ELAN3_PTBL *parent, ELAN3MMU *elan3mmu, -+ E3_Addr base, spinlock_t **plock, unsigned long *flags); -+ -+static int elan3mmu_steal_this_ptbl (ELAN3_DEV *dev, ELAN3_PTBL *l3ptbl); -+static ELAN3_PTBL *elan3mmu_steal_l3ptbl (ELAN3_DEV *dev, int attr); -+ -+static spinlock_t *elan3mmu_ptbl_to_lock (int level, ELAN3_PTBL *ptbl); -+ -+/* -+ * Encoding of MMU permissions against access type, -+ * to allow quick permission checking against access -+ * type. -+ */ -+u_char elan3mmu_permissionTable[] = -+{ -+ 0xcc, /* 11001100 ELAN3_PERM_NULL */ -+ 0x01, /* 00000001 ELAN3_PERM_LOCALREAD */ -+ 0x05, /* 00000101 ELAN3_PERM_READ */ -+ 0x33, /* 00110011 ELAN3_PERM_NOREMOTE */ -+ 0x37, /* 00110111 ELAN3_PERM_REMOTEREAD */ -+ 0x3f, /* 00111111 ELAN3_PERM_REMOTEWRITE */ -+ 0xf7, /* 11110111 ELAN3_PERM_REMOTEEVENT */ -+ 0xff, /* 11111111 ELAN3_PERM_REMOTEALL */ -+} ; -+ -+void -+elan3mmu_init() -+{ -+ register int i; -+ -+ HAT_PRINTF0 (1, "elan3mmu_init: initialising elan mmu\n"); -+ -+ for (i = 0; i < N_L1PTBL_MTX; i++) -+ spin_lock_init (&l1ptbl_lock[i]); -+ -+ for (i = 0; i < N_L2PTBL_MTX; i++) -+ spin_lock_init (&l2ptbl_lock[i]); -+ -+ for (i = 0; i < N_L3PTBL_MTX; i++) -+ spin_lock_init (&l3ptbl_lock[i]); -+ -+ elan3mmu_global_stats.version = ELAN3MMU_STATS_VERSION; -+ -+ elan3mmu_init_osdep(); -+} -+ -+void -+elan3mmu_fini() -+{ -+ register int i; -+ -+ HAT_PRINTF0 (1, "elan3mmu_fini: finalising elan mmu\n"); -+ -+ for (i = 0; i < N_L1PTBL_MTX; i++) -+ spin_lock_destroy (&l1ptbl_lock[i]); -+ -+ for (i = 0; i < N_L2PTBL_MTX; i++) -+ spin_lock_destroy (&l2ptbl_lock[i]); -+ -+ for (i = 0; i < N_L3PTBL_MTX; i++) -+ spin_lock_destroy (&l3ptbl_lock[i]); -+ -+ elan3mmu_fini_osdep(); -+} -+ -+ELAN3MMU * -+elan3mmu_alloc (ELAN3_CTXT *ctxt) -+{ -+ ELAN3MMU *elan3mmu; -+ ELAN3_PTBL *l1ptbl; -+ -+ ALLOC_ELAN3MMU (elan3mmu, TRUE); -+ -+ spin_lock_init (&elan3mmu->elan3mmu_lock); -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); /* lock_lint */ -+ -+ elan3mmu->elan3mmu_ergns = NULL; -+ elan3mmu->elan3mmu_etail = NULL; -+ elan3mmu->elan3mmu_ergnlast = NULL; -+ elan3mmu->elan3mmu_mrgns = NULL; -+ elan3mmu->elan3mmu_mtail = NULL; -+ elan3mmu->elan3mmu_mrgnlast = NULL; -+ elan3mmu->elan3mmu_ctxt = ctxt; -+ -+ spin_lock_init (&elan3mmu->elan3mmu_lXptbl_lock); -+ elan3mmu->elan3mmu_lXptbl = NULL; -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); /* lock_lint */ -+ -+ l1ptbl = elan3mmu_alloc_l1ptbl(ctxt->Device, 0, elan3mmu); -+ -+ elan3mmu->elan3mmu_ctp = (sdramaddr_t) 0; -+ elan3mmu->elan3mmu_dev = ctxt->Device; -+ elan3mmu->elan3mmu_l1ptbl = l1ptbl; -+ -+ /* Ensure that there are at least some level 3 page tables, since if a level 2 and */ -+ /* a level 3 table are allocated together, then the level 3 is allocated with the NO_ALLOC */ -+ /* flag, thus there MUST be at least one that can be stolen or on the free list */ -+ if (elan3mmu->elan3mmu_dev->Level[PTBL_LEVEL_3].PtblFreeList == NULL) -+ elan3mmu_create_ptbls (elan3mmu->elan3mmu_dev, PTBL_LEVEL_3, 0, 0); -+ -+ HAT_PRINTF1 (1, "elan3mmu_alloc: elan3mmu %p\n", elan3mmu); -+ -+ elan3mmu_alloc_osdep (elan3mmu); -+ -+ return (elan3mmu); -+} -+ -+void -+elan3mmu_free (ELAN3MMU *elan3mmu) -+{ -+ ELAN3MMU_RGN *rgn; -+ ELAN3_PTBL *l1ptbl; -+ spinlock_t *l1lock; -+ unsigned long l1flags; -+ unsigned long flags; -+ -+ HAT_PRINTF1 (1, "elan3mmu_free : elan3mmu %p\n", elan3mmu); -+ -+ /* -+ * Invalidate the level1 page table, since it's already removed -+ * from the context table, there is no need to flush the tlb. -+ */ -+ l1ptbl = elan3mmu->elan3mmu_l1ptbl; -+ elan3mmu->elan3mmu_l1ptbl = NULL; -+ -+ if (elan3mmu_lock_ptbl (l1ptbl, LK_PTBL_FAILOK, elan3mmu, (E3_Addr) 0, PTBL_LEVEL_1, &l1lock, &l1flags) == LK_PTBL_OK) -+ { -+ elan3mmu_l1inval (elan3mmu, l1ptbl, PTE_UNLOAD_NOFLUSH); -+ elan3mmu_free_l1ptbl (elan3mmu->elan3mmu_dev, l1ptbl, l1lock, l1flags); -+ } -+ -+ /* -+ * Free of any permission regions. -+ */ -+ spin_lock (&elan3mmu->elan3mmu_lock); /* lock_lint */ -+ while ((rgn = elan3mmu->elan3mmu_mrgns) != NULL) -+ { -+ spin_lock_irqsave (&elan3mmu->elan3mmu_dev->IntrLock, flags); /* lock_lint */ -+ elan3mmu_removergn_elan (elan3mmu, rgn->rgn_ebase); -+ elan3mmu_removergn_main (elan3mmu, rgn->rgn_mbase); -+ spin_unlock_irqrestore (&elan3mmu->elan3mmu_dev->IntrLock, flags); /* lock_lint */ -+ -+ FREE_ELAN3MMU_RGN (rgn); -+ } -+ elan3mmu->elan3mmu_mrgnlast = NULL; -+ elan3mmu->elan3mmu_ergnlast = NULL; -+ -+ /* -+ * Free the lXptbl list -+ */ -+ ASSERT (elan3mmu->elan3mmu_lXptbl == NULL); /* XXXX MRH need to add list removal */ -+ -+ elan3mmu->elan3mmu_lXptbl = NULL; -+ spin_lock_destroy (&elan3mmu->elan3mmu_lXptbl_lock); -+ -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); /* lock_lint */ -+ -+ spin_lock_destroy (&elan3mmu->elan3mmu_lock); -+ -+ FREE_ELAN3MMU (elan3mmu); -+} -+ -+/*================================================================================*/ -+/* Interface routines to device driver */ -+static void -+elan3mmu_flush_context_filter (ELAN3_DEV *dev, void *arg) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ ASSERT ((read_reg32 (dev, Exts.InterruptReg) & (INT_DiscardingSysCntx | INT_DiscardingNonSysCntx)) == -+ (INT_DiscardingSysCntx | INT_DiscardingNonSysCntx)); -+ -+ dev->FilterHaltQueued = 0; -+ -+ write_reg32 (dev, Input_Context_Fil_Flush, 0); -+ -+ HAT_PRINTF0 (1, "elan3mmu_flush_context_filter completed\n"); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+void -+elan3mmu_set_context_filter (ELAN3_DEV *dev, int ctx, int disabled, E3_uint32 Pend, E3_uint32 *Maskp) -+{ -+ int mctx = ctx & MAX_ROOT_CONTEXT_MASK; -+ sdramaddr_t ctp = dev->ContextTable + mctx * sizeof (E3_ContextControlBlock); -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ ASSERT ((mctx < 32 || mctx >= ELAN3_KCOMM_BASE_CONTEXT_NUM) ? (ctx & SYS_CONTEXT_BIT) : ! (ctx & SYS_CONTEXT_BIT)); -+ -+ elan3_sdram_writel (dev, ctp + offsetof (E3_ContextControlBlock, filter), -+ ((ctx & SYS_CONTEXT_BIT) ? E3_CCB_CNTX0 : 0) | (disabled ? E3_CCB_DISCARD_ALL : 0)); -+ -+ HAT_PRINTF4 (1, "elan3mmu_set_context_filter: ctx %x [%lx] -> %s (%x)\n", ctx, ctp, -+ disabled ? "up" : "down", elan3_sdram_readl (dev, ctp + offsetof (E3_ContextControlBlock, filter))); -+ -+ /* queue a halt operation to flush the context filter while the inputter is halted */ -+ if (dev->FilterHaltQueued == 0) -+ { -+ dev->FilterHaltQueued = 1; -+ QueueHaltOperation (dev, Pend, Maskp, INT_DiscardingSysCntx | INT_DiscardingNonSysCntx, -+ elan3mmu_flush_context_filter, NULL); -+ } -+} -+ -+int -+elan3mmu_attach (ELAN3_DEV *dev, int ctx, ELAN3MMU *elan3mmu, sdramaddr_t routeTable, E3_uint32 routeMask) -+{ -+ sdramaddr_t ctp; -+ ELAN3_PTP trootptp; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ ctx &= MAX_ROOT_CONTEXT_MASK; /* Mask out all high bits in context */ -+ -+ if (ctx < 0 || ctx >= dev->ContextTableSize) -+ return (EINVAL); -+ -+ ctp = dev->ContextTable + ctx * sizeof (E3_ContextControlBlock); -+ -+ trootptp = elan3_readptp (dev, ctp + offsetof (E3_ContextControlBlock, rootPTP)); -+ -+ if (ELAN3_PTP_TYPE(trootptp) != ELAN3_ET_INVALID) -+ return (EBUSY); -+ -+ elan3mmu->elan3mmu_ctp = ctp; -+ -+ trootptp = PTBL_TO_PTADDR (elan3mmu->elan3mmu_l1ptbl) | ELAN3_ET_PTP; -+ -+ HAT_PRINTF4 (1, "elan3mmu_attach: ctp at %08lx : trootptp=%08x VPT_ptr=%08lx VPT_mask=%08x\n", -+ ctp, trootptp, routeTable, routeMask); -+ -+ elan3_writeptp (dev, ctp + offsetof (E3_ContextControlBlock, rootPTP), trootptp); -+ elan3_writeptp (dev, ctp + offsetof (E3_ContextControlBlock, VPT_ptr), routeTable); -+ elan3_writeptp (dev, ctp + offsetof (E3_ContextControlBlock, VPT_mask), routeMask); -+ -+ return (ESUCCESS); -+} -+ -+void -+elan3mmu_detach (ELAN3_DEV *dev, int ctx) -+{ -+ ELAN3_PTP invalidptp = ELAN3_INVALID_PTP; -+ sdramaddr_t ctp; -+ -+ ctx &= MAX_ROOT_CONTEXT_MASK; /* Mask out all high bits in context */ -+ -+ if (ctx < 0 || ctx >= dev->ContextTableSize) -+ return; -+ -+ ctp = dev->ContextTable + ctx * sizeof (E3_ContextControlBlock); -+ -+ HAT_PRINTF1 (1, "elan3mmu_detach: clearing ptp at %lx\n", ctp); -+ -+ elan3_writeptp (dev, ctp + offsetof (E3_ContextControlBlock, rootPTP), invalidptp); -+ elan3_writeptp (dev, ctp + offsetof (E3_ContextControlBlock, VPT_mask), 0); -+ elan3_writeptp (dev, ctp + offsetof (E3_ContextControlBlock, VPT_ptr), 0); -+ -+ ElanFlushTlb (dev); -+} -+ -+int -+elan3mmu_reference (ELAN3MMU *elan3mmu, int ctx) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ sdramaddr_t ctp; -+ E3_ContextControlBlock ccb; -+ ELAN3_PTP trootptp; -+ -+ ctx &= MAX_ROOT_CONTEXT_MASK; /* Mask out all high bits in context */ -+ -+ if (ctx < 0 || ctx >= dev->ContextTableSize) -+ return (EINVAL); -+ -+ ctp = dev->ContextTable + ctx * sizeof (E3_ContextControlBlock); -+ -+ trootptp = elan3_readptp (dev, ctp + offsetof (E3_ContextControlBlock, rootPTP)); -+ -+ if (ELAN3_PTP_TYPE(trootptp) != ELAN3_ET_INVALID) -+ return (EBUSY); -+ -+ elan3_sdram_copyl_from_sdram (dev, elan3mmu->elan3mmu_ctp, &ccb, sizeof (E3_ContextControlBlock)); -+ elan3_sdram_copyl_to_sdram (dev, &ccb, ctp, sizeof (E3_ContextControlBlock)); -+ -+ return (ESUCCESS); -+ -+} -+/*================================================================================*/ -+/* Elan permission regions. */ -+ -+/* elan address region management */ -+ELAN3MMU_RGN * -+elan3mmu_findrgn_elan (ELAN3MMU *elan3mmu, -+ E3_Addr addr, int tail) -+{ -+ ELAN3MMU_RGN *next = NULL; -+ ELAN3MMU_RGN *rgn; -+ ELAN3MMU_RGN *hirgn; -+ ELAN3MMU_RGN *lorgn; -+ E3_Addr base; -+ E3_Addr lastaddr; -+ int forward; -+ -+ ASSERT (SPINLOCK_HELD (&elan3mmu->elan3mmu_dev->IntrLock) || SPINLOCK_HELD (&elan3mmu->elan3mmu_lock)); -+ -+ if (elan3mmu->elan3mmu_ergns == NULL) -+ return (NULL); -+ -+ rgn = elan3mmu->elan3mmu_ergnlast; -+ if (rgn == NULL) -+ rgn = elan3mmu->elan3mmu_ergns; -+ -+ forward = 0; -+ if ((u_long) (base = rgn->rgn_ebase) < (u_long)addr) -+ { -+ if ((u_long)addr <= ((u_long) base + rgn->rgn_len - 1)) -+ return (rgn); /* ergnlast contained addr */ -+ -+ hirgn = elan3mmu->elan3mmu_etail; -+ -+ if ((u_long) (lastaddr = (hirgn->rgn_ebase + hirgn->rgn_len - 1)) < (u_long) addr) -+ return (tail ? hirgn : NULL); /* addr is out of range */ -+ -+ if ((u_long) (addr - base) > (u_long) (lastaddr - addr)) -+ rgn = hirgn; -+ else -+ { -+ rgn = rgn->rgn_enext; -+ forward++; -+ } -+ } -+ else -+ { -+ lorgn = elan3mmu->elan3mmu_ergns; -+ -+ if ((u_long)lorgn->rgn_ebase > (u_long) addr) -+ return (lorgn); /* lowest regions is higher than addr */ -+ if ((u_long)(addr - lorgn->rgn_ebase) < (u_long) (base - addr)) -+ { -+ rgn = lorgn; /* search forward from head */ -+ forward++; -+ } -+ } -+ if (forward) -+ { -+ while ((u_long)(rgn->rgn_ebase + rgn->rgn_len - 1) < (u_long)addr) -+ rgn = rgn->rgn_enext; -+ -+ if ((u_long)rgn->rgn_ebase <= (u_long)addr) -+ elan3mmu->elan3mmu_ergnlast = rgn; -+ return (rgn); -+ } -+ else -+ { -+ while ((u_long)rgn->rgn_ebase > (u_long)addr) -+ { -+ next = rgn; -+ rgn = rgn->rgn_eprev; -+ } -+ -+ if ((u_long) (rgn->rgn_ebase + rgn->rgn_len - 1) < (u_long)addr) -+ return (next); -+ else -+ { -+ elan3mmu->elan3mmu_ergnlast = rgn; -+ return (rgn); -+ } -+ } -+} -+ -+int -+elan3mmu_addrgn_elan (ELAN3MMU *elan3mmu, ELAN3MMU_RGN *nrgn) -+{ -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_elan (elan3mmu, nrgn->rgn_ebase, 1); -+ E3_Addr nbase = nrgn->rgn_ebase; -+ E3_Addr ntop = nbase + nrgn->rgn_len - 1; /* avoid wrap */ -+ E3_Addr base; -+ -+ ASSERT (SPINLOCK_HELD (&elan3mmu->elan3mmu_dev->IntrLock) && SPINLOCK_HELD (&elan3mmu->elan3mmu_lock)); -+ -+ if (rgn == NULL) -+ { -+ elan3mmu->elan3mmu_ergns = elan3mmu->elan3mmu_etail = nrgn; -+ nrgn->rgn_enext = nrgn->rgn_eprev = NULL; -+ } -+ else -+ { -+ base = rgn->rgn_ebase; -+ -+ if ((u_long)(base + rgn->rgn_len - 1) < (u_long)nbase) /* top of region below requested address */ -+ { /* so insert after region (and hence at end */ -+ nrgn->rgn_eprev = rgn; /* of list */ -+ nrgn->rgn_enext = NULL; -+ rgn->rgn_enext = elan3mmu->elan3mmu_etail = nrgn; -+ } -+ else -+ { -+ if ((u_long)nbase >= (u_long)base || (u_long)ntop >= (u_long)base) -+ return (-1); /* overlapping region */ -+ -+ nrgn->rgn_enext = rgn; /* insert before region */ -+ nrgn->rgn_eprev = rgn->rgn_eprev; -+ rgn->rgn_eprev = nrgn; -+ if (elan3mmu->elan3mmu_ergns == rgn) -+ elan3mmu->elan3mmu_ergns = nrgn; -+ else -+ nrgn->rgn_eprev->rgn_enext = nrgn; -+ } -+ } -+ elan3mmu->elan3mmu_ergnlast = nrgn; -+ -+ return (0); -+} -+ -+ELAN3MMU_RGN * -+elan3mmu_removergn_elan (ELAN3MMU *elan3mmu, E3_Addr addr) -+{ -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_elan (elan3mmu, addr, 0); -+ -+ ASSERT (SPINLOCK_HELD (&elan3mmu->elan3mmu_dev->IntrLock) && SPINLOCK_HELD (&elan3mmu->elan3mmu_lock)); -+ -+ if (rgn == NULL || rgn->rgn_ebase != addr) -+ return (NULL); -+ -+ elan3mmu->elan3mmu_ergnlast = rgn->rgn_enext; -+ if (rgn == elan3mmu->elan3mmu_etail) -+ elan3mmu->elan3mmu_etail = rgn->rgn_eprev; -+ else -+ rgn->rgn_enext->rgn_eprev = rgn->rgn_eprev; -+ -+ if (rgn == elan3mmu->elan3mmu_ergns) -+ elan3mmu->elan3mmu_ergns = rgn->rgn_enext; -+ else -+ rgn->rgn_eprev->rgn_enext = rgn->rgn_enext; -+ -+ return (rgn); -+} -+ -+ELAN3MMU_RGN * -+elan3mmu_rgnat_elan (ELAN3MMU *elan3mmu, E3_Addr addr) -+{ -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_elan (elan3mmu, addr, 0); -+ E3_Addr base; -+ -+ if (rgn != NULL && (u_long)(base = rgn->rgn_ebase) <= (u_long)addr && (u_long)addr <= (u_long)(base + rgn->rgn_len - 1)) -+ return (rgn); -+ return (NULL); -+} -+ -+/* main address region management */ -+ELAN3MMU_RGN * -+elan3mmu_findrgn_main (ELAN3MMU *elan3mmu, -+ caddr_t addr, int tail) -+{ -+ ELAN3MMU_RGN *next = NULL; -+ ELAN3MMU_RGN *rgn; -+ ELAN3MMU_RGN *hirgn; -+ ELAN3MMU_RGN *lorgn; -+ caddr_t lastaddr; -+ caddr_t base; -+ int forward; -+ -+ ASSERT (SPINLOCK_HELD (&elan3mmu->elan3mmu_dev->IntrLock) || SPINLOCK_HELD (&elan3mmu->elan3mmu_lock)); -+ -+ if (elan3mmu->elan3mmu_mrgns == NULL) -+ return (NULL); -+ -+ rgn = elan3mmu->elan3mmu_mrgnlast; -+ if (rgn == NULL) -+ rgn = elan3mmu->elan3mmu_mrgns; -+ -+ forward = 0; -+ if ((base = rgn->rgn_mbase) < addr) -+ { -+ if (addr <= (base + rgn->rgn_len - 1)) -+ return (rgn); /* ergnlast contained addr */ -+ -+ hirgn = elan3mmu->elan3mmu_mtail; -+ if ((lastaddr = hirgn->rgn_mbase + hirgn->rgn_len - 1) < addr) -+ return (tail ? hirgn : NULL); /* addr is out of range */ -+ -+ if ((addr - base) > (lastaddr - addr)) -+ rgn = hirgn; -+ else -+ { -+ rgn = rgn->rgn_mnext; -+ forward++; -+ } -+ } -+ else -+ { -+ lorgn = elan3mmu->elan3mmu_mrgns; -+ if (lorgn->rgn_mbase > addr) -+ return (lorgn); /* lowest regions is higher than addr */ -+ if ((addr - lorgn->rgn_mbase) < (base - addr)) -+ { -+ rgn = lorgn; /* search forward from head */ -+ forward++; -+ } -+ } -+ if (forward) -+ { -+ while ((rgn->rgn_mbase + rgn->rgn_len - 1) < addr) -+ rgn = rgn->rgn_mnext; -+ -+ if (rgn->rgn_mbase <= addr) -+ elan3mmu->elan3mmu_mrgnlast = rgn; -+ return (rgn); -+ } -+ else -+ { -+ while (rgn->rgn_mbase > addr) -+ { -+ next = rgn; -+ rgn = rgn->rgn_mprev; -+ } -+ if ((rgn->rgn_mbase + rgn->rgn_len - 1) < addr) -+ return (next); -+ else -+ { -+ elan3mmu->elan3mmu_mrgnlast = rgn; -+ return (rgn); -+ } -+ } -+} -+ -+int -+elan3mmu_addrgn_main (ELAN3MMU *elan3mmu, ELAN3MMU_RGN *nrgn) -+{ -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_main (elan3mmu, nrgn->rgn_mbase, 1); -+ caddr_t nbase = nrgn->rgn_mbase; -+ caddr_t ntop = nbase + nrgn->rgn_len - 1; -+ caddr_t base; -+ -+ ASSERT (SPINLOCK_HELD (&elan3mmu->elan3mmu_dev->IntrLock) && SPINLOCK_HELD (&elan3mmu->elan3mmu_lock)); -+ -+ if (rgn == NULL) -+ { -+ elan3mmu->elan3mmu_mrgns = elan3mmu->elan3mmu_mtail = nrgn; -+ nrgn->rgn_mnext = nrgn->rgn_mprev = NULL; -+ } -+ else -+ { -+ base = rgn->rgn_mbase; -+ -+ if ((base + rgn->rgn_len - 1) < nbase) /* top of region below requested address */ -+ { /* so insert after region (and hence at end */ -+ nrgn->rgn_mprev = rgn; /* of list */ -+ nrgn->rgn_mnext = NULL; -+ rgn->rgn_mnext = elan3mmu->elan3mmu_mtail = nrgn; -+ } -+ else -+ { -+ if (nbase >= base || ntop >= base) -+ return (-1); /* overlapping region */ -+ -+ nrgn->rgn_mnext = rgn; /* insert before region */ -+ nrgn->rgn_mprev = rgn->rgn_mprev; -+ rgn->rgn_mprev = nrgn; -+ if (elan3mmu->elan3mmu_mrgns == rgn) -+ elan3mmu->elan3mmu_mrgns = nrgn; -+ else -+ nrgn->rgn_mprev->rgn_mnext = nrgn; -+ } -+ } -+ elan3mmu->elan3mmu_mrgnlast = nrgn; -+ -+ return (0); -+} -+ -+ELAN3MMU_RGN * -+elan3mmu_removergn_main (ELAN3MMU *elan3mmu, caddr_t addr) -+{ -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_main (elan3mmu, addr, 0); -+ -+ ASSERT (SPINLOCK_HELD (&elan3mmu->elan3mmu_dev->IntrLock) && SPINLOCK_HELD (&elan3mmu->elan3mmu_lock)); -+ -+ if (rgn == NULL || rgn->rgn_mbase != addr) -+ return (NULL); -+ -+ elan3mmu->elan3mmu_mrgnlast = rgn->rgn_mnext; -+ if (rgn == elan3mmu->elan3mmu_mtail) -+ elan3mmu->elan3mmu_mtail = rgn->rgn_mprev; -+ else -+ rgn->rgn_mnext->rgn_mprev = rgn->rgn_mprev; -+ -+ if (rgn == elan3mmu->elan3mmu_mrgns) -+ elan3mmu->elan3mmu_mrgns = rgn->rgn_mnext; -+ else -+ rgn->rgn_mprev->rgn_mnext = rgn->rgn_mnext; -+ -+ return (rgn); -+} -+ -+ELAN3MMU_RGN * -+elan3mmu_rgnat_main (ELAN3MMU *elan3mmu, caddr_t addr) -+{ -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_main (elan3mmu, addr, 0); -+ caddr_t base; -+ -+ if (rgn != NULL && (base = rgn->rgn_mbase) <= addr && addr <= (base + rgn->rgn_len - 1)) -+ return (rgn); -+ return (NULL); -+} -+ -+int -+elan3mmu_setperm (ELAN3MMU *elan3mmu, -+ caddr_t maddr, -+ E3_Addr eaddr, -+ u_int len, -+ u_int perm) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3MMU_RGN *nrgn; -+ unsigned long flags; -+ -+ HAT_PRINTF4 (1, "elan3mmu_setperm: user %p elan %08x len %x perm %x\n", maddr, eaddr, len, perm); -+ -+ if ((((uintptr_t) maddr) & PAGEOFFSET) || (eaddr & PAGEOFFSET) || (len & PAGEOFFSET)) -+ { -+ HAT_PRINTF0 (1, "elan3mmu_setperm: alignment failure\n"); -+ return (EINVAL); -+ } -+ -+ if (((uintptr_t) maddr + len - 1) < (uintptr_t) maddr || ((u_long)eaddr + len - 1) < (u_long)eaddr) -+ { -+ HAT_PRINTF0 (1, "elan3mmu_setperm: range failure\n"); -+ return (EINVAL); -+ } -+ -+ ALLOC_ELAN3MMU_RGN(nrgn, TRUE); -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ nrgn->rgn_mbase = maddr; -+ nrgn->rgn_ebase = eaddr; -+ nrgn->rgn_len = len; -+ nrgn->rgn_perm = perm; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ if (elan3mmu_addrgn_elan (elan3mmu, nrgn) < 0) -+ { -+ HAT_PRINTF0 (1, "elan3mmu_setperm: elan address exists\n"); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ FREE_ELAN3MMU_RGN (nrgn); -+ return (EINVAL); -+ } -+ -+ if (elan3mmu_addrgn_main (elan3mmu, nrgn) < 0) -+ { -+ HAT_PRINTF0 (1, "elan3mmu_setperm: main address exists\n"); -+ elan3mmu_removergn_elan (elan3mmu, eaddr); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ FREE_ELAN3MMU_RGN (nrgn); -+ return (EINVAL); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ return (ESUCCESS); -+} -+ -+void -+elan3mmu_clrperm (ELAN3MMU *elan3mmu, -+ E3_Addr addr, -+ u_int len) -+{ -+ E3_Addr raddr; -+ E3_Addr rtop; -+ ELAN3MMU_RGN *nrgn; -+ ELAN3MMU_RGN *rgn; -+ ELAN3MMU_RGN *rgn_next; -+ u_int ssize; -+ unsigned long flags; -+ int res; -+ -+ HAT_PRINTF2 (1, "elan3mmu_clrperm: elan %08x len %x\n", addr, len); -+ -+ raddr = (addr & PAGEMASK); -+ rtop = ((addr + len - 1) & PAGEMASK) + PAGEOFFSET; -+ -+ ALLOC_ELAN3MMU_RGN (nrgn, TRUE); -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ -+ for (rgn = elan3mmu_findrgn_elan (elan3mmu, addr, 0); rgn != NULL; rgn = rgn_next) -+ { -+ if (rtop < rgn->rgn_ebase) /* rtop was in a gap */ -+ break; -+ -+ rgn_next = rgn->rgn_enext; /* Save next region pointer */ -+ -+ if (raddr <= rgn->rgn_ebase && rtop >= (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ { -+ /* whole region is cleared */ -+ elan3mmu_unload (elan3mmu, rgn->rgn_ebase, rgn->rgn_len, PTE_UNLOAD); -+ -+ spin_lock_irqsave (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ elan3mmu_removergn_elan (elan3mmu, rgn->rgn_ebase); -+ elan3mmu_removergn_main (elan3mmu, rgn->rgn_mbase); -+ spin_unlock_irqrestore (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ -+ FREE_ELAN3MMU_RGN (rgn); -+ } -+ else if (raddr <= rgn->rgn_ebase) -+ { -+ /* clearing at beginning, so shrink size and increment base ptrs */ -+ ssize = rtop - rgn->rgn_ebase + 1; -+ -+ elan3mmu_unload (elan3mmu, rgn->rgn_ebase, ssize, PTE_UNLOAD); -+ -+ spin_lock_irqsave (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ rgn->rgn_mbase += ssize; -+ rgn->rgn_ebase += ssize; -+ rgn->rgn_len -= ssize; -+ spin_unlock_irqrestore (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ -+ } -+ else if (rtop >= (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ { -+ /* clearing at end, so just shrink length of region */ -+ ssize = ((rgn->rgn_ebase + rgn->rgn_len - 1) - raddr) + 1; -+ -+ elan3mmu_unload (elan3mmu, raddr, ssize, PTE_UNLOAD); -+ -+ spin_lock_irqsave (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ rgn->rgn_len -= ssize; -+ spin_unlock_irqrestore (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ } -+ else -+ { -+ /* the section to go is in the middle, so need to */ -+ /* split it into two regions */ -+ elan3mmu_unload (elan3mmu, raddr, rtop - raddr + 1, PTE_UNLOAD); -+ -+ spin_lock_irqsave (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ -+ ASSERT (nrgn != NULL); -+ -+ nrgn->rgn_mbase = rgn->rgn_mbase + (rtop - rgn->rgn_ebase + 1);; -+ nrgn->rgn_ebase = rtop + 1; -+ nrgn->rgn_len = ((rgn->rgn_ebase + rgn->rgn_len - 1) - rtop); -+ nrgn->rgn_perm = rgn->rgn_perm; -+ -+ rgn->rgn_len = (raddr - rgn->rgn_ebase); /* shrink original region */ -+ -+ res = elan3mmu_addrgn_elan (elan3mmu, nrgn); /* insert new region */ -+ ASSERT (res == 0); /* which cannot fail */ -+ -+ res = elan3mmu_addrgn_main (elan3mmu, nrgn); -+ ASSERT (res == 0); -+ spin_unlock_irqrestore (&elan3mmu->elan3mmu_dev->IntrLock, flags); -+ -+ nrgn = NULL; -+ } -+ } -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ if (nrgn != NULL) -+ FREE_ELAN3MMU_RGN (nrgn); -+} -+ -+int -+elan3mmu_checkperm (ELAN3MMU *elan3mmu, -+ E3_Addr addr, -+ u_int len, -+ u_int access) -+{ -+ E3_Addr raddr = (((E3_Addr) addr) & PAGEMASK); -+ u_int rtop = ((addr + len - 1) & PAGEMASK) + PAGEOFFSET; -+ u_int rsize = rtop - raddr + 1; -+ ELAN3MMU_RGN *rgn; -+ -+ HAT_PRINTF3 (1, "elan3mmu_checkperm: user %08x len %x access %x\n", addr, len, access); -+ -+ -+ if ((raddr + rsize - 1) < raddr) -+ return (ENOMEM); -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ if ((rgn = elan3mmu_rgnat_elan (elan3mmu, raddr)) == (ELAN3MMU_RGN *) NULL) -+ { -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ return (ENOMEM); -+ } -+ else -+ { -+ register int ssize; -+ -+ for (; rsize != 0; rsize -= ssize, raddr += ssize) -+ { -+ if (raddr > (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ { -+ rgn = rgn->rgn_enext; -+ -+ if (rgn == NULL || raddr != rgn->rgn_ebase) -+ { -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ return (ENOMEM); -+ } -+ } -+ if ((raddr + rsize - 1) > (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ ssize = ((rgn->rgn_ebase + rgn->rgn_len - 1) - raddr) + 1; -+ else -+ ssize = rsize; -+ -+ HAT_PRINTF4 (1, "elan3mmu_checkperm : rgn %x -> %x perm %x access %x\n", -+ rgn->rgn_ebase, rgn->rgn_ebase + rgn->rgn_len, rgn->rgn_perm, access); -+ -+ if (ELAN3_INCOMPAT_ACCESS (rgn->rgn_perm, access)) -+ { -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ return (EACCES); -+ } -+ } -+ } -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ return (ESUCCESS); -+} -+ -+caddr_t -+elan3mmu_mainaddr (ELAN3MMU *elan3mmu, E3_Addr addr) -+{ -+ ELAN3MMU_RGN *rgn; -+ caddr_t raddr; -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ if ((rgn = elan3mmu_rgnat_elan (elan3mmu, addr)) == (ELAN3MMU_RGN *) NULL) -+ raddr = NULL; -+ else -+ raddr = rgn->rgn_mbase + (addr - rgn->rgn_ebase); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ return (raddr); -+} -+ -+E3_Addr -+elan3mmu_elanaddr (ELAN3MMU *elan3mmu, caddr_t addr) -+{ -+ ELAN3MMU_RGN *rgn; -+ E3_Addr raddr; -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ if ((rgn = elan3mmu_rgnat_main (elan3mmu, addr)) == (ELAN3MMU_RGN *) NULL) -+ raddr = (E3_Addr) 0; -+ else -+ raddr = rgn->rgn_ebase + (addr - rgn->rgn_mbase); -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+ -+ return (raddr); -+} -+ -+void -+elan3mmu_displayrgns(ELAN3MMU *elan3mmu) -+{ -+ ELAN3MMU_RGN *rgn; -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ HAT_PRINTF0 (1, "elan3mmu_displayrgns: main regions\n"); -+ for (rgn = elan3mmu->elan3mmu_mrgns; rgn; rgn = (rgn->rgn_mnext == elan3mmu->elan3mmu_mrgns) ? NULL : rgn->rgn_mnext) -+ HAT_PRINTF5 (1, " RGN %p ebase %08x mbase %p len %08x perm %08x\n", rgn, rgn->rgn_ebase, rgn->rgn_mbase, rgn->rgn_len, rgn->rgn_perm); -+ HAT_PRINTF0 (1, "elan3mmu_displayrgns: elan regions\n"); -+ for (rgn = elan3mmu->elan3mmu_ergns; rgn; rgn = (rgn->rgn_enext == elan3mmu->elan3mmu_ergns) ? NULL : rgn->rgn_enext) -+ HAT_PRINTF5 (1, " RGN %p ebase %08x mbase %p len %08x perm %08x\n", rgn, rgn->rgn_ebase, rgn->rgn_mbase, rgn->rgn_len, rgn->rgn_perm); -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+} -+ -+/*============================================================================*/ -+/* Private functions */ -+#define ELAN3_PTE_IS_VALID(ptbl, pte) \ -+ ((ptbl->ptbl_flags & PTBL_KERNEL) ? \ -+ (pte&(~ELAN3_PTE_REF)) != elan3mmu_kernel_invalid_pte(ptbl->ptbl_elan3mmu) : \ -+ ELAN3_PTE_VALID(pte)) -+ -+void -+elan3mmu_expand (ELAN3MMU *elan3mmu, E3_Addr addr, int len, int level, int attr) -+{ -+ ELAN3_PTBL *ptbl; -+ sdramaddr_t pte; -+ spinlock_t *lock; -+ u_int span; -+ unsigned long flags; -+ -+ HAT_PRINTF3 (1, "elan3mmu_expand: elan3mmu %p %08x to %08x\n", elan3mmu, -+ addr, addr + len); -+ -+ for ( ; len != 0; addr += span, len -= span) -+ { -+ /* as we asked for level 3 we know its a pte */ -+ pte = elan3mmu_ptealloc (elan3mmu, addr, level, &ptbl, &lock, attr, &flags); -+ -+ switch (level) -+ { -+ case PTBL_LEVEL_3: -+ span = MIN(len, ELAN3_L3_PTSIZE - ((E3_Addr) addr & ELAN3_L3_PTOFFSET)); -+ break; -+ case PTBL_LEVEL_2: -+ span = MIN(len, ELAN3_L2_PTSIZE - ((E3_Addr) addr & ELAN3_L2_PTOFFSET)); -+ break; -+ default: -+ span = len; -+ break; -+ } -+ -+ if (pte != (sdramaddr_t) 0) -+ elan3mmu_unlock_ptbl (ptbl, lock, flags); -+ } -+} -+ -+void -+elan3mmu_reserve (ELAN3MMU *elan3mmu, E3_Addr addr, u_int npages, sdramaddr_t *ptes) -+{ -+ ELAN3_PTBL *ptbl; -+ sdramaddr_t pte; -+ spinlock_t *lock; -+ u_int span; -+ int len; -+ int i; -+ unsigned long flags; -+ -+ HAT_PRINTF3 (1, "elan3mmu_reserve: elan3mmu %p %08x to %08x\n", elan3mmu, -+ addr, addr + (npages << ELAN3_PAGE_SHIFT)); -+ -+ for (len = (npages << ELAN3_PAGE_SHIFT); len != 0; addr += span, len -= span) -+ { -+ /* as we asked for level 3 we know its a pte */ -+ pte = elan3mmu_ptealloc (elan3mmu, addr, 3, &ptbl, &lock, 0, &flags); -+ -+ span = MIN(len, ELAN3_L3_PTSIZE - ((E3_Addr) addr & ELAN3_L3_PTOFFSET)); -+ -+ if (ptes != NULL) -+ { -+ for (i = 0; i < span; i += ELAN3_PAGE_SIZE, pte += ELAN3_PTE_SIZE) -+ *ptes++ = pte; -+ ptbl->ptbl_valid += (span >> ELAN3_PAGE_SHIFT); -+ -+ HAT_PRINTF4 (2, "elan3mmu_reserve: inc valid for level %d ptbl %p to %d (%d)\n", -+ PTBL_LEVEL(ptbl->ptbl_flags), ptbl, ptbl->ptbl_valid, (span >> ELAN3_PAGE_SHIFT)); -+ -+ } -+ -+ elan3mmu_unlock_ptbl (ptbl, lock, flags); -+ } -+} -+ -+void -+elan3mmu_release (ELAN3MMU *elan3mmu, E3_Addr addr, u_int npages, sdramaddr_t *ptes) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTBL *ptbl; -+ sdramaddr_t pte; -+ ELAN3_PTE tpte; -+ spinlock_t *lock; -+ u_int span; -+ int len; -+ int i; -+ int level; -+ unsigned long flags; -+ -+ HAT_PRINTF3 (1, "elan3mmu_release: elan3mmu %p %08x to %08x\n", elan3mmu, -+ addr, addr + (npages << ELAN3_PAGE_SHIFT)); -+ -+ if (ptes == NULL) -+ return; -+ -+ tpte = elan3mmu_kernel_invalid_pte (elan3mmu); -+ -+ for (len = (npages << ELAN3_PAGE_SHIFT); len != 0; addr += span, len -= span) -+ { -+ /* as we asked for level 3 we know its a pte */ -+ pte = elan3mmu_ptefind(elan3mmu, addr, &level, &ptbl, &lock, &flags); -+ ASSERT (level == PTBL_LEVEL_3); -+ -+ span = MIN(len, ELAN3_L3_PTSIZE - ((E3_Addr) addr & ELAN3_L3_PTOFFSET)); -+ -+ -+ for (i = 0 ; i < span; i += ELAN3_PAGE_SIZE, pte += ELAN3_PTE_SIZE) -+ elan3_writepte (dev, pte, tpte); -+ ptbl->ptbl_valid -= (span >> ELAN3_PAGE_SHIFT); -+ -+ HAT_PRINTF3 (2, "elan3mmu_release: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(ptbl->ptbl_flags), ptbl, ptbl->ptbl_valid); -+ -+ elan3mmu_unlock_ptbl (ptbl, lock, flags); -+ } -+ ElanFlushTlb (elan3mmu->elan3mmu_dev); -+} -+ -+void -+elan3mmu_pteload (ELAN3MMU *elan3mmu, int level, E3_Addr addr, physaddr_t paddr, int perm, int attr) -+ -+{ -+ ELAN3_DEV *dev; -+ ELAN3_PTBL *ptbl; -+ spinlock_t *lock; -+ unsigned long flags; -+ ELAN3_PTE newpte; -+ ELAN3_PTE oldpte; -+ sdramaddr_t pte; -+ -+ ASSERT((level == PTBL_LEVEL_2) || (level == PTBL_LEVEL_3)); -+ -+ /* Generate the new pte which we're going to load */ -+ dev = elan3mmu->elan3mmu_dev; -+ -+ newpte = elan3mmu_phys_to_pte (dev, paddr, perm); -+ -+ if (attr & PTE_LOAD_BIG_ENDIAN) -+ newpte |= ELAN3_PTE_BIG_ENDIAN; -+ -+ HAT_PRINTF4 (1, "elan3mmu_pteload: elan3mmu %p level %d addr %x pte %llx\n", elan3mmu, level, addr, (long long) newpte); -+ HAT_PRINTF5 (1, "elan3mmu_pteload:%s%s%s perm=%d phys=%llx\n", -+ (newpte & ELAN3_PTE_LOCAL) ? " local" : "", -+ (newpte & ELAN3_PTE_64_BIT) ? " 64 bit" : "", -+ (newpte & ELAN3_PTE_BIG_ENDIAN) ? " big-endian" : " little-endian", -+ (u_int) (newpte & ELAN3_PTE_PERM_MASK) >> ELAN3_PTE_PERM_SHIFT, -+ (unsigned long long) (newpte & ELAN3_PTE_PFN_MASK)); -+ -+ if (level == PTBL_LEVEL_3) -+ pte = elan3mmu_ptealloc (elan3mmu, addr, level, &ptbl, &lock, attr, &flags); -+ else -+ { -+ sdramaddr_t ptp = elan3mmu_ptealloc (elan3mmu, addr, level, &ptbl, &lock, attr, &flags); -+ -+ pte = elan3mmu_ptp2pte (elan3mmu, ptp, level); -+ -+ HAT_PRINTF3 (2, "elan3mmu_pteload: level %d ptp at %lx => pte at %lx\n", level, ptp, pte); -+ } -+ -+ if (pte == (sdramaddr_t) 0) -+ { -+ ASSERT (level == PTBL_LEVEL_3 && (attr & (PTE_NO_SLEEP | PTE_NO_STEAL)) == (PTE_NO_SLEEP | PTE_NO_STEAL)); -+ return; -+ } -+ -+ ASSERT (ptbl->ptbl_elan3mmu == elan3mmu); -+ ASSERT (PTBL_LEVEL(ptbl->ptbl_flags) == level); -+ ASSERT (PTBL_IS_LOCKED (ptbl->ptbl_flags)); -+ -+ oldpte = elan3_readpte (dev, pte); -+ -+ HAT_PRINTF3 (2, "elan3mmu_pteload: modify pte at %lx from %llx to %llx\n", pte, (long long) oldpte, (long long) newpte); -+ -+ if (ELAN3_PTE_IS_VALID(ptbl, oldpte)) -+ { -+ ELAN3MMU_STAT(ptereload); -+ -+ ASSERT ((newpte & ~((E3_uint64)ELAN3_PTE_PERM_MASK | ELAN3_RM_MASK)) == (oldpte & ~((E3_uint64)ELAN3_PTE_PERM_MASK | ELAN3_RM_MASK))); -+ -+ if ((newpte & ~ELAN3_RM_MASK) != (oldpte & ~ELAN3_RM_MASK)) -+ { -+ /* We're modifying a valid translation, it must be mapping the same page */ -+ /* so we use elan3_modifypte to not affect the referenced and modified bits */ -+ elan3_modifypte (dev, pte, newpte); -+ -+ -+ ElanFlushTlb (elan3mmu->elan3mmu_dev); -+ } -+ } -+ else -+ { -+ ELAN3MMU_STAT(pteload); -+ -+ ptbl->ptbl_valid++; -+ -+ HAT_PRINTF3 (2, "elan3mmu_pteload: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(ptbl->ptbl_flags), ptbl, ptbl->ptbl_valid); -+ -+ HAT_PRINTF2 (2, "elan3mmu_pteload: write pte %lx to %llx\n", pte, (long long) newpte); -+ -+ elan3_writepte (dev, pte, newpte); -+ -+ if (ptbl->ptbl_flags & PTBL_KERNEL) -+ ElanFlushTlb (elan3mmu->elan3mmu_dev); -+ -+ } -+ -+ elan3mmu_unlock_ptbl (ptbl, lock, flags); -+} -+ -+void -+elan3mmu_unload (ELAN3MMU *elan3mmu, E3_Addr addr, u_int len, int attr) -+{ -+ ELAN3_PTBL *ptbl; -+ sdramaddr_t ptp; -+ spinlock_t *lock; -+ int level; -+ u_int span; -+ unsigned long flags; -+ -+ HAT_PRINTF3(1, "elan3mmu_unload (elan3mmu %p addr %x -> %x)\n", elan3mmu, addr, addr+len-1); -+ -+ for (; len != 0; addr += span, len -= span) -+ { -+ ptp = elan3mmu_ptefind(elan3mmu, addr, &level, &ptbl, &lock, &flags); -+ -+ span = MIN(len, ELAN3_L3_PTSIZE - ((E3_Addr) addr & ELAN3_L3_PTOFFSET)); -+ -+ if (ptp != (sdramaddr_t) 0) -+ { -+ HAT_PRINTF2 (2, "elan3mmu_unload: unload [%x,%x]\n", addr, addr + span); -+ -+ if ( level == PTBL_LEVEL_3 ) -+ elan3mmu_unload_loop (elan3mmu, ptbl, ptp - PTBL_TO_PTADDR(ptbl), span >> ELAN3_PAGE_SHIFT, attr); -+ else -+ { -+ ELAN3_PTP invalidptp = ELAN3_INVALID_PTP; -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTBL *lXptbl; -+ ELAN3_PTP tptp; -+ int idx; -+ -+ tptp = elan3_readptp (elan3mmu->elan3mmu_dev, ptp); -+ -+ ASSERT (ELAN3_PTP_TYPE(tptp) == ELAN3_ET_PTE); -+ -+ lXptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tptp); -+ idx = (PTP_TO_PT_PADDR(tptp) - PTBL_TO_PTADDR(lXptbl))/ELAN3_PTE_SIZE; -+ -+ if ( level == PTBL_LEVEL_1) -+ span = MIN(len, ELAN3_L2_PTSIZE - ((E3_Addr) addr & ELAN3_L2_PTOFFSET)); -+ else -+ span = MIN(len, ELAN3_L3_PTSIZE - ((E3_Addr) addr & ELAN3_L3_PTOFFSET)); -+ -+ /* invalidate the ptp. */ -+ elan3_writeptp (dev, ptp, invalidptp); -+ if (! (attr & PTE_UNLOAD_NOFLUSH)) -+ ElanFlushTlb (dev); -+ -+ elan3mmu_free_pte ( dev, elan3mmu, lXptbl, idx); -+ -+ ptbl->ptbl_valid--; -+ -+ HAT_PRINTF3 (2, "elan3mmu_unload: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(ptbl->ptbl_flags), ptbl, ptbl->ptbl_valid); -+ -+ } -+ elan3mmu_unlock_ptbl (ptbl, lock, flags); -+ } -+ } -+} -+ -+static void -+elan3mmu_unload_loop (ELAN3MMU *elan3mmu, ELAN3_PTBL *ptbl, int first_valid, int nptes, int flags) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ sdramaddr_t pte; -+ ELAN3_PTE tpte; -+ int last_valid = first_valid + nptes; -+ int i; -+ -+ HAT_PRINTF3 (1, "elan3mmu_unloadloop: ptbl %p entries [%d->%d]\n", ptbl, first_valid, last_valid); -+ -+ ASSERT (PTBL_IS_LOCKED (ptbl->ptbl_flags)); -+ ASSERT (PTBL_LEVEL(ptbl->ptbl_flags) == PTBL_LEVEL_3); -+ -+ pte = PTBL_TO_PTADDR(ptbl) + first_valid; -+ -+ for (i = first_valid; i < last_valid; i++, pte += ELAN3_PTE_SIZE) -+ { -+ if (ptbl->ptbl_valid == 0) -+ break; -+ -+ tpte = elan3_readpte (dev, pte); -+ if (! ELAN3_PTE_IS_VALID(ptbl, tpte)) -+ continue; -+ -+ elan3mmu_pteunload (ptbl, pte, flags, NO_MLIST_LOCK); -+ } -+} -+ -+void -+elan3mmu_pteunload (ELAN3_PTBL *ptbl, sdramaddr_t pte, int flags, int got_mlist_lock) -+{ -+ ELAN3_DEV *dev = ptbl->ptbl_elan3mmu->elan3mmu_dev; -+ ELAN3_PTE tpte; -+ -+ ASSERT (PTBL_LEVEL (ptbl->ptbl_flags) == PTBL_LEVEL_3); -+ ASSERT (PTBL_IS_LOCKED (ptbl->ptbl_flags)); -+ -+ HAT_PRINTF2 (1, "elan3mmu_pteunload: ptbl %p pte %lx\n", ptbl, pte); -+ -+ ELAN3MMU_STAT (pteunload); -+ -+ elan3_invalidatepte (dev, pte); -+ -+ if (! (flags & PTE_UNLOAD_NOFLUSH)) -+ ElanFlushTlb (dev); -+ -+ tpte = ELAN3_INVALID_PTE; -+ elan3_writepte (dev, pte, tpte); -+ -+ if (ptbl->ptbl_flags & PTBL_KERNEL) -+ { -+ tpte = elan3mmu_kernel_invalid_pte(ptbl->ptbl_elan3mmu); -+ -+ elan3_writepte (dev, pte, tpte); -+ } -+ -+ ptbl->ptbl_valid--; -+ -+ HAT_PRINTF3 (2, "elan3mmu_pteunload: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(ptbl->ptbl_flags), ptbl, ptbl->ptbl_valid); -+ -+} -+ -+void -+elan3mmu_ptesync (ELAN3_PTBL *ptbl, sdramaddr_t pte, int flags, int got_mlist_lock) -+{ -+ -+} -+ -+/* -+ * Create more page tables at a given level for this Elan. -+ */ -+static ELAN3_PTBL * -+elan3mmu_create_ptbls (ELAN3_DEV *dev, int level, int attr, int keep) -+{ -+ sdramaddr_t pts; -+ ELAN3_PTBL *ptbl; -+ ELAN3_PTBL *first; -+ ELAN3_PTBL *last; -+ ELAN3_PTBL_GR *ptg; -+ register int i; -+ register int inc; -+ -+ HAT_PRINTF1 (2, "elan3mmu_create_ptbls: create level %d ptbls\n", level); -+ -+ pts = elan3_sdram_alloc (dev, PTBL_GROUP_SIZE); -+ if (pts == (sdramaddr_t) 0) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_create_ptbls: cannot map elan pages\n"); -+ -+ ELAN3MMU_STAT (create_ptbl_failed); -+ return (NULL); -+ } -+ -+ HAT_PRINTF1 (2, "elan3mmu_create_ptbls: pts at %lx\n", pts); -+ -+ ALLOC_PTBL_GR (ptg, !(attr & PTE_NO_SLEEP)); /* Allocate the group of page tables */ -+ if (ptg == NULL) /* for this page */ -+ { -+ HAT_PRINTF0 (2, "elan3mmu_create_ptbls: cannot allocate page table group\n"); -+ -+ elan3_sdram_free (dev, pts, PTBL_GROUP_SIZE); -+ -+ ELAN3MMU_STAT (create_ptbl_failed); -+ return (NULL); -+ } -+ -+ HAT_PRINTF1 (2, "elan3mmu_create_ptbls: ptg is %p\n", ptg); -+ -+ ElanSetPtblGr (dev, pts, ptg); -+ -+ HAT_PRINTF4 (2, "elan3mmu_create_ptbls: zeroing %d bytes at %lx, %d bytes at %p\n", -+ PTBL_GROUP_SIZE, pts, (int) sizeof (ELAN3_PTBL_GR), ptg); -+ -+#ifndef zero_all_ptbls -+ elan3_sdram_zeroq_sdram (dev, pts, PTBL_GROUP_SIZE); /* Ensure that all PTEs/PTPs are invalid */ -+#endif -+ bzero ((caddr_t) ptg, sizeof (ELAN3_PTBL_GR)); -+ -+ ptg->pg_addr = pts; -+ ptg->pg_level = level; -+ -+ ptbl = ptg->pg_ptbls; /* Initialise the index in all page tables */ -+ for (i = 0; i < PTBLS_PER_GROUP_MAX; i++) -+ { -+ ptbl->ptbl_index = (u_char) i; -+ ptbl->ptbl_next = (ELAN3_PTBL *) 0xdeaddead; -+ ptbl++; -+ } -+ -+ switch (level) /* Determine the number of ptbls we can */ -+ { /* allocate from this page, by jumping */ -+ case PTBL_LEVEL_X: inc = PTBLS_PER_PTBL_LX; break; /* multiples of the smallest. */ -+ case PTBL_LEVEL_1: inc = PTBLS_PER_PTBL_L1; break; -+ case PTBL_LEVEL_2: inc = PTBLS_PER_PTBL_L2; break; -+ case PTBL_LEVEL_3: inc = PTBLS_PER_PTBL_L3; break; -+ default: inc = PTBLS_PER_PTBL_L3; break; -+ } -+ -+ ptbl = ptg->pg_ptbls; /* Chain them together */ -+ for (i = 0; i < PTBLS_PER_GROUP_MAX; i += inc, ptbl += inc) -+ ptbl->ptbl_next = ptbl + inc; -+ -+ first = ptg->pg_ptbls; /* Determine list of */ -+ last = first + PTBLS_PER_GROUP_MAX - inc; /* ptbls to add to free list */ -+ if (! keep) -+ ptbl = NULL; -+ else -+ { -+ ptbl = first; -+ first = first->ptbl_next; -+ } -+ -+ spin_lock (&dev->Level[level].PtblLock); -+ dev->Level[level].PtblTotal += PTBLS_PER_GROUP_MAX/inc; /* Increment the counts */ -+ dev->Level[level].PtblFreeCount += PTBLS_PER_GROUP_MAX/inc; -+ -+ ELAN3MMU_SET_STAT (num_ptbl_level[level], dev->Level[level].PtblTotal); -+ -+ if (keep) -+ dev->Level[level].PtblFreeCount--; -+ -+ last->ptbl_next = dev->Level[level].PtblFreeList; /* And add to free list */ -+ dev->Level[level].PtblFreeList = first; -+ spin_unlock (&dev->Level[level].PtblLock); -+ -+ spin_lock (&dev->PtblGroupLock); -+ ptg->pg_next = dev->Level[level].PtblGroupList; -+ dev->Level[level].PtblGroupList = ptg; -+ spin_unlock (&dev->PtblGroupLock); -+ -+ HAT_PRINTF1 (2, "elan3mmu_create_ptbls: returning ptbl %p\n", ptbl); -+ -+ return (ptbl); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_ta_to_ptbl (ELAN3MMU *elan3mmu, ELAN3_PTP *ptp) -+{ -+ E3_Addr ptpa = PTP_TO_PT_PADDR(*ptp); -+ ELAN3_PTBL_GR *pg = ElanGetPtblGr (elan3mmu->elan3mmu_dev, (sdramaddr_t)ptpa & ~(PTBL_GROUP_SIZE-1)); -+ -+ return (pg->pg_ptbls + ((ptpa - pg->pg_addr) >> ELAN3_PT_SHIFT)); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_alloc_lXptbl (ELAN3_DEV *dev, int attr, ELAN3MMU *elan3mmu) -+{ -+ ELAN3_PTBL *ptbl = NULL; -+ -+ spin_lock (&dev->Level[PTBL_LEVEL_X].PtblLock); -+ if (dev->Level[PTBL_LEVEL_X].PtblFreeList) -+ { -+ ptbl = dev->Level[PTBL_LEVEL_X].PtblFreeList; -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_lXptbl: found ptbl %p on free list\n", ptbl); -+ -+ dev->Level[PTBL_LEVEL_X].PtblFreeList = ptbl->ptbl_next; -+ dev->Level[PTBL_LEVEL_X].PtblFreeCount--; -+ } -+ spin_unlock (&dev->Level[PTBL_LEVEL_X].PtblLock); -+ -+ if (ptbl == NULL) -+ { -+ ptbl = elan3mmu_create_ptbls (dev, PTBL_LEVEL_X, attr, 1); -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_lXptbl: created level X ptbl %p\n", ptbl); -+ } -+ -+ if (ptbl == NULL) -+ { -+ if ((attr & PTE_NO_STEAL)) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_alloc_lXptbl: not allowed to steal ptbl for use at level 2\n"); -+ return NULL; -+ } -+ -+ ELAN3MMU_STAT(lX_alloc_l3); -+ -+ ptbl = elan3mmu_steal_l3ptbl (dev, attr); -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_lXptbl: stolen level3 ptbl %p used as level 2\n", ptbl); -+ } -+ -+ ptbl->ptbl_elan3mmu = elan3mmu; -+ ptbl->ptbl_base = 0; -+ ptbl->ptbl_parent = 0; -+ ptbl->ptbl_flags = PTBL_LEVEL_X | PTBL_ALLOCED; -+ -+ HAT_PRINTF2 (2, "elan3mmu_alloc_lXptbl: ptbl %p dev %p\n", ptbl, dev); -+ -+#ifdef zero_all_ptbls -+ elan3_sdram_zero_sdarm (dev, PTBL_TO_PTADDR(ptbl), ELAN3_LX_ENTRIES*ELAN3_PTE_SIZE); -+#endif -+ -+ return (ptbl); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_alloc_pte (ELAN3_DEV *dev, ELAN3MMU *elan3mmu, int *idx) -+{ -+ ELAN3_PTBL * ptbl_ptr; -+ int index; -+ -+ /* lock whilst looking for space */ -+ spin_lock (&elan3mmu->elan3mmu_lXptbl_lock); -+ -+ /* walk the lXptbl list */ -+ ptbl_ptr = elan3mmu->elan3mmu_lXptbl; -+ while ( ptbl_ptr != NULL ) -+ { -+ /* does this ptlb have any free ones */ -+ if ( (index = ptbl_ptr->ptbl_valid) < ELAN3_LX_ENTRIES) -+ { -+ /* better to search from valid count as its likly to be free */ -+ index = ptbl_ptr->ptbl_valid; -+ do { -+ if ((ptbl_ptr->ptbl_base & (1 << index)) == 0) -+ goto found; -+ -+ /* move index on and wrap back to start if needed */ -+ if ((++index) == ELAN3_LX_ENTRIES) -+ index = 0; -+ } while (index != ptbl_ptr->ptbl_valid); -+ -+ panic ("elan3mmu_alloc_pte: has ptbl valid < 32 when but no free pte's"); -+ } -+ ptbl_ptr = ptbl_ptr->ptbl_parent; -+ } -+ -+ /* unlock so we can create space */ -+ spin_unlock (&elan3mmu->elan3mmu_lXptbl_lock); -+ -+ /* if create some more */ -+ ptbl_ptr = elan3mmu_alloc_lXptbl(dev, 0, elan3mmu); -+ -+ /* get the lock again */ -+ spin_lock (&elan3mmu->elan3mmu_lXptbl_lock); -+ -+ /* add to front of list as its obviously got free ones on it */ -+ ptbl_ptr->ptbl_parent = elan3mmu->elan3mmu_lXptbl; -+ elan3mmu->elan3mmu_lXptbl = ptbl_ptr; -+ -+ /* grap the first one */ -+ index = 0; -+ -+ found: -+ ptbl_ptr->ptbl_base |= (1 << index); -+ ptbl_ptr->ptbl_valid++; -+ -+ HAT_PRINTF3 (2, "elan3mmu_alloc_pte: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(ptbl_ptr->ptbl_flags), ptbl_ptr, ptbl_ptr->ptbl_valid); -+ -+ /* release the loc and return it */ -+ spin_unlock (&elan3mmu->elan3mmu_lXptbl_lock); -+ -+ *idx = index; -+ return (ptbl_ptr); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_alloc_l1ptbl (ELAN3_DEV *dev, int attr, ELAN3MMU *elan3mmu) -+{ -+ ELAN3_PTBL *ptbl = NULL; -+ ELAN3_PTBL *p; -+ int i,j; -+ -+ spin_lock (&dev->Level[PTBL_LEVEL_1].PtblLock); -+ if (dev->Level[PTBL_LEVEL_1].PtblFreeList) -+ { -+ ptbl = dev->Level[PTBL_LEVEL_1].PtblFreeList; -+ dev->Level[PTBL_LEVEL_1].PtblFreeList = ptbl->ptbl_next; -+ dev->Level[PTBL_LEVEL_1].PtblFreeCount--; -+ } -+ spin_unlock (&dev->Level[PTBL_LEVEL_1].PtblLock); -+ -+ if (ptbl == NULL) -+ ptbl = elan3mmu_create_ptbls (dev, PTBL_LEVEL_1, attr, 1); -+ -+ if (ptbl == NULL) -+ panic ("elan3mmu_alloc_l1ptbl: cannot alloc ptbl"); -+ -+ for (p = ptbl, j = i = 0; i < PTBLS_PER_PTBL_L1; i++, p++) -+ { -+ p->ptbl_elan3mmu = elan3mmu; -+ p->ptbl_base = VA2BASE (j); -+ p->ptbl_flags = PTBL_LEVEL_1 | PTBL_GROUPED; -+ p->ptbl_parent = NULL; -+ -+ j += L1_VA_PER_PTBL; -+ } -+ -+ /* Now mark the real page table as allocated */ -+ /* level 1 ptbls are returned unlocked */ -+ ptbl->ptbl_flags = PTBL_LEVEL_1 | PTBL_ALLOCED; -+ -+ HAT_PRINTF2 (2, "elan3mmu_alloc_l1ptbl: ptbl %p dev %p\n", ptbl, dev); -+ -+#ifdef zero_all_ptbls -+ elan3_sdram_zeroq_sdram (dev, PTBL_TO_PTADDR(ptbl), ELAN3_L1_ENTRIES*ELAN3_PTP_SIZE); -+#endif -+ -+ return (ptbl); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_alloc_l2ptbl (ELAN3_DEV *dev, int attr, ELAN3_PTBL *parent, ELAN3MMU *elan3mmu, E3_Addr base, spinlock_t **plock, unsigned long *flags) -+{ -+ ELAN3_PTBL *ptbl = NULL; -+ ELAN3_PTBL *p; -+ int i; -+ int j; -+ unsigned long ptbl_flags; -+ -+ spin_lock_irqsave (&dev->Level[PTBL_LEVEL_2].PtblLock, ptbl_flags); -+ if (dev->Level[PTBL_LEVEL_2].PtblFreeList) -+ { -+ ptbl = dev->Level[PTBL_LEVEL_2].PtblFreeList; -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_l2ptbl: found ptbl %p on free list\n", ptbl); -+ -+ dev->Level[PTBL_LEVEL_2].PtblFreeList = ptbl->ptbl_next; -+ dev->Level[PTBL_LEVEL_2].PtblFreeCount--; -+ } -+ spin_unlock_irqrestore (&dev->Level[PTBL_LEVEL_2].PtblLock, ptbl_flags); -+ -+ if (ptbl == NULL) -+ { -+ ptbl = elan3mmu_create_ptbls (dev, PTBL_LEVEL_2, attr, 1); -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_l2ptbl: created level 2 ptbl %p\n", ptbl); -+ } -+ -+ if (ptbl == NULL) -+ { -+ if ((attr & PTE_NO_STEAL)) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_alloc_l2ptbl: not allowted to steal ptbl for use at level 2\n"); -+ return (NULL); -+ } -+ -+ ELAN3MMU_STAT(l2_alloc_l3); -+ -+ ptbl = elan3mmu_steal_l3ptbl (dev, attr); -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_l2ptbl: stolen level3 ptbl %p used as level 2\n", ptbl); -+ } -+ -+ *plock = elan3mmu_ptbl_to_lock (PTBL_LEVEL_2, ptbl); -+ spin_lock_irqsave (*plock, *flags); -+ -+ for (p = ptbl, j = i = 0; i < PTBLS_PER_PTBL_L2; i++, p++) -+ { -+ p->ptbl_elan3mmu = elan3mmu; -+ p->ptbl_base = VA2BASE (base + j); -+ p->ptbl_flags = PTBL_LEVEL_2 | PTBL_GROUPED; -+ p->ptbl_parent = parent; -+ -+ j += L2_VA_PER_PTBL; -+ } -+ -+ ptbl->ptbl_flags = PTBL_LEVEL_2 | PTBL_ALLOCED | PTBL_LOCKED; -+ -+ HAT_PRINTF3 (2, "elan3mmu_alloc_l2ptbl: ptbl %p dev %p base %x\n", ptbl, dev, base); -+ -+#ifdef zero_all_ptbls -+ elan3_sdram_zero_sdarm (dev, PTBL_TO_PTADDR(ptbl), ELAN3_L2_ENTRIES*ELAN3_PTP_SIZE); -+#endif -+ -+ return (ptbl); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_alloc_l3ptbl (ELAN3_DEV *dev, int attr, ELAN3_PTBL *parent, ELAN3MMU *elan3mmu, E3_Addr base, spinlock_t **plock, unsigned long *flags) -+{ -+ ELAN3_PTBL *ptbl = NULL; -+ ELAN3_PTBL *p; -+ int i; -+ int j; -+ unsigned long ptbl_flags; -+ -+ spin_lock_irqsave (&dev->Level[PTBL_LEVEL_3].PtblLock, ptbl_flags); -+ if (dev->Level[PTBL_LEVEL_3].PtblFreeList) -+ { -+ HAT_PRINTF1 (2, "elan3mmu_alloc_l3ptbl: found ptbl %p on free list\n", ptbl); -+ -+ ptbl = dev->Level[PTBL_LEVEL_3].PtblFreeList; -+ dev->Level[PTBL_LEVEL_3].PtblFreeList = ptbl->ptbl_next; -+ dev->Level[PTBL_LEVEL_3].PtblFreeCount--; -+ } -+ spin_unlock_irqrestore (&dev->Level[PTBL_LEVEL_3].PtblLock, ptbl_flags); -+ -+ if (ptbl == NULL) -+ { -+ ptbl = elan3mmu_create_ptbls (dev, PTBL_LEVEL_3, attr, 1); -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_l3ptbl: created level 3 ptbl %p\n", ptbl); -+ } -+ -+ if (ptbl == NULL) -+ { -+ if ((attr & PTE_NO_STEAL)) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_alloc_l3ptbl: not allowed to steal ptbl for use at level 3\n"); -+ return (NULL); -+ } -+ -+ ptbl = elan3mmu_steal_l3ptbl (dev, attr); -+ -+ HAT_PRINTF1 (2, "elan3mmu_alloc_l3ptbl: stolen level3 ptbl %p\n", ptbl); -+ } -+ -+ *plock = elan3mmu_ptbl_to_lock (PTBL_LEVEL_3, ptbl); -+ spin_lock_irqsave (*plock,*flags); -+ -+ for (p = ptbl, j = i = 0; i < PTBLS_PER_PTBL_L3; i++, p++) -+ { -+ p->ptbl_elan3mmu = elan3mmu; -+ p->ptbl_base = VA2BASE (base + j); -+ p->ptbl_flags = PTBL_LEVEL_3 | PTBL_GROUPED; -+ p->ptbl_parent = parent; -+ -+ j += L3_VA_PER_PTBL; -+ } -+ -+ ptbl->ptbl_flags = PTBL_LEVEL_3 | PTBL_ALLOCED | PTBL_LOCKED; -+ -+ HAT_PRINTF3 (2, "elan3mmu_alloc_l3ptbl: ptbl %p dev %p base %x\n", ptbl, dev, base); -+ -+#ifdef zero_all_ptbls -+ elan3_sdram_zeroq_sdram (dev, PTBL_TO_PTADDR(ptbl), ELAN3_L3_ENTRIES*ELAN3_PTE_SIZE); -+#endif -+ -+ return (ptbl); -+} -+ -+void -+elan3mmu_free_pte (ELAN3_DEV *dev, ELAN3MMU *elan3mmu, ELAN3_PTBL *ptbl_ptr, int idx) -+{ -+ sdramaddr_t pte = PTBL_TO_PTADDR (ptbl_ptr) | (idx * sizeof (ELAN3_PTE)); -+ ELAN3_PTE tpte = ELAN3_INVALID_PTE; -+ ELAN3_PTBL *prev; -+ -+ /* ensure that the pte is invalid when free */ -+ elan3_writepte (dev, pte, tpte); -+ -+ /* lock whilst removing */ -+ spin_lock (&elan3mmu->elan3mmu_lXptbl_lock); -+ -+ HAT_PRINTF4 (2, "elan3mmu_free_pte idx %d ptbl_ptr %p ptbl_base %x ptbl_ptr->ptbl_valid %d \n", -+ idx, ptbl_ptr, ptbl_ptr->ptbl_base, ptbl_ptr->ptbl_valid); -+ /* make sure it was set */ -+ ASSERT ( ptbl_ptr->ptbl_base & (1 << idx) ); -+ ASSERT ( ptbl_ptr->ptbl_valid > 0 ); -+ -+ ptbl_ptr->ptbl_base &= ~(1 << idx); -+ ptbl_ptr->ptbl_valid--; -+ -+ HAT_PRINTF3 (2, "elan3mmu_free_pte: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(ptbl_ptr->ptbl_flags), ptbl_ptr, ptbl_ptr->ptbl_valid); -+ -+ /* was that the last one on this page */ -+ if ( ! ptbl_ptr->ptbl_valid ) -+ { -+ /* so no bits should be set then */ -+ ASSERT ( ptbl_ptr->ptbl_base == 0 ); -+ -+ /* is this the first page ?? */ -+ if ( elan3mmu->elan3mmu_lXptbl == ptbl_ptr ) -+ { -+ /* make the list start at the second element */ -+ elan3mmu->elan3mmu_lXptbl = ptbl_ptr->ptbl_parent; -+ -+ /* put ptbl back on free list */ -+ elan3mmu_free_lXptbl(dev, ptbl_ptr); -+ -+ /* unlock and return */ -+ spin_unlock (&elan3mmu->elan3mmu_lXptbl_lock); -+ return ; -+ } -+ -+ /* scan thro list looking for this page */ -+ prev = elan3mmu->elan3mmu_lXptbl; -+ while ( prev->ptbl_parent != NULL ) -+ { -+ if ( prev->ptbl_parent == ptbl_ptr ) /* its the next one */ -+ { -+ /* remove element from chain */ -+ prev->ptbl_parent = ptbl_ptr->ptbl_parent; -+ -+ /* put ptbl back on free list */ -+ elan3mmu_free_lXptbl(dev, ptbl_ptr); -+ -+ /* unlock and return */ -+ spin_unlock (&elan3mmu->elan3mmu_lXptbl_lock); -+ return ; -+ } -+ prev = prev->ptbl_parent; -+ } -+ -+ panic ("elan3mmu_free_pte: failed to find ptbl in chain"); -+ /* NOTREACHED */ -+ } -+ -+ spin_unlock (&elan3mmu->elan3mmu_lXptbl_lock); -+} -+ -+void -+elan3mmu_free_lXptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl) -+{ -+ ELAN3_PTBL_GR *ptg; -+ -+ HAT_PRINTF2 (2, "elan3mmu_free_lXptbl: dev %p ptbl %p\n", dev, ptbl); -+ -+ ASSERT (ptbl->ptbl_flags & PTBL_ALLOCED); -+ ASSERT ((ptbl->ptbl_flags & PTBL_KEEP) == 0); -+ ASSERT (PTBL_LEVEL(ptbl->ptbl_flags) == PTBL_LEVEL_X); -+ ASSERT (ptbl->ptbl_valid == 0); -+ -+ ptbl->ptbl_flags = 0; -+ -+ ptg = PTBL_TO_GR(ptbl); -+ -+ if (ptg->pg_level == PTBL_LEVEL_3) -+ { -+ ELAN3MMU_STAT(lX_freed_l3); -+ -+ HAT_PRINTF1 (2, "elan3mmu_free_lXptbl: freeing stolen level 3 ptbl %p\n", ptbl); -+ -+ /* this was really a level 3 ptbl which we had to steal */ -+ spin_lock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ ptbl->ptbl_next = dev->Level[PTBL_LEVEL_3].PtblFreeList; -+ dev->Level[PTBL_LEVEL_3].PtblFreeList = ptbl; -+ dev->Level[PTBL_LEVEL_3].PtblFreeCount++; -+ spin_unlock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ } -+ else -+ { -+ spin_lock (&dev->Level[PTBL_LEVEL_X].PtblLock); -+ ptbl->ptbl_next = dev->Level[PTBL_LEVEL_X].PtblFreeList; -+ dev->Level[PTBL_LEVEL_X].PtblFreeList = ptbl; -+ dev->Level[PTBL_LEVEL_X].PtblFreeCount++; -+ spin_unlock (&dev->Level[PTBL_LEVEL_X].PtblLock); -+ } -+} -+ -+void -+elan3mmu_free_l1ptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags) -+{ -+ HAT_PRINTF3 (2, "elan3mmu_free_l1ptbl: dev %p ptbl %p ptbl->ptbl_valid %x \n", dev, ptbl, ptbl->ptbl_valid); -+ -+ ASSERT (ptbl->ptbl_flags & PTBL_ALLOCED); -+ ASSERT ((ptbl->ptbl_flags & PTBL_KEEP) == 0); -+ ASSERT (PTBL_LEVEL(ptbl->ptbl_flags) == PTBL_LEVEL_1); -+ ASSERT (ptbl->ptbl_valid == 0); -+ -+ HAT_PRINTF2 (2, "elan3mmu_free_l1ptbl: dev %p ptbl %p\n", dev, ptbl); -+ -+ ptbl->ptbl_flags = 0; -+ spin_unlock (lock); -+ -+ spin_lock (&dev->Level[PTBL_LEVEL_1].PtblLock); -+ ptbl->ptbl_next = dev->Level[PTBL_LEVEL_1].PtblFreeList; -+ dev->Level[PTBL_LEVEL_1].PtblFreeList = ptbl; -+ dev->Level[PTBL_LEVEL_1].PtblFreeCount++; -+ spin_unlock (&dev->Level[PTBL_LEVEL_1].PtblLock); -+ -+ local_irq_restore (flags); -+} -+ -+void -+elan3mmu_free_l2ptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags) -+{ -+ ELAN3_PTBL_GR *ptg; -+ -+ HAT_PRINTF2 (2, "elan3mmu_free_l2ptbl: dev %p ptbl %p\n", dev, ptbl); -+ -+ ASSERT (PTBL_IS_LOCKED(ptbl->ptbl_flags)); -+ ASSERT (ptbl->ptbl_flags & PTBL_ALLOCED); -+ ASSERT ((ptbl->ptbl_flags & PTBL_KEEP) == 0); -+ ASSERT (PTBL_LEVEL(ptbl->ptbl_flags) == PTBL_LEVEL_2); -+ ASSERT (ptbl->ptbl_valid == 0); -+ -+ ptbl->ptbl_flags = 0; -+ spin_unlock (lock); -+ -+ ptg = PTBL_TO_GR(ptbl); -+ -+ if (ptg->pg_level == PTBL_LEVEL_3) -+ { -+ ELAN3MMU_STAT(l2_freed_l3); -+ -+ HAT_PRINTF1 (2, "elan3mmu_free_l2ptbl: freeing stolen level 3 ptbl %p\n", ptbl); -+ -+ /* this was really a level 3 ptbl which we had to steal */ -+ spin_lock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ ptbl->ptbl_next = dev->Level[PTBL_LEVEL_3].PtblFreeList; -+ dev->Level[PTBL_LEVEL_3].PtblFreeList = ptbl; -+ dev->Level[PTBL_LEVEL_3].PtblFreeCount++; -+ spin_unlock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ } -+ else -+ { -+ spin_lock (&dev->Level[PTBL_LEVEL_2].PtblLock); -+ ptbl->ptbl_next = dev->Level[PTBL_LEVEL_2].PtblFreeList; -+ dev->Level[PTBL_LEVEL_2].PtblFreeList = ptbl; -+ dev->Level[PTBL_LEVEL_2].PtblFreeCount++; -+ spin_unlock (&dev->Level[PTBL_LEVEL_2].PtblLock); -+ } -+ local_irq_restore (flags); -+} -+ -+void -+elan3mmu_free_l3ptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags) -+{ -+ ASSERT (PTBL_IS_LOCKED(ptbl->ptbl_flags)); -+ ASSERT (ptbl->ptbl_flags & PTBL_ALLOCED); -+ ASSERT ((ptbl->ptbl_flags & PTBL_KEEP) == 0); -+ ASSERT (PTBL_LEVEL(ptbl->ptbl_flags) == PTBL_LEVEL_3); -+ ASSERT (ptbl->ptbl_valid == 0); -+ -+ HAT_PRINTF2 (2, "elan3mmu_free_l3ptbl: dev %p ptbl %p\n", dev, ptbl); -+ -+ if (ptbl->ptbl_flags & PTBL_KERNEL) /* if the ptbl has been used by the kernel */ -+ { /* then zero all the pte's, since they will */ -+ elan3_sdram_zeroq_sdram (dev, PTBL_TO_PTADDR(ptbl), ELAN3_L3_ENTRIES*ELAN3_PTE_SIZE); -+ } -+ -+ ptbl->ptbl_flags = 0; -+ spin_unlock (lock); -+ -+ spin_lock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ ptbl->ptbl_next = dev->Level[PTBL_LEVEL_3].PtblFreeList; -+ dev->Level[PTBL_LEVEL_3].PtblFreeList = ptbl; -+ dev->Level[PTBL_LEVEL_3].PtblFreeCount++; -+ spin_unlock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ -+ local_irq_restore (flags); -+} -+ -+void -+elan3mmu_kernel_l3ptbl (ELAN3_PTBL *ptbl) -+{ -+ ELAN3_DEV *dev = ptbl->ptbl_elan3mmu->elan3mmu_dev; -+ sdramaddr_t pte = PTBL_TO_PTADDR(ptbl); -+ ELAN3_PTE tpte = elan3mmu_kernel_invalid_pte(ptbl->ptbl_elan3mmu); -+ int i; -+ -+ ptbl->ptbl_flags |= PTBL_KERNEL; -+ for (i = 0; i < ELAN3_L3_ENTRIES; i++, pte += ELAN3_PTE_SIZE) -+ { -+ elan3_writepte (dev, pte, tpte); -+ } -+} -+ -+#define PTBL_CAN_STEAL(flag) (((flag) & (PTBL_KERNEL|PTBL_KEEP)) == 0 && (((flag) & PTBL_ALLOCED) && PTBL_LEVEL(flag) == PTBL_LEVEL_3)) -+#define PTBL_MAY_STEAL(flag) (((flag) & (PTBL_KERNEL|PTBL_KEEP|PTBL_LOCKED)) == 0 && (((flag) & PTBL_ALLOCED) && PTBL_LEVEL(flag) == PTBL_LEVEL_3)) -+ -+static int -+elan3mmu_steal_this_ptbl (ELAN3_DEV *dev, ELAN3_PTBL *l3ptbl) -+{ -+ ELAN3_PTBL *l2ptbl = l3ptbl->ptbl_parent; -+ E3_Addr l2addr = BASE2VA(l2ptbl); -+ E3_Addr l3addr = BASE2VA(l3ptbl); -+ ELAN3_PTP invalidptp = ELAN3_INVALID_PTP; -+ sdramaddr_t l2ptp; -+ spinlock_t *l2lock; -+ unsigned long l2flags; -+ -+ HAT_PRINTF5 (1, "elan3mmu_steal_this_ptbl: l3ptbl %p (%x) l2ptbl %p (%x) l2addr %x\n", -+ l3ptbl, l3ptbl->ptbl_flags, l2ptbl, l2ptbl->ptbl_flags, l2addr); -+ -+ if (PTBL_CAN_STEAL (l3ptbl->ptbl_flags) && -+ elan3mmu_lock_ptbl (l2ptbl, LK_PTBL_NOWAIT, l3ptbl->ptbl_elan3mmu, l2addr, PTBL_LEVEL_2, &l2lock, &l2flags) == LK_PTBL_OK) -+ { -+ ELAN3MMU_STAT(stolen_ptbls); -+ -+ /* Locked both L3 and L2 page tables. */ -+ l2ptp = PTBL_TO_PTADDR (l2ptbl) + ELAN3_L2_INDEX(l3addr)*ELAN3_PTP_SIZE; -+ -+ /* detach the level 3 page table */ -+ elan3_writeptp (dev, l2ptp, invalidptp); -+ ElanFlushTlb (dev); -+ -+ l2ptbl->ptbl_valid--; -+ -+ HAT_PRINTF3 (2, "elan3mmu_steal_this_ptbl: dec valid for level %d ptbl %p to %d\n", PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ -+ elan3mmu_unload_loop (l3ptbl->ptbl_elan3mmu, l3ptbl, 0, ELAN3_L3_ENTRIES, PTE_UNLOAD_NOFLUSH); -+ -+ ASSERT (l3ptbl->ptbl_valid == 0); -+ -+ l3ptbl->ptbl_flags = 0; -+ return (1); -+ } -+ return (0); -+} -+ -+static ELAN3_PTBL * -+elan3mmu_steal_l3ptbl (ELAN3_DEV *dev, int attr) -+{ -+ ELAN3_PTBL_GR *ptg; -+ ELAN3_PTBL *ptbl; -+ spinlock_t *lock; -+ unsigned long group_flags; -+ unsigned long ptbl_flags; -+ register int i; -+ -+ HAT_PRINTF1 (2, "elan3mmu_steal_l3ptbl: attr %x\n", attr); -+ -+ spin_lock_irqsave (&dev->PtblGroupLock, group_flags); -+ -+ ptg = dev->Level3PtblGroupHand; -+ -+ if (ptg == NULL) -+ ptg = dev->Level[PTBL_LEVEL_3].PtblGroupList; -+ -+ for (;;) -+ { -+ while (ptg) -+ { -+ for (i = 0, ptbl = ptg->pg_ptbls; i < PTBLS_PER_GROUP_MAX; i++, ptbl++) -+ { -+ if (PTBL_MAY_STEAL (ptbl->ptbl_flags) && -+ elan3mmu_lock_this_ptbl (ptbl, LK_PTBL_NOWAIT, &lock, &ptbl_flags) == LK_PTBL_OK) -+ { -+ if (elan3mmu_steal_this_ptbl (dev, ptbl )) -+ { -+ HAT_PRINTF1 (2, "elan3mmu_steal_l3ptbl: stolen ptbl %p\n", ptbl); -+ -+ elan3mmu_unlock_ptbl (ptbl, lock,ptbl_flags); -+ -+ dev->Level3PtblGroupHand = ptg->pg_next; -+ -+ spin_unlock_irqrestore (&dev->PtblGroupLock, group_flags); -+ -+ return (ptbl); -+ } -+ elan3mmu_unlock_ptbl (ptbl, lock, ptbl_flags); -+ } -+ } -+ ptg = ptg->pg_next; -+ } -+ -+ if (dev->Level[PTBL_LEVEL_3].PtblFreeList) -+ { -+ spin_lock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ ptbl = dev->Level[PTBL_LEVEL_3].PtblFreeList; -+ if (ptbl != NULL) -+ { -+ dev->Level[PTBL_LEVEL_3].PtblFreeList = ptbl->ptbl_next; -+ dev->Level[PTBL_LEVEL_3].PtblFreeCount--; -+ } -+ spin_unlock (&dev->Level[PTBL_LEVEL_3].PtblLock); -+ -+ if (ptbl != NULL) -+ { -+ HAT_PRINTF1 (2, "elan3mmu_steal_l3ptbl: found ptbl %p on free list\n", ptbl); -+ break; -+ } -+ } -+ -+ ptbl = elan3mmu_create_ptbls (dev, PTBL_LEVEL_3, attr, 1); -+ -+ if (ptbl != NULL) -+ { -+ HAT_PRINTF1 (2, "elan3mmu_steal_l3ptbl: created new ptbl %p\n", ptbl); -+ break; -+ } -+ -+ HAT_PRINTF0 (1, "elan3mmu_steal_l3ptbl: cannot find a ptbl, retrying\n"); -+ ptg = dev->Level[PTBL_LEVEL_3].PtblGroupList; -+ } -+ -+ spin_unlock (&dev->PtblGroupLock); -+ return (ptbl); -+} -+ -+sdramaddr_t -+elan3mmu_ptefind (ELAN3MMU *elan3mmu, E3_Addr addr, int *level, -+ ELAN3_PTBL **pptbl, spinlock_t **plock, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTBL *l1ptbl; -+ sdramaddr_t l1ptp; -+ ELAN3_PTP tl1ptp; -+ E3_Addr l1base; -+ ELAN3_PTBL *l2ptbl; -+ sdramaddr_t l2ptp; -+ ELAN3_PTP tl2ptp; -+ E3_Addr l2base; -+ ELAN3_PTBL *l3ptbl; -+ sdramaddr_t l3pte; -+ spinlock_t *l1lock; -+ spinlock_t *l2lock; -+ spinlock_t *l3lock; -+ unsigned long l1flags; -+ unsigned long l2flags; -+ unsigned long l3flags; -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptefind: elan3mmu %p addr %x\n", elan3mmu, addr); -+ -+ l1ptbl = elan3mmu->elan3mmu_l1ptbl; -+ *level = 0; -+ -+ if (l1ptbl == NULL) -+ return ((sdramaddr_t) NULL); -+ -+ l1ptp = PTBL_TO_PTADDR(l1ptbl) + ELAN3_L1_INDEX(addr)*ELAN3_PTP_SIZE; -+ l1base = ELAN3_L1_BASE(addr); -+ -+retryl1: -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ -+ HAT_PRINTF4 (2, "elan3mmu_ptefind: l1ptbl %p l1ptp %lx l1base %x : tl1ptp %x\n", l1ptbl, l1ptp, l1base, tl1ptp); -+ -+ switch (ELAN3_PTP_TYPE(tl1ptp)) -+ { -+ case ELAN3_ET_PTE: -+ elan3mmu_lock_ptbl (l1ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_1, &l1lock, &l1flags); -+ -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ if (ELAN3_PTP_TYPE(tl1ptp) != ELAN3_ET_PTE) -+ { -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l1flags); -+ goto retryl1; -+ } -+ -+ *level = 1; -+ *pptbl = l1ptbl; -+ *plock = l1lock; -+ *flags = l1flags; -+ -+ /* return with l1lock */ -+ return (l1ptp); -+ -+ case ELAN3_ET_INVALID: -+ return ((sdramaddr_t) 0); -+ -+ case ELAN3_ET_PTP: -+ break; -+ -+ default: -+ panic ("elan3mmu_ptefind: found bad entry in level 1 page table"); -+ /* NOTREACHED */ -+ } -+ -+ HAT_PRINTF1 (2, "elan3mmu_ptefind: chain to level 2 ptbl from ptp %x\n", tl1ptp); -+ -+ l2ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl1ptp); -+ l2ptp = PTBL_TO_PTADDR(l2ptbl) + ELAN3_L2_INDEX(addr)*ELAN3_PTP_SIZE; -+ l2base = ELAN3_L2_BASE(addr); -+ -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ -+ HAT_PRINTF4 (2, "elan3mmu_ptefind: l2ptbl %p l2ptp %lx l2base %x : tl2ptp %x\n", l2ptbl, l2ptp, l2base, tl2ptp); -+ -+ switch (ELAN3_PTP_TYPE(tl2ptp)) -+ { -+ case ELAN3_ET_PTE: -+ switch (elan3mmu_lock_ptbl (l2ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &l2flags)) -+ { -+ case LK_PTBL_OK: -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ if (ELAN3_PTP_TYPE(tl2ptp) != ELAN3_ET_PTE) -+ { -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ goto retryl1; -+ } -+ -+ *level = 2; -+ *pptbl = l2ptbl; -+ *plock = l2lock; -+ *flags = l2flags; -+ -+ /* return with l2lock */ -+ return (l2ptp); -+ -+ case LK_PTBL_MISMATCH: -+ HAT_PRINTF6 (2, "elan3mmu_ptefind: PTBL_MISMATCH : ptbl %p flags %x elan3mmu %p base %x (%p %x)\n", -+ l2ptbl, l2ptbl->ptbl_flags, l2ptbl->ptbl_elan3mmu, l2ptbl->ptbl_base, elan3mmu, addr); -+ -+ /* -+ * We've trogged down to this ptbl, but someone has just -+ * stolen it, so try all over again. -+ */ -+ goto retryl1; -+ -+ default: -+ panic ("elan3mmu_ptefind: elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+ case ELAN3_ET_INVALID: -+ return ((sdramaddr_t) 0); -+ -+ case ELAN3_ET_PTP: -+ break; -+ default: -+ panic ("elan3mmu_ptefind: found bad entry in level 2 page table"); -+ /* NOTREACHED */ -+ } -+ -+ HAT_PRINTF1 (2, "elan3mmu_ptefind: chain to level 3 page table from ptp %x\n", tl2ptp); -+ -+ l3ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl2ptp); -+ l3pte = PTBL_TO_PTADDR(l3ptbl) + ELAN3_L3_INDEX(addr)*ELAN3_PTE_SIZE; -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptefind: l3ptbl %p l3pte %lx\n", l3ptbl, l3pte); -+ -+ switch (elan3mmu_lock_ptbl (l3ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_3, &l3lock, &l3flags)) -+ { -+ case LK_PTBL_OK: -+ *level = 3; -+ *plock = l3lock; -+ *pptbl = l3ptbl; -+ *flags = l3flags; -+ -+ return (l3pte); -+ -+ case LK_PTBL_FAILED: -+ panic ("elan3mmu_ptefind: l3 lock failed"); -+ /* NOTREACHED */ -+ -+ case LK_PTBL_MISMATCH: -+ HAT_PRINTF6 (2, "elan3mmu_ptefind: PTBL_MISMATCH : ptbl %p flags %x elan3mmu %p base %x (%p %x)\n", -+ l3ptbl, l3ptbl->ptbl_flags, l3ptbl->ptbl_elan3mmu, l3ptbl->ptbl_base, elan3mmu, addr); -+ -+ /* -+ * We've trogged down to this ptbl, but someone has just -+ * stolen it, so try all over again. -+ */ -+ goto retryl1; -+ -+ default: -+ panic ("elan3mmu_ptefind: elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+ /* NOTREACHED */ -+ return ((sdramaddr_t) 0); -+} -+ -+sdramaddr_t -+elan3mmu_ptp2pte (ELAN3MMU *elan3mmu, sdramaddr_t ptp, int level) -+{ -+ ELAN3_PTP tptp = elan3_readptp (elan3mmu->elan3mmu_dev, ptp); -+ -+ ASSERT (level != 3 && ELAN3_PTP_TYPE(tptp) == ELAN3_ET_PTE); -+ -+ return PTP_TO_PT_PADDR(tptp); -+} -+ -+sdramaddr_t -+elan3mmu_ptealloc (ELAN3MMU *elan3mmu, E3_Addr addr, int level, -+ ELAN3_PTBL **pptbl, spinlock_t **plock, int attr, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTBL *l1ptbl; -+ ELAN3_PTBL *lXptbl; -+ int idx; -+ sdramaddr_t l1ptp; -+ ELAN3_PTP tl1ptp; -+ E3_Addr l1base; -+ spinlock_t *l1lock; -+ ELAN3_PTBL *l2ptbl; -+ sdramaddr_t l2ptp; -+ ELAN3_PTP tl2ptp; -+ E3_Addr l2base; -+ spinlock_t *l2lock; -+ ELAN3_PTBL *l3ptbl; -+ sdramaddr_t l3pte; -+ E3_Addr l3base; -+ spinlock_t *l3lock; -+ -+ unsigned long l1flags; -+ unsigned long l2flags; -+ unsigned long l3flags; -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: elan3mmu %p addr %x\n", elan3mmu, addr); -+ -+ l1ptbl = elan3mmu->elan3mmu_l1ptbl; -+ if (l1ptbl == NULL) -+ return ((sdramaddr_t) 0); -+ -+ l1ptp = PTBL_TO_PTADDR(l1ptbl) + ELAN3_L1_INDEX(addr)*ELAN3_PTP_SIZE; -+ l1base = ELAN3_L1_BASE(addr); -+ -+retryl1: -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ -+ HAT_PRINTF5 (2, "elan3mmu_ptealloc: l1ptbl %p 1ptp %lx l1base %x (%x) : tl1ptp %x\n", -+ l1ptbl, l1ptp, l1base, l1ptbl->ptbl_base, tl1ptp); -+ -+ switch (ELAN3_PTP_TYPE(tl1ptp)) -+ { -+ case ELAN3_ET_PTE: -+ if (level == PTBL_LEVEL_1) -+ { -+ elan3mmu_lock_ptbl (l1ptbl, 0, elan3mmu, addr, PTBL_LEVEL_1, &l1lock, &l1flags); -+ -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ if (ELAN3_PTP_TYPE(tl1ptp) != ELAN3_ET_PTE) -+ { -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l1flags); -+ goto retryl1; -+ } -+ -+ *pptbl = l1ptbl; -+ *plock = l1lock; -+ *flags = l1flags; -+ -+ /* return holding l1lock */ -+ return (l1ptp); -+ } -+ panic ("elan3mmu_ptealloc: found pte in level 1 page table"); -+ /* NOTREACHED */ -+ -+ case ELAN3_ET_PTP: -+ if (level == PTBL_LEVEL_1) -+ panic ("elan3mmu_ptealloc: found PTP when loading a level 1 PTE\n"); -+ break; -+ -+ case ELAN3_ET_INVALID: -+ if (level == PTBL_LEVEL_1) -+ { -+ if ((lXptbl = elan3mmu_alloc_pte (dev, elan3mmu, &idx)) == NULL) -+ return ((sdramaddr_t) 0); -+ -+ elan3mmu_lock_ptbl (l1ptbl, 0, elan3mmu, addr, PTBL_LEVEL_1, &l1lock, &l1flags); -+ -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ if (ELAN3_PTP_TYPE(tl1ptp) != ELAN3_ET_INVALID) -+ { -+ /* raced with someone else, whose got there first */ -+ elan3mmu_free_pte (dev, elan3mmu, lXptbl, idx); -+ -+ /* drop the l1lock and retry */ -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l1flags); -+ goto retryl1; -+ } -+ -+ tl1ptp = PTBL_TO_PTADDR(lXptbl) | (idx * ELAN3_PTE_SIZE) | ELAN3_ET_PTE; -+ -+ elan3_writeptp (dev, l1ptp, tl1ptp); -+ -+ *pptbl = l1ptbl; -+ *plock = l1lock; -+ *flags = l1flags; -+ -+ /* return holding l1lock */ -+ return (l1ptp); -+ } -+ -+ if (level == PTBL_LEVEL_2) -+ { -+ if ((lXptbl = elan3mmu_alloc_pte (dev, elan3mmu, &idx)) == NULL) -+ return ((sdramaddr_t) 0); -+ -+ if ((l2ptbl = elan3mmu_alloc_l2ptbl (dev, attr, l1ptbl, elan3mmu, ELAN3_L2_BASE(addr), &l2lock, &l2flags)) == NULL) -+ { -+ elan3mmu_free_pte (dev, elan3mmu, lXptbl, idx); -+ return ((sdramaddr_t) 0); -+ } -+ -+ /* Connect l2ptbl to the new LX pte */ -+ l2ptp = PTBL_TO_PTADDR(l2ptbl) + ELAN3_L2_INDEX(addr) * ELAN3_PTP_SIZE; -+ tl2ptp = PTBL_TO_PTADDR(lXptbl) | (idx * ELAN3_PTE_SIZE) | ELAN3_ET_PTE; -+ -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ -+ /* Now need to lock the l1 ptbl */ -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ -+ elan3mmu_lock_ptbl (l1ptbl, 0, elan3mmu, addr, PTBL_LEVEL_1, &l1lock, &l1flags); -+ elan3mmu_lock_ptbl (l2ptbl, 0, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &l2flags); -+ -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ if (ELAN3_PTP_TYPE(tl1ptp) != ELAN3_ET_INVALID) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: beaten to it, free l2 ptbl/lx pte\n"); -+ -+ tl2ptp = ELAN3_INVALID_PTP; -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write level 2 ptp %lx to %x\n", l2ptp, tl2ptp); -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: freeing l2 ptbl %p (%x)\n", l2ptbl, l2ptbl->ptbl_flags); -+ -+ elan3mmu_free_l2ptbl (dev, l2ptbl, l2lock, l2flags); -+ elan3mmu_free_pte (dev, elan3mmu, lXptbl, idx); -+ -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l1flags); -+ -+ goto retryl1; -+ } -+ -+ /* Now have L1 locked, so install the L2 ptbl */ -+ l1ptp = PTBL_TO_PTADDR(l1ptbl) + ELAN3_L1_INDEX(addr)*ELAN3_PTP_SIZE; -+ tl1ptp = PTBL_TO_PTADDR(l2ptbl) | ELAN3_ET_PTP; -+ l1ptbl->ptbl_valid++; -+ -+ HAT_PRINTF3 (2, "elan3mmu_ptealloc: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l1ptbl->ptbl_flags), l1ptbl, l1ptbl->ptbl_valid); -+ -+ elan3_writeptp (dev, l1ptp, tl1ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write l1ptp %lx to %x\n", l1ptp, tl1ptp); -+ -+ /* unordered unlock - lock l1ptbl, lock l2ptbl, unlock l1ptbl */ -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l2flags); /* need to unlock with the l2flags to keep irq order correct */ -+ -+ *pptbl = l2ptbl; -+ *plock = l2lock; -+ *flags = l1flags; /* return the l1flags here as we have released the l2flags already to keep order */ -+ -+ /* return holding l2lock */ -+ return (l2ptp); -+ } -+ -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: allocating level 2 and level 3 page tables\n"); -+ -+ /* Allocate a level 2 and level 3 page table and link them together */ -+ if ((l2ptbl = elan3mmu_alloc_l2ptbl (dev, attr, l1ptbl, elan3mmu, ELAN3_L2_BASE(addr), &l2lock, &l2flags)) == NULL) -+ return ((sdramaddr_t) 0); -+ -+ if ((l3ptbl = elan3mmu_alloc_l3ptbl (dev, attr | PTE_NO_SLEEP, l2ptbl, elan3mmu, ELAN3_L3_BASE(addr), &l3lock, &l3flags)) == NULL) -+ { -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ return ((sdramaddr_t) 0); -+ } -+ -+ ASSERT (PTBL_IS_LOCKED (l2ptbl->ptbl_flags)); -+ ASSERT (PTBL_LEVEL (l2ptbl->ptbl_flags) == PTBL_LEVEL_2); -+ ASSERT (PTBL_IS_LOCKED (l3ptbl->ptbl_flags)); -+ ASSERT (PTBL_LEVEL (l3ptbl->ptbl_flags) == PTBL_LEVEL_3); -+ -+ HAT_PRINTF6 (2, "elan3mmu_ptealloc: l2ptbl %p (%x,%x) l3ptbl %p (%x,%x)\n", -+ l2ptbl, l2ptbl->ptbl_flags, l2ptbl->ptbl_base, -+ l3ptbl, l3ptbl->ptbl_flags, l3ptbl->ptbl_base); -+ -+ if (CTXT_IS_KERNEL (elan3mmu->elan3mmu_ctxt)) -+ { -+ l2ptbl->ptbl_flags |= PTBL_KERNEL; -+ elan3mmu_kernel_l3ptbl (l3ptbl); -+ } -+ -+ /* -+ * Connect L3 ptbl to the new L2 ptbl. -+ */ -+ l2ptp = PTBL_TO_PTADDR(l2ptbl) + ELAN3_L2_INDEX(addr) * ELAN3_PTP_SIZE; -+ tl2ptp = PTBL_TO_PTADDR(l3ptbl) | ELAN3_ET_PTP; -+ -+ l2ptbl->ptbl_valid = 1; -+ -+ HAT_PRINTF3 (2, "elan3mmu_ptealloc: set valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write level 2 ptp %lx to %x\n", l2ptp, tl2ptp); -+ -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ -+ /* -+ * Now need to lock the l1 ptbl - to maintain lock ordering -+ * we set the PTBL_KEEP bit to stop the l3 ptbl from being -+ * stolen and drop the locks in the order we aquired them -+ */ -+ l3ptbl->ptbl_flags |= PTBL_KEEP; -+ -+ elan3mmu_unlock_ptbl (l3ptbl, l3lock, l3flags); -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ -+ elan3mmu_lock_ptbl (l1ptbl, 0, elan3mmu, addr, PTBL_LEVEL_1, &l1lock, &l1flags); -+ elan3mmu_lock_ptbl (l3ptbl, 0, elan3mmu, addr, PTBL_LEVEL_3, &l3lock, &l3flags); -+ -+ l3ptbl->ptbl_flags &= ~PTBL_KEEP; -+ -+ /* Now have l1 and l3 ptbls locked, so install the new l2 ptbl into the l1. */ -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: l1ptp %lx is %x\n", l1ptp, tl1ptp); -+ -+ if (ELAN3_PTP_TYPE(tl1ptp) != ELAN3_ET_INVALID) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: beaten to it, free l2/l3 ptbls\n"); -+ -+ /* free off the level 3 page table */ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: freeing l3 ptbl %p (%x)\n", l3ptbl, l3ptbl->ptbl_flags); -+ -+ l3ptbl->ptbl_flags &= ~PTBL_KEEP; -+ elan3mmu_free_l3ptbl (dev, l3ptbl, l3lock, l3flags); -+ -+ /* and unlock the level 1 ptbl */ -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l1flags); -+ -+ /* lock the level 2 page table, and clear out the PTP, then free it */ -+ (void) elan3mmu_lock_ptbl (l2ptbl, 0, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &l2flags); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: locked l2 ptbl %p (%x)\n", l2ptbl, l2ptbl->ptbl_flags); -+ -+ tl2ptp = ELAN3_INVALID_PTP; -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ l2ptbl->ptbl_valid = 0; -+ -+ HAT_PRINTF3 (2, "elan3mmu_ptealloc: set to 0 valid for level %d ptbl %p to %d\n", PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write level 2 ptp %lx to %x\n", l2ptp, tl2ptp); -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: freeing l2 ptbl %p (%x)\n", l2ptbl, l2ptbl->ptbl_flags); -+ -+ elan3mmu_free_l2ptbl (dev, l2ptbl, l2lock, l2flags); -+ -+ goto retryl1; -+ } -+ -+ HAT_PRINTF4 (2, "elan3mmu_ptealloc: l1ptbl is %p (%x), l3ptbl is %p (%x)\n", -+ l1ptbl, l1ptbl->ptbl_flags, l3ptbl, l3ptbl->ptbl_flags); -+ -+ /* Now have L1 and L3 locked, so install the L2 ptbl */ -+ l1ptp = PTBL_TO_PTADDR(l1ptbl) + ELAN3_L1_INDEX(addr)*ELAN3_PTP_SIZE; -+ tl1ptp = PTBL_TO_PTADDR(l2ptbl) | ELAN3_ET_PTP; -+ l1ptbl->ptbl_valid++; -+ -+ HAT_PRINTF3 (2, "elan3mmu_ptealloc: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l1ptbl->ptbl_flags), l1ptbl, l1ptbl->ptbl_valid); -+ -+ elan3_writeptp (dev, l1ptp, tl1ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write l1ptp %lx to %x\n", l1ptp, tl1ptp); -+ -+ /* unordered unlock - lock l1ptbl, lock l3ptbl, unlock l1ptbl */ -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, l3flags); /* free using l3flags to keep irq ordering */ -+ -+ l3pte = PTBL_TO_PTADDR (l3ptbl) + ELAN3_L3_INDEX(addr)*ELAN3_PTE_SIZE; -+ -+ /* Level 3 ptbl is already locked, so just return the pte */ -+ *pptbl = l3ptbl; -+ *plock = l3lock; -+ *flags = l1flags; /* return l1flags to keep irq ordering */ -+ -+ return (l3pte); -+ -+ default: -+ panic ("elan3mmu_ptealloc: found bad entry in level 1 page table"); -+ /* NOTREACHED */ -+ } -+ -+ HAT_PRINTF1 (2, "elan3mmu_ptealloc: chain to level 2 ptbl from ptp %x\n", tl1ptp); -+ -+ l2ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl1ptp); -+ l2ptp = PTBL_TO_PTADDR(l2ptbl) + ELAN3_L2_INDEX(addr)*ELAN3_PTP_SIZE; -+ l2base = ELAN3_L2_BASE(addr); -+ -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ -+ HAT_PRINTF5 (2, "elan3mmu_ptealloc: l2ptbl %p l2ptp %lx l2base %x (%x) : tl2ptp %x\n", -+ l2ptbl, l2ptp, l2base, l2ptbl->ptbl_base, tl2ptp); -+ -+ switch (ELAN3_PTP_TYPE(tl2ptp)) -+ { -+ case ELAN3_ET_PTE: -+ if (level == PTBL_LEVEL_2) { -+ /* this is a pointer to a pte, we should just return it */ -+ -+ switch (elan3mmu_lock_ptbl (l2ptbl, 0, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &l2flags)) -+ { -+ case LK_PTBL_OK: -+ break; -+ -+ case LK_PTBL_FAILED: -+ panic ("elan3mmu_ptealloc: l2 lock failed"); -+ /* NOTREACHED */ -+ -+ case LK_PTBL_MISMATCH: -+ HAT_PRINTF6 (2, "elan3mmu_ptealloc: PTBL_MISMATCH : ptbl %p flags %x elan3mmu %p base %x (%p %x)\n", -+ l2ptbl, l2ptbl->ptbl_flags, l2ptbl->ptbl_elan3mmu, l2ptbl->ptbl_base, elan3mmu, addr); -+ -+ /* -+ * We've trogged down to this ptbl, but someone has just -+ * stolen it, so try all over again. -+ */ -+ goto retryl1; -+ -+ default: -+ panic ("elan3mmu_ptealloc: elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+ -+ -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ if (ELAN3_PTP_TYPE(tl2ptp) != ELAN3_ET_PTE) -+ { -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ goto retryl1; -+ } -+ -+ *pptbl = l2ptbl; -+ *plock = l2lock; -+ *flags = l2flags; -+ -+ /* return holdind l2lock */ -+ return (l2ptp); -+ } -+ panic ("elan3mmu: found pte in level 2 page table"); -+ /* NOTREACHED */ -+ -+ case ELAN3_ET_PTP: -+ break; -+ -+ case ELAN3_ET_INVALID: -+ if (level == PTBL_LEVEL_2) -+ { -+ if ((lXptbl = elan3mmu_alloc_pte (dev, elan3mmu, &idx)) == NULL) -+ return ((sdramaddr_t) 0); -+ -+ switch (elan3mmu_lock_ptbl (l2ptbl, 0, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &l2flags)) -+ { -+ case LK_PTBL_OK: -+ break; -+ -+ case LK_PTBL_FAILED: -+ panic ("elan3mmu_ptealloc: l2 lock failed"); -+ /* NOTREACHED */ -+ -+ case LK_PTBL_MISMATCH: -+ HAT_PRINTF6 (2, "elan3mmu_ptealloc: PTBL_MISMATCH : ptbl %p flags %x elan3mmu %p base %x (%p %x)\n", -+ l2ptbl, l2ptbl->ptbl_flags, l2ptbl->ptbl_elan3mmu, l2ptbl->ptbl_base, elan3mmu, addr); -+ -+ /* -+ * We've trogged down to this ptbl, but someone has just -+ * stolen it, so try all over again. -+ */ -+ goto retryl1; -+ -+ default: -+ panic ("elan3mmu_ptealloc: elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+ -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ if (ELAN3_PTP_TYPE(tl2ptp) != ELAN3_ET_INVALID) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: beaten to it, free lx pte\n"); -+ -+ elan3mmu_free_pte (dev, elan3mmu, lXptbl, idx); -+ -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ goto retryl1; -+ } -+ -+ /* Connect l2ptbl to the new LX pte */ -+ tl2ptp = PTBL_TO_PTADDR(lXptbl) | (idx * ELAN3_PTE_SIZE) | ELAN3_ET_PTE; -+ -+ HAT_PRINTF3 (2, "elan3mmu_ptealloc: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write l2ptp %lx to %x\n", l2ptp, tl2ptp); -+ -+ *pptbl = l2ptbl; -+ *plock = l2lock; -+ *flags = l2flags; -+ -+ /* return holding l2lock */ -+ return (l2ptp); -+ } -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: allocate level 3 page table\n"); -+ -+ if ((l3ptbl = elan3mmu_alloc_l3ptbl (dev, attr, l2ptbl, elan3mmu, ELAN3_L3_BASE(addr), &l3lock, &l3flags)) == NULL) -+ return ((sdramaddr_t) 0); -+ -+ if (CTXT_IS_KERNEL (elan3mmu->elan3mmu_ctxt)) -+ elan3mmu_kernel_l3ptbl (l3ptbl); -+ -+ /* -+ * Now need to lock the l2 ptbl - to maintain lock ordering -+ * we set the PTBL_KEEP bit to stop the l3 ptbl from being -+ * stolen and drop the locks in the order we aquired them -+ */ -+ l3ptbl->ptbl_flags |= PTBL_KEEP; -+ -+ elan3mmu_unlock_ptbl (l3ptbl, l3lock, l3flags); -+ -+ if (elan3mmu_lock_ptbl (l2ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &l2flags) == LK_PTBL_MISMATCH) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: l2ptbl freed, free l3 ptbl and try again\n"); -+ -+ elan3mmu_lock_ptbl (l3ptbl, 0, elan3mmu, addr, PTBL_LEVEL_3, &l3lock, &l3flags); -+ -+ /* free off the level 3 page table, and try again */ -+ l3ptbl->ptbl_flags &= ~PTBL_KEEP; -+ elan3mmu_free_l3ptbl (dev, l3ptbl, l3lock, l3flags); -+ -+ goto retryl1; -+ } -+ -+ elan3mmu_lock_ptbl (l3ptbl, 0, elan3mmu, addr, PTBL_LEVEL_3, &l3lock, &l3flags); -+ -+ l3ptbl->ptbl_flags &= ~PTBL_KEEP; -+ -+ /* Now have L2 and L3 ptbls locked, see if someone has beaten us to it. */ -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: l2ptp at %lx is %x\n", l2ptp, tl2ptp); -+ -+ if (ELAN3_PTP_TYPE(tl2ptp) != ELAN3_ET_INVALID) -+ { -+ HAT_PRINTF0 (2, "elan3mmu_ptealloc: beaten to it, free l3 ptbl and try again\n"); -+ -+ /* free off the level 3 page table, and try again */ -+ l3ptbl->ptbl_flags &= ~PTBL_KEEP; -+ elan3mmu_free_l3ptbl (dev, l3ptbl, l3lock, l3flags); -+ -+ /* Someone has allocated the ptbl before us */ -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l2flags); -+ -+ goto retryl1; -+ } -+ -+ ASSERT (PTBL_IS_LOCKED (l2ptbl->ptbl_flags)); -+ -+ /* Install the L3 ptbl into the L2 one */ -+ l2ptp = PTBL_TO_PTADDR(l2ptbl) + ELAN3_L2_INDEX(addr)*ELAN3_PTP_SIZE; -+ tl2ptp = PTBL_TO_PTADDR(l3ptbl) | ELAN3_ET_PTP; -+ l2ptbl->ptbl_valid++; -+ -+ HAT_PRINTF3 (2, "elan3mmu_ptealloc: inc valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ -+ HAT_PRINTF2 (2, "elan3mmu_ptealloc: write level 2 ptp %lx to %x\n", l2ptp, tl2ptp); -+ -+ /* unordered unlock - lock l2ptbl, lock l3ptbl, unlock l2ptbl */ -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, l3flags); /* free with the l3flags to keep irq ordering */ -+ -+ l3pte = PTBL_TO_PTADDR(l3ptbl) + ELAN3_L3_INDEX(addr)*ELAN3_PTE_SIZE; -+ -+ /* Level 3 ptbl is already locked, so just return the pte */ -+ *pptbl = l3ptbl; -+ *plock = l3lock; -+ *flags = l2flags; /* return l2flags to keep irq ordering */ -+ -+ return (l3pte); -+ -+ default: -+ panic ("elan3mmu_ptealloc: found bad entry in level 2 page table"); -+ /* NOTREACHED */ -+ } -+ -+ HAT_PRINTF1 (2, "elan3mmu_ptealloc: chain to level 3 page table from ptp %x\n", tl2ptp); -+ -+ l3ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl2ptp); -+ l3pte = PTBL_TO_PTADDR(l3ptbl) + ELAN3_L3_INDEX(addr)*ELAN3_PTE_SIZE; -+ l3base = ELAN3_L3_BASE(addr); -+ -+ HAT_PRINTF4 (2, "elan3mmu_ptealloc: l3ptbl %p 3pte %lx l3base %x (%x)\n", -+ l3ptbl, l3pte, l3base, l3ptbl->ptbl_base); -+ -+ if (elan3mmu_lock_ptbl (l3ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_3, &l3lock, &l3flags) == LK_PTBL_OK) -+ { -+ *pptbl = l3ptbl; -+ *plock = l3lock; -+ *flags = l3flags; -+ -+ return (l3pte); -+ } -+ -+ /* got all the way down here, but its been nicked before we could lock it */ -+ /* so try all over again */ -+ goto retryl1; -+} -+ -+void -+elan3mmu_l1inval (ELAN3MMU *elan3mmu, ELAN3_PTBL *l1ptbl, int attr) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTP invalidptp = ELAN3_INVALID_PTP; -+ ELAN3_PTP tl1ptp; -+ sdramaddr_t l1ptp; -+ E3_Addr addr; -+ spinlock_t *l2lock; -+ ELAN3_PTBL *l2ptbl; -+ ELAN3_PTBL *lXptbl; -+ int idx; -+ int i; -+ int ret; -+ unsigned long flags; -+ -+ l1ptp = PTBL_TO_PTADDR(l1ptbl); -+ -+ HAT_PRINTF2 (1, "elan3mmu_l1inval: l1ptbl %p l1ptp %lx\n", l1ptbl, l1ptp); -+ -+ for (i = 0, addr = 0; i < ELAN3_L1_ENTRIES; i++, l1ptp += ELAN3_PTP_SIZE) -+ { -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ switch (ELAN3_PTP_TYPE(tl1ptp)) -+ { -+ case ELAN3_ET_PTE: -+ lXptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl1ptp); -+ idx = (PTP_TO_PT_PADDR(tl1ptp) - PTBL_TO_PTADDR(lXptbl))/ELAN3_PTE_SIZE; -+ -+ HAT_PRINTF3 (2, "elan3mmu_l1inval: l1ptbl %p : lXptbl %p idx %d\n", -+ l1ptbl, lXptbl, idx); -+ -+ /* invalidate the L1 pte. */ -+ elan3_writeptp (dev, l1ptp, invalidptp); -+ if (! (attr & PTE_UNLOAD_NOFLUSH)) -+ ElanFlushTlb (dev); -+ -+ l1ptbl->ptbl_valid--; -+ elan3mmu_free_pte ( dev, elan3mmu, lXptbl, idx); -+ -+ HAT_PRINTF3 (2, "elan3mmu_l1inval: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l1ptbl->ptbl_flags), l1ptbl, l1ptbl->ptbl_valid); -+ -+ break; -+ -+ case ELAN3_ET_PTP: -+ HAT_PRINTF5 (2, "elan3mmu_l1inval: l1ptbl %p : ptp %lx (%x) addr %x (%d)\n", -+ l1ptbl, l1ptp, tl1ptp, addr, i); -+ -+ /* invalidate the L1 ptp. */ -+ elan3_writeptp (dev, l1ptp, invalidptp); -+ if (! (attr & PTE_UNLOAD_NOFLUSH)) -+ ElanFlushTlb (dev); -+ -+ /* invalidate the level 2 page table */ -+ l2ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl1ptp); -+ ret = elan3mmu_l2inval (elan3mmu, l2ptbl, attr | PTE_UNLOAD_NOFLUSH, addr, &l2lock, &flags); -+ -+ ASSERT ((l2ptbl->ptbl_flags & PTBL_KEEP) == 0); -+ -+ if (ret == LK_PTBL_OK) -+ { -+ if (((l2ptbl->ptbl_flags & PTBL_KEEP) == 0) && l2ptbl->ptbl_valid == 0) -+ { -+ HAT_PRINTF1 (2, "elan3mmu_l1inval: free l2ptbl %p\n", l2ptbl); -+ -+ l1ptbl->ptbl_valid--; -+ elan3mmu_free_l2ptbl (elan3mmu->elan3mmu_dev, l2ptbl, l2lock, flags); -+ -+ HAT_PRINTF3 (2, "elan3mmu_l1inval: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l1ptbl->ptbl_flags), l1ptbl, l1ptbl->ptbl_valid); -+ } -+ else -+ { -+ /* need to keep this page table, so even though its now empty, */ -+ /* chain it back in */ -+ HAT_PRINTF1 (2, "elan3mmu_l1inval: keep l2ptbl %p\n", l2ptbl); -+ -+ elan3_writeptp (dev, l1ptp, tl1ptp); -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, flags); -+ } -+ } -+ else -+ { -+ l1ptbl->ptbl_valid--; -+ -+ HAT_PRINTF3 (2, "elan3mmu_l1inval: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l1ptbl->ptbl_flags), l1ptbl, l1ptbl->ptbl_valid); -+ } -+ break; -+ -+ case ELAN3_ET_INVALID: -+ break; -+ -+ default: -+ panic ("elan3mmu_l1inval: found invalid entry in level 1 page table"); -+ /* NOTREACHED */ -+ } -+ -+ if (l1ptbl->ptbl_valid == 0) -+ break; -+ -+ addr += ELAN3_L1_SIZE; -+ } -+} -+ -+int -+elan3mmu_l2inval (ELAN3MMU *elan3mmu, ELAN3_PTBL *l2ptbl, int attr, E3_Addr addr, spinlock_t **pl2lock, unsigned long *flags) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTP invalidptp = ELAN3_INVALID_PTP; -+ ELAN3_PTP tl2ptp; -+ sdramaddr_t l2ptp; -+ spinlock_t *l3lock; -+ unsigned long l3flags; -+ ELAN3_PTBL *l3ptbl; -+ ELAN3_PTBL *lXptbl; -+ int idx; -+ int i; -+ int ret; -+ -+ HAT_PRINTF2 (1, "elan3mmu_l2inval: l2ptbl %p addr %x\n", l2ptbl, addr); -+ -+ ASSERT (PTBL_LEVEL (l2ptbl->ptbl_flags) == PTBL_LEVEL_2); -+ ASSERT (PTBL_LEVEL (l2ptbl->ptbl_parent->ptbl_flags) == PTBL_LEVEL_1); -+ -+ ret = elan3mmu_lock_ptbl (l2ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_2, pl2lock, flags); -+ -+ ASSERT (ret == LK_PTBL_OK); -+ ASSERT (l2ptbl->ptbl_elan3mmu == elan3mmu); -+ ASSERT (l2ptbl->ptbl_parent->ptbl_elan3mmu == elan3mmu); -+ -+ l2ptp = PTBL_TO_PTADDR(l2ptbl); -+ -+ for (i = 0; i < ELAN3_L2_ENTRIES; i++, l2ptp += ELAN3_PTP_SIZE) -+ { -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ switch (ELAN3_PTP_TYPE(tl2ptp)) -+ { -+ case ELAN3_ET_PTE: -+ lXptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl2ptp); -+ idx = (PTP_TO_PT_PADDR(tl2ptp) - PTBL_TO_PTADDR(lXptbl))/ELAN3_PTE_SIZE; -+ -+ HAT_PRINTF3 (2, "elan3mmu_l2inval: l2ptbl %p : lXptbl %p idx %d\n", -+ l2ptbl, lXptbl, idx); -+ -+ /* invalidate the L2 pte. */ -+ elan3_writeptp (dev, l2ptp, invalidptp); -+ if (! (attr & PTE_UNLOAD_NOFLUSH)) -+ ElanFlushTlb (dev); -+ -+ l2ptbl->ptbl_valid--; -+ elan3mmu_free_pte ( dev, elan3mmu, lXptbl, idx); -+ -+ HAT_PRINTF3 (2, "elan3mmu_l2inval: dec valid for level %d ptbl %p to %d\n", PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ -+ break; -+ -+ case ELAN3_ET_PTP: -+ HAT_PRINTF5 (2, "elan3mmu_l2inval: l2ptbl %p : ptp %lx (%x) addr %x (%d)\n", -+ l2ptbl, l2ptp, tl2ptp, addr, i); -+ -+ /* invalidate the L2 ptp. */ -+ elan3_writeptp (dev, l2ptp, invalidptp); -+ if (! (attr & PTE_UNLOAD_NOFLUSH)) -+ ElanFlushTlb (dev); -+ -+ /* unload the level 3 page table */ -+ l3ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl2ptp); -+ ret = elan3mmu_l3inval (elan3mmu, l3ptbl, attr | PTE_UNLOAD_NOFLUSH, addr, &l3lock, &l3flags); -+ -+ if (ret == LK_PTBL_OK) -+ { -+ if ((l3ptbl->ptbl_flags & PTBL_KEEP) == 0 && l3ptbl->ptbl_valid == 0) -+ { -+ /* decrement the valid count of the level 2 page table, and */ -+ /* free off the level 3 page table */ -+ HAT_PRINTF1 (2, "elan3mmu_l2inval: free l3ptbl %p\n", l3ptbl); -+ -+ l2ptbl->ptbl_valid--; -+ elan3mmu_free_l3ptbl (elan3mmu->elan3mmu_dev, l3ptbl, l3lock, l3flags); -+ -+ HAT_PRINTF3 (2, "elan3mmu_l2inval: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ } -+ else -+ { -+ /* need to keep this page table, so even though its now empty, */ -+ /* chain it back in */ -+ HAT_PRINTF1 (2, "elan3mmu_l2inval: keep l3ptbl %p\n", l3ptbl); -+ -+ elan3_writeptp (dev, l2ptp, tl2ptp); -+ elan3mmu_unlock_ptbl (l3ptbl, l3lock, l3flags); -+ } -+ } -+ else -+ { -+ l2ptbl->ptbl_valid--; -+ -+ HAT_PRINTF3 (2, "elan3mmu_l2inval: dec valid for level %d ptbl %p to %d\n", -+ PTBL_LEVEL(l2ptbl->ptbl_flags), l2ptbl, l2ptbl->ptbl_valid); -+ } -+ break; -+ -+ case ELAN3_ET_INVALID: -+ break; -+ -+ default: -+ panic ("elan3mmu_l2inval: found pte in level 2 page table"); -+ /* NOTREACHED */ -+ } -+ -+ if (l2ptbl->ptbl_valid == 0) -+ break; -+ -+ addr += ELAN3_L2_SIZE; -+ } -+ -+ ASSERT (PTBL_IS_LOCKED(l2ptbl->ptbl_flags)); -+ -+ return (ret); -+} -+ -+int -+elan3mmu_l3inval (ELAN3MMU *elan3mmu, ELAN3_PTBL *l3ptbl, int attr, E3_Addr addr, spinlock_t **pl3lock, unsigned long *flags) -+{ -+ int ret; -+ -+ HAT_PRINTF3 (2, "elan3mmu_l3inval: l3ptbl %p parent %p addr %x\n", l3ptbl, l3ptbl->ptbl_parent, addr); -+ -+ ASSERT (PTBL_IS_LOCKED (l3ptbl->ptbl_parent->ptbl_flags)); -+ ASSERT (PTBL_LEVEL (l3ptbl->ptbl_parent->ptbl_flags) == PTBL_LEVEL_2); -+ ASSERT (l3ptbl->ptbl_parent->ptbl_elan3mmu == elan3mmu); -+ ASSERT (l3ptbl->ptbl_parent->ptbl_base == VA2BASE (ELAN3_L2_BASE(addr))); -+ -+ ret = elan3mmu_lock_ptbl (l3ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_3, pl3lock, flags); -+ -+ ASSERT (ret == LK_PTBL_OK); -+ ASSERT (PTBL_LEVEL (l3ptbl->ptbl_flags) == PTBL_LEVEL_3); -+ -+ elan3mmu_unload_loop (elan3mmu, l3ptbl, 0, ELAN3_L3_ENTRIES, attr); -+ -+ ASSERT (PTBL_IS_LOCKED (l3ptbl->ptbl_flags)); -+ -+ return (ret); -+ } -+ -+int -+elan3mmu_lock_this_ptbl (ELAN3_PTBL *ptbl, int flag, spinlock_t **plock, unsigned long *flags) -+{ -+ int level = PTBL_LEVEL (ptbl->ptbl_flags); -+ spinlock_t *lock = elan3mmu_ptbl_to_lock (level, ptbl); -+ -+ local_irq_save (*flags); -+ -+ if ((flag & LK_PTBL_NOWAIT) == 0) -+ spin_lock (lock); -+ else if (! spin_trylock (lock)) { -+ local_irq_restore (*flags); -+ return (LK_PTBL_FAILED); -+ } -+ -+ if (level != PTBL_LEVEL (ptbl->ptbl_flags)) -+ { -+ spin_unlock (lock); -+ local_irq_restore (*flags); -+ return (LK_PTBL_MISMATCH); -+ } -+ -+ ptbl->ptbl_flags |= PTBL_LOCKED; -+ *plock = lock; -+ return (LK_PTBL_OK); -+} -+ -+int -+elan3mmu_lock_ptbl (ELAN3_PTBL *ptbl, u_int flag, ELAN3MMU *elan3mmu, E3_Addr va, int level, spinlock_t **plock, unsigned long *flags) -+{ -+ spinlock_t *lock = elan3mmu_ptbl_to_lock (level, ptbl); -+ int res = LK_PTBL_MISMATCH; -+ -+ local_irq_save (*flags); -+ -+ if ((flag & LK_PTBL_NOWAIT) == 0) -+ spin_lock (lock); -+ else if (spin_trylock (lock) == 0) { -+ local_irq_restore(*flags); -+ return (LK_PTBL_FAILED); -+ } -+ -+ if (PTBL_LEVEL (ptbl->ptbl_flags) != level) -+ { -+ res = LK_PTBL_MISMATCH; -+ goto mismatch; -+ } -+ -+ /* We have the right mutex, so check that its the ptbl we want. */ -+ switch (level) -+ { -+ case PTBL_LEVEL_1: va = ELAN3_L1_BASE(va); break; -+ case PTBL_LEVEL_2: va = ELAN3_L2_BASE(va); break; -+ case PTBL_LEVEL_3: va = ELAN3_L3_BASE(va); break; -+ } -+ -+ if (ptbl->ptbl_elan3mmu != elan3mmu || ptbl->ptbl_base != VA2BASE(va)) -+ { -+ res = LK_PTBL_MISMATCH; -+ goto mismatch; -+ } -+ -+ ASSERT ((ptbl->ptbl_flags & PTBL_LOCKED) == 0); -+ ptbl->ptbl_flags |= PTBL_LOCKED; -+ -+ *plock = lock; -+ return (LK_PTBL_OK); -+ -+mismatch: -+ if (! (flag & LK_PTBL_FAILOK)) -+ panic ("elan3mmu: failed to lock ptbl\n"); -+ -+ spin_unlock (lock); -+ local_irq_restore(*flags); -+ return (res); -+} -+ -+void -+elan3mmu_unlock_ptbl (ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags) -+{ -+ ptbl->ptbl_flags &= ~PTBL_LOCKED; -+ spin_unlock_irqrestore (lock,flags); -+} -+ -+static spinlock_t * -+elan3mmu_ptbl_to_lock (int level, ELAN3_PTBL *ptbl) -+{ -+ switch (level) -+ { -+ case PTBL_LEVEL_3: return (&l3ptbl_lock[L3PTBL_MTX_HASH(ptbl)]); -+ case PTBL_LEVEL_2: return (&l2ptbl_lock[L2PTBL_MTX_HASH(ptbl)]); -+ case PTBL_LEVEL_1: return (&l1ptbl_lock[L1PTBL_MTX_HASH(ptbl)]); -+ case PTBL_LEVEL_X: -+ panic ("elan3mmu: ptbl_to_lock, bad level X"); -+ default: -+ panic ("elan3mmu: ptbl_to_lock, bad level"); -+ /* NOTREACHED */ -+ } -+ return (NULL); -+} -+ -+void -+elan3mmu_display (ELAN3MMU *elan3mmu, E3_Addr addr) -+{ -+ ELAN3_DEV *dev = elan3mmu->elan3mmu_dev; -+ ELAN3_PTBL *l1ptbl; -+ sdramaddr_t l1ptp; -+ spinlock_t *l1lock; -+ ELAN3_PTE tl1pte; -+ ELAN3_PTP tl1ptp; -+ E3_Addr l1base; -+ ELAN3_PTBL *l2ptbl; -+ sdramaddr_t l2ptp; -+ ELAN3_PTE tl2pte; -+ spinlock_t *l2lock; -+ ELAN3_PTP tl2ptp; -+ E3_Addr l2base; -+ ELAN3_PTBL *l3ptbl; -+ sdramaddr_t l3pte; -+ ELAN3_PTE tl3pte; -+ spinlock_t *l3lock; -+ ELAN3_PTBL *lXptbl; -+ int idx; -+ unsigned long flags; -+ -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: elan3mmu %p addr %x\n", elan3mmu, addr); -+ -+ l1ptbl = elan3mmu->elan3mmu_l1ptbl; -+ -+ if (l1ptbl == NULL) -+ return; -+ -+ l1ptp = PTBL_TO_PTADDR(l1ptbl) + ELAN3_L1_INDEX(addr)*ELAN3_PTP_SIZE; -+ l1base = ELAN3_L1_BASE(addr); -+ -+ tl1ptp = elan3_readptp (dev, l1ptp); -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: l1ptbl %p l1ptp %lx l1base %x : tl1ptp %x\n", l1ptbl, l1ptp, l1base, tl1ptp); -+ -+ switch (ELAN3_PTP_TYPE(tl1ptp)) -+ { -+ case ELAN3_ET_PTE: -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: level 1 page table for pte %x\n", tl1ptp); -+ -+ lXptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl1ptp); -+ idx = (PTP_TO_PT_PADDR(tl1ptp) - PTBL_TO_PTADDR(lXptbl))/ELAN3_PTE_SIZE; -+ -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: lXptbl %p idx %d\n",lXptbl, idx); -+ -+ tl1pte = elan3_readpte (dev,(PTBL_TO_PTADDR (lXptbl) + idx * ELAN3_PTE_SIZE)); -+ -+ switch (elan3mmu_lock_ptbl (l1ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_1, &l1lock, &flags)) -+ { -+ case LK_PTBL_OK: -+ elan3mmu_unlock_ptbl (l1ptbl, l1lock, flags); -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: lvl 1 l1pte matches value %llx\n", (long long) tl1pte); -+ break; -+ -+ case LK_PTBL_FAILED: -+ panic ("elan3mmu_display: l1 lock failed"); -+ /* NOTREACHED */ -+ -+ case LK_PTBL_MISMATCH: -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: PTBL_MISMATCH : lvl 1 ptbl %p flags %x elan3mmu %p base %x (%p %x) %llx\n", -+ l1ptbl, l1ptbl->ptbl_flags, l1ptbl->ptbl_elan3mmu, l1ptbl->ptbl_base, elan3mmu, addr, (long long)tl1pte); -+ -+ break; -+ default: -+ panic ("elan3mmu_display: lvl 1 elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+ return; -+ -+ case ELAN3_ET_INVALID: -+ return; -+ -+ case ELAN3_ET_PTP: -+ break; -+ -+ default: -+ panic ("elan3mmu_display: found bad entry in level 1 page table"); -+ /* NOTREACHED */ -+ } -+ -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: chain to level 2 ptbl from ptp %x\n", tl1ptp); -+ -+ l2ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl1ptp); -+ l2ptp = PTBL_TO_PTADDR(l2ptbl) + ELAN3_L2_INDEX(addr)*ELAN3_PTP_SIZE; -+ l2base = ELAN3_L2_BASE(addr); -+ -+ tl2ptp = elan3_readptp (dev, l2ptp); -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: l2ptbl %p l2ptp %lx l2base %x : tl2ptp %x\n", -+ l2ptbl, l2ptp, l2base, tl2ptp); -+ -+ switch (ELAN3_PTP_TYPE(tl2ptp)) -+ { -+ case ELAN3_ET_PTE: -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: level 2 page table for pte %x\n", tl2ptp); -+ -+ lXptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl2ptp); -+ idx = (PTP_TO_PT_PADDR(tl2ptp) - PTBL_TO_PTADDR(lXptbl))/ELAN3_PTE_SIZE; -+ -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: lXptbl %p idx %d\n",lXptbl, idx); -+ -+ tl2pte = elan3_readpte (dev,(PTBL_TO_PTADDR (lXptbl) + idx * ELAN3_PTE_SIZE)); -+ -+ switch (elan3mmu_lock_ptbl (l2ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_2, &l2lock, &flags)) -+ { -+ case LK_PTBL_OK: -+ elan3mmu_unlock_ptbl (l2ptbl, l2lock, flags); -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: lvl 2 l1pte matches value %llx\n", (long long)tl2pte); -+ break; -+ -+ case LK_PTBL_FAILED: -+ panic ("elan3mmu_display: l2 lock failed"); -+ /* NOTREACHED */ -+ -+ case LK_PTBL_MISMATCH: -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: PTBL_MISMATCH : lvl 2 ptbl %p flags %x elan3mmu %p base %x (%p %x) %llx\n", -+ l2ptbl, l2ptbl->ptbl_flags, l2ptbl->ptbl_elan3mmu, l2ptbl->ptbl_base, elan3mmu, addr, (long long) tl2pte); -+ -+ break; -+ default: -+ panic ("elan3mmu_display: lvl 2 elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+ return; -+ -+ case ELAN3_ET_INVALID: -+ return; -+ -+ case ELAN3_ET_PTP: -+ break; -+ -+ default: -+ panic ("elan3mmu_display: found bad entry in level 2 page table"); -+ /* NOTREACHED */ -+ } -+ -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: chain to level 3 page table from ptp %x\n", tl2ptp); -+ -+ l3ptbl = elan3mmu_ta_to_ptbl (elan3mmu, &tl2ptp); -+ l3pte = PTBL_TO_PTADDR(l3ptbl) + ELAN3_L3_INDEX(addr)*ELAN3_PTE_SIZE; -+ -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: l3ptbl %p l3pte %lx\n",l3ptbl, l3pte); -+ -+ tl3pte = elan3_readpte (dev, l3pte); -+ switch (elan3mmu_lock_ptbl (l3ptbl, LK_PTBL_FAILOK, elan3mmu, addr, PTBL_LEVEL_3, &l3lock, &flags)) -+ { -+ case LK_PTBL_OK: -+ elan3mmu_unlock_ptbl (l3ptbl, l3lock, flags); -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: l3pte matches value %llx\n", (long long) tl3pte); -+ break; -+ -+ case LK_PTBL_FAILED: -+ panic ("elan3mmu_display: l3 lock failed"); -+ /* NOTREACHED */ -+ -+ case LK_PTBL_MISMATCH: -+ elan3_debugf (NULL, DBG_HAT, "elan3mmu_display: PTBL_MISMATCH : ptbl %p flags %x elan3mmu %p base %x (%p %x) %llx\n", -+ l3ptbl, l3ptbl->ptbl_flags, l3ptbl->ptbl_elan3mmu, l3ptbl->ptbl_base, elan3mmu, addr, (long long) tl3pte); -+ -+ break; -+ -+ default: -+ panic ("elan3mmu_display: elan3mmu_lock_ptbl returned bad value"); -+ /* NOTREACHED */ -+ } -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elan3mmu_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elan3mmu_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elan3mmu_linux.c 2005-06-01 23:12:54.574442904 -0400 -@@ -0,0 +1,284 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elan3mmu_linux.c,v 1.50.2.3 2004/12/14 10:19:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/vm/elan3mmu_linux.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * Strategy for syncing main <-> elan pte's: -+ * -+ * Install callbacks for linux flush_tlb_page(), flush_tlb_range(), -+ * flush_tlb_all(), and flush_tlb_mm() so when a main PTE changes, -+ * the elan translations, if any, are invalidated. They can then be -+ * faulted in again with the correct physical page, perms, etc., on demand. -+ * -+ * Callbacks are stacked on the mm_struct, one per context. We also stack -+ * a ctxt pointer so we don't have to do lookups on every call. -+ * -+ * Sanity check -- we clearly want to flush the elan PTEs in these -+ * situations, all of which are covered by tlb_flush_{page,range}() -+ * -+ * 1) kernel/vmscan.c::try_to_swap_out() swaps out a page -+ * -+ * 2) kernel/mremap.c::copy_one_pte() moves a page as a result of the -+ * mremap system call -+ * -+ * 3) kernel/mprotect.c::change_pte_range() changes the permissions of a -+ * page as the result of the mprotect system call -+ * -+ * Other Notes: -+ * -+ * Dirty a page in the mains page tables when it is faulted into the elan. -+ * This way it will not be thrown away by the swapper. -+ * -+ * Pages write protected for COW are copied by elan3mmu_main_pagefault() -+ * when a writeable translation is loaded into the elan. -+ */ -+ -+caddr_t elan3mmu_kernel_invalid_space; -+ELAN3_PTE elan3mmu_kernel_invalid_pte_val; -+ -+void -+elan3mmu_init_osdep (void) -+{ -+ pte_t *pte; -+ -+ KMEM_GETPAGES (elan3mmu_kernel_invalid_space, caddr_t, 1, TRUE); -+ -+ ASSERT(elan3mmu_kernel_invalid_space != NULL); -+ -+ pte = find_pte_kernel ((unsigned long) elan3mmu_kernel_invalid_space); -+ -+ elan3mmu_kernel_invalid_pte_val = ELAN3_PTE_64_BIT | (pte_phys(*pte) & ELAN3_PTE_PFN_MASK) | ELAN3_PERM_REMOTEREAD | ELAN3_ET_PTE; -+ -+#ifdef __alpha -+ /* -+ * NOTE: Elan sign-extends bit 48 of the physical address, so if we need to -+ * set any of bits 63:48, then we will set them all by setting bit 48/ -+ */ -+ if (alpha_mv.pci_dac_offset & 0xFFFF000000000000ull) -+ elan3mmu_kernel_invalid_pte_val |= (1ull << 48); -+ else -+ elan3mmu_kernel_invalid_pte_val |= alpha_mv.pci_dac_offset; -+#endif -+ -+ HAT_PRINTF(0x10, "elan3mmu_invalid_space at %p phys=%llx pte=%llx\n", elan3mmu_kernel_invalid_space, -+ (unsigned long long) pte_phys(*pte), (unsigned long long) elan3mmu_kernel_invalid_pte_val); -+} -+ -+void -+elan3mmu_fini_osdep() -+{ -+ KMEM_FREEPAGES (elan3mmu_kernel_invalid_space, 1); -+} -+ -+void -+elan3mmu_alloc_osdep (ELAN3MMU *elan3mmu) -+{ -+ elan3mmu->elan3mmu_coproc_mm = current->mm; -+} -+ -+/* -+ * Convert physical page frame number to elan pte. -+ */ -+ELAN3_PTE -+elan3mmu_phys_to_pte (ELAN3_DEV *dev, physaddr_t paddr, int perm) -+{ -+ ELAN3_PTE newpte; -+ -+ ASSERT (paddr != 0); -+ -+ if ((paddr & dev->SdramPhysMask) == dev->SdramPhysBase) /* SDRAM, turn on PTE_LOCAL bit */ -+ { -+ PRINTF(NULL, DBG_HAT, "elan3mmu_phys_to_pte: phys %llx SDRAM\n", (unsigned long long) paddr); -+ -+ newpte = ELAN3_PTE_LOCAL | (paddr & ELAN3_PTE_PFN_MASK & ~dev->SdramPhysMask) | perm | ELAN3_ET_PTE; -+ } -+#if defined(LINUX_ALPHA) -+ else if ((paddr & dev->PciPhysMask) == dev->PciPhysBase) -+ { -+ PRINTF(NULL, DBG_HAT, "elan3mmu_phys_to_pte: phys %llx PCI\n", (unsigned long long) paddr); -+ newpte = ELAN3_PTE_64_BIT | (paddr & ELAN3_PTE_PFN_MASK & ~dev->PciPhysMask) | perm | ELAN3_ET_PTE; -+ } -+#endif -+ else /* main memory, must convert to PCI view */ -+ { -+ PRINTF(NULL, DBG_HAT, "elan3mmu_phys_to_pte: phys %llx is main memory\n", (unsigned long long) paddr); -+ -+ /* main memory, just set the architecture specific PTE_BYPASS bit */ -+ /* This requires the Tsunami chipset being programmed to support -+ * the monster window option. This is in linux-2.4.5 and later kernels -+ * and is also patched into the RH 7.1/2.4.3-12 Alpha kernel -+ */ -+ newpte = ELAN3_PTE_64_BIT | (paddr & ELAN3_PTE_PFN_MASK) | perm | ELAN3_ET_PTE; -+ -+#ifdef __alpha -+ /* -+ * NOTE: Elan sign-extends bit 48 of the physical address, so if we need to -+ * set any of bits 63:48, then we will set them all by setting bit 48/ -+ */ -+ if (alpha_mv.pci_dac_offset & 0xFFFF000000000000ull) -+ newpte |= (1ull << 48); -+ else -+ newpte |= alpha_mv.pci_dac_offset; -+#endif -+ } -+ -+ if ( ELAN3_PERM_WRITEABLE( perm )) -+ newpte |= ( ELAN3_PTE_MOD | ELAN3_PTE_REF ); -+ else -+ newpte |= ( ELAN3_PTE_REF ) ; -+ -+ return (newpte); -+} -+ -+ELAN3_PTE -+elan3mmu_kernel_invalid_pte (ELAN3MMU *elan3mmu) -+{ -+ if (elan3mmu->elan3mmu_dev->Devinfo.dev_revision_id == PCI_REVISION_ID_ELAN3_REVB) -+ return (elan3mmu_kernel_invalid_pte_val); -+ return (ELAN3_INVALID_PTE); -+} -+ -+/* -+ * Invalidate a range of addresses for specified context. -+ */ -+void -+elan3mmu_pte_range_unload (ELAN3MMU *elan3mmu, struct mm_struct *mm, caddr_t addr, unsigned long len) -+{ -+ E3_Addr eaddr; -+ ELAN3MMU_RGN *rgn; -+ unsigned long span; -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ -+ for (; len; len -= span, addr += span) -+ { -+ rgn = elan3mmu_findrgn_main (elan3mmu, addr, 0); -+ -+ if (rgn == NULL || (rgn->rgn_mbase + rgn->rgn_len) < addr) -+ span = len; -+ else if (rgn->rgn_mbase > addr) -+ span = MIN(len, rgn->rgn_mbase - addr); -+ else -+ { -+ span = MIN(len, (rgn->rgn_mbase + rgn->rgn_len) - addr); -+ eaddr = rgn->rgn_ebase + (addr - rgn->rgn_mbase); -+ -+ HAT_PRINTF(0x10, " unloading eaddr %x main %p (%ld pages)\n", -+ eaddr, addr, btopr(span)); -+ elan3mmu_unload (elan3mmu, eaddr, span, PTE_UNLOAD); -+ } /* takes care of elan tlb flush also */ -+ } -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+} -+ -+/* -+ * -+ */ -+void -+elan3mmu_update_range (ELAN3MMU *elan3mmu, struct mm_struct *mm, caddr_t vaddr, E3_Addr eaddr, u_int len, u_int perm) -+{ -+ u_int roperm = ELAN3_PERM_READONLY(perm & ELAN3_PTE_PERM_MASK) | (perm & ~ELAN3_PTE_PERM_MASK); -+ u_int off; -+ -+ HAT_PRINTF3(1, "elan3mmu_update_range (elan3mmu %p addr %p -> %p)\n", elan3mmu, vaddr, vaddr+len-1); -+ -+ while (len > 0) -+ { -+ pte_t *pte_ptr; -+ pte_t pte_value; -+ -+ pte_ptr = find_pte_map(mm, (unsigned long)vaddr); -+ if (pte_ptr) { -+ pte_value = *pte_ptr; -+ pte_unmap(pte_ptr); -+ } -+ -+ HAT_PRINTF(0x10, " elan3mmu_update_range %x (%p) %s\n", eaddr, vaddr, -+ !pte_ptr ? "invalid" : pte_none(pte_value) ? "none " : !pte_present(pte_value) ? "swapped " : -+ !pte_write(pte_value) ? "RO/COW" : "OK"); -+ -+ if (pte_ptr && !pte_none(pte_value) && pte_present(pte_value)) -+ for (off = 0; off < PAGE_SIZE; off += ELAN3_PAGE_SIZE) -+ elan3mmu_pteload (elan3mmu, PTBL_LEVEL_3, eaddr + off, pte_phys(pte_value) + off, pte_write(pte_value) ? perm : roperm, PTE_LOAD|PTE_NO_SLEEP|PTE_NO_STEAL); -+ vaddr += PAGESIZE; -+ eaddr += PAGESIZE; -+ len -= PAGESIZE; -+ } -+} -+ -+/* -+ * Update a range of addresses for specified context. -+ */ -+void -+elan3mmu_pte_range_update (ELAN3MMU *elan3mmu, struct mm_struct *mm,caddr_t vaddr, unsigned long len) -+{ -+ E3_Addr eaddr; -+ ELAN3MMU_RGN *rgn; -+ unsigned long span; -+ -+ spin_lock (&elan3mmu->elan3mmu_lock); -+ -+ for (; len; len -= span, vaddr += span) -+ { -+ rgn = elan3mmu_findrgn_main (elan3mmu, vaddr, 0); -+ -+ if (rgn == NULL || (rgn->rgn_mbase + rgn->rgn_len) < vaddr) -+ span = len; -+ else if (rgn->rgn_mbase > vaddr) -+ span = MIN(len, rgn->rgn_mbase - vaddr); -+ else -+ { -+ span = MIN(len, (rgn->rgn_mbase + rgn->rgn_len) - vaddr); -+ eaddr = rgn->rgn_ebase + (vaddr - rgn->rgn_mbase); -+ -+ HAT_PRINTF(0x10, " updating eaddr %u main %p (%ld pages)\n", -+ eaddr, vaddr, btopr(span)); -+ -+ elan3mmu_update_range(elan3mmu, mm, vaddr, eaddr, span, rgn->rgn_perm); -+ } -+ } -+ -+ spin_unlock (&elan3mmu->elan3mmu_lock); -+} -+ -+/* -+ * Invalidate all ptes for the given context. -+ */ -+void -+elan3mmu_pte_ctxt_unload(ELAN3MMU *elan3mmu) -+{ -+ ELAN3_PTBL *l1ptbl = (elan3mmu ? elan3mmu->elan3mmu_l1ptbl : NULL); -+ spinlock_t *l1mtx; -+ unsigned long flags; -+ -+ if (l1ptbl && elan3mmu_lock_ptbl (l1ptbl, LK_PTBL_FAILOK, elan3mmu, (E3_Addr) 0, 1, &l1mtx, &flags) == LK_PTBL_OK) -+ { -+ elan3mmu_l1inval(elan3mmu, elan3mmu->elan3mmu_l1ptbl, 0); -+ elan3mmu_unlock_ptbl (l1ptbl, l1mtx, flags); -+ } -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elan3ops.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elan3ops.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elan3ops.c 2005-06-01 23:12:54.575442752 -0400 -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elan3ops.c,v 1.4 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/elan3ops.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+extern ELAN_STATS_OPS elan3_device_stats_ops; -+ -+ELAN_DEV_OPS elan3_dev_ops = { -+ -+ get_position, -+ set_position, -+ -+ ELAN_DEV_OPS_VERSION -+}; -+ -+ELAN_STATS_OPS elan3_device_stats_ops = { -+ ELAN_STATS_OPS_VERSION, -+ -+ stats_get_index_name, -+ stats_get_block, -+ stats_clear_block -+}; -+ -+static char *elan3_device_stats_names[ELAN3_NUM_STATS] = -+{ -+ "version field", /* not cleared */ -+ "elan interrupts", -+ "tlb flushes", -+ "traps with invalid context", -+ "interrupts com queue half full", -+ "cproc traps", -+ "dproc traps", -+ "tproc traps", -+ "iproc traps", -+ "event interrupts", -+ "elan page faults", -+ "EopBadAcks", -+ "EopResets", -+ "InputterBadLength", -+ "InputterCRCDiscards", -+ "InputterCRCErrors", -+ "InputterCRCBad", -+ "errors in dma data", -+ "errors after dma identify", -+ "errors after thread identify", -+ "dma retries", -+ "dma output timeouts", -+ "dma packet ack errors", -+ "forced tproc traps", -+ "too many instruction traps", -+ "output timeouts", -+ "packet ack errors", -+ "LockError", -+ "DeskewError", -+ "PhaseError", -+ "DataError", -+ "FifoOvFlow0", -+ "FifoOvFlow1", -+ "link error value on data error", -+ "correctable ecc errors", -+ "uncorrectable ecc errors", -+ "multiple ecc errors", -+ "sdram bytes free", /* not cleared */ -+ "longest interrupt in ticks", -+ "punts of event int's to thread", -+ "reschedules of event int's thread" -+}; -+ -+int -+stats_get_index_name (void *arg, uint index, caddr_t name) -+{ -+ copyout (elan3_device_stats_names[index], name, strlen (elan3_device_stats_names[index]) + 1 /* with \0 */); -+ -+ return (0); -+} -+ -+int -+stats_get_block (void *arg, uint entries, ulong *value) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *) arg; -+ -+ if ( entries > ELAN3_NUM_STATS ) /* if space too big only send valid portion */ -+ entries = ELAN3_NUM_STATS; -+ -+ copyout(&dev->Stats, value, sizeof(ulong) * entries); -+ -+ return (0); -+} -+ -+int -+stats_clear_block (void *arg) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *) arg; -+ u_long *ptr = (u_long *) &dev->Stats; -+ int n; -+ -+ for (n = 0; n < ELAN3_NUM_STATS; n++) -+ { -+ switch (n) -+ { -+ case offsetof (ELAN3_STATS, Version)/sizeof(u_long): -+ case offsetof (ELAN3_STATS, SdramBytesFree)/sizeof(u_long): -+ break; -+ default: -+ ptr[n] = (ulong)0; -+ } -+ } -+ return (0); -+} -+ -+int -+get_position (void *user_data, ELAN_POSITION *position) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *)user_data; -+ -+ copyout(&dev->Position, position, sizeof(ELAN_POSITION)); -+ -+ return (0); -+} -+ -+int -+set_position (void *user_data, unsigned short nodeId, unsigned short numNodes) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *)user_data; -+ -+ if (ComputePosition (&dev->Position, nodeId, numNodes, dev->Devinfo.dev_num_down_links_value) != 0) -+ return (EINVAL); -+ -+ return (0); -+} -+ -+int -+elan3_register_dev_stats(ELAN3_DEV * dev) -+{ -+ char name[ELAN_STATS_NAME_MAX_LEN+1]; -+ -+ sprintf (name, ELAN3_STATS_DEV_FMT, dev->Instance); -+ -+ elan_stats_register(&dev->StatsIndex, -+ name, -+ sizeof (elan3_device_stats_names)/sizeof (elan3_device_stats_names[0]), -+ &elan3_device_stats_ops, -+ (void *)dev); -+ -+ return (0); -+} -+ -+void -+elan3_deregister_dev_stats(ELAN3_DEV * dev) -+{ -+ elan_stats_deregister(dev->StatsIndex); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elandebug.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elandebug.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elandebug.c 2005-06-01 23:12:54.575442752 -0400 -@@ -0,0 +1,151 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elandebug.c,v 1.25 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/elandebug.c,v $*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+void -+elan3_debugf (void *p, unsigned int mode, char *fmt,...) -+{ -+ char prefix[128]; -+ -+#if defined (DIGITAL_UNIX) -+#define PREFIX_FMT "[%lx.%08x]" -+#define PREFIX_VAL (int)CURTHREAD() -+#else -+#define PREFIX_FMT "[%lx.%04d]" -+#define PREFIX_VAL (current->pid) -+#endif -+ -+ if ((unsigned long) p > DBG_NTYPES) -+ { -+ ELAN3_CTXT *ctxt = (ELAN3_CTXT *) p; -+ -+ if (elan3_debug_display_ctxt && (ctxt->Capability.cap_mycontext & MAX_ROOT_CONTEXT_MASK) != elan3_debug_display_ctxt) -+ return; -+ if (elan3_debug_ignore_ctxt && (ctxt->Capability.cap_mycontext & MAX_ROOT_CONTEXT_MASK) == elan3_debug_ignore_ctxt) -+ return; -+ -+ if (ctxt->Capability.cap_mycontext == ELAN_CAP_UNINITIALISED) -+ sprintf (prefix, PREFIX_FMT " (XXX) ", lbolt, PREFIX_VAL); -+ else -+ sprintf (prefix, PREFIX_FMT " (%03x) ", lbolt, PREFIX_VAL, -+ ctxt->Capability.cap_mycontext & MAX_ROOT_CONTEXT_MASK); -+ } -+ else -+ { -+ char *what; -+ -+ if (elan3_debug_ignore_dev & (1 << ((unsigned long) p))) -+ return; -+ -+ switch ((unsigned long) p) -+ { -+ case (int) DBG_DEVICE: what = "dev"; break; -+ case (int) DBG_KCOMM: what = "kcm"; break; -+ case (int) DBG_ICS: what = "ics"; break; -+ case (int) DBG_USER: what = "usr"; break; -+ default: what = NULL; break; -+ } -+ -+ if (what) -+ sprintf (prefix, PREFIX_FMT " [%s] ", lbolt, PREFIX_VAL, what); -+ else -+ sprintf (prefix, PREFIX_FMT " [%3d] ", lbolt, PREFIX_VAL, (int)(long)what); -+ } -+ -+ { -+ va_list ap; -+ -+ va_start (ap, fmt); -+ qsnet_vdebugf ((((mode & elan3_debug_buffer)?QSNET_DEBUG_BUFFER:0)|((mode & elan3_debug_console)?QSNET_DEBUG_CONSOLE:0)) , prefix, fmt, ap); -+ va_end (ap); -+ } -+} -+ -+ -+void -+elan3_alloc_panicstate (ELAN3_DEV *dev, int allocsdram) -+{ -+ register int bank; -+ -+ if (dev->PanicState.RegPtr == NULL) -+ KMEM_ZALLOC (dev->PanicState.RegPtr, E3_Regs *, sizeof (E3_Regs), 1); -+ -+ if (allocsdram) -+ for (bank = 0; bank < ELAN3_SDRAM_NUM_BANKS; bank++) -+ if (dev->PanicState.Sdram[bank] == NULL && dev->SdramBanks[bank].Size) -+ KMEM_ZALLOC (dev->PanicState.Sdram[bank], char *, dev->SdramBanks[bank].Size, 1); -+} -+ -+void -+elan3_free_panicstate (ELAN3_DEV *dev) -+{ -+ register int bank; -+ -+ if (dev->PanicState.RegPtr != NULL) -+ KMEM_FREE (dev->PanicState.RegPtr, sizeof (E3_Regs)); -+ -+ for (bank = 0; bank < ELAN3_SDRAM_NUM_BANKS; bank++) -+ if (dev->PanicState.Sdram[bank] != NULL && dev->SdramBanks[bank].Size) -+ KMEM_FREE (dev->PanicState.Sdram[bank], dev->SdramBanks[bank].Size); -+ -+ bzero (&dev->PanicState, sizeof (dev->PanicState)); -+} -+ -+void -+elan3_save_panicstate (ELAN3_DEV *dev) -+{ -+ register int bank; -+ -+ if (dev->PanicState.RegPtr) -+ { -+ printk ("elan%d: saving state on panic .....\n", dev->Devinfo.dev_instance); -+ -+ bcopy ((void *) dev->RegPtr, (void *) dev->PanicState.RegPtr, sizeof (E3_Regs)); -+ -+ for (bank = 0; bank < ELAN3_SDRAM_NUM_BANKS; bank++) -+ if (dev->SdramBanks[bank].Size && dev->PanicState.Sdram[bank]) -+ elan3_sdram_copyq_from_sdram (dev, (bank << ELAN3_SDRAM_BANK_SHIFT), dev->PanicState.Sdram[bank], dev->SdramBanks[bank].Size); -+ -+ } -+} -+ -+int -+elan3_assfail (ELAN3_DEV *dev, char *string, char *file, int line) -+{ -+ if (panicstr) -+ return (0); -+ -+ printk ("elan: assertion failed '%s' File '%s' Line %d\n", string, file, line); -+ -+#if defined(LINUX) -+ elan3_save_panicstate (dev); -+ -+ panic ("elan: assertion failed '%s' File '%s' Line %d\n", string, file, line); -+#else -+ cmn_err (CE_PANIC, "elan: assertion failed '%s' File '%s' Line %d\n", string, file, line); -+#endif -+ /*NOTREACHED*/ -+ return (0); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elandev_generic.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elandev_generic.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elandev_generic.c 2005-06-01 23:12:54.578442296 -0400 -@@ -0,0 +1,1862 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elandev_generic.c,v 1.111.2.3 2004/11/15 11:12:36 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/elandev_generic.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * Module globals, configurable from system file. -+ */ -+u_int elan3_debug = 0; -+u_int elan3_debug_console = 0; -+u_int elan3_debug_buffer = -1; -+u_int elan3_debug_ignore_dev = 0; -+u_int elan3_debug_ignore_kcomm = 0; -+u_int elan3_debug_ignore_ctxt = 0; -+u_int elan3_debug_display_ctxt = 0; -+ -+int eventint_punt_loops; -+int eventint_punt_ticks; -+int eventint_resched_ticks; -+ -+static void InitialiseDmaBuffers (ELAN3_DEV *dev, ioaddr_t CmdPort); -+static int ProbeSdram (ELAN3_DEV *dev); -+static void InitialiseSdram (ELAN3_DEV *dev); -+static void ReEnableErrorInterrupts (void *arg); -+void PollForDmaHungup (void *arg); -+static void elan3_event_interrupt (ELAN3_DEV *dev); -+ -+/* -+ * BaseAddr is ptr to the start of a table aligned on a power of two byte address. -+ * SizePower must be in the range of 6 to 12. It defines the number of valid contexts as -+ * shown below. -+ * -+ * SizePower Valid Contexts Table size in bytes. -+ * 6 64 1k -+ * 7 128 2k -+ * 8 256 4K -+ * 9 512 8k -+ * 10 1024 16k -+ * 11 2048 32k -+ * 12 4096 64k -+ */ -+#define GEN_CONTEXT_PTR(BaseAddr, SizePower) (((E3_uint32) BaseAddr) | \ -+ (~((1 << ((SizePower) - 6)) - 1) & 0x3f)) -+ -+int -+InitialiseElan (ELAN3_DEV *dev, ioaddr_t CmdPort) -+{ -+ E3_IprocTrapHeader_BE TrapCleanup[4]; -+ E3_ContextControlBlock ContextControlBlock; -+ sdramaddr_t ptr; -+ int res; -+ int i; -+ -+ eventint_punt_loops = 100; -+ eventint_punt_ticks = (hz/100); -+ eventint_resched_ticks = (hz/4); -+ -+ dev->Stats.Version = ELAN3_STATS_VERSION; -+ dev->Position.pos_mode = ELAN_POS_UNKNOWN; -+ -+ /* -+ * The elan should have already been reset, so the interrupt mask -+ * should be 0 and the schedule status register should be set to -+ * its initial state -+ */ -+ ASSERT (dev->InterruptMask == 0); -+ ASSERT ((read_reg32 (dev, Exts.SchCntReg) & HaltStopAndExtTestMask) == Sched_Initial_Value); -+ -+ /* -+ * Write any value here to clear out the half full and error bits of the command -+ * overflow queues. -+ */ -+ write_reg32 (dev, ComQueueStatus, 0); -+ -+ /* Initialise the cache tags before touching the SDRAM */ -+ /* we initialise them to "map" the bottom of SDRAM */ -+ for (i = 0; i < E3_NumCacheLines; i++) -+ { -+ write_cache_tag (dev, Tags[i][0].Value, 0x0000000000000000ULL); -+ write_cache_tag (dev, Tags[i][1].Value, 0x0000080000000000ULL); -+ write_cache_tag (dev, Tags[i][2].Value, 0x0000100000000000ULL); -+ write_cache_tag (dev, Tags[i][3].Value, 0x0000180000000000ULL); -+ } -+ -+#ifndef CONFIG_MPSAS -+ for (i = 0; i < E3_NumCacheLines*(E3_CACHELINE_SIZE/sizeof(E3_uint64)); i++) -+ { -+ write_cache_set (dev, Set0[i], 0xcac1ecac1ecac1e0ULL); -+ write_cache_set (dev, Set1[i], 0xcac1ecac1ecac1e1ULL); -+ write_cache_set (dev, Set2[i], 0xcac1ecac1ecac1e2ULL); -+ write_cache_set (dev, Set3[i], 0xcac1ecac1ecac1e3ULL); -+ } -+#endif -+ -+ if ((res = ProbeSdram(dev)) != ESUCCESS) -+ return (res); -+ -+ /* Enable all cache sets before initialising the sdram allocators */ -+ write_reg32 (dev, Cache_Control_Reg.ContReg, (dev->Cache_Control_Reg |= CONT_EN_ALL_SETS)); -+ -+ InitialiseSdram (dev); -+ -+ dev->TAndQBase = elan3_sdram_alloc (dev, ELAN3_TANDQ_SIZE); -+ dev->ContextTable = elan3_sdram_alloc (dev, ELAN3_CONTEXT_SIZE); -+ dev->ContextTableSize = ELAN3_NUM_CONTEXTS; -+ dev->CommandPortTraps[0] = elan3_sdram_alloc (dev, ELAN3_COMMAND_TRAP_SIZE); -+ dev->CommandPortTraps[1] = elan3_sdram_alloc (dev, ELAN3_COMMAND_TRAP_SIZE); -+ dev->CurrentCommandPortTrap = 0; -+ -+ PRINTF3 (DBG_DEVICE, DBG_CONFIG, "InitialiseElan: ContextTable %08lx TAndQ %08lx CommandPortTrap %08lx\n", -+ dev->ContextTable, dev->TAndQBase, dev->CommandPortTraps[0]); -+ -+ /* Allocate the thread amd dma trap areas */ -+ KMEM_ZALLOC (dev->ThreadTrap, THREAD_TRAP *, sizeof (THREAD_TRAP), TRUE); -+ KMEM_ZALLOC (dev->DmaTrap, DMA_TRAP *, sizeof (DMA_TRAP), TRUE); -+ -+ /* Allocate the ctxt table */ -+ KMEM_ZALLOC (dev->CtxtTable, ELAN3_CTXT **, dev->ContextTableSize * sizeof ( ELAN3_CTXT *), TRUE); -+ -+ /* Initialise halt queue list */ -+ dev->HaltOperationsTailpp = &dev->HaltOperations; -+ -+ /* From elan3/code/harness/elanstuff.c */ -+ /* Init the clock. */ -+ write_ureg64 (dev, Clock.NanoSecClock, 0); -+ -+ /* Init the instruction count reg. */ -+ write_ureg32 (dev, InstCount.s.StatsCount, 0); -+ -+ /* Init the stats control reg. Must be done before the count regs.*/ -+ write_ureg32 (dev, StatCont.StatsControl, 0); -+ -+ /* Init the stats count regs. */ -+ write_ureg32 (dev, StatCounts[0].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[1].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[2].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[3].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[4].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[5].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[6].s.StatsCount, 0); -+ write_ureg32 (dev, StatCounts[7].s.StatsCount, 0); -+ -+ /* -+ * Initialise the Context_Ptr and Fault_Base_Ptr -+ */ -+ write_reg32 (dev, Fault_Base_Ptr, dev->TAndQBase + offsetof(E3_TrapAndQueue, IProcSysCntx)); -+ write_reg32 (dev, Context_Ptr, GEN_CONTEXT_PTR (dev->ContextTable, ELAN3_LN2_NUM_CONTEXTS)); -+ -+ /* scrub the TProc Registers */ -+ for (i = 0; i < 8; i++) -+ write_reg32 (dev, Globals[i], 0xdeadbabe); -+ for (i = 0; i < 8; i++) -+ write_reg32 (dev, Outs[i], 0xdeadbabe); -+ for (i = 0; i < 8; i++) -+ write_reg32 (dev, Locals[i], 0xdeadbabe); -+ for (i = 0; i < 8; i++) -+ write_reg32 (dev, Ins[i], 0xdeadbabe); -+ -+ /* -+ * Initialise the Queue pointers. Arrange them so that the starting positions are -+ * farthest apart in one set of the cache. Thus 512 bytes apart, but with cntx0 -+ * thread the same as the interrupt queue. -+ */ -+ write_reg32 (dev, TProc_NonSysCntx_FPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxThreadQueue[0xc0])); -+ write_reg32 (dev, TProc_NonSysCntx_BPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxThreadQueue[0xc0])); -+ write_reg32 (dev, TProc_SysCntx_FPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxThreadQueue[0x80])); -+ write_reg32 (dev, TProc_SysCntx_BPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxThreadQueue[0x80])); -+ -+ write_reg32 (dev, DProc_NonSysCntx_FPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxDmaQueue[0])); -+ write_reg32 (dev, DProc_NonSysCntx_BPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxDmaQueue[0])); -+ write_reg32 (dev, DProc_SysCntx_FPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[0x10])); -+ write_reg32 (dev, DProc_SysCntx_BPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[0x10])); -+ -+ dev->Event_Int_Queue_FPtr = dev->TAndQBase + offsetof (E3_TrapAndQueue, EventIntQueue[0x80]); -+ write_reg32 (dev, Event_Int_Queue_FPtr, dev->Event_Int_Queue_FPtr); -+ write_reg32 (dev, Event_Int_Queue_BPtr, dev->TAndQBase + offsetof (E3_TrapAndQueue, EventIntQueue[0x80])); -+ -+ -+ /* Initialise Input_Trap_Base to last 8 Kbytes of trap area, uCode adds the right offset */ -+ write_reg32 (dev, Input_Trap_Base, dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxThreadQueue[0])); -+ -+ /* Ptr to word used to save the SP to when a thread deschedules */ -+ write_reg32 (dev, Thread_SP_Save_Ptr, dev->TAndQBase + offsetof (E3_TrapAndQueue, Thread_SP_Save)); -+ -+ /* Initialise the command trap base */ -+ write_reg32 (dev, CProc_TrapSave_Addr, dev->CommandPortTraps[0]); -+ -+ /* Initialise the set event tracing registers */ -+ write_reg32 (dev, Event_Trace_Ptr, 0); -+ write_reg32 (dev, Event_Trace_Mask, 0); -+ -+ /* Initialise Tlb_Line_Value to zero. The TLB cannot be read while either the */ -+ /* uCode or thread proc might be running. Must be set to 0. */ -+ write_reg64 (dev, Tlb_Line_Value, 0); -+ -+ /* Control register. Cache everything, Enable MMU, RefreshRate=3, CasLatency=1, StartSDR */ -+ dev->Cache_Control_Reg |= CONT_MMU_ENABLE | CONT_EN_ALL_SETS | CONT_CACHE_ALL | CONT_ENABLE_ECC; -+ -+#if ELAN3_PAGE_SHIFT == 13 -+ dev->Cache_Control_Reg |= CONT_ENABLE_8K_PAGES; -+#endif -+ -+ write_reg32 (dev, Cache_Control_Reg.ContReg, dev->Cache_Control_Reg); -+ -+ /* -+ * Initialise the context table to be discard for all contexts -+ */ -+ ContextControlBlock.rootPTP = 0; -+ ContextControlBlock.filter = E3_CCB_DISCARD_ALL; -+ ContextControlBlock.VPT_mask = 0; -+ ContextControlBlock.VPT_ptr = 0; -+ -+ for (i = 0, ptr = dev->ContextTable; i < ELAN3_NUM_CONTEXTS; i++, ptr += sizeof (E3_ContextControlBlock)) -+ elan3_sdram_copyl_to_sdram (dev, &ContextControlBlock, ptr, sizeof (E3_ContextControlBlock)); -+ -+ /* From elan3/code/trap_handler/init.c */ -+ /* -+ * Initialise the Trap And Queue area in Elan SDRAM. -+ */ -+ TrapCleanup[0].s.TrTypeCntx.TypeContext = 0; -+ TrapCleanup[0].s.TrAddr = 0; -+ TrapCleanup[0].s.IProcTrapStatus.Status = CRC_STATUS_GOOD; -+ TrapCleanup[0].s.TrData0 = 0; -+ TrapCleanup[1].s.TrTypeCntx.TypeContext = 0; -+ TrapCleanup[1].s.TrAddr = 0; -+ TrapCleanup[1].s.IProcTrapStatus.Status = CRC_STATUS_GOOD; -+ TrapCleanup[1].s.TrData0 = 0; -+ TrapCleanup[2].s.TrTypeCntx.TypeContext = 0; -+ TrapCleanup[2].s.TrAddr = 0; -+ TrapCleanup[2].s.IProcTrapStatus.Status = CRC_STATUS_GOOD; -+ TrapCleanup[2].s.TrData0 = 0; -+ TrapCleanup[3].s.TrTypeCntx.TypeContext = 0; -+ TrapCleanup[3].s.TrAddr = 0; -+ TrapCleanup[3].s.IProcTrapStatus.Status = CRC_STATUS_GOOD; -+ TrapCleanup[3].s.TrData0 = 0; -+ -+ elan3_sdram_writel (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcSysCntx.s.FaultContext), 0); -+ elan3_sdram_writel (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcSysCntx.s.FSR.Status), 0); -+ elan3_sdram_writel (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcNonSysCntx.s.FaultContext), 0); -+ elan3_sdram_writel (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcNonSysCntx.s.FSR.Status), 0); -+ -+ /* Must now zero all the FSRs so that a subsequent Fault can be seen */ -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, CProc), 16); -+ -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0), 64); -+ -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, TProc), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcData), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcInst), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcOpen), 16); -+ -+ elan3_sdram_copyq_to_sdram (dev, TrapCleanup, dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh0_C0_TrHead[0]), 64); -+ elan3_sdram_copyq_to_sdram (dev, TrapCleanup, dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh1_C0_TrHead[0]), 64); -+ -+ elan3_sdram_copyq_to_sdram (dev, TrapCleanup, dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh0_NonC0_TrHead[0]), 64); -+ elan3_sdram_copyq_to_sdram (dev, TrapCleanup, dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh1_NonC0_TrHead[0]), 64); -+ -+ InitialiseDmaBuffers(dev, CmdPort); -+ -+ /* reserve a halt operation for flushing the context filter */ -+ ReserveHaltOperations (dev, 1, TRUE); -+ -+ /* Allow the Thread/Dma to run */ -+ CLEAR_SCHED_STATUS (dev, HaltThread | HaltDmas); -+ -+ /* Enable All Interrrupts */ -+ SET_INT_MASK (dev, (INT_PciMemErr | INT_SDRamInt | INT_EventInterrupt | INT_LinkError | INT_ComQueue | -+ INT_TProc | INT_CProc | INT_DProc | INT_IProcCh1NonSysCntx | -+ INT_IProcCh1SysCntx | INT_IProcCh0NonSysCntx | INT_IProcCh0SysCntx)); -+ -+ /* Take the link out of boundary scan */ -+ SET_SCHED_LINK_VALUE (dev, 0, 0); -+ -+ /* And clear any link errors */ -+ PULSE_SCHED_STATUS (dev, ClearLinkErrorInt); -+ -+ /* XXXX: clear discard context 0, AFTER setting up the kernel comms */ -+ CLEAR_SCHED_STATUS (dev, DiscardSysCntxIn | DiscardNonSysCntxIn); -+ -+ /* Start a thread to handle excessive Event Interrrupts */ -+ if (kernel_thread_create (elan3_event_interrupt, (caddr_t) dev) == NULL) -+ { -+ panic ("InitialiseElan: cannot start elan3_event_interrupt\n"); -+ return (EFAIL); -+ } -+ dev->EventInterruptThreadStarted = 1; -+ -+ ReserveHaltOperations (dev, 1, TRUE); -+ -+ PollForDmaHungup (dev); -+ -+ /* register the device and stats with elanmod for RMS */ -+ dev->DeviceIdx = elan_dev_register(&dev->Devinfo, &elan3_dev_ops, (void *) dev); -+ -+ elan3_register_dev_stats(dev); -+ -+ return (ESUCCESS); -+} -+ -+static void -+InitialiseDmaBuffers(ELAN3_DEV *dev, ioaddr_t CmdPort) -+{ -+ register int i; -+ -+ /* GNAT sw-elan3/3908: -+ * Clear down the power on state of the Dma_Desc registers to make sure we don't -+ * try and interpret them when a trap happens. -+ */ -+ write_reg32 (dev, Dma_Desc.dma_type, 0); -+ write_reg32 (dev, Dma_Desc.dma_size, 0); -+ write_reg32 (dev, Dma_Desc.dma_source, 0); -+ write_reg32 (dev, Dma_Desc.dma_dest, 0); -+ write_reg32 (dev, Dma_Desc.dma_destEvent, 0); -+ write_reg32 (dev, Dma_Desc.dma_destCookieVProc, 0); -+ write_reg32 (dev, Dma_Desc.dma_srcEvent, 0); -+ write_reg32 (dev, Dma_Desc.dma_srcCookieVProc, 0); -+ -+ /* -+ * The following is a sequence of writes to remove X's from the dma buffers and -+ * registers. It is only safe to write these registers after reset and before any -+ * dma's have been issued. The chip will NOT function corectly if they are written at -+ * any other time or in a different order. -+ */ -+ write_reg64 (dev, Exts.Dmas.DmaWrs.LdAlignment, 0); -+ write_reg64 (dev, Exts.Dmas.DmaWrs.LdDmaType, 0); -+ write_reg64 (dev, Exts.Dmas.DmaWrs.ResetAckNLdBytesToWr, ((u_longlong_t)0x1000) << 32); -+ write_reg64 (dev, Exts.Dmas.DmaWrs.LdBytesToRd, ((u_longlong_t)0x100) << 32); -+ -+ for (i=0;i<(4*8);i++) -+ write_reg64 (dev, Dma_Alignment_Port[0], 0); -+ -+ /* -+ * This is used to clear out X's from some of the trap registers. This is required to -+ * prevent the first traps from possibly writting X's into the SDram and upsetting the -+ * ECC value. It requires that the trap save area registers have been set up but does -+ * not require any translations to be ready. -+ */ -+ writel (-1, CmdPort + offsetof (E3_CommandPort, SetEvent)); -+ while ((read_reg32 (dev, Exts.InterruptReg) & INT_CProc) == 0) -+ { -+ mb(); -+ DELAY (1); -+ } -+ -+ write_reg32 (dev, CProc_TrapSave_Addr, dev->CommandPortTraps[dev->CurrentCommandPortTrap]); -+ -+ PULSE_SCHED_STATUS(dev, RestartCProc); -+} -+ -+void -+FinaliseElan (ELAN3_DEV *dev) -+{ -+ ELAN3_PTBL_GR *ptg; -+ ELAN3_HALTOP *op; -+ ELAN3_HALTOP *chain = NULL; -+ int bank; -+ int indx; -+ int size; -+ unsigned long flags; -+ int level; -+ -+ elan_stats_deregister (dev->StatsIndex); -+ elan_dev_deregister(&dev->Devinfo); -+ -+ /* Cancel the dma poller */ -+ cancel_timer_fn (&dev->DmaPollTimeoutId); -+ -+ /* release it's halt operation */ -+ ReleaseHaltOperations (dev, 1); -+ -+ /* stop all kernel threads */ -+ dev->ThreadsShouldStop = 1; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ while (dev->EventInterruptThreadStarted && !dev->EventInterruptThreadStopped) -+ { -+ kcondvar_wakeupall (&dev->IntrWait, &dev->IntrLock); -+ kcondvar_wait (&dev->IntrWait, &dev->IntrLock, &flags); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ /* Set the interrupt mask to 0 and the schedule control register to run nothing */ -+ SET_INT_MASK (dev, 0); -+ SET_SCHED_STATUS (dev, DiscardNonSysCntxIn | DiscardSysCntxIn | HaltThread | HaltDmas); -+ -+ /* Cancel any link error timeout */ -+ if (timer_fn_queued(&dev->ErrorTimeoutId)) -+ cancel_timer_fn (&dev->ErrorTimeoutId); -+ -+ /* Free of and page tables that have been allocated */ -+ spin_lock (&dev->PtblGroupLock); -+ for(level=0; level<4; level++) -+ { -+ while ((ptg = dev->Level[level].PtblGroupList) != NULL) -+ { -+ dev->Level[level].PtblGroupList = ptg->pg_next; -+ -+ elan3_sdram_free (dev, ptg->pg_addr, PTBL_GROUP_SIZE); -+ FREE_PTBL_GR(ptg); -+ } -+ } -+ -+ spin_unlock (&dev->PtblGroupLock); -+ -+ /* Free of all halt operations */ -+ spin_lock_irqsave (&dev->FreeHaltLock, flags); -+ while ((op = dev->FreeHaltOperations) != NULL) -+ { -+ dev->FreeHaltOperations = op->Next; -+ -+ /* Keep a list of 'freed' ops for later KMEM_FREE call */ -+ op->Next = chain; -+ chain = op; -+ } -+ spin_unlock_irqrestore (&dev->FreeHaltLock, flags); -+ -+ /* Have now dropped the spinlock - can call KMEM_FREE */ -+ while ((op = chain) != NULL) -+ { -+ chain = op->Next; -+ -+ KMEM_FREE (op, sizeof (ELAN3_HALTOP)); -+ } -+ -+ /* Free of the ctxt table */ -+ KMEM_FREE (dev->CtxtTable, dev->ContextTableSize * sizeof (ELAN3_CTXT *)); -+ -+ /* Free of the thread and dma atrap areas */ -+ KMEM_FREE (dev->ThreadTrap, sizeof (THREAD_TRAP)); -+ KMEM_FREE (dev->DmaTrap, sizeof (DMA_TRAP)); -+ -+ /* Free of the memsegs and pages */ -+ for (bank = 0; bank < ELAN3_SDRAM_NUM_BANKS; bank++) -+ { -+ if (dev->SdramBanks[bank].Size) -+ { -+ UnmapDeviceRegister (dev, &dev->SdramBanks[bank].Handle); -+ -+ KMEM_FREE (dev->SdramBanks[bank].PtblGroups, sizeof (ELAN3_PTBL_GR *) * (dev->SdramBanks[bank].Size / PTBL_GROUP_SIZE)); -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size <= dev->SdramBanks[bank].Size; indx++, size <<= 1) -+ KMEM_FREE (dev->SdramBanks[bank].Bitmaps[indx], sizeof (bitmap_t)*BT_BITOUL(dev->SdramBanks[bank].Size/size)); -+ } -+ } -+ elan3_sdram_fini (dev); -+} -+ -+#define INIT_PATTERN(offset) (0xBEEC000000000011ull | ((u_longlong_t)(offset)) << 16) -+#define FREE_PATTERN(offset) (0xBEEC000000000022ull | ((u_longlong_t)(offset)) << 16) -+ -+static int -+ProbeSdram (ELAN3_DEV *dev) -+{ -+ int Instance; -+ u_int Bank; -+ int MemSpaceSize; -+ int BankMaxSize; -+ int BankOffset; -+ int BankSize; -+ ioaddr_t BankBase; -+ ioaddr_t PageBase; -+ ioaddr_t PageBase1; -+ ioaddr_t PageBase2; -+ DeviceMappingHandle BankHandle; -+ DeviceMappingHandle PageHandle; -+ DeviceMappingHandle PageHandle1; -+ DeviceMappingHandle PageHandle2; -+ register int i; -+ u_longlong_t value; -+ extern int sdram_bank_limit; -+ -+ /* NOTE: The Cache control register is set to only enable cache set 0 */ -+ /* and has ECC disabled */ -+ Instance = dev->Instance; -+ -+ /* Determine the size of the SDRAM from the BAR register */ -+ if (DeviceRegisterSize (dev, ELAN3_BAR_SDRAM, &MemSpaceSize) != ESUCCESS) -+ { -+ printk ("elan%d: cannot determine SDRAM size\n", Instance); -+ return (EFAIL); -+ } -+ -+ elan3_sdram_init (dev); -+ -+ BankMaxSize = MemSpaceSize / ELAN3_SDRAM_NUM_BANKS; -+ -+ for (Bank = 0; Bank < ELAN3_SDRAM_NUM_BANKS; Bank++) -+ { -+ BankOffset = Bank * BankMaxSize; -+ -+ PRINTF3 (DBG_DEVICE, DBG_CONFIG, "elan%d: Probing RAM Bank %d (max size %08x)\n", Instance, Bank, BankMaxSize); -+ -+ /* Probe the memory bank by mapping two pages that are the size of the cache apart */ -+ /* this guarantees that when we store the second pattern we displace the first pattern */ -+ /* from the cache, also store the second pattern again the size of the cache up again */ -+ /* to ensure that the SDRAM wires don't stay floating at pattern1 */ -+ -+ if (MapDeviceRegister (dev, ELAN3_BAR_SDRAM, &BankBase, BankOffset, PAGESIZE, &BankHandle) != ESUCCESS) -+ { -+ printk ("elan%d: Cannot probe memory bank %d\n", Instance, Bank); -+ continue; -+ } -+ -+ if (MapDeviceRegister (dev, ELAN3_BAR_SDRAM, &PageBase1, BankOffset + ELAN3_MAX_CACHE_SIZE, PAGESIZE, &PageHandle1) != ESUCCESS) -+ { -+ printk ("elan%d: Cannot probe memory bank %d\n", Instance, Bank); -+ UnmapDeviceRegister (dev, &BankHandle); -+ continue; -+ } -+ -+ if (MapDeviceRegister (dev, ELAN3_BAR_SDRAM, &PageBase2, BankOffset + 2*ELAN3_MAX_CACHE_SIZE, PAGESIZE, &PageHandle2) != ESUCCESS) -+ { -+ printk ("elan%d: Cannot probe memory bank %d\n", Instance, Bank); -+ UnmapDeviceRegister (dev, &BankHandle); -+ UnmapDeviceRegister (dev, &PageHandle1); -+ continue; -+ } -+ -+#define PATTERN0 (0x5555555555555555L) -+#define PATTERN1 (0xAAAAAAAAAAAAAAAAL) -+ writeq (PATTERN0, (u_longlong_t *) BankBase); -+ writeq (PATTERN1, (u_longlong_t *) PageBase1); -+ writeq (PATTERN1, (u_longlong_t *) PageBase2); -+ -+ mmiob(); -+ -+ value = readq ((u_longlong_t *) BankBase); -+ -+ if (value != PATTERN0) -+ { -+ UnmapDeviceRegister (dev, &BankHandle); -+ UnmapDeviceRegister (dev, &PageHandle1); -+ UnmapDeviceRegister (dev, &PageHandle2); -+ continue; -+ } -+ -+ writeq (PATTERN1, (u_longlong_t *) BankBase); -+ writeq (PATTERN0, (u_longlong_t *) PageBase1); -+ writeq (PATTERN0, (u_longlong_t *) PageBase2); -+ -+ mmiob(); -+ -+ value = readq ((u_longlong_t *) BankBase); -+ if (value != PATTERN1) -+ { -+ UnmapDeviceRegister (dev, &BankHandle); -+ UnmapDeviceRegister (dev, &PageHandle1); -+ UnmapDeviceRegister (dev, &PageHandle2); -+ continue; -+ } -+ UnmapDeviceRegister (dev, &PageHandle1); -+ UnmapDeviceRegister (dev, &PageHandle2); -+ -+ /* Bank is present, so work out its size, we store tha maximum size at the base */ -+ /* and then store the address at each address on every power of two address until */ -+ /* we reach the minimum mappable size (PAGESIZE), we then read back the value at the */ -+ /* base to determine the bank size */ -+ writeq ((u_longlong_t) BankMaxSize, (u_longlong_t *) BankBase); -+ -+ for (BankSize = (BankMaxSize>>1); BankSize > PAGESIZE; BankSize >>= 1) -+ { -+ if (MapDeviceRegister (dev, ELAN3_BAR_SDRAM, &PageBase, BankOffset + BankSize, PAGESIZE, &PageHandle) == ESUCCESS) -+ { -+ writeq (BankSize, (u_longlong_t *) PageBase); -+ UnmapDeviceRegister (dev, &PageHandle); -+ } -+ } -+ mmiob(); -+ -+ BankSize = (u_long) readq ((u_longlong_t *) BankBase); -+ -+ if (sdram_bank_limit == 0 || BankSize <= (sdram_bank_limit * 1024 * 1024)) -+ printk ("elan%d: memory bank %d is %dK\n", Instance, Bank, BankSize / 1024); -+ else -+ { -+ BankSize = (sdram_bank_limit * 1024 * 1024); -+ printk ("elan%d: limit memory bank %d to %dK\n", Instance, Bank, BankSize / 1024); -+ } -+ -+ UnmapDeviceRegister (dev, &BankHandle); -+ -+ /* Now map all of this bank into the kernel */ -+ if (MapDeviceRegister (dev, ELAN3_BAR_SDRAM, &BankBase, BankOffset, BankSize, &BankHandle) != ESUCCESS) -+ { -+ printk ("elan%d: Cannot initialise memory bank %d\n", Instance, Bank); -+ continue; -+ } -+ -+ dev->SdramBanks[Bank].Size = BankSize; -+ dev->SdramBanks[Bank].Mapping = BankBase; -+ dev->SdramBanks[Bank].Handle = BankHandle; -+ -+#ifndef CONFIG_MPSAS -+ /* Initialise it for ECC */ -+ preemptable_start { -+ for (i = 0; i < BankSize; i += 8) -+ { -+ elan3_sdram_writeq (dev, (Bank << ELAN3_SDRAM_BANK_SHIFT) | i, INIT_PATTERN(BankOffset+i)); -+ -+ preemptable_check(); -+ } -+ } preemptable_end; -+#endif -+ } -+ -+ return (ESUCCESS); -+} -+ -+static void -+InitialiseSdram (ELAN3_DEV *dev) -+{ -+ int indx, size, b; -+ -+ for (b = 0; b < ELAN3_SDRAM_NUM_BANKS; b++) -+ { -+ ELAN3_SDRAM_BANK *bank = &dev->SdramBanks[b]; -+ -+ if (bank->Size == 0) -+ continue; -+ -+ /* allocate a ptbl group pointer for each possible ptbl group in this bank */ -+ KMEM_ZALLOC (bank->PtblGroups, ELAN3_PTBL_GR **, sizeof (ELAN3_PTBL_GR *) * bank->Size/PTBL_GROUP_SIZE, TRUE); -+ -+ /* allocate the buddy allocator bitmaps */ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size <= bank->Size; indx++, size <<= 1) -+ KMEM_ZALLOC (bank->Bitmaps[indx], bitmap_t *, sizeof (bitmap_t)*BT_BITOUL(bank->Size/size), TRUE); -+ -+ /* and add it to the sdram buddy allocator */ -+ elan3_sdram_add (dev, (b << ELAN3_SDRAM_BANK_SHIFT), (b << ELAN3_SDRAM_BANK_SHIFT) + bank->Size); -+ } -+} -+ -+#include -+ -+int -+ReadVitalProductData (ELAN3_DEV *dev, int *CasLatency) -+{ -+ DeviceMappingHandle RomHandle; -+ unsigned char *RomBase; -+ unsigned char *PCIDataPtr; -+ unsigned char *VPDPtr; -+ unsigned char *lim; -+ int type; -+ int i, len, len2; -+ char name[3] = "XX"; -+ char value[256]; -+ int finished = 0; -+ -+ -+ /* default valud for CAS latency is 3 */ -+ (*CasLatency) = CAS_LATENCY_3; -+ -+ if (MapDeviceRegister (dev, ELAN3_BAR_EBUS, (ioaddr_t *) &RomBase, ELAN3_EBUS_ROM_OFFSET, ELAN3_EBUS_ROM_SIZE, &RomHandle) != ESUCCESS) -+ { -+ printk ("elan%d: Cannot map ROM\n", dev->Instance); -+ return (EFAIL); -+ } -+ -+ /* Check the ROM signature */ -+ if (RomBase[0] != 0x55 || RomBase[1] != 0xAA) -+ { -+ printk ("elan%d: Invalid ROM signature %02x %02x\n", dev->Instance, RomBase[0], RomBase[1]); -+ return (ESUCCESS); -+ } -+ -+ PCIDataPtr = RomBase + ((RomBase[0x19] << 8) | RomBase[0x18]); -+ -+ /* check the pci data structure */ -+ if (PCIDataPtr[0] != 'P' || PCIDataPtr[1] != 'C' || PCIDataPtr[2] != 'I' || PCIDataPtr[3] != 'R') -+ { -+ printk ("elan%d: Invalid PCI Data structure\n", dev->Instance); -+ return (ESUCCESS); -+ } -+ -+ /* Extract the VPD pointer */ -+ VPDPtr = RomBase + ((PCIDataPtr[9] << 8) | PCIDataPtr[8]); -+ -+ if (VPDPtr == RomBase) -+ { -+ printk ("elan%d: No Vital Product Data\n", dev->Instance); -+ return (ESUCCESS); -+ } -+ -+ while (! finished) -+ { -+ type = *VPDPtr++; -+ -+ if (type & LARGE_RESOURCE_BIT) -+ { -+ len = *(VPDPtr++); -+ len += *(VPDPtr++) << 8; -+ -+ switch (type & ~LARGE_RESOURCE_BIT) -+ { -+ case LARGE_RESOURCE_STRING: -+ printk ("elan%d: ", dev->Instance); -+ for (i = 0; i < len; i++) -+ printk ("%c", *VPDPtr++); -+ printk ("\n"); -+ break; -+ -+ case LARGE_RESOURCE_VENDOR_DEFINED: -+ VPDPtr += len; -+ break; -+ -+ case LARGE_RESOURCE_VITAL_PRODUCT_DATA: -+ for (lim = VPDPtr + len; VPDPtr < lim; ) -+ { -+ name[0] = *VPDPtr++; -+ name[1] = *VPDPtr++; -+ len2 = *VPDPtr++; -+ -+ for (i = 0; i < len2 && VPDPtr < lim; i++) -+ value[i] = *VPDPtr++; -+ value[i] = '\0'; -+ -+ if (! strcmp (name, "SN")) -+ printk ("elan%d: Serial Number - %s\n", dev->Instance, value); -+ -+ if (! strcmp (name, "Z0")) -+ (*CasLatency) = (strcmp (value, "CAS_LATENCY_2") ? CAS_LATENCY_3 : CAS_LATENCY_2); -+ } -+ break; -+ -+ default: -+ printk ("elan%d: unknown large resource %x\n", dev->Instance, type); -+ finished = 1; -+ break; -+ } -+ } -+ else -+ { -+ len = type & 0x7; -+ -+ switch (type >> 3) -+ { -+ case SMALL_RESOURCE_COMPATIBLE_DEVICE_ID: -+ VPDPtr += len; -+ break; -+ -+ case SMALL_RESOURCE_VENDOR_DEFINED: -+ VPDPtr += len; -+ break; -+ -+ case SMALL_RESOURCE_END_TAG: -+ finished = 1; -+ break; -+ -+ default: -+ printk ("elan%d: unknown small resource %x\n", dev->Instance, type >> 3); -+ finished = 1; -+ break; -+ } -+ } -+ } -+ -+ UnmapDeviceRegister (dev, &RomHandle); -+ return (ESUCCESS); -+} -+ -+void -+ElanSetPtblGr (ELAN3_DEV *dev, sdramaddr_t offset, ELAN3_PTBL_GR *ptg) -+{ -+ int bank = offset >> ELAN3_SDRAM_BANK_SHIFT; -+ -+ dev->SdramBanks[bank].PtblGroups[(offset & (ELAN3_SDRAM_BANK_SIZE-1)) / PTBL_GROUP_SIZE] = ptg; -+} -+ -+ELAN3_PTBL_GR * -+ElanGetPtblGr (ELAN3_DEV *dev, sdramaddr_t offset) -+{ -+ int bank = offset >> ELAN3_SDRAM_BANK_SHIFT; -+ -+ return (dev->SdramBanks[bank].PtblGroups[(offset & (ELAN3_SDRAM_BANK_SIZE-1)) / PTBL_GROUP_SIZE]); -+} -+ -+void -+ElanFlushTlb (ELAN3_DEV *dev) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->TlbLock, flags); -+ BumpStat (dev, TlbFlushes); -+ -+ write_reg32 (dev, Cache_Control_Reg.ContReg, dev->Cache_Control_Reg | MMU_FLUSH); -+ mmiob(); -+ spin_unlock_irqrestore (&dev->TlbLock, flags); -+ -+ while (! (read_reg32 (dev, Cache_Control_Reg.ContReg) & MMU_FLUSHED)) -+ mb(); -+} -+ -+void -+KillNegativeDma (ELAN3_DEV *dev, void *arg) -+{ -+ DMA_TRAP *trap = dev->DmaTrap; -+ E3_Status_Reg status; -+ sdramaddr_t FPtr, BPtr; -+ sdramaddr_t Base, Top; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ ASSERT (read_reg32 (dev, Exts.InterruptReg) & INT_DProcHalted); -+ -+ /* Initialise the trap to deliver to the offending user process */ -+ trap->Status.Status = read_reg32 (dev, Exts.DProcStatus.Status); -+ trap->PacketInfo.Value = 0; -+ -+ bzero (&trap->FaultSave, sizeof (trap->FaultSave)); -+ bzero (&trap->Data0, sizeof (trap->Data0)); -+ bzero (&trap->Data1, sizeof (trap->Data1)); -+ bzero (&trap->Data2, sizeof (trap->Data2)); -+ bzero (&trap->Data3, sizeof (trap->Data3)); -+ -+ /* run down the kernel dma run queue and panic on a -ve length dma */ -+ FPtr = read_reg32 (dev, DProc_SysCntx_FPtr); -+ BPtr = read_reg32 (dev, DProc_SysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[E3_SysCntxQueueSize-1]); -+ -+ while (FPtr != BPtr) -+ { -+ elan3_sdram_copyq_from_sdram (dev, FPtr, &trap->Desc, sizeof (E3_DMA_BE)); -+ -+ if (trap->Desc.s.dma_size > E3_MAX_DMA_SIZE) -+ panic ("KillNegativeDma: -ve sized kernel dma\n"); -+ -+ FPtr = (FPtr == Top) ? Base : FPtr + sizeof (E3_DMA); -+ } -+ -+ /* run down the user dma run queue and "remove" and -ve length dma's */ -+ FPtr = read_reg32 (dev, DProc_NonSysCntx_FPtr); -+ BPtr = read_reg32 (dev, DProc_NonSysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxDmaQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, NonSysCntxDmaQueue[E3_NonSysCntxQueueSize-1]); -+ -+ while (FPtr != BPtr) -+ { -+ elan3_sdram_copyq_from_sdram (dev, FPtr, &trap->Desc, sizeof (E3_DMA_BE)); -+ -+ if (trap->Desc.s.dma_size > E3_MAX_DMA_SIZE) -+ { -+ PRINTF3 (NULL, DBG_INTR, "KillNegativeDma: remove dma - context %d size %d SuspendAddr %x\n", -+ trap->Desc.s.dma_u.s.Context, trap->Desc.s.dma_size, trap->Status.s.SuspendAddr); -+ -+ trap->Status.s.TrapType = trap->Status.s.SuspendAddr; -+ trap->Status.s.Context = trap->Desc.s.dma_u.s.Context; -+ -+ DeliverDProcTrap (dev, trap, 0); -+ -+ /* -+ * Remove the DMA from the queue by replacing it with one with -+ * zero size and no events. -+ * -+ * NOTE: we must preserve the SYS_CONTEXT_BIT since the Elan uses this -+ * to mark the approriate run queue as empty. -+ */ -+ trap->Desc.s.dma_type = 0; -+ trap->Desc.s.dma_size = 0; -+ trap->Desc.s.dma_source = (E3_Addr) 0; -+ trap->Desc.s.dma_dest = (E3_Addr) 0; -+ trap->Desc.s.dma_destCookieVProc = (E3_Addr) 0; -+ trap->Desc.s.dma_srcEvent = (E3_Addr) 0; -+ trap->Desc.s.dma_srcCookieVProc = (E3_Addr) 0; -+ -+ elan3_sdram_copyq_to_sdram (dev, &trap->Desc, FPtr, sizeof (E3_DMA_BE)); -+ } -+ -+ FPtr = (FPtr == Top) ? Base : FPtr + sizeof (E3_DMA); -+ } -+ -+ status.Status = read_reg32 (dev, Exts.DProcStatus.Status); -+ -+ if (status.s.SuspendAddr == MI_DequeueNonSysCntxDma || -+ status.s.SuspendAddr == MI_DequeueSysCntxDma || -+ status.s.SuspendAddr == MI_DmaLoop) -+ { -+ PRINTF0 (NULL, DBG_INTR, "KillNegativeDma: unlock dma processor\n"); -+ write_reg32 (dev, Exts.Dmas.DmaWrs.LdAlignment, 0); -+ write_reg32 (dev, Exts.Dmas.DmaWrs.LdDmaType, 0); -+ mmiob(); -+ -+ DELAY (10); -+ -+ write_reg32 (dev, Exts.Dmas.DmaWrs.LdAlignment, 0); -+ write_reg32 (dev, Exts.Dmas.DmaWrs.LdDmaType, 0); -+ mmiob(); -+ } -+ -+ PRINTF0 (NULL, DBG_INTR, "KillNegativeDma: dma processor restarted\n"); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ schedule_timer_fn (&dev->DmaPollTimeoutId, PollForDmaHungup, (void *) dev, 1); -+} -+ -+void -+ForceTProcTrap (ELAN3_DEV *dev, void *arg) -+{ -+ printk ("elan%d: forced tproc trap .....\n", dev->Instance); -+ -+ schedule_timer_fn (&dev->DmaPollTimeoutId, PollForDmaHungup, (void *) dev, 1); -+} -+ -+void -+PollForDmaHungup (void *arg) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *) arg; -+ unsigned long flags; -+ E3_Status_Reg status; -+ E3_uint32 insn1, insn3; -+ register int i; -+ -+ if (read_reg32 (dev, Dma_Desc.dma_size) > E3_MAX_DMA_SIZE) -+ { -+ status.Status = read_reg32 (dev, Exts.DProcStatus); -+ -+ PRINTF2 (NULL, DBG_INTR, "PollForDmaHungup: size %x SuspendAddr %x\n", read_reg32 (dev, Dma_Desc.dma_size), status.s.SuspendAddr); -+ -+ if (status.s.SuspendAddr == MI_DequeueNonSysCntxDma || -+ status.s.SuspendAddr == MI_DequeueSysCntxDma || -+ status.s.SuspendAddr == MI_DmaLoop) -+ { -+ printk ("elan%d: PollForDmaHungup: size %x context %d SuspendAddr %x\n", -+ dev->Instance, read_reg32 (dev, Dma_Desc.dma_size), -+ status.s.Context, status.s.SuspendAddr); -+ -+ PRINTF2 (NULL, DBG_INTR, "PollForDmaHungup: dma_size %x status %x\n", -+ read_reg32 (dev, Dma_Desc.dma_size), status.Status); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ QueueHaltOperation (dev, 0, NULL, INT_DProcHalted, KillNegativeDma, NULL); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return; -+ } -+ } -+ -+ status.Status = read_reg32 (dev, Exts.TProcStatus); -+ if (status.s.WakeupFunction == WakeupStopped) -+ { -+ E3_uint32 PC = read_reg32 (dev, ExecutePC); -+ -+ /* See if it's likely that the thread is really "stuck" on a waitevent/break -+ * instruction ......... */ -+ for (i = 0; i < 10; i++) -+ { -+ status.Status = read_reg32 (dev, Exts.TProcStatus); -+ insn1 = read_reg32 (dev, IBufferReg[1]); -+ insn3 = read_reg32 (dev, IBufferReg[3]); -+ -+ if (! (status.s.WakeupFunction == WakeupStopped && read_reg32 (dev, ExecutePC) == PC && /* stopping and it could be a break/waitevent */ -+ (insn1 == 0x81a00000 || insn3 == 0x81a00000 || /* break instruction */ -+ insn1 == 0x81b00000 || insn3 == 0x81b00000))) /* waitevent instruction */ -+ break; -+ } -+ -+ if (i == 10) -+ { -+ printk ("elan%d: forcing tproc trap from %s instruction at pc %x\n", dev->Instance, -+ (insn1 == 0x81a00000 || insn3 == 0x81a00000) ? "break" : "waitevent", PC); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ QueueHaltOperation (dev, 0, NULL, INT_TProcHalted, ForceTProcTrap, NULL); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return; -+ } -+ } -+ -+ schedule_timer_fn (&dev->DmaPollTimeoutId, PollForDmaHungup, (void *) dev, 10); -+} -+ -+/*=======================================================================================*/ -+/* -+ * Interrupt handler. -+ */ -+static void -+ReEnableErrorInterrupts (void *arg) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *) arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ if ((dev->SchCntReg & LinkBoundaryScan) == 0) -+ ENABLE_INT_MASK (dev, INT_ErrorInterrupts); -+ -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "ReEnableErrorInterrupts: IntMask=%x\n", read_reg32 (dev, Exts.InterruptMask)); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+void -+CheckForExcessiveErrorRate (ELAN3_DEV *dev) -+{ -+ if (dev->ErrorTime == (lbolt/hz)) -+ { -+ if (dev->ErrorsPerTick++ > 100) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "CheckForExcessiveErrorRate: too many links errors, disabling interrupt\n"); -+ -+ DISABLE_INT_MASK (dev, INT_ErrorInterrupts); -+ -+ schedule_timer_fn (&dev->ErrorTimeoutId, ReEnableErrorInterrupts, (void *) dev, hz); -+ } -+ } -+ else -+ { -+ dev->ErrorTime = (lbolt/hz); -+ dev->ErrorsPerTick = 0; -+ } -+} -+/*=======================================================================================*/ -+/* -+ * Interrupt handler. -+ */ -+static void -+HandlePciMemErr (ELAN3_DEV *dev) -+{ -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "HandlePciMemErr : masking out interrupt\n"); -+ -+ ElanBusError (dev); -+ panic ("elan pci memory error\n"); -+} -+ -+static void -+HandleSDRamInterrupt (ELAN3_DEV *dev) -+{ -+ E3_uint32 EccStatus0 = read_reg32 (dev, ECC_STATUS0); -+ E3_uint32 EccStatus1 = read_reg32 (dev, ECC_STATUS1); -+ unsigned long flags; -+ -+ PRINTF5 (DBG_DEVICE, DBG_INTR, "elan: ECC error - Addr=%x UE=%x CE=%x ME=%x Syn=%x\n", -+ EccStatus0 & ECC_ADDR_MASK, EccStatus0 & ECC_UE_MASK, -+ EccStatus0 & ECC_CE_MASK, EccStatus0 & ECC_ME_MASK, -+ EccStatus1 & ECC_SYN_MASK); -+ -+ if (EccStatus0 & (ECC_UE_MASK|ECC_CE_MASK)) -+ { -+ printk ("elan%d: ECC memory error (Address=%08x Syndrome=%02x %s%s%s)\n", -+ dev->Instance, -+ (EccStatus0 & ECC_ADDR_MASK), (EccStatus1 & ECC_SYN_MASK), -+ (EccStatus0 & ECC_UE_MASK) ? "Uncorrectable " : "", -+ (EccStatus0 & ECC_CE_MASK) ? "Correctable " : "", -+ (EccStatus0 & ECC_ME_MASK) ? "Multiple Errors " : ""); -+ } -+ -+ if (EccStatus0 & ECC_UE_MASK) -+ panic ("elan: Uncorrectable ECC memory error"); -+ if (EccStatus0 & ECC_CE_MASK) -+ BumpStat (dev, CorrectableErrors); -+ if (EccStatus0 & ECC_ME_MASK) -+ BumpStat (dev, MultipleErrors); -+ -+ /* -+ * Clear the interrupt and reset the error flags. -+ * Note. Might loose an UE or CE if it occurs between reading the status and -+ * clearing the interrupt. I don't think this matters very much as the -+ * status reg will only be used to identify a bad simm. -+ */ -+ -+ spin_lock_irqsave (&dev->TlbLock, flags); -+ write_reg32 (dev, Cache_Control_Reg.ContReg, dev->Cache_Control_Reg | CLEAR_SDRAM_ERROR); -+ mmiob(); -+ spin_unlock_irqrestore (&dev->TlbLock, flags); -+ -+ CheckForExcessiveErrorRate (dev); -+} -+ -+static int -+HandleEventInterrupt (ELAN3_DEV *dev, int nticks, unsigned long *flags) -+{ -+ E3_uint32 Fptr = dev->Event_Int_Queue_FPtr; -+ E3_uint32 Bptr = read_reg32 (dev, Event_Int_Queue_BPtr); /* PCI read */ -+ long tlim = lbolt + nticks; -+ long count = 0; -+ ELAN3_CTXT *ctxt; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ ASSERT ((dev->InterruptMask & INT_EventInterrupt) == 0); -+ -+ while (Fptr != Bptr) -+ { -+ while (Fptr != Bptr) -+ { -+ E3_EventInt_BE EvInt; -+ E3_uint32 Context; -+ -+ /* If we're running in the interrupt handler and have seen a high -+ * rate of event interrupts then punt to the thread - however on -+ * Linux the elan interrupt handler can block the timer interrupt, -+ * and so lbolt (jiffies) is not incremented, hence we punt after -+ a number of loops instead */ -+#if defined(LINUX) -+ if (in_interrupt() && ++count > eventint_punt_loops) -+ return (EAGAIN); -+#endif -+ -+ if (nticks && ((int) (lbolt - tlim)) > 0) -+ { -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "HandleEventInterrupt: Fptr %x Bptr %x punting to thread\n", Fptr, Bptr); -+ return (EAGAIN); -+ } -+ -+ elan3_sdram_copyq_from_sdram (dev, Fptr, (void *) &EvInt, 8); /* PCI read */ -+ -+ /* The context number is held in the top 16 bits of the EventContext */ -+ Context = (EvInt.s.EventContext >> 16) & MAX_ROOT_CONTEXT_MASK; -+ -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "HandleEventInterrupt: Context %d : Cookie %x\n", Context, EvInt.s.IntCookie); -+ -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, Context); -+ -+ /* Work out new fptr, and store it in the device, since we'll be dropping the IntrLock */ -+ Fptr = E3_EVENT_INTQ_NEXT(Fptr); -+ dev->Event_Int_Queue_FPtr = Fptr; -+ -+ if (ctxt == NULL) -+ { -+ PRINTF3 (DBG_DEVICE, DBG_INTR, "HandleEventInterrupt: Fptr %x Bptr %x context %d invalid\n", -+ Fptr, Bptr, Context); -+ BumpStat (dev, InvalidContext); -+ } -+ else -+ { -+ BumpStat (dev, EventInterrupts); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, *flags); -+ QueueEventInterrupt (ctxt, EvInt.s.IntCookie); -+ spin_lock_irqsave (&dev->IntrLock, *flags); -+ } -+ -+ /* Re-read the FPtr, since we've dropped the IntrLock */ -+ Fptr = dev->Event_Int_Queue_FPtr; -+ -+ /* Store the new FPtr to the elan, this also clears the interrupt. */ -+ write_reg32 (dev, Event_Int_Queue_FPtr, Fptr); /* PCI write */ -+ -+ mmiob(); -+ } -+ -+ mb(); -+ Bptr = read_reg32 (dev, Event_Int_Queue_BPtr); /* PCI read */ -+ } -+ -+ return (ESUCCESS); -+} -+ -+int -+SetLinkBoundaryScan (ELAN3_DEV *dev) -+{ -+ int res = ESUCCESS; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ if ((dev->SchCntReg & LinkBoundaryScan) != 0) -+ res = EAGAIN; -+ else -+ { -+ PRINTF0 (DBG_DEVICE, DBG_BSCAN, "SetLinkBoundaryScan: setting link into boundary scan mode\n"); -+ -+ /* -+ * We're going to set the link into boundary scan mode, so firstly -+ * set the inputters to discard everything. -+ */ -+ if (dev->DiscardAllCount++ == 0) -+ SetSchedStatusRegister (dev, read_reg32 (dev, Exts.InterruptReg), NULL); -+ -+ /* -+ * Now disable the error interrupts -+ */ -+ DISABLE_INT_MASK (dev, INT_ErrorInterrupts); -+ -+ /* -+ * And set the link into boundary scan mode, and drive -+ * a reset token onto the link. -+ */ -+ SET_SCHED_LINK_VALUE (dev, 1, LinkResetToken); -+ } -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+void -+ClearLinkBoundaryScan (ELAN3_DEV *dev) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ if ((dev->SchCntReg & LinkBoundaryScan) != 0) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_BSCAN, "ClearLinkBoundaryScan: taking link out of boundary scan mode\n"); -+ -+ /* -+ * Take the link out of boundary scan -+ */ -+ SET_SCHED_LINK_VALUE (dev, 0, 0); -+ -+ /* -+ * Clear any link errors. -+ */ -+ PULSE_SCHED_STATUS (dev, ClearLinkErrorInt); -+ -+ /* -+ * Re-enable the error interrupts. -+ */ -+ if (! timer_fn_queued(&dev->ErrorTimeoutId)) -+ ENABLE_INT_MASK (dev, INT_ErrorInterrupts); -+ -+ /* -+ * And stop the inputter from discarding all packets. -+ */ -+ if (--dev->DiscardAllCount == 0) -+ SetSchedStatusRegister (dev, 0, NULL); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+int -+WriteBoundaryScanValue (ELAN3_DEV *dev, int value) -+{ -+ int res = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ if ((dev->SchCntReg & LinkBoundaryScan) != 0) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_BSCAN, "WriteBoundaryScanValue: driving value 0x%x onto link\n", value); -+ SET_SCHED_LINK_VALUE (dev, 1, value); -+ -+ res = read_reg32 (dev, Exts.LinkState); -+ -+ PRINTF1 (DBG_DEVICE, DBG_BSCAN, "WriteBoundaryScanValue: return 0x%x\n", res); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+int -+ReadBoundaryScanValue(ELAN3_DEV *dev, int link) -+{ -+ int res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ if ((dev->SchCntReg & LinkBoundaryScan) == 0) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_BSCAN, "ReadBoundaryScanValue: set linkval 0x%x\n", link); -+ SET_SCHED_LINK_VALUE (dev, 0, link); -+ } -+ res = read_reg32 (dev, Exts.LinkState); -+ PRINTF1 (DBG_DEVICE, DBG_BSCAN, "ReadBoundaryScanValue: return 0x%x\n", res); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+static int -+ReadLinkVal (ELAN3_DEV *dev, int link) -+{ -+ if ((dev->SchCntReg & LinkBoundaryScan) == 0) -+ SET_SCHED_LINK_VALUE (dev, 0, link); -+ -+ return (read_reg32 (dev, Exts.LinkState)); -+} -+ -+static void -+HandleLinkError (ELAN3_DEV *dev) -+{ -+ E3_uint32 value = read_reg32 (dev, Exts.LinkErrorTypes); -+ -+ PRINTF1 (DBG_DEVICE, DBG_LINKERR, "HandleLinkError: LinkErrorTypes %08x - clearing\n", value); -+ -+ if (value & LS_LockError) BumpStat (dev, LockError); -+ if (value & LS_DeskewError) BumpStat (dev, DeskewError); -+ if (value & LS_PhaseError) BumpStat (dev, PhaseError); -+ if (value & LS_DataError) BumpStat (dev, DataError); -+ if (value & LS_FifoOvFlow0) BumpStat (dev, FifoOvFlow0); -+ if (value & LS_FifoOvFlow1) BumpStat (dev, FifoOvFlow1); -+ -+ if (value & LS_DataError) -+ dev->Stats.LinkErrorValue = ReadLinkVal (dev, 12) | (ReadLinkVal (dev, 13) << 9); -+ -+ PULSE_SCHED_STATUS (dev, ClearLinkErrorInt); -+ -+ CheckForExcessiveErrorRate (dev); -+} -+ -+static void -+HandleErrorInterrupt (ELAN3_DEV *dev, E3_uint32 Pend) -+{ -+ if (Pend & INT_PciMemErr) -+ HandlePciMemErr (dev); -+ -+ if (Pend & INT_SDRamInt) -+ HandleSDRamInterrupt (dev); -+ -+ if (Pend & INT_LinkError) -+ HandleLinkError (dev); -+} -+ -+static void -+HandleAnyIProcTraps (ELAN3_DEV *dev, E3_uint32 Pend) -+{ -+ E3_uint32 RestartBits = 0; -+ -+ if (Pend & INT_IProcCh0SysCntx) -+ { -+ HandleIProcTrap (dev, 0, Pend, -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcSysCntx), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh0_C0_TrHead[0]), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh0_C0_TrData[0])); -+ -+ RestartBits |= RestartCh0SysCntx; -+ } -+ -+ if (Pend & INT_IProcCh1SysCntx) -+ { -+ HandleIProcTrap (dev, 1, Pend, -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcSysCntx), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh1_C0_TrHead[0]), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh1_C0_TrData[0])); -+ -+ RestartBits |= RestartCh1SysCntx; -+ } -+ -+ if (Pend & INT_IProcCh0NonSysCntx) -+ { -+ HandleIProcTrap (dev, 0, Pend, -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcNonSysCntx), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh0_NonC0_TrHead[0]), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh0_NonC0_TrData[0])); -+ -+ RestartBits |= RestartCh0NonSysCntx; -+ } -+ -+ -+ if (Pend & INT_IProcCh1NonSysCntx) -+ { -+ HandleIProcTrap (dev, 1, Pend, -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, IProcNonSysCntx), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh1_NonC0_TrHead[0]), -+ dev->TAndQBase + offsetof (E3_TrapAndQueue, VCh1_NonC0_TrData[0])); -+ RestartBits |= RestartCh1NonSysCntx; -+ } -+ -+ PULSE_SCHED_STATUS (dev, RestartBits); -+} -+ -+static void -+elan3_event_interrupt (ELAN3_DEV *dev) -+{ -+ unsigned long flags; -+ -+ kernel_thread_init("elan3_event_int"); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ for (;;) -+ { -+ /* Make sure we never sleep with the EventInterrupt disabled */ -+ if (! (dev->InterruptMask & INT_EventInterrupt)) -+ { -+ if (HandleEventInterrupt (dev, eventint_resched_ticks, &flags) != ESUCCESS) -+ BumpStat (dev, EventRescheds); -+ -+ ENABLE_INT_MASK (dev, INT_EventInterrupt); -+ } -+ -+ if (dev->ThreadsShouldStop) -+ break; -+ -+ kcondvar_wait (&dev->IntrWait, &dev->IntrLock, &flags); -+ } -+ -+ dev->EventInterruptThreadStopped = 1; -+ kcondvar_wakeupall (&dev->IntrWait, &dev->IntrLock); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ kernel_thread_exit (); -+} -+ -+int -+InterruptHandler (ELAN3_DEV *dev) -+{ -+ E3_uint32 Mask; -+ E3_uint32 Pend; -+ E3_uint32 RestartBits; -+ int deliverDProcTrap; -+ int deliverTProcTrap; -+ static long lboltsave; -+ int loop_count = 0; -+ unsigned long flags; -+ int tproc_delivered; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ BumpStat (dev, Interrupts); -+ -+ Mask = dev->InterruptMask; -+ Pend = read_reg32 (dev, Exts.InterruptReg); /* PCI read */ -+ -+ /* Save the lbolt so we know how long in do loop or in event handling */ -+ lboltsave = lbolt; -+ -+ if ((Pend & Mask) == INT_EventInterrupt) -+ { -+ DISABLE_INT_MASK (dev, INT_EventInterrupt); -+ -+ if (HandleEventInterrupt (dev, eventint_punt_ticks, &flags) == ESUCCESS) -+ ENABLE_INT_MASK (dev, INT_EventInterrupt); -+ else -+ { -+ BumpStat (dev, EventPunts); -+ -+ kcondvar_wakeupone (&dev->IntrWait, &dev->IntrLock); -+ } -+ -+ if ((lbolt - lboltsave) > dev->Stats.LongestInterrupt) -+ dev->Stats.LongestInterrupt = (lbolt - lboltsave); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return (ESUCCESS); -+ } -+ -+ if ((Pend & Mask) == 0) -+ { -+ PRINTF3 (DBG_DEVICE, DBG_INTR, "InterruptHandler: Spurious Pend %x Mask %x SchedStatus %x\n", -+ Pend, Mask, read_reg32 (dev, Exts.SchCntReg)); -+ -+ if ((lbolt - lboltsave) > dev->Stats.LongestInterrupt) -+ dev->Stats.LongestInterrupt = (lbolt - lboltsave); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ return (EFAIL); -+ } -+ -+ PRINTF3 (DBG_DEVICE, DBG_INTR, "InterruptHandler: Pend %x Mask %08x SchedStatus %x\n", -+ Pend, Mask, read_reg32 (dev, Exts.SchCntReg)); -+ -+ do { -+ loop_count++; -+ RestartBits = 0; -+ -+ if (Pend & Mask & (INT_CProc | INT_ComQueue)) -+ HandleCProcTrap (dev, Pend, &Mask); -+ -+ tproc_delivered = 0; -+ -+ if (Pend & Mask & INT_TProc) { -+ ELAN_REG_REC(Pend); -+ tproc_delivered = 1; -+ deliverTProcTrap = HandleTProcTrap (dev, &RestartBits); -+ } -+ else -+ deliverTProcTrap = 0; -+ -+ if (Pend & Mask & INT_DProc) -+ deliverDProcTrap = HandleDProcTrap (dev, &RestartBits); -+ else -+ deliverDProcTrap = 0; -+ -+ ASSERT ((RestartBits & RestartDProc) == 0 || (read_reg32 (dev, Exts.DProcStatus.Status) >> 29) == 4); -+ ASSERT ((RestartBits & RestartDProc) == 0 || elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc.s.FSR.Status)) == 0); -+ ASSERT ((RestartBits & RestartDProc) == 0 || elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0.s.FSR.Status)) == 0); -+ ASSERT ((RestartBits & RestartDProc) == 0 || elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData1.s.FSR.Status)) == 0); -+ ASSERT ((RestartBits & RestartDProc) == 0 || elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData2.s.FSR.Status)) == 0); -+ ASSERT ((RestartBits & RestartDProc) == 0 || elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData3.s.FSR.Status)) == 0); -+ -+ PULSE_SCHED_STATUS (dev, RestartBits); /* Restart any processors which had trapped. */ -+ SET_INT_MASK (dev, Mask); /* And install the new interrupt mask */ -+ -+ if ((Pend & Mask & INT_TProc) && deliverTProcTrap) -+ DeliverTProcTrap (dev, dev->ThreadTrap, Pend); -+ -+ if ((Pend & Mask & INT_DProc) && deliverDProcTrap) -+ DeliverDProcTrap (dev, dev->DmaTrap, Pend); -+ -+ if (Pend & Mask & INT_Inputters) -+ HandleAnyIProcTraps (dev, Pend); -+ -+ if (Pend & Mask & INT_EventInterrupt) -+ { -+ DISABLE_INT_MASK (dev, INT_EventInterrupt); -+ -+ if (loop_count == 1 && HandleEventInterrupt (dev, eventint_punt_ticks, &flags) == ESUCCESS) /* always punt to the thread if we've */ -+ ENABLE_INT_MASK (dev, INT_EventInterrupt); /* been round the loop once */ -+ else -+ { -+ BumpStat (dev, EventPunts); -+ -+ kcondvar_wakeupone (&dev->IntrWait, &dev->IntrLock); -+ } -+ } -+ -+ if (Pend & (INT_Halted | INT_Discarding)) -+ ProcessHaltOperations (dev, Pend); -+ -+ if (Pend & Mask & INT_ErrorInterrupts) -+ HandleErrorInterrupt (dev, Pend); -+ -+ Mask = dev->InterruptMask; -+ Pend = read_reg32 (dev, Exts.InterruptReg); /* PCI read */ -+ -+ if (tproc_delivered) -+ ELAN_REG_REC(Pend); -+ -+ PRINTF3 (DBG_DEVICE, DBG_INTR, "InterruptHandler: Pend %x Mask %08x SchedStatus %x\n", -+ Pend, Mask, read_reg32 (dev, Exts.SchCntReg)); -+ } while ((Pend & Mask) != 0); -+ -+ if ((lbolt - lboltsave) > dev->Stats.LongestInterrupt) -+ dev->Stats.LongestInterrupt = (lbolt - lboltsave); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "InterruptHandler: lbolt is %lx; start lbolt is %lx\n", -+ lbolt, lboltsave); -+ -+ return (ESUCCESS); -+} -+ -+void -+SetSchedStatusRegister (ELAN3_DEV *dev, E3_uint32 Pend, volatile E3_uint32 *Maskp) -+{ -+ E3_uint32 HaltMask = dev->HaltOperationsMask; -+ E3_uint32 Mask = Maskp ? *Maskp : dev->InterruptMask; -+ E3_uint32 ClearBits = 0; -+ E3_uint32 SetBits = 0; -+ -+ PRINTF5 (DBG_DEVICE, DBG_INTR, "SetSchedStatusRegister: HaltOperationsMask=%x HaltAll=%d HaltDmaDequeue=%d HaltThread=%d DiscardAll=%d\n", -+ HaltMask, dev->HaltAllCount, dev->HaltDmaDequeueCount, dev->HaltThreadCount, dev->DiscardAllCount); -+ -+ if (dev->FlushCommandCount) -+ SetBits |= FlushCommandQueues; -+ -+ if ((HaltMask & INT_DProcHalted) || dev->HaltAllCount) -+ { -+ SetBits |= HaltDmas | HaltDmaDequeue; -+ if (Pend & INT_DProcHalted) -+ Mask &= ~INT_DProcHalted; -+ else -+ Mask |= INT_DProcHalted; -+ } -+ -+ if (dev->HaltDmaDequeueCount) -+ { -+ SetBits |= HaltDmaDequeue; -+ if (Pend & INT_DProcHalted) -+ Mask &= ~INT_DProcHalted; -+ else -+ Mask |= INT_DProcHalted; -+ } -+ -+ if ((HaltMask & INT_TProcHalted) || dev->HaltAllCount || dev->HaltThreadCount) -+ { -+ SetBits |= HaltThread; -+ if (Pend & INT_TProcHalted) -+ Mask &= ~INT_TProcHalted; -+ else -+ Mask |= INT_TProcHalted; -+ } -+ -+ if ((HaltMask & INT_DiscardingSysCntx) || dev->DiscardAllCount) -+ { -+ SetBits |= DiscardSysCntxIn; -+ if (Pend & INT_DiscardingSysCntx) -+ Mask &= ~INT_DiscardingSysCntx; -+ else -+ Mask |= INT_DiscardingSysCntx; -+ } -+ -+ if ((HaltMask & INT_DiscardingNonSysCntx) || dev->DiscardNonContext0Count || dev->DiscardAllCount) -+ { -+ SetBits |= DiscardNonSysCntxIn; -+ if (Pend & INT_DiscardingNonSysCntx) -+ Mask &= ~INT_DiscardingNonSysCntx; -+ else -+ Mask |= INT_DiscardingNonSysCntx; -+ } -+ -+ if (dev->HaltNonContext0Count) -+ SetBits |= StopNonSysCntxs; -+ -+ ClearBits = SetBits ^ (FlushCommandQueues | HaltDmas | HaltDmaDequeue | HaltThread | -+ DiscardSysCntxIn | DiscardNonSysCntxIn | StopNonSysCntxs); -+ -+ PRINTF4 (DBG_DEVICE, DBG_INTR, "SetSchedStatusRegister: SetBits=%x InterruptMask=%x InterruptReg=%x Mask=%x\n", -+ SetBits, dev->InterruptMask, read_reg32 (dev, Exts.InterruptReg), Mask); -+ -+ MODIFY_SCHED_STATUS (dev, SetBits, ClearBits); -+ -+ if (Maskp) -+ *Maskp = Mask; /* copyback new interrupt mask */ -+ else -+ SET_INT_MASK(dev, Mask); -+} -+ -+void -+FreeHaltOperation (ELAN3_DEV *dev, ELAN3_HALTOP *op) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->FreeHaltLock, flags); -+ op->Next = dev->FreeHaltOperations; -+ dev->FreeHaltOperations = op; -+ spin_unlock_irqrestore (&dev->FreeHaltLock, flags); -+} -+ -+int -+ReserveHaltOperations (ELAN3_DEV *dev, int count, int cansleep) -+{ -+ ELAN3_HALTOP *op; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->FreeHaltLock, flags); -+ while ((dev->NumHaltOperations - dev->ReservedHaltOperations) < count) -+ { -+ spin_unlock_irqrestore (&dev->FreeHaltLock, flags); -+ -+ KMEM_ZALLOC (op, ELAN3_HALTOP *, sizeof (ELAN3_HALTOP), cansleep); -+ -+ if (op == NULL) -+ return (FALSE); -+ -+ spin_lock_irqsave (&dev->FreeHaltLock, flags); -+ -+ dev->NumHaltOperations++; -+ -+ op->Next = dev->FreeHaltOperations; -+ dev->FreeHaltOperations = op; -+ } -+ -+ dev->ReservedHaltOperations += count; -+ -+ spin_unlock_irqrestore (&dev->FreeHaltLock, flags); -+ -+ return (TRUE); -+} -+ -+void -+ReleaseHaltOperations (ELAN3_DEV *dev, int count) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->FreeHaltLock, flags); -+ dev->ReservedHaltOperations -= count; -+ spin_unlock_irqrestore (&dev->FreeHaltLock, flags); -+} -+ -+void -+QueueHaltOperation (ELAN3_DEV *dev, E3_uint32 Pend, volatile E3_uint32 *Maskp, -+ E3_uint32 ReqMask, void (*Function)(ELAN3_DEV *, void *), void *Arguement) -+{ -+ ELAN3_HALTOP *op; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ spin_lock (&dev->FreeHaltLock); -+ op = dev->FreeHaltOperations; -+ -+ ASSERT (op != NULL); -+ -+ dev->FreeHaltOperations = op->Next; -+ spin_unlock (&dev->FreeHaltLock); -+ -+ op->Mask = ReqMask; -+ op->Function = (void (*)(void *, void *))Function; -+ op->Arguement = Arguement; -+ -+ dev->HaltOperationsMask |= ReqMask; /* Add our bits to the global bits needed. */ -+ SetSchedStatusRegister (dev, Pend, Maskp); /* Set the control register and the interrupt mask */ -+ -+ /* -+ * If the condition is already satisfied, then SetSchedStatusRegister will -+ * have masked out the interrupt, so re-enable it now to take it straight -+ * away -+ */ -+ if (Maskp == NULL) -+ { -+ if ((read_reg32 (dev, Exts.InterruptReg) & ReqMask) == ReqMask) -+ ENABLE_INT_MASK (dev, ReqMask); -+ } -+ else -+ { -+ if ((Pend & ReqMask) == ReqMask) -+ *Maskp |= ReqMask; -+ } -+ -+ *dev->HaltOperationsTailpp = op; /* Queue at end of list, since ProcessHaltOperations */ -+ dev->HaltOperationsTailpp = &op->Next; /* drops the IntrLock while running down the list */ -+ op->Next = NULL; -+} -+ -+void -+ProcessHaltOperations (ELAN3_DEV *dev, E3_uint32 Pend) -+{ -+ E3_uint32 Mask; -+ ELAN3_HALTOP *op; -+ ELAN3_HALTOP **prevp; -+ E3_uint32 haltMask; -+ ELAN3_HALTOP *next; -+ -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "ProcessHaltOperations: Pend %x\n", Pend); -+ -+ for (;;) -+ { -+ ELAN3_HALTOP *head = NULL; -+ ELAN3_HALTOP **tailp = &head; -+ -+ /* -+ * Generate a list of halt operations which can be called now. -+ */ -+ for (haltMask = 0, prevp = &dev->HaltOperations; (op = *prevp) != NULL; ) -+ { -+ if ((Pend & op->Mask) != op->Mask) -+ { -+ haltMask |= op->Mask; -+ prevp = &op->Next; -+ } -+ else -+ { -+ *prevp = op->Next; /* remove from list */ -+ if (op->Next == NULL) -+ dev->HaltOperationsTailpp = prevp; -+ -+ *tailp = op; /* add to local list */ -+ op->Next = NULL; -+ tailp = &op->Next; -+ } -+ } -+ -+ if (head == NULL) /* nothing to do, so update */ -+ { /* the schedule status register */ -+ dev->HaltOperationsMask = haltMask; /* and the interrupt mask */ -+ SetSchedStatusRegister (dev, Pend, NULL); -+ return; -+ } -+ -+ /* -+ * flush the command queues, before calling any operations -+ */ -+ Mask = dev->InterruptMask; -+ -+ if (dev->FlushCommandCount++ == 0) -+ SetSchedStatusRegister (dev, Pend, &Mask); -+ -+ if ((read_reg32 (dev, ComQueueStatus) & ComQueueNotEmpty) != 0) -+ { -+ if (dev->HaltThreadCount++ == 0) -+ SetSchedStatusRegister (dev, Pend, &Mask); -+ -+ CAPTURE_CPUS(); -+ -+ while ((read_reg32 (dev, ComQueueStatus) & ComQueueNotEmpty) != 0) -+ mb(); -+ -+ RELEASE_CPUS(); -+ -+ if (--dev->HaltThreadCount == 0) -+ SetSchedStatusRegister (dev, Pend, &Mask); -+ } -+ -+ if (read_reg32 (dev, Exts.InterruptReg) & INT_CProc) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "ProcessHaltOperations: command processor has trapped\n"); -+ HandleCProcTrap (dev, Pend, &Mask); -+ } -+ -+ if (--dev->FlushCommandCount == 0) -+ SetSchedStatusRegister (dev, Pend, &Mask); -+ -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "ProcessHaltOperations: interrupt mask %08x -> %08x\n", -+ dev->InterruptMask, Mask); -+ -+ SET_INT_MASK (dev, Mask); -+ spin_unlock (&dev->IntrLock); -+ -+ /* -+ * now process the list of operations -+ * we have -+ */ -+ for (op = head; op != NULL; op = next) -+ { -+ next = op->Next; -+ -+ op->Function (dev, op->Arguement); -+ -+ FreeHaltOperation (dev, op); -+ } -+ -+ spin_lock (&dev->IntrLock); -+ } -+} -+ -+int -+ComputePosition (ELAN_POSITION *pos, unsigned nodeId, unsigned numNodes, unsigned numDownLinksVal) -+{ -+ int i, lvl, n; -+ char numDownLinks[ELAN_MAX_LEVELS]; -+ -+ if (nodeId >= numNodes) -+ return (EINVAL); -+ -+ for (i = 0; i < ELAN_MAX_LEVELS; i++, numDownLinksVal >>= 4) -+ numDownLinks[i] = numDownLinksVal & 7; -+ -+ for (lvl = 0, n = numNodes; n > ((lvl % 3) == 2 ? 8 : 4) && lvl < ELAN_MAX_LEVELS; lvl++) -+ { -+ if (numDownLinks[lvl] == 0) -+ numDownLinks[lvl] = 4; -+ -+ if ((n % numDownLinks[lvl]) != 0) -+ return (EINVAL); -+ -+ n /= numDownLinks[lvl]; -+ } -+ -+ if (numDownLinks[lvl] == 0) -+ numDownLinks[lvl] = n; -+ -+ if (numDownLinks[lvl] != n) -+ return (EINVAL); -+ -+ for (i = 0; i <= lvl; i++) -+ pos->pos_arity[i] = numDownLinks[lvl - i]; -+ -+ pos->pos_nodes = numNodes; -+ pos->pos_levels = lvl + 1; -+ pos->pos_nodeid = nodeId; -+ pos->pos_mode = ELAN_POS_MODE_SWITCHED; -+ -+ return (0); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elandev_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elandev_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elandev_linux.c 2005-06-01 23:12:54.582441688 -0400 -@@ -0,0 +1,2302 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: elandev_linux.c,v 1.102.2.4 2004/12/20 16:55:17 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/elandev_linux.c,v $*/ -+ -+#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 -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) -+#error please use a 2.2 series kernel or newer -+#endif -+ -+/* Minor numbers encoded as : -+ * [5:0] device number -+ * [15:6] function number -+ */ -+#define ELAN3_DEVICE_MASK 0x3F -+ -+#define ELAN3_MINOR_CONTROL 0 -+#define ELAN3_MINOR_MEM 1 -+#define ELAN3_MINOR_USER 2 -+#define ELAN3_MINOR_SHIFT 6 -+ -+#define ELAN3_DEVICE(inode) (MINOR(inode->i_rdev) & ELAN3_DEVICE_MASK) -+#define ELAN3_MINOR(inode) (MINOR(inode->i_rdev) >> ELAN3_MINOR_SHIFT) -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -+# define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags) -+# define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) -+typedef void irqreturn_t; -+#endif -+# define IRQ_NONE -+# define IRQ_HANDLED -+# define IRQ_RETVAL(x) -+#endif -+ -+ -+/* -+ * Function prototypes. -+ */ -+static int elanattach(int instance, struct pci_dev *pcidev); -+static int elandetach(int instance); -+ -+static int elan3_open (struct inode *inode, struct file *file); -+static int elan3_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg); -+static int elan3_mmap (struct file *file, struct vm_area_struct *vm_area); -+static int elan3_release (struct inode *inode, struct file *file); -+ -+static int elan3_reboot_event (struct notifier_block *self, unsigned long event, void *buffer); -+static int elan3_panic_event (struct notifier_block *self, unsigned long event, void *buffer); -+ -+static irqreturn_t InterruptHandlerWrapper(int irq, void *dev_id, struct pt_regs *regs); -+ -+static int ConfigurePci(ELAN3_DEV *dev); -+static int ResetElan(ELAN3_DEV *dev, ioaddr_t intPalAddr); -+ -+static void elan3_shutdown_devices(int panicing); -+ -+/* -+ * Globals. -+ */ -+static ELAN3_DEV *elan3_devices[ELAN3_MAX_CONTROLLER]; -+static int NodeId = ELAN3_INVALID_NODE; -+static int NumNodes; -+static int DownLinks; -+static int RandomRoutingDisabled; -+int BackToBackMaster; -+int BackToBackSlave; -+int enable_sdram_writecombining; -+int sdram_bank_limit; -+extern int LwpNice; -+ -+char * elan_reg_rec_file [ELAN_REG_REC_MAX]; -+int elan_reg_rec_line [ELAN_REG_REC_MAX]; -+long elan_reg_rec_lbolt[ELAN_REG_REC_MAX]; -+int elan_reg_rec_cpu [ELAN_REG_REC_MAX]; -+E3_uint32 elan_reg_rec_reg [ELAN_REG_REC_MAX]; -+int elan_reg_rec_index; -+ -+MODULE_AUTHOR("Quadrics Ltd."); -+MODULE_DESCRIPTION("Elan3 Device Driver"); -+ -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(NodeId,"i"); -+MODULE_PARM(NumNodes,"i"); -+MODULE_PARM(RandomRoutingDisabled,"i"); -+MODULE_PARM(DownLinks,"i"); -+MODULE_PARM(BackToBackMaster,"i"); -+MODULE_PARM(BackToBackSlave,"i"); -+MODULE_PARM(LwpNice, "i"); -+MODULE_PARM(elan3_debug, "i"); -+MODULE_PARM(elan3_debug_console, "i"); -+MODULE_PARM(elan3_debug_buffer, "i"); -+MODULE_PARM(elan3mmu_debug, "i"); -+MODULE_PARM(sdram_bank_limit, "i"); -+ -+/* elan3/os/context.c */ -+EXPORT_SYMBOL(elan3_alloc); -+EXPORT_SYMBOL(elan3_attach); -+EXPORT_SYMBOL(elan3_doattach); -+EXPORT_SYMBOL(elan3_free); -+EXPORT_SYMBOL(elan3_detach); -+EXPORT_SYMBOL(elan3_dodetach); -+EXPORT_SYMBOL(elan3_block_inputter); -+EXPORT_SYMBOL(CheckCommandQueueFlushed); -+ -+/* elan3/os/sdram.c */ -+EXPORT_SYMBOL(elan3_sdram_alloc); -+EXPORT_SYMBOL(elan3_sdram_free); -+EXPORT_SYMBOL(elan3_sdram_to_phys); -+EXPORT_SYMBOL(elan3_sdram_writeb); -+EXPORT_SYMBOL(elan3_sdram_writew); -+EXPORT_SYMBOL(elan3_sdram_writel); -+EXPORT_SYMBOL(elan3_sdram_writeq); -+EXPORT_SYMBOL(elan3_sdram_readb); -+EXPORT_SYMBOL(elan3_sdram_readw); -+EXPORT_SYMBOL(elan3_sdram_readl); -+EXPORT_SYMBOL(elan3_sdram_readq); -+EXPORT_SYMBOL(elan3_sdram_zerob_sdram); -+EXPORT_SYMBOL(elan3_sdram_zerow_sdram); -+EXPORT_SYMBOL(elan3_sdram_zerol_sdram); -+EXPORT_SYMBOL(elan3_sdram_zeroq_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyb_to_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyw_to_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyl_to_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyq_to_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyb_from_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyw_from_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyl_from_sdram); -+EXPORT_SYMBOL(elan3_sdram_copyq_from_sdram); -+ -+/* elan3/os/tproc.c */ -+EXPORT_SYMBOL(DeliverTProcTrap); -+EXPORT_SYMBOL(HandleTProcTrap); -+EXPORT_SYMBOL(SaveThreadToStack); -+ -+/* elan3/os/tprocinsts.c */ -+EXPORT_SYMBOL(RollThreadToClose); -+ -+/* elan3/os/iproc.c */ -+EXPORT_SYMBOL(InspectIProcTrap); -+EXPORT_SYMBOL(IProcTrapString); -+EXPORT_SYMBOL(SimulateUnlockQueue); -+ -+/* elan3/os/cproc.c */ -+EXPORT_SYMBOL(HandleCProcTrap); -+ -+/* elan3/os/route_table.c */ -+EXPORT_SYMBOL(GenerateRoute); -+EXPORT_SYMBOL(LoadRoute); -+EXPORT_SYMBOL(InvalidateRoute); -+EXPORT_SYMBOL(ValidateRoute); -+EXPORT_SYMBOL(ClearRoute); -+EXPORT_SYMBOL(GenerateProbeRoute); -+EXPORT_SYMBOL(GenerateCheckRoute); -+ -+/* elan3/os/elandev_generic.c */ -+EXPORT_SYMBOL(elan3_debug); -+EXPORT_SYMBOL(QueueHaltOperation); -+EXPORT_SYMBOL(ReleaseHaltOperations); -+EXPORT_SYMBOL(ReserveHaltOperations); -+ -+/* elan3/vm/elan3mmu_generic.c */ -+EXPORT_SYMBOL(elan3mmu_pteload); -+EXPORT_SYMBOL(elan3mmu_unload); -+EXPORT_SYMBOL(elan3mmu_set_context_filter); -+EXPORT_SYMBOL(elan3mmu_reserve); -+EXPORT_SYMBOL(elan3mmu_attach); -+EXPORT_SYMBOL(elan3mmu_detach); -+EXPORT_SYMBOL(elan3mmu_release); -+/* elan3/vm/elan3mmu_linux.c */ -+EXPORT_SYMBOL(elan3mmu_phys_to_pte); -+EXPORT_SYMBOL(elan3mmu_kernel_invalid_pte); -+ -+/* elan3/os/elan3_debug.c */ -+EXPORT_SYMBOL(elan3_debugf); -+ -+/* elan3/os/minames.c */ -+EXPORT_SYMBOL(MiToName); -+ -+/* elan3/os/elandev_generic.c */ -+EXPORT_SYMBOL(MapDeviceRegister); -+EXPORT_SYMBOL(UnmapDeviceRegister); -+ -+EXPORT_SYMBOL(elan_reg_rec_lbolt); -+EXPORT_SYMBOL(elan_reg_rec_file); -+EXPORT_SYMBOL(elan_reg_rec_index); -+EXPORT_SYMBOL(elan_reg_rec_cpu); -+EXPORT_SYMBOL(elan_reg_rec_reg); -+EXPORT_SYMBOL(elan_reg_rec_line); -+ -+/* -+ * Standard device entry points. -+ */ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ -+#include -+ -+static int elan3_dump_event (struct notifier_block *self, unsigned long event, void *buffer); -+ -+static struct notifier_block elan3_dump_notifier = -+{ -+ notifier_call: elan3_dump_event, -+ priority: 0, -+}; -+ -+static int -+elan3_dump_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ if ( event == DUMP_BEGIN ) -+ elan3_shutdown_devices (FALSE); -+ -+ return (NOTIFY_DONE); -+} -+ -+#endif -+ -+static struct file_operations elan3_fops = { -+ ioctl: elan3_ioctl, /* ioctl */ -+ mmap: elan3_mmap, /* mmap */ -+ open: elan3_open, /* open */ -+ release: elan3_release, /* release */ -+}; -+ -+static struct notifier_block elan3_reboot_notifier = -+{ -+ notifier_call: elan3_reboot_event, -+ priority: 0, -+}; -+ -+static struct notifier_block elan3_panic_notifier = -+{ -+ notifier_call: elan3_panic_event, -+ priority: 0, -+}; -+ -+ELAN3_DEV * -+elan3_device (int instance) -+{ -+ if (instance < 0 || instance >= ELAN3_MAX_CONTROLLER) -+ return ((ELAN3_DEV *) NULL); -+ return elan3_devices[instance]; -+} -+EXPORT_SYMBOL(elan3_device); -+ -+/* -+ * Called at rmmod time. elandetach() for each card + general cleanup. -+ */ -+#ifdef MODULE -+static void __exit elan3_exit(void) -+{ -+ int i; -+ -+ printk("elan: preparing to remove module\n"); -+ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ unregister_dump_notifier (&elan3_dump_notifier); -+#endif -+ unregister_reboot_notifier (&elan3_reboot_notifier); -+ notifier_chain_unregister (&panic_notifier_list, &elan3_panic_notifier); -+ -+ /* call elandetach() for each device configured. */ -+ for (i = 0; i < ELAN3_MAX_CONTROLLER; i++) -+ if (elan3_devices[i] != NULL) -+ elandetach(i); -+ -+ FinaliseNetworkErrorResolver(); -+ elan3mmu_fini(); -+ -+ cookie_fini(); -+ unregister_chrdev(ELAN3_MAJOR, ELAN3_NAME); -+ -+ elan3_procfs_fini(); -+ -+ printk("elan: module removed\n"); -+} -+ -+/* -+ * Called at insmod time. First we perform general driver initialization, -+ * then call elanattach() for each card. -+ */ -+#ifdef MODULE -+static int __init elan3_init(void) -+#else -+__initfunc(int elan3_init(void)) -+#endif -+{ -+ int e; -+ int boards; -+ struct pci_dev *dev; -+ char revid; -+ -+ elan_reg_rec_index=0; -+ { -+ int i; -+ for(i=0;islot_name); -+ else -+ { -+ if (boards < ELAN3_MAX_CONTROLLER) -+ /* Count successfully attached devices */ -+ boards += ((elanattach(boards, dev) == 0) ? 1 : 0); -+ else -+ { -+ printk ("elan: max controllers = %d\n", ELAN3_MAX_CONTROLLER); -+ break; -+ } -+ } -+ } -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ register_dump_notifier (&elan3_dump_notifier); -+#endif -+ register_reboot_notifier (&elan3_reboot_notifier); -+ notifier_chain_register (&panic_notifier_list, &elan3_panic_notifier); -+ -+ return 0; -+} -+ -+/* Declare the module init and exit functions */ -+module_init(elan3_init); -+module_exit(elan3_exit); -+ -+#endif -+ -+static void -+elan3_shutdown_devices(int panicing) -+{ -+ ELAN3_DEV *dev; -+ unsigned long flags; -+ register int i; -+ -+ local_irq_save (flags); -+ for (i = 0; i < ELAN3_MAX_CONTROLLER; i++) -+ { -+ if ((dev = elan3_devices[i]) != NULL) -+ { -+ if (! panicing) spin_lock (&dev->IntrLock); -+ -+ printk(KERN_INFO "elan%d: forcing link into reset\n", dev->Instance); -+ -+ /* -+ * We're going to set the link into boundary scan mode, so firstly -+ * set the inputters to discard everything. -+ */ -+ if (dev->DiscardAllCount++ == 0) -+ SetSchedStatusRegister (dev, read_reg32 (dev, Exts.InterruptReg), NULL); -+ -+ dev->LinkShutdown = 1; -+ -+ /* -+ * Now disable the error interrupts -+ */ -+ DISABLE_INT_MASK (dev, INT_ErrorInterrupts); -+ -+ /* -+ * And set the link into boundary scan mode, and drive -+ * a reset token onto the link. -+ */ -+ SET_SCHED_LINK_VALUE (dev, 1, LinkResetToken); -+ -+ if (! panicing) spin_unlock (&dev->IntrLock); -+ } -+ } -+ local_irq_restore (flags); -+} -+ -+static int -+elan3_reboot_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ if (! (event == SYS_RESTART || event == SYS_HALT || event == SYS_POWER_OFF)) -+ return (NOTIFY_DONE); -+ -+ elan3_shutdown_devices (FALSE); -+ -+ return (NOTIFY_DONE); -+} -+ -+static int -+elan3_panic_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ elan3_shutdown_devices (TRUE); -+ -+ return (NOTIFY_DONE); -+} -+ -+#include -+/* -+ * Called by init_module() for each card discovered on PCI. -+ */ -+static int -+elanattach(int instance, struct pci_dev *pcidev) -+{ -+ ELAN3_DEV *dev; -+ int ramSize; -+ int level; -+ ioaddr_t sdramAddr, cmdPortAddr, intPalAddr; -+ DeviceMappingHandle handle; -+ -+ printk("elan%d: attach, irq=%d\n", instance, pcidev->irq); -+ -+ /* -+ * Allocate the ELAN3_DEV structure. -+ */ -+ KMEM_ZALLOC(dev, ELAN3_DEV *, sizeof(ELAN3_DEV), TRUE); -+ if (dev == NULL) { -+ printk ("elan%d: KMEM_ALLOC failed\n", instance); -+ return (-ENOMEM); -+ } -+ elan3_devices[instance] = dev; -+ dev->Osdep.pci = pcidev; -+ -+ dev->Instance = instance; -+ -+ /* Initialise the device information */ -+ pci_read_config_word (pcidev, PCI_VENDOR_ID, &dev->Devinfo.dev_vendor_id); -+ pci_read_config_word (pcidev, PCI_DEVICE_ID, &dev->Devinfo.dev_device_id); -+ pci_read_config_byte (pcidev, PCI_REVISION_ID, &dev->Devinfo.dev_revision_id); -+ -+ dev->Devinfo.dev_instance = instance; -+ dev->Devinfo.dev_rail = instance; -+ dev->Devinfo.dev_driver_version = 0; -+ dev->Devinfo.dev_num_down_links_value = DownLinks; -+ -+ dev->Position.pos_mode = ELAN_POS_UNKNOWN; -+ dev->Position.pos_random_disabled = RandomRoutingDisabled; -+ -+ /* -+ * Set up PCI config regs. -+ */ -+ if (ConfigurePci(dev) != ESUCCESS) -+ goto fail0; -+ -+ /* -+ * Determine the PFnums of the SDRAM and command port -+ */ -+ if (MapDeviceRegister(dev, ELAN3_BAR_SDRAM, &sdramAddr, 0, PAGESIZE, &handle) != ESUCCESS) -+ goto fail1; -+ -+ DeviceRegisterSize(dev, ELAN3_BAR_SDRAM, &ramSize); -+ -+ dev->SdramPhysMask = ~((physaddr_t) ramSize - 1); -+ dev->SdramPhysBase = kmem_to_phys((void *) sdramAddr); -+ -+ UnmapDeviceRegister (dev, &handle); -+ -+#if defined(LINUX_ALPHA) -+ /* -+ * consider a physical address to be on the same pci bus -+ * as us if it's physical address is "close" to our sdram -+ * physical address. -+ * this is almost certainly incorrect for large memory (> 2Gb) -+ * i386 machines - and is only correct for alpha for 32 bit -+ * base address registers. -+ * -+ * Modified this to match the Tru64 driver value; -+ * i.e. PciPhysMask = 0xfffffffffffc0000 -+ */ -+# define PCI_ADDR_MASK (0x7FFFFFFFl) -+ -+ dev->PciPhysMask = ~PCI_ADDR_MASK; -+ dev->PciPhysBase = dev->SdramPhysBase & dev->PciPhysMask; -+#endif -+ /* -+ * Now reset the elan chip. -+ */ -+ if (MapDeviceRegister(dev, ELAN3_BAR_REGISTERS, &dev->RegPtr, 0, 0, &dev->RegHandle) != ESUCCESS) -+ goto fail1; -+ -+ if (MapDeviceRegister(dev, ELAN3_BAR_EBUS, &intPalAddr, ELAN3_EBUS_INTPAL_OFFSET, PAGESIZE, -+ &handle) != ESUCCESS) -+ goto fail2; -+ -+ ResetElan(dev, intPalAddr); -+ -+ UnmapDeviceRegister (dev, &handle); -+ -+ /* -+ * Initialise the device mutex's which must be accessible from the -+ * interrupt handler. -+ */ -+ kcondvar_init (&dev->IntrWait); -+ spin_lock_init (&dev->IntrLock); -+ spin_lock_init (&dev->TlbLock); -+ spin_lock_init (&dev->CProcLock); -+ spin_lock_init (&dev->FreeHaltLock); -+ for(level=0; level<4; level++) -+ spin_lock_init (&dev->Level[level].PtblLock); -+ spin_lock_init (&dev->PtblGroupLock); -+ -+ /* -+ * Add the interrupt handler, -+ */ -+ if (request_irq(dev->Osdep.pci->irq, InterruptHandlerWrapper, -+ SA_SHIRQ, "elan3", dev) != 0) { -+ printk ("elan%d: request_irq failed\n", instance); -+ goto fail3; -+ } -+ -+ if (MapDeviceRegister(dev, ELAN3_BAR_COMMAND_PORT, &cmdPortAddr, 0, PAGESIZE, &handle) != ESUCCESS) -+ goto fail4; -+ -+ if (InitialiseElan(dev, cmdPortAddr) == EFAIL) { -+ printk ("elan%d: InitialiseElan failed\n", instance); -+ UnmapDeviceRegister (dev, &handle); -+ goto fail4; -+ } -+ UnmapDeviceRegister (dev, &handle); -+ -+ /* If our nodeid is defined, then set it now */ -+ if (NodeId != ELAN3_INVALID_NODE && ComputePosition (&dev->Position, NodeId, NumNodes, DownLinks) == 0) -+ { -+ if (RandomRoutingDisabled & ((1 << (dev->Position.pos_levels-1))-1)) -+ printk ("elan%d: NodeId=%d NodeLevel=%d NumNodes=%d (random routing disabled 0x%x)\n", -+ dev->Instance, dev->Position.pos_nodeid, dev->Position.pos_levels, dev->Position.pos_nodes, RandomRoutingDisabled); -+ else -+ printk ("elan%d: NodeId=%d NodeLevel=%d NumNodes=%d (random routing ok)\n", -+ dev->Instance, dev->Position.pos_nodeid, dev->Position.pos_levels, dev->Position.pos_nodes); -+ } -+ -+ if (BackToBackMaster || BackToBackSlave) -+ { -+ dev->Position.pos_mode = ELAN_POS_MODE_BACKTOBACK; -+ dev->Position.pos_nodeid = (BackToBackMaster == 0); -+ dev->Position.pos_nodes = 2; -+ dev->Position.pos_levels = 1; -+ dev->Position.pos_arity[0] = 2; -+ -+ printk ("elan%d: back-to-back %s - elan node %d\n", dev->Instance, -+ BackToBackMaster ? "master" : "slave", dev->Position.pos_nodeid); -+ } -+ -+ elan3_procfs_device_init (dev); -+ -+ /* Success */ -+ return (0); -+ -+fail4: -+ free_irq(dev->Osdep.pci->irq, dev); -+ -+fail3: -+ kcondvar_destroy (&dev->IntrWait); -+ spin_lock_destroy (&dev->IntrLock); -+ spin_lock_destroy (&dev->InfoLock); -+ spin_lock_destroy (&dev->TlbLock); -+ spin_lock_destroy (&dev->CProcLock); -+ spin_lock_destroy (&dev->FreeHaltLock); -+ spin_lock_destroy (&dev->Level1PtblLock); -+ spin_lock_destroy (&dev->Level2PtblLock); -+ spin_lock_destroy (&dev->Level3PtblLock); -+ spin_lock_destroy (&dev->PtblGroupLock); -+ -+fail2: -+ UnmapDeviceRegister (dev, &dev->RegHandle); -+ -+fail1: -+ pci_disable_device (dev->Osdep.pci); -+fail0: -+ KMEM_FREE(dev, sizeof(ELAN3_DEV)); -+ -+ elan3_devices[instance] = NULL; -+ -+ /* Failure */ -+ return (-ENODEV); -+} -+ -+/* -+ * Called by elan3_exit() for each board found on PCI. -+ */ -+static int -+elandetach(int instance) -+{ -+ ELAN3_DEV *dev = elan3_devices[instance]; -+ -+ printk("elan%d: detach\n", instance); -+ -+ elan3_procfs_device_fini (dev); -+ -+ FinaliseElan (dev); -+ -+ UnmapDeviceRegister (dev, &dev->RegHandle); -+ -+ free_irq(dev->Osdep.pci->irq, dev); -+ -+ pci_disable_device(dev->Osdep.pci); -+ -+ kcondvar_destroy (&dev->IntrWait); -+ spin_lock_destroy (&dev->IntrLock); -+ spin_lock_destroy (&dev->InfoLock); -+ spin_lock_destroy (&dev->TlbLock); -+ spin_lock_destroy (&dev->CProcLock); -+ spin_lock_destroy (&dev->FreeHaltLock); -+ spin_lock_destroy (&dev->Level1PtblLock); -+ spin_lock_destroy (&dev->Level2PtblLock); -+ spin_lock_destroy (&dev->Level3PtblLock); -+ spin_lock_destroy (&dev->PtblGroupLock); -+ -+ KMEM_FREE(dev, sizeof(ELAN3_DEV)); -+ elan3_devices[instance] = NULL; -+ -+ return 0; -+} -+ -+/* -+ * generic ioctls - available on control and user devices. -+ */ -+ -+static int -+device_stats_ioctl (ELAN3_DEV *dev, unsigned long arg) -+{ -+ ELAN3IO_STATS_STRUCT *args; -+ -+ KMEM_ALLOC(args, ELAN3IO_STATS_STRUCT *, sizeof(ELAN3IO_STATS_STRUCT), TRUE); -+ -+ if (args == NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (args, (void *) arg, sizeof (ELAN3IO_STATS_STRUCT))) -+ { -+ KMEM_FREE(args, sizeof(ELAN3IO_STATS_STRUCT)); -+ return (-EFAULT); -+ } -+ -+ switch (args->which) -+ { -+ case ELAN3_SYS_STATS_DEVICE: -+ if (copy_to_user (args->ptr, &dev->Stats, sizeof (ELAN3_STATS))) -+ { -+ KMEM_FREE(args, sizeof(ELAN3IO_STATS_STRUCT)); -+ return (-EFAULT); -+ } -+ KMEM_FREE(args, sizeof(ELAN3IO_STATS_STRUCT)); -+ return (0); -+ -+ case ELAN3_SYS_STATS_MMU: -+ if (copy_to_user (args->ptr, &elan3mmu_global_stats, sizeof (ELAN3MMU_GLOBAL_STATS))) -+ { -+ KMEM_FREE(args, sizeof(ELAN3IO_STATS_STRUCT)); -+ return (-EFAULT); -+ } -+ KMEM_FREE(args, sizeof(ELAN3IO_STATS_STRUCT)); -+ return (0); -+ -+ default: -+ KMEM_FREE(args, sizeof(ELAN3IO_STATS_STRUCT)); -+ return (-EINVAL); -+ } -+} -+ -+/* -+ * /dev/elan3/controlX - control device -+ * -+ */ -+ -+typedef struct control_private -+{ -+ u_int pr_boundary_scan; -+} CONTROL_PRIVATE; -+ -+static int -+control_open (struct inode *inode, struct file *file) -+{ -+ CONTROL_PRIVATE *pr; -+ -+ KMEM_ALLOC(pr, CONTROL_PRIVATE *, sizeof (CONTROL_PRIVATE), TRUE); -+ -+ if (pr == NULL) -+ return (-ENOMEM); -+ -+ pr->pr_boundary_scan = 0; -+ -+ file->private_data = (void *) pr; -+ -+ MOD_INC_USE_COUNT; -+ -+ return (0); -+} -+ -+static int -+control_release (struct inode *inode, struct file *file) -+{ -+ ELAN3_DEV *dev = elan3_devices[ELAN3_DEVICE(inode)]; -+ CONTROL_PRIVATE *pr = (CONTROL_PRIVATE *) file->private_data; -+ -+ if (pr->pr_boundary_scan) -+ ClearLinkBoundaryScan(dev); -+ -+ KMEM_FREE (pr, sizeof(CONTROL_PRIVATE)); -+ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static int -+control_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ ELAN3_DEV *dev = elan3_devices[ELAN3_DEVICE(inode)]; -+ CONTROL_PRIVATE *pr = (CONTROL_PRIVATE *) file->private_data; -+ int res; -+ -+ switch (cmd) -+ { -+ case ELAN3IO_SET_BOUNDARY_SCAN: -+ if (SetLinkBoundaryScan (dev) == 0) -+ pr->pr_boundary_scan = 1; -+ return (0); -+ -+ case ELAN3IO_CLEAR_BOUNDARY_SCAN: -+ if (pr->pr_boundary_scan == 0) -+ return (-EINVAL); -+ -+ pr->pr_boundary_scan = 0; -+ -+ ClearLinkBoundaryScan (dev); -+ return (0); -+ -+ case ELAN3IO_READ_LINKVAL: -+ { -+ E3_uint32 val; -+ -+ if (pr->pr_boundary_scan == 0) -+ return (-EINVAL); -+ -+ if (copy_from_user(&val, (E3_uint32 *)arg, sizeof(E3_uint32))) -+ return (-EFAULT); -+ -+ val = ReadBoundaryScanValue (dev, val); -+ -+ if (copy_to_user((E3_uint32 *)arg, &val, sizeof(E3_uint32))) -+ return (-EFAULT); -+ return (0); -+ } -+ -+ case ELAN3IO_WRITE_LINKVAL: -+ { -+ E3_uint32 val; -+ -+ if (pr->pr_boundary_scan == 0) -+ return (-EINVAL); -+ -+ if (copy_from_user(&val, (E3_uint32 *)arg, sizeof(E3_uint32))) -+ return (-EFAULT); -+ -+ val = WriteBoundaryScanValue (dev, val); -+ -+ if (copy_to_user((E3_uint32 *)arg, &val, sizeof(E3_uint32))) -+ return (-EFAULT); -+ -+ return (0); -+ } -+ -+ case ELAN3IO_SET_POSITION: -+ { -+ ELAN3IO_SET_POSITION_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_SET_POSITION_STRUCT))) -+ return (-EFAULT); -+ -+ if (ComputePosition (&dev->Position, args.nodeId, args.numNodes, dev->Devinfo.dev_num_down_links_value) != 0) -+ return (-EINVAL); -+ -+ return (0); -+ } -+ -+ case ELAN3IO_SET_DEBUG: -+ { -+ ELAN3IO_SET_DEBUG_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_SET_DEBUG_STRUCT))) -+ return (-EFAULT); -+ -+ if (! strcmp (args.what, "elan3_debug")) -+ elan3_debug = args.value; -+ else if (! strcmp (args.what, "elan3_debug_console")) -+ elan3_debug_console = args.value; -+ else if (! strcmp (args.what, "elan3_debug_buffer")) -+ elan3_debug_buffer = args.value; -+ else if (! strcmp (args.what, "elan3_debug_ignore_dev")) -+ elan3_debug_ignore_dev = args.value; -+ else if (! strcmp (args.what, "elan3_debug_ignore_ctxt")) -+ elan3_debug_ignore_ctxt = args.value; -+ else if (! strcmp (args.what, "elan3mmu_debug")) -+ elan3mmu_debug = args.value; -+ -+ return (0); -+ } -+ -+ case ELAN3IO_NETERR_SERVER: -+ { -+ ELAN3IO_NETERR_SERVER_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_NETERR_SERVER_STRUCT))) -+ return (-EFAULT); -+ -+ res = AddNeterrServerSyscall (args.elanid, args.addr, args.name, NULL); -+ return (set_errno (res)); -+ } -+ -+ case ELAN3IO_NETERR_FIXUP: -+ { -+ NETERR_MSG *msg; -+ -+ KMEM_ALLOC(msg, NETERR_MSG *, sizeof (NETERR_MSG), TRUE); -+ -+ if (msg == NULL) -+ return (set_errno (ENOMEM)); -+ -+ if (copy_from_user (msg, (void *) arg, sizeof (NETERR_MSG))) -+ res = EFAULT; -+ else -+ res = ExecuteNetworkErrorFixup (msg); -+ -+ KMEM_FREE (msg, sizeof (NETERR_MSG)); -+ return (set_errno (res)); -+ } -+ -+ case ELAN3IO_STATS: -+ return (device_stats_ioctl (dev, arg)); -+ -+ case ELAN3IO_GET_DEVINFO: -+ { -+ if (copy_to_user ((void *) arg, &dev->Devinfo, sizeof (ELAN_DEVINFO))) -+ return (-EFAULT); -+ return (0); -+ } -+ -+ case ELAN3IO_GET_POSITION: -+ { -+ if (copy_to_user ((void *) arg, &dev->Position, sizeof (ELAN_POSITION))) -+ return (-EFAULT); -+ return (0); -+ } -+ default: -+ return (-EINVAL); -+ } -+} -+ -+static int -+control_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ ELAN3_DEV *dev = elan3_devices[ELAN3_DEVICE(file->f_dentry->d_inode)]; -+ int space = OFF_TO_SPACE(vma->vm_pgoff << PAGE_SHIFT); -+ int off = OFF_TO_OFFSET(vma->vm_pgoff << PAGE_SHIFT); -+ int size; -+ ioaddr_t addr; -+ DeviceMappingHandle handle; -+ physaddr_t phys; -+ -+ if (space < ELAN3_BAR_SDRAM || space > ELAN3_BAR_EBUS) -+ return (-EINVAL); -+ -+ if (off < 0 || DeviceRegisterSize (dev, space, &size) != ESUCCESS || off > size) -+ return (-EINVAL); -+ -+ if (MapDeviceRegister(dev, space, &addr, off, PAGESIZE, &handle) != ESUCCESS) -+ return (-EINVAL); -+ -+ phys = kmem_to_phys((caddr_t) addr); -+ UnmapDeviceRegister(dev, &handle); -+ -+#ifdef NO_RMAP -+ if (remap_page_range(vma->vm_start, phys, vma->vm_end - vma->vm_start, vma->vm_page_prot)) -+#else -+ if (remap_page_range(vma, vma->vm_start, phys, vma->vm_end - vma->vm_start, vma->vm_page_prot)) -+#endif -+ return (-EAGAIN); -+ -+ return (0); -+} -+ -+/* -+ * /dev/elan3/sdramX - sdram access device -+ */ -+typedef struct mem_page -+{ -+ struct mem_page *pg_next; -+ sdramaddr_t pg_addr; -+ u_long pg_pgoff; -+ u_int pg_ref; -+} MEM_PAGE; -+ -+#define MEM_HASH_SIZE 32 -+#define MEM_HASH(pgoff) ((pgoff) & (MEM_HASH_SIZE-1)) -+ -+typedef struct mem_private -+{ -+ ELAN3_DEV *pr_dev; -+ MEM_PAGE *pr_pages[MEM_HASH_SIZE]; -+ spinlock_t pr_lock; -+} MEM_PRIVATE; -+ -+static void -+mem_freepage (MEM_PRIVATE *pr, MEM_PAGE *pg) -+{ -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_freepage: pr=%p pgoff=%lx pg=%p ref=%d\n", pr, pg->pg_pgoff, pg, pg->pg_ref); -+ -+ elan3_sdram_free (pr->pr_dev, pg->pg_addr, PAGE_SIZE); -+ KMEM_FREE (pg, sizeof(MEM_PAGE)); -+} -+ -+static MEM_PAGE * -+mem_getpage (MEM_PRIVATE *pr, u_long pgoff, virtaddr_t addr) -+{ -+ int hashval = MEM_HASH (pgoff); -+ MEM_PAGE *npg = NULL; -+ MEM_PAGE *pg; -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_getpage: pr=%p pgoff=%lx addr=%lx\n", pr, pgoff, addr); -+ -+ again: -+ spin_lock (&pr->pr_lock); -+ for (pg = pr->pr_pages[hashval]; pg; pg = pg->pg_next) -+ if (pg->pg_pgoff == pgoff) -+ break; -+ -+ if (pg != NULL) -+ { -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_getpage: pr=%p pgoff=%lx addr=%lx -> found %p addr=%lx\n", pr, pgoff, addr, pg, pg->pg_addr); -+ -+ pg->pg_ref++; -+ spin_unlock (&pr->pr_lock); -+ -+ if (npg != NULL) /* we'd raced and someone else had created */ -+ mem_freepage (pr, npg); /* this page - so free of our new one*/ -+ return (pg); -+ } -+ -+ if (npg != NULL) /* didn't find the page, so inset the */ -+ { /* new one we've just created */ -+ npg->pg_next = pr->pr_pages[hashval]; -+ pr->pr_pages[hashval] = npg; -+ -+ spin_unlock (&pr->pr_lock); -+ return (npg); -+ } -+ -+ spin_unlock (&pr->pr_lock); /* drop spinlock before creating a new page */ -+ -+ KMEM_ALLOC(npg, MEM_PAGE *, sizeof (MEM_PAGE), TRUE); -+ -+ if (npg == NULL) -+ return (NULL); -+ -+ if ((npg->pg_addr = elan3_sdram_alloc (pr->pr_dev, PAGE_SIZE)) == 0) -+ { -+ KMEM_FREE (npg, sizeof (MEM_PAGE)); -+ return (NULL); -+ } -+ -+ /* zero the page before returning it to the user */ -+ elan3_sdram_zeroq_sdram (pr->pr_dev, npg->pg_addr, PAGE_SIZE); -+ -+ npg->pg_pgoff = pgoff; -+ npg->pg_ref = 1; -+ -+ /* created a new page - so have to rescan before inserting it */ -+ goto again; -+} -+ -+static void -+mem_droppage (MEM_PRIVATE *pr, u_long pgoff, int dontfree) -+{ -+ MEM_PAGE **ppg; -+ MEM_PAGE *pg; -+ -+ spin_lock (&pr->pr_lock); -+ for (ppg = &pr->pr_pages[MEM_HASH(pgoff)]; *ppg; ppg = &(*ppg)->pg_next) -+ if ((*ppg)->pg_pgoff == pgoff) -+ break; -+ -+ pg = *ppg; -+ -+ ASSERT (*ppg != NULL); -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_droppage: pr=%p pgoff=%lx pg=%p ref=%d dontfree=%d\n", pr, pgoff, (*ppg), (*ppg)->pg_ref, dontfree); -+ -+ if (--pg->pg_ref == 0 && !dontfree) -+ { -+ *ppg = pg->pg_next; -+ -+ mem_freepage (pr, pg); -+ } -+ -+ spin_unlock (&pr->pr_lock); -+} -+ -+static int -+mem_open (struct inode *inode, struct file *file) -+{ -+ ELAN3_DEV *dev = elan3_devices[ELAN3_DEVICE(inode)]; -+ MEM_PRIVATE *pr; -+ register int i; -+ -+ KMEM_ALLOC(pr, MEM_PRIVATE *, sizeof (MEM_PRIVATE), TRUE); -+ -+ if (pr == NULL) -+ return (-ENOMEM); -+ -+ spin_lock_init (&pr->pr_lock); -+ pr->pr_dev = dev; -+ for (i = 0; i < MEM_HASH_SIZE; i++) -+ pr->pr_pages[i] = NULL; -+ -+ file->private_data = (void *) pr; -+ -+ MOD_INC_USE_COUNT; -+ return (0); -+} -+ -+static int -+mem_release (struct inode *node, struct file *file) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) file->private_data; -+ MEM_PAGE *pg, *next; -+ int i; -+ -+ /* free off any pages that we'd allocated */ -+ spin_lock (&pr->pr_lock); -+ for (i = 0; i < MEM_HASH_SIZE; i++) -+ { -+ for (pg = pr->pr_pages[i]; pg; pg = next) -+ { -+ next = pg->pg_next; -+ mem_freepage (pr, pg); -+ } -+ } -+ spin_unlock (&pr->pr_lock); -+ -+ KMEM_FREE (pr, sizeof (MEM_PRIVATE)); -+ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static int -+mem_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return (-EINVAL); -+} -+ -+static void mem_vma_open(struct vm_area_struct *vma) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) vma->vm_private_data; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_vma_open: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ preemptable_start { -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) { -+ mem_getpage (pr, pgoff, addr); -+ preemptable_check(); -+ } -+ } preemptable_end; -+} -+ -+static void mem_vma_close(struct vm_area_struct *vma) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) vma->vm_private_data; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_vma_close: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ /* NOTE: the call to close may not have the same vm_start/vm_end values as -+ * were passed into mmap()/open() - since if an partial unmap had occured -+ * then the vma could have been shrunk or even split. -+ * -+ * if a the vma is split then an vma_open() will be called for the top -+ * portion - thus causing the reference counts to become incorrect. -+ * -+ * We drop the reference to any pages we're notified about - so they get freed -+ * earlier than when the device is finally released. -+ */ -+ for (pgoff = vma->vm_pgoff, addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ mem_droppage (pr, pgoff, 0); -+} -+ -+static struct vm_operations_struct mem_vm_ops = { -+ open: mem_vma_open, -+ close: mem_vma_close, -+}; -+ -+static int -+mem_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) file->private_data; -+ MEM_PAGE *pg; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_mmap: vm_mm=%p start=%lx end=%lx pgoff=%lx prot=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_page_prot.pgprot , file); -+ -+ preemptable_start { -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ { -+ if ((pg = mem_getpage (pr, pgoff, addr)) == NULL) -+ goto failed; -+ -+#ifdef LINUX_SPARC -+ pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE); -+ pgprot_val(vma->vm_page_prot) |= _PAGE_IE; -+#elif defined(pgprot_noncached) -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+#endif -+ -+#if defined(__ia64__) -+ if (enable_sdram_writecombining) -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+#endif -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_mmap: addr %lx -> pg=%p addr=%lx phys=%lx flags=%lx prot=%lx\n", -+ addr, pg, pg->pg_addr, elan3_sdram_to_phys (pr->pr_dev, pg->pg_addr), vma->vm_flags, vma->vm_page_prot.pgprot); -+ -+#ifdef NO_RMAP -+ if (remap_page_range (addr, elan3_sdram_to_phys (pr->pr_dev, pg->pg_addr), PAGE_SIZE, vma->vm_page_prot)) -+#else -+ if (remap_page_range (vma, addr, elan3_sdram_to_phys (pr->pr_dev, pg->pg_addr), PAGE_SIZE, vma->vm_page_prot)) -+#endif -+ { -+ mem_droppage (pr, pgoff, 0); /* drop our reference to this page */ -+ goto failed; -+ } -+ -+ preemptable_check(); -+ } -+ } preemptable_end; -+ -+ /* Don't try to swap out Elan SDRAM pages.. */ -+ vma->vm_flags |= VM_RESERVED; -+ -+ /* -+ * Don't dump SDRAM pages to a core file -+ * (Pity I would really like to do this but it crashes in elf_core_dump() as -+ * it can only handle pages that are in the mem_map area (addy 11/01/2002)) -+ */ -+ vma->vm_flags |= VM_IO; -+ -+ vma->vm_ops = &mem_vm_ops; -+ vma->vm_file = file; -+ vma->vm_private_data = (void *) pr; -+ -+ return (0); -+ -+ failed: -+ PRINTF (DBG_DEVICE, DBG_SEG, "mem_mmap: failed\n"); -+ -+ /* free of any pages we've already allocated/referenced */ -+ while ((--pgoff) >= vma->vm_pgoff) -+ mem_droppage (pr, pgoff, 0); -+ -+ return (-ENOMEM); -+} -+ -+/* -+ * /dev/elan3/userX - control device -+ * -+ * "user_private" can be referenced from a number of places -+ * 1) the "file" structure. -+ * 2) the "mm" coproc ops -+ * 3) the "mmap" of the command port. -+ * -+ */ -+typedef struct user_private -+{ -+ spinlock_t pr_lock; -+ atomic_t pr_mappings; -+ atomic_t pr_ref; -+ ELAN3_CTXT *pr_ctxt; -+ struct mm_struct *pr_mm; -+ coproc_ops_t pr_coproc; -+} USER_PRIVATE; -+ -+static void -+user_free (USER_PRIVATE *pr) -+{ -+ /* Have to unreserve the FlagPage or else we leak memory like a sieve! */ -+ ClearPageReserved(pte_page(*find_pte_kernel((unsigned long) pr->pr_ctxt->FlagPage))); -+ -+ elan3_detach(pr->pr_ctxt); -+ elan3_free (pr->pr_ctxt); -+ -+ KMEM_FREE (pr, sizeof(USER_PRIVATE)); -+ -+ MOD_DEC_USE_COUNT; -+} -+ -+static void -+user_coproc_release (void *arg, struct mm_struct *mm) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF3 (pr->pr_ctxt, DBG_SEG, "user_coproc_release: ctxt=%p pr=%p ref=%d\n", -+ pr->pr_ctxt, pr, atomic_read (&pr->pr_ref)); -+ -+ elan3mmu_pte_ctxt_unload (pr->pr_ctxt->Elan3mmu); -+ -+ pr->pr_mm = NULL; -+ -+ if (atomic_dec_and_test (&pr->pr_ref)) -+ user_free (pr); -+} -+ -+static void -+user_coproc_sync_range (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF2 (pr->pr_ctxt, DBG_SEG, "user_coproc_sync_range: start=%lx end=%lx\n", start, end); -+ -+ ASSERT(start <= end); -+ -+ elan3mmu_pte_range_unload(pr->pr_ctxt->Elan3mmu, mm, (caddr_t) start, end-start); -+} -+ -+static void -+user_coproc_invalidate_range (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF2 (pr->pr_ctxt, DBG_SEG, "user_coproc_invalidate_range: start=%lx end=%lx\n", start, end); -+ -+ ASSERT(start <= end); -+ -+ elan3mmu_pte_range_unload(pr->pr_ctxt->Elan3mmu, mm, (caddr_t) start, end-start); -+} -+ -+static void -+user_coproc_update_range (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ ASSERT(start <= end && ((start & PAGEOFFSET) == 0) && ((end & PAGEOFFSET) == 0)); -+ -+ PRINTF2 (pr->pr_ctxt, DBG_SEG, "user_coproc_update_range: start=%lx end=%lx\n", start, end); -+ -+ elan3mmu_pte_range_update (pr->pr_ctxt->Elan3mmu, mm,(caddr_t) start, end-start); -+} -+ -+static void -+user_coproc_change_protection (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end, pgprot_t newprot) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF2 (pr->pr_ctxt, DBG_SEG, "user_coproc_change_protection: start=%lx end=%lx\n", start, end); -+ -+ ASSERT(start <= end); -+ -+ elan3mmu_pte_range_unload(pr->pr_ctxt->Elan3mmu, mm, (caddr_t) start, end-start); -+} -+ -+static void -+user_coproc_sync_page (void *arg, struct vm_area_struct *vma, unsigned long addr) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF1 (pr->pr_ctxt, DBG_SEG, "user_coproc_sync_page: addr=%lx\n", addr); -+ -+ elan3mmu_pte_range_unload(pr->pr_ctxt->Elan3mmu, vma->vm_mm, (caddr_t) (addr & PAGE_MASK), PAGE_SIZE); -+} -+ -+static void -+user_coproc_invalidate_page (void *arg, struct vm_area_struct *vma, unsigned long addr) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF1 (pr->pr_ctxt, DBG_SEG, "user_coproc_invalidate_page: addr=%lx\n", addr); -+ -+ elan3mmu_pte_range_unload(pr->pr_ctxt->Elan3mmu, vma->vm_mm, (caddr_t) (addr & PAGE_MASK), PAGE_SIZE); -+} -+ -+static void -+user_coproc_update_page (void *arg, struct vm_area_struct *vma, unsigned long addr) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF1 (pr->pr_ctxt, DBG_SEG, "user_coproc_update_page: addr=%lx\n", addr); -+ -+ elan3mmu_pte_range_update (pr->pr_ctxt->Elan3mmu,vma->vm_mm, (caddr_t) (addr & PAGE_MASK), PAGE_SIZE); -+} -+ -+int -+user_ptrack_handler (void *arg, int phase, struct task_struct *child) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ ELAN3_CTXT *ctxt = pr->pr_ctxt; -+ -+ PRINTF5 (pr->pr_ctxt, DBG_FN, "user_ptrack_handler: ctxt=%p pr=%p ref=%d phase %d mm->ref %d\n", -+ pr->pr_ctxt, pr, atomic_read (&pr->pr_ref), phase, atomic_read (¤t->mm->mm_count)); -+ -+ if (phase == PTRACK_PHASE_EXIT) -+ { -+ /* this will force the helper thread to exit */ -+ elan3_swapout (ctxt, CTXT_EXITING); -+ -+ if (atomic_dec_and_test (&pr->pr_ref)) -+ user_free (pr); -+ } -+ return PTRACK_FINISHED; -+} -+ -+static int -+user_open (struct inode *inode, struct file *file) -+{ -+ ELAN3_DEV *dev = elan3_devices[ELAN3_DEVICE(inode)]; -+ USER_PRIVATE *pr; -+ ELAN3_CTXT *ctxt; -+ -+ if (dev == NULL) -+ return (-ENXIO); -+ -+ KMEM_ALLOC(pr, USER_PRIVATE *, sizeof (USER_PRIVATE), TRUE); -+ -+ if (pr == NULL) -+ return (-ENOMEM); -+ -+ if ((ctxt = elan3_alloc (dev, 0)) == NULL) -+ { -+ KMEM_FREE (pr, sizeof (USER_PRIVATE)); -+ return (-ENOMEM); -+ } -+ -+ if (sys_init (ctxt) == NULL) -+ { -+ elan3_detach(ctxt); -+ elan3_free (ctxt); -+ KMEM_FREE (pr, sizeof (USER_PRIVATE)); -+ return (-ENOMEM); -+ } -+ -+ /* initialise refcnt to 3 - one for "file", one for XA handler, one for the coproc ops */ -+ atomic_set (&pr->pr_ref, 3); -+ -+ atomic_set (&pr->pr_mappings, 0); -+ spin_lock_init (&pr->pr_lock); -+ -+ pr->pr_ctxt = ctxt; -+ pr->pr_mm = current->mm; -+ -+ /* register an ptrack handler to force the helper thread to exit when we do */ -+ if (ptrack_register (user_ptrack_handler, pr) < 0) -+ { -+ elan3_detach(ctxt); -+ elan3_free (ctxt); -+ KMEM_FREE (pr, sizeof (USER_PRIVATE)); -+ return (-ENOMEM); -+ } -+ -+ /* register a coproc callback to notify us of translation changes */ -+ -+ pr->pr_coproc.arg = (void *) pr; -+ pr->pr_coproc.release = user_coproc_release; -+ pr->pr_coproc.sync_range = user_coproc_sync_range; -+ pr->pr_coproc.invalidate_range = user_coproc_invalidate_range; -+ pr->pr_coproc.update_range = user_coproc_update_range; -+ pr->pr_coproc.change_protection = user_coproc_change_protection; -+ pr->pr_coproc.sync_page = user_coproc_sync_page; -+ pr->pr_coproc.invalidate_page = user_coproc_invalidate_page; -+ pr->pr_coproc.update_page = user_coproc_update_page; -+ -+ spin_lock (¤t->mm->page_table_lock); -+ register_coproc_ops (current->mm, &pr->pr_coproc); -+ spin_unlock (¤t->mm->page_table_lock); -+ -+ file->private_data = (void *) pr; -+ -+ PRINTF2 (pr->pr_ctxt, DBG_FN, "user_open: done ctxt=%p pr=%p\n", ctxt, pr); -+ -+ MOD_INC_USE_COUNT; -+ return (0); -+} -+ -+static int -+user_release (struct inode *inode, struct file *file) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ -+ PRINTF3 (pr->pr_ctxt, DBG_FN, "user_release: ctxt=%p pr=%p ref=%d\n", pr->pr_ctxt, pr, -+ atomic_read (&pr->pr_ref)); -+ -+ if (atomic_dec_and_test (&pr->pr_ref)) -+ user_free (pr); -+ -+ return (0); -+} -+ -+static int -+user_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ ELAN3_CTXT *ctxt = pr->pr_ctxt; -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ int res = 0; -+ -+ if (current->mm != pr->pr_mm) -+ return (-EINVAL); -+ -+ PRINTF4 (ctxt, DBG_FN, "user_ioctl: ctxt=%p cmd=%x(%d) arg=%lx\n", ctxt, cmd, _IOC_NR(cmd), arg); -+ -+ switch (cmd) -+ { -+ case ELAN3IO_FREE: -+ if (atomic_read (&pr->pr_mappings) > 0) -+ return (-EINVAL); -+ -+ spin_lock (¤t->mm->page_table_lock); -+ if (pr->pr_mm != current->mm) -+ spin_unlock (¤t->mm->page_table_lock); -+ else -+ { -+ unregister_coproc_ops (current->mm, &pr->pr_coproc); -+ spin_unlock (¤t->mm->page_table_lock); -+ -+ user_coproc_release (pr, current->mm); -+ } -+ -+ if (ptrack_registered (user_ptrack_handler, pr)) -+ { -+ ptrack_deregister (user_ptrack_handler, pr); -+ user_ptrack_handler (pr, PTRACK_PHASE_EXIT, NULL); -+ } -+ break; -+ -+ case ELAN3IO_ATTACH: -+ { -+ ELAN_CAPABILITY *cap; -+ -+ KMEM_ALLOC(cap, ELAN_CAPABILITY *, sizeof (ELAN_CAPABILITY), TRUE); -+ -+ if (cap == NULL) -+ return (set_errno (EFAULT)); -+ -+ if (copy_from_user (cap, (void *) arg, sizeof (ELAN_CAPABILITY))) -+ res = EFAULT; -+ else -+ { -+ if ((res = elan3_attach (ctxt, cap)) == 0) -+ { -+ if (copy_to_user ((void *) arg, cap, sizeof (ELAN_CAPABILITY))) -+ { -+ elan3_detach (ctxt); -+ res = EFAULT; -+ } -+ } -+ } -+ KMEM_FREE (cap, sizeof(ELAN_CAPABILITY)); -+ break; -+ } -+ -+ case ELAN3IO_DETACH: -+ spin_lock (&pr->pr_lock); -+ if (atomic_read (&pr->pr_mappings) > 0) -+ res = EINVAL; -+ else -+ elan3_detach (ctxt); -+ spin_unlock (&pr->pr_lock); -+ break; -+ -+ case ELAN3IO_ADDVP: -+ { -+ ELAN3IO_ADDVP_STRUCT *args; -+ -+ KMEM_ALLOC(args, ELAN3IO_ADDVP_STRUCT *, sizeof (ELAN3IO_ADDVP_STRUCT), TRUE); -+ -+ if (args == NULL) -+ return (set_errno (ENOMEM)); -+ -+ if (copy_from_user (args, (void *) arg, sizeof (ELAN3IO_ADDVP_STRUCT))) -+ res = EFAULT; -+ else -+ { -+ if ( (res=elan3_addvp (ctxt, args->process, &args->capability)) != 0) -+ PRINTF0 (ctxt, DBG_FN, "ELAN3IO_ADDVP elan3_addvp failed \n"); -+ } -+ -+ KMEM_FREE (args, sizeof (ELAN3IO_ADDVP_STRUCT)); -+ break; -+ } -+ -+ case ELAN3IO_REMOVEVP: -+ res = elan3_removevp (ctxt, arg); -+ break; -+ -+ case ELAN3IO_BCASTVP: -+ { -+ ELAN3IO_BCASTVP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_BCASTVP_STRUCT))) -+ return (-EFAULT); -+ -+ res = elan3_addbcastvp (ctxt, args.process, args.lowvp, args.highvp); -+ break; -+ } -+ -+ case ELAN3IO_LOAD_ROUTE: -+ { -+ ELAN3IO_LOAD_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_LOAD_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ res = elan3_load_route (ctxt, args.process, args.flits); -+ break; -+ } -+ -+ case ELAN3IO_CHECK_ROUTE: -+ { -+ ELAN3IO_CHECK_ROUTE_STRUCT args; -+ -+ args.routeError = 0; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_LOAD_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ if ((res = elan3_check_route (ctxt, args.process, args.flits, & args.routeError)) == ESUCCESS) -+ { -+ if (copy_to_user ( (void *) arg, &args,sizeof (ELAN3IO_LOAD_ROUTE_STRUCT))) -+ return (-EFAULT); -+ } -+ break; -+ } -+ -+ case ELAN3IO_PROCESS_2_LOCATION: -+ { -+ ELAN3IO_PROCESS_2_LOCATION_STRUCT args; -+ ELAN_LOCATION loc; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_PROCESS_2_LOCATION_STRUCT))) -+ return (-EFAULT); -+ -+ krwlock_write (&ctxt->VpLock); -+ loc = ProcessToLocation (ctxt, NULL, args.process , NULL); -+ krwlock_done (&ctxt->VpLock); -+ -+ args.loc = loc; -+ -+ if (copy_to_user ( (void *) arg, &args,sizeof (ELAN3IO_PROCESS_2_LOCATION_STRUCT))) -+ return (-EFAULT); -+ -+ break; -+ } -+ -+ case ELAN3IO_GET_ROUTE: -+ { -+ ELAN3IO_GET_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_GET_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ if ((res = elan3_get_route (ctxt, args.process, args.flits)) == ESUCCESS) -+ { -+ if (copy_to_user ( (void *) arg, &args,sizeof (ELAN3IO_GET_ROUTE_STRUCT))) -+ return (-EFAULT); -+ } -+ break; -+ } -+ -+ case ELAN3IO_RESET_ROUTE: -+ { -+ ELAN3IO_RESET_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_RESET_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ res = elan3_reset_route (ctxt, args.process); -+ break; -+ } -+ -+ case ELAN3IO_VP2NODEID: -+ { -+ ELAN3IO_VP2NODEID_STRUCT *vp2nodeId; -+ ELAN_LOCATION location; -+ -+ KMEM_ALLOC (vp2nodeId, ELAN3IO_VP2NODEID_STRUCT *, sizeof(ELAN3IO_VP2NODEID_STRUCT), TRUE); -+ if (vp2nodeId == NULL) -+ return (set_errno (ENOMEM)); -+ -+ if (copy_from_user (vp2nodeId, (void *) arg, sizeof (ELAN3IO_VP2NODEID_STRUCT))) { -+ KMEM_FREE (vp2nodeId, sizeof(ELAN3IO_VP2NODEID_STRUCT)); -+ return (-EFAULT); -+ } -+ -+ krwlock_write (&ctxt->VpLock); -+ location = ProcessToLocation (ctxt, NULL, vp2nodeId->process , NULL); -+ krwlock_done (&ctxt->VpLock); -+ -+ vp2nodeId->nodeId = location.loc_node; -+ if (copy_to_user ( (void *) arg, vp2nodeId, sizeof (ELAN3IO_VP2NODEID_STRUCT))) { -+ KMEM_FREE (vp2nodeId, sizeof(ELAN3IO_VP2NODEID_STRUCT)); -+ return (-EFAULT); -+ } -+ -+ KMEM_FREE (vp2nodeId, sizeof(ELAN3IO_VP2NODEID_STRUCT)); -+ -+ break; -+ } -+ -+ case ELAN3IO_PROCESS: -+ return (elan3_process (ctxt)); -+ -+ case ELAN3IO_SETPERM: -+ { -+ ELAN3IO_SETPERM_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_SETPERM_STRUCT))) -+ return (-EFAULT); -+ -+ res = elan3mmu_setperm (ctxt->Elan3mmu, args.maddr, args.eaddr, args.len, args.perm); -+ break; -+ } -+ -+ case ELAN3IO_CLEARPERM: -+ { -+ ELAN3IO_CLEARPERM_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_CLEARPERM_STRUCT))) -+ return (-EFAULT); -+ -+ elan3mmu_clrperm (ctxt->Elan3mmu, args.eaddr, args.len); -+ break; -+ } -+ -+ case ELAN3IO_CHANGEPERM: -+ { -+ ELAN3IO_CHANGEPERM_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_CHANGEPERM_STRUCT))) -+ return (-EFAULT); -+ -+ res = EINVAL; -+ break; -+ } -+ -+ case ELAN3IO_HELPER_THREAD: -+ res = elan3_lwp (ctxt); -+ break; -+ -+ case ELAN3IO_WAITCOMMAND: -+ res = WaitForCommandPort (ctxt); -+ break; -+ -+ case ELAN3IO_BLOCK_INPUTTER: -+ elan3_block_inputter (ctxt, arg); -+ break; -+ -+ case ELAN3IO_SET_FLAGS: -+ sctx->Flags = arg; -+ break; -+ -+ case ELAN3IO_SET_SIGNAL: -+ sctx->signal = arg; -+ break; -+ -+ case ELAN3IO_WAITEVENT: -+ res = sys_waitevent (ctxt, (E3_Event *) arg); -+ break; -+ -+ case ELAN3IO_ALLOC_EVENTCOOKIE: -+ res = cookie_alloc_cookie (sctx->Table, arg); -+ break; -+ -+ case ELAN3IO_FREE_EVENTCOOKIE: -+ res = cookie_free_cookie (sctx->Table, arg); -+ break; -+ -+ case ELAN3IO_ARM_EVENTCOOKIE: -+ res = cookie_arm_cookie (sctx->Table, arg); -+ break; -+ -+ case ELAN3IO_WAIT_EVENTCOOKIE: -+ res = cookie_wait_cookie (sctx->Table, arg); -+ break; -+ -+ case ELAN3IO_SWAPSPACE: -+ if (fuword (&((SYS_SWAP_SPACE *) arg)->Magic) != SYS_SWAP_MAGIC) -+ return (set_errno (EINVAL)); -+ -+ ((SYS_CTXT *) ctxt->Private)->Swap = (SYS_SWAP_SPACE *) arg; -+ break; -+ -+ case ELAN3IO_EXCEPTION_SPACE: -+ if (fuword (&((SYS_EXCEPTION_SPACE *) arg)->Magic) != SYS_EXCEPTION_MAGIC) -+ return (set_errno (EINVAL)); -+ -+ ((SYS_CTXT *) ctxt->Private)->Exceptions = (SYS_EXCEPTION_SPACE *) arg; -+ break; -+ -+ case ELAN3IO_GET_EXCEPTION: -+ { -+ SYS_EXCEPTION *exception; -+ -+ if (((SYS_CTXT *) ctxt->Private)->Exceptions == NULL) -+ return (set_errno (EINVAL)); -+ -+ KMEM_ALLOC(exception, SYS_EXCEPTION *, sizeof (SYS_EXCEPTION), TRUE); -+ -+ if (exception == NULL) -+ return (set_errno (ENOMEM)); -+ -+ if ((res = sys_getException (((SYS_CTXT *) ctxt->Private), exception)) == 0 && -+ copy_to_user ((void *) arg, exception, sizeof (SYS_EXCEPTION))) -+ res = EFAULT; -+ -+ KMEM_FREE (exception, sizeof (SYS_EXCEPTION)); -+ break; -+ } -+ -+ case ELAN3IO_UNLOAD: -+ { -+ ELAN3MMU *elan3mmu = ctxt->Elan3mmu; -+ ELAN3IO_UNLOAD_STRUCT args; -+ int span; -+ unsigned long flags; -+ E3_Addr eaddr; -+ caddr_t addr; -+ size_t len; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_UNLOAD_STRUCT))) -+ return (-EFAULT); -+ -+ addr = (caddr_t) args.addr; -+ len = args.len; -+ -+ if (((unsigned long) addr & PAGEMASK) || (len & PAGEMASK) || (len < 0)) -+ return -EINVAL; -+ -+ spin_lock_irqsave (&elan3mmu->elan3mmu_lock, flags); -+ for (; len; len -= span, addr += span) -+ { -+ ELAN3MMU_RGN *rgn = elan3mmu_findrgn_main (elan3mmu, addr, 0); -+ -+ if (rgn == NULL || (rgn->rgn_mbase + rgn->rgn_len) < addr) -+ span = len; -+ else if (rgn->rgn_mbase > addr) -+ span = MIN(len, rgn->rgn_mbase - addr); -+ else -+ { -+ span = MIN(len, (rgn->rgn_mbase + rgn->rgn_len) - addr); -+ eaddr = rgn->rgn_ebase + (addr - rgn->rgn_mbase); -+ -+ elan3mmu_unload (elan3mmu, eaddr, span, PTE_UNLOAD); -+ } -+ } -+ spin_unlock_irqrestore (&elan3mmu->elan3mmu_lock, flags); -+ -+ return 0; -+ } -+ -+ case ELAN3IO_GET_DEVINFO: -+ { -+ ELAN3IO_GET_DEVINFO_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_GET_DEVINFO_STRUCT))) -+ return (-EFAULT); -+ -+ if (copy_to_user ((void *) args.devinfo, &ctxt->Device->Devinfo, sizeof (ELAN_DEVINFO))) -+ res = EFAULT; -+ break; -+ } -+ -+ case ELAN3IO_GET_POSITION: -+ { -+ ELAN3IO_GET_POSITION_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN3IO_GET_POSITION_STRUCT))) -+ return (-EFAULT); -+ -+ if (copy_to_user ((void *) args.position, &ctxt->Device->Position, sizeof (ELAN_POSITION))) -+ res = EFAULT; -+ break; -+ } -+ -+ default: -+ return (-EINVAL); -+ } -+ -+ return (res ? set_errno (res) : 0); -+} -+ -+static void user_vma_open(struct vm_area_struct *vma) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) vma->vm_private_data; -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_vma_open: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ if (vma->vm_pgoff == ELAN3IO_OFF_COMMAND_PAGE) -+ if (atomic_dec_and_test (&pr->pr_mappings)) -+ pr->pr_ctxt->CommandPageMapping = NULL; -+} -+ -+static void user_vma_close(struct vm_area_struct *vma) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) vma->vm_private_data; -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_vma_close: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ if (vma->vm_pgoff == ELAN3IO_OFF_COMMAND_PAGE) -+ atomic_inc (&pr->pr_mappings); -+} -+ -+static struct vm_operations_struct user_vm_ops = { -+ open: user_vma_open, -+ close: user_vma_close, -+}; -+ -+static int -+user_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ ELAN3_CTXT *ctxt = pr->pr_ctxt; -+ ioaddr_t ioaddr; -+ -+ /* -+ * NOTE - since we need to maintain the reference count on -+ * the user_private we only permit single page -+ * mmaps - this means that we will certainly see -+ * the correct number of closes to maintain the -+ * the reference count correctly. -+ */ -+ -+ if ((vma->vm_end - vma->vm_start) != PAGE_SIZE) -+ return (-EINVAL); -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_mmap: vm_mm=%p start=%lx end=%lx pgoff=%lx flags=%lx prot=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_flags, vma->vm_page_prot.pgprot, vma->vm_file); -+ -+ switch (vma->vm_pgoff) -+ { -+ default: -+ return (-EINVAL); -+ -+ case ELAN3IO_OFF_COMMAND_PAGE: -+ spin_lock (&pr->pr_lock); -+ if (ctxt->CommandPage == (ioaddr_t) 0 || atomic_read (&pr->pr_mappings) != 0) -+ { -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_mmap: command port - %s\n", ctxt->CommandPort ? "already mapped" : "not attached"); -+ spin_unlock (&pr->pr_lock); -+ return (-EINVAL); -+ } -+#ifdef LINUX_SPARC -+ pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE); -+ pgprot_val(vma->vm_page_prot) |= _PAGE_IE; -+#elif defined(pgprot_noncached) -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+#endif -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_mmap: commandport at %lx phys %llx prot %lx\n", -+ vma->vm_start, (unsigned long long) kmem_to_phys ((void *) ctxt->CommandPort), vma->vm_page_prot.pgprot); -+ -+ /* Don't try to swap out physical pages.. */ -+ vma->vm_flags |= VM_RESERVED; -+ -+ /* -+ * Don't dump addresses that are not real memory to a core file. -+ */ -+ vma->vm_flags |= VM_IO; -+ -+#ifdef NO_RMAP -+ if (remap_page_range (vma->vm_start, kmem_to_phys ((void *) ctxt->CommandPage), vma->vm_end - vma->vm_start, vma->vm_page_prot)) -+#else -+ if (remap_page_range (vma, vma->vm_start, kmem_to_phys ((void *) ctxt->CommandPage), vma->vm_end - vma->vm_start, vma->vm_page_prot)) -+#endif -+ { -+ spin_unlock (&pr->pr_lock); -+ return (-EAGAIN); -+ } -+ ctxt->CommandPageMapping = (void *) vma->vm_start; -+ -+ atomic_inc (&pr->pr_mappings); -+ -+ spin_unlock (&pr->pr_lock); -+ break; -+ -+ case ELAN3IO_OFF_UREG_PAGE: -+#ifdef LINUX_SPARC -+ pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE); -+ pgprot_val(vma->vm_page_prot) |= _PAGE_IE; -+#elif defined(pgprot_noncached) -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+#endif -+ ioaddr = ctxt->Device->RegPtr + (offsetof (E3_Regs, URegs) & PAGEMASK); -+ -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_mmap: user_regs at %lx phys %llx prot %lx\n", vma->vm_start, -+ (unsigned long long) kmem_to_phys ((void *) ioaddr), vma->vm_page_prot.pgprot); -+ -+ /* Don't try to swap out physical pages.. */ -+ vma->vm_flags |= VM_RESERVED; -+ -+ /* -+ * Don't dump addresses that are not real memory to a core file. -+ */ -+ vma->vm_flags |= VM_IO; -+ -+#ifdef NO_RMAP -+ if (remap_page_range (vma->vm_start, kmem_to_phys ((void *) ioaddr), -+#else -+ if (remap_page_range (vma, vma->vm_start, kmem_to_phys ((void *) ioaddr), -+#endif -+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) -+ return (-EAGAIN); -+ break; -+ -+ case ELAN3IO_OFF_FLAG_PAGE: -+ PRINTF (DBG_DEVICE, DBG_SEG, "user_mmap: flag page at %lx phys %llx\n", vma->vm_start, -+ (unsigned long long) kmem_to_phys ((void *) ctxt->FlagPage)); -+ -+ /* we do not want to have this area swapped out, lock it */ -+ vma->vm_flags |= VM_LOCKED; -+ -+ /* Mark the page as reserved or else the remap_page_range() doesn't remap it */ -+ SetPageReserved(pte_page(*find_pte_kernel((unsigned long) ctxt->FlagPage))); -+ -+#ifdef NO_RMAP -+ if (remap_page_range (vma->vm_start, kmem_to_phys ((void *) ctxt->FlagPage), -+#else -+ if (remap_page_range (vma, vma->vm_start, kmem_to_phys ((void *) ctxt->FlagPage), -+#endif -+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) -+ return (-EAGAIN); -+ break; -+ } -+ -+ ASSERT (vma->vm_ops == NULL); -+ -+ vma->vm_ops = &user_vm_ops; -+ vma->vm_file = file; -+ vma->vm_private_data = (void *) pr; -+ -+ return (0); -+} -+ -+/* driver entry points */ -+static int -+elan3_open (struct inode *inode, struct file *file) -+{ -+ if (elan3_devices[ELAN3_DEVICE(inode)] == NULL) -+ return (-ENXIO); -+ -+ PRINTF (DBG_DEVICE, DBG_FN, "elan3_open: device %d minor %d file=%p\n", ELAN3_DEVICE(inode), ELAN3_MINOR(inode), file); -+ -+ switch (ELAN3_MINOR (inode)) -+ { -+ case ELAN3_MINOR_CONTROL: -+ return (control_open (inode, file)); -+ case ELAN3_MINOR_MEM: -+ return (mem_open (inode, file)); -+ case ELAN3_MINOR_USER: -+ return (user_open (inode, file)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+static int -+elan3_release (struct inode *inode, struct file *file) -+{ -+ PRINTF (DBG_DEVICE, DBG_FN, "elan3_release: device %d minor %d file=%p\n", ELAN3_DEVICE(inode), ELAN3_MINOR(inode), file); -+ -+ switch (ELAN3_MINOR (inode)) -+ { -+ case ELAN3_MINOR_CONTROL: -+ return (control_release (inode, file)); -+ case ELAN3_MINOR_MEM: -+ return (mem_release (inode, file)); -+ case ELAN3_MINOR_USER: -+ return (user_release (inode, file)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+static int -+elan3_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ switch (ELAN3_MINOR (inode)) -+ { -+ case ELAN3_MINOR_CONTROL: -+ return (control_ioctl (inode, file, cmd, arg)); -+ case ELAN3_MINOR_MEM: -+ return (mem_ioctl (inode, file, cmd, arg)); -+ case ELAN3_MINOR_USER: -+ return (user_ioctl (inode, file, cmd, arg)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+ -+static int -+elan3_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ PRINTF (DBG_DEVICE, DBG_SEG, "elan3_mmap: instance %d minor %d start=%lx end=%lx pgoff=%lx flags=%lx prot=%lx\n", -+ ELAN3_DEVICE (file->f_dentry->d_inode), ELAN3_MINOR (file->f_dentry->d_inode), -+ vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_flags, vma->vm_page_prot.pgprot); -+ -+ switch (ELAN3_MINOR (file->f_dentry->d_inode)) -+ { -+ case ELAN3_MINOR_CONTROL: -+ return (control_mmap (file, vma)); -+ case ELAN3_MINOR_MEM: -+ return (mem_mmap (file, vma)); -+ case ELAN3_MINOR_USER: -+ return (user_mmap (file, vma)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+static irqreturn_t -+InterruptHandlerWrapper(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ if (InterruptHandler ((ELAN3_DEV *)dev_id) == 0) -+ return IRQ_HANDLED; -+ else -+ return IRQ_NONE; -+} -+ -+ -+/* -+ * Elan specific PCI configuration registers. -+ */ -+ -+#define PCI_CONF_PARITY_PHYS_LO 0x40 -+#define PCI_CONF_PARITY_PHYS_HI 0x44 -+#define PCI_CONF_PARITY_PHASE_ADDR 0x46 -+#define PCI_CONF_PARITY_MASTER_TYPE 0x47 -+#define PCI_CONF_ELAN3_CTRL 0x48 -+ -+#define ECTRL_EXTEND_LATENCY (1 << 0) -+#define ECTRL_ENABLE_PREFETCH (1 << 1) -+#define ECTRL_SOFTWARE_INTERNAL_RESET (1 << 2) -+#define ECTRL_REDUCED_RETRY_RATE (1 << 3) -+#define ECTRL_CLOCK_DIVIDE_RATE_SHIFT 4 -+#define ECTRL_COMMS_DIVIDE_RATE_SHIFT 10 -+#define ECTRL_FORCE_COMMSCLK_LOCAL (1 << 14) -+ -+/* -+ * Configure PCI. -+ */ -+static int -+ConfigurePci(ELAN3_DEV *dev) -+{ -+ struct pci_dev *pci = dev->Osdep.pci; -+ u32 rom_address; -+ -+ if (pci_enable_device(pci)) -+ return (ENXIO); -+ -+ /* disable ROM */ -+ pci_read_config_dword(pci, PCI_ROM_ADDRESS, &rom_address); -+ rom_address &= ~PCI_ROM_ADDRESS_ENABLE; -+ pci_write_config_dword(pci, PCI_ROM_ADDRESS, rom_address); -+ mb(); -+ -+ /* this is in 32-bit WORDS */ -+ pci_write_config_byte(pci, PCI_CACHE_LINE_SIZE, (64 >> 2)); -+ mb(); -+ -+ /* allow 40 ticks to respond, 16 data phases */ -+ pci_write_config_byte(pci, PCI_LATENCY_TIMER, 255); -+ mb(); -+ -+ /* don't enable PCI_COMMAND_SERR--see note in elandev_dunix.c */ -+ pci_write_config_word(pci, PCI_COMMAND, PCI_COMMAND_MEMORY -+ | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY); -+ mb(); -+ -+ return ESUCCESS; -+} -+ -+/* -+ * Reset chip to a known state. -+ */ -+static int -+ResetElan(ELAN3_DEV *dev, ioaddr_t intPalAddr) -+{ -+ struct pci_dev *pci = dev->Osdep.pci; -+ int instance = dev->Instance; -+ u32 val; -+ u8 revid; -+ int CasLatency; -+ int res; -+ -+ /* determine rev of board */ -+ pci_read_config_byte(pci, PCI_REVISION_ID, &revid); -+ -+ /* GNAT 2328 - don't set ECTRL_ENABLE_PREFETCH on Elan rev A */ -+ val = ECTRL_EXTEND_LATENCY | (39 << ECTRL_CLOCK_DIVIDE_RATE_SHIFT) -+ | (6 << ECTRL_COMMS_DIVIDE_RATE_SHIFT); -+ switch (revid) -+ { -+ case PCI_REVISION_ID_ELAN3_REVA: -+ printk("elan%d: is an elan3 (revision a) - not supported\n", instance); -+ return (EFAIL); -+ -+ case PCI_REVISION_ID_ELAN3_REVB: -+ val |= ECTRL_ENABLE_PREFETCH; -+ if (BackToBackMaster) -+ val |= ECTRL_FORCE_COMMSCLK_LOCAL; -+ printk("elan%d: is an elan3 (revision b)\n", instance); -+ break; -+ default: -+ printk("elan%d: unsupported elan3 revision %d\n", -+ instance, revid); -+ return EFAIL; -+ } -+ pci_write_config_dword(pci, PCI_CONF_ELAN3_CTRL, val); -+ mb(); -+ -+ /* -+ * GNAT: 2474 -+ * Hit reset on the Elan, then we MUST initialise the schedule status -+ * register to drive reset on the link before the link can come out -+ * of reset (15 uS). We need to keep it like this until we've -+ * initialised SDRAM -+ */ -+ pci_read_config_dword(pci, PCI_CONF_ELAN3_CTRL, &val); -+ pci_write_config_dword(pci, PCI_CONF_ELAN3_CTRL, -+ val | ECTRL_SOFTWARE_INTERNAL_RESET); -+ mb(); -+ -+ /* Read the Vital Product Data to determine the cas latency */ -+ if ((res = ReadVitalProductData (dev, &CasLatency)) != ESUCCESS) -+ return (res); -+ -+ /* -+ * Now clear the Software internal reset bit, and start the sdram -+ */ -+ pci_write_config_dword(pci, PCI_CONF_ELAN3_CTRL, val); -+ mb(); -+ -+ /* -+ * Enable SDRAM before sizing and initalising it for ECC. -+ * NOTE: don't enable all sets of the cache (yet), nor ECC -+ */ -+ dev->Cache_Control_Reg = (CasLatency | REFRESH_RATE_16US); -+ -+ write_reg32 (dev, Cache_Control_Reg.ContReg, (dev->Cache_Control_Reg | SETUP_SDRAM)); -+ mb(); -+ -+ INIT_SCHED_STATUS(dev, Sched_Initial_Value); -+ -+ /* -+ * Set the interrupt mask to 0 and enable the interrupt PAL -+ * by writing any value to it. -+ */ -+ SET_INT_MASK (dev, 0); -+ writeb (0, intPalAddr); -+ -+ return ESUCCESS; -+} -+ -+/* -+ * Determine the size of elan PCI address spaces. EFAIL is returned if -+ * unused or invalid BAR is specified, or if board reports I/O mapped space. -+ */ -+int -+DeviceRegisterSize(ELAN3_DEV *dev, int rnumber, int *sizep) -+{ -+ struct pci_dev *pdev = dev->Osdep.pci; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ *sizep = pci_resource_size(pdev, rnumber); -+#else -+ *sizep = pci_resource_end(pdev, rnumber) - pci_resource_start(pdev, rnumber) + 1; -+#endif -+ return ESUCCESS; -+} -+ -+/* -+ * Map PCI memory into kernel virtual address space. On the alpha, -+ * we just return appropriate kseg address, and Unmap is a no-op. -+ */ -+int -+MapDeviceRegister(ELAN3_DEV *dev, int rnumber, ioaddr_t *addrp, -+ int off, int len, DeviceMappingHandle *handlep) -+{ -+ struct pci_dev *pdev = dev->Osdep.pci; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ u64 base = pci_get_base_address(pdev, rnumber); -+ *addrp = (ioaddr_t) pci_base_to_kseg(base + off, pdev->bus->number); -+ -+#else -+ if (len == 0) -+ len = pci_resource_end(pdev, rnumber) - pci_resource_start(pdev, rnumber) + 1; -+ -+ if (len == 0) -+ return (EINVAL); -+ -+ *addrp = (ioaddr_t) ioremap_nocache (pci_resource_start(pdev, rnumber) + off, len); -+#endif -+ -+ *handlep = (void *) *addrp; -+ -+ return (*addrp ? ESUCCESS : ENOMEM); -+} -+void -+UnmapDeviceRegister(ELAN3_DEV *dev, DeviceMappingHandle *handlep) -+{ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -+ iounmap (*handlep); -+#endif -+} -+ -+void -+ElanBusError (ELAN3_DEV *dev) -+{ -+ struct pci_dev *pci = dev->Osdep.pci; -+ u8 phaseaddr, type; -+ u16 status, cmd, physhi; -+ u32 physlo; -+ -+ printk("elan%d: bus error occured\n", dev->Instance); -+ -+ pci_read_config_word (pci, PCI_STATUS, &status); -+ pci_read_config_word (pci, PCI_COMMAND, &cmd); -+ pci_read_config_dword(pci, PCI_CONF_PARITY_PHYS_LO, &physlo); -+ pci_read_config_word (pci, PCI_CONF_PARITY_PHYS_HI, &physhi); -+ pci_read_config_byte (pci, PCI_CONF_PARITY_PHASE_ADDR, &phaseaddr); -+ pci_read_config_byte (pci, PCI_CONF_PARITY_MASTER_TYPE, &type); -+ -+#define PCI_CONF_STAT_FORMAT "\20" \ -+ "\6SIXTY_SIX_MHZ\7UDF\10FAST_BACK\11PARITY" \ -+ "\14SIG_TARGET_ABORT\15REC_TARGET_ABORT\16REC_MASTER_ABORT" \ -+ "\17SIG_SYSTEM_ERROR\20DETECTED_PARITY" -+ -+ printk ("elan%d: status %x cmd %4x physaddr %04x%08x phase %x type %x\n", -+ dev->Instance, status, cmd, physhi, physlo, phaseaddr, type); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/elansyscall.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/elansyscall.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/elansyscall.c 2005-06-01 23:12:54.584441384 -0400 -@@ -0,0 +1,1230 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elansyscall.c,v 1.99.2.1 2004/10/28 17:08:56 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/elansyscall.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int sys_exception (ELAN3_CTXT *ctxt, int type, int proc, void *trap, va_list ap); -+static int sys_getWordItem (ELAN3_CTXT *ctxt, int list, void **itemp, E3_uint32 *valuep); -+static int sys_getBlockItem (ELAN3_CTXT *ctxt, int list, void **itemp, E3_Addr *valuep); -+static void sys_putWordItem (ELAN3_CTXT *ctxt, int list, E3_uint32 value); -+static void sys_putBlockItem (ELAN3_CTXT *ctxt, int list, E3_uint32 *ptr); -+static void sys_putbackItem (ELAN3_CTXT *ctxt, int list, void *item); -+static void sys_freeWordItem (ELAN3_CTXT *ctxt, void *item); -+static void sys_freeBlockItem (ELAN3_CTXT *ctxt, void *item); -+static int sys_countItems (ELAN3_CTXT *ctxt, int list); -+static int sys_event (ELAN3_CTXT *ctxt, E3_uint32 cookie, int flag); -+static void sys_swapin (ELAN3_CTXT *ctxt); -+static void sys_swapout (ELAN3_CTXT *ctxt); -+static void sys_freePrivate (ELAN3_CTXT *ctxt); -+static int sys_fixupNetworkError (ELAN3_CTXT *ctxt, NETERR_FIXUP *nef); -+static int sys_startFaultCheck (ELAN3_CTXT *ctxt); -+static void sys_endFaultCheck (ELAN3_CTXT *ctxt); -+static E3_uint8 sys_load8 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void sys_store8 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint8 val); -+static E3_uint16 sys_load16 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void sys_store16 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint16 val); -+static E3_uint32 sys_load32 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void sys_store32 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint32 val); -+static E3_uint64 sys_load64 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void sys_store64 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint64 val); -+ -+static ELAN3_OPS elan3_sys_ops = { -+ ELAN3_OPS_VERSION, /* Version */ -+ -+ sys_exception, /* Exception */ -+ sys_getWordItem, /* GetWordItem */ -+ sys_getBlockItem, /* GetBlockItem */ -+ sys_putWordItem, /* PutWordItem */ -+ sys_putBlockItem, /* PutBlockItem */ -+ sys_putbackItem, /* PutbackItem */ -+ sys_freeWordItem, /* FreeWordItem */ -+ sys_freeBlockItem, /* FreeBlockItem */ -+ sys_countItems, /* CountItems */ -+ sys_event, /* Event */ -+ sys_swapin, /* Swapin */ -+ sys_swapout, /* Swapout */ -+ sys_freePrivate, /* FreePrivate */ -+ sys_fixupNetworkError, /* FixupNetworkError */ -+ NULL, /* DProcTrap */ -+ NULL, /* TProcTrap */ -+ NULL, /* IProcTrap */ -+ NULL, /* CProcTrap */ -+ NULL, /* CProcReissue */ -+ sys_startFaultCheck, /* StartFaultCheck */ -+ sys_endFaultCheck, /* EndFaultCheck */ -+ sys_load8, /* Load8 */ -+ sys_store8, /* Store8 */ -+ sys_load16, /* Load16 */ -+ sys_store16, /* Store16 */ -+ sys_load32, /* Load32 */ -+ sys_store32, /* Store32 */ -+ sys_load64, /* Load64 */ -+ sys_store64 /* Store64 */ -+}; -+ -+va_list null_valist; -+ -+SYS_CTXT * -+sys_init (ELAN3_CTXT *ctxt) -+{ -+ SYS_CTXT *sctx; -+ -+ /* Allocate and initialise the context private data */ -+ KMEM_ZALLOC (sctx, SYS_CTXT *, sizeof (SYS_CTXT), TRUE); -+ -+ if (sctx == NULL) -+ return ((SYS_CTXT *) NULL); -+ -+ sctx->Swap = NULL; -+ sctx->Armed = 0; -+ sctx->Backoff = 1; -+ sctx->Table = cookie_alloc_table ((unsigned long) ELAN3_MY_TASK_HANDLE(), 0); -+ sctx->signal = SIGSEGV; -+ -+ if (sctx->Table == NULL) -+ { -+ KMEM_FREE (sctx, sizeof (SYS_CTXT)); -+ return ((SYS_CTXT *) NULL); -+ } -+ -+ kmutex_init (&sctx->Lock); -+ spin_lock_init (&sctx->WaitLock); -+ kcondvar_init (&sctx->NetworkErrorWait); -+ -+ /* Install my context operations and private data */ -+ ctxt->Operations = &elan3_sys_ops; -+ ctxt->Private = (void *) sctx; -+ -+ return (sctx); -+} -+ -+/* returns -ve on error or ELAN_CAP_OK or ELAN_CAP_RMS */ -+/* use = ELAN_USER_ATTACH, ELAN_USER_P2P, ELAN_USER_BROADCAST */ -+int -+elan3_validate_cap(ELAN3_DEV *dev, ELAN_CAPABILITY *cap ,int use) -+{ -+ /* Don't allow a user process to attach to system context */ -+ if (ELAN3_SYSTEM_CONTEXT (cap->cap_lowcontext) || ELAN3_SYSTEM_CONTEXT (cap->cap_highcontext) -+ || cap->cap_highcontext <= ELAN_USER_BASE_CONTEXT_NUM || cap->cap_highcontext <= ELAN_USER_BASE_CONTEXT_NUM) -+ { -+ PRINTF2 (DBG_DEVICE, DBG_VP,"elan3_validate_cap: lctx %x hctx %x \n",cap->cap_lowcontext, cap->cap_highcontext); -+ PRINTF3 (DBG_DEVICE, DBG_VP,"elan3_validate_cap: bit %x low %x high %x\n", ((cap->cap_lowcontext) & SYS_CONTEXT_BIT), -+ E3_NUM_CONTEXT_0, ELAN3_KCOMM_BASE_CONTEXT_NUM); -+ -+ -+ PRINTF0 (DBG_DEVICE, DBG_VP,"elan3_validate_cap: user process cant attach to system cap\n"); -+ return (-EINVAL); -+ } -+ -+ if (cap->cap_type & ELAN_CAP_TYPE_HWTEST) -+ { -+ if (!(cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP)) /* cant have a bit map */ -+ { -+ PRINTF0 (DBG_DEVICE, DBG_VP, "elanmod_classify_cap: ELAN_CAP_TYPE_HWTEST must have ELAN_CAP_TYPE_NO_BITMAP\n"); -+ return (-EINVAL); -+ } -+ -+ if (cap->cap_lowcontext != cap->cap_highcontext) -+ { -+ PRINTF2 (DBG_DEVICE, DBG_VP, "elanmod_classify_cap: ELAN_CAP_TYPE_HWTEST (cap->cap_lowcontext != cap->cap_highcontext) %d %d\n",cap->cap_lowcontext , cap->cap_highcontext) ; -+ return (-EINVAL); -+ } -+ -+ if ( ! (ELAN3_HWTEST_CONTEXT(cap->cap_lowcontext) && ELAN3_HWTEST_CONTEXT(cap->cap_highcontext))) -+ { -+ PRINTF3 (DBG_DEVICE, DBG_VP, "elanmod_classify_cap: ELAN_CAP_TYPE_HWTEST HWTEST_BASE_CONTEXT %d %d %d \n" , ELAN3_HWTEST_BASE_CONTEXT_NUM,cap->cap_lowcontext ,ELAN3_HWTEST_TOP_CONTEXT_NUM); -+ return (-EINVAL); -+ } -+ -+ if (cap->cap_lownode != ELAN_CAP_UNINITIALISED || cap->cap_highnode != ELAN_CAP_UNINITIALISED) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_VP, "elanmod_classify_cap: ELAN_CAP_TYPE_HWTEST nodes != ELAN_CAP_UNINITIALISED\n"); -+ return (-EINVAL); -+ } -+ -+ return ELAN_CAP_OK; -+ } -+ -+ return elanmod_classify_cap(&dev->Position, cap, use); -+} -+ -+int -+sys_waitevent (ELAN3_CTXT *ctxt, E3_Event *event) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ EVENT_COOKIE cookie; -+ -+ if (ctxt->Device->Devinfo.dev_revision_id == PCI_REVISION_ID_ELAN3_REVA) -+ return (EINVAL); -+ -+ cookie = fuword ((int *) &event->ev_Type) & ~(EV_TYPE_MASK_EVIRQ | EV_TYPE_MASK_BCOPY); -+ -+ if (cookie_alloc_cookie (sctx->Table, cookie) != ESUCCESS) -+ return (EINVAL); -+ -+ cookie_arm_cookie (sctx->Table, cookie); -+ -+ if (fuword ((int *) &event->ev_Count) > 0) -+ cookie_wait_cookie (sctx->Table, cookie); -+ -+ cookie_free_cookie (sctx->Table, cookie); -+ -+ return (ESUCCESS); -+} -+ -+static void * -+sys_getItem (SYS_SWAP_SPACE *sp, int list) -+{ -+ void *itemp = (void *) fuptr_noerr ((void **) &sp->ItemListsHead[list]); -+ void *next; -+ -+ PRINTF4 (DBG_DEVICE, DBG_SYSCALL, "sys_getItem: sp=%p list=%d head=%p itemp=%p\n", -+ sp, list, &sp->ItemListsHead[list], itemp); -+ -+ if (itemp == NULL) -+ return (NULL); -+ -+ next = (void *) fuptr_noerr ((void *) itemp); -+ -+ suptr_noerr ((void *) &sp->ItemListsHead[list], (void *) next); -+ if (next == NULL) -+ suptr_noerr ((void *) &sp->ItemListsTailp[list], (void *)&sp->ItemListsHead[list]); -+ return (itemp); -+} -+ -+static void -+sys_putItemBack (SYS_SWAP_SPACE *sp, int list, void *itemp) -+{ -+ PRINTF4 (DBG_DEVICE, DBG_SYSCALL, "sys_putItemBack: sp=%p list=%d itemp=%p value=%08x\n", -+ sp, list, itemp, fuword_noerr ((int *) &((SYS_WORD_ITEM *) itemp)->Value)); -+ -+ suptr_noerr ((void **) itemp, NULL); /* item->Next = NULL */ -+ suptr_noerr ((void **) fuptr_noerr ((void **) &sp->ItemListsTailp[list]), (void *)itemp); /* *Tailp = item */ -+ suptr_noerr ((void **) &sp->ItemListsTailp[list], (void *) itemp); /* Tailp = &item->Next */ -+} -+ -+static void -+sys_putItemFront (SYS_SWAP_SPACE *sp, int list, void *itemp) -+{ -+ PRINTF4 (DBG_DEVICE, DBG_SYSCALL, "sys_putItemFront: sp=%p list=%d itemp=%p value=%08x\n", -+ sp, list, itemp, fuword_noerr ((int *) &((SYS_WORD_ITEM *) itemp)->Value)); -+ -+ suptr_noerr ((void **) itemp, fuptr_noerr ((void **) &sp->ItemListsHead[list])); /* item->Next = Head */ -+ suptr_noerr ((void **) &sp->ItemListsHead[list], (void *) itemp); /* Head = item */ -+ -+ if (fuptr_noerr ((void **) &sp->ItemListsTailp[list]) == (void *) &sp->ItemListsHead[list]) /* if (Tailp == &Head) */ -+ suptr_noerr ((void **) &sp->ItemListsTailp[list], (void *) itemp); /* Tailp = &Item->Next */ -+} -+ -+ -+static int -+sys_getWordItem (ELAN3_CTXT *ctxt, int list, void **itemp, E3_uint32 *valuep) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ SYS_WORD_ITEM *item; -+ int res; -+ label_t ljb; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljb)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, list, (void *) NULL, null_valist); -+ return (0); -+ } -+ -+ item = (SYS_WORD_ITEM *) sys_getItem (sp, list); -+ -+ if (item == NULL) -+ res = 0; -+ else -+ { -+ if (list == LIST_DMA_PTR) -+ sctx->Armed = TRUE; -+ -+ *itemp = (void *) item; -+ *valuep = (E3_Addr) fuword_noerr ((E3_int32 *) &item->Value); -+ -+ PRINTF3 (ctxt, DBG_SYSCALL, "sys_getWordItem: list=%d -> item=%p value=%08x\n", list, *itemp, *valuep); -+ -+ res = 1; -+ } -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ return (res); -+} -+ -+static int -+sys_getBlockItem (ELAN3_CTXT *ctxt, int list, void **itemp, E3_Addr *valuep) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ SYS_BLOCK_ITEM *item; -+ int res; -+ label_t ljb; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljb)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, list, (void *) NULL, null_valist); -+ return (0); -+ } -+ -+ item = sys_getItem (sp, list); -+ -+ if (item == NULL) -+ res = 0; -+ else -+ { -+ E3_uint32 *dest = fuptr_noerr ((void **) &item->Pointer); -+ -+ if (list == LIST_DMA_DESC) -+ sctx->Armed = TRUE; -+ -+ *itemp = (void *) item; -+ *valuep = elan3mmu_elanaddr (ctxt->Elan3mmu, (caddr_t) dest); -+ -+ PRINTF3 (ctxt, DBG_SYSCALL, "sys_getBlockItem: list=%d -> item=%p addr=%08x\n", list, *itemp, *valuep); -+ PRINTF4 (ctxt, DBG_SYSCALL, " %08x %08x %08x %08x\n", -+ fuword_noerr ((int *) &dest[0]), fuword_noerr ((int *) &dest[1]), -+ fuword_noerr ((int *) &dest[2]), fuword_noerr ((int *) &dest[3])); -+ PRINTF4 (ctxt, DBG_SYSCALL, " %08x %08x %08x %08x\n", -+ fuword_noerr ((int *) &dest[4]), fuword_noerr ((int *) &dest[5]), -+ fuword_noerr ((int *) &dest[6]), fuword_noerr ((int *) &dest[7])); -+ -+ -+ res = 1; -+ } -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ return (res); -+} -+ -+static void -+sys_putWordItem (ELAN3_CTXT *ctxt, int list, E3_Addr value) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ SYS_WORD_ITEM *item; -+ label_t ljp; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ PRINTF2 (ctxt,DBG_SYSCALL, "sys_putWordItem: list=%x value=%x\n", list, value); -+ -+ if (on_fault (&ljp)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, list, (void *) NULL, null_valist); -+ return; -+ } -+ -+ item = sys_getItem (sp, LIST_FREE_WORD); -+ -+ PRINTF1 (ctxt, DBG_SYSCALL, "sys_putWordItem: item=%p\n", item); -+ -+ if (item == NULL) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAILED, list, (void *) NULL, null_valist); -+ return; -+ } -+ -+ PRINTF2 (ctxt, DBG_SYSCALL, "sys_putWordItem: storing value=%08x at %p\n", value, &item->Value); -+ -+ PRINTF2 (ctxt, DBG_SYSCALL, "sys_putWordItem: item=%p value=%08x\n", item, value); -+ -+ suword_noerr ((E3_int32 *) &item->Value, value); /* write "value" into item */ -+ -+ sys_putItemBack (sp, list, item); -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+} -+ -+static void -+sys_putBlockItem (ELAN3_CTXT *ctxt, int list, E3_uint32 *ptr) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ SYS_BLOCK_ITEM *item; -+ label_t ljp; -+ E3_uint32 *source; -+ E3_uint32 *dest; -+ -+ PRINTF2 (ctxt, DBG_SYSCALL, "sys_putBlockItem: list=%x ptr=%p\n", list, ptr); -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljp)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, list, (void *) NULL, null_valist); -+ return; -+ } -+ -+ item = sys_getItem (sp, LIST_FREE_BLOCK); /* get an item from the freelist. */ -+ -+ if (item == NULL) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAILED, list, (void *) NULL, null_valist); -+ return; -+ } -+ -+ /* -+ * The block will have been read using 64 bit reads, since we have -+ * to write it to user memory using 32 bit writes, we need to perform -+ * an endian swap on the Ultrasparc. -+ */ -+ dest = (E3_uint32 *) fuptr_noerr ((void **) &item->Pointer); -+ source = (E3_uint32 *) ptr; -+ -+ PRINTF2 (ctxt, DBG_SYSCALL, "sys_putBlockItem: item=%p dest=%p\n",item, dest); -+ PRINTF4 (ctxt, DBG_SYSCALL, " %08x %08x %08x %08x\n", -+ source[0^WordEndianFlip], source[1^WordEndianFlip], source[2^WordEndianFlip], source[3^WordEndianFlip]); -+ PRINTF4 (ctxt, DBG_SYSCALL, " %08x %08x %08x %08x\n", -+ source[4^WordEndianFlip], source[5^WordEndianFlip], source[6^WordEndianFlip], source[7^WordEndianFlip]); -+ -+ suword_noerr ((E3_int32 *) &dest[7], (E3_int32) source[7^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[6], (E3_int32) source[6^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[5], (E3_int32) source[5^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[4], (E3_int32) source[4^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[3], (E3_int32) source[3^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[2], (E3_int32) source[2^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[1], (E3_int32) source[1^WordEndianFlip]); -+ suword_noerr ((E3_int32 *) &dest[0], (E3_int32) source[0^WordEndianFlip]); -+ -+ sys_putItemBack (sp, list, item); /* chain onto list of items. */ -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+} -+ -+static void -+sys_freeWordItem (ELAN3_CTXT *ctxt, void *itemp) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ label_t ljp; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljp)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, LIST_FREE_WORD, (void *) NULL, null_valist); -+ return; -+ } -+ -+ sys_putItemBack (sp, LIST_FREE_WORD, itemp); -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+} -+ -+static void -+sys_freeBlockItem (ELAN3_CTXT *ctxt, void *itemp) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ SYS_BLOCK_ITEM *item = (SYS_BLOCK_ITEM *)itemp; -+ E3_uint32 *dest; -+ label_t ljp; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljp)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, LIST_FREE_BLOCK, (void *) NULL, null_valist); -+ return; -+ } -+#ifdef DEBUG_PRINTF -+ dest = (E3_uint32 *) fuptr_noerr ((void **) &item->Pointer); -+ -+ PRINTF2 (ctxt, DBG_SYSCALL, "sys_freeBlockItem: item=%p dest=%p\n", item, dest); -+ PRINTF4 (ctxt, DBG_SYSCALL, " %08x %08x %08x %08x\n", -+ fuword_noerr ((int *) &dest[0]), fuword_noerr ((int *) &dest[1]), -+ fuword_noerr ((int *) &dest[2]), fuword_noerr ((int *) &dest[3])); -+ PRINTF4 (ctxt, DBG_SYSCALL, " %08x %08x %08x %08x\n", -+ fuword_noerr ((int *) &dest[4]), fuword_noerr ((int *) &dest[5]), -+ fuword_noerr ((int *) &dest[6]), fuword_noerr ((int *) &dest[7])); -+#endif -+ -+ sys_putItemBack (sp, LIST_FREE_BLOCK, itemp); -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+} -+ -+static void -+sys_putbackItem (ELAN3_CTXT *ctxt, int list, void *itemp) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ label_t ljp; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljp)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, list, (void *) NULL, null_valist); -+ return; -+ } -+ -+ sys_putItemFront (sp, list, itemp); -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+} -+ -+static int -+sys_countItems (ELAN3_CTXT *ctxt, int list) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ int count = 0; -+ void *item; -+ label_t ljb; -+ -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljb)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ sys_exception (ctxt, EXCEPTION_SWAP_FAULT, list, (void *) NULL, null_valist); -+ return (0); -+ } -+ -+ for (item = (void *) fuptr_noerr ((void **) &sp->ItemListsHead[list]); -+ item != NULL; -+ item = (void *) fuptr_noerr ((void **) item)) -+ { -+ count++; -+ } -+ -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ return (count); -+} -+ -+ -+long sys_longTime; -+long sys_shortTime; -+int sys_waitTicks; -+int sys_maxBackoff; -+ -+#define SYS_LONG_TIME MAX((hz * 5) / 1000, 1) /* 5 ms */ -+#define SYS_SHORT_TIME MAX((hz * 2) / 1000, 1) /* 2 ms */ -+#define SYS_WAIT_TICKS MAX((hz * 1) / 1000, 1) /* 1 ms - backoff granularity */ -+#define SYS_MAX_BACKOFF MAX((hz * 5) / 1000, 1) /* 5 ms - max backoff for "nacked" packets*/ -+#define SYS_TIMEOUT_BACKOFF MAX((hz * 10) / 1000, 1) /* 10 ms - backoff for output timeout (point to point) */ -+#define SYS_BCAST_BACKOFF MAX((hz * 50) / 1000, 1) /* 50 ms - backoff for output timeout (broadcast) */ -+#define SYS_NETERR_BACKOFF MAX((hz * 10) / 1000, 1) /* 10 ms - delay for network error in dma data */ -+ -+static void -+sys_backoffWait (ELAN3_CTXT *ctxt, int ticks) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ long t; -+ -+ spin_lock (&sctx->WaitLock); -+ -+ t = lbolt - sctx->Time; -+ -+ if (sys_longTime == 0) sys_longTime = SYS_LONG_TIME; -+ if (sys_shortTime == 0) sys_shortTime = SYS_SHORT_TIME; -+ if (sys_waitTicks == 0) sys_waitTicks = SYS_WAIT_TICKS; -+ if (sys_maxBackoff == 0) sys_maxBackoff = SYS_MAX_BACKOFF; -+ -+ if (t > sys_longTime) /* It's a long time since the last trap */ -+ sctx->Backoff = 0; /* so set the backoff back down to 0 */ -+ -+ if (ticks) -+ { -+ PRINTF2 (ctxt, DBG_DPROC, "sys_backoffWait : Waiting - %d ticks [%lx]\n", ticks, t); -+ kcondvar_timedwait (&sctx->NetworkErrorWait, &sctx->WaitLock, NULL, lbolt + ticks); -+ } -+ else if (sctx->Armed) -+ { -+ if (t < sys_shortTime) /* It's been a short time since the last */ -+ { /* trap, so increase the backoff */ -+ sctx->Backoff++; -+ -+ if (sctx->Backoff > sys_maxBackoff) -+ sctx->Backoff = sys_maxBackoff; -+ } -+ -+ PRINTF2 (ctxt, DBG_DPROC, "sys_backoffWait : Waiting - %d [%lx]\n", sctx->Backoff, t); -+ -+ if (sctx->Backoff) -+ kcondvar_timedwaitsig (&sctx->NetworkErrorWait, &sctx->WaitLock, NULL, lbolt + sctx->Backoff * sys_waitTicks); -+ -+ sctx->Armed = 0; -+ } -+ else -+ { -+ PRINTF1 (ctxt, DBG_DPROC, "sys_backoffWait : Not Waiting - %d\n", sctx->Backoff); -+ -+ } -+ sctx->Time = lbolt; -+ -+ spin_unlock (&sctx->WaitLock); -+} -+ -+static int -+trapSize (int proc) -+{ -+ switch (proc) -+ { -+ case DMA_PROC: return (sizeof (DMA_TRAP)); -+ case THREAD_PROC: return (sizeof (THREAD_TRAP)); -+ case COMMAND_PROC: return (sizeof (COMMAND_TRAP)); -+ case INPUT_PROC: return (sizeof (INPUT_TRAP)); -+ default: return (0); -+ } -+} -+ -+static int -+sys_exception (ELAN3_CTXT *ctxt, int type, int proc, void *trapp, va_list ap) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ int res; -+ -+ PRINTF2 (ctxt, DBG_SYSCALL, "sys_exception: type %d proc %d\n", type, proc); -+ -+ switch (type) -+ { -+ case EXCEPTION_INVALID_ADDR: -+ { -+ E3_FaultSave_BE *faultSave = va_arg (ap, E3_FaultSave_BE *); -+ int res = va_arg (ap, int); -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), faultSave, res, 0); -+ break; -+ } -+ -+ case EXCEPTION_UNIMP_INSTR: -+ { -+ E3_uint32 instr = va_arg (ap, E3_uint32); -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, 0, instr); -+ break; -+ } -+ -+ case EXCEPTION_INVALID_PROCESS: -+ { -+ E3_uint32 vproc = va_arg (ap, E3_uint32); -+ int res = va_arg (ap, int); -+ -+ switch (proc) -+ { -+ case DMA_PROC: -+ if (sctx->Flags & ELAN3_SYS_FLAG_DMA_BADVP) -+ { -+ DMA_TRAP *trap = (DMA_TRAP *) trapp; -+ -+ if (trap->Desc.s.dma_direction != DMA_WRITE) -+ trap->Desc.s.dma_srcEvent = trap->Desc.s.dma_destEvent; -+ -+ trap->Desc.s.dma_direction = DMA_WRITE; -+ trap->Desc.s.dma_size = 0; -+ trap->Desc.s.dma_source = (E3_Addr) 0; -+ trap->Desc.s.dma_dest = (E3_Addr) 0; -+ trap->Desc.s.dma_destEvent = (E3_Addr) 0; -+ trap->Desc.s.dma_destCookieVProc = 0; -+ trap->Desc.s.dma_srcCookieVProc = 0; -+ -+ return (OP_IGNORE); -+ } -+ break; -+ -+ case THREAD_PROC: -+ if (sctx->Flags & ELAN3_SYS_FLAG_THREAD_BADVP) -+ { -+ THREAD_TRAP *trap = (THREAD_TRAP *) trapp; -+ -+ trap->TrapBits.s.PacketAckValue = E3_PAckError; -+ -+ return (OP_IGNORE); -+ } -+ break; -+ } -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, res, vproc); -+ break; -+ } -+ -+ case EXCEPTION_FAULTED: -+ { -+ E3_Addr addr = va_arg (ap, E3_Addr); -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, 0, addr); -+ break; -+ } -+ -+ case EXCEPTION_QUEUE_OVERFLOW: -+ { -+ E3_FaultSave_BE *faultSave = va_arg (ap, E3_FaultSave_BE *); -+ int trapType = va_arg (ap, int); -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), faultSave, 0, trapType); -+ break; -+ } -+ -+ case EXCEPTION_COMMAND_OVERFLOW: -+ { -+ int count = va_arg (ap, int); -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, 0, count); -+ break; -+ } -+ -+ case EXCEPTION_CHAINED_EVENT: -+ { -+ E3_Addr addr = va_arg (ap, E3_Addr); -+ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, 0, addr); -+ break; -+ } -+ -+ case EXCEPTION_DMA_RETRY_FAIL: -+ case EXCEPTION_PACKET_TIMEOUT: -+ if (proc != DMA_PROC) -+ sys_backoffWait (ctxt, SYS_TIMEOUT_BACKOFF); -+ else -+ { -+ DMA_TRAP *trap = (DMA_TRAP *) trapp; -+ -+ if (sctx->Flags & ELAN3_SYS_FLAG_DMAFAIL) -+ { -+ E3_BlockCopyEvent *event; -+ -+ if (trap->Desc.s.dma_direction != DMA_WRITE) -+ trap->Desc.s.dma_srcEvent = trap->Desc.s.dma_destEvent; -+ -+ /* change the source word to be E3_EVENT_FAILED */ -+ if ((event = (E3_BlockCopyEvent *) elan3mmu_mainaddr (ctxt->Elan3mmu, trap->Desc.s.dma_srcEvent)) == NULL) -+ { -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, 0, 0); -+ break; -+ } -+ -+ suword (&event->ev_Source, E3_EVENT_FAILED); -+ wmb(); mmiob(); -+ -+ trap->Desc.s.dma_direction = DMA_WRITE; -+ trap->Desc.s.dma_size = 0; -+ trap->Desc.s.dma_source = (E3_Addr) 0; -+ trap->Desc.s.dma_dest = (E3_Addr) 0; -+ trap->Desc.s.dma_destEvent = (E3_Addr) 0; -+ trap->Desc.s.dma_destCookieVProc = 0; -+ trap->Desc.s.dma_srcCookieVProc = 0; -+ -+ return (OP_IGNORE); -+ } -+ -+ if (type == EXCEPTION_DMA_RETRY_FAIL) -+ sys_backoffWait (ctxt, 0); -+ else -+ { -+ ELAN_LOCATION location; -+ -+ krwlock_read (&ctxt->VpLock); -+ location = ProcessToLocation (ctxt, NULL, trap->Desc.s.dma_direction == DMA_WRITE ? -+ trap->Desc.s.dma_destVProc : trap->Desc.s.dma_srcVProc, NULL); -+ krwlock_done (&ctxt->VpLock); -+ -+ sys_backoffWait (ctxt, location.loc_node == ELAN3_INVALID_NODE ? SYS_BCAST_BACKOFF : SYS_TIMEOUT_BACKOFF); -+ } -+ } -+ return (OP_IGNORE); -+ -+ case EXCEPTION_NETWORK_ERROR: -+ { -+ INPUT_TRAP *trap = (INPUT_TRAP *) trapp; -+ NETERR_RESOLVER **rvpp = va_arg (ap, NETERR_RESOLVER **); -+ -+ ASSERT (trap->State == CTXT_STATE_NETWORK_ERROR); -+ -+ if (! (sctx->Flags & ELAN3_SYS_FLAG_NETERR) && (trap->DmaIdentifyTransaction || trap->ThreadIdentifyTransaction)) -+ { -+ if ((*rvpp) != (NETERR_RESOLVER *) NULL) -+ res = (*rvpp)->Status; -+ else if ((res = QueueNetworkErrorResolver (ctxt, trap, rvpp)) == ESUCCESS) -+ { -+ /* Successfully queued the network error resolver */ -+ return (OP_HANDLED); -+ } -+ -+ /* network error resolution has failed - either a bad cookie or */ -+ /* an rpc error has occured */ -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, res, 0); -+ } -+ else -+ { -+ /* Must be an overlaped dma packet. Must wait long enough to -+ * ensure that the sending dma'er has tried to send the next -+ * packet and had it discarded. In the real world this should -+ * be greater than an output timeout. (About 8mSec) */ -+ -+ sys_backoffWait (ctxt, SYS_NETERR_BACKOFF); -+ -+ /* set this inputter state to be ok, since we've been called -+ * by the lwp it will lower the context filter for us, so -+ * re-enabling the inputter, note we don't need to execute -+ * any of the packet since the dma process will re-transmit -+ * it after receiving a nack for the next packet */ -+ trap->State = CTXT_STATE_OK; -+ -+ return (OP_HANDLED); -+ } -+ break; -+ } -+ -+ default: -+ sys_addException (sctx, type, proc, trapp, trapSize(proc), NULL, 0, 0); -+ break; -+ } -+ -+ if (type != EXCEPTION_DEBUG) -+#ifdef LINUX -+#ifdef NO_NPTL -+ psignal (CURPROC()->p_opptr, sctx->signal); -+#else -+ psignal (CURPROC()->parent, sctx->signal); -+#endif -+#else -+ psignal (CURPROC(), sctx->signal); -+#endif -+ return (OP_HANDLED); -+} -+ -+static int -+sys_event (ELAN3_CTXT *ctxt, E3_uint32 cookie, int flag) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ -+ cookie_fire_cookie (sctx->Table, cookie); -+ -+ return (OP_HANDLED); -+} -+ -+static void -+sys_swapin (ELAN3_CTXT *ctxt) -+{ -+ PRINTF0 (ctxt, DBG_SYSCALL, "sys_swapin\n"); -+} -+ -+static void -+sys_swapout (ELAN3_CTXT *ctxt) -+{ -+ PRINTF0 (ctxt, DBG_SYSCALL, "sys_swapout\n"); -+} -+ -+static void -+sys_freePrivate (ELAN3_CTXT *ctxt) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ -+ cookie_free_table (sctx->Table); -+ -+ kmutex_destroy (&sctx->Lock); -+ spin_lock_destroy (&sctx->WaitLock); -+ kcondvar_destroy (&sctx->NetworkErrorWait); -+ -+ KMEM_FREE (sctx, sizeof (SYS_CTXT)); -+ ctxt->Private = NULL; -+} -+ -+static int -+sys_checkThisDma (ELAN3_CTXT *ctxt, NETERR_FIXUP *nef, E3_DMA *dma) -+{ -+ E3_DmaType type; -+ E3_uint32 cookie; -+ E3_uint32 cvproc; -+ int ignore; -+ int match; -+ -+ type.type = fuword_noerr ((int *) &dma->dma_type); -+ -+ if (type.s.direction == DMA_WRITE) -+ { -+ cookie = fuword_noerr ((int *) &dma->dma_srcCookieVProc); -+ cvproc = fuword_noerr ((int *) &dma->dma_destCookieVProc); -+ } -+ else -+ { -+ cookie = fuword_noerr ((int *) &dma->dma_destCookieVProc); -+ cvproc = fuword_noerr ((int *) &dma->dma_srcCookieVProc); -+ } -+ -+ PRINTF5 (ctxt, DBG_NETERR, "sys_checkThisDma: dir = %d cookie = %08x cvproc = %08x CookieVProc %08x DstProcess %04x\n", -+ type.s.direction, cookie, cvproc, nef->Message.CookieVProc, nef->Message.DstProcess); -+ -+ /* A DMA matches a network errror fixup if it's going to the right place (or is a broadcast) -+ * and the approriate cookie matches, except that we ignore DMA's which don't have a destEvent -+ * since they don't have any atomic behaviour (though they still send the identify) */ -+ -+ ignore = (type.s.direction == DMA_WRITE && cookie == 0 && -+ fuword_noerr ((int *) &dma->dma_destEvent) == 0); -+ match = (nef->Message.CookieVProc == cookie && -+ (nef->Message.DstProcess == (cvproc & DMA_PROCESS_MASK) || nef->Message.WaitForEop)); -+ -+ PRINTF2 (ctxt, DBG_NETERR, " -> %s %s\n", ignore ? "ignore" : match ? "matched" : "not-matched", nef->Message.WaitForEop ? "wait for eop" : ""); -+ -+ if (match && !ignore && !nef->Message.WaitForEop) -+ { -+ PRINTF0 (ctxt, DBG_NETERR, "sys_checkThisDma: nuking the dma\n"); -+ -+ /* NOTE - we access the dma descriptor backwards since it could exist in sdram */ -+ if (type.s.direction != DMA_WRITE) -+ suword_noerr ((int *) &dma->dma_srcEvent, 0); -+ -+ suword_noerr ((int *) &dma->dma_destEvent, 0); -+ suword_noerr ((int *) &dma->dma_dest, 0); -+ suword_noerr ((int *) &dma->dma_source, 0); -+ suword_noerr ((int *) &dma->dma_size, 0); -+ -+ if (type.s.direction != DMA_WRITE) -+ suword_noerr ((int *) &dma->dma_type, fuword_noerr ((int *) &dma->dma_type) & E3_DMA_CONTEXT_MASK); -+ -+ wmb(); mmiob(); -+ } -+ -+ return (match && !ignore); -+} -+ -+static int -+sys_fixupNetworkError (ELAN3_CTXT *ctxt, NETERR_FIXUP *nef) -+{ -+ SYS_CTXT *sctx = (SYS_CTXT *) ctxt->Private; -+ SYS_SWAP_SPACE *sp = sctx->Swap; -+ int matched = 0; -+ SYS_WORD_ITEM *wordp; -+ SYS_BLOCK_ITEM *blockp; -+ label_t ljb; -+ int res; -+ -+ PRINTF3 (ctxt, DBG_NETERR, "sys_fixupnetworkError %08x %08x %08x\n", -+ nef->Message.CookieAddr, nef->Message.CookieVProc, nef->Message.NextCookie); -+ -+ if (nef->Message.CookieAddr == (E3_Addr) 0) /* It's a DMA which requires fixing up */ -+ { -+ kmutex_lock (&sctx->Lock); -+ -+ if (on_fault (&ljb)) -+ res = EFAULT; -+ else -+ { -+ /* scan the dma ptr list */ -+ for (wordp = (SYS_WORD_ITEM *) fuptr_noerr ((void **) &sp->ItemListsHead[LIST_DMA_PTR]); -+ wordp != NULL; -+ wordp = (SYS_WORD_ITEM *) fuptr_noerr ((void **) &wordp->Next)) -+ { -+ E3_uint32 value = fuword_noerr ((int *) &wordp->Value); -+ E3_DMA *dma = (E3_DMA *) elan3mmu_mainaddr (ctxt->Elan3mmu, value); -+ -+ PRINTF3 (ctxt, DBG_NETERR, "sys_fixupnetworkError: check block item %p Value %08x dma %p\n", wordp, value, dma); -+ -+ matched += sys_checkThisDma (ctxt, nef, dma); -+ } -+ -+ /* scan the dma desc list */ -+ for (blockp = (SYS_BLOCK_ITEM *) fuptr_noerr ((void **) &sp->ItemListsHead[LIST_DMA_DESC]); -+ blockp != NULL; -+ blockp = (SYS_BLOCK_ITEM *) fuptr_noerr ((void **) &blockp->Next)) -+ { -+ E3_DMA *dma = (E3_DMA *) fuptr_noerr ((void *) &blockp->Pointer); -+ -+ PRINTF2 (ctxt, DBG_NETERR, "sys_fixupnetworkError: check block item %p Pointer %p\n", blockp, dma); -+ -+ matched += sys_checkThisDma (ctxt, nef, dma); -+ } -+ -+ /* If we've still not found it, then check the command port item */ -+ /* it MUST be present as a command waiting to be executed, as */ -+ /* otherwise it could have already happened and we will claim to */ -+ /* have found it, but not realy */ -+ if (ctxt->CommandPortItem != NULL) -+ { -+ E3_DMA *dma = (E3_DMA *) fuptr_noerr ((void *) &((SYS_BLOCK_ITEM *) ctxt->CommandPortItem)->Pointer); -+ -+ if (sys_checkThisDma (ctxt, nef, dma)) -+ { -+ printk ("!!! it's the command port item - need to ensure that the command exists\n"); -+ matched++; -+ } -+ } -+ -+ res = matched ? ESUCCESS : ESRCH; -+ } -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ if (matched > 1) -+ ElanException (ctxt, EXCEPTION_COOKIE_ERROR, DMA_PROC, NULL, NULL, nef->Message.CookieVProc); -+ } -+ else /* It's a thread which requires fixing up */ -+ { -+ E3_int32 *cookiePtr = (E3_int32 *) elan3mmu_mainaddr (ctxt->Elan3mmu, nef->Message.CookieAddr); -+ E3_uint32 curval = fuword_noerr (cookiePtr); -+ -+ if (curval == nef->Message.CookieVProc) /* thread doesn't think it's been done */ -+ { -+ if (! nef->Message.WaitForEop) -+ { -+ suword_noerr (cookiePtr, nef->Message.NextCookie); -+ mb(); mmiob(); -+ } -+ -+ res = ESUCCESS; -+ } -+ else /* thread thinks that it's been executed */ -+ { -+ res = ESRCH; -+ } -+ } -+ -+ CompleteNetworkErrorFixup (ctxt, nef, res); -+ -+ return (OP_HANDLED); -+} -+ -+ -+static int -+sys_startFaultCheck (ELAN3_CTXT *ctxt) -+{ -+ return (0); -+} -+ -+static void -+sys_endFaultCheck (ELAN3_CTXT *ctxt) -+{ -+ wmb(); -+} -+ -+static E3_uint8 -+sys_load8 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ E3_uint8 *maddr = (E3_uint8 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ return (fubyte_noerr (maddr)); -+} -+ -+static void -+sys_store8 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint8 val) -+{ -+ E3_uint8 *maddr = (E3_uint8 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ subyte_noerr (maddr, val); -+ wmb(); mmiob(); -+} -+ -+static E3_uint16 -+sys_load16 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ E3_uint16 *maddr = (E3_uint16 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ return (fusword_noerr (maddr)); -+} -+ -+static void -+sys_store16 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint16 val) -+{ -+ E3_uint16 *maddr = (E3_uint16 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ susword_noerr (maddr, val); -+ wmb(); mmiob(); -+} -+ -+static E3_uint32 -+sys_load32 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ E3_uint32 *maddr = (E3_uint32 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ return (fuword_noerr (maddr)); -+} -+ -+static void -+sys_store32 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint32 val) -+{ -+ E3_uint32 *maddr = (E3_uint32 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ suword_noerr (maddr, val); -+ wmb(); mmiob(); -+} -+ -+static E3_uint64 -+sys_load64 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ E3_uint64 *maddr = (E3_uint64 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ return (fulonglong_noerr ((long long *) maddr)); -+} -+ -+static void -+sys_store64 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint64 val) -+{ -+ E3_uint64 *maddr = (E3_uint64 *) elan3mmu_mainaddr (ctxt->Elan3mmu, addr); -+ -+ sulonglong_noerr ((long long *) maddr, val); -+ wmb(); mmiob(); -+} -+ -+ -+void -+sys_addException (SYS_CTXT *sctx, int type, int proc, caddr_t trapp, int size, -+ E3_FaultSave_BE *faultSave, u_long res, u_long value) -+{ -+ SYS_EXCEPTION *ex_ptr; -+ int front; -+ int back; -+ int count; -+ label_t ljp; -+ -+ PRINTF4 (DBG_DEVICE, DBG_FN, "sys_addException: type %d proc %d res %ld value %ld\n", -+ type, proc, res, value); -+ -+ KMEM_ZALLOC (ex_ptr, SYS_EXCEPTION *, sizeof (SYS_EXCEPTION), TRUE); -+ -+ if (ex_ptr != NULL) -+ { -+ bzero ((caddr_t) ex_ptr, sizeof (SYS_EXCEPTION)); -+ -+ ex_ptr->Type = type; -+ ex_ptr->Proc = proc; -+ ex_ptr->Res = res; -+ ex_ptr->Value = value; -+ -+ if (trapp && size) -+ bcopy (trapp, (caddr_t) &ex_ptr->Union, size); -+ if (faultSave) -+ bcopy ((caddr_t) faultSave, (caddr_t) &ex_ptr->FaultArea, sizeof (E3_FaultSave_BE)); -+ } -+ -+ kmutex_lock (&sctx->Lock); -+ if (! on_fault (&ljp)) -+ { -+ front = fuword_noerr (&sctx->Exceptions->Front); -+ back = fuword_noerr (&sctx->Exceptions->Back); -+ count = fuword_noerr (&sctx->Exceptions->Count); -+ -+ if (count <= 0 || front < 0 || back < 0 || front >= count || back >= count) -+ suword_noerr (&sctx->Exceptions->Overflow, fuword_noerr (&sctx->Exceptions->Overflow) + 1); -+ else if (((front+1) % count ) == back) -+ suword_noerr (&sctx->Exceptions->Overflow, fuword_noerr (&sctx->Exceptions->Overflow) + 1); -+ else -+ { -+ if (ex_ptr != NULL) -+ copyout_noerr ((caddr_t) ex_ptr, (caddr_t) &sctx->Exceptions->Exceptions[front], sizeof (SYS_EXCEPTION)); -+ else -+ { -+ suword_noerr (&sctx->Exceptions->Exceptions[front].Type, EXCEPTION_ENOMEM); -+ suword_noerr (&sctx->Exceptions->Exceptions[front].Proc, 0); -+ } -+ suword_noerr (&sctx->Exceptions->Front, (front + 1) % count); -+ } -+ -+ /* always reset the magic number in case it's been overwritten */ -+ /* so that 'edb' can find the exception page in the core file */ -+ suword_noerr (&sctx->Exceptions->Magic, SYS_EXCEPTION_MAGIC); -+ } -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ if (ex_ptr != NULL) -+ KMEM_FREE (ex_ptr, sizeof (SYS_EXCEPTION)); -+} -+ -+int -+sys_getException (SYS_CTXT *sctx, SYS_EXCEPTION *ex) -+{ -+ int front; -+ int back; -+ int count; -+ int res; -+ label_t ljp; -+ -+ if (sctx->Exceptions == NULL) -+ return (EINVAL); -+ -+ kmutex_lock (&sctx->Lock); -+ if (on_fault (&ljp)) -+ { -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ return (EFAULT); -+ } -+ -+ front = fuword_noerr (&sctx->Exceptions->Front); -+ back = fuword_noerr (&sctx->Exceptions->Back); -+ count = fuword_noerr (&sctx->Exceptions->Count); -+ -+ if (count <= 0 || front < 0 || back < 0 || front >= count || back >= count || back == front) -+ res = EINVAL; -+ else -+ { -+ copyin_noerr ((caddr_t) &sctx->Exceptions->Exceptions[back], (caddr_t) ex, sizeof (SYS_EXCEPTION)); -+ suword_noerr (&sctx->Exceptions->Back, (back+1) % count); -+ -+ res = ESUCCESS; -+ } -+ no_fault(); -+ kmutex_unlock (&sctx->Lock); -+ -+ return (res); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/eventcookie.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/eventcookie.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/eventcookie.c 2005-06-01 23:12:54.585441232 -0400 -@@ -0,0 +1,324 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: eventcookie.c,v 1.7 2003/08/13 10:03:03 fabien Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/eventcookie.c,v $*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static EVENT_COOKIE_TABLE *cookie_tables; -+static spinlock_t cookie_table_lock; -+ -+/* -+ * cookie_drop_entry: -+ * drop the reference to a cookie held -+ * by the cookie table -+ */ -+static void -+cookie_drop_entry (EVENT_COOKIE_ENTRY *ent) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&ent->ent_lock, flags); -+ if (--ent->ent_ref != 0) -+ { -+ ent->ent_fired = ent->ent_cookie; -+ kcondvar_wakeupall (&ent->ent_wait, &ent->ent_lock); -+ -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ } -+ else -+ { -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ -+ spin_lock_destroy (&ent->ent_lock); -+ kcondvar_destroy (&ent->ent_wait); -+ -+ KMEM_FREE (ent, sizeof (EVENT_COOKIE_ENTRY)); -+ } -+} -+ -+void -+cookie_init() -+{ -+ spin_lock_init (&cookie_table_lock); -+} -+ -+void -+cookie_fini() -+{ -+ spin_lock_destroy (&cookie_table_lock); -+} -+ -+EVENT_COOKIE_TABLE * -+cookie_alloc_table (unsigned long task, unsigned long handle) -+{ -+ EVENT_COOKIE_TABLE *tbl, *ntbl; -+ -+ KMEM_ZALLOC (ntbl, EVENT_COOKIE_TABLE *, sizeof (EVENT_COOKIE_TABLE), TRUE); -+ -+ if (ntbl == NULL) -+ return (NULL); -+ -+ spin_lock (&cookie_table_lock); -+ -+ for (tbl = cookie_tables; tbl; tbl = tbl->tbl_next) -+ if (tbl->tbl_task == task && tbl->tbl_handle == handle) -+ break; -+ -+ if (tbl != NULL) -+ tbl->tbl_ref++; -+ else -+ { -+ spin_lock_init (&ntbl->tbl_lock); -+ -+ ntbl->tbl_task = task; -+ ntbl->tbl_handle = handle; -+ ntbl->tbl_ref = 1; -+ ntbl->tbl_entries = NULL; -+ -+ if ((ntbl->tbl_next = cookie_tables) != NULL) -+ cookie_tables->tbl_prev = ntbl; -+ cookie_tables = ntbl; -+ ntbl->tbl_prev = NULL; -+ } -+ spin_unlock (&cookie_table_lock); -+ -+ if (tbl == NULL) -+ return (ntbl); -+ else -+ { -+ KMEM_FREE (ntbl, sizeof (EVENT_COOKIE_TABLE)); -+ return (tbl); -+ } -+} -+ -+void -+cookie_free_table (EVENT_COOKIE_TABLE *tbl) -+{ -+ EVENT_COOKIE_ENTRY *ent; -+ -+ spin_lock (&cookie_table_lock); -+ if (tbl->tbl_ref > 1) -+ { -+ tbl->tbl_ref--; -+ spin_unlock (&cookie_table_lock); -+ return; -+ } -+ -+ if (tbl->tbl_prev) -+ tbl->tbl_prev->tbl_next = tbl->tbl_next; -+ else -+ cookie_tables = tbl->tbl_next; -+ if (tbl->tbl_next) -+ tbl->tbl_next->tbl_prev = tbl->tbl_prev; -+ -+ spin_unlock (&cookie_table_lock); -+ -+ /* NOTE - table no longer visible to other threads -+ * no need to aquire tbl_lock */ -+ while ((ent = tbl->tbl_entries) != NULL) -+ { -+ if ((tbl->tbl_entries = ent->ent_next) != NULL) -+ ent->ent_next->ent_prev = NULL; -+ -+ cookie_drop_entry (ent); -+ } -+ spin_lock_destroy (&tbl->tbl_lock); -+ -+ KMEM_FREE (tbl, sizeof (EVENT_COOKIE_TABLE)); -+} -+ -+int -+cookie_alloc_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie) -+{ -+ EVENT_COOKIE_ENTRY *ent, *nent; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (nent, EVENT_COOKIE_ENTRY *, sizeof (EVENT_COOKIE_ENTRY), TRUE); -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ kcondvar_init (&nent->ent_wait); -+ spin_lock_init (&nent->ent_lock); -+ -+ nent->ent_ref = 1; -+ nent->ent_cookie = cookie; -+ -+ if ((nent->ent_next = tbl->tbl_entries) != NULL) -+ tbl->tbl_entries->ent_prev = nent; -+ tbl->tbl_entries = nent; -+ nent->ent_prev = NULL; -+ } -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ if (ent == NULL) -+ return (ESUCCESS); -+ else -+ { -+ KMEM_FREE (nent, sizeof (EVENT_COOKIE_ENTRY)); -+ return (EINVAL); -+ } -+} -+ -+int -+cookie_free_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie) -+{ -+ EVENT_COOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (EINVAL); -+ } -+ -+ if (ent->ent_prev == NULL) -+ tbl->tbl_entries = ent->ent_next; -+ else -+ ent->ent_prev->ent_next = ent->ent_next; -+ -+ if (ent->ent_next != NULL) -+ ent->ent_next->ent_prev = ent->ent_prev; -+ -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ cookie_drop_entry (ent); -+ -+ return (ESUCCESS); -+} -+ -+/* -+ * cookie_fire_cookie: -+ * fire the cookie - this is called from the event interrupt. -+ */ -+int -+cookie_fire_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie) -+{ -+ EVENT_COOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (EINVAL); -+ } -+ -+ spin_lock (&ent->ent_lock); -+ ent->ent_fired = cookie; -+ kcondvar_wakeupall (&ent->ent_wait, &ent->ent_lock); -+ spin_unlock (&ent->ent_lock); -+ -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ return (ESUCCESS); -+} -+ -+/* -+ * cookie_wait_cookie: -+ * deschedule on a cookie if it has not already fired. -+ * note - if the cookie is removed from the table, then -+ * we free it off when we're woken up. -+ */ -+int -+cookie_wait_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie) -+{ -+ EVENT_COOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (EINVAL); -+ } -+ -+ spin_lock (&ent->ent_lock); -+ spin_unlock (&tbl->tbl_lock); -+ -+ if (ent->ent_fired != 0) -+ { -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ return (ESUCCESS); -+ } -+ -+ ent->ent_ref++; -+ kcondvar_waitsig (&ent->ent_wait, &ent->ent_lock, &flags); -+ -+ if (--ent->ent_ref > 0) -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ else -+ { -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ -+ spin_lock_destroy (&ent->ent_lock); -+ kcondvar_destroy (&ent->ent_wait); -+ -+ KMEM_FREE (ent, sizeof (EVENT_COOKIE_ENTRY)); -+ } -+ return (ESUCCESS); -+} -+ -+int -+cookie_arm_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie) -+{ -+ EVENT_COOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (EINVAL); -+ } -+ -+ spin_lock (&ent->ent_lock); -+ ent->ent_fired = 0; -+ spin_unlock (&ent->ent_lock); -+ -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ return (ESUCCESS); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/iproc.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/iproc.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/iproc.c 2005-06-01 23:12:54.586441080 -0400 -@@ -0,0 +1,925 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: iproc.c,v 1.47 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/iproc.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+static int TrSizeTable[] = {0, 8, 16, 32, 64}; -+ -+static void ConvertTransactionToSetEvent (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_Addr Addr); -+static void SimulateBlockWrite (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap); -+static void SimulateWriteWord (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap); -+static void SimulateWriteDWord (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap); -+static void SimulateTraceRoute (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap); -+static void BumpInputterStats (ELAN3_DEV *dev, E3_IprocTrapHeader_BE *hdrp); -+ -+void -+HandleIProcTrap (ELAN3_DEV *dev, -+ int Channel, -+ E3_uint32 Pend, -+ sdramaddr_t FaultSaveOff, -+ sdramaddr_t TransactionsOff, -+ sdramaddr_t DataOff) -+{ -+ E3_IprocTrapHeader_BE Transaction0; -+ ELAN3_CTXT *ctxt; -+ INPUT_TRAP *trap; -+ register int i; -+ -+ /* -+ * Read the 1st set of transactions, so we can determine the -+ * context for the trap -+ */ -+ elan3_sdram_copyq_from_sdram (dev, TransactionsOff, (void *) &Transaction0, 16); -+ -+ BumpStat (dev, IProcTraps); -+ BumpInputterStats (dev, &Transaction0); -+ -+ if (Transaction0.s.TrTypeCntx.s.TypeCntxInvalid) -+ { -+ /* -+ * The context is not valid. This will occur if the packet -+ * trapped for an EopError with no IdentTrans or an error corrupted the context -+ * giving a CRC error on the first transaction and the Ack had not been returned. -+ */ -+ if (Transaction0.s.TrTypeCntx.s.LastTrappedTrans) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_IPROC, "iproc: Error on EOP without a good context, ignoring trap\n"); -+ } -+ else -+ { -+ /* Check that only crap has been received. If not then die. */ -+ if (! Transaction0.s.IProcTrapStatus.s.BadLength && -+ (Transaction0.s.IProcTrapStatus.Status & CRC_MASK) == CRC_STATUS_GOOD) -+ { -+ printk ("iproc: Did not have a valid context for the trap area.\n"); -+ printk ("iproc: TrTypeCntx=%x TrAddr=%x TrData0=%x IProcTrapStatus=%x\n", -+ Transaction0.s.TrTypeCntx.TypeContext, Transaction0.s.TrAddr, -+ Transaction0.s.TrData0, Transaction0.s.IProcTrapStatus.Status); -+ panic ("elan3: iproc did not have a valid context"); -+ /* NOTREACHED */ -+ } -+ PRINTF0 (DBG_DEVICE, DBG_IPROC, "iproc: First transaction is bad, ignoring trap\n"); -+ } -+ } -+ else -+ { -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, Transaction0.s.TrTypeCntx.s.Context); -+ -+ if (ctxt == NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "HandleIProcTrap: context %x invalid\n", -+ Transaction0.s.TrTypeCntx.s.Context); -+ -+ BumpStat (dev, InvalidContext); -+ } -+ else -+ { -+ trap = (Channel == 0) ? &ctxt->Input0Trap : &ctxt->Input1Trap; -+ -+ ASSERT (trap->State == CTXT_STATE_OK); -+ -+ trap->Transactions[0] = Transaction0; -+ -+ PRINTF1 (ctxt, DBG_INTR, "HandleIProcTrap: %s\n", IProcTrapString (&trap->Transactions[0], NULL)); -+ /* -+ * Copy the rest of the transactions into the trap area. -+ */ -+ for (i = 0; !(trap->Transactions[i].s.TrTypeCntx.s.LastTrappedTrans);) -+ { -+ if (++i >= MAX_TRAPPED_TRANS) -+ { -+ trap->Overflow = 1; -+ break; -+ } -+ -+ elan3_sdram_copyq_from_sdram (dev, TransactionsOff + i*sizeof (E3_IprocTrapHeader), (void *) &trap->Transactions[i], 16); -+ -+ PRINTF1 (ctxt, DBG_INTR, " %s\n", IProcTrapString (&trap->Transactions[i], NULL)); -+ -+ BumpInputterStats (dev, &trap->Transactions[i]); -+ } -+ -+ /* -+ * Remember the number of transactions we've copied. -+ */ -+ trap->NumTransactions = i+1; -+ -+ PRINTF1 (ctxt, DBG_INTR, " NumTransactions = %d\n", trap->NumTransactions); -+ -+ /* -+ * Copy all the data blocks in one go to let the Elan prefetcher work -+ */ -+ elan3_sdram_copyq_from_sdram (dev, DataOff, trap->DataBuffers, trap->NumTransactions*sizeof (E3_IprocTrapData)); -+ -+ /* -+ * Copy fault save area and clear out for next time round. -+ */ -+ elan3_sdram_copyq_from_sdram (dev, FaultSaveOff, (void *) &trap->FaultSave, 16); -+ elan3_sdram_zeroq_sdram (dev, FaultSaveOff, 16); -+ -+ if (ELAN3_OP_IPROC_TRAP (ctxt, trap, Channel) == OP_DEFER) -+ { -+ /* -+ * Mark the trap as valid and set the inputter state to -+ * raise the context filter. -+ */ -+ trap->State = CTXT_STATE_TRAPPED; -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ -+ SetInputterStateForContext (ctxt, Pend, NULL); -+ } -+ } -+ } -+} -+ -+void -+InspectIProcTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap) -+{ -+ int i; -+ int StatusValid; -+ -+ trap->AckSent = 0; -+ trap->BadTransaction = 0; -+ -+ trap->TrappedTransaction = NULL; -+ trap->TrappedDataBuffer = NULL; -+ trap->WaitForEopTransaction = NULL; -+ trap->WaitForEopDataBuffer = NULL; -+ trap->DmaIdentifyTransaction = NULL; -+ trap->ThreadIdentifyTransaction = NULL; -+ trap->LockQueuePointer = (E3_Addr) 0; -+ trap->UnlockQueuePointer = (E3_Addr) 0; -+ -+ /* -+ * Now scan all the transactions received -+ */ -+ for (i = 0; i < trap->NumTransactions ; i++) -+ { -+ E3_IprocTrapHeader_BE *hdrp = &trap->Transactions[i]; -+ E3_IprocTrapData_BE *datap = &trap->DataBuffers[i]; -+ -+ StatusValid = hdrp->s.TrTypeCntx.s.StatusRegValid != 0; -+ -+ if (StatusValid && hdrp->s.IProcTrapStatus.s.AckSent) /* Remember if we've sent the ack back */ -+ trap->AckSent = 1; -+ -+ if (hdrp->s.TrTypeCntx.s.LastTrappedTrans) /* Check for EOP */ -+ { -+ ASSERT (i == trap->NumTransactions - 1); -+ -+ switch (hdrp->s.IProcTrapStatus.Status & E3_IPS_EopType) -+ { -+ case EOP_GOOD: -+ /* if we get an EOP_GOOD then the outputer should have received a PAckOk. */ -+ /* unless it was a flood, in which case someone must have sent an ack */ -+ /* but not necessarily us */ -+ break; -+ -+ case EOP_BADACK: -+ BumpUserStat (ctxt, EopBadAcks); -+ -+ /* if we get an EOP_BADACK then the outputer did not receive a PAckOk even if -+ * we sent a PAckOk. We can clear tinfo.AckSent. */ -+ if (trap->AckSent == 1) -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "InspectIProcTrap: Network error destroyed PAckOk\n"); -+ trap->AckSent = 0; -+ } -+ break; -+ -+ case EOP_ERROR_RESET: -+ BumpUserStat (ctxt, EopResets); -+ -+ /* if we get an EOP_ERROR_RESET then the outputer may or may not have got a PAckOk. */ -+ trap->BadTransaction = 1; -+ break; -+ -+ default: -+ panic ("InspectIProcTrap: invalid EOP type in status register\n"); -+ /* NOTREACHED */ -+ } -+ continue; -+ } -+ -+ PRINTF2 (ctxt, DBG_IPROC, "InspectIProcTrap: %2d: %s\n", i, IProcTrapString (hdrp, datap)); -+ -+ if (! StatusValid) /* We're looking at transactions stored before the trap */ -+ { /* these should only be identifies and lock transactions */ -+ -+ if (hdrp->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) -+ panic ("InspectIProcTrap: writeblock transaction found in input trap header before trap occured\n"); -+ -+ switch (hdrp->s.TrTypeCntx.s.Type & TR_OPCODE_TYPE_MASK) -+ { -+ case TR_LOCKQUEUE & TR_OPCODE_TYPE_MASK: -+ if (trap->LockQueuePointer) /* Already seen a LOCKQUEUE transaction in this packet, */ -+ { /* the user program should not have done this !! */ -+ ElanException (ctxt, EXCEPTION_BAD_PACKET, INPUT_PROC, trap); -+ return; -+ } -+ -+ trap->LockQueuePointer = (E3_Addr) hdrp->s.TrAddr; /* Remember the queue pointer in case we need to unlock it */ -+ break; -+ -+ case TR_DMAIDENTIFY & TR_OPCODE_TYPE_MASK: -+ if (trap->DmaIdentifyTransaction || /* Already seen an identify transaction in this packet */ -+ trap->ThreadIdentifyTransaction) /* the user program should not have done this */ -+ { -+ ElanException (ctxt, EXCEPTION_BAD_PACKET, INPUT_PROC, trap); -+ return; -+ } -+ trap->DmaIdentifyTransaction = hdrp; -+ break; -+ -+ case TR_THREADIDENTIFY & TR_OPCODE_TYPE_MASK: -+ if (trap->DmaIdentifyTransaction || /* Already seen an identify transaction in this packet */ -+ trap->ThreadIdentifyTransaction) /* the user program should not have done this */ -+ { -+ ElanException (ctxt, EXCEPTION_BAD_PACKET, INPUT_PROC, trap); -+ return; -+ } -+ trap->ThreadIdentifyTransaction = hdrp; -+ break; -+ -+ default: -+ panic ("InspectIProcTrap: invalid transaction found in input trap header before trap occured\n"); -+ /* NOTREACHED */ -+ } -+ continue; -+ } -+ -+ if (StatusValid && trap->TrappedTransaction == NULL) /* Remember the transaction which caused the */ -+ { /* trap */ -+ trap->TrappedTransaction = hdrp; -+ trap->TrappedDataBuffer = datap; -+ } -+ -+ if(hdrp->s.IProcTrapStatus.s.BadLength || -+ ((hdrp->s.IProcTrapStatus.Status & CRC_MASK) == CRC_STATUS_ERROR) || -+ ((hdrp->s.IProcTrapStatus.Status & CRC_MASK) == CRC_STATUS_BAD)) -+ { -+ int j; -+ PRINTF0 (ctxt, DBG_IPROC, "InspectIProcTrap: transaction has a bad crc\n"); -+ for (j=0; jTrData[j], datap->TrData[j+1], datap->TrData[j+2], datap->TrData[j+3]); -+ trap->BadTransaction = 1; -+ continue; -+ } -+ -+ /* No more to do if it's a writeblock transaction */ -+ if (hdrp->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) -+ continue; -+ -+ -+ if (GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus) == MI_InputDoTrap && -+ (hdrp->s.TrTypeCntx.s.Type & TR_WAIT_FOR_EOP) != 0) -+ { -+ /* -+ * This is a wait for eop transaction that has trapped because the inputer -+ * then received a EopError. The next transaction saved should always be an -+ * EopError. -+ */ -+ PRINTF0 (ctxt, DBG_IPROC, "InspectIProcTrap: got a trapped WaitForEop transaction due to EopError\n"); -+ -+ trap->WaitForEopTransaction = hdrp; -+ trap->WaitForEopDataBuffer = datap; -+ continue; -+ } -+ -+ switch (hdrp->s.TrTypeCntx.s.Type & TR_OPCODE_TYPE_MASK) -+ { -+ case TR_UNLOCKQUEUE & TR_OPCODE_TYPE_MASK: -+ if (trap->UnlockQueuePointer) -+ { -+ ElanException (ctxt, EXCEPTION_BAD_PACKET, INPUT_PROC, trap); -+ return; -+ } -+ trap->UnlockQueuePointer = (E3_Addr) hdrp->s.TrAddr; -+ break; -+ } -+ } -+} -+ -+void -+ResolveIProcTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, NETERR_RESOLVER **rvpp) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ int res; -+ unsigned long flags; -+ -+ ASSERT (! CTXT_IS_KERNEL (ctxt)); -+ -+ BumpUserStat (ctxt, IProcTraps); -+ -+ InspectIProcTrap (ctxt, trap); -+ -+ /* -+ * fixup page fault if we've trapped because of one. -+ */ -+ if (trap->FaultSave.s.FaultContext != 0) -+ { -+ /* -+ * If it's a WRITEBLOCK transaction, then see if we remember faulting -+ * before it, and try and prefault in a sensible amount past it. -+ */ -+ int fixedFault = FALSE; -+ INPUT_FAULT_SAVE *entry; -+ INPUT_FAULT_SAVE **predp; -+ int npages; -+ -+ if ((trap->TrappedTransaction->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) != 0 && /* a DMA packet */ -+ trap->LockQueuePointer == (E3_Addr) 0 && /* but not a queueing DMA */ -+ trap->TrappedTransaction->s.TrAddr != 0) /* and not a DMA to 0 */ -+ { -+ spin_lock (&ctxt->InputFaultLock); -+ -+ for (predp = &ctxt->InputFaultList; (entry = *predp)->Next != NULL ; predp = &entry->Next) -+ { -+ if (entry->Addr == trap->TrappedTransaction->s.TrAddr) -+ break; -+ } -+ -+ *predp = entry->Next; -+ entry->Next = ctxt->InputFaultList; -+ ctxt->InputFaultList = entry; -+ -+ if (entry->Addr == trap->TrappedTransaction->s.TrAddr) -+ { -+ if ((entry->Count <<= 1) > MAX_INPUT_FAULT_PAGES) -+ entry->Count = MAX_INPUT_FAULT_PAGES; -+ } -+ else -+ { -+ entry->Count = MIN_INPUT_FAULT_PAGES; -+ } -+ -+ entry->Addr = trap->TrappedTransaction->s.TrAddr + (entry->Count * PAGESIZE); -+ npages = entry->Count; -+ -+ spin_unlock (&ctxt->InputFaultLock); -+ -+ if (elan3_pagefault (ctxt, &trap->FaultSave, npages) != ESUCCESS) -+ { -+ PRINTF2 (ctxt, DBG_IPROC, "ResolveIProcTrap: pagefaulting %d pages at %08x - failed\n", -+ npages, trap->TrappedTransaction->s.TrAddr); -+ } -+ else -+ { -+ PRINTF2 (ctxt, DBG_IPROC, "ResolveIProcTrap: pagefaulting %d pages at %08x - succeeded\n", -+ npages, trap->TrappedTransaction->s.TrAddr); -+ -+ fixedFault = TRUE; -+ } -+ } -+ -+ /* Workaround WRITEBLOCK transaction executed when LOCKQUEUE transaction missed */ -+ /* the packet will have been nacked */ -+ if ((trap->TrappedTransaction->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) && /* a DMA packet */ -+ trap->LockQueuePointer == 0 && trap->UnlockQueuePointer && /* a queueing DMA */ -+ trap->TrappedTransaction->s.TrAddr == trap->FaultSave.s.FaultAddress) /* and missed lockqueue */ -+ { -+ fixedFault = TRUE; -+ } -+ -+ if (! fixedFault) -+ { -+ if ((res = elan3_pagefault (ctxt, &trap->FaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_IPROC, "ResolveIProcTrap: elan3_pagefault failed at %x\n", -+ trap->FaultSave.s.FaultAddress); -+ ElanException (ctxt, EXCEPTION_INVALID_ADDR, INPUT_PROC, trap, &trap->FaultSave, res); -+ return; -+ } -+ } -+ } -+ -+ if (! trap->AckSent && trap->LockQueuePointer) /* Queued DMA */ -+ { /* The ack was not sent, so the queue will be locked. */ -+ SimulateUnlockQueue (ctxt, trap->LockQueuePointer, FALSE); /* We must unlock it. */ -+ } -+ -+ if (trap->AckSent && trap->BadTransaction) -+ { -+ if (trap->DmaIdentifyTransaction) -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: Dma identify needs network resultion\n"); -+ -+ BumpStat (dev, DmaIdentifyNetworkErrors); -+ BumpUserStat (ctxt, DmaIdentifyNetworkErrors); -+ -+ if (trap->WaitForEopTransaction) -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: have delayed wait for eop transaction\n"); -+ } -+ else if (trap->ThreadIdentifyTransaction) -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: Thread identify needs network resolution\n"); -+ -+ BumpStat (dev, ThreadIdentifyNetworkErrors); -+ BumpUserStat (ctxt, ThreadIdentifyNetworkErrors); -+ -+ if (trap->WaitForEopTransaction) -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: have delayed wait for eop transaction\n"); -+ } -+ else -+ { -+ BumpStat (dev, DmaNetworkErrors); -+ BumpUserStat (ctxt, DmaNetworkErrors); -+ } -+ } -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ if (! trap->AckSent) -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: ack not sent, lowering context filter\n"); -+ -+ trap->State = CTXT_STATE_OK; -+ } -+ else -+ { -+ if (trap->BadTransaction) -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: ack sent, waiting on bad transaction\n"); -+ trap->State = CTXT_STATE_NETWORK_ERROR; -+ } -+ else -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "ResolveIProcTrap: ack sent, waiting on packet to be re-executed\n"); -+ trap->State = CTXT_STATE_NEEDS_RESTART; -+ } -+ } -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ if (trap->AckSent && trap->BadTransaction) -+ ElanException (ctxt, EXCEPTION_NETWORK_ERROR, INPUT_PROC, trap, rvpp); -+} -+ -+int -+RestartIProcTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap) -+{ -+ PRINTF1 (ctxt, DBG_IPROC, "RestartIProc: %d transactions\n", trap->NumTransactions); -+ -+ if (trap->TrappedTransaction == NULL) /* No transaction trapped - probably a network */ -+ return (ESUCCESS); /* error */ -+ -+ while (! trap->TrappedTransaction->s.TrTypeCntx.s.LastTrappedTrans) -+ { -+ E3_IprocTrapHeader_BE *hdrp = trap->TrappedTransaction; -+ E3_IprocTrapData_BE *datap = trap->TrappedDataBuffer; -+ -+ ASSERT (hdrp->s.TrTypeCntx.s.StatusRegValid != 0); -+ -+ PRINTF2 (ctxt, DBG_IPROC, "RestartIProc: TrType=0x%x Status=0x%x\n", -+ hdrp->s.TrTypeCntx.TypeContext, hdrp->s.IProcTrapStatus.Status); -+ -+ if ((hdrp->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) != 0) -+ { -+ PRINTF1 (ctxt, DBG_IPROC, "RestartIProc: WRITEBLOCK : Addr %x\n", hdrp->s.TrAddr); -+ SimulateBlockWrite (ctxt, hdrp, datap); -+ } -+ else -+ { -+ switch (hdrp->s.TrTypeCntx.s.Type & TR_OPCODE_TYPE_MASK) -+ { -+ case TR_SETEVENT & TR_OPCODE_TYPE_MASK: -+ PRINTF1 (ctxt, DBG_IPROC, "RestartIProc: SETEVENT : %x\n", hdrp->s.TrAddr); -+ -+ if (GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus) != MI_InputDoTrap) -+ FixupEventTrap (ctxt, INPUT_PROC, trap, GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus), &trap->FaultSave, FALSE); -+ else if (hdrp->s.TrAddr) -+ { -+ if (IssueCommand (ctxt, offsetof (E3_CommandPort, SetEvent), hdrp->s.TrAddr, FALSE) != ISSUE_COMMAND_OK) -+ return (EAGAIN); -+ } -+ break; -+ -+ case TR_WRITEWORD & TR_OPCODE_TYPE_MASK: -+ SimulateWriteWord (ctxt, hdrp, datap); -+ break; -+ -+ case TR_WRITEDOUBLEWORD & TR_OPCODE_TYPE_MASK: -+ SimulateWriteDWord (ctxt, hdrp, datap); -+ break; -+ -+ case TR_UNLOCKQUEUE & TR_OPCODE_TYPE_MASK: -+ if (GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus) == MI_InputDoTrap) -+ ElanException (ctxt, EXCEPTION_BAD_PACKET, INPUT_PROC, trap); -+ else -+ { -+ switch (GET_STATUS_TRAPTYPE (hdrp->s.IProcTrapStatus)) -+ { -+ case MI_WaitForUnLockDescRead: -+ /* -+ * Fault occured on the read of the queue descriptor - since the ack -+ * has been sent we need to move the queue on one slot. -+ */ -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: TR_UNLOCKQUEUE : desc read fault\n"); -+ -+ SimulateUnlockQueue (ctxt, trap->LockQueuePointer, TRUE); -+ -+ if (IssueCommand (ctxt, offsetof (E3_CommandPort, SetEvent), -+ hdrp->s.TrAddr + E3_QUEUE_EVENT_OFFSET, FALSE) != ISSUE_COMMAND_OK) -+ { -+ /* Failed to issue setevent to complete queue unlock, since we've already unlocked */ -+ /* the queue, we should "convert" this transaction into a setevent transaction that */ -+ /* hasn't trapped */ -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: could not issue setevent for SimulateUnlockQueue\n"); -+ -+ ConvertTransactionToSetEvent (ctxt, hdrp, hdrp->s.TrAddr + E3_QUEUE_EVENT_OFFSET); -+ return (EAGAIN); -+ } -+ break; -+ -+ case MI_DoSetEvent: -+ /* -+ * Fault occured on either the write to unlock the queue or during -+ * processing of the event. Test the fault address against the -+ * queue address to find out which - in this case, since the ack -+ * has been sent we need to move the queue on one slot. -+ */ -+ if (trap->FaultSave.s.FaultAddress == trap->LockQueuePointer) -+ { -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: fixed unlock queue write to unlock fault\n"); -+ -+ SimulateUnlockQueue (ctxt, trap->LockQueuePointer, TRUE); -+ -+ if (IssueCommand (ctxt, offsetof (E3_CommandPort, SetEvent), -+ hdrp->s.TrAddr + E3_QUEUE_EVENT_OFFSET, FALSE) != ISSUE_COMMAND_OK) -+ { -+ /* Failed to issue setevent to complete queue unlock, since we've already unlocked */ -+ /* the queue, we should "convert" this transaction into a setevent transaction that */ -+ /* hasn't trapped */ -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: could not issue setevent for SimulateUnlockQueue\n"); -+ -+ ConvertTransactionToSetEvent (ctxt, hdrp, hdrp->s.TrAddr + E3_QUEUE_EVENT_OFFSET); -+ return (EFAIL); -+ } -+ break; -+ } -+ /*DROPTHROUGH*/ -+ -+ default: -+ FixupEventTrap (ctxt, INPUT_PROC, trap, GET_STATUS_TRAPTYPE (hdrp->s.IProcTrapStatus), -+ &trap->FaultSave, FALSE); -+ break; -+ } -+ trap->LockQueuePointer = trap->UnlockQueuePointer = 0; -+ } -+ break; -+ -+ case TR_SENDDISCARD & TR_OPCODE_TYPE_MASK: -+ /* Just ignore send-discard transactions */ -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: ignore SENDDISCARD\n"); -+ break; -+ -+ case TR_REMOTEDMA & TR_OPCODE_TYPE_MASK: -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: REMOTEDMA\n"); -+ -+ /* modify the dma type since it will still be a "read" dma */ -+ ((E3_DMA_BE *) datap)->s.dma_type &= ~(DMA_TYPE_READ | E3_DMA_CONTEXT_MASK); -+ ((E3_DMA_BE *) datap)->s.dma_type |= DMA_TYPE_ISREMOTE; -+ -+ RestartDmaDesc (ctxt, (E3_DMA_BE *) datap); -+ break; -+ -+ case TR_TRACEROUTE & TR_OPCODE_TYPE_MASK: -+ PRINTF0 (ctxt, DBG_IPROC, "RestartIProc: TRACEROUTE\n"); -+ SimulateTraceRoute (ctxt, hdrp, datap); -+ break; -+ -+ default: -+ ElanException (ctxt, EXCEPTION_BAD_PACKET, INPUT_PROC, trap); -+ break; -+ } -+ } -+ -+ /* -+ * We've successfully processed this transaction, so move onto the -+ * next one. -+ */ -+ trap->TrappedTransaction++; -+ trap->TrappedDataBuffer++; -+ } -+ -+ return (ESUCCESS); -+} -+ -+static void -+ConvertTransactionToSetEvent (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_Addr Addr) -+{ -+ hdrp->s.TrTypeCntx.s.Type = TR_SETEVENT; -+ hdrp->s.TrTypeCntx.s.StatusRegValid = 0; -+ hdrp->s.TrAddr = Addr; -+} -+ -+void -+SimulateBlockWrite (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap) -+{ -+ void *saddr = (void *) ((unsigned long) datap + (hdrp->s.TrAddr & 0x3f)); -+ unsigned nbytes = (hdrp->s.TrTypeCntx.s.Type) & TR_PARTSIZE_MASK; -+ int i; -+ -+ if (nbytes == 0) -+ nbytes = sizeof (E3_IprocTrapData_BE); -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF1 (ctxt, DBG_IPROC, "SimulateBlockWrite: faulted at %x\n", hdrp->s.TrAddr); -+ ElanException (ctxt, EXCEPTION_FAULTED, INPUT_PROC, NULL, hdrp->s.TrAddr); -+ return; -+ } -+ -+ /* -+ * NOTE: since the block copy could be to sdram, we issue the writes backwards, -+ * except we MUST ensure that the last item in the block is written last. -+ */ -+ switch (((hdrp->s.TrTypeCntx.s.Type) >> TR_TYPE_SHIFT) & TR_TYPE_MASK) -+ { -+ case TR_TYPE_BYTE: /* 8 bit */ -+ for (i = nbytes - (2*sizeof (E3_uint8)); i >= 0; i -= sizeof (E3_uint8)) -+ ELAN3_OP_STORE8 (ctxt, hdrp->s.TrAddr + i, ((E3_uint8 *) saddr)[i]); -+ i = nbytes - sizeof (E3_uint8); -+ ELAN3_OP_STORE8 (ctxt, hdrp->s.TrAddr + i, ((E3_uint8 *) saddr)[i]); -+ break; -+ -+ case TR_TYPE_SHORT: /* 16 bit */ -+ for (i = nbytes - (2*sizeof (E3_uint16)); i >= 0; i -= sizeof (E3_uint16)) -+ ELAN3_OP_STORE16 (ctxt, hdrp->s.TrAddr + i, ((E3_uint16 *) saddr)[i]); -+ i = nbytes - sizeof (E3_uint16); -+ ELAN3_OP_STORE16 (ctxt, hdrp->s.TrAddr + i, ((E3_uint16 *) saddr)[i]); -+ break; -+ -+ case TR_TYPE_WORD: /* 32 bit */ -+ for (i = nbytes - (2*sizeof (E3_uint32)); i >= 0; i -= sizeof (E3_uint32)) -+ ELAN3_OP_STORE32 (ctxt, hdrp->s.TrAddr + i, ((E3_uint32 *) saddr)[i]); -+ i = nbytes - sizeof (E3_uint32); -+ ELAN3_OP_STORE32 (ctxt, hdrp->s.TrAddr + i, ((E3_uint32 *) saddr)[i]); -+ break; -+ -+ case TR_TYPE_DWORD: /* 64 bit */ -+ for (i = nbytes - (2*sizeof (E3_uint64)); i >= 0; i -= sizeof (E3_uint64)) -+ ELAN3_OP_STORE64 (ctxt, hdrp->s.TrAddr + i, ((E3_uint64 *) saddr)[i]); -+ i = nbytes - sizeof (E3_uint64); -+ ELAN3_OP_STORE64 (ctxt, hdrp->s.TrAddr + i, ((E3_uint64 *) saddr)[i]); -+ break; -+ } -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+} -+ -+void -+SimulateWriteWord (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap) -+{ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF1 (ctxt, DBG_IPROC, "SimulateWriteWord: faulted at %x\n", hdrp->s.TrAddr); -+ ElanException (ctxt, EXCEPTION_FAULTED, INPUT_PROC, NULL, hdrp->s.TrAddr); -+ return; -+ } -+ -+ ELAN3_OP_STORE32 (ctxt, hdrp->s.TrAddr, ((E3_uint32 *) datap)[WordEndianFlip]); -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+} -+ -+void -+SimulateWriteDWord (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap) -+{ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF1 (ctxt, DBG_IPROC, "SimulateWriteDWord: faulted at %x\n", hdrp->s.TrAddr); -+ ElanException (ctxt, EXCEPTION_FAULTED, INPUT_PROC, NULL, hdrp->s.TrAddr); -+ return; -+ } -+ -+ ELAN3_OP_STORE64 (ctxt, hdrp->s.TrAddr, ((E3_uint64 *) datap)[0]); -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+} -+ -+void -+SimulateTraceRoute (ELAN3_CTXT *ctxt, E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap) -+{ -+ E3_uint32 *saddr = (E3_uint32 *) ((unsigned long) datap + (hdrp->s.TrAddr & 0x3f)); -+ unsigned nwords = TrSizeTable[(hdrp->s.TrTypeCntx.s.Type >> TR_SIZE_SHIFT) & TR_SIZE_MASK] / sizeof (E3_uint32); -+ int i; -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF1 (ctxt, DBG_IPROC, "SimulateTraceRoute: faulted at %x\n", hdrp->s.TrAddr); -+ ElanException (ctxt, EXCEPTION_FAULTED, INPUT_PROC, NULL, hdrp->s.TrAddr); -+ return; -+ } -+ -+ for (i = nwords-2; i >= 0; i--) -+ ELAN3_OP_STORE32 (ctxt, hdrp->s.TrAddr + (i * sizeof (E3_uint32)), saddr[i ^ WordEndianFlip]); -+ -+ i = nwords-1; -+ ELAN3_OP_STORE32 (ctxt, hdrp->s.TrAddr + (i * sizeof (E3_uint32)), saddr[i ^ WordEndianFlip]); -+ -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+} -+ -+void -+SimulateUnlockQueue (ELAN3_CTXT *ctxt, E3_Addr QueuePointer, int SentAck) -+{ -+ E3_uint32 QueueLock; -+ E3_Addr QueueBPTR; -+ E3_Addr QueueFPTR; -+ E3_uint64 QueueStateAndBPTR; -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF1 (ctxt, DBG_IPROC, "UnlockQueue: faulted with QueuePointer %x\n", QueuePointer); -+ ElanException (ctxt, EXCEPTION_FAULTED, INPUT_PROC, NULL, QueuePointer); -+ return; -+ } -+ -+ if (SentAck) -+ { -+ QueueBPTR = ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_bptr)); -+ QueueFPTR = ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_fptr)); -+ -+ if (QueueBPTR == ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_top))) /* move on back pointer */ -+ QueueBPTR = ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_base)); -+ else -+ QueueBPTR += ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_size)); -+ -+ QueueLock = ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_state)); -+ -+ if (QueueBPTR == QueueFPTR) /* and set full bit if fptr == bptr */ -+ QueueLock |= E3_QUEUE_FULL; -+ -+ QueueLock &= ~E3_QUEUE_LOCKED; -+ -+ QueueStateAndBPTR = (E3_uint64)QueueLock << 32 | QueueBPTR; -+ -+ ELAN3_OP_STORE64 (ctxt, QueuePointer + offsetof (E3_Queue, q_state), QueueStateAndBPTR); -+ } -+ else -+ { -+ QueueLock = ELAN3_OP_LOAD32 (ctxt, QueuePointer + offsetof (E3_Queue, q_state)); -+ -+ QueueLock &= ~E3_QUEUE_LOCKED; -+ -+ ELAN3_OP_STORE32 (ctxt, QueuePointer + offsetof (E3_Queue, q_state), QueueLock); -+ } -+ -+ no_fault(); -+} -+ -+static void -+BumpInputterStats (ELAN3_DEV *dev, E3_IprocTrapHeader_BE *hdrp) -+{ -+ if (hdrp->s.TrTypeCntx.s.LastTrappedTrans) /* EOP */ -+ { -+ switch (hdrp->s.IProcTrapStatus.Status & E3_IPS_EopType) -+ { -+ case EOP_BADACK: -+ BumpStat (dev, EopBadAcks); -+ break; -+ case EOP_ERROR_RESET: -+ BumpStat (dev, EopResets); -+ break; -+ } -+ } -+ else if (hdrp->s.TrTypeCntx.s.StatusRegValid) -+ { -+ /* -+ * Errors are tested in order of badness. i.e. badlength will prevent a BadCrc and so on... -+ */ -+ if (hdrp->s.IProcTrapStatus.s.BadLength) -+ BumpStat (dev, InputterBadLength); -+ else if ((hdrp->s.IProcTrapStatus.Status & CRC_MASK) == CRC_STATUS_BAD) -+ BumpStat (dev, InputterCRCBad); -+ else if ((hdrp->s.IProcTrapStatus.Status & CRC_MASK) == CRC_STATUS_ERROR) -+ BumpStat (dev, InputterCRCErrors); -+ else if ((hdrp->s.IProcTrapStatus.Status & CRC_MASK) == CRC_STATUS_DISCARD) -+ BumpStat (dev, InputterCRCDiscards); -+ } -+} -+ -+char * -+IProcTrapString (E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData_BE *datap) -+{ -+ static char buffer[256]; -+ static char typeString[256]; -+ static char statusString[256]; -+ char *ptr; -+ E3_Addr Addr = hdrp->s.TrAddr; -+ E3_uint32 Type = hdrp->s.TrTypeCntx.s.Type; -+ E3_uint32 Context = hdrp->s.TrTypeCntx.s.Context; -+ E3_uint32 StatusValid = hdrp->s.TrTypeCntx.s.StatusRegValid; -+ -+ if (hdrp->s.TrTypeCntx.s.LastTrappedTrans) -+ { -+ switch (hdrp->s.IProcTrapStatus.Status & E3_IPS_EopType) -+ { -+ case EOP_GOOD: sprintf (typeString, "EOP GOOD"); break; -+ case EOP_BADACK: sprintf (typeString, "EOP BADACK"); break; -+ case EOP_ERROR_RESET: sprintf (typeString, "EOP ERROR RESET"); break; -+ default: sprintf (typeString, "EOP - bad status"); break; -+ } -+ sprintf (buffer, "%15s Cntx=%08x", typeString, Context); -+ } -+ else -+ { -+ if (Type & TR_WRITEBLOCK_BIT) -+ { -+ switch ((Type >> TR_TYPE_SHIFT) & TR_TYPE_MASK) -+ { -+ case TR_TYPE_BYTE: ptr = "Byte"; break; -+ case TR_TYPE_SHORT: ptr = "Short"; break; -+ case TR_TYPE_WORD: ptr = "Word"; break; -+ case TR_TYPE_DWORD: ptr = "Double"; break; -+ default: ptr = "Unknown"; break; -+ } -+ -+ sprintf (typeString, "WriteBlock Type=%s Size=%2d", ptr, Type & TR_PARTSIZE_MASK); -+ } -+ else -+ { -+ switch (Type & TR_OPCODE_TYPE_MASK) -+ { -+ case TR_SETEVENT & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Setevent"); break; -+ case TR_REMOTEDMA & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Remote DMA"); break; -+ case TR_LOCKQUEUE & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Lock Queue"); break; -+ case TR_UNLOCKQUEUE & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Unlock Queue"); break; -+ case TR_SENDDISCARD & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Send Discard"); break; -+ case TR_DMAIDENTIFY & TR_OPCODE_TYPE_MASK: sprintf (typeString, "DMA Identify"); break; -+ case TR_THREADIDENTIFY & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Thread Identify"); break; -+ case TR_GTE & TR_OPCODE_TYPE_MASK: sprintf (typeString, "GTE"); break; -+ case TR_LT & TR_OPCODE_TYPE_MASK: sprintf (typeString, "LT"); break; -+ case TR_EQ & TR_OPCODE_TYPE_MASK: sprintf (typeString, "EQ"); break; -+ case TR_NEQ & TR_OPCODE_TYPE_MASK: sprintf (typeString, "NEQ"); break; -+ case TR_WRITEWORD & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Write Word"); break; -+ case TR_WRITEDOUBLEWORD & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Write Double"); break; -+ case TR_ATOMICADDWORD & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Atomic Add"); break; -+ case TR_TESTANDWRITE & TR_OPCODE_TYPE_MASK: sprintf (typeString, "Test and Write"); break; -+ default: sprintf (typeString, "Type=%d", Type & TR_OPCODE_TYPE_MASK); break; -+ } -+ } -+ sprintf (buffer, "%15s Addr=%08x Cntx=%08x", typeString, Addr, Context); -+ /*(Type & TR_SENDACK) ? " Sendack" : "", */ -+ /*(Type & TR_LAST_TRANS) ? " LastTrans" : "", */ -+ /*(Type & TR_WAIT_FOR_EOP) ? " WaitForEop" : ""); */ -+ } -+ -+ if (StatusValid) -+ { -+ sprintf (statusString, " Type=%s %x", MiToName (hdrp->s.IProcTrapStatus.s.TrapType), hdrp->s.IProcTrapStatus.Status); -+ strcat (buffer, statusString); -+ -+ if (hdrp->s.IProcTrapStatus.s.BadLength) -+ strcat (buffer, " BadLength"); -+ switch (hdrp->s.IProcTrapStatus.Status & CRC_MASK) -+ { -+ case CRC_STATUS_DISCARD: -+ strcat (buffer, " CRC Discard"); -+ break; -+ case CRC_STATUS_ERROR: -+ strcat (buffer, " CRC Error"); -+ break; -+ -+ case CRC_STATUS_BAD: -+ strcat (buffer, " CRC Bad"); -+ break; -+ } -+ } -+ -+ return (buffer); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/Makefile 2005-06-01 23:12:54.587440928 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/elan3/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/elan3/Makefile -+# -+ -+list-multi := elan3.o -+elan3-objs := context.o cproc.o dproc.o elandebug.o elandev_generic.o elansyscall.o eventcookie.o iproc.o sdram.o minames.o network_error.o route_table.o tproc.o tprocinsts.o routecheck.o virtual_process.o elan3ops.o context_linux.o elandev_linux.o procfs_linux.o tproc_linux.o elan3mmu_generic.o elan3mmu_linux.o -+export-objs := elandev_linux.o procfs_linux.o -+obj-$(CONFIG_ELAN3) := elan3.o -+ -+elan3.o : $(elan3-objs) -+ $(LD) -r -o $@ $(elan3-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/elan3/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/Makefile.conf 2005-06-01 23:12:54.587440928 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = elan3.o -+MODULENAME = elan3 -+KOBJFILES = context.o cproc.o dproc.o elandebug.o elandev_generic.o elansyscall.o eventcookie.o iproc.o sdram.o minames.o network_error.o route_table.o tproc.o tprocinsts.o routecheck.o virtual_process.o elan3ops.o context_linux.o elandev_linux.o procfs_linux.o tproc_linux.o elan3mmu_generic.o elan3mmu_linux.o -+EXPORT_KOBJS = elandev_linux.o procfs_linux.o -+CONFIG_NAME = CONFIG_ELAN3 -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/elan3/minames.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/minames.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/minames.c 2005-06-01 23:12:54.587440928 -0400 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: minames.c,v 1.12 2003/06/07 15:57:49 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/minames.c,v $*/ -+ -+#include -+#include -+ -+caddr_t -+MiToName (int mi) -+{ -+ static char space[32]; -+ static struct { -+ int mi; -+ char *name; -+ } info[] = { -+#include -+ }; -+ register int i; -+ -+ -+ for (i = 0; i < sizeof(info)/sizeof(info[0]); i++) -+ if (info[i].mi == mi) -+ return (info[i].name); -+ sprintf (space, "MI %x", mi); -+ return (space); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/network_error.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/network_error.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/network_error.c 2005-06-01 23:12:54.589440624 -0400 -@@ -0,0 +1,777 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: network_error.c,v 1.32.2.1 2004/10/28 11:54:57 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/network_error.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef DIGITAL_UNIX -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+typedef xdrproc_t kxdrproc_t; -+#endif -+ -+#ifdef LINUX -+#include -+#include -+#include -+#include -+ -+#include -+#define SYS_NMLN __NEW_UTS_LEN -+#endif -+ -+#include -+ -+spinlock_t ResolveRequestLock; -+kcondvar_t ResolveRequestWait; -+ -+NETERR_RESOLVER *ResolveRequestHead; -+NETERR_RESOLVER **ResolveRequestTailp = &ResolveRequestHead; -+int ResolveRequestCount; -+int ResolveRequestThreads; -+int ResolveRequestMaxThreads = 4; -+int ResolveRequestTimeout = 60; -+ -+typedef struct neterr_server -+{ -+ struct neterr_server *Next; -+ struct neterr_server *Prev; -+ unsigned ElanId; -+ -+ char *Name; -+ int RefCount; -+ struct sockaddr_in Addr; -+} NETERR_SERVER; -+ -+#define NETERR_HASH_ENTRIES 64 -+#define NETERR_HASH(elanid) (((unsigned) elanid) % NETERR_HASH_ENTRIES) -+NETERR_SERVER *NeterrServerHash[NETERR_HASH_ENTRIES]; -+kmutex_t NeterrServerLock; -+ -+static NETERR_SERVER *FindNeterrServer (int elanId); -+static void DereferenceNeterrServer (NETERR_SERVER *server); -+static int CallNeterrServer (NETERR_SERVER *server, NETERR_MSG *msg); -+ -+void -+InitialiseNetworkErrorResolver () -+{ -+ spin_lock_init (&ResolveRequestLock); -+ kcondvar_init (&ResolveRequestWait); -+ -+ ResolveRequestHead = NULL; -+ ResolveRequestTailp = &ResolveRequestHead; -+ -+ kmutex_init (&NeterrServerLock); -+} -+ -+void -+FinaliseNetworkErrorResolver () -+{ -+ spin_lock_destroy (&ResolveRequestLock); -+ kcondvar_destroy (&ResolveRequestWait); -+ -+ kmutex_destroy (&NeterrServerLock); -+} -+ -+static NETERR_RESOLVER * -+AllocateNetworkErrorResolver (void) -+{ -+ NETERR_RESOLVER *rvp; -+ -+ KMEM_ZALLOC (rvp, NETERR_RESOLVER *, sizeof (NETERR_RESOLVER), TRUE); -+ spin_lock_init (&rvp->Lock); -+ -+ return (rvp); -+} -+ -+void -+FreeNetworkErrorResolver (NETERR_RESOLVER *rvp) -+{ -+ spin_lock_destroy (&rvp->Lock); -+ KMEM_FREE (rvp, sizeof (NETERR_RESOLVER)); -+} -+ -+static void -+elan3_neterr_resolver (void) -+{ -+ NETERR_RESOLVER *rvp; -+ NETERR_SERVER *server; -+ int status; -+ unsigned long flags; -+ -+ kernel_thread_init("elan3_neterr_resolver"); -+ spin_lock (&ResolveRequestLock); -+ -+ while ((rvp = ResolveRequestHead) != NULL) -+ { -+ if ((ResolveRequestHead = rvp->Next) == NULL) -+ ResolveRequestTailp = &ResolveRequestHead; -+ -+ spin_unlock (&ResolveRequestLock); -+ -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, "elan3_neterr_resolver: rvp = %p\n", rvp); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " Rail %d\n", rvp->Message.Rail); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " SrcCapability %s\n", CapabilityString (&rvp->Message.SrcCapability)); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " DstCapability %s\n", CapabilityString (&rvp->Message.DstCapability)); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " CookieAddr %08x\n", rvp->Message.CookieAddr); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " CookieVProc %08x\n", rvp->Message.CookieVProc); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " NextCookie %08x\n", rvp->Message.NextCookie); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " WaitForEop %08x\n", rvp->Message.WaitForEop); -+ -+ if ((server = FindNeterrServer (rvp->Location.loc_node)) == NULL) -+ status = ECONNREFUSED; -+ else if (ResolveRequestTimeout && ((int)(lbolt - rvp->Timestamp)) > (ResolveRequestTimeout*HZ)) -+ { -+ printk ("elan_neterr: rpc to '%s' timedout - context %d killed\n", server->Name, rvp->Message.SrcCapability.cap_mycontext); -+ status = ECONNABORTED; -+ } -+ else -+ { -+ status = CallNeterrServer (server, &rvp->Message); -+ -+ DereferenceNeterrServer (server); -+ } -+ -+ if ((status == EINTR || status == ETIMEDOUT) && rvp->Ctxt != NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, "elan3_neterr_resolver: retry rvp=%p\n", rvp); -+ spin_lock (&ResolveRequestLock); -+ rvp->Next = NULL; -+ *ResolveRequestTailp = rvp; -+ ResolveRequestTailp = &rvp->Next; -+ } -+ else -+ { -+ rvp->Status = status; -+ -+ spin_lock (&rvp->Lock); -+ -+ if (rvp->Ctxt != NULL) -+ { -+ PRINTF2 (rvp->Ctxt, DBG_NETERR, "elan3_neterr_resolver: completing rvp %p for ctxt %p\n", rvp, rvp->Ctxt); -+ spin_lock_irqsave (&rvp->Ctxt->Device->IntrLock, flags); -+ -+ rvp->Completed = TRUE; -+ -+ kcondvar_wakeupall (&rvp->Ctxt->Wait, &rvp->Ctxt->Device->IntrLock); -+ -+ /* -+ * drop the locks out of order since the rvp can get freeed -+ * as soon as we drop the IntrLock - so cannot reference the -+ * rvp after this. -+ */ -+ -+ spin_unlock (&rvp->Lock); -+ spin_unlock_irqrestore (&rvp->Ctxt->Device->IntrLock, flags); -+ } -+ else -+ { -+ PRINTF2 (DBG_DEVICE, DBG_NETERR, "elan3_neterr_resolver: completing rvp %p for deceased ctxt %p\n", rvp, rvp->Ctxt); -+ spin_unlock (&rvp->Lock); -+ FreeNetworkErrorResolver (rvp); -+ } -+ -+ spin_lock (&ResolveRequestLock); -+ ResolveRequestCount--; -+ } -+ } -+ -+ ResolveRequestThreads--; -+ -+ spin_unlock (&ResolveRequestLock); -+ kernel_thread_exit(); -+} -+ -+int -+QueueNetworkErrorResolver (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, NETERR_RESOLVER **rvpp) -+{ -+ int isdma = trap->DmaIdentifyTransaction != NULL; -+ E3_IprocTrapHeader_BE *hdrp = isdma ? trap->DmaIdentifyTransaction : trap->ThreadIdentifyTransaction; -+ E3_uint32 process = isdma ? (hdrp->s.TrAddr & 0xFFFF) : (hdrp->s.TrData0 & 0xFFFF); -+ NETERR_RESOLVER *rvp; -+ -+ PRINTF2 (ctxt, DBG_NETERR, "QueueNetworkErrorResolver: process = %d %s\n", process, isdma ? "(dma)" : "(thread)"); -+ -+ if ((rvp = AllocateNetworkErrorResolver()) == NULL) -+ { -+ PRINTF0 (ctxt, DBG_NETERR, "QueueNetworkErrorResolver: cannot allocate resolver\n"); -+ return (ENOMEM); -+ } -+ -+ rvp->Message.Rail = ctxt->Device->Devinfo.dev_rail; -+ -+ krwlock_read (&ctxt->VpLock); -+ rvp->Location = ProcessToLocation (ctxt, NULL, process, &rvp->Message.SrcCapability); -+ krwlock_done (&ctxt->VpLock); -+ -+ if (rvp->Location.loc_node == ELAN3_INVALID_NODE) -+ { -+ PRINTF0 (ctxt, DBG_NETERR, "QueueNetworkErrorResolver: invalid elan id\n"); -+ -+ FreeNetworkErrorResolver (rvp); -+ return (EINVAL); -+ } -+ -+ rvp->Message.DstCapability = ctxt->Capability; -+ rvp->Message.DstProcess = elan3_process (ctxt); -+ rvp->Message.WaitForEop = (trap->WaitForEopTransaction != NULL); -+ -+ if (isdma) -+ { -+ rvp->Message.CookieAddr = 0; -+ rvp->Message.CookieVProc = hdrp->s.TrAddr; -+ rvp->Message.NextCookie = 0; -+ } -+ else -+ { -+ rvp->Message.CookieAddr = hdrp->s.TrAddr; -+ rvp->Message.CookieVProc = hdrp->s.TrData0; -+ rvp->Message.NextCookie = hdrp->s.TrData1; -+ } -+ -+ rvp->Completed = FALSE; -+ rvp->Ctxt = ctxt; -+ rvp->Timestamp = lbolt; -+ -+ spin_lock (&ResolveRequestLock); -+ -+ rvp->Next = NULL; -+ *ResolveRequestTailp = rvp; -+ ResolveRequestTailp = &rvp->Next; -+ ResolveRequestCount++; -+ -+ kcondvar_wakeupone (&ResolveRequestWait, &ResolveRequestLock); -+ -+ if (ResolveRequestCount < ResolveRequestThreads || ResolveRequestThreads >= ResolveRequestMaxThreads) -+ spin_unlock (&ResolveRequestLock); -+ else -+ { -+ ResolveRequestThreads++; -+ -+ spin_unlock (&ResolveRequestLock); -+ if (kernel_thread_create (elan3_neterr_resolver, NULL) == NULL) -+ { -+ spin_lock (&ResolveRequestLock); -+ ResolveRequestThreads--; -+ spin_unlock (&ResolveRequestLock); -+ -+ if (ResolveRequestThreads == 0) -+ { -+ PRINTF0 (ctxt, DBG_NETERR, "QueueNetworkErrorResolver: cannot thread pool\n"); -+ -+ FreeNetworkErrorResolver (rvp); -+ return (ENOMEM); -+ } -+ } -+ } -+ -+ *rvpp = rvp; -+ return (ESUCCESS); -+} -+ -+void -+CancelNetworkErrorResolver (NETERR_RESOLVER *rvp) -+{ -+ spin_lock (&rvp->Lock); -+ -+ PRINTF2 (rvp->Ctxt, DBG_NETERR, "CancelNetworkErrorResolver: rvp=%p %s\n", rvp, rvp->Completed ? "Completed" : "Pending"); -+ -+ if (rvp->Completed) -+ { -+ spin_unlock (&rvp->Lock); -+ FreeNetworkErrorResolver (rvp); -+ } -+ else -+ { -+ rvp->Ctxt = NULL; -+ spin_unlock (&rvp->Lock); -+ } -+} -+ -+static NETERR_FIXUP * -+AllocateNetworkErrorFixup (void) -+{ -+ NETERR_FIXUP *nef; -+ -+ KMEM_ZALLOC (nef, NETERR_FIXUP *, sizeof (NETERR_FIXUP), TRUE); -+ -+ if (nef == (NETERR_FIXUP *) NULL) -+ return (NULL); -+ -+ kcondvar_init (&nef->Wait); -+ -+ return (nef); -+} -+ -+static void -+FreeNetworkErrorFixup (NETERR_FIXUP *nef) -+{ -+ kcondvar_destroy (&nef->Wait); -+ KMEM_FREE (nef, sizeof (NETERR_FIXUP)); -+} -+ -+int -+ExecuteNetworkErrorFixup (NETERR_MSG *msg) -+{ -+ ELAN3_DEV *dev; -+ ELAN3_CTXT *ctxt; -+ NETERR_FIXUP *nef; -+ NETERR_FIXUP **predp; -+ int rc; -+ unsigned long flags; -+ -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, "ExecuteNetworkErrorFixup: msg = %p\n", msg); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " Rail %d\n", msg->Rail); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " SrcCapability %s\n", CapabilityString (&msg->SrcCapability)); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " DstCapability %s\n", CapabilityString (&msg->DstCapability)); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " CookieAddr %08x\n", msg->CookieAddr); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " CookieVProc %08x\n", msg->CookieVProc); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " NextCookie %08x\n", msg->NextCookie); -+ PRINTF1 (DBG_DEVICE, DBG_NETERR, " WaitForEop %08x\n", msg->WaitForEop); -+ -+ if ((dev = elan3_device (msg->Rail)) == NULL) -+ return (ESRCH); -+ -+ if ((nef = AllocateNetworkErrorFixup()) == NULL) -+ return (ENOMEM); -+ -+ if (nef == (NETERR_FIXUP *) NULL) -+ return (ENOMEM); -+ -+ bcopy (msg, &nef->Message, sizeof (NETERR_MSG)); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, msg->SrcCapability.cap_mycontext); -+ -+ if (ctxt == NULL) -+ rc = ESRCH; -+ else if (!ELAN_CAP_MATCH (&msg->SrcCapability, &ctxt->Capability)) -+ rc = EPERM; -+ else -+ { -+ if (ctxt->Status & CTXT_NO_LWPS) -+ rc = EAGAIN; -+ else -+ { -+ for (predp = &ctxt->NetworkErrorFixups; *predp != NULL; predp = &(*predp)->Next) -+ ; -+ nef->Next = NULL; -+ *predp = nef; -+ -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ -+ while (! nef->Completed) -+ kcondvar_wait (&nef->Wait, &dev->IntrLock, &flags); -+ -+ rc = nef->Status; -+ } -+ } -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ FreeNetworkErrorFixup (nef); -+ -+ return (rc); -+} -+ -+void -+CompleteNetworkErrorFixup (ELAN3_CTXT *ctxt, NETERR_FIXUP *nef, int status) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ unsigned long flags; -+ -+ PRINTF2 (ctxt, DBG_NETERR, "CompleteNetworkErrorFixup: %p %d\n", nef, status); -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ nef->Status = status; -+ nef->Completed = TRUE; -+ kcondvar_wakeupone (&nef->Wait, &dev->IntrLock); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+ -+static NETERR_SERVER * -+NewNeterrServer (int elanId, struct sockaddr_in *addr, char *name) -+{ -+ NETERR_SERVER *server; -+ -+ KMEM_ZALLOC (server, NETERR_SERVER *, sizeof (NETERR_SERVER), TRUE); -+ KMEM_ALLOC (server->Name, char *, strlen (name)+1, TRUE); -+ -+ bcopy (addr, &server->Addr, sizeof (struct sockaddr_in)); -+ bcopy (name, server->Name, strlen (name)+1); -+ -+ server->ElanId = elanId; -+ server->RefCount = 1; -+ -+ return (server); -+} -+ -+static void -+DeleteNeterrServer (NETERR_SERVER *server) -+{ -+ KMEM_FREE (server->Name, strlen(server->Name)+1); -+ KMEM_FREE (server, sizeof (NETERR_SERVER)); -+} -+ -+static NETERR_SERVER * -+FindNeterrServer (int elanId) -+{ -+ NETERR_SERVER *server; -+ -+ kmutex_lock (&NeterrServerLock); -+ -+ for (server = NeterrServerHash[NETERR_HASH(elanId)]; server != NULL; server = server->Next) -+ if (server->ElanId == elanId) -+ break; -+ -+ if (server != NULL) -+ server->RefCount++; -+ kmutex_unlock (&NeterrServerLock); -+ -+ return (server); -+} -+ -+static void -+DereferenceNeterrServer (NETERR_SERVER *server) -+{ -+ kmutex_lock (&NeterrServerLock); -+ if ((--server->RefCount) == 0) -+ DeleteNeterrServer (server); -+ kmutex_unlock (&NeterrServerLock); -+} -+ -+int -+AddNeterrServer (int elanId, struct sockaddr_in *addr, char *name) -+{ -+ NETERR_SERVER *server; -+ NETERR_SERVER *old; -+ int hashval = NETERR_HASH(elanId); -+ -+ server = NewNeterrServer (elanId, addr, name); -+ -+ if (server == NULL) -+ return (ENOMEM); -+ -+ kmutex_lock (&NeterrServerLock); -+ for (old = NeterrServerHash[hashval]; old != NULL; old = old->Next) -+ if (old->ElanId == elanId) -+ break; -+ -+ /* remove "old" server from hash table */ -+ if (old != NULL) -+ { -+ if (old->Prev) -+ old->Prev->Next = old->Next; -+ else -+ NeterrServerHash[hashval] = old->Next; -+ if (old->Next) -+ old->Next->Prev = old->Prev; -+ } -+ -+ /* insert "new" server into hash table */ -+ if ((server->Next = NeterrServerHash[hashval]) != NULL) -+ server->Next->Prev = server; -+ server->Prev = NULL; -+ NeterrServerHash[hashval] = server; -+ -+ kmutex_unlock (&NeterrServerLock); -+ -+ if (old != NULL) -+ DereferenceNeterrServer (old); -+ -+ return (ESUCCESS); -+} -+ -+int -+AddNeterrServerSyscall (int elanId, void *addrp, void *namep, char *unused) -+{ -+ struct sockaddr_in addr; -+ char *name; -+ int error; -+ int nob; -+ -+ /* Sanity check the supplied elanId argument */ -+ if (elanId < 0) -+ return ( set_errno(EINVAL) ); -+ -+ KMEM_ALLOC (name, caddr_t, SYS_NMLN, TRUE); -+ -+ if (copyin ((caddr_t) addrp, (caddr_t) &addr, sizeof (addr)) || -+ copyinstr ((caddr_t) namep, name, SYS_NMLN, &nob)) -+ { -+ error = EFAULT; -+ } -+ else -+ { -+ PRINTF2 (DBG_DEVICE, DBG_NETERR, "AddNeterrServer: '%s' at elanid %d\n", name, elanId); -+ -+ error = AddNeterrServer (elanId, &addr, name); -+ } -+ KMEM_FREE (name, SYS_NMLN); -+ -+ return (error ? set_errno(error) : ESUCCESS); -+} -+ -+ -+#if defined(DIGITAL_UNIX) -+static int -+CallNeterrServer (NETERR_SERVER *server, NETERR_MSG *msg) -+{ -+ cred_t *cr = crget(); -+ struct rpc_err rpcerr; -+ extern cred_t *kcred; -+ struct timeval wait; -+ enum clnt_stat rc; -+ int status; -+ CLIENT *clnt; -+ int error; -+ -+ PRINTF4 (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s) - family=%d port=%d addr=%08x\n", server->Name, -+ server->Addr.sin_family, server->Addr.sin_port, server->Addr.sin_addr.s_addr); -+ -+ if ((clnt = clntkudp_create (&server->Addr, (struct sockaddr_in *)0, NETERR_PROGRAM, NETERR_VERSION, 1, cr)) == NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s): clntkudp_create error\n", server->Name); -+ -+ return (ENOMEM); -+ } -+ -+ wait.tv_sec = NETERR_RPC_TIMEOUT; -+ wait.tv_usec = 0; -+ -+ PRINTF2 (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s): CLNT_CALL timeout = %d\n", server->Name, NETERR_RPC_TIMEOUT); -+ -+ rc = CLNT_CALL(clnt, NETERR_FIXUP_RPC, xdr_neterr_msg, (void *)msg, xdr_int, (void *) &status, wait); -+ -+ PRINTF3 (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s): CLNT_CALL -> %d (%s)\n", server->Name, rc, clnt_sperrno(rc));; -+ -+ switch (rc) -+ { -+ case RPC_SUCCESS: -+ break; -+ -+ case RPC_INTR: -+ status = EINTR; -+ break; -+ -+ case RPC_TIMEDOUT: -+ status = ETIMEDOUT; -+ break; -+ -+ default: -+ printf ("CallNeterrServer(%s): %s\n", server->Name, clnt_sperrno(status)); -+ status = ENOENT; -+ break; -+ } -+ -+ CLNT_DESTROY(clnt); -+ -+ crfree(cr); -+ -+ ASSERT(rc == RPC_SUCCESS || status != 0); -+ -+ PRINTF2 (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s): status=%d\n", server->Name, status); -+ -+ return (status); -+} -+#endif -+ -+#if defined(LINUX) -+ -+#define xdrsize(type) ((sizeof(type) + 3) >> 2) -+ -+static int -+xdr_error(struct rpc_rqst *req, u32 *p, void *dummy) -+{ -+ return -EIO; -+} -+ -+static int -+xdr_decode_int(struct rpc_rqst *req, u32 *p, int *res) -+{ -+ *res = ntohl(*p++); -+ return 0; -+} -+ -+#define XDR_capability_sz ((12 + BT_BITOUL(ELAN3_MAX_VPS)) * sizeof (u32)) -+ -+static int -+xdr_encode_capability(u32 *p, ELAN_CAPABILITY *cap) -+{ -+ u32 *pp = p; -+ -+ /* basic xdr unit is u32 - for opaque types we must round up to that */ -+ memcpy(p, &cap->cap_userkey, sizeof(cap->cap_userkey)); -+ p += xdrsize(cap->cap_userkey); -+ -+ *p++ = htonl(cap->cap_version); -+ ((u16 *) (p++))[1] = htons(cap->cap_type); -+ *p++ = htonl(cap->cap_lowcontext); -+ *p++ = htonl(cap->cap_highcontext); -+ *p++ = htonl(cap->cap_mycontext); -+ *p++ = htonl(cap->cap_lownode); -+ *p++ = htonl(cap->cap_highnode); -+ *p++ = htonl(cap->cap_railmask); -+ -+ memcpy(p, &cap->cap_bitmap[0], sizeof(cap->cap_bitmap)); -+ p += xdrsize(cap->cap_bitmap); -+ -+ ASSERT (((unsigned long) p - (unsigned long) pp) == XDR_capability_sz); -+ -+ return (p - pp); -+} -+ -+ -+#define XDR_neterr_sz (((1 + 5) * sizeof (u32)) + (2*XDR_capability_sz)) -+ -+static int -+xdr_encode_neterr_msg(struct rpc_rqst *req, u32 *p, NETERR_MSG *msg) -+{ -+ u32 *pp = p; -+ -+ *p++ = htonl(msg->Rail); -+ -+ p += xdr_encode_capability(p, &msg->SrcCapability); -+ p += xdr_encode_capability(p, &msg->DstCapability); -+ -+ *p++ = htonl(msg->DstProcess); -+ *p++ = htonl(msg->CookieAddr); -+ *p++ = htonl(msg->CookieVProc); -+ *p++ = htonl(msg->NextCookie); -+ *p++ = htonl(msg->WaitForEop); -+ -+ ASSERT (((unsigned long) p - (unsigned long) pp) == XDR_neterr_sz); -+ -+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); -+ -+ return 0; -+} -+ -+static struct rpc_procinfo neterr_procedures[2] = -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -+# define RPC_ID_NULL "neterr_null" -+# define RPC_ID_FIXUP_RPC "neterr_fixup_rpc" -+#else -+# define RPC_ID_NULL NETERR_NULL_RPC -+# define RPC_ID_FIXUP_RPC NETERR_FIXUP_RPC -+#endif -+ { -+ RPC_ID_NULL, /* procedure name or number*/ -+ (kxdrproc_t) xdr_error, /* xdr encode fun */ -+ (kxdrproc_t) xdr_error, /* xdr decode fun */ -+ 0, /* req buffer size */ -+ 0, /* call count */ -+ }, -+ { -+ RPC_ID_FIXUP_RPC, -+ (kxdrproc_t) xdr_encode_neterr_msg, -+ (kxdrproc_t) xdr_decode_int, -+ XDR_neterr_sz, -+ 0, -+ }, -+}; -+ -+static struct rpc_version neterr_version1 = -+{ -+ 1, /* version */ -+ 2, /* number of procedures */ -+ neterr_procedures /* procedures */ -+}; -+ -+static struct rpc_version *neterr_version[] = -+{ -+ NULL, -+ &neterr_version1, -+}; -+ -+static struct rpc_stat neterr_stats; -+ -+static struct rpc_program neterr_program = -+{ -+ NETERR_SERVICE, -+ NETERR_PROGRAM, -+ sizeof(neterr_version)/sizeof(neterr_version[0]), -+ neterr_version, -+ &neterr_stats, -+}; -+ -+static int -+CallNeterrServer (NETERR_SERVER *server, NETERR_MSG *msg) -+{ -+ struct rpc_xprt *xprt; -+ struct rpc_clnt *clnt; -+ struct rpc_timeout to; -+ int rc, status; -+ -+ PRINTF (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s)\n", server->Name); -+ -+ xprt_set_timeout(&to, 1, NETERR_RPC_TIMEOUT * HZ); -+ -+ if ((xprt = xprt_create_proto(IPPROTO_UDP, &server->Addr, &to)) == NULL) -+ { -+ PRINTF (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s) xprt_create_proto failed\n", server->Name); -+ return EFAIL; -+ } -+ -+ if ((clnt = rpc_create_client(xprt, server->Name, &neterr_program, NETERR_VERSION, RPC_AUTH_NULL)) == NULL) -+ { -+ PRINTF (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s) rpc_create_client failed\n", server->Name); -+ xprt_destroy (xprt); -+ -+ return EFAIL; -+ } -+ -+ clnt->cl_softrtry = 1; -+ clnt->cl_chatty = 0; -+ clnt->cl_oneshot = 1; -+ clnt->cl_intr = 0; -+ -+ if ((rc = rpc_call(clnt, NETERR_FIXUP_RPC, msg, &status, 0)) < 0) -+ { -+ /* RPC error has occured - determine whether we should retry */ -+ -+ status = ETIMEDOUT; -+ } -+ -+ PRINTF (DBG_DEVICE, DBG_NETRPC, "CallNeterrServer(%s): -> %d\n", server->Name, status); -+ -+ return (status); -+} -+ -+#endif /* defined(LINUX) */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/procfs_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/procfs_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/procfs_linux.c 2005-06-01 23:12:54.589440624 -0400 -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: procfs_linux.c,v 1.21 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/procfs_linux.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+struct proc_dir_entry *elan3_procfs_root; -+struct proc_dir_entry *elan3_config_root; -+ -+static int -+proc_read_position (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *) data; -+ int len; -+ -+ if (dev->Position.pos_mode == ELAN_POS_UNKNOWN) -+ len = sprintf (page, "\n"); -+ else -+ len = sprintf (page, -+ "NodeId %d\n" -+ "NumLevels %d\n" -+ "NumNodes %d\n", -+ dev->Position.pos_nodeid, dev->Position.pos_levels, dev->Position.pos_nodes); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static int -+proc_write_position (struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ ELAN3_DEV *dev = (ELAN3_DEV *) data; -+ unsigned nodeid = ELAN3_INVALID_NODE; -+ unsigned numnodes = 0; -+ char *page, *p; -+ int res; -+ -+ if (count == 0) -+ return (0); -+ -+ if (count >= PAGE_SIZE) -+ return (-EINVAL); -+ -+ if ((page = (char *) __get_free_page (GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ MOD_INC_USE_COUNT; -+ -+ if (copy_from_user (page, buf, count)) -+ res = -EFAULT; -+ else -+ { -+ page[count] = '\0'; -+ -+ if (page[count-1] == '\n') -+ page[count-1] = '\0'; -+ -+ if (! strcmp (page, "")) -+ { -+ dev->Position.pos_mode = ELAN_POS_UNKNOWN; -+ dev->Position.pos_nodeid = ELAN3_INVALID_NODE; -+ dev->Position.pos_nodes = 0; -+ dev->Position.pos_levels = 0; -+ } -+ else -+ { -+ for (p = page; *p; ) -+ { -+ while (isspace (*p)) -+ p++; -+ -+ if (! strncmp (p, "NodeId=", strlen("NodeId="))) -+ nodeid = simple_strtoul (p + strlen ("NodeId="), NULL, 0); -+ if (! strncmp (p, "NumNodes=", strlen ("NumNodes="))) -+ numnodes = simple_strtoul (p + strlen ("NumNodes="), NULL, 0); -+ -+ while (*p && !isspace(*p)) -+ p++; -+ } -+ -+ if (ComputePosition (&dev->Position, nodeid, numnodes, dev->Devinfo.dev_num_down_links_value) != 0) -+ printk ("elan%d: invalid values for NodeId=%d NumNodes=%d\n", dev->Instance, nodeid, numnodes); -+ else -+ printk ("elan%d: setting NodeId=%d NumNodes=%d NumLevels=%d\n", dev->Instance, dev->Position.pos_nodeid, -+ dev->Position.pos_nodes, dev->Position.pos_levels); -+ } -+ } -+ -+ MOD_DEC_USE_COUNT; -+ free_page ((unsigned long) page); -+ -+ return (count); -+} -+ -+ -+void -+elan3_procfs_device_init (ELAN3_DEV *dev) -+{ -+ struct proc_dir_entry *dir, *p; -+ char name[NAME_MAX]; -+ -+ sprintf (name, "device%d", dev->Instance); -+ dir = dev->Osdep.procdir = proc_mkdir (name, elan3_procfs_root); -+ -+ if ((p = create_proc_entry ("position", 0, dir)) != NULL) -+ { -+ p->read_proc = proc_read_position; -+ p->write_proc = proc_write_position; -+ p->data = dev; -+ p->owner = THIS_MODULE; -+ } -+ -+} -+ -+void -+elan3_procfs_device_fini (ELAN3_DEV *dev) -+{ -+ struct proc_dir_entry *dir = dev->Osdep.procdir; -+ char name[NAME_MAX]; -+ -+ remove_proc_entry ("position", dir); -+ -+ sprintf (name, "device%d", dev->Instance); -+ remove_proc_entry (name, elan3_procfs_root); -+} -+ -+void -+elan3_procfs_init() -+{ -+ extern int eventint_punt_loops; -+ extern int ResolveRequestTimeout; -+ -+ elan3_procfs_root = proc_mkdir("elan3", qsnet_procfs_root); -+ -+ elan3_config_root = proc_mkdir("config", elan3_procfs_root); -+ -+ qsnet_proc_register_hex (elan3_config_root, "elan3_debug", &elan3_debug, 0); -+ qsnet_proc_register_hex (elan3_config_root, "elan3_debug_console", &elan3_debug_console, 0); -+ qsnet_proc_register_hex (elan3_config_root, "elan3_debug_buffer", &elan3_debug_buffer, 0); -+ qsnet_proc_register_hex (elan3_config_root, "elan3mmu_debug", &elan3mmu_debug, 0); -+ qsnet_proc_register_int (elan3_config_root, "eventint_punt_loops", &eventint_punt_loops, 0); -+ qsnet_proc_register_int (elan3_config_root, "neterr_timeout", &ResolveRequestTimeout, 0); -+ -+#if defined(__ia64__) -+ { -+ extern int enable_sdram_writecombining; -+ qsnet_proc_register_int (elan3_config_root, "enable_sdram_writecombining", &enable_sdram_writecombining, 0); -+ } -+#endif -+} -+ -+void -+elan3_procfs_fini() -+{ -+#if defined(__ia64__) -+ remove_proc_entry ("enable_sdram_writecombining", elan3_config_root); -+#endif -+ remove_proc_entry ("neterr_timeout", elan3_config_root); -+ remove_proc_entry ("eventint_punt_loops", elan3_config_root); -+ remove_proc_entry ("elan3mmu_debug", elan3_config_root); -+ remove_proc_entry ("elan3_debug_buffer", elan3_config_root); -+ remove_proc_entry ("elan3_debug_console", elan3_config_root); -+ remove_proc_entry ("elan3_debug", elan3_config_root); -+ -+ remove_proc_entry ("config", elan3_procfs_root); -+ remove_proc_entry ("version", elan3_procfs_root); -+ -+ remove_proc_entry ("elan3", qsnet_procfs_root); -+} -+ -+EXPORT_SYMBOL(elan3_procfs_root); -+EXPORT_SYMBOL(elan3_config_root); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/quadrics_version.h 2005-06-01 23:12:54.589440624 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/elan3/routecheck.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/routecheck.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/routecheck.c 2005-06-01 23:12:54.590440472 -0400 -@@ -0,0 +1,313 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* ------------------------------------------------------------- */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* ---------------------------------------------------------------------- */ -+typedef struct elan3_net_location { -+ int netid; -+ int plane; -+ int level; -+} ELAN3_NET_LOCATION; -+/* ---------------------------------------------------------------------- */ -+#define FLIT_LINK_ARRAY_MAX (ELAN3_MAX_LEVELS*2) -+/* ---------------------------------------------------------------------- */ -+int -+elan3_route_follow_link( ELAN3_CTXT *ctxt, ELAN3_NET_LOCATION *loc, int link) -+{ -+ ELAN_POSITION *pos = &ctxt->Position; -+ -+ if ((link<0) || (link>7)) -+ { -+ PRINTF1 (ctxt, DBG_VP, "elan3_route_follow_link: link (%d) out of range \n",link); -+ return (ELAN3_ROUTE_INVALID); -+ } -+ -+ /* going up or down ? */ -+ if ( link >= pos->pos_arity[loc->level] ) -+ { -+ /* Up */ -+ if (loc->level >= pos->pos_levels) -+ loc->plane = 0; -+ else -+ { -+ if ((loc->level == 1) && (pos->pos_arity[0] == 8)) /* oddness in some machines ie 512 */ -+ loc->plane = (16 * ( loc->plane / 8 )) + (4 * ( loc->plane % 4)) -+ +(link - pos->pos_arity[loc->level]); -+ else -+ loc->plane = (loc->plane * (8 - pos->pos_arity[loc->level])) -+ +(link - pos->pos_arity[loc->level]); -+ } -+ loc->level--; -+ if ( loc->level < 0 ) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_follow_link: link goes off the top\n"); -+ return (ELAN3_ROUTE_INVALID_LEVEL); -+ } -+ loc->netid = loc->netid / pos->pos_arity[loc->level]; -+ } -+ else -+ { -+ /* going down */ -+ if ((loc->level == 0) && (pos->pos_arity[0] == 8)) /* oddness in some machines ie 512 */ -+ loc->netid = link % 2; -+ else -+ loc->netid =(loc->netid * pos->pos_arity[loc->level])+link; -+ -+ loc->level++; -+ if (loc->level > pos->pos_levels) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_follow_link: link goes off the bottom\n"); -+ return (ELAN3_ROUTE_INVALID_LEVEL); -+ } -+ -+ if ( loc->level >= (pos->pos_levels-1)) -+ loc->plane = 0; -+ else -+ if ((loc->level == 1) && (pos->pos_arity[0] == 8)) /* oddness in some machines ie 512 */ -+ loc->plane = (((loc->plane)>>2)*2) - ( ((loc->plane)>>2) & 3 ) + ((link<2)?0:4); /* ((p/4) % 4) */ -+ else -+ loc->plane = loc->plane/(8-pos->pos_arity[loc->level]); -+ } -+ return (ELAN3_ROUTE_SUCCESS); -+} -+/* ---------------------------------------------------------------------- */ -+int /* assumes they are connected, really only used for finding the MyLink */ -+elan3_route_get_mylink (ELAN_POSITION *pos, ELAN3_NET_LOCATION *locA, ELAN3_NET_LOCATION *locB) -+{ -+ /* whats the My Link for locA to LocB */ -+ if ( locA->level > locB->level ) -+ return locB->plane - (locA->plane * (8 - pos->pos_arity[locA->level])) + pos->pos_arity[locA->level]; -+ -+ return locB->netid - (locA->netid * pos->pos_arity[locA->level]); -+} -+/* ---------------------------------------------------------------------- */ -+#define FIRST_GET_HIGH_PRI(FLIT) (FLIT & FIRST_HIGH_PRI) -+#define FIRST_GET_AGE(FLIT) ((FLIT & FIRST_AGE(15))>>11) -+#define FIRST_GET_TIMEOUT(FLIT) ((FLIT & FIRST_TIMEOUT(3))>>9) -+#define FIRST_GET_NEXT(FLIT) ((FLIT & FIRST_PACKED(3))>>7) -+#define FIRST_GET_ROUTE(FLIT) (FLIT & 0x7f) -+#define FIRST_GET_BCAST(FLIT) (FLIT & 0x40) -+#define FIRST_GET_IS_INVALID(FLIT) ((FLIT & 0x78) == 0x08) -+#define FIRST_GET_TYPE(FLIT) ((FLIT & 0x30)>>4) -+#define PRF_GET_ROUTE(FLIT,N) ((FLIT >> (N*4)) & 0x0F) -+#define PRF_GET_IS_MYLINK(ROUTE) (ROUTE == PACKED_MYLINK) -+#define PRF_GET_IS_NORMAL(ROUTE) (ROUTE & 0x8) -+#define PRF_GET_NORMAL_LINK(ROUTE) (ROUTE & 0x7) -+#define PRF_MOVE_ON(INDEX,NEXT) do { if (NEXT==3) {NEXT=0;INDEX++;} else {NEXT++; }} while (0); -+/* ---------------------------------------------------------------------- */ -+int /* turn level needed or -1 if not possible */ -+elan3_route_get_min_turn_level( ELAN_POSITION *pos, int nodeId) -+{ -+ int l,range = 1; -+ -+ for(l=pos->pos_levels-1;l>=0;l--) -+ { -+ range = range * pos->pos_arity[l]; -+ -+ if ( ((pos->pos_nodeid - (pos->pos_nodeid % range)) <= nodeId ) -+ && (nodeId <= (pos->pos_nodeid - (pos->pos_nodeid % range)+range -1))) -+ return l; -+ } -+ return -1; -+} -+/* ---------------------------------------------------------------------- */ -+int -+elan3_route_check(ELAN3_CTXT *ctxt, E3_uint16 *flits, int destNodeId) -+{ -+ ELAN3_NET_LOCATION lastLoc,currLoc; -+ int err; -+ int turnLevel; -+ int goingDown; -+ int lnk,index,next,val; -+ ELAN_POSITION *pos = &ctxt->Position; -+ -+ /* is the dest possible */ -+ if ( (destNodeId <0 ) || (destNodeId >= pos->pos_nodes)) -+ return (ELAN3_ROUTE_PROC_RANGE); -+ -+ /* -+ * walk the route, -+ * - to see if we get there -+ * - checking we dont turn around -+ */ -+ currLoc.netid = pos->pos_nodeid; /* the elan */ -+ currLoc.plane = 0; -+ currLoc.level = pos->pos_levels; -+ -+ turnLevel = currLoc.level; /* track the how far the route goes in */ -+ goingDown = 0; /* once set we cant go up again ie only one change of direction */ -+ -+ /* move onto the network from the elan */ -+ if ((err=elan3_route_follow_link(ctxt,&currLoc,4)) != ELAN3_ROUTE_SUCCESS) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: initial elan3_route_follow_link failed\n"); -+ return err; -+ } -+ /* do the first part of flit */ -+ switch ( FIRST_GET_TYPE(flits[0]) ) -+ { -+ case 0 /* sent */ : { lnk = (flits[0] & 0x7); break; } -+ case PACKED_MYLINK : { lnk = pos->pos_nodeid % pos->pos_arity[pos->pos_levels-1]; break; } -+ case PACKED_ADAPTIVE : { lnk = 7; /* all routes are the same just check one */ break; } -+ default : -+ PRINTF1 (ctxt, DBG_VP, "elan3_route_check: unexpected first flit (%d)\n",flits[0]); -+ return (ELAN3_ROUTE_INVALID); -+ } -+ -+ /* move along this link and check new location */ -+ memcpy(&lastLoc,&currLoc,sizeof(ELAN3_NET_LOCATION)); /* keep track of last loc */ -+ if ((err=elan3_route_follow_link(ctxt,&currLoc,lnk)) != ELAN3_ROUTE_SUCCESS ) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: elan3_route_follow_link failed\n"); -+ return err; -+ } -+ if ((currLoc.level > pos->pos_levels) || (currLoc.level < 0 )) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: route leaves machine\n"); -+ return (ELAN3_ROUTE_INVALID_LEVEL); -+ } -+ if ( lastLoc.level < currLoc.level ) -+ { -+ turnLevel = lastLoc.level; -+ goingDown = 1; -+ } -+ else -+ { -+ if (turnLevel > currLoc.level) -+ turnLevel = currLoc.level; -+ if (goingDown) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: route ocilated\n"); -+ return (ELAN3_ROUTE_OCILATES); -+ } -+ } -+ -+ /* loop on doing the remaining flits */ -+ index = 1; -+ next = FIRST_GET_NEXT(flits[0]); -+ val = PRF_GET_ROUTE(flits[index],next); -+ while(val) -+ { -+ if (PRF_GET_IS_NORMAL(val) ) -+ lnk = PRF_GET_NORMAL_LINK(val); -+ else -+ { -+ switch ( val ) -+ { -+ case PACKED_MYLINK : -+ { -+ lnk = elan3_route_get_mylink(pos, &currLoc,&lastLoc); -+ break; -+ } -+ default : -+ PRINTF1 (ctxt, DBG_VP, "elan3_route_check: unexpected packed flit (%d)\n",val); -+ return (ELAN3_ROUTE_INVALID); -+ } -+ } -+ -+ /* move along this link and check new location */ -+ memcpy(&lastLoc,&currLoc,sizeof(ELAN3_NET_LOCATION)); /* keep track of last loc */ -+ if ((err=elan3_route_follow_link(ctxt,&currLoc,lnk)) != ELAN3_ROUTE_SUCCESS) -+ return err; -+ -+ if ((currLoc.level > pos->pos_levels ) || ( currLoc.level < 0 )) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: route leaves machine\n"); -+ return (ELAN3_ROUTE_INVALID_LEVEL); -+ } -+ -+ if ( lastLoc.level < currLoc.level ) -+ goingDown = 1; -+ else -+ { -+ if (turnLevel > currLoc.level) -+ turnLevel = currLoc.level; -+ if (goingDown) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: route ocilated\n"); -+ return (ELAN3_ROUTE_OCILATES); -+ } -+ } -+ -+ /* move to next part of flit */ -+ PRF_MOVE_ON(index,next); -+ if ( index >= MAX_FLITS) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: route too long\n"); -+ return (ELAN3_ROUTE_TOO_LONG); -+ } -+ /* extract the new value */ -+ val = PRF_GET_ROUTE(flits[index],next); -+ } -+ -+ /* have we got to where we want ? */ -+ if ((currLoc.level != pos->pos_levels) || (currLoc.netid != destNodeId)) -+ { -+ PRINTF2 (ctxt, DBG_VP, "elan3_route_check: goes to %d instead of %d\n",currLoc.netid , destNodeId ); -+ return (ELAN3_ROUTE_WRONG_DEST); -+ } -+ -+ /* -+ * there is the case of src == dest -+ * getTurnLevel returns pos->pos_levels, and turnLevel is (pos->pos_levels -1) -+ * then we assume they really want to go onto the network. -+ * otherwise we check that the turn at the appriate level -+ */ -+ if ( (pos->pos_nodeid != destNodeId) || ( turnLevel != (pos->pos_levels -1)) ) -+ { -+ int lev; -+ if ((lev = elan3_route_get_min_turn_level(pos,destNodeId)) == -1) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_route_check: cant calculate turn level\n"); -+ return (ELAN3_ROUTE_INVALID); /* not sure this can happen here as checks above should protect me */ -+ } -+ if (turnLevel != lev) -+ { -+ PRINTF2 (ctxt, DBG_VP, "elan3_route_check: turn level should be %d but is %d \n", lev, turnLevel); -+ return (ELAN3_ROUTE_TURN_LEVEL); -+ } -+ } -+ return (ELAN3_ROUTE_SUCCESS); -+} -+/* ---------------------------------------------------------------------- */ -+int -+elan3_route_broadcast_check(ELAN3_CTXT *ctxt , E3_uint16 *flits, int lowNode, int highNode ) -+{ -+ E3_uint16 flitsTmp[MAX_FLITS]; -+ int nflits,i; -+ -+ nflits = GenerateRoute (&ctxt->Position, flitsTmp, lowNode, highNode, DEFAULT_ROUTE_TIMEOUT, DEFAULT_ROUTE_PRIORITY); -+ -+ for(i=0;i -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static sdramaddr_t -+AllocateLargeRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int ctxnum, E3_uint64 *smallRoute) -+{ -+ int bit = -1; -+ ELAN3_ROUTES *rent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ for (rent = tbl->LargeRoutes; rent; rent = rent->Next) -+ { -+ if ((bit = bt_freebit (rent->Bitmap, NROUTES_PER_BLOCK)) != -1) -+ break; -+ } -+ -+ if (bit == -1) /* No spare entries in large routes */ -+ { /* so allocate a new page */ -+ PRINTF0 (DBG_DEVICE, DBG_VP, "AllocateLargeRoute: allocate route entries\n"); -+ -+ spin_unlock_irqrestore (&tbl->Lock, flags); -+ -+ KMEM_ZALLOC(rent, ELAN3_ROUTES *, sizeof (ELAN3_ROUTES), TRUE); -+ -+ if (rent == (ELAN3_ROUTES *) NULL) -+ return ((sdramaddr_t) 0); -+ -+ rent->Routes = elan3_sdram_alloc (dev, PAGESIZE); -+ if (rent->Routes == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (rent, sizeof (ELAN3_ROUTES)); -+ return ((sdramaddr_t) 0); -+ } -+ -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ /* Add to list of large routes */ -+ rent->Next = tbl->LargeRoutes; -+ tbl->LargeRoutes = rent; -+ -+ /* and use entry 0 */ -+ bit = 0; -+ } -+ -+ /* Set the bit in the bitmap to mark this route as allocated */ -+ BT_SET (rent->Bitmap, bit); -+ -+ /* And generate the small route pointer and the pointer to the large routes */ -+ (*smallRoute) = BIG_ROUTE_PTR(rent->Routes + (bit*NBYTES_PER_LARGE_ROUTE), ctxnum); -+ -+ PRINTF4 (DBG_DEVICE, DBG_VP, "AllocateLargeRoute: rent %p using entry %d at %lx with route pointer %llx\n", -+ rent, bit, rent->Routes + (bit * NBYTES_PER_LARGE_ROUTE), (long long) (*smallRoute)); -+ -+ /* Invalidate the large route */ -+ elan3_sdram_zeroq_sdram (dev, rent->Routes + (bit * NBYTES_PER_LARGE_ROUTE), NBYTES_PER_LARGE_ROUTE); -+ -+ spin_unlock_irqrestore (&tbl->Lock, flags); -+ -+ return (rent->Routes + (bit * NBYTES_PER_LARGE_ROUTE)); -+} -+ -+static void -+FreeLargeRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, E3_uint64 smallRoute) -+{ -+ E3_Addr addr = (E3_Addr) (smallRoute & ((1ULL << ROUTE_CTXT_SHIFT)-1)); -+ ELAN3_ROUTES *rent; -+ -+ PRINTF1 (DBG_DEVICE, DBG_VP, "FreeLargeRoute: free route %llx\n", (long long) smallRoute); -+ -+ ASSERT (SPINLOCK_HELD (&tbl->Lock)); -+ -+ for (rent = tbl->LargeRoutes; rent; rent = rent->Next) -+ { -+ if (rent->Routes <= addr && (rent->Routes + ROUTE_BLOCK_SIZE) > addr) -+ { -+ int indx = (addr - rent->Routes)/NBYTES_PER_LARGE_ROUTE; -+ -+ PRINTF2 (DBG_DEVICE, DBG_VP, "FreeLargeRoute: rent=%p indx=%d\n", rent, indx); -+ -+ BT_CLEAR(rent->Bitmap, indx); -+ return; -+ } -+ } -+ -+ panic ("elan: FreeLargeRoute - route not found in large route tables"); -+} -+ -+static void -+FreeLargeRoutes (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl) -+{ -+ ELAN3_ROUTES *rent; -+ -+ while ((rent = tbl->LargeRoutes) != NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_VP, "FreeLargeRoutes: free rent %p\n", rent); -+ -+ tbl->LargeRoutes = rent->Next; -+ -+ elan3_sdram_free (dev, rent->Routes, PAGESIZE); -+ -+ KMEM_FREE (rent, sizeof(ELAN3_ROUTES)); -+ } -+} -+ -+int -+GetRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int process, E3_uint16 *flits) -+{ -+ E3_uint64 routeValue; -+ sdramaddr_t largeRouteOff; -+ -+ if (process < 0 || process >= tbl->Size) -+ return (EINVAL); -+ -+ routeValue = elan3_sdram_readq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE); -+ -+ if (routeValue & ROUTE_PTR) -+ { -+ largeRouteOff = (routeValue & ROUTE_PTR_MASK); -+ -+ routeValue = elan3_sdram_readq (dev, largeRouteOff + 0); -+ flits[0] = routeValue & 0xffff; -+ flits[1] = (routeValue >> 16) & 0xffff; -+ flits[2] = (routeValue >> 32) & 0xffff; -+ flits[3] = (routeValue >> 48) & 0xffff; -+ -+ routeValue = elan3_sdram_readq (dev, largeRouteOff + 8); -+ flits[4] = routeValue & 0xffff; -+ flits[5] = (routeValue >> 16) & 0xffff; -+ flits[6] = (routeValue >> 32) & 0xffff; -+ flits[6] = (routeValue >> 48) & 0xffff; -+ } -+ else -+ { -+ flits[0] = routeValue & 0xffff; -+ flits[1] = (routeValue >> 16) & 0xffff; -+ flits[2] = (routeValue >> 32) & 0xffff; -+ } -+ -+ return (ESUCCESS); -+} -+ -+ELAN3_ROUTE_TABLE * -+AllocateRouteTable (ELAN3_DEV *dev, int size) -+{ -+ ELAN3_ROUTE_TABLE *tbl; -+ -+ KMEM_ZALLOC (tbl, ELAN3_ROUTE_TABLE *, sizeof (ELAN3_ROUTE_TABLE), TRUE); -+ -+ if (tbl == (ELAN3_ROUTE_TABLE *) NULL) -+ return (NULL); -+ -+ tbl->Size = size; -+ tbl->Table = elan3_sdram_alloc (dev, size*NBYTES_PER_SMALL_ROUTE); -+ -+ if (tbl->Table == 0) -+ { -+ KMEM_FREE (tbl, sizeof (ELAN3_ROUTE_TABLE)); -+ return (NULL); -+ } -+ spin_lock_init (&tbl->Lock); -+ -+ /* zero the route table */ -+ elan3_sdram_zeroq_sdram (dev, tbl->Table, size*NBYTES_PER_SMALL_ROUTE); -+ -+ return (tbl); -+} -+ -+void -+FreeRouteTable (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl) -+{ -+ elan3_sdram_free (dev, tbl->Table, tbl->Size*NBYTES_PER_SMALL_ROUTE); -+ -+ FreeLargeRoutes (dev, tbl); -+ -+ spin_lock_destroy (&tbl->Lock); -+ -+ KMEM_FREE (tbl, sizeof (ELAN3_ROUTE_TABLE)); -+} -+ -+int -+LoadRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int process, int ctxnum, int nflits, E3_uint16 *flits) -+{ -+ E3_uint64 routeValue; -+ E3_uint64 largeRouteValue; -+ sdramaddr_t largeRouteOff; -+ unsigned long flags; -+ -+ if (process < 0 || process >= tbl->Size) -+ return (EINVAL); -+ -+ PRINTF3 (DBG_DEVICE, DBG_VP, "LoadRoute: table %lx process %d ctxnum %x\n", tbl->Table ,process, ctxnum); -+ -+ if (nflits < 4) -+ { -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ /* See if we're replacing a "large" route */ -+ routeValue = elan3_sdram_readq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE); -+ if (routeValue & ROUTE_PTR) -+ FreeLargeRoute (dev, tbl, routeValue); -+ -+ routeValue = SMALL_ROUTE(flits, ctxnum); -+ -+ if ( routeValue & ROUTE_PTR) -+ PRINTF0 (DBG_DEVICE, DBG_VP, "SHOULD BE A SMALL ROUTE !!!!!!!\n"); -+ -+ PRINTF2 (DBG_DEVICE, DBG_VP, "LoadRoute: loading small route %d %llx\n", process, (long long) routeValue); -+ elan3_sdram_writeq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE, routeValue); -+ } -+ else -+ { -+ E3_uint64 value0 = BIG_ROUTE0(flits); -+ E3_uint64 value1 = BIG_ROUTE1(flits); -+ -+ if ((largeRouteOff = AllocateLargeRoute (dev, tbl, ctxnum, &largeRouteValue)) == (sdramaddr_t) 0) -+ return (ENOMEM); -+ -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ routeValue = elan3_sdram_readq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE); -+ -+ if ((routeValue & ROUTE_PTR) == 0) -+ elan3_sdram_writeq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE, largeRouteValue); -+ else -+ { -+ FreeLargeRoute (dev, tbl, largeRouteValue); -+ -+ largeRouteOff = (routeValue & ROUTE_PTR_MASK); -+ } -+ -+ PRINTF3 (DBG_DEVICE, DBG_VP, "LoadRoute: loading large route %d - %llx %llx\n", process, -+ (long long) value0, (long long) value1); -+ -+ elan3_sdram_writeq (dev, largeRouteOff + 0, value0); -+ elan3_sdram_writeq (dev, largeRouteOff + 8, value1); -+ } -+ -+ spin_unlock_irqrestore (&tbl->Lock, flags); -+ return (ESUCCESS); -+} -+void -+InvalidateRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int process) -+{ -+ E3_uint64 routeValue; -+ unsigned long flags; -+ -+ if (process < 0 || process >= tbl->Size) -+ return; -+ -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ /* unset ROUTE_VALID -+ * does not matter if its short or long, will check when we re-use it -+ */ -+ routeValue = elan3_sdram_readq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE); -+ elan3_sdram_writeq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE, (routeValue & (~ROUTE_VALID))); -+ -+ spin_unlock_irqrestore (&tbl->Lock, flags); -+} -+void -+ValidateRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int process) -+{ -+ E3_uint64 routeValue; -+ unsigned long flags; -+ -+ if (process < 0 || process >= tbl->Size) -+ return; -+ -+ PRINTF2 (DBG_DEVICE, DBG_VP, "ValidateRoute: table %ld process %d \n", tbl->Table ,process); -+ -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ /* set ROUTE_VALID -+ */ -+ routeValue = elan3_sdram_readq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE); -+ elan3_sdram_writeq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE, (routeValue | ROUTE_VALID)); -+ -+ spin_unlock_irqrestore (&tbl->Lock, flags); -+} -+void -+ClearRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int process) -+{ -+ E3_uint64 routeValue; -+ unsigned long flags; -+ -+ if (process < 0 || process >= tbl->Size) -+ return; -+ -+ spin_lock_irqsave (&tbl->Lock, flags); -+ -+ PRINTF2 (DBG_DEVICE, DBG_VP, "ClearRoute: table %ld process %d \n", tbl->Table ,process); -+ -+ routeValue = elan3_sdram_readq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE); -+ -+ elan3_sdram_writeq (dev, tbl->Table + process * NBYTES_PER_SMALL_ROUTE, 0); -+ -+ if (routeValue & ROUTE_PTR) -+ FreeLargeRoute (dev, tbl, routeValue); -+ -+ spin_unlock_irqrestore (&tbl->Lock, flags); -+} -+ -+static int -+ElanIdEqual (ELAN_POSITION *pos, int level, int ida, int idb) -+{ -+ int l; -+ -+ for (l = pos->pos_levels-1; l >= level; l--) -+ { -+ ida /= pos->pos_arity[l]; -+ idb /= pos->pos_arity[l]; -+ } -+ -+ return (ida == idb); -+} -+ -+static int -+RouteDown (ELAN_POSITION *pos, int level, int elanid) -+{ -+ int l; -+ -+ for (l = (pos->pos_levels - 1); level < pos->pos_levels - 1; level++, l--) -+ { -+ if ( pos->pos_arity[l] ) -+ elanid /= pos->pos_arity[l]; -+ } -+ elanid %= pos->pos_arity[l]; -+ -+ return elanid; -+} -+ -+static int -+InitPackedAndFlits (u_char *packed, E3_uint16 *flits) -+{ -+ int rb = 0; -+ -+ bzero ((caddr_t) packed, MAX_PACKED+4); -+ bzero ((caddr_t) flits, MAX_FLITS * sizeof (E3_uint16)); -+ -+ /* Initialise 4 bytes of packed, so that the "padding" */ -+ /* NEVER terminates with 00, as this is recognised as */ -+ /* as CRC flit */ -+ packed[rb++] = 0xF; -+ packed[rb++] = 0xF; -+ packed[rb++] = 0xF; -+ packed[rb++] = 0xF; -+ -+ return (rb); -+} -+ -+static int -+PackThemRoutesUp (E3_uint16 *flits, u_char *packed, int rb, int timeout, int highPri) -+{ -+ int i, nflits; -+ -+ flits[0] |= FIRST_TIMEOUT(timeout); -+ if (highPri) -+ flits[0] |= FIRST_HIGH_PRI; -+ -+ /* round up the number of route bytes to flits */ -+ /* and subtract the 4 extra we've padded out with */ -+ nflits = (rb-1)/4; -+ -+ for (i = nflits; i > 0; i--) -+ { -+ flits[i] = (packed[rb-1] << 12 | -+ packed[rb-2] << 8 | -+ packed[rb-3] << 4 | -+ packed[rb-4] << 0); -+ rb -= 4; -+ } -+ -+ /* Now set the position of the first packed route */ -+ /* byte in the 2nd 16 bit flit, taking account of the */ -+ /* 4 byte padding */ -+ flits[0] |= FIRST_PACKED (4-rb); -+ -+ return (nflits+1); -+} -+ -+int -+GenerateRoute (ELAN_POSITION *pos, E3_uint16 *flits, int lowid, int highid, int timeout, int highPri) -+{ -+ int broadcast = (lowid != highid); -+ int rb = 0; -+ int first = 1; -+ int noRandom = 0; -+ int level; -+ u_char packed[MAX_PACKED+4]; -+ int numDownLinks; -+ -+ rb = InitPackedAndFlits (packed, flits); -+ -+ for (level = pos->pos_levels-1; /* Move up out of the elan */ -+ level > 0 && ! (ElanIdEqual (pos, level, pos->pos_nodeid, lowid) && -+ ElanIdEqual (pos, level, pos->pos_nodeid, highid)); level--) -+ { -+ noRandom |= pos->pos_random_disabled & (1 << (pos->pos_levels-1-level)); -+ } -+ -+ for (level = pos->pos_levels-1; /* Move up out of the elan */ -+ level > 0 && ! (ElanIdEqual (pos, level, pos->pos_nodeid, lowid) && -+ ElanIdEqual (pos, level, pos->pos_nodeid, highid)); level--) -+ { -+ numDownLinks = pos->pos_arity [level]; -+ if (first) -+ { -+ if (broadcast || noRandom) -+ flits[0] = FIRST_BCAST_TREE; -+ else -+ { -+ if (numDownLinks == 4) -+ flits[0] = FIRST_ADAPTIVE; -+ else -+ flits[0] = FIRST_ROUTE( numDownLinks + ( lowid % (8-numDownLinks) )); -+ } -+ first = 0; -+ } -+ else -+ { -+ if (broadcast || noRandom) -+ packed[rb++] = PACKED_BCAST_TREE; -+ else -+ { -+ if (numDownLinks == 4) -+ packed[rb++] = PACKED_ADAPTIVE; -+ else -+ packed[rb++] = PACKED_ROUTE( numDownLinks + ( lowid % (8-numDownLinks) )); -+ } -+ } -+ } -+ -+ while (level < pos->pos_levels) -+ { -+ int lowRoute = RouteDown (pos, level, lowid); -+ int highRoute = RouteDown (pos, level, highid); -+ -+ if (first) -+ { -+ if (broadcast) -+ flits[0] = FIRST_BCAST(highRoute, lowRoute); -+ else -+ flits[0] = FIRST_ROUTE(lowRoute); -+ -+ first = 0; -+ } -+ else -+ { -+ if (broadcast) -+ { -+ packed[rb++] = PACKED_BCAST0(highRoute, lowRoute); -+ packed[rb++] = PACKED_BCAST1(highRoute, lowRoute); -+ } -+ else -+ packed[rb++] = PACKED_ROUTE(lowRoute); -+ } -+ -+ level++; -+ } -+ -+#ifdef ELITE_REVA_SUPPORTED -+ if (broadcast && (pos->pos_levels == 3)) -+ { -+ packed[rb++] = PACKED_BCAST0(0, 0); -+ packed[rb++] = PACKED_BCAST1(0, 0); -+ } -+#endif -+ -+ return (PackThemRoutesUp (flits, packed, rb, timeout, highPri)); -+} -+ -+int -+GenerateCheckRoute (ELAN_POSITION *pos, E3_uint16 *flits, int level, int adaptive) -+{ -+ int notfirst = 0; -+ int l, rb; -+ u_char packed[MAX_PACKED+4]; -+ -+ rb = InitPackedAndFlits (packed, flits); -+ -+ for (l = pos->pos_levels-1; l > level; l--) -+ if (! notfirst++) -+ flits[0] = adaptive ? FIRST_ADAPTIVE : FIRST_BCAST_TREE; -+ else -+ packed[rb++] = adaptive ? PACKED_ADAPTIVE : PACKED_BCAST_TREE; -+ -+ if (! notfirst++ ) -+ flits[0] = FIRST_MYLINK; -+ else -+ packed[rb++] = PACKED_MYLINK; -+ -+ for (l++ /* consume mylink */; l < pos->pos_levels; l++) -+ if (! notfirst++) -+ flits[0] = FIRST_ROUTE (RouteDown (pos, l, pos->pos_nodeid)); -+ else -+ packed[rb++] = PACKED_ROUTE (RouteDown (pos, l, pos->pos_nodeid)); -+ -+ -+ return (PackThemRoutesUp (flits, packed, rb, DEFAULT_ROUTE_TIMEOUT, HIGH_ROUTE_PRIORITY)); -+} -+ -+ -+/* -+ * In this case "level" is the number of levels counted from the bottom. -+ */ -+int -+GenerateProbeRoute (E3_uint16 *flits, int nodeid, int level, int *linkup, int *linkdown, int adaptive ) -+{ -+ int first = 1; -+ int i, rb; -+ u_char packed[MAX_PACKED+4]; -+ -+ rb = InitPackedAndFlits (packed, flits); -+ -+ /* Generate "up" routes */ -+ for (i = 0; i < level; i++) -+ { -+ if (first) -+ flits[0] = linkup ? FIRST_ROUTE(linkup[i]) : adaptive ? FIRST_ADAPTIVE : FIRST_BCAST_TREE; -+ else -+ packed[rb++] = linkup ? PACKED_ROUTE(linkup[i]) : adaptive ? PACKED_ADAPTIVE : PACKED_BCAST_TREE; -+ first = 0; -+ } -+ -+ /* Generate a "to-me" route down */ -+ if (first) -+ flits[0] = FIRST_MYLINK; -+ else -+ packed[rb++] = PACKED_MYLINK; -+ -+ for (i = level-1; i >= 0; i--) -+ packed[rb++] = PACKED_ROUTE(linkdown[i]); -+ -+ return (PackThemRoutesUp (flits, packed, rb, DEFAULT_ROUTE_TIMEOUT, HIGH_ROUTE_PRIORITY)); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/sdram.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/sdram.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/sdram.c 2005-06-01 23:12:54.593440016 -0400 -@@ -0,0 +1,807 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: sdram.c,v 1.17 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/sdram.c,v $*/ -+ -+ -+#include -+ -+#include -+#include -+#include -+ -+/* sdram access functions */ -+#define sdram_off_to_bank(dev,off) (&dev->SdramBanks[(off) >> ELAN3_SDRAM_BANK_SHIFT]) -+#define sdram_off_to_offset(dev,off) ((off) & (ELAN3_SDRAM_BANK_SIZE-1)) -+#define sdram_off_to_bit(dev,indx,off) (sdram_off_to_offset(dev,off) >> (SDRAM_MIN_BLOCK_SHIFT+(indx))) -+ -+#define sdram_off_to_mapping(dev,off) (sdram_off_to_bank(dev,off)->Mapping + sdram_off_to_offset(dev,off)) -+ -+unsigned char -+elan3_sdram_readb (ELAN3_DEV *dev, sdramaddr_t off) -+{ -+ return (readb ((unsigned char *) sdram_off_to_mapping(dev, off))); -+} -+ -+unsigned short -+elan3_sdram_readw (ELAN3_DEV *dev, sdramaddr_t off) -+{ -+ return (readw ((unsigned short *) sdram_off_to_mapping(dev, off))); -+} -+ -+unsigned int -+elan3_sdram_readl (ELAN3_DEV *dev, sdramaddr_t off) -+{ -+ return (readl ((unsigned int *) sdram_off_to_mapping(dev, off))); -+} -+ -+unsigned long long -+elan3_sdram_readq (ELAN3_DEV *dev, sdramaddr_t off) -+{ -+ return (readq ((unsigned long long *) sdram_off_to_mapping(dev, off))); -+} -+ -+void -+elan3_sdram_writeb (ELAN3_DEV *dev, sdramaddr_t off, unsigned char val) -+{ -+ writeb (val, (unsigned char *) sdram_off_to_mapping(dev, off)); -+ wmb(); -+} -+ -+void -+elan3_sdram_writew (ELAN3_DEV *dev, sdramaddr_t off, unsigned short val) -+{ -+ writew (val, (unsigned short *) sdram_off_to_mapping(dev, off)); -+ wmb(); -+} -+ -+void -+elan3_sdram_writel (ELAN3_DEV *dev, sdramaddr_t off, unsigned int val) -+{ -+ writel (val, (unsigned int *) sdram_off_to_mapping(dev, off)); -+ wmb(); -+} -+ -+void -+elan3_sdram_writeq (ELAN3_DEV *dev, sdramaddr_t off, unsigned long long val) -+{ -+ writeq (val, (unsigned long long *) sdram_off_to_mapping(dev, off)); -+ wmb(); -+} -+ -+void -+elan3_sdram_copyb_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+ bcopy ((void *)sdram_off_to_mapping(dev, from), to, nbytes); -+} -+ -+void -+elan3_sdram_copyw_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+#ifdef __LITTLE_ENDIAN__ -+ bcopy ((void *)sdram_off_to_mapping(dev, from), to, nbytes); -+#else -+#error incorrect for big endian -+#endif -+} -+ -+void -+elan3_sdram_copyl_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+#ifdef __LITTLE_ENDIAN__ -+ bcopy ((void *)sdram_off_to_mapping(dev, from), to, nbytes); -+#else -+#error incorrect for big endian -+#endif -+} -+ -+void -+elan3_sdram_copyq_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+#ifdef __LITTLE_ENDIAN__ -+ bcopy ((void *)sdram_off_to_mapping(dev, from), to, nbytes); -+#else -+#error incorrect for big endian -+#endif -+} -+ -+#define E3_WRITEBUFFER_SIZE 16 -+#define E3_WRITEBUFFER_OFFSET(x) (((unsigned long) x) & (E3_WRITEBUFFER_SIZE-1)) -+#define E3_WRITEBUFFER_BASE(x) (((unsigned long) x) & ~((unsigned long) (E3_WRITEBUFFER_SIZE-1))) -+ -+void -+elan3_sdram_copyb_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ virtaddr_t slim = (virtaddr_t) from + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint8_t)) + sizeof (uint8_t); -+ int i; -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ for (i = 0; i < nbytes/sizeof(uint8_t); i++) -+ writeb (((uint8_t *) from)[i], &((uint8_t *) dbase)[i]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ slim -= ntop; -+ dlim -= ntop; -+ -+ for (i = 0; i < ntop/sizeof(uint8_t); i++) -+ writeb (((uint8_t *) slim)[i], &((uint8_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ slim -= E3_WRITEBUFFER_SIZE; -+ -+ for (i = 0; i < E3_WRITEBUFFER_SIZE/sizeof (uint8_t); i++) -+ writeb (((uint8_t *) slim)[i], &((uint8_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ for (i = 0; i < nbase/sizeof(uint8_t); i++) -+ writeb (((uint8_t *) from)[i], &((uint8_t *) dbase)[i]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_zerob_sdram (ELAN3_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint8_t)) + sizeof (uint8_t); -+ int i; -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ for (i = 0; i < nbytes/sizeof(uint8_t); i++) -+ writeb (0, &((uint8_t *) dbase)[i]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ dlim -= ntop; -+ -+ for (i = 0; i < ntop/sizeof(uint8_t); i++) -+ writeb (0, &((uint8_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ -+ writeq (0, &((uint64_t *) dlim)[0]); -+ writeq (0, &((uint64_t *) dlim)[1]); -+ -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ for (i = 0; i < nbase/sizeof(uint8_t); i++) -+ writeb (0, &((uint8_t *) dbase)[i]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_copyw_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ virtaddr_t slim = (virtaddr_t) from + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint16_t)) + sizeof (uint16_t); -+ int i; -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ for (i = 0; i < nbytes/sizeof(uint16_t); i++) -+ writew (((uint16_t *) from)[i], &((uint16_t *) dbase)[i]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ slim -= ntop; -+ dlim -= ntop; -+ -+ for (i = 0; i < ntop/sizeof(uint16_t); i++) -+ writew (((uint16_t *) slim)[i], &((uint16_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ slim -= E3_WRITEBUFFER_SIZE; -+ -+ writew (((uint16_t *) slim)[0], &((uint16_t *) dlim)[0]); -+ writew (((uint16_t *) slim)[1], &((uint16_t *) dlim)[1]); -+ writew (((uint16_t *) slim)[2], &((uint16_t *) dlim)[2]); -+ writew (((uint16_t *) slim)[3], &((uint16_t *) dlim)[3]); -+ writew (((uint16_t *) slim)[4], &((uint16_t *) dlim)[4]); -+ writew (((uint16_t *) slim)[5], &((uint16_t *) dlim)[5]); -+ writew (((uint16_t *) slim)[6], &((uint16_t *) dlim)[6]); -+ writew (((uint16_t *) slim)[7], &((uint16_t *) dlim)[7]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ for (i = 0; i < nbase/sizeof(uint16_t); i++) -+ writew (((uint16_t *) from)[i], &((uint16_t *) dbase)[i]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_zerow_sdram (ELAN3_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint16_t)) + sizeof (uint16_t); -+ int i; -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ for (i = 0; i < nbytes/sizeof(uint16_t); i++) -+ writew (0, &((uint16_t *) dbase)[i]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ dlim -= ntop; -+ -+ for (i = 0; i < ntop/sizeof(uint16_t); i++) -+ writew (0, &((uint16_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ -+ writeq (0, &((uint64_t *) dlim)[0]); -+ writeq (0, &((uint64_t *) dlim)[1]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ for (i = 0; i < nbase/sizeof(uint16_t); i++) -+ writew (0, &((uint16_t *) dbase)[i]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_copyl_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ virtaddr_t slim = (virtaddr_t) from + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint32_t)) + sizeof (uint32_t); -+ int i; -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ for (i = 0; i < nbytes/sizeof(uint32_t); i++) -+ writel (((uint32_t *) from)[i], &((uint32_t *) dbase)[i]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ slim -= ntop; -+ dlim -= ntop; -+ -+ for (i = 0; i < ntop/sizeof(uint32_t); i++) -+ writel (((uint32_t *) slim)[i], &((uint32_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ slim -= E3_WRITEBUFFER_SIZE; -+ -+ writel (((uint32_t *) slim)[0], &((uint32_t *) dlim)[0]); -+ writel (((uint32_t *) slim)[1], &((uint32_t *) dlim)[1]); -+ writel (((uint32_t *) slim)[2], &((uint32_t *) dlim)[2]); -+ writel (((uint32_t *) slim)[3], &((uint32_t *) dlim)[3]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ for (i = 0; i < nbase/sizeof(uint32_t); i++) -+ writel (((uint32_t *) from)[i], &((uint32_t *) dbase)[i]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_zerol_sdram (ELAN3_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint32_t)) + sizeof (uint32_t); -+ int i; -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ for (i = 0; i < nbytes/sizeof(uint32_t); i++) -+ writel (0, &((uint32_t *) dbase)[i]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ dlim -= ntop; -+ -+ for (i = 0; i < ntop/sizeof(uint32_t); i++) -+ writel (0, &((uint32_t *) dlim)[i]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ -+ writeq (0, &((uint64_t *) dlim)[0]); -+ writeq (0, &((uint64_t *) dlim)[1]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ for (i = 0; i < nbase/sizeof(uint32_t); i++) -+ writel (0, &((uint32_t *) dbase)[i]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_copyq_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ virtaddr_t slim = (virtaddr_t) from + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint64_t)) + sizeof (uint64_t); -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ writeq (((uint64_t *) from)[0], &((uint64_t *) dbase)[0]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ slim -= ntop; -+ dlim -= ntop; -+ -+ writeq (((uint64_t *) slim)[0], &((uint64_t *) dlim)[0]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ slim -= E3_WRITEBUFFER_SIZE; -+ -+ writeq (((uint64_t *) slim)[0], &((uint64_t *) dlim)[0]); -+ writeq (((uint64_t *) slim)[1], &((uint64_t *) dlim)[1]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ writeq (((uint64_t *) from)[0], &((uint64_t *) dbase)[0]); -+ wmb(); -+ } -+ } -+} -+ -+void -+elan3_sdram_zeroq_sdram (ELAN3_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ virtaddr_t dbase = (virtaddr_t) sdram_off_to_mapping (dev, to); -+ virtaddr_t dlim = (virtaddr_t) dbase + nbytes; -+ unsigned nbase = E3_WRITEBUFFER_SIZE - E3_WRITEBUFFER_OFFSET (dbase); -+ unsigned ntop = E3_WRITEBUFFER_OFFSET (dlim - sizeof (uint64_t)) + sizeof (uint64_t); -+ -+ if (E3_WRITEBUFFER_BASE(dbase) == E3_WRITEBUFFER_BASE(dlim)) -+ { -+ writeq (0, &((uint64_t *) dbase)[0]); -+ wmb(); -+ } -+ else -+ { -+ if (ntop < E3_WRITEBUFFER_SIZE) -+ { -+ dlim -= ntop; -+ -+ writeq (0, &((uint64_t *) dlim)[0]); -+ wmb(); -+ } -+ -+ while (dlim >= (dbase + E3_WRITEBUFFER_SIZE)) -+ { -+ dlim -= E3_WRITEBUFFER_SIZE; -+ -+ writeq (0, &((uint64_t *) dlim)[0]); -+ writeq (0, &((uint64_t *) dlim)[1]); -+ wmb(); -+ } -+ -+ if (nbase < E3_WRITEBUFFER_SIZE) -+ { -+ writeq (0, &((uint64_t *) dbase)[0]); -+ wmb(); -+ } -+ } -+} -+ -+physaddr_t -+elan3_sdram_to_phys (ELAN3_DEV *dev, sdramaddr_t off) -+{ -+#if defined(DIGITAL_UNIX) -+ return (KSEG_TO_PHYS (sdram_off_to_mapping (dev, off))); -+#elif defined(LINUX) -+ return (kmem_to_phys ((void *) sdram_off_to_mapping (dev, off))); -+#endif -+} -+ -+/* sdram buddy allocator */ -+#define read_next(dev, block) elan3_sdram_readl(dev, block + 0) -+#define read_prev(dev, block) elan3_sdram_readl(dev, block + 4) -+#define write_next(dev, block, val) (elan3_sdram_writel(dev, block + 0, val), val) -+#define write_prev(dev, block, val) (elan3_sdram_writel(dev, block + 4, val), val) -+ -+#define freelist_insert(dev,idx,block)\ -+do {\ -+ sdramaddr_t next = dev->SdramFreeLists[(idx)];\ -+\ -+ /*\ -+ * block->prev = NULL;\ -+ * block->next = next;\ -+ * if (next != NULL)\ -+ * next->prev = block;\ -+ * freelist = block;\ -+ */\ -+ write_prev (dev, block, (sdramaddr_t) 0);\ -+ write_next (dev, block, next);\ -+ if (next != (sdramaddr_t) 0)\ -+ write_prev (dev, next, block);\ -+ dev->SdramFreeLists[idx] = block;\ -+\ -+ dev->SdramFreeCounts[idx]++;\ -+ dev->Stats.SdramBytesFree += (SDRAM_MIN_BLOCK_SIZE << idx);\ -+} while (0) -+ -+#define freelist_remove(dev,idx,block)\ -+do {\ -+ /*\ -+ * if (block->prev)\ -+ * block->prev->next = block->next;\ -+ * else\ -+ * dev->SdramFreeLists[idx] = block->next;\ -+ * if (block->next)\ -+ * block->next->prev = block->prev;\ -+ */\ -+ sdramaddr_t blocknext = read_next (dev, block);\ -+ sdramaddr_t blockprev = read_prev (dev, block);\ -+\ -+ if (blockprev)\ -+ write_next (dev, blockprev, blocknext);\ -+ else\ -+ dev->SdramFreeLists[idx] = blocknext;\ -+ if (blocknext)\ -+ write_prev (dev, blocknext, blockprev);\ -+\ -+ dev->SdramFreeCounts[idx]--;\ -+ dev->Stats.SdramBytesFree -= (SDRAM_MIN_BLOCK_SIZE << idx);\ -+} while (0) -+ -+#define freelist_removehead(dev,idx,block)\ -+do {\ -+ sdramaddr_t blocknext = read_next (dev, block);\ -+\ -+ if ((dev->SdramFreeLists[idx] = blocknext) != 0)\ -+ write_prev (dev, blocknext, 0);\ -+\ -+ dev->SdramFreeCounts[idx]--;\ -+ dev->Stats.SdramBytesFree -= (SDRAM_MIN_BLOCK_SIZE << idx);\ -+} while (0) -+ -+#if defined(DEBUG) -+static int -+display_blocks (ELAN3_DEV *dev, int indx, char *string) -+{ -+ sdramaddr_t block; -+ int nbytes = 0; -+ -+ printk ("%s - indx %d\n", string, indx); -+ for (block = dev->SdramFreeLists[indx]; block != (sdramaddr_t) 0; block = read_next (dev, block)) -+ { -+ printk (" %lx", block); -+ nbytes += (SDRAM_MIN_BLOCK_SIZE << indx); -+ } -+ printk ("\n"); -+ -+ return (nbytes); -+} -+ -+ -+void -+elan3_sdram_display (ELAN3_DEV *dev, char *string) -+{ -+ int indx; -+ int nbytes = 0; -+ -+ printk ("elan3_sdram_display: dev=%p\n", dev); -+ for (indx = 0; indx < SDRAM_NUM_FREE_LISTS; indx++) -+ if (dev->SdramFreeLists[indx] != (sdramaddr_t) 0) -+ nbytes += display_blocks (dev, indx, string); -+ printk ("\n%d bytes free\n", nbytes); -+} -+ -+void -+elan3_sdram_verify (ELAN3_DEV *dev) -+{ -+ int indx, size, nbits, i, b; -+ sdramaddr_t block; -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; indx < SDRAM_NUM_FREE_LISTS; indx++, size <<= 1) -+ { -+ unsigned count = 0; -+ -+ for (block = dev->SdramFreeLists[indx]; block; block = read_next (dev, block), count++) -+ { -+ ELAN3_SDRAM_BANK *bank = sdram_off_to_bank (dev, block); -+ unsigned off = sdram_off_to_offset (dev, block); -+ int bit = sdram_off_to_bit (dev, indx, block); -+ -+ if ((block & (size-1)) != 0) -+ printk ("elan3_sdram_verify: block=%lx indx=%x - not aligned\n", block, indx); -+ -+ if (bank == NULL || off > bank->Size) -+ printk ("elan3_sdram_verify: block=%lx indx=%x - outside bank\n", block, indx); -+ else if (BT_TEST (bank->Bitmaps[indx], bit) == 0) -+ printk ("elan3_sdram_verify: block=%lx indx=%x - bit not set\n", block, indx); -+ else -+ { -+ for (i = indx-1, nbits = 2; i >= 0; i--, nbits <<= 1) -+ { -+ bit = sdram_off_to_bit (dev, i, block); -+ -+ for (b = 0; b < nbits; b++) -+ if (BT_TEST(bank->Bitmaps[i], bit + b)) -+ printk ("elan3_sdram_verify: block=%lx indx=%x - also free i=%d bit=%x\n", block, indx, i, bit+b); -+ } -+ } -+ } -+ -+ if (dev->SdramFreeCounts[indx] != count) -+ printk ("elan3_sdram_verify: indx=%x expected %d got %d\n", indx, dev->SdramFreeCounts[indx], count); -+ } -+} -+ -+#endif /* defined(DEBUG) */ -+ -+static void -+free_block (ELAN3_DEV *dev, sdramaddr_t block, int indx) -+{ -+ ELAN3_SDRAM_BANK *bank = sdram_off_to_bank (dev, block); -+ unsigned bit = sdram_off_to_bit(dev, indx, block); -+ unsigned size = SDRAM_MIN_BLOCK_SIZE << indx; -+ -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "free_block: block=%lx indx=%d bit=%x\n", block, indx, bit); -+ -+ ASSERT ((block & (size-1)) == 0); -+ ASSERT (BT_TEST (bank->Bitmaps[indx], bit) == 0); -+ -+ while (BT_TEST (bank->Bitmaps[indx], bit ^ 1)) -+ { -+ sdramaddr_t buddy = block ^ size; -+ -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "free_block: merge block=%lx buddy=%lx indx=%d\n", block, buddy, indx); -+ -+ BT_CLEAR (bank->Bitmaps[indx], bit ^ 1); -+ -+ freelist_remove (dev, indx, buddy); -+ -+ block = (block < buddy) ? block : buddy; -+ indx++; -+ size <<= 1; -+ bit >>= 1; -+ } -+ -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "free_block: free block=%lx indx=%d bit=%x\n", block, indx, bit); -+ -+ freelist_insert (dev, indx, block); -+ -+ BT_SET (bank->Bitmaps[indx], bit); -+} -+ -+void -+elan3_sdram_init (ELAN3_DEV *dev) -+{ -+ int indx; -+ -+ spin_lock_init (&dev->SdramLock); -+ -+ for (indx = 0; indx < SDRAM_NUM_FREE_LISTS; indx++) -+ { -+ dev->SdramFreeLists[indx] = (sdramaddr_t) 0; -+ dev->SdramFreeCounts[indx] = 0; -+ } -+} -+ -+void -+elan3_sdram_fini (ELAN3_DEV *dev) -+{ -+ spin_lock_destroy (&dev->SdramLock); -+} -+ -+void -+elan3_sdram_add (ELAN3_DEV *dev, sdramaddr_t base, sdramaddr_t top) -+{ -+ register int indx; -+ register unsigned long size; -+ -+ /* align to the minimum block size */ -+ base = (base + SDRAM_MIN_BLOCK_SIZE - 1) & ~((sdramaddr_t) SDRAM_MIN_BLOCK_SIZE-1); -+ top &= ~((sdramaddr_t) SDRAM_MIN_BLOCK_SIZE-1); -+ -+ /* don't allow 0 as a valid "base" */ -+ if (base == 0) -+ base = E3_CACHE_SIZE; -+ -+ /* carve the bottom to the biggest boundary */ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; indx < SDRAM_NUM_FREE_LISTS; indx++, size <<= 1) -+ { -+ if ((base & size) == 0) -+ continue; -+ -+ if ((base + size) > top) -+ break; -+ -+ free_block (dev, base, indx); -+ -+ base += size; -+ } -+ -+ /* carve the top down to the biggest boundary */ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; indx < SDRAM_NUM_FREE_LISTS; indx++, size <<= 1) -+ { -+ if ((top & size) == 0) -+ continue; -+ -+ if ((top - size) < base) -+ break; -+ -+ free_block (dev, (top - size), indx); -+ -+ top -= size; -+ } -+ -+ /* now free of the space in between */ -+ while (base < top) -+ { -+ free_block (dev, base, (SDRAM_NUM_FREE_LISTS-1)); -+ -+ base += SDRAM_MAX_BLOCK_SIZE; -+ } -+} -+ -+sdramaddr_t -+elan3_sdram_alloc (ELAN3_DEV *dev, int nbytes) -+{ -+ sdramaddr_t block; -+ register int i, indx; -+ unsigned long size; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->SdramLock, flags); -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size < nbytes; indx++, size <<= 1) -+ ; -+ -+ PRINTF2 (DBG_DEVICE, DBG_SDRAM, "elan3_sdram_alloc: nbytes=%d indx=%d\n", nbytes, indx); -+ -+ /* find the smallest block which is big enough for this allocation */ -+ for (i = indx; i < SDRAM_NUM_FREE_LISTS; i++, size <<= 1) -+ if (dev->SdramFreeLists[i]) -+ break; -+ -+ if (i == SDRAM_NUM_FREE_LISTS) -+ { -+ spin_unlock_irqrestore (&dev->SdramLock, flags); -+ return ((sdramaddr_t) 0); -+ } -+ -+ PRINTF2 (DBG_DEVICE, DBG_SDRAM, "elan3_sdram_alloc: use block=%lx indx=%d\n", dev->SdramFreeLists[i], i); -+ -+ /* remove the block from the free list */ -+ freelist_removehead (dev, i, (block = dev->SdramFreeLists[i])); -+ -+ /* clear the approriate bit in the bitmap */ -+ BT_CLEAR (sdram_off_to_bank (dev, block)->Bitmaps[i], sdram_off_to_bit (dev,i, block)); -+ -+ /* and split it up as required */ -+ while (i-- > indx) -+ free_block (dev, block + (size >>= 1), i); -+ -+ PRINTF1 (DBG_DEVICE, DBG_SDRAM, "elan3_sdram_alloc: return block=%lx\n", block); -+ -+ spin_unlock_irqrestore (&dev->SdramLock, flags); -+ -+ ASSERT ((block & ((SDRAM_MIN_BLOCK_SIZE << (indx))-1)) == 0); -+ -+ return ((sdramaddr_t) block); -+} -+ -+void -+elan3_sdram_free (ELAN3_DEV *dev, sdramaddr_t block, int nbytes) -+{ -+ register int indx; -+ unsigned long size; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->SdramLock, flags); -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size < nbytes; indx++, size <<= 1) -+ ; -+ -+ PRINTF2 (DBG_DEVICE, DBG_SDRAM, "elan3_sdram_free: indx=%d block=%lx\n", indx, block); -+ -+ free_block (dev, block, indx); -+ -+ spin_unlock_irqrestore (&dev->SdramLock, flags); -+} -+ -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/tproc.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/tproc.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/tproc.c 2005-06-01 23:12:54.594439864 -0400 -@@ -0,0 +1,778 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: tproc.c,v 1.51.2.1 2004/11/15 11:12:36 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/tproc.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int -+HandleTProcTrap (ELAN3_DEV *dev, E3_uint32 *RestartBits) -+{ -+ THREAD_TRAP *trap = dev->ThreadTrap; -+ int delay = 1; -+ -+ ASSERT(SPINLOCK_HELD (&dev->IntrLock)); -+ -+ trap->Status.Status = read_reg32 (dev, Exts.TProcStatus); -+ trap->sp = read_reg32 (dev, Thread_Desc_SP); -+ trap->pc = read_reg32 (dev, ExecutePC); -+ trap->npc = read_reg32 (dev, ExecuteNPC); -+ trap->StartPC = read_reg32 (dev, StartPC); -+ trap->mi = GET_STATUS_TRAPTYPE(trap->Status); -+ trap->TrapBits.Bits = read_reg32 (dev, TrapBits.Bits); -+ trap->DirtyBits.Bits = read_reg32 (dev, DirtyBits.Bits); -+ -+ if ( ! (trap->Status.s.WakeupFunction == SleepOneTick) ) { -+ int p,i; -+ E3_uint32 reg = read_reg32 (dev, Exts.InterruptReg); -+ -+ ELAN_REG_REC(reg); -+ p = elan_reg_rec_index; -+ for(i=0;iStatus.s.WakeupFunction == SleepOneTick); -+ -+ /* copy the four access fault areas */ -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, TProc), (void *) &trap->FaultSave, 16); -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcData), (void *) &trap->DataFaultSave, 16); -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcInst), (void *) &trap->InstFaultSave, 16); -+ elan3_sdram_copyq_from_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcOpen), (void *) &trap->OpenFaultSave, 16); -+ -+ /* copy the registers, note the endian swap flips the odd registers into the even registers -+ and visa versa. */ -+ copy_thread_regs (dev, trap->Registers); -+ -+ /* -+ * If the output was open then the ack may not have returned yet. Must wait for the -+ * ack to become valid and update trap_dirty with the new value. Will simulate the -+ * instructions later. -+ */ -+ if (trap->TrapBits.s.OutputWasOpen) -+ { -+ trap->TrapBits.Bits = read_reg32 (dev, TrapBits.Bits); -+ while (! trap->TrapBits.s.AckBufferValid) -+ { -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "tproc: waiting for ack to become valid\n"); -+ trap->TrapBits.Bits = read_reg32 (dev, TrapBits.Bits); -+ DELAY (delay); -+ -+ if ((delay <<= 1) == 0) delay = 1; -+ } -+ } -+ -+ /* update device statistics */ -+ BumpStat (dev, TProcTraps); -+ switch (trap->mi) -+ { -+ case MI_UnimplementedError: -+ if (trap->TrapBits.s.ForcedTProcTrap) -+ BumpStat (dev, ForcedTProcTraps); -+ if (trap->TrapBits.s.ThreadTimeout) -+ { -+ if (trap->TrapBits.s.PacketTimeout) -+ BumpStat (dev, ThreadOutputTimeouts); -+ else if (trap->TrapBits.s.PacketAckValue == E3_PAckError) -+ BumpStat (dev, ThreadPacketAckErrors); -+ } -+ if (trap->TrapBits.s.TrapForTooManyInsts) -+ BumpStat (dev, TrapForTooManyInsts); -+ break; -+ } -+ -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, TProc), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcData), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcInst), 16); -+ elan3_sdram_zeroq_sdram (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, ThreadProcOpen), 16); -+ -+ *RestartBits |= RestartTProc; -+ -+ return (TRUE); -+} -+ -+void -+DeliverTProcTrap (ELAN3_DEV *dev, THREAD_TRAP *threadTrap, E3_uint32 Pend) -+{ -+ ELAN3_CTXT *ctxt; -+ THREAD_TRAP *trap; -+ -+ ASSERT(SPINLOCK_HELD (&dev->IntrLock)); -+ -+ ctxt = ELAN3_DEV_CTX_TABLE(dev, threadTrap->Status.s.Context); -+ -+ if (ctxt == NULL) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "DeliverTProcTrap: context %x invalid\n", threadTrap->Status.s.Context); -+ BumpStat (dev, InvalidContext); -+ } -+ else -+ { -+ if (ELAN3_OP_TPROC_TRAP (ctxt, threadTrap) == OP_DEFER) -+ { -+ if (ELAN3_QUEUE_REALLY_FULL (ctxt->ThreadTrapQ)) -+ { -+ ctxt->Status |= CTXT_COMMAND_OVERFLOW_ERROR; -+ StartSwapoutContext (ctxt, Pend, NULL); -+ } -+ else -+ { -+ trap = ELAN3_QUEUE_BACK (ctxt->ThreadTrapQ, ctxt->ThreadTraps); -+ -+ bcopy (threadTrap, trap, sizeof (THREAD_TRAP)); -+ -+ PRINTF4 (ctxt, DBG_INTR, "DeliverTProcTrap: SP=%08x PC=%08x NPC=%08x StartPC %08x\n", -+ trap->sp, trap->pc, trap->npc, trap->StartPC); -+ PRINTF3 (ctxt, DBG_INTR, " mi=%s trap=%08x dirty=%08x\n", -+ MiToName (trap->mi), trap->TrapBits.Bits, trap->DirtyBits.Bits); -+ PRINTF3 (ctxt, DBG_INTR, " FaultSave : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, trap->FaultSave.s.FSR.Status); -+ PRINTF3 (ctxt, DBG_INTR, " DataFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->DataFaultSave.s.FaultAddress, trap->DataFaultSave.s.EventAddress, trap->DataFaultSave.s.FSR.Status); -+ PRINTF3 (ctxt, DBG_INTR, " InstFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->InstFaultSave.s.FaultAddress, trap->InstFaultSave.s.EventAddress, trap->InstFaultSave.s.FSR.Status); -+ PRINTF3 (ctxt, DBG_INTR, " OpenFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->OpenFaultSave.s.FaultAddress, trap->OpenFaultSave.s.EventAddress, trap->OpenFaultSave.s.FSR.Status); -+ -+ PRINTF4 (ctxt, DBG_INTR, " g0=%08x g1=%08x g2=%08x g3=%08x\n", -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)], trap->Registers[REG_GLOBALS+(1^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(2^WordEndianFlip)], trap->Registers[REG_GLOBALS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " g4=%08x g5=%08x g6=%08x g7=%08x\n", -+ trap->Registers[REG_GLOBALS+(4^WordEndianFlip)], trap->Registers[REG_GLOBALS+(5^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(6^WordEndianFlip)], trap->Registers[REG_GLOBALS+(7^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " o0=%08x o1=%08x o2=%08x o3=%08x\n", -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)], trap->Registers[REG_OUTS+(1^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(2^WordEndianFlip)], trap->Registers[REG_OUTS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " o4=%08x o5=%08x o6=%08x o7=%08x\n", -+ trap->Registers[REG_OUTS+(4^WordEndianFlip)], trap->Registers[REG_OUTS+(5^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)], trap->Registers[REG_OUTS+(7^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " l0=%08x l1=%08x l2=%08x l3=%08x\n", -+ trap->Registers[REG_LOCALS+(0^WordEndianFlip)], trap->Registers[REG_LOCALS+(1^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(2^WordEndianFlip)], trap->Registers[REG_LOCALS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " l4=%08x l5=%08x l6=%08x l7=%08x\n", -+ trap->Registers[REG_LOCALS+(4^WordEndianFlip)], trap->Registers[REG_LOCALS+(5^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(6^WordEndianFlip)], trap->Registers[REG_LOCALS+(7^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " i0=%08x i1=%08x i2=%08x i3=%08x\n", -+ trap->Registers[REG_INS+(0^WordEndianFlip)], trap->Registers[REG_INS+(1^WordEndianFlip)], -+ trap->Registers[REG_INS+(2^WordEndianFlip)], trap->Registers[REG_INS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_INTR, " i4=%08x i5=%08x i6=%08x i7=%08x\n", -+ trap->Registers[REG_INS+(4^WordEndianFlip)], trap->Registers[REG_INS+(5^WordEndianFlip)], -+ trap->Registers[REG_INS+(6^WordEndianFlip)], trap->Registers[REG_INS+(7^WordEndianFlip)]); -+ -+ ELAN3_QUEUE_ADD (ctxt->ThreadTrapQ); -+ kcondvar_wakeupone (&ctxt->Wait, &dev->IntrLock); -+ -+ if (ELAN3_QUEUE_FULL (ctxt->ThreadTrapQ)) -+ { -+ PRINTF0 (ctxt, DBG_INTR, "DeliverTProcTrap: thread queue full, must swap out\n"); -+ ctxt->Status |= CTXT_THREAD_QUEUE_FULL; -+ -+ StartSwapoutContext (ctxt, Pend, NULL); -+ } -+ } -+ } -+ } -+} -+ -+int -+NextTProcTrap (ELAN3_CTXT *ctxt, THREAD_TRAP *trap) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ -+ ASSERT (SPINLOCK_HELD (&dev->IntrLock)); -+ -+ if (ELAN3_QUEUE_EMPTY (ctxt->ThreadTrapQ)) -+ return (0); -+ -+ *trap = *ELAN3_QUEUE_FRONT (ctxt->ThreadTrapQ, ctxt->ThreadTraps); -+ ELAN3_QUEUE_REMOVE (ctxt->ThreadTrapQ); -+ -+ return (1); -+} -+ -+void -+ResolveTProcTrap (ELAN3_CTXT *ctxt, THREAD_TRAP *trap) -+{ -+ int i; -+ int res; -+ E3_Addr StackPointer; -+ -+ PRINTF4 (ctxt, DBG_TPROC, "ResolveTProcTrap: SP=%08x PC=%08x NPC=%08x StartPC %08x\n", -+ trap->sp, trap->pc, trap->npc, trap->StartPC); -+ PRINTF3 (ctxt, DBG_TPROC, " mi=%s trap=%08x dirty=%08x\n", -+ MiToName (trap->mi), trap->TrapBits.Bits, trap->DirtyBits.Bits); -+ PRINTF3 (ctxt, DBG_TPROC, " FaultSave : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, trap->FaultSave.s.FSR.Status); -+ PRINTF3 (ctxt, DBG_TPROC, " DataFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->DataFaultSave.s.FaultAddress, trap->DataFaultSave.s.EventAddress, trap->DataFaultSave.s.FSR.Status); -+ PRINTF3 (ctxt, DBG_TPROC, " InstFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->InstFaultSave.s.FaultAddress, trap->InstFaultSave.s.EventAddress, trap->InstFaultSave.s.FSR.Status); -+ PRINTF3 (ctxt, DBG_TPROC, " OpenFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->OpenFaultSave.s.FaultAddress, trap->OpenFaultSave.s.EventAddress, trap->OpenFaultSave.s.FSR.Status); -+ -+ PRINTF4 (ctxt, DBG_TPROC, " g0=%08x g1=%08x g2=%08x g3=%08x\n", -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)], trap->Registers[REG_GLOBALS+(1^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(2^WordEndianFlip)], trap->Registers[REG_GLOBALS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " g4=%08x g5=%08x g6=%08x g7=%08x\n", -+ trap->Registers[REG_GLOBALS+(4^WordEndianFlip)], trap->Registers[REG_GLOBALS+(5^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(6^WordEndianFlip)], trap->Registers[REG_GLOBALS+(7^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " o0=%08x o1=%08x o2=%08x o3=%08x\n", -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)], trap->Registers[REG_OUTS+(1^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(2^WordEndianFlip)], trap->Registers[REG_OUTS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " o4=%08x o5=%08x o6=%08x o7=%08x\n", -+ trap->Registers[REG_OUTS+(4^WordEndianFlip)], trap->Registers[REG_OUTS+(5^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)], trap->Registers[REG_OUTS+(7^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " l0=%08x l1=%08x l2=%08x l3=%08x\n", -+ trap->Registers[REG_LOCALS+(0^WordEndianFlip)], trap->Registers[REG_LOCALS+(1^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(2^WordEndianFlip)], trap->Registers[REG_LOCALS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " l4=%08x l5=%08x l6=%08x l7=%08x\n", -+ trap->Registers[REG_LOCALS+(4^WordEndianFlip)], trap->Registers[REG_LOCALS+(5^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(6^WordEndianFlip)], trap->Registers[REG_LOCALS+(7^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " i0=%08x i1=%08x i2=%08x i3=%08x\n", -+ trap->Registers[REG_INS+(0^WordEndianFlip)], trap->Registers[REG_INS+(1^WordEndianFlip)], -+ trap->Registers[REG_INS+(2^WordEndianFlip)], trap->Registers[REG_INS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " i4=%08x i5=%08x i6=%08x i7=%08x\n", -+ trap->Registers[REG_INS+(4^WordEndianFlip)], trap->Registers[REG_INS+(5^WordEndianFlip)], -+ trap->Registers[REG_INS+(6^WordEndianFlip)], trap->Registers[REG_INS+(7^WordEndianFlip)]); -+ -+ -+ BumpUserStat (ctxt, TProcTraps); -+ -+ switch (trap->mi) -+ { -+ case MI_UnimplementedError: -+ { -+ /* -+ * This occurs if the threads processor trapped. All other cases will be for the ucode -+ * thread trapping. -+ */ -+ int restart = 1; -+ int skip = 0; -+ -+ PRINTF1 (ctxt, DBG_TPROC, "TProc: Mi=Unimp. Using trap->TrapBits=%x\n", trap->TrapBits.Bits); -+ -+ /* -+ * Data Access Exception. -+ */ -+ if (trap->TrapBits.s.DataAccessException) -+ { -+ ASSERT (CTXT_IS_KERNEL(ctxt) || trap->DataFaultSave.s.FSR.Status == 0 || -+ ctxt->Capability.cap_mycontext == trap->DataFaultSave.s.FaultContext); -+ -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: DataAccessException %08x\n", trap->DataFaultSave.s.FaultAddress); -+ -+ if ((res = elan3_pagefault (ctxt, &trap->DataFaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: elan3_pagefault failed for data %08x\n", -+ trap->DataFaultSave.s.FaultAddress); -+ -+ if (ElanException (ctxt, EXCEPTION_INVALID_ADDR, THREAD_PROC, trap, &trap->DataFaultSave, res) != OP_IGNORE) -+ restart = 0; -+ } -+ } -+ -+ /* -+ * Instruction Access Exception. -+ */ -+ if (trap->TrapBits.s.InstAccessException) -+ { -+ ASSERT (CTXT_IS_KERNEL (ctxt) || trap->InstFaultSave.s.FSR.Status == 0 || -+ ctxt->Capability.cap_mycontext == trap->InstFaultSave.s.FaultContext); -+ -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: InstAccessException %08x\n", trap->InstFaultSave.s.FaultAddress); -+ -+ if ((res = elan3_pagefault (ctxt, &trap->InstFaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: elan3_pagefault failed for inst %08x\n", -+ trap->InstFaultSave.s.FaultAddress); -+ -+ ElanException (ctxt, EXCEPTION_INVALID_ADDR, THREAD_PROC, trap, &trap->InstFaultSave, res); -+ restart = 0; -+ } -+ } -+ -+ /* -+ * Forced TProc trap/Unimplemented instruction -+ * -+ * If there is a force tproc trap then don't look at -+ * the unimplemented instruction bit - since it can -+ * be set in obscure circumstances. -+ */ -+ if (trap->TrapBits.s.ForcedTProcTrap) -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: forced tproc trap, restarting\n"); -+ else if (trap->TrapBits.s.Unimplemented) -+ { -+ E3_uint32 instr = ELAN3_OP_LOAD32 (ctxt, trap->pc & PC_MASK); -+ -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: unimplemented instruction %08x\n", instr); -+ -+ if ((instr & OPCODE_MASK) == OPCODE_Ticc && -+ (instr & OPCODE_IMM) == OPCODE_IMM && -+ (Ticc_COND(instr) == Ticc_TA)) -+ { -+ switch (INSTR_IMM(instr)) -+ { -+ case ELAN3_ELANCALL_TRAPNUM: -+ /* -+ * Since the thread cannot easily access the global variable which holds -+ * the elan system call number, we provide a different trap for the elan -+ * system call, and copy the system call number into %g1 before calling -+ * ThreadSyscall(). -+ */ -+ BumpUserStat (ctxt, ThreadElanCalls); -+ -+ if (ThreadElancall (ctxt, trap, &skip) != ESUCCESS) -+ { -+ ElanException (ctxt, EXCEPTION_BAD_SYSCALL, THREAD_PROC, trap); -+ restart = 0; -+ } -+ break; -+ -+ case ELAN3_SYSCALL_TRAPNUM: -+ BumpUserStat (ctxt, ThreadSystemCalls); -+ -+ if (ThreadSyscall (ctxt, trap, &skip) != ESUCCESS) -+ { -+ ElanException (ctxt, EXCEPTION_BAD_SYSCALL, THREAD_PROC, trap); -+ restart = 0; -+ } -+ break; -+ -+ case ELAN3_DEBUG_TRAPNUM: -+ ElanException (ctxt, EXCEPTION_DEBUG, THREAD_PROC, trap); -+ skip = 1; -+ break; -+ -+ case ELAN3_ABORT_TRAPNUM: -+ default: -+ ElanException (ctxt, EXCEPTION_UNIMP_INSTR, THREAD_PROC, trap, instr); -+ restart = 0; -+ break; -+ } -+ -+ } -+ else -+ { -+ ElanException (ctxt, EXCEPTION_UNIMP_INSTR, THREAD_PROC, trap, instr); -+ restart = 0; -+ } -+ } -+ -+ /* -+ * Faulted fetching routes. -+ */ -+ if (trap->TrapBits.s.OpenRouteFetch) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: OpenRouteFetch %08x\n", trap->OpenFaultSave.s.FaultAddress); -+ -+ if ((res = ResolveVirtualProcess (ctxt, trap->OpenFaultSave.s.FaultAddress)) != ESUCCESS && -+ ElanException (ctxt, EXCEPTION_INVALID_PROCESS, THREAD_PROC, trap, trap->DataFaultSave.s.FaultAddress, res) != OP_IGNORE) -+ { -+ restart = 0; -+ } -+ else if (RollThreadToClose (ctxt, trap, E3_PAckDiscard) != ESUCCESS) /* Force a discard */ -+ { -+ restart = 0; -+ } -+ } -+ -+ /* -+ * Thread Timeout -+ */ -+ if (trap->TrapBits.s.ThreadTimeout) -+ { -+ if (ElanException (ctxt, EXCEPTION_PACKET_TIMEOUT, THREAD_PROC, trap) != OP_IGNORE) -+ restart = 0; -+ else -+ { -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: timeout or PAckError!\n"); -+ -+ /* Might deschedule the thread for a while or mark the link error here. */ -+ if (! trap->TrapBits.s.OutputWasOpen && RollThreadToClose (ctxt, trap, trap->TrapBits.s.PacketAckValue) != ESUCCESS) -+ { -+ restart = 0; -+ } -+ } -+ } -+ -+ /* -+ * Open exception -+ */ -+ if (trap->TrapBits.s.OpenException) -+ { -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: open exception\n"); -+ if (ElanException (ctxt, EXCEPTION_THREAD_KILLED, THREAD_PROC, trap) != OP_IGNORE) -+ restart = 0; -+ } -+ -+ /* -+ * Too many instructions. -+ */ -+ if (trap->TrapBits.s.TrapForTooManyInsts) -+ { -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: too many instructions\n"); -+ if (ElanException (ctxt, EXCEPTION_THREAD_KILLED, THREAD_PROC, trap) != OP_IGNORE) -+ restart = 0; -+ } -+ -+ if (restart) -+ { -+ /* -+ * If the output was open when the trap was taken then the trap code must move -+ * the PC on past the close instruction and simulate the effect of all the instructions -+ * that do not output onto the link. The value of the ack received is then used to -+ * simulate the close instruction. -+ */ -+ if (trap->TrapBits.s.OutputWasOpen && RollThreadToClose(ctxt, trap, trap->TrapBits.s.PacketAckValue) != ESUCCESS) -+ { -+ /* -+ * Don't restart if we couldn't roll it forweards -+ * to a close instruction. -+ */ -+ break; -+ } -+ -+ /* -+ * We must check back 3 instructions from the PC, and if we see the -+ * c_close_cookie() sequence then we must execute the instructions to -+ * the end of it. -+ */ -+ /* XXXX: code to be written */ -+ -+ StackPointer = SaveThreadToStack (ctxt, trap, skip); -+ -+ ReissueStackPointer (ctxt, StackPointer); -+ } -+ -+ break; -+ } -+ -+ /* -+ * This case is different from the others as %o6 has been overwritten with -+ * the SP. The real PC can be read from StartPC and written back -+ * into %o6 on the stack. -+ */ -+ case MI_TProcNext: /* Reading the outs block */ -+ { -+ E3_Addr stack = (trap->sp & SP_MASK) - sizeof (E3_Stack); -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: faulted writing StartPc to o6\n"); -+ ElanException (ctxt, EXCEPTION_CANNOT_SAVE_THREAD, THREAD_PROC, NULL); -+ break; -+ } -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Outs[6]), trap->StartPC & PC_MASK); -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ /* DROPTHROUGH */ -+ } -+ /* -+ * all of these will be generated when starting up a thread. -+ * Just re-issue the command after fixing the trap. The ucode keeps the startup -+ * from trap information in Thread_Desc_SP while it is still loading the regs. -+ */ -+ case MI_WaitForGlobalsRead: /* Reading the globals block (trap restart) */ -+ case MI_WaitForNPCRead: /* Reading the nPC, V and C (trap restart) */ -+ case MI_WaitForPCload: /* Reading the PC, N and Z (trap restart) */ -+ case MI_WaitForInsRead: /* Reading the ins block (trap restart) */ -+ case MI_WaitForLocals: /* Reading the ins block (trap restart) */ -+ case MI_WaitForPCload2: /* Reading the PC (normal thread start) */ -+ case MI_WaitForSpStore: /* Writing the SP to the outs block */ -+ PRINTF2 (ctxt, DBG_TPROC, "ResolveTProcTrap: %s %08x\n", MiToName (trap->mi), trap->InstFaultSave.s.FaultAddress); -+ -+ if ((res = elan3_pagefault (ctxt, &trap->FaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: elan3_pagefault failed at %08x\n", -+ trap->FaultSave.s.FaultAddress); -+ if (ElanException (ctxt, EXCEPTION_INVALID_ADDR, THREAD_PROC, &trap->FaultSave, trap, res) != OP_IGNORE) -+ break; -+ } -+ -+ ReissueStackPointer (ctxt, trap->sp); -+ break; -+ -+ /* -+ * These traps could occur after the threads proc has stopped (either for a wait, -+ * break, or suspend, but not a trap). Must simulate the uCode's job. -+ */ -+ case MI_WaitForOutsWrite: /* Writing the outs block */ -+ case MI_WaitForNPCWrite: /* Writing the nPC block */ -+ { -+ E3_uint32 DeschedBits = (trap->TrapBits.Bits & E3_TProcDescheduleMask); -+ E3_Addr stack = (trap->sp & SP_MASK) - sizeof (E3_Stack); -+ -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: trapped on %s while stopping a thread\n", MiToName(trap->mi)); -+ -+ /* -+ * Copy npc into o6. -+ */ -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)] = trap->npc; -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: faulted writing outs to stack\n"); -+ ElanException (ctxt, EXCEPTION_CANNOT_SAVE_THREAD, THREAD_PROC, NULL); -+ break; -+ } -+ -+ /* -+ * Now write the outs back to the stack. NOTE then endian flip is undone. -+ */ -+ for (i = 0; i < 8; i++) -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Outs[i]), trap->Registers[REG_OUTS+(i^WordEndianFlip)]); -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ /* -+ * thread has been saved. Now find out why the thread proc stopped. -+ */ -+ if (DeschedBits == E3_TProcDescheduleSuspend) -+ { -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: suspend instruction executed\n"); -+ break; -+ } -+ -+ /* -+ * Break. Just reissue the command. -+ */ -+ if (DeschedBits == E3_TProcDescheduleBreak) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: break instruction, reissue sp %08x\n", trap->sp); -+ ReissueStackPointer (ctxt, trap->sp); -+ break; -+ } -+ -+ ASSERT (DeschedBits == E3_TProcDescheduleWait); -+ -+ /* DROPTHROUGH to fix up a wait event */ -+ } -+ -+ /* -+ * Trapped here trying to execute a wait instruction. All the thread state has already -+ * been saved and the trap has been fixed so simplest thing to do is to start the -+ * thread up at the wait instruction again. -+ */ -+ case MI_WaitForEventWaitAddr: /* Reading back the %o0,%o1 pair for a -+ wait event instr. */ -+ case MI_WaitForWaitEventAccess: /* Locked dword read of the event location. -+ Note that this read is done with write -+ permissions so we never get a trap on the write */ -+ { -+ E3_Addr stack = (trap->sp & SP_MASK) - sizeof (E3_Stack); -+ -+ if ((res = elan3_pagefault (ctxt, &trap->FaultSave, 1)) != ESUCCESS) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "ResolveTProcTrap: elan3_pagefault failed at %08x\n", -+ trap->FaultSave.s.FaultAddress); -+ if (ElanException (ctxt, EXCEPTION_INVALID_ADDR, THREAD_PROC, trap, &trap->DataFaultSave, res) != OP_IGNORE) -+ break; -+ } -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF0 (ctxt, DBG_TPROC, "ResolveTProcTrap: faulted writing pc to stack\n"); -+ ElanException (ctxt, EXCEPTION_CANNOT_SAVE_THREAD, THREAD_PROC, NULL); -+ break; -+ } -+ -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Outs[6]), trap->pc); -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ ReissueStackPointer (ctxt, trap->sp); -+ break; -+ } -+ -+ /* -+ * Assume the fault will be fixed by FixupEventTrap. -+ */ -+ default: -+ FixupEventTrap (ctxt, THREAD_PROC, trap, trap->mi, &trap->FaultSave, 0); -+ break; -+ } -+} -+ -+int -+TProcNeedsRestart (ELAN3_CTXT *ctxt) -+{ -+ return (ctxt->ItemCount[LIST_THREAD] != 0); -+} -+ -+void -+RestartTProcItems (ELAN3_CTXT *ctxt) -+{ -+ void *item; -+ E3_uint32 StackPointer; -+ -+ kmutex_lock (&ctxt->SwapListsLock); -+ -+ while (ctxt->ItemCount[LIST_THREAD]) -+ { -+ if (! ELAN3_OP_GET_WORD_ITEM (ctxt, LIST_THREAD, &item, &StackPointer)) -+ ctxt->ItemCount[LIST_THREAD] = 0; -+ else -+ { -+ if (IssueCommand (ctxt, offsetof (E3_CommandPort, RunThread), StackPointer, 0) == ISSUE_COMMAND_RETRY) -+ { -+ ELAN3_OP_PUTBACK_ITEM (ctxt, LIST_THREAD, item); -+ kmutex_unlock (&ctxt->SwapListsLock); -+ return; -+ } -+ -+ ctxt->ItemCount[LIST_THREAD]--; -+ ELAN3_OP_FREE_WORD_ITEM (ctxt, item); -+ } -+ } -+ kmutex_unlock (&ctxt->SwapListsLock); -+} -+ -+E3_Addr -+SaveThreadToStack (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, int SkipInstruction) -+{ -+ E3_Addr stack = (trap->sp & SP_MASK) - sizeof (E3_Stack); -+ E3_Addr orflag; -+ register int i; -+ -+ /* -+ * When the thread deschedules normally, the N & Z flags are written -+ * to the stack in o6, and the V & C flags are lost. -+ * Since the Elan will store the NPC into o6 (to skip the instruction), -+ * the CC flags are visible to the trap handler in the trapped PC and NPC. -+ * If the instruction needs to be re-executed then the CC flags need to be -+ * kept in the right place to be read in when the thread re-starts. -+ * -+ * PC has N & Z from trapped NPC. -+ * NPC has V & C from trapped PC. -+ */ -+ if (SkipInstruction) -+ { -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)] = trap->npc; -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)] = ((trap->npc & PC_MASK) + 4) | (trap->pc & CC_MASK); -+ } -+ else -+ { -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)] = (trap->pc & PC_MASK) | (trap->npc & CC_MASK); -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)] = (trap->npc & PC_MASK) | (trap->pc & CC_MASK); -+ } -+ -+ if (ELAN3_OP_START_FAULT_CHECK(ctxt)) -+ { -+ PRINTF0 (ctxt, DBG_TPROC, "RestartThread: faulted writing out thread\n"); -+ ELAN3_OP_END_FAULT_CHECK(ctxt); -+ -+ ElanException (ctxt, EXCEPTION_CANNOT_SAVE_THREAD, THREAD_PROC, NULL); -+ return ((E3_Addr) 0); -+ } -+ -+ -+#ifdef DEBUG_PRINTF -+ PRINTF4 (ctxt, DBG_TPROC, "SaveThreadToStack: SP=%08x PC=%08x NPC=%08x DIRTY=%08x\n", -+ trap->sp, trap->pc, trap->npc, trap->DirtyBits.Bits); -+ if (trap->DirtyBits.s.GlobalsDirty) -+ { -+ PRINTF4 (ctxt, DBG_TPROC, " g0=%08x g1=%08x g2=%08x g3=%08x\n", -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)], trap->Registers[REG_GLOBALS+(1^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(2^WordEndianFlip)], trap->Registers[REG_GLOBALS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " g4=%08x g5=%08x g6=%08x g7=%08x\n", -+ trap->Registers[REG_GLOBALS+(4^WordEndianFlip)], trap->Registers[REG_GLOBALS+(5^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(6^WordEndianFlip)], trap->Registers[REG_GLOBALS+(7^WordEndianFlip)]); -+ } -+ if (trap->DirtyBits.s.OutsDirty) -+ { -+ PRINTF4 (ctxt, DBG_TPROC, " o0=%08x o1=%08x o2=%08x o3=%08x\n", -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)], trap->Registers[REG_OUTS+(1^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(2^WordEndianFlip)], trap->Registers[REG_OUTS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " o4=%08x o5=%08x o6=%08x o7=%08x\n", -+ trap->Registers[REG_OUTS+(4^WordEndianFlip)], trap->Registers[REG_OUTS+(5^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)], trap->Registers[REG_OUTS+(7^WordEndianFlip)]); -+ } -+ if (trap->DirtyBits.s.LocalsDirty) -+ { -+ PRINTF4 (ctxt, DBG_TPROC, " l0=%08x l1=%08x l2=%08x l3=%08x\n", -+ trap->Registers[REG_LOCALS+(0^WordEndianFlip)], trap->Registers[REG_LOCALS+(1^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(2^WordEndianFlip)], trap->Registers[REG_LOCALS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " l4=%08x l5=%08x l6=%08x l7=%08x\n", -+ trap->Registers[REG_LOCALS+(4^WordEndianFlip)], trap->Registers[REG_LOCALS+(5^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(6^WordEndianFlip)], trap->Registers[REG_LOCALS+(7^WordEndianFlip)]); -+ } -+ if (trap->DirtyBits.s.InsDirty) -+ { -+ PRINTF4 (ctxt, DBG_TPROC, " i0=%08x i1=%08x i2=%08x i3=%08x\n", -+ trap->Registers[REG_INS+(0^WordEndianFlip)], trap->Registers[REG_INS+(1^WordEndianFlip)], -+ trap->Registers[REG_INS+(2^WordEndianFlip)], trap->Registers[REG_INS+(3^WordEndianFlip)]); -+ PRINTF4 (ctxt, DBG_TPROC, " i4=%08x i5=%08x i6=%08x i7=%08x\n", -+ trap->Registers[REG_INS+(4^WordEndianFlip)], trap->Registers[REG_INS+(5^WordEndianFlip)], -+ trap->Registers[REG_INS+(6^WordEndianFlip)], trap->Registers[REG_INS+(7^WordEndianFlip)]); -+ } -+#endif -+ -+ PRINTF1 (ctxt, DBG_TPROC, "flushing registers to stack %08x\n", stack); -+ -+ /* -+ * NOTE - store the register to the stack in reverse order, since the stack -+ * will be allocated in sdram, and we cannot use the sdram accessing functions -+ * here, as it is "mapped" in user-space. -+ */ -+ for (i = 0; i < 8; i++) -+ { -+ if (trap->DirtyBits.s.GlobalsDirty & (1 << i)) -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Globals[i]), trap->Registers[REG_GLOBALS+(i^WordEndianFlip)]); -+ if (trap->DirtyBits.s.OutsDirty & (1 << i)) -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Outs[i]), trap->Registers[REG_OUTS+(i^WordEndianFlip)]); -+ if (trap->DirtyBits.s.LocalsDirty & (1 << i)) -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Locals[i]), trap->Registers[REG_LOCALS+(i^WordEndianFlip)]); -+ if (trap->DirtyBits.s.InsDirty & (1 << i)) -+ ELAN3_OP_STORE32 (ctxt, stack + offsetof (E3_Stack, Ins[i]), trap->Registers[REG_INS+(i^WordEndianFlip)]); -+ } -+ -+ /* always restore all registers */ -+ orflag = ThreadRestartFromTrapBit | ThreadReloadAllRegs; -+ -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ return (trap->sp | orflag); -+} -+ -+void -+ReissueStackPointer (ELAN3_CTXT *ctxt, E3_Addr StackPointer) -+{ -+ PRINTF1 (ctxt, DBG_TPROC, "ReissueStackPointer : Queue SP %08x\n", StackPointer); -+ -+ kmutex_lock (&ctxt->SwapListsLock); -+ ctxt->ItemCount[LIST_THREAD]++; -+ ELAN3_OP_PUT_WORD_ITEM (ctxt, LIST_THREAD, StackPointer); -+ kmutex_unlock (&ctxt->SwapListsLock); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/tprocinsts.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/tprocinsts.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/tprocinsts.c 2005-06-01 23:12:54.595439712 -0400 -@@ -0,0 +1,401 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: tprocinsts.c,v 1.20 2003/09/24 13:57:25 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/tprocinsts.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAXINSTR 256 /* # Instructions to look at while looking for close */ -+ -+static E3_uint32 ALU (ELAN3_CTXT *ctxt, -+ E3_uint32 fcode, E3_uint32 X, E3_uint32 Y, -+ E3_uint32 *Z, E3_uint32 *N, E3_uint32 *C, E3_uint32 *V); -+ -+char *OpcodeNames[] = -+{ -+ "ADD ", -+ "AND ", -+ "OR ", -+ "XOR ", -+ "SUB ", -+ "ANDN ", -+ "ORN ", -+ "XNOR ", -+ "ADDX ", -+ "UNIP ", -+ "UMUL ", -+ "SMUL ", -+ "SUBX ", -+ "UNIP ", -+ "UDIV ", -+ "SDIV ", -+ "ADDcc ", -+ "ANDcc ", -+ "ORcc ", -+ "XORcc ", -+ "SUBcc ", -+ "ANDNcc", -+ "ORNcc ", -+ "XNORcc", -+ "ADDXcc", -+ "UNIPcc", -+ "UMULcc", -+ "SMULcc", -+ "SUBXcc", -+ "UNIPcc", -+ "UDIVcc", -+ "SDIVcc" -+}; -+ -+#define REGISTER_VALUE(trap, rN) (((rN) == 0) ? 0 : (trap)->Registers[(rN)^WordEndianFlip]) -+#define ASSIGN_REGISTER(trap, rN, value) ((rN) != 0 ? trap->Registers[(rN)^WordEndianFlip] = (value) : 0) -+ -+int -+RollThreadToClose (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, E3_uint32 PAckVal) -+{ -+ E3_Addr pc = (trap->pc & PC_MASK); -+ E3_Addr npc = (trap->npc & PC_MASK); -+ E3_uint32 Z = (trap->npc & PSR_Z_BIT) ? 1 : 0; -+ E3_uint32 N = (trap->npc & PSR_N_BIT) ? 1 : 0; -+ E3_uint32 C = (trap->pc & PSR_C_BIT) ? 1 : 0; -+ E3_uint32 V = (trap->pc & PSR_V_BIT) ? 1 : 0; -+ E3_uint32 instr; -+ E3_Addr addr; -+ -+ if (ELAN3_OP_START_FAULT_CHECK (ctxt)) -+ { -+ failed: -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ ElanException (ctxt, EXCEPTION_SIMULATION_FAILED, THREAD_PROC, trap); -+ return (EFAULT); -+ } -+ -+ /* -+ * Thread trapped with output open, or while closing, -+ * so roll the PC forwards to the instruction after the -+ * next c_close, and execute that with the register -+ * specified in c_close set to the trap which occured. -+ * (This is not 1 which means an ACK) -+ */ -+ PRINTF1 (ctxt, DBG_TPROC, "RollThreadToClose: roll pc %x to c_close\n", pc); -+ -+ for (;;) -+ { -+ instr = ELAN3_OP_LOAD32 (ctxt, pc); -+ -+ PRINTF2 (ctxt, DBG_TPROC, "RollThreadToClose: PC=%x INSTR=%x\n", pc, instr); -+ -+ switch (OPCODE_CLASS(instr)) -+ { -+ case OPCODE_CLASS_0: -+ switch ((instr) & OPCODE_CLASS0_MASK) -+ { -+ case OPCODE_SETHI: -+ PRINTF3 (ctxt, DBG_TPROC, "PC %x : sethi r%d = %x\n", pc, INSTR_RD(instr), instr << 10); -+ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), instr << 10); -+ break; -+ -+ case OPCODE_SENDREG: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : sendreg\n", pc); -+ break; -+ -+ case OPCODE_SENDMEM: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : sendmem\n", pc); -+ break; -+ -+ case OPCODE_BICC: -+ { -+ int DoBranch = (instr >> 28) & 1; -+ int CondBranch = 1; -+ E3_Addr OldnPC = npc; -+ -+ PRINTF5 (ctxt, DBG_TPROC, "PC %x : Bicc Z=%x N=%x C=%x V=%x ", pc, Z, N, C, V); -+ switch (instr & OPCODE_BICC_MASK) -+ { -+ case OPCODE_BICC_BN: CondBranch = 0; break; -+ case OPCODE_BICC_BE: DoBranch ^= Z; break; -+ case OPCODE_BICC_BLE: DoBranch ^= Z | (N ^ V); break; -+ case OPCODE_BICC_BL: DoBranch ^= N ^ V; break; -+ case OPCODE_BICC_BLEU: DoBranch ^= C | Z; break; -+ case OPCODE_BICC_BCS: DoBranch ^= C; break; -+ case OPCODE_BICC_BNEG: DoBranch ^= N; break; -+ case OPCODE_BICC_BVS: DoBranch ^= V; break; -+ } -+ -+ /* Do the branch */ -+ if (DoBranch != 0) -+ { -+ npc = pc + (((instr & 0x3fffff) << 2) | -+ (((instr & 0x200000) != 0) ? 0xff000000 : 0)); -+ -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : branch taken to %x\n", pc, npc); -+ } -+ else -+ { -+ npc = npc + 4; -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : branch not taken\n", pc); -+ } -+ pc = OldnPC; -+ -+ /* Test if the next is annuled */ -+ if (((instr & OPCODE_BICC_ANNUL) != 0) & -+ ((DoBranch == 0) | (CondBranch == 0))) -+ { -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : branch annulled\n", pc); -+ -+ pc = npc; -+ npc += 4; -+ } -+ -+ /* -+ * we've already consumed the instruction - so continue rather -+ * than break; -+ */ -+ continue; -+ } -+ -+ default: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : unknown class 0 instr %x\n", pc, instr); -+ goto failed; -+ } -+ break; -+ -+ case OPCODE_CLASS_1: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : unknown class 1 instr %x\n", pc, instr); -+ goto failed; -+ -+ case OPCODE_CLASS_2: -+ { -+ E3_uint32 X = REGISTER_VALUE (trap, INSTR_RS1(instr)); -+ E3_uint32 Y = (instr & OPCODE_IMM) ? INSTR_IMM(instr) : REGISTER_VALUE (trap, INSTR_RS2(instr)); -+ -+ if ((instr & OPCODE_NOT_ALUOP) == 0) -+ { -+ E3_uint32 fcode = (instr >> OPCODE_FCODE_SHIFT) & OPCODE_FCODE_MASK; -+ E3_uint32 result = ALU (ctxt, fcode, X, Y, &Z, &N, &C, &V); -+ -+ PRINTF5 (ctxt, DBG_TPROC, "PC %x : %s %x %x -> %x", pc, OpcodeNames[fcode], X, Y, result); -+ PRINTF4 (ctxt, DBG_TPROC, " Z=%x N=%x C=%x V=%x\n", Z, N, C, V); -+ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), result); -+ } -+ else -+ { -+ switch (instr & OPCODE_MASK) -+ { -+ case OPCODE_OPEN: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : c_open\n", pc); -+ break; -+ -+ case OPCODE_CLOSE: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : c_close\n", pc); -+ goto found_close; -+ -+ case OPCODE_SLL: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : SLL\n", pc); -+ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), X << Y); -+ break; -+ -+ case OPCODE_SRL: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : SRL\n", pc); -+ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), X >> Y); -+ break; -+ -+ case OPCODE_SRA: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : SRA\n", pc); -+ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), X >> Y); -+ break; -+ -+ case OPCODE_BREAKTEST: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : BREAKTEST not allowed while open\n", pc); -+ goto failed; -+ -+ case OPCODE_BREAK: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : BREAK not allowed while open\n", pc); -+ goto failed; -+ -+ case OPCODE_SUSPEND: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : SUSPEND not allowed while open\n", pc); -+ goto failed; -+ -+ case OPCODE_WAIT: -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : WAIT not allowed while open\n", pc); -+ goto failed; -+ -+ default: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : unknown class 2 instr %x\n", pc, instr); -+ goto failed; -+ } -+ } -+ break; -+ } -+ -+ case OPCODE_CLASS_3: -+ { -+ if ((instr & OPCODE_IMM) != 0) -+ addr = REGISTER_VALUE (trap, INSTR_RS1(instr)) + INSTR_IMM(instr); -+ else -+ addr = (REGISTER_VALUE (trap, INSTR_RS1(instr)) + -+ REGISTER_VALUE (trap, INSTR_RS2(instr))); -+ -+ switch (instr & OPCODE_MASK) -+ { -+ case OPCODE_LD: -+ PRINTF3 (ctxt, DBG_TPROC, "PC %x : LD [%x], r%d\n", pc, addr, INSTR_RD(instr)); -+ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), ELAN3_OP_LOAD32 (ctxt, addr)); -+ break; -+ -+ case OPCODE_LDD: -+ case OPCODE_LDBLOCK16: -+ case OPCODE_LDBLOCK32: -+ case OPCODE_LDBLOCK64: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : LDBLOCKx @ %x is not possible while output open\n", pc, addr); -+ goto failed; -+ -+ case OPCODE_ST: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : ST @ %x\n", pc, addr); -+ -+ ELAN3_OP_STORE32 (ctxt, addr, REGISTER_VALUE (trap, INSTR_RD(instr))); -+ break; -+ -+ case OPCODE_STD: -+ case OPCODE_STBLOCK16: -+ case OPCODE_STBLOCK32: -+ case OPCODE_STBLOCK64: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : STD @ %x is not posisble while output open\n", pc, addr); -+ goto failed; -+ -+ case OPCODE_SWAP: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : SWAP @ %x is not posible while output open\n", pc, addr); -+ goto failed; -+ -+ default: -+ PRINTF2 (ctxt, DBG_TPROC, "PC %x : unknown class 3 instr %x\n", pc, instr); -+ goto failed; -+ } -+ break; -+ }} -+ -+ pc = npc; -+ npc += 4; -+ } -+ -+found_close: -+ ELAN3_OP_END_FAULT_CHECK (ctxt); -+ -+ PRINTF1 (ctxt, DBG_TPROC, "PC %x : c_close\n", pc); -+ -+ /* -+ * Found the new pc, and have the close instruction in *instr -+ */ -+ ASSIGN_REGISTER (trap, INSTR_RD(instr), PAckVal); -+ -+ /* -+ * Move to instruction after close. -+ */ -+ trap->pc = npc; -+ -+ /* Insert the value of Z and N from the close inst */ -+ trap->npc = (npc + 4) | ((PAckVal == E3_PAckOk) ? 1 : -+ (PAckVal == E3_PAckTestFail) ? 2 : 0); -+ -+ return (ESUCCESS); -+} -+ -+E3_uint32 -+ALU (ELAN3_CTXT *ctxt, -+ E3_uint32 fcode, E3_uint32 X, E3_uint32 Y, -+ E3_uint32 *Z, E3_uint32 *N, E3_uint32 *C, E3_uint32 *V) -+{ -+ E3_uint32 XMSB, YMSB, ZMSB, Cprime; -+ E3_uint32 Yprime; -+ E3_uint32 Result=0; -+ -+ Yprime = ((fcode >> 2) & 1) ? ~Y : Y; -+ Cprime = ((fcode >> 2) & 1) ^ (*C & ((fcode >> 3) & 1)); -+ XMSB = (X >> 31) & 1; -+ YMSB = (Yprime >> 31) & 1; -+ /* mul or div */ -+ if ((fcode & 0xa) == 0xa) -+ { -+ PRINTF0 (ctxt, DBG_TPROC, "ALU: tried a multiply or a divide\n"); -+ return (0); -+ } -+ -+ switch (fcode & 3) -+ { -+ /*ADD */ -+ case 0: -+ Result = X + Yprime + Cprime ; -+ if ((fcode & 0x10) == 0) -+ return (Result); -+ -+ ZMSB = Result >> 31; -+ *V = ((XMSB & YMSB & ~ZMSB) | (~XMSB &~YMSB & ZMSB)); -+ *C = ((fcode >> 2) & 1) ^ ( (XMSB & YMSB) | (~ZMSB & (XMSB | YMSB))); -+ break; -+ -+ /*AND */ -+ case 1: -+ Result = X & Yprime ; -+ if ((fcode & 0x10) == 0) -+ return (Result); -+ -+ *V = 0; -+ *C = 0; -+ break; -+ -+ /*OR */ -+ case 2: -+ Result = X | Yprime ; -+ if ((fcode & 0x10) == 0) -+ return (Result); -+ -+ *V = 0; -+ *C = 0; -+ break; -+ -+ /*XOR */ -+ case 3: -+ Result = X ^ Yprime ; -+ if ((fcode & 0x10) == 0) -+ return (Result); -+ -+ *V = 0; -+ *C = 0; -+ break; -+ } -+ -+ *Z = (Result == 0) ? 1 : 0; -+ *N = (Result >> 31) & 1; -+ -+ return (Result); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/tproc_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/tproc_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/tproc_linux.c 2005-06-01 23:12:54.596439560 -0400 -@@ -0,0 +1,215 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: tproc_linux.c,v 1.19.2.1 2004/10/28 17:08:56 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/tproc_linux.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+ -+#ifdef NO_ABI -+#include -+extern asmlinkage long sys_open(const char *, int, int); -+extern asmlinkage ssize_t sys_write(unsigned int, const char *, size_t); -+extern asmlinkage ssize_t sys_read(unsigned int, char *, size_t); -+extern asmlinkage off_t sys_lseek(unsigned int, off_t, unsigned int); -+extern asmlinkage long sys_poll(struct pollfd *, unsigned int, long); -+extern asmlinkage long sys_kill(int, int); -+#else -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * NOTE: system calls from kernel on Linux are different on alpha and i386 -+ * on alpha they return -errno on failure -+ * on i386 they return -1 on failure and set errno -+ */ -+ -+static void -+ReturnSyscall (THREAD_TRAP *trap, unsigned long rc, int *skip) -+{ -+ if (rc >= (unsigned long) (-130)) -+ { -+ trap->pc |= PSR_C_BIT; /* clear carry to indicate failure */ -+ -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)] = -rc; -+ } -+ else -+ { -+ trap->pc &= ~PSR_C_BIT; /* set carry to indicate success */ -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)] = rc; -+ } -+ trap->Registers[REG_OUTS+(1^WordEndianFlip)] = 0; -+ *skip = 1; -+} -+ -+static void -+dump_regs(ELAN3_CTXT *ctxt, THREAD_TRAP *trap) -+{ -+ PRINTF (ctxt, DBG_TPROC, " OUTS %08x %08x %08x %08x\n", -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(1^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(2^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(3^WordEndianFlip)]); -+ PRINTF (ctxt, DBG_TPROC, " %08x %08x %08x %08x\n", -+ trap->Registers[REG_OUTS+(4^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(5^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(7^WordEndianFlip)]); -+} -+ -+int -+ThreadSyscall (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, int *skip) -+{ -+ int code; -+ caddr_t maddr; -+ struct file *file; -+ unsigned long rc; -+ int i; -+ uintptr_t av[6]; -+ uintptr_t ptr; -+ -+ PRINTF (ctxt, DBG_TPROC, "ThreadSyscall: PC %08x G1 %08x\n", -+ trap->pc, trap->Registers[REG_GLOBALS+(1^WordEndianFlip)]); -+ dump_regs(ctxt, trap); -+ -+ code = trap->Registers[REG_GLOBALS+(1^WordEndianFlip)]; -+ -+ /* Copy the system call arguments from %o0-%o5 */ -+ for (i = 0; i < 6; i++) -+ av[i] = trap->Registers[REG_OUTS+(i^WordEndianFlip)]; -+ -+ rc = (unsigned long) -EINVAL; -+ -+ switch (code) { -+ case ELAN3_SYS_open: -+ maddr = elan3mmu_mainaddr (ctxt->Elan3mmu, (E3_Addr) av[0]); -+ if (maddr != NULL) -+ rc = sys_open((const char *)maddr, av[1], av[2]); -+ break; -+ -+ case ELAN3_SYS_close: -+ rc = sys_close(av[0]); -+ break; -+ -+ case ELAN3_SYS_write: -+ maddr = elan3mmu_mainaddr (ctxt->Elan3mmu, (E3_Addr) av[1]); -+ if (maddr != NULL) -+ rc = sys_write(av[0], (const char *)maddr, av[2]); -+ break; -+ -+ case ELAN3_SYS_read: -+ maddr = elan3mmu_mainaddr (ctxt->Elan3mmu, (E3_Addr) av[1]); -+ if (maddr != NULL) -+ rc = sys_read(av[0], (char *)maddr, av[2]); -+ break; -+ -+ case ELAN3_SYS_poll: -+ maddr = elan3mmu_mainaddr (ctxt->Elan3mmu, (E3_Addr) av[0]); -+ if (maddr != NULL) -+ rc = sys_poll((struct pollfd *)maddr, av[1], av[2]); -+ break; -+ -+ case ELAN3_SYS_lseek: -+ rc = sys_lseek(av[0], av[1], av[2]); -+ break; -+ -+ case ELAN3_SYS_mmap: -+ if ((E3_Addr) av[0] == (E3_Addr) 0) -+ maddr = NULL; -+ else if ((maddr = elan3mmu_mainaddr (ctxt->Elan3mmu, (E3_Addr) av[0])) == NULL) -+ break; -+ -+ file = NULL; -+ /* GNAT 5515: If *not* anonymous memory need to do fget */ -+ if ((av[3] & MAP_ANONYMOUS) == 0 && (file = fget (av[4])) == NULL) -+ { -+ rc = -EBADF; -+ break; -+ } -+ -+ down_write (¤t->mm->mmap_sem); -+ ptr = do_mmap_pgoff (file, (unsigned long) maddr, av[1], av[2], av[3], av[5] >>PAGE_SHIFT); -+ up_write (¤t->mm->mmap_sem); -+ -+ if (file) -+ fput (file); -+ -+ if (IS_ERR((void *) ptr)) -+ rc = PTR_ERR((void *) ptr); -+ else -+ rc = elan3mmu_elanaddr (ctxt->Elan3mmu, (caddr_t)ptr); -+ -+ break; -+ -+ case ELAN3_SYS_munmap: -+ maddr = elan3mmu_mainaddr (ctxt->Elan3mmu, (E3_Addr) av[0]); -+ -+#ifdef AC -+ if (maddr != NULL) -+ rc = do_munmap(current->mm, (unsigned long) maddr, av[1], 1); -+#else -+ if (maddr != NULL) -+ rc = do_munmap(current->mm, (unsigned long) maddr, av[1]); -+#endif -+ break; -+ -+ case ELAN3_SYS_kill: -+ rc = sys_kill(av[0], av[1]); -+ break; -+ -+ case ELAN3_SYS_getpid: -+ rc = current->pid; -+ break; -+ -+ default: -+ return EINVAL; -+ } -+ ReturnSyscall(trap, rc, skip); -+ return ESUCCESS; -+} -+ -+ -+int -+ThreadElancall (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, int *skip) -+{ -+ int ret = ESUCCESS; -+ -+ PRINTF (ctxt, DBG_TPROC, "ThreadElancall: PC %08x\n", trap->pc); -+ dump_regs(ctxt, trap); -+ -+ /* -+ * Elan system call 'type' is passed in o0 -+ */ -+ switch (trap->Registers[REG_OUTS+(0^WordEndianFlip)]) -+ { -+ default: -+ ret = EINVAL; -+ break; -+ } -+ return ret; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan3/virtual_process.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan3/virtual_process.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan3/virtual_process.c 2005-06-01 23:12:54.597439408 -0400 -@@ -0,0 +1,884 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: virtual_process.c,v 1.68 2004/06/07 13:50:10 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/os/virtual_process.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static ELAN3_VPSEG * -+InstallSegment (ELAN3_CTXT *ctxt, int process, int entries) -+{ -+ ELAN3_VPSEG **prevSeg, *seg; -+ int lastTop = -1; -+ int top = process + entries-1; -+ -+ ASSERT (krwlock_is_write_locked (&ctxt->VpLock)); -+ -+ for (prevSeg = &ctxt->VpSegs; (seg = (*prevSeg)) != NULL; prevSeg = &seg->Next) -+ { -+ int thisTop = seg->Process + seg->Entries - 1; -+ -+ if (process < seg->Process && (process <= lastTop || top >= seg->Process)) -+ { -+ /* -+ * Overlaps with last segment, or this one -+ */ -+ return (NULL); -+ } -+ if (seg->Process > process) -+ break; -+ -+ lastTop = thisTop; -+ } -+ -+ KMEM_ZALLOC (seg, ELAN3_VPSEG *, sizeof (ELAN3_VPSEG), TRUE); -+ -+ if (seg == (ELAN3_VPSEG *) NULL) -+ return (NULL); -+ -+ seg->Process = process; -+ seg->Entries = entries; -+ -+ -+ PRINTF2 (ctxt, DBG_VP, "InstallSegment: add seg %p before %p\n", seg, *prevSeg); -+ -+ seg->Next = *prevSeg; -+ *prevSeg = seg; -+ -+ return (seg); -+} -+ -+static int -+RemoveSegment (ELAN3_CTXT *ctxt, ELAN3_VPSEG *seg) -+{ -+ ELAN3_VPSEG **prevSeg, *thisSeg; -+ -+ ASSERT (krwlock_is_write_locked (&ctxt->VpLock)); -+ -+ for (prevSeg = &ctxt->VpSegs; (thisSeg = (*prevSeg)) != NULL; prevSeg = &thisSeg->Next) -+ { -+ if (thisSeg == seg) -+ break; -+ } -+ -+ if (thisSeg == (ELAN3_VPSEG *) NULL) -+ return (EINVAL); -+ -+ -+ PRINTF2 (ctxt, DBG_VP, "RemoveSegment: remove seg %p next %p\n", thisSeg, thisSeg->Next); -+ -+ *prevSeg = thisSeg->Next; -+ -+ KMEM_FREE ((caddr_t) seg, sizeof (ELAN3_VPSEG)); -+ -+ return (ESUCCESS); -+} -+ -+static ELAN3_VPSEG * -+FindSegment (ELAN3_CTXT *ctxt, int low, int high) -+{ -+ ELAN3_VPSEG *seg; -+ -+ ASSERT(krwlock_is_locked (&ctxt->VpLock)); -+ -+ for (seg = ctxt->VpSegs; seg; seg = seg->Next) -+ { -+ if (seg->Process <= low && (seg->Process + seg->Entries) > high) -+ return (seg); -+ } -+ -+ return ((ELAN3_VPSEG *) NULL); -+} -+ -+ELAN_LOCATION -+ProcessToLocation (ELAN3_CTXT *ctxt, ELAN3_VPSEG *seg, int process, ELAN_CAPABILITY *cap) -+{ -+ ELAN_LOCATION location; -+ int nnodes,nctxs; -+ int node,ctx,i; -+ -+ ASSERT(krwlock_is_locked (&ctxt->VpLock)); -+ -+ location.loc_node = ELAN3_INVALID_NODE; -+ location.loc_context = -1; -+ -+ PRINTF3 (ctxt, DBG_VP, "ProcessToLocation: process %d seg %p cap %p\n", process, seg, cap); -+ -+ if (seg == NULL) -+ seg = FindSegment (ctxt, process, process); -+ -+ if (!seg || (seg->Type != ELAN3_VPSEG_P2P)) -+ return (location); -+ -+ cap = &seg->SegCapability; -+ nnodes = ELAN_CAP_NUM_NODES (cap); -+ nctxs = ELAN_CAP_NUM_CONTEXTS (cap); -+ -+ switch (seg->SegCapability.cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ { -+ int entries = ELAN_CAP_ENTRIES(cap); -+ -+ for (node = 0, i = 0; node < nnodes && i < entries; node++) -+ { -+ for (ctx = 0; ctx < nctxs && i < entries; ctx++) -+ { -+ if (( seg->SegCapability.cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (seg->SegCapability.cap_bitmap, ctx + (node * nctxs))) -+ { -+ if (i++ == (process - seg->Process)) -+ { -+ location.loc_node = seg->SegCapability.cap_lownode + node; -+ location.loc_context = seg->SegCapability.cap_lowcontext + ctx; -+ goto found; -+ } -+ } -+ } -+ } -+ break; -+ } -+ case ELAN_CAP_TYPE_CYCLIC: -+ { -+ int entries = ELAN_CAP_ENTRIES(cap); -+ -+ for (ctx = 0, i = 0; ctx < nctxs && i < entries; ctx++) -+ { -+ for (node = 0; node < nnodes && i < entries; node++) -+ { -+ if ((seg->SegCapability.cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (seg->SegCapability.cap_bitmap, node + (ctx * nnodes))) -+ { -+ if (i++ == (process - seg->Process)) -+ { -+ location.loc_node = seg->SegCapability.cap_lownode + node; -+ location.loc_context = seg->SegCapability.cap_lowcontext + ctx; -+ goto found; -+ } -+ } -+ } -+ } -+ break; -+ } -+ default: -+ break; -+ } -+ -+ found: -+ -+ PRINTF3 (ctxt, DBG_VP, "ProcessToLocation: process %d -> Node %d Context %d\n", process, location.loc_node, location.loc_context); -+ -+ if (cap != NULL) -+ { -+ bcopy ((caddr_t) &seg->SegCapability, (caddr_t) cap, sizeof (ELAN_CAPABILITY)); -+ cap->cap_mycontext = location.loc_context; -+ } -+ -+ return (location); -+} -+ -+int -+LocationToProcess (ELAN3_CTXT *ctxt, ELAN3_VPSEG *seg, ELAN_LOCATION loc, ELAN_CAPABILITY *cap) -+{ -+ int nnodes,nctxs; -+ int node,ctx,i; -+ -+ if (seg == NULL) -+ return ELAN3_INVALID_PROCESS; -+ -+ if (!seg || (seg->Type != ELAN3_VPSEG_P2P)) -+ return ELAN3_INVALID_PROCESS; -+ -+ nnodes = cap->cap_highnode - cap->cap_lownode + 1; -+ nctxs = cap->cap_highcontext - cap->cap_lowcontext + 1; -+ -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ { -+ int entries = ELAN_CAP_ENTRIES(cap); -+ -+ for (node = 0, i = 0; node < nnodes && i < entries; node++) -+ { -+ for (ctx = 0; ctx < nctxs && i < entries; ctx++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, ctx + (node * nctxs))) -+ { -+ if ((loc.loc_node == (cap->cap_lownode + node) ) -+ && (loc.loc_context == (cap->cap_lowcontext + ctx) )) -+ { -+ return (i + seg->Process); -+ } -+ i++; -+ } -+ } -+ } -+ break; -+ } -+ case ELAN_CAP_TYPE_CYCLIC: -+ { -+ int entries = ELAN_CAP_ENTRIES(cap); -+ -+ for (ctx = 0, i = 0; ctx < nctxs && i < entries; ctx++) -+ { -+ for (node = 0; node < nnodes && i < entries; node++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, node + (ctx * nnodes))) -+ { -+ if ((loc.loc_node == (cap->cap_lownode + node) ) -+ && (loc.loc_context == (cap->cap_lowcontext + ctx) )) -+ { -+ return (i + seg->Process); -+ } -+ i++; -+ -+ } -+ } -+ } -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return ELAN3_INVALID_PROCESS; -+} -+ -+int -+elan3_addvp (ELAN3_CTXT *ctxt, int process, ELAN_CAPABILITY *cap) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ ELAN_POSITION *pos = &ctxt->Position; -+ ELAN3_VPSEG *seg; -+ int i; -+ int nodeOff; -+ int ctxOff; -+ int nnodes; -+ int nctxs; -+ E3_uint16 flits[MAX_FLITS]; -+ int nflits; -+ int entries; -+ -+ PRINTF2 (ctxt, DBG_VP, "elan3_addvp: %d -> %s\n", process, CapabilityString (cap)); -+ -+ entries = ELAN_CAP_ENTRIES(cap); -+ if (entries <= 0 || (process + entries) > ELAN3_MAX_VPS) -+ return (EINVAL); -+ -+ /* -+ * Scan the virtual process segment list, to add this entry, and ensure that -+ * the ranges don't overlap. -+ */ -+ krwlock_write (&ctxt->VpLock); -+ -+ /* check cap. */ -+ switch (elan3_validate_cap (ctxt->Device, cap, ELAN_USER_P2P)) -+ { -+ case ELAN_CAP_OK: -+ /* nothing */ -+ break; -+ -+ case ELAN_CAP_RMS: -+ if ( elan_validate_map(cap, cap) != ESUCCESS) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ break; -+ -+ default: -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if ((seg = InstallSegment (ctxt, process, entries)) == NULL) -+ { -+ PRINTF0 (ctxt, DBG_VP, "elan3_addvp: failed to find a seg\n"); -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ seg->Type = ELAN3_VPSEG_P2P; -+ seg->SegCapability = *cap; -+ seg->SegCapability.cap_mycontext = ELAN_CAP_UNINITIALISED; -+ -+ PRINTF3 (ctxt, DBG_VP, "elan3_addvp: segment type %x %d %d\n", -+ seg->SegCapability.cap_type, seg->Process, entries); -+ -+ -+ nnodes = cap->cap_highnode - cap->cap_lownode + 1; -+ nctxs = cap->cap_highcontext - cap->cap_lowcontext + 1; -+ -+ /* position not determined, so cannot load any routes, the hwtest -+ * process must explicitly set it's own routes */ -+ -+ if (!(cap->cap_type & ELAN_CAP_TYPE_HWTEST) && (pos->pos_mode != ELAN_POS_UNKNOWN)) -+ { -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ for (nodeOff = 0, i = 0; nodeOff < nnodes && i < entries; nodeOff++) -+ { -+ for (ctxOff = 0; ctxOff < nctxs && i < entries; ctxOff++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, ctxOff + (nodeOff * nctxs))) -+ { -+ /* Don't load a route if there's no switch and trying to talk to myself */ -+ if (pos->pos_mode == ELAN_POS_MODE_SWITCHED || -+ (pos->pos_mode == ELAN_POS_MODE_LOOPBACK && cap->cap_lownode + nodeOff == pos->pos_nodeid) || -+ (pos->pos_mode == ELAN_POS_MODE_BACKTOBACK && cap->cap_lownode + nodeOff != pos->pos_nodeid)) -+ { -+ PRINTF3 (ctxt, DBG_VP, "elan3_addvp: virtual process %d -> node %d context %d\n", -+ seg->Process + i, cap->cap_lownode +nodeOff, cap->cap_lowcontext +ctxOff); -+ -+ nflits = GenerateRoute (pos, flits, cap->cap_lownode + nodeOff, cap->cap_lownode + nodeOff, -+ DEFAULT_ROUTE_TIMEOUT, DEFAULT_ROUTE_PRIORITY); -+ -+ -+ -+ LoadRoute (dev, ctxt->RouteTable, seg->Process+i, cap->cap_lowcontext + ctxOff, nflits, flits); -+ } -+ -+ i++; -+ } -+ } -+ } -+ break; -+ -+ case ELAN_CAP_TYPE_CYCLIC: -+ for (ctxOff = 0, i = 0; ctxOff < nctxs && i < entries; ctxOff++) -+ { -+ for (nodeOff = 0; nodeOff < nnodes && i < entries; nodeOff++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, nodeOff + (ctxOff * nnodes))) -+ { -+ /* Don't load a route if there's no switch and trying to talk to myself */ -+ if (pos->pos_mode == ELAN_POS_MODE_SWITCHED || -+ (pos->pos_mode == ELAN_POS_MODE_LOOPBACK && cap->cap_lownode + nodeOff == pos->pos_nodeid) || -+ (pos->pos_mode == ELAN_POS_MODE_BACKTOBACK && cap->cap_lownode + nodeOff != pos->pos_nodeid)) -+ { -+ PRINTF3 (ctxt, DBG_VP, "elan3_addvp: virtual process %d -> node %d context %d\n", -+ seg->Process + i, cap->cap_lownode + nodeOff, cap->cap_lowcontext +ctxOff); -+ -+ nflits = GenerateRoute (pos, flits, cap->cap_lownode + nodeOff, cap->cap_lownode + nodeOff, -+ DEFAULT_ROUTE_TIMEOUT, DEFAULT_ROUTE_PRIORITY); -+ -+ -+ LoadRoute (dev, ctxt->RouteTable, seg->Process+i, cap->cap_lowcontext +ctxOff, nflits, flits); -+ } -+ i++; -+ } -+ } -+ } -+ break; -+ default: -+ break; -+ } -+ } -+ -+ krwlock_done (&ctxt->VpLock); -+ -+ return (ESUCCESS); -+} -+ -+int -+elan3_removevp (ELAN3_CTXT *ctxt, int process) -+{ -+ ELAN3_VPSEG *seg; -+ ELAN3_VPSEG *next; -+ int i; -+ -+ krwlock_write (&ctxt->VpLock); -+ -+ PRINTF1 (ctxt, DBG_VP, "elan3_removevp: remove process %d\n", process); -+ -+ if (process == ELAN3_INVALID_PROCESS) -+ seg = ctxt->VpSegs; -+ else -+ seg = FindSegment (ctxt, process, process); -+ -+ if (seg == (ELAN3_VPSEG *) NULL) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ do { -+ PRINTF3 (ctxt, DBG_VP, "elan3_removevp: segment is %p [%x,%x]\n", -+ seg, seg->Process, seg->Process+seg->Entries); -+ -+ for (i = 0; i < seg->Entries; i++) -+ ClearRoute (ctxt->Device, ctxt->RouteTable, seg->Process+i); -+ -+ /* get Next pointer value before structure is free'd */ -+ next = seg->Next; -+ RemoveSegment (ctxt, seg); -+ -+ } while (process == ELAN3_INVALID_PROCESS && (seg = next) != NULL); -+ -+ krwlock_done (&ctxt->VpLock); -+ -+ return (ESUCCESS); -+} -+ -+int -+elan3_addbcastvp (ELAN3_CTXT *ctxt, int process, int lowProc, int highProc) -+{ -+ ELAN_POSITION *pos = &ctxt->Position; -+ ELAN3_VPSEG *seg; -+ ELAN3_VPSEG *aseg; -+ int virtualProcess; -+ E3_uint64 routeValue; -+ -+ PRINTF3 (ctxt, DBG_VP, "elan3_addbcastvp: process %d [%d,%d]\n", process, lowProc, highProc); -+ -+ if (lowProc > highProc || pos->pos_mode != ELAN_POS_MODE_SWITCHED) -+ return (EINVAL); -+ -+ krwlock_write (&ctxt->VpLock); -+ -+ if ((aseg = FindSegment (ctxt, lowProc, highProc)) == NULL || (aseg->Type != ELAN3_VPSEG_P2P)) -+ { -+ PRINTF2 (ctxt, DBG_VP, "elan3_addbcastvp: process [%d,%d] does not map to p2p segment\n", lowProc, highProc); -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ /* check aseg->SegCapability */ -+ switch (elan3_validate_cap (ctxt->Device, &aseg->SegCapability, ELAN_USER_BROADCAST)) -+ { -+ case ELAN_CAP_OK: -+ /* nothing */ -+ break; -+ -+ case ELAN_CAP_RMS: -+ if ( elan_validate_map(&ctxt->Capability, &aseg->SegCapability) != ESUCCESS ) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ break; -+ -+ default: -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if ( ProcessToLocation (ctxt, aseg, lowProc, NULL).loc_context != -+ ProcessToLocation (ctxt, aseg, highProc, NULL).loc_context) -+ { -+ PRINTF2 (ctxt, DBG_VP, "elan3_addbcastvp: process [%d,%d] does not map to single context\n", lowProc, highProc); -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if ((seg = InstallSegment (ctxt, process, 1)) == NULL) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ seg->Type = ELAN3_VPSEG_BROADCAST; -+ seg->SegLowProc = lowProc; -+ seg->SegHighProc = highProc; -+ -+ PRINTF4 (ctxt, DBG_VP, "elan3_addbcastvp: installed seg %p Type %d LowProc %d HighProc %d\n", -+ seg, seg->Type, seg->SegLowProc, seg->SegHighProc); -+ -+ for (virtualProcess = lowProc; virtualProcess <= highProc; virtualProcess++) -+ { -+ if (virtualProcess < 0 || virtualProcess >= ctxt->RouteTable->Size) -+ routeValue = 0; -+ else -+ routeValue = elan3_sdram_readq ( ctxt->Device, ctxt->RouteTable->Table + virtualProcess * NBYTES_PER_SMALL_ROUTE); -+ -+ if (! (routeValue & ROUTE_VALID)) -+ { -+ PRINTF2 (ctxt, DBG_VP, "loadvp[%x]: broadcast %x not valid\n", -+ ctxt->Capability.cap_mycontext, virtualProcess); -+ break; -+ } -+ } -+ -+ if (virtualProcess > highProc) /* All vps now present */ -+ { /* so load up broadcast route */ -+ E3_uint16 flits[MAX_FLITS]; -+ ELAN_LOCATION low = ProcessToLocation (ctxt, aseg, lowProc, NULL); -+ ELAN_LOCATION high = ProcessToLocation (ctxt, aseg, highProc, NULL); -+ int nflits = GenerateRoute (pos, flits, low.loc_node, high.loc_node, DEFAULT_ROUTE_TIMEOUT, DEFAULT_ROUTE_PRIORITY); -+ -+ PRINTF6 (ctxt, DBG_VP, "loadvp[%x]: broadcast %d -> %x.%x [%x.%x]\n", ctxt->Capability.cap_mycontext, -+ seg->Process, low.loc_node, high.loc_node, -+ low.loc_context, high.loc_context); -+ -+ LoadRoute ( ctxt->Device, ctxt->RouteTable, seg->Process, low.loc_context, nflits, flits); -+ } -+ -+ krwlock_done (&ctxt->VpLock); -+ -+ return (ESUCCESS); -+} -+ -+int -+elan3_process (ELAN3_CTXT *ctxt) -+{ -+ int res = ELAN3_INVALID_PROCESS; -+ ELAN3_VPSEG *seg; -+ ELAN_LOCATION loc; -+ -+ krwlock_write (&ctxt->VpLock); -+ -+ loc.loc_node = ctxt->Position.pos_nodeid; -+ loc.loc_context = ctxt->Capability.cap_mycontext; -+ -+ for (seg = ctxt->VpSegs ; seg; seg = seg->Next) -+ { -+ if (seg->Type == ELAN3_VPSEG_P2P && -+ seg->SegCapability.cap_lowcontext <= ctxt->Capability.cap_mycontext && -+ seg->SegCapability.cap_highcontext >= ctxt->Capability.cap_mycontext && -+ seg->SegCapability.cap_lownode <= ctxt->Position.pos_nodeid && -+ seg->SegCapability.cap_highnode >= ctxt->Position.pos_nodeid) -+ { -+ if ((res=LocationToProcess (ctxt,seg,loc,&ctxt->Capability)) != ELAN3_INVALID_PROCESS) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return res; -+ } -+ } -+ } -+ -+ krwlock_done (&ctxt->VpLock); -+ -+ return (res); -+} -+ -+int -+elan3_check_route (ELAN3_CTXT *ctxt, int process, E3_uint16 *flits, E3_uint32 *routeError) -+{ -+ PRINTF5 (ctxt, DBG_VP, "elan3_check_route: vp=%d flits=%04x %04x %04x %04x\n", -+ process, flits[0], flits[1], flits[2], flits[3]); -+ PRINTF4 (ctxt, DBG_VP, " %04x %04x %04x %04x\n", -+ flits[4], flits[5], flits[6], flits[7]); -+ -+ krwlock_read (&ctxt->VpLock); -+ *routeError=elan3_route_check(ctxt,flits,ProcessToLocation (ctxt, NULL, process, NULL).loc_node); -+ krwlock_done (&ctxt->VpLock); -+ -+ return (ESUCCESS); /* the call is a success tho the errorcode may be set */ -+} -+ -+int -+elan3_load_route (ELAN3_CTXT *ctxt, int process, E3_uint16 *flits) -+{ -+ ELAN3_VPSEG *seg; -+ int res = 0; -+ int nflits; -+ int err; -+ -+ PRINTF5 (ctxt, DBG_VP, "elan3_load_route: vp=%d flits=%04x %04x %04x %04x\n", -+ process, flits[0], flits[1], flits[2], flits[3]); -+ PRINTF4 (ctxt, DBG_VP, " %04x %04x %04x %04x\n", -+ flits[4], flits[5], flits[6], flits[7]); -+ -+ krwlock_write (&ctxt->VpLock); -+ -+ /* check the route is valid */ -+ if (!(ctxt->Capability.cap_type & ELAN_CAP_TYPE_HWTEST)) -+ { -+ /* must have already attached to define my context number */ -+ if (ctxt->Capability.cap_mycontext == ELAN_CAP_UNINITIALISED) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if ((err=elan3_route_check(ctxt,flits,ProcessToLocation (ctxt, NULL, process, NULL).loc_node)) != ELAN3_ROUTE_SUCCESS) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ } -+ -+ if ((seg = FindSegment (ctxt, process, process)) == NULL || seg->Type != ELAN3_VPSEG_P2P) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ /* Calculate number of flits in this route */ -+ for (nflits = 0; nflits < MAX_FLITS && flits[nflits]; nflits++) -+ ; -+ -+ res = LoadRoute (ctxt->Device, ctxt->RouteTable, process, ProcessToLocation (ctxt, seg, process, NULL).loc_context, nflits, flits); -+ -+ krwlock_done (&ctxt->VpLock); -+ -+ return (res); -+} -+ -+int -+elan3_get_route (ELAN3_CTXT *ctxt, int process, E3_uint16 *flits) -+{ -+ ELAN3_VPSEG *seg; -+ int res = 0; -+ -+ PRINTF1 (ctxt, DBG_VP, "elan3_get_route: vp=%d \n", process); -+ -+ krwlock_write (&ctxt->VpLock); -+ -+ if (ctxt->RouteTable == NULL) /* is there a route table */ -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if ((seg = FindSegment (ctxt, process, process)) != NULL && seg->Type != ELAN3_VPSEG_P2P) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if (seg == NULL) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ res = GetRoute (ctxt->Device, ctxt->RouteTable, process, flits); -+ -+ krwlock_done (&ctxt->VpLock); -+ -+ return (res); -+} -+ -+int -+elan3_reset_route (ELAN3_CTXT *ctxt, int process) -+{ -+ E3_uint16 flits[MAX_FLITS]; -+ -+ PRINTF1 (ctxt, DBG_VP, "elan3_reset_route: vp=%d \n", process); -+ -+ GenerateRoute (&ctxt->Position, flits, process, process, DEFAULT_ROUTE_TIMEOUT, DEFAULT_ROUTE_PRIORITY); -+ -+ return elan3_load_route(ctxt,process,flits); -+} -+ -+int -+ResolveVirtualProcess (ELAN3_CTXT *ctxt, int process) -+{ -+ E3_uint16 flits[MAX_FLITS]; -+ ELAN3_DEV *dev = ctxt->Device; -+ int res = ESUCCESS; -+ ELAN3_VPSEG *seg; -+ ELAN3_VPSEG *aseg; -+ E3_uint64 routeValue; -+ -+ krwlock_read (&ctxt->VpLock); -+ -+ PRINTF1 (ctxt, DBG_VP, "ResolveVirtualProcess: vp=%d \n", process); -+ -+ if (ctxt->RouteTable == NULL || process < 0 || process >= ctxt->RouteTable->Size) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ if (! (seg = FindSegment (ctxt, process, process))) -+ { -+ PRINTF1 (ctxt, DBG_VP, "ResolveVirtualProcess: cannot find segment for virtual process %d\n", process); -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ /* check cap. */ -+ switch (elan3_validate_cap (ctxt->Device, &seg->SegCapability, ((seg->Type == ELAN3_VPSEG_P2P) ? ELAN_USER_P2P : ELAN_USER_BROADCAST))) -+ { -+ case ELAN_CAP_OK: -+ /* nothing */ -+ break; -+ -+ case ELAN_CAP_RMS: -+ if ( elan_validate_map(&ctxt->Capability, &seg->SegCapability) != ESUCCESS) -+ { -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ break; -+ -+ default: -+ krwlock_done (&ctxt->VpLock); -+ return (EINVAL); -+ } -+ -+ BumpUserStat (ctxt, LoadVirtualProcess); -+ -+ routeValue = elan3_sdram_readq (dev, ctxt->RouteTable->Table + process * NBYTES_PER_SMALL_ROUTE); -+ if (routeValue & ROUTE_VALID) /* Virtual process already */ -+ { /* loaded */ -+ krwlock_done (&ctxt->VpLock); -+ return (ESUCCESS); -+ } -+ -+ switch (seg->Type) -+ { -+ case ELAN3_VPSEG_P2P: -+ switch (seg->SegCapability.cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ case ELAN_CAP_TYPE_CYCLIC: -+ if ((res = elan_validate_map (&ctxt->Capability,&seg->SegCapability)) == ESUCCESS && -+ (res = GetRoute(dev, ctxt->RouteTable ,process, flits)) == ESUCCESS) -+ { -+ if (elan3_route_check(ctxt, flits, ProcessToLocation (ctxt, seg, process, NULL).loc_node)) -+ res = EINVAL; -+ else -+ ValidateRoute(dev, ctxt->RouteTable, process); -+ } -+ break; -+ default: -+ res = EINVAL; -+ break; -+ } -+ break; -+ -+ case ELAN3_VPSEG_BROADCAST: -+ /* Find the segment that this broadcast range spans. */ -+ aseg = FindSegment (ctxt, seg->SegLowProc, seg->SegHighProc); -+ -+ if (aseg == NULL || (aseg->Type != ELAN3_VPSEG_P2P) || !(aseg->SegCapability.cap_type & ELAN_CAP_TYPE_BROADCASTABLE)) -+ { -+ PRINTF2 (ctxt, DBG_VP, "resolveVirtualProcess: %d -> EINVAL (%s)\n", process, -+ (aseg == NULL ? "no segment" : ((seg->Type != ELAN3_VPSEG_P2P) ? "not point to point" : -+ "not broadcastable"))); -+ res = EINVAL; -+ break; -+ } -+ -+ switch (aseg->SegCapability.cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ case ELAN_CAP_TYPE_CYCLIC: -+ { -+ ELAN_LOCATION lowNode = ProcessToLocation (ctxt,aseg,seg->SegLowProc , NULL); -+ ELAN_LOCATION highNode = ProcessToLocation (ctxt,aseg,seg->SegHighProc , NULL); -+ -+ -+ if ((res = elan_validate_map (&ctxt->Capability,&aseg->SegCapability)) == ESUCCESS && -+ (res=GetRoute(dev, ctxt->RouteTable ,process, flits)) == ESUCCESS) -+ { -+ if (elan3_route_broadcast_check(ctxt,flits, lowNode.loc_node , highNode.loc_node ) != ELAN3_ROUTE_SUCCESS ) -+ res = EINVAL; -+ else -+ ValidateRoute(dev, ctxt->RouteTable, process); -+ } -+ break; -+ } -+ -+ default: -+ res = EINVAL; -+ break; -+ } -+ default: -+ res = EINVAL; -+ break; -+ } -+ -+ krwlock_done (&ctxt->VpLock); -+ return (res); -+} -+ -+void -+UnloadVirtualProcess (ELAN3_CTXT *ctxt, ELAN_CAPABILITY *cap) -+{ -+ ELAN3_DEV *dev = ctxt->Device; -+ ELAN3_VPSEG *seg; -+ ELAN_CAPABILITY *scap; -+ int i; -+ -+ for (seg = ctxt->VpSegs; seg; seg = seg->Next) -+ { -+ switch (seg->Type) -+ { -+ case ELAN3_VPSEG_P2P: -+ scap = &seg->SegCapability; -+ -+ if (cap == NULL || ELAN_CAP_MATCH (scap, cap)) -+ { -+ PRINTF2 (ctxt, DBG_VP, "unloadvp: segment [%x.%x]\n", -+ seg->Process, seg->Process + seg->Entries-1); -+ -+ for (i = 0; i < seg->Entries; i++) -+ InvalidateRoute (dev, ctxt->RouteTable, seg->Process+i); -+ } -+ break; -+ -+ case ELAN3_VPSEG_BROADCAST: -+ for (i = 0; i < seg->Entries; i++) -+ { -+ ELAN3_VPSEG *aseg = FindSegment (ctxt, seg->SegLowProc, seg->SegHighProc); -+ -+ if (aseg != NULL && ELAN_CAP_MATCH(&aseg->SegCapability, cap)) -+ { -+ PRINTF1 (ctxt, DBG_VP, "unloadvp: broadcast vp %d\n", seg->Process); -+ -+ InvalidateRoute (dev, ctxt->RouteTable, seg->Process+i); -+ } -+ } -+ } -+ } -+} -+ -+caddr_t -+CapabilityString (ELAN_CAPABILITY *cap) -+{ -+#define CAPSTR_LEN 200 -+#define NCAPSTRS 4 -+ static char space[CAPSTR_LEN*NCAPSTRS]; -+ static int bufnum; -+ static spinlock_t lock; -+ static int lockinitialised; -+ int num; -+ unsigned long flags; -+ -+ if (! lockinitialised) -+ { -+ spin_lock_init (&lock); -+ lockinitialised = 1; -+ } -+ -+ spin_lock_irqsave (&lock, flags); -+ -+ if ((num = ++bufnum) == NCAPSTRS) -+ num = bufnum = 0; -+ spin_unlock_irqrestore (&lock, flags); -+ -+ sprintf (space + (num * CAPSTR_LEN), "%4x %4x %4x %4x %4x %4x %4x [%x.%x.%x.%x]", cap->cap_type, -+ cap->cap_lownode, cap->cap_highnode, -+ cap->cap_lowcontext, cap->cap_mycontext, cap->cap_highcontext, ELAN_CAP_ENTRIES(cap), -+ cap->cap_userkey.key_values[0], cap->cap_userkey.key_values[1], -+ cap->cap_userkey.key_values[2], cap->cap_userkey.key_values[3]); -+ -+ return (space + (num * CAPSTR_LEN)); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/debug.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/debug.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/debug.c 2005-06-01 23:12:54.597439408 -0400 -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: debug.c,v 1.16 2004/07/07 11:22:33 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/debug.c,v $*/ -+ -+#include -+ -+#include -+#include -+ -+unsigned elan4_debug = 0; -+unsigned elan4_debug_toconsole = 0; -+unsigned elan4_debug_tobuffer = DBG_ALL; -+ -+unsigned elan4_debug_display_ctxt; -+unsigned elan4_debug_ignore_ctxt; -+unsigned elan4_debug_ignore_type; -+ -+void -+elan4_debug_init() -+{ -+ if ((elan4_debug & elan4_debug_tobuffer) != 0) -+ qsnet_debug_alloc(); -+} -+ -+void -+elan4_debug_fini() -+{ -+} -+ -+void -+elan4_debugf (void *type, int mode, char *fmt,...) -+{ -+ char prefix[128]; -+ int where = 0; -+ va_list ap; -+ -+ if ((mode & elan4_debug_tobuffer) != 0 || type == DBG_BUFFER) -+ where |= QSNET_DEBUG_BUFFER; -+ if ((mode & elan4_debug_toconsole) != 0 || type == DBG_CONSOLE) -+ where |= QSNET_DEBUG_CONSOLE; -+ -+ if (where == 0) -+ return; -+ -+ if ((unsigned long) type > DBG_NTYPES) -+ { -+ ELAN4_CTXT *ctxt = (ELAN4_CTXT *) type; -+ -+ if (elan4_debug_display_ctxt && ctxt->ctxt_num != elan4_debug_display_ctxt) -+ return; -+ if (elan4_debug_ignore_ctxt && ctxt->ctxt_num == elan4_debug_ignore_ctxt) -+ return; -+ -+ sprintf (prefix, "[%08ld.%04d] elan4 (%03x) ", lbolt, current->pid, ctxt->ctxt_num); -+ } -+ else if ((unsigned long) type == (int) DBG_CONSOLE) -+ prefix[0] = '\0'; -+ else -+ { -+ char *what; -+ -+ if (elan4_debug_ignore_type & (1 << ((unsigned long) type))) -+ return; -+ -+ switch ((unsigned long) type) -+ { -+ case (int) DBG_DEVICE: what = "dev"; break; -+ case (int) DBG_USER: what = "usr"; break; -+ default: what = NULL; break; -+ } -+ -+ if (what) -+ sprintf (prefix, "[%08ld.%04d] elan4 [%s] ", lbolt, current->pid, what); -+ else -+ sprintf (prefix, "[%08ld.%04d] elan4 [%3d] ", lbolt, current->pid, (int)(long)type); -+ } -+ -+ va_start(ap,fmt); -+ qsnet_vdebugf (where, prefix, fmt, ap); -+ va_end (ap); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/device.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/device.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/device.c 2005-06-01 23:12:54.602438648 -0400 -@@ -0,0 +1,2805 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: device.c,v 1.87.6.3 2005/01/18 14:25:35 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/device.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* allow this code to compile against an Eagle elanmod */ -+#ifdef __ELANMOD_DEVICE_H -+#define ELAN_DEV_OPS ELANMOD_DEV_OPS -+#define ELAN_DEV_OPS_VERSION ELANMOD_DEV_OPS_VERSION -+#define elan_dev_register elanmod_dev_register -+#define elan_dev_deregister elanmod_dev_deregister -+#endif -+ -+/* XXXX configurational defines */ -+ -+#if defined (CONFIG_MPSAS) -+#define HASH_0_SIZE_VAL (12 + 6) -+#define HASH_1_SIZE_VAL (2 + 6) -+#define CTXT_TABLE_SHIFT 8 -+#define LN2_MAX_CQS 8 /* 256 */ -+#else -+#define HASH_0_SIZE_VAL (13 + 6) -+#define HASH_1_SIZE_VAL (2 + 6) -+#define CTXT_TABLE_SHIFT 12 -+#define LN2_MAX_CQS 10 /* 1024 */ -+#endif -+ -+unsigned int elan4_hash_0_size_val = HASH_0_SIZE_VAL; -+unsigned int elan4_hash_1_size_val = HASH_1_SIZE_VAL; -+unsigned int elan4_ctxt_table_shift = CTXT_TABLE_SHIFT; -+unsigned int elan4_ln2_max_cqs = LN2_MAX_CQS; -+unsigned int elan4_dmaq_highpri_size = 2; /* 8192 entries */ -+unsigned int elan4_threadq_highpri_size = 1; /* 1024 entries */ -+unsigned int elan4_dmaq_lowpri_size = 2; /* 8192 entries */ -+unsigned int elan4_threadq_lowpri_size = 1; /* 1024 entries */ -+unsigned int elan4_interruptq_size = 0; /* 1024 entries */ -+unsigned int elan4_mainint_punt_loops = 1; -+unsigned int elan4_mainint_resched_ticks = 0; -+ -+static int -+elan4_op_get_position (void *arg, ELAN_POSITION *ptr) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *)arg; -+ ELAN_POSITION pos; -+ -+ elan4_get_position (dev, &pos); -+ -+ return copyout (&pos, ptr, sizeof (ELAN_POSITION)); -+} -+ -+static int -+elan4_op_set_position (void *arg, unsigned short nodeid, unsigned short numnodes) -+{ -+ /* XXXXX -+ -+ ELAN4_DEV *dev = (ELAN4_DEV *) arg; -+ -+ compute_position (&pos, nodeid, numnode, num_down_links_value); -+ -+ return elan4_set_position (dev, pos); -+ */ -+ return EINVAL; -+} -+ -+ELAN_DEV_OPS elan4_dev_ops = -+{ -+ elan4_op_get_position, -+ elan4_op_set_position, -+ -+ ELAN_DEV_OPS_VERSION -+}; -+ -+static E4_uint32 -+elan4_read_filter (ELAN4_DEV *dev, unsigned networkctx) -+{ -+ return (elan4_sdram_readl (dev, dev->dev_ctxtable + (networkctx * sizeof (E4_ContextControlBlock)) + -+ offsetof (E4_ContextControlBlock, Filter))); -+} -+ -+static void -+elan4_write_filter (ELAN4_DEV *dev, unsigned networkctx, E4_uint32 value) -+{ -+ elan4_sdram_writel (dev, (dev->dev_ctxtable + (networkctx * sizeof (E4_ContextControlBlock)) + -+ offsetof (E4_ContextControlBlock, Filter)), value); -+ pioflush_sdram(dev); -+} -+ -+void -+elan4_set_schedstatus (ELAN4_DEV *dev, E4_uint32 intreg) -+{ -+ E4_uint32 setbits = 0; -+ E4_uint32 intmask = 0; -+ E4_uint32 haltmask; -+ E4_uint32 next_sched; -+ E4_uint32 next_intmask; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_intmask_lock, flags); -+ -+ haltmask = (dev->dev_haltop_mask | dev->dev_haltop_active); -+ -+ if ((haltmask & INT_DProcHalted) || dev->dev_halt_all_count || dev->dev_halt_dproc_count) -+ setbits |= SCH_DProcHalt; -+ -+ if ((haltmask & INT_TProcHalted) || dev->dev_halt_all_count || dev->dev_halt_tproc_count) -+ setbits |= SCH_TProcHalt; -+ -+ if ((haltmask & INT_CProcHalted) || dev->dev_halt_all_count || dev->dev_halt_cproc_count) -+ setbits |= SCH_CProcHalt; -+ -+ if ((haltmask & INT_DiscardingLowPri) || dev->dev_discard_all_count || dev->dev_discard_lowpri_count) -+ setbits |= SCH_DiscardLowPriInput; -+ -+ if ((haltmask & INT_DiscardingHighPri) || dev->dev_discard_all_count || dev->dev_discard_highpri_count) -+ setbits |= SCH_DiscardHighPriInput; -+ -+ if (dev->dev_halt_lowpri_count) -+ setbits |= SCH_StopLowPriQueues; -+ -+ if (haltmask & INT_DProcHalted) intmask |= INT_DProcHalted; -+ if (haltmask & INT_TProcHalted) intmask |= INT_TProcHalted; -+ if (haltmask & INT_CProcHalted) intmask |= INT_CProcHalted; -+ if (haltmask & INT_DiscardingLowPri) intmask |= INT_DiscardingLowPri; -+ if (haltmask & INT_DiscardingHighPri) intmask |= INT_DiscardingHighPri; -+ -+ next_intmask = (dev->dev_intmask & ~(INT_Halted | INT_Discarding)) | (intmask & ~intreg); -+ next_sched = (dev->dev_schedstatus & ~(SCH_Halt | SCH_Discard)) | setbits; -+ -+ PRINTF5 (DBG_DEVICE, DBG_REGISTER, "elan4_set_schedstatus: haltmask=%x setbits=%x intmask=%x next_sched=%x next_intmask=%x\n", -+ haltmask, setbits, intmask, next_sched, next_intmask); -+ -+ CHANGE_INT_MASK (dev, next_intmask); -+ CHANGE_SCHED_STATUS (dev, next_sched); -+ -+ spin_unlock_irqrestore (&dev->dev_intmask_lock, flags); -+} -+ -+void -+elan4_queue_haltop (ELAN4_DEV *dev, ELAN4_HALTOP *op) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ -+ /* add to the end of the halt operations list */ -+ list_add_tail (&op->op_link, &dev->dev_haltop_list); -+ -+ if ((dev->dev_haltop_mask & op->op_mask) != op->op_mask) -+ { -+ dev->dev_haltop_mask |= op->op_mask; -+ -+ elan4_set_schedstatus (dev, 0); -+ } -+ -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+} -+ -+void -+elan4_queue_intop (ELAN4_DEV *dev, ELAN4_CQ *cq, ELAN4_INTOP *op) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_intop_lock, flags); -+ -+ op->op_cookie = INTOP_ONESHOT | ((dev->dev_intop_cookie++) & INTOP_VALUE_MASK); -+ -+ list_add_tail (&op->op_link, &dev->dev_intop_list); -+ -+ writeq ((op->op_cookie << E4_MAIN_INT_SHIFT) | INTERRUPT_CMD, cq->cq_mapping); -+ -+ spin_unlock_irqrestore (&dev->dev_intop_lock, flags); -+} -+ -+void -+elan4_register_intop (ELAN4_DEV *dev, ELAN4_INTOP *op) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_intop_lock, flags); -+ -+ op->op_cookie = INTOP_PERSISTENT | ((dev->dev_intop_cookie++) & INTOP_VALUE_MASK); -+ -+ list_add_tail (&op->op_link, &dev->dev_intop_list); -+ -+ spin_unlock_irqrestore (&dev->dev_intop_lock, flags); -+} -+ -+void -+elan4_deregister_intop (ELAN4_DEV *dev, ELAN4_INTOP *op) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_intop_lock, flags); -+ list_del (&op->op_link); -+ spin_unlock_irqrestore (&dev->dev_intop_lock, flags); -+} -+ -+static __inline__ void -+__issue_dma_flushop_cmd (ELAN4_CQ *cq) -+{ -+ writeq (DMA_ShMemWrite | RUN_DMA_CMD, cq->cq_mapping); -+ writeq (0 /* cookie */, cq->cq_mapping); -+ writeq (0 /* vproc */, cq->cq_mapping); -+ writeq (0 /* srcAddr */, cq->cq_mapping); -+ writeq (0 /* dstAddr */, cq->cq_mapping); -+ writeq (0 /* srcEvent */, cq->cq_mapping); -+ writeq (0 /* dstEvent */, cq->cq_mapping); -+ writeq (SET_EVENT_CMD, cq->cq_mapping); -+} -+ -+static void -+handle_dma_flushops_intop (ELAN4_DEV *dev, void *arg) -+{ -+ unsigned int hipri = ((unsigned long) arg & 1); -+ E4_uint64 status = dev->dev_dma_flushop[hipri].status; -+ ELAN4_CQ *cq = dev->dev_dma_flushop[hipri].cq; -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (elan4_cq2num(cq) * sizeof (E4_CommandQueueDesc)); -+ E4_uint64 queuePtrs = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs)); -+ E4_uint32 completedPtr = CQ_CompletedPtr(queuePtrs); -+ E4_uint32 size = CQ_Size ((queuePtrs >> CQ_SizeShift) & CQ_SizeMask); -+ unsigned long flags; -+ -+ /* -+ * Since we're called from a main interrupt which was issued through the approriate -+ * flushcq the command queue descriptor for dma flushing can no longer be in the -+ * insert cache, nor can it be in the extractor (as it's trapped), hence it is -+ * safe to modify the completed pointer -+ */ -+ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ -+ ASSERT (status != 0); -+ -+ /* skip over either the DMA/SETEVENT or just the SETEVENT depending on the trap type */ -+ if (CPROC_TrapType (status) == CommandProcDmaQueueOverflow) -+ completedPtr = (completedPtr & ~(size-1)) | ((completedPtr + 64) & (size - 1)); -+ else -+ completedPtr = (completedPtr & ~(size-1)) | ((completedPtr + 8) & (size - 1)); -+ -+ elan4_sdram_writel (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs) + 4, -+ ((queuePtrs >> 32) & ~CQ_PtrOffsetMask) | (completedPtr & CQ_PtrOffsetMask)); -+ -+ elan4_restartcq (dev, dev->dev_dma_flushop[hipri].cq); -+ -+ if (! list_empty (&dev->dev_dma_flushop[hipri].list)) -+ __issue_dma_flushop_cmd (dev->dev_dma_flushop[hipri].cq); -+ -+ dev->dev_dma_flushop[hipri].status = 0; -+ -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+ -+} -+ -+static void -+handle_dma_flushops (ELAN4_DEV *dev, E4_uint64 status, int cqnum) -+{ -+ unsigned int hipri = (cqnum == elan4_cq2num(dev->dev_dma_flushop[1].cq) ? 1 : 0); -+ ELAN4_CQ *cq = dev->dev_dma_flushop[hipri].cq; -+ ELAN4_CQ *flushq = dev->dev_flush_cq[elan4_cq2num(cq) & (COMMAND_INSERTER_CACHE_ENTRIES-1)]; -+ struct list_head *ops; -+ unsigned long flags; -+ int qfull,count; -+ E4_uint64 queuePtrs; -+ LIST_HEAD(list); -+ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ -+ ASSERT (cqnum == elan4_cq2num (dev->dev_dma_flushop[hipri].cq)); -+ ASSERT (! list_empty (&dev->dev_dma_flushop[hipri].list)); -+ ASSERT (dev->dev_dma_flushop[hipri].status == 0); -+ -+ /* remove the whole list */ -+ ops = dev->dev_dma_flushop[hipri].list.next; -+ -+ list_del_init (&dev->dev_dma_flushop[hipri].list); -+ -+ /* and add it to our local list */ -+ list_add_tail (&list, ops); -+ -+ /* now determine whether the queue was full - since it cannot be empty -+ * then if the front and back pointers are the same then it is full */ -+ queuePtrs = hipri ? read_reg64 (dev, DProcHighPriPtrs) : read_reg64 (dev, DProcLowPriPtrs); -+ qfull = (E4_QueueFrontPointer (queuePtrs) == E4_QueueBackPointer (queuePtrs)); -+ -+ if (CPROC_TrapType(status) == CommandProcDmaQueueOverflow && !qfull) -+ printk (" ******* queue overflow trap - but queue not full\n"); -+ -+ if (qfull && CPROC_TrapType(status) != CommandProcDmaQueueOverflow) -+ printk (" ****** queue full - but not overflow trap : %llx %llx %x\n", -+ read_reg64 (dev, DProcLowPriPtrs), read_reg64 (dev, DProcHighPriPtrs), CPROC_TrapType(status)); -+ -+ /* Store the status register, this also indicates that the intop is pending */ -+ dev->dev_dma_flushop[hipri].status = status; -+ -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+ -+ /* Issue a main interrupt command to the approriate flush command queue, -+ * which will then safely update the completed pointer to skip over the -+ * command which has trapped, also prevent any new commands to be issued -+ * to the command queue. -+ */ -+ dev->dev_dma_flushop[hipri].intop.op_function = handle_dma_flushops_intop; -+ dev->dev_dma_flushop[hipri].intop.op_arg = (void *) (unsigned long) hipri; -+ -+ elan4_queue_intop (dev, flushq, &dev->dev_dma_flushop[hipri].intop); -+ -+ /* now execute all operations */ -+ for (count = 0; ! list_empty (&list); count++) -+ { -+ ELAN4_DMA_FLUSHOP *op = list_entry (list.next, ELAN4_DMA_FLUSHOP, op_link); -+ -+ list_del (&op->op_link); -+ -+ (*op->op_function) (dev, op->op_arg, qfull); -+ } -+ -+ /* finally release the "reasons" for halting */ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ if ((dev->dev_halt_dproc_count -= count) == 0) -+ elan4_set_schedstatus (dev, 0); -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+ -+ return; -+} -+ -+void -+elan4_queue_dma_flushop (ELAN4_DEV *dev, ELAN4_DMA_FLUSHOP *op, int hipri) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ -+ if (dev->dev_halt_dproc_count++ == 0) /* ensure that the DMA processor cannot */ -+ elan4_set_schedstatus (dev, 0); /* execute the DMA we issue. */ -+ -+ if (list_empty (&dev->dev_dma_flushop[hipri].list) && dev->dev_dma_flushop[hipri].status == 0) -+ __issue_dma_flushop_cmd (dev->dev_dma_flushop[hipri].cq); -+ -+ list_add_tail (&op->op_link, &dev->dev_dma_flushop[hipri].list); -+ -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+} -+ -+static void -+enable_elan_errors (void *arg) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) arg; -+ -+ ENABLE_INT_MASK (dev, INT_ErrorInterrupts); -+} -+ -+#define ERROR_DISABLE_PERIOD (hz/2) -+#define ERROR_SAMPLE_PERIOD (hz/10) -+#define ERROR_LIMIT (100) -+ -+static __inline__ void -+check_error_rate (ELAN4_DEV *dev) -+{ -+ if (dev->dev_error_time == (lbolt/ERROR_SAMPLE_PERIOD)) -+ { -+ if (++dev->dev_errors_per_period >= ERROR_LIMIT && (dev->dev_intmask & INT_ErrorInterrupts)) -+ { -+ DISABLE_INT_MASK (dev, INT_ErrorInterrupts); -+ -+ schedule_timer_fn (&dev->dev_error_timeoutid, enable_elan_errors, (void *) dev, ERROR_DISABLE_PERIOD); -+ } -+ } -+ else -+ { -+ dev->dev_error_time = (lbolt/ERROR_SAMPLE_PERIOD); -+ dev->dev_errors_per_period = 0; -+ } -+} -+ -+static __inline__ int -+handle_mainints (ELAN4_DEV *dev, int nticks, int nintr) -+{ -+ E4_uint32 nfptr = dev->dev_interruptq_nfptr; -+ E4_uint32 bptr = read_reg32 (dev, MainIntQueuePtrs.s.Back); -+ E4_uint32 qsize = E4_QueueSize(elan4_interruptq_size); -+ E4_uint32 qmask = qsize - 1; -+ long tlim = lbolt + nticks; -+ int done = 0; -+ unsigned long flags; -+ -+ do { -+ int todo = ((bptr - nfptr) & qmask) / E4_MainIntEntrySize; -+ -+ ASSERT (todo > 0); -+ -+ PRINTF4 (DBG_DEVICE, DBG_MAININT, "handle_mainints: fptr %x nfptr %x bptr %x : %d todo\n", -+ read_reg32 (dev, MainIntQueuePtrs.s.Front), nfptr, bptr, todo); -+ -+ if (nintr >= 0 && (done + todo) > nintr) /* punt because too may to do in interrupt */ -+ { -+ PRINTF4 (DBG_DEVICE, DBG_MAININT, "handle_mainints: punting (done %d todo %d) (bptr %x fptr %x)\n", -+ done, todo, bptr, read_reg32 (dev, MainIntQueuePtrs.s.Front)); -+ -+ return 1; -+ } -+ -+ BucketDevStat (dev, s_mainints, todo, MainIntBuckets); -+ -+ /* consume all the entries in the queue which we think are there */ -+ do { -+ E4_uint64 value = elan4_sdram_readq (dev, nfptr); -+ ELAN4_CTXT *ctxt = elan4_localctxt (dev, E4_MAIN_INT_CTX (value)); -+ E4_uint32 fptr = nfptr; -+ -+ PRINTF2 (DBG_DEVICE, DBG_MAININT, "handle_mainints: process cookie %llx - write fptr=%x\n", value, nfptr); -+ -+ if (ctxt == NULL) -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "handle_mainints: context %d invalid\n", E4_MAIN_INT_CTX (value)); -+ else -+ ctxt->ctxt_ops->op_interrupt (ctxt, E4_MAIN_INT_COOKIE(value)); -+ -+ /* compute the next queue front pointer, before updating the front pointer -+ * since we need to ensure that elan4_queue_mainintop doesn't see the queue -+ * as being empty if an extra interrupt is queued in between */ -+ dev->dev_interruptq_nfptr = nfptr = (nfptr & ~qmask) | ((nfptr + sizeof (E4_uint64)) & qmask); -+ -+ /* update the queue front pointer, doing this will clear the -+ * interrupt for *all* interrupt cookies which have previously -+ * been added to the queue */ -+ write_reg32 (dev, MainIntQueuePtrs.s.Front, E4_QueueFrontValue (fptr, elan4_interruptq_size)); -+ pioflush_reg (dev); -+ } while (bptr != nfptr); -+ -+ /* re-sample the back pointer and if it's different from the previous -+ * queue front pointer, then the queue has something on it again */ -+ done += todo; -+ -+ if ((nticks > 0 && ((int) (lbolt - tlim)) > 0)) /* been executing for too long in thread */ -+ return 1; -+ -+ bptr = read_reg32 (dev, MainIntQueuePtrs.s.Back); -+ -+ PRINTF3 (DBG_DEVICE, DBG_MAININT, "handle_mainints: resample : fptr %x nfptr %x bptr %x\n", -+ read_reg32 (dev, MainIntQueuePtrs.s.Front), nfptr, bptr); -+ -+ /* at this point we've made some space in the interrupt queue, -+ * so check to see if we've got anything to restart */ -+ spin_lock_irqsave (&dev->dev_mainint_lock, flags); -+ while (! list_empty (&dev->dev_interruptq_list)) -+ { -+ ELAN4_INTOP *op = list_entry (dev->dev_interruptq_list.next, ELAN4_INTOP, op_link); -+ -+ list_del (&op->op_link); -+ -+ op->op_function (dev, op->op_arg); -+ } -+ spin_unlock_irqrestore (&dev->dev_mainint_lock, flags); -+ -+ } while (bptr != nfptr); -+ -+ return 0; -+} -+ -+static void -+elan4_mainint_thread (ELAN4_DEV *dev) -+{ -+ unsigned long flags; -+ -+ kernel_thread_init ("elan4_mainint"); -+ -+ spin_lock_irqsave (&dev->dev_mainint_lock, flags); -+ for (;;) -+ { -+ if (dev->dev_stop_threads) -+ break; -+ -+ if (! (dev->dev_intmask & INT_MainInterrupt)) -+ { -+ spin_unlock_irqrestore (&dev->dev_mainint_lock, flags); -+ -+ if (handle_mainints (dev, elan4_mainint_resched_ticks, -1)) -+ BumpDevStat (dev, s_mainint_rescheds); -+ -+ spin_lock_irqsave (&dev->dev_mainint_lock, flags); -+ ENABLE_INT_MASK (dev, INT_MainInterrupt); -+ } -+ -+ kcondvar_wait (&dev->dev_mainint_wait, &dev->dev_mainint_lock, &flags); -+ } -+ -+ dev->dev_mainint_stopped = 1; -+ kcondvar_wakeupall (&dev->dev_mainint_wait, &dev->dev_mainint_lock); -+ -+ spin_unlock_irqrestore (&dev->dev_mainint_lock, flags); -+ -+ kernel_thread_exit(); -+} -+ -+void -+elan4_queue_mainintop (ELAN4_DEV *dev, ELAN4_INTOP *op) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_mainint_lock, flags); -+ if (dev->dev_interruptq_nfptr == read_reg32 (dev, MainIntQueuePtrs.s.Back)) -+ op->op_function (dev, op->op_arg); -+ else -+ list_add_tail (&op->op_link, &dev->dev_interruptq_list); -+ spin_unlock_irqrestore (&dev->dev_mainint_lock, flags); -+} -+ -+static __inline__ E4_uint32 -+handle_cproc_trap (ELAN4_DEV *dev) -+{ -+ E4_uint32 cqptr = read_reg32 (dev, CommandControl.CommandQueueDescsBase) & E4_QueueDescPtrMask; -+ unsigned cqnum = ((cqptr - dev->dev_cqaddr) / sizeof (E4_CommandQueueDesc)); -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (cqnum * sizeof (E4_CommandQueueDesc)); -+ E4_uint64 control = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control)); -+ E4_uint64 status = read_reg64 (dev, CProcStatus); -+ ELAN4_CTXT *ctxt = elan4_localctxt (dev, CQ_Context (control)); -+ -+ PRINTF4 (DBG_DEVICE, DBG_INTR, "handle_cproc_trap: cqnum=%d status=%016llx control=%016llx TrapType\n", -+ cqnum, status, control, CPROC_TrapType (status)); -+ PRINTF4 (DBG_DEVICE, DBG_INTR, " %016llx %016llx %016llx %016llx\n", -+ elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs)), -+ elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_HoldingValue)), -+ elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_AckBuffers)), -+ elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control))); -+ -+ BumpDevStat (dev, s_cproc_traps); -+ -+ ctxt->ctxt_ops->op_cproc_trap (ctxt, status, cqnum); -+ -+ return (CPROC_TrapType (status) == CommandProcWaitTrap ? SCH_RestartCProc | SCH_RestartEProc : SCH_RestartCProc); -+} -+ -+static __inline__ E4_uint32 -+handle_dproc_trap (ELAN4_DEV *dev, int unit) -+{ -+ E4_uint64 status = (unit == 0) ? read_reg64 (dev, DProc0Status) : read_reg64 (dev, DProc1Status); -+ E4_uint32 restart = (unit == 0) ? SCH_RestartDma0Proc : SCH_RestartDma1Proc; -+ ELAN4_CTXT *ctxt = elan4_localctxt (dev, DPROC_Context (status)); -+ -+ PRINTF3 (DBG_DEVICE, DBG_INTR, "handle_dproc_trap: unit %d context %d%s\n", unit, DPROC_Context(status), -+ DPROC_PrefetcherFault(status) ? " (prefetcher)" : ""); -+ -+ if (DPROC_PrefetcherFault (status)) -+ restart |= SCH_RestartDmaPrefetchProc; -+ -+ BumpDevStat (dev, s_dproc_traps); -+ -+ ctxt->ctxt_ops->op_dproc_trap (ctxt, status, unit); -+ -+ return (restart); -+} -+ -+static __inline__ E4_uint32 -+handle_eproc_trap (ELAN4_DEV *dev) -+{ -+ E4_uint64 status = read_reg64 (dev, EProcStatus); -+ ELAN4_CTXT *ctxt = elan4_localctxt (dev, EPROC_Context (status)); -+ -+ BumpDevStat (dev, s_eproc_traps); -+ -+ ctxt->ctxt_ops->op_eproc_trap (ctxt, status); -+ -+ return (SCH_RestartEProc); -+} -+ -+static __inline__ E4_uint32 -+handle_tproc_trap (ELAN4_DEV *dev) -+{ -+ E4_uint64 status = read_reg64 (dev, TProcStatus); -+ ELAN4_CTXT *ctxt = elan4_localctxt (dev, TPROC_Context (status)); -+ -+ BumpDevStat (dev, s_tproc_traps); -+ -+ ctxt->ctxt_ops->op_tproc_trap (ctxt, status); -+ -+ return (SCH_RestartTProc); -+} -+ -+static __inline__ void -+handle_haltints (ELAN4_DEV *dev, E4_uint32 intreg) -+{ -+ struct list_head list = LIST_HEAD_INIT(list); -+ E4_uint32 mask = 0; -+ E4_uint32 active = 0; -+ struct list_head *entry; -+ struct list_head *next; -+ unsigned long flags; -+ -+ BumpDevStat (dev, s_haltints); -+ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ -+ list_for_each_safe (entry, next, &dev->dev_haltop_list) { -+ ELAN4_HALTOP *op = list_entry (entry, ELAN4_HALTOP, op_link); -+ -+ PRINTF (DBG_DEVICE, DBG_INTR, "handle_haltints: op=%p op_mask=%x intreg=%x\n", op, op->op_mask, intreg); -+ -+ if ((op->op_mask & intreg) != op->op_mask) -+ mask |= op->op_mask; -+ else -+ { -+ list_del (&op->op_link); /* remove from list */ -+ list_add_tail (&op->op_link, &list); /* add to local list */ -+ -+ active |= op->op_mask; -+ } -+ } -+ -+ ASSERT (dev->dev_haltop_mask == (mask | active)); -+ -+ dev->dev_haltop_mask = mask; -+ -+ if (list_empty (&list)) -+ elan4_set_schedstatus (dev, intreg); -+ else -+ { -+ dev->dev_haltop_active = active; -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+ -+ while (! list_empty (&list)) -+ { -+ ELAN4_HALTOP *op = list_entry (list.next, ELAN4_HALTOP, op_link); -+ -+ list_del (&op->op_link); -+ -+ (*op->op_function) (dev, op->op_arg); -+ } -+ -+ spin_lock_irqsave (&dev->dev_haltop_lock, flags); -+ dev->dev_haltop_active = 0; -+ -+ elan4_set_schedstatus (dev, 0); -+ } -+ -+ spin_unlock_irqrestore (&dev->dev_haltop_lock, flags); -+} -+ -+static __inline__ E4_uint32 -+handle_iproc_trap (ELAN4_DEV *dev, unsigned unit) -+{ -+ sdramaddr_t hdroff = dev->dev_inputtraparea + offsetof (E4_IprocTrapState, TrHeader[0][unit]); -+ E4_uint64 status = elan4_sdram_readq (dev, hdroff + offsetof (E4_IprocTrapHeader, IProcStatusCntxAndTrType)); -+ E4_uint32 filter = elan4_read_filter (dev, IPROC_NetworkContext (status)); -+ ELAN4_CTXT *ctxt = elan4_localctxt (dev, filter & E4_FILTER_CONTEXT_MASK); -+ -+ /* -+ * The context is not valid in the following case : -+ * ack not been sent AND bad CRC/bad length. -+ * -+ * NOTE TransCRCStatus and BadLength only valid if NOT an EopTrap. -+ */ -+ ASSERT ((IPROC_GoodAckSent (status) & (1 << IPROC_InputterChan (status))) || IPROC_EOPTrap (status) || -+ (IPROC_TransCRCStatus (status) == CRC_STATUS_GOOD && !IPROC_BadLength (status))); -+ -+ BumpDevStat (dev, s_iproc_traps); -+ -+ ctxt->ctxt_ops->op_iproc_trap (ctxt, status, unit); -+ -+ return (SCH_RestartCh0LowPriInput << unit); -+} -+ -+void -+handle_pcimemerr (ELAN4_DEV *dev) -+{ -+ elan4_pcierror (dev); -+ -+ check_error_rate (dev); -+} -+ -+void -+handle_sdramint (ELAN4_DEV *dev) -+{ -+ E4_uint64 status = read_reg64 (dev, SDRamECCStatus); -+ char errstr[200]; -+ int i; -+ int Found = 0; -+ -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "handle_sdramint\n"); -+ -+ /* search for this error already being logged */ -+ for (i = sizeof (dev->dev_sdramerrs)/sizeof (dev->dev_sdramerrs[0]) - 1; i >= 0; i--) -+ if ((dev->dev_sdramerrs[i] & 0x000fffffffffffffULL) == status) -+ { -+ Found = 1; -+ dev->dev_sdramerrs[i] += 10000000000000ULL; // Keep a count. -+ break; -+ } -+ -+ /* stash the status for /proc */ -+ if (!Found) -+ { -+ for (i = sizeof (dev->dev_sdramerrs)/sizeof (dev->dev_sdramerrs[0]) - 1; i > 0; i--) -+ dev->dev_sdramerrs[i] = dev->dev_sdramerrs[i-1]; -+ dev->dev_sdramerrs[0] = status; -+ } -+ -+ printk ("elan%d: ECC Error %s\n", dev->dev_instance, elan4_sdramerr2str (dev, status, errstr)); -+ -+ if (!ECC_UncorrectableErr(status) && !ECC_MultUncorrectErrs(status)) -+ printk ("elan%d: ECC error data=%016llx\n", dev->dev_instance, elan4_sdram_readq (dev, ECC_Addr(status))); -+ -+ if (ECC_CorrectableErr (status)) -+ BumpDevStat (dev, s_correctable_errors); -+ if (ECC_MultCorrectErrs (status)) -+ BumpDevStat (dev, s_multiple_errors); -+ -+ if (ECC_UncorrectableErr(status)) -+ panic ("elan%d: uncorrectable ECC error\n", dev->dev_instance); -+ if (ECC_MultUncorrectErrs(status)) -+ panic ("elan%d: muliple uncorrectable ECC error\n", dev->dev_instance); -+ -+ PULSE_SYSCONTROL (dev, CONT_CLEAR_SDRAM_ERROR); -+ -+ check_error_rate (dev); -+} -+ -+static void -+clear_linkerr_led (void *arg) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) arg; -+ -+ write_i2c (dev, I2cStatus, read_i2c (dev, I2cStatus) | I2cCntl_ClearLinkError); -+} -+ -+void -+handle_linkerror (ELAN4_DEV *dev) -+{ -+ E4_uint32 LinkState; -+ E4_uint32 CurrState = read_reg32 (dev, LinkControlReg); -+ -+ /* Set for reading errors. */ -+ write_reg32 (dev, LinkControlReg, -+ (CurrState = CurrState & ~((LCONT_TEST_CONTROL_MASK << LCONT_TEST_CONTROL_SHIFT) | -+ (LCONT_TEST_VALUE_MASK << LCONT_TEST_VALUE_SHIFT)))); -+ LinkState = LCONT_LINK_STATE(CurrState = read_reg32 (dev, LinkControlReg)); -+ -+#ifdef DEBUG -+ { -+ E4_uint8 ErrorMsg[256], DataErrorVal[64]; -+ -+ strcpy (ErrorMsg, "handle_linkerror:"); -+ if (LinkState & LS_LockError) strcat (ErrorMsg, " LockError"); -+ if (LinkState & LS_DeskewError) strcat (ErrorMsg, " DeskewError"); -+ if (LinkState & LS_PhaseError) strcat (ErrorMsg, " PhaseError"); -+ if (LinkState & LS_DataError) -+ { -+ E4_uint32 error[4]; -+ E4_uint32 i; -+ strcat (ErrorMsg, " DataError"); -+ /* Errors */ -+ for(i = LRS_ErrorVal8to0; i <= LRS_ErrorVal35to27; i++) -+ { -+ write_reg32 (dev, LinkControlReg, -+ CurrState | LCONT_TEST_VALUE(i) | (LCONT_READ_STATE << LCONT_TEST_CONTROL_SHIFT)); -+ error[i - LRS_ErrorVal8to0] = LCONT_LINK_STATE(read_reg32 (dev, LinkControlReg)); -+ } -+ sprintf (DataErrorVal, " Link State Error Val: %09llx %03x %03x %03x %03x", -+ (unsigned long long) ((error[0] & 0x1ffUL) | ((error[1] & 0x1ffUL) << 9) | -+ ((error[2] & 0x1ffUL) << 18) | ((error[3] & 0x1ffUL) << 27)), -+ error[3], error[2], error[1], error[0]); -+ strcat (ErrorMsg, DataErrorVal); -+ } -+ if (LinkState & LS_FifoOvFlow0) strcat (ErrorMsg, " FifoOvFlow0"); -+ if (LinkState & LS_FifoOvFlow1) strcat (ErrorMsg, " FifoOvFlow1"); -+ if (LinkState & LS_Mod45Changed) strcat (ErrorMsg, " Mod45Changed"); -+ if (LinkState & LS_PAckNotSeenError) strcat (ErrorMsg, " PAckNotSeenError"); -+ strcat (ErrorMsg, "\n"); -+ PRINTF0 (DBG_DEVICE, DBG_INTR, ErrorMsg); -+ } -+#endif -+ -+ BumpDevStat (dev, s_link_errors); -+ -+ if (LinkState & LS_LockError) BumpDevStat (dev, s_lock_errors); -+ if (LinkState & LS_DeskewError) BumpDevStat (dev, s_deskew_errors); -+ if (LinkState & LS_PhaseError) BumpDevStat (dev, s_phase_errors); -+ if (LinkState & LS_DataError) BumpDevStat (dev, s_data_errors); -+ if (LinkState & LS_FifoOvFlow0) BumpDevStat (dev, s_fifo_overflow0); -+ if (LinkState & LS_FifoOvFlow1) BumpDevStat (dev, s_fifo_overflow1); -+ if (LinkState & LS_Mod45Changed) BumpDevStat (dev, s_mod45changed); -+ if (LinkState & LS_PAckNotSeenError) BumpDevStat (dev, s_pack_not_seen); -+ -+ PULSE_SCHED_RESTART (dev, SCH_ClearLinkErrorInt); -+ -+ /* schedule a timer to clear the link error LED, so that it stays on -+ * for a second for every link error that occurs */ -+ if (dev->dev_devinfo.dev_revision_id != PCI_REVISION_ID_ELAN4_REVA && !timer_fn_queued (&dev->dev_linkerr_timeoutid)) -+ schedule_timer_fn (&dev->dev_linkerr_timeoutid, clear_linkerr_led, (void *) dev, HZ); -+ -+ check_error_rate (dev); -+} -+ -+void -+handle_linkportkeyfail (ELAN4_DEV *dev) -+{ -+ PRINTF0 (DBG_DEVICE, DBG_INTR, "handle_linkportkeyfail\n"); -+ -+ BumpDevStat (dev, s_linkport_keyfail); -+ -+ PULSE_SYSCONTROL (dev, CONT_CLEAR_LINKPORT_INT); -+ -+ check_error_rate (dev); -+} -+ -+ -+static __inline__ void -+__elan4_4msi0 (ELAN4_DEV *dev, E4_uint32 intreg, E4_uint32 intmask) -+{ -+ unsigned long flags; -+ -+ if (intreg & intmask & INT_MainInterrupt) -+ { -+ DISABLE_INT_MASK (dev, INT_MainInterrupt); -+ -+ if (handle_mainints (dev, -1, elan4_mainint_punt_loops) == 0) -+ ENABLE_INT_MASK (dev, INT_MainInterrupt); -+ else -+ { -+ BumpDevStat (dev, s_mainint_punts); -+ -+ spin_lock_irqsave (&dev->dev_mainint_lock, flags); -+ kcondvar_wakeupone (&dev->dev_mainint_wait, &dev->dev_mainint_lock); -+ spin_unlock_irqrestore (&dev->dev_mainint_lock, flags); -+ } -+ } -+} -+ -+static __inline__ void -+__elan4_4msi1 (ELAN4_DEV *dev, E4_uint32 intreg, E4_uint32 intmask) -+{ -+ E4_uint32 restart = 0; -+ -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "__elan4_4msi1: %x\n", intreg); -+ -+ spin_lock (&dev->dev_trap_lock); -+ -+ if (intreg & intmask & INT_CProc) -+ restart |= handle_cproc_trap (dev); -+ if (intreg & intmask & INT_EProc) -+ restart |= handle_eproc_trap (dev); -+ if (intreg & intmask & INT_Dma0Proc) -+ restart |= handle_dproc_trap (dev, 0); -+ if (intreg & intmask & INT_Dma1Proc) -+ restart |= handle_dproc_trap (dev, 1); -+ if (intreg & intmask & INT_TProc) -+ restart |= handle_tproc_trap (dev); -+ -+ PULSE_SCHED_RESTART (dev, restart); -+ -+ spin_unlock (&dev->dev_trap_lock); -+ -+ if (intreg & (INT_Halted|INT_Discarding)) -+ handle_haltints (dev, intreg); -+} -+ -+static __inline__ void -+__elan4_4msi2 (ELAN4_DEV *dev, E4_uint32 intreg, E4_uint32 intmask) -+{ -+ E4_uint32 restart = 0; -+ -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "__elan4_4msi2: %x\n", intreg); -+ -+ spin_lock (&dev->dev_trap_lock); -+ if (intreg & intmask & INT_IProcCh0LowPri) -+ restart |= handle_iproc_trap (dev, 0); -+ -+ if (intreg & intmask & INT_IProcCh1LowPri) -+ restart |= handle_iproc_trap (dev, 1); -+ -+ if (intreg & intmask & INT_IProcCh0HighPri) -+ restart |= handle_iproc_trap (dev, 2); -+ -+ if (intreg & intmask & INT_IProcCh1HighPri) -+ restart |= handle_iproc_trap (dev, 3); -+ -+ PULSE_SCHED_RESTART (dev, restart); -+ -+ spin_unlock (&dev->dev_trap_lock); -+} -+ -+static __inline__ void -+__elan4_4msi3 (ELAN4_DEV *dev, E4_uint32 intreg, E4_uint32 intmask) -+{ -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "__elan4_4msi3: %x\n", intreg); -+ -+ if (intreg & intmask & INT_PciMemErr) -+ handle_pcimemerr (dev); -+ -+ if (intreg & intmask & INT_SDRamInt) -+ handle_sdramint (dev); -+ -+ if (intreg & intmask & INT_LinkError) -+ handle_linkerror (dev); -+ -+ if (intreg & intmask & INT_LinkPortKeyFail) -+ handle_linkportkeyfail (dev); -+} -+ -+int -+elan4_1msi0 (ELAN4_DEV *dev) -+{ -+ E4_uint32 intmask = dev->dev_intmask; -+ E4_uint32 intreg; -+ -+ if (intmask == 0 || ((intreg = read_reg32 (dev, InterruptReg)) & intmask) == 0) -+ return (0); -+ -+ BumpDevStat (dev, s_interrupts); -+ -+ do { -+ PRINTF1 (DBG_DEVICE, DBG_INTR, "elan4_1msi0: %x\n", intreg); -+ -+ if (intreg & intmask & INT_MSI0) -+ __elan4_4msi0(dev, intreg, intmask); -+ if (intreg & intmask & INT_MSI1) -+ __elan4_4msi1(dev, intreg, intmask); -+ if (intreg & intmask & INT_MSI2) -+ __elan4_4msi2(dev, intreg, intmask); -+ if (intreg & intmask & INT_MSI3) -+ __elan4_4msi3(dev, intreg, intmask); -+ -+ /* must ensure that the read of the interrupt mask -+ * completes before the read of the interrupt register -+ * since the main interrupt thread clears it's interrupt -+ * and then re-enables it in the interrupt mask. */ -+ intmask = dev->dev_intmask; -+ mb(); -+ intreg = read_reg32 (dev, InterruptReg); -+ -+ } while ((intreg & intmask) != 0); -+ -+ return (1); -+} -+ -+/* local context management */ -+int -+elan4_insertctxt (ELAN4_DEV *dev, ELAN4_CTXT *ctxt, ELAN4_TRAP_OPS *ops) -+{ -+ unsigned long flags; -+ int tbl; -+ -+ ctxt->ctxt_dev = dev; -+ ctxt->ctxt_ops = ops; -+ -+ INIT_LIST_HEAD (&ctxt->ctxt_cqalist); -+ spin_lock_init (&ctxt->ctxt_mmulock); -+ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ { -+ KMEM_ZALLOC (ctxt->ctxt_mmuhash[tbl], ELAN4_HASH_ENTRY **, dev->dev_hashsize[tbl] * sizeof (ELAN4_HASH_ENTRY *), 1); -+ -+ if (ctxt->ctxt_mmuhash[tbl] == NULL) -+ { -+ if (tbl != 0) -+ KMEM_FREE (ctxt->ctxt_mmuhash[0], dev->dev_hashsize[0] * sizeof (ELAN4_HASH_ENTRY *)); -+ spin_lock_destroy (&ctxt->ctxt_mmulock); -+ return (-ENOMEM); -+ } -+ } -+ -+ spin_lock_irqsave (&dev->dev_ctxt_lock, flags); -+ -+ if ((ctxt->ctxt_num = bt_freebit (dev->dev_ctxmap, (1 << dev->dev_ctxtableshift))) >= 0) -+ { -+ /* chain onto the lists of all contexts */ -+ list_add (&ctxt->ctxt_link, &dev->dev_ctxt_list); -+ -+ BT_SET (dev->dev_ctxmap, ctxt->ctxt_num); -+ } -+ -+ spin_unlock_irqrestore (&dev->dev_ctxt_lock, flags); -+ -+ return (ctxt->ctxt_num < 0 ? -ENOMEM : 0); -+} -+ -+void -+elan4_removectxt (ELAN4_DEV *dev, ELAN4_CTXT *ctxt) -+{ -+ unsigned long flags; -+ int tbl; -+ -+ /* remove from list of contexts */ -+ spin_lock_irqsave (&dev->dev_ctxt_lock, flags); -+ -+ list_del (&ctxt->ctxt_link); -+ -+ BT_CLEAR (dev->dev_ctxmap, ctxt->ctxt_num); -+ -+ spin_unlock_irqrestore (&dev->dev_ctxt_lock, flags); -+ -+ spin_lock_destroy (&ctxt->ctxt_info_lock); -+ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ KMEM_FREE (ctxt->ctxt_mmuhash[tbl], dev->dev_hashsize[tbl] * sizeof (ELAN4_HASH_ENTRY *)); -+ -+ spin_lock_destroy (&ctxt->ctxt_mmulock); -+} -+ -+ELAN4_CTXT * -+elan4_localctxt (ELAN4_DEV *dev, unsigned num) -+{ -+ struct list_head *entry; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_ctxt_lock, flags); -+ -+ list_for_each (entry, &dev->dev_ctxt_list) { -+ ELAN4_CTXT *ctxt = list_entry (entry, ELAN4_CTXT, ctxt_link); -+ -+ if (ctxt->ctxt_num == num) -+ { -+ spin_unlock_irqrestore (&dev->dev_ctxt_lock, flags); -+ return (ctxt); -+ } -+ } -+ spin_unlock_irqrestore (&dev->dev_ctxt_lock, flags); -+ -+ return ((ELAN4_CTXT *) NULL); -+} -+ -+ELAN4_CTXT * -+elan4_networkctxt (ELAN4_DEV *dev, unsigned num) -+{ -+ E4_uint32 filter = elan4_read_filter (dev, num); -+ -+ if ((filter & E4_FILTER_CONTEXT_MASK) == INVALID_CONTEXT) -+ return NULL; -+ else -+ return elan4_localctxt (dev, filter & E4_FILTER_CONTEXT_MASK); -+} -+ -+/* network context management */ -+int -+elan4_attach_filter (ELAN4_CTXT *ctxt, unsigned int ctxnum) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ int res = 0; -+ E4_uint32 filter; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_ctxt_lock, flags); -+ -+ filter = elan4_read_filter (dev, ctxnum); -+ if ((filter & E4_FILTER_CONTEXT_MASK) != INVALID_CONTEXT) -+ { -+ PRINTF2 (ctxt, DBG_NETWORK_CTX, "elan4_attach_filter: ctx=%d filter=%x -> EBUSY\n", ctxnum, filter); -+ res = -EBUSY; -+ } -+ else -+ { -+ PRINTF1 (ctxt, DBG_NETWORK_CTX, "elan4_attach_filter: ctx=%d - SUCCESS\n", ctxnum); -+ -+ elan4_write_filter (dev, ctxnum, ctxt->ctxt_num | E4_FILTER_DISCARD_ALL); -+ PULSE_SCHED_RESTART (dev, SCH_ContextFilterFlush); -+ } -+ spin_unlock_irqrestore (&dev->dev_ctxt_lock, flags); -+ -+ return (res); -+} -+ -+void -+elan4_detach_filter (ELAN4_CTXT *ctxt, unsigned int ctxnum) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ -+ PRINTF1 (ctxt, DBG_NETWORK_CTX, "elan4_detach_filter: detach from network context %d\n", ctxnum); -+ -+ elan4_write_filter (dev, ctxnum, INVALID_CONTEXT | E4_FILTER_DISCARD_ALL); -+ PULSE_SCHED_RESTART (dev, SCH_ContextFilterFlush); -+} -+ -+void -+elan4_set_filter (ELAN4_CTXT *ctxt, unsigned int ctxnum, E4_uint32 state) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ -+ PRINTF6 (ctxt, DBG_NETWORK_CTX, "elan4_set_filter: set filter state %x for network context %d <%s%s%s%s>\n", state, ctxnum, -+ (state & E4_FILTER_DISCARD_ALL) ? "discard," : "", -+ (state & E4_FILTER_ACKOK_ALL) ? "ack-ok," : "", -+ (state & E4_FILTER_HIGH_PRI) ? "high-pri," : "", -+ (state & E4_FILTER_STATS) ? "stats," : ""); -+ -+ elan4_write_filter (dev, ctxnum, ctxt->ctxt_num | state); -+ PULSE_SCHED_RESTART (dev, SCH_ContextFilterFlush); -+} -+ -+void -+elan4_set_routetable (ELAN4_CTXT *ctxt, ELAN4_ROUTE_TABLE *tbl) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ E4_uint32 value = tbl ? (E4_VPT_VALID | E4_VPT_VALUE(tbl->tbl_entries, tbl->tbl_size)) : 0; -+ -+ /* and insert into the vp table */ -+ elan4_sdram_writel (dev, (dev->dev_ctxtable + (ctxt->ctxt_num * sizeof (E4_ContextControlBlock)) + -+ offsetof (E4_ContextControlBlock, VirtualProcessTable)), value); -+ pioflush_sdram(dev); -+ -+ PULSE_SYSCONTROL (dev, CONT_ROUTE_FLUSH); -+} -+ -+/* command queue management */ -+ELAN4_CQA * -+elan4_getcqa (ELAN4_CTXT *ctxt, unsigned int idx) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ struct list_head *el; -+ -+ spin_lock (&dev->dev_cqlock); -+ list_for_each (el, &ctxt->ctxt_cqalist) { -+ ELAN4_CQA *cqa = list_entry (el, ELAN4_CQA, cqa_link); -+ -+ if (cqa->cqa_idx == idx) -+ { -+ cqa->cqa_ref++; -+ -+ spin_unlock (&dev->dev_cqlock); -+ return cqa; -+ } -+ } -+ spin_unlock (&dev->dev_cqlock); -+ return NULL; -+} -+ -+void -+elan4_putcqa (ELAN4_CTXT *ctxt, unsigned int idx) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ struct list_head *el, *nel; -+ -+ spin_lock (&dev->dev_cqlock); -+ list_for_each_safe (el, nel, &ctxt->ctxt_cqalist) { -+ ELAN4_CQA *cqa = list_entry (el, ELAN4_CQA, cqa_link); -+ -+ if (cqa->cqa_idx == idx) -+ { -+ if (--cqa->cqa_ref || bt_lowbit (cqa->cqa_bitmap, ELAN4_CQ_PER_CQA) != -1) -+ spin_unlock (&dev->dev_cqlock); -+ else -+ { -+ list_del (&cqa->cqa_link); -+ -+ BT_CLEAR (ctxt->ctxt_cqamap, cqa->cqa_idx); -+ BT_CLEAR (dev->dev_cqamap, cqa->cqa_cqnum/ELAN4_CQ_PER_CQA); -+ spin_unlock (&dev->dev_cqlock); -+ -+ KMEM_FREE (cqa, sizeof (ELAN4_CQA)); -+ } -+ return; -+ } -+ } -+ spin_unlock (&dev->dev_cqlock); -+ -+ printk ("elan4_putcqa: idx %d not found\n", idx); -+ BUG(); -+} -+ -+static ELAN4_CQ * -+elan4_getcq (ELAN4_CTXT *ctxt, unsigned int type) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ ELAN4_CQA *cqa; -+ struct list_head *el; -+ int cidx, didx; -+ -+ spin_lock (&dev->dev_cqlock); -+ list_for_each (el, &ctxt->ctxt_cqalist) { -+ cqa = list_entry (el, ELAN4_CQA, cqa_link); -+ -+ if (cqa->cqa_type == type && (cidx = bt_freebit (cqa->cqa_bitmap, ELAN4_CQ_PER_CQA)) >=0) -+ { -+ BT_SET (cqa->cqa_bitmap, cidx); -+ -+ spin_unlock (&dev->dev_cqlock); -+ return &cqa->cqa_cq[cidx]; -+ } -+ } -+ spin_unlock (&dev->dev_cqlock); -+ -+ /* allocate a new cqa and it's chunk of command queue descriptors */ -+ KMEM_ZALLOC (cqa, ELAN4_CQA *, sizeof (ELAN4_CQA), 1); -+ if (cqa == NULL) -+ return NULL; -+ -+ spin_lock (&dev->dev_cqlock); -+ cidx = bt_freebit (ctxt->ctxt_cqamap, ELAN4_MAX_CQA); -+ -+ /* On architectures which have MTRR registers for write-combinig -+ * the top command queues from dev->dev_cqreorder upwards are -+ * used for reordered queues. Without MTRR registers any page -+ * sized group can use write combinig through the ptes. */ -+#ifdef CONFIG_MTRR -+ if ((type & CQ_Reorder) != 0) -+ didx = bt_nextbit (dev->dev_cqamap, dev->dev_cqcount, dev->dev_cqreorder - 1, 0); -+ else -+ didx = bt_freebit (dev->dev_cqamap, dev->dev_cqreorder); -+#else -+ didx = bt_freebit (dev->dev_cqamap, dev->dev_cqcount); -+#endif -+ -+ if (cidx < 0 || didx < 0) -+ { -+ spin_unlock (&dev->dev_cqlock); -+ KMEM_FREE (cqa, sizeof (ELAN4_CQA)); -+ return NULL; -+ } -+ -+ BT_SET (ctxt->ctxt_cqamap, cidx); -+ BT_SET (dev->dev_cqamap, didx); -+ -+ cqa->cqa_idx = cidx; -+ cqa->cqa_type = type; -+ cqa->cqa_cqnum = (didx * ELAN4_CQ_PER_CQA); -+ -+ list_add_tail (&cqa->cqa_link, &ctxt->ctxt_cqalist); -+ -+ /* initialise the cqa struct */ -+ for (cidx = 0; cidx < ELAN4_CQ_PER_CQA; cidx++) -+ { -+ cqa->cqa_cq[cidx].cq_idx = cidx; -+ cqa->cqa_cq[cidx].cq_cqa = cqa; -+ } -+ -+ /* no mappings yet */ -+ cqa->cqa_ref = 0; -+ -+ /* we're going to return entry zero */ -+ BT_SET (cqa->cqa_bitmap, 0); -+ spin_unlock (&dev->dev_cqlock); -+ -+ return &cqa->cqa_cq[0]; -+} -+ -+static void -+elan4_putcq (ELAN4_CTXT *ctxt, ELAN4_CQ *cq) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ ELAN4_CQA *cqa = cq->cq_cqa; -+ -+ spin_lock (&dev->dev_cqlock); -+ -+ BT_CLEAR (cqa->cqa_bitmap, cq->cq_idx); -+ -+ if (bt_lowbit (cqa->cqa_bitmap, ELAN4_CQ_PER_CQA) != -1 || cqa->cqa_ref) -+ spin_unlock (&dev->dev_cqlock); -+ else -+ { -+ list_del (&cqa->cqa_link); -+ -+ BT_CLEAR (ctxt->ctxt_cqamap, cqa->cqa_idx); -+ BT_CLEAR (dev->dev_cqamap, cqa->cqa_cqnum/ELAN4_CQ_PER_CQA); -+ spin_unlock (&dev->dev_cqlock); -+ -+ KMEM_FREE (cqa, sizeof (ELAN4_CQA)); -+ } -+} -+ -+ELAN4_CQ * -+elan4_alloccq (ELAN4_CTXT *ctxt, unsigned cqsize, unsigned perm, unsigned cqtype) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ ELAN4_CQ *cq; -+ int cqnum; -+ sdramaddr_t cqdesc; -+ unsigned offset; -+ E4_uint64 value; -+ -+ if ((cq = elan4_getcq (ctxt, cqtype)) == NULL) -+ return NULL; -+ -+ cqnum = elan4_cq2num(cq); -+ -+ cq->cq_space = elan4_sdram_alloc (dev, CQ_Size(cqsize)); -+ if (cq->cq_space == (virtaddr_t) 0) -+ { -+ elan4_putcq (ctxt, cq); -+ return (NULL); -+ } -+ -+ cq->cq_size = cqsize; -+ cq->cq_perm = perm; -+ -+ /* and finally initialise the command queue descriptor */ -+ cqdesc = dev->dev_cqaddr + (cqnum * sizeof (E4_CommandQueueDesc)); -+ -+ value = CQ_QueuePtrsValue (cqsize, cq->cq_space, cq->cq_space); -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ value |= ((cqtype & CQ_Priority) ? CQ_RevA_Priority : 0); -+ else -+ value |= (((cqtype & CQ_Priority) ? CQ_RevB_Priority : 0) | -+ ((cqtype & CQ_Reorder) ? CQ_RevB_ReorderingQueue : CQ_RevB_32bitWriteQueue)); -+ -+ elan4_sdram_writeq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs), value); -+ elan4_sdram_writeq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_HoldingValue), 0); -+ elan4_sdram_writeq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_AckBuffers), 0); -+ elan4_sdram_writeq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control), CQ_ControlValue (ctxt->ctxt_num, 2, perm)); -+ pioflush_sdram (dev); -+ -+ offset = (cqnum + dev->dev_cqoffset) * CQ_CommandMappingSize; -+ -+ cq->cq_mapping = elan4_map_device (dev, ELAN4_BAR_REGISTERS, (offset & ~(PAGE_SIZE-1)), -+ PAGE_SIZE, &cq->cq_handle) + (offset & (PAGE_SIZE-1)); -+#ifdef CONFIG_MPSAS -+ if (ctxt == &dev->dev_ctxt) -+ return (cq); -+#endif -+ -+ elan4_sdram_flushcache (dev, cq->cq_space, CQ_Size(cqsize)); -+ -+ return (cq); -+} -+ -+void -+elan4_freecq (ELAN4_CTXT *ctxt, ELAN4_CQ *cq) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned offset = (elan4_cq2num(cq) + dev->dev_cqoffset) * CQ_CommandMappingSize; -+ -+ elan4_flushcq (dev, cq); -+ -+ elan4_unmap_device (dev, cq->cq_mapping - (offset & (PAGE_SIZE-1)), PAGE_SIZE, &cq->cq_handle); -+ elan4_sdram_free (dev, cq->cq_space, CQ_Size (cq->cq_size)); -+ -+ elan4_putcq (ctxt, cq); -+} -+ -+void -+elan4_restartcq (ELAN4_DEV *dev, ELAN4_CQ *cq) -+{ -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (elan4_cq2num(cq) * sizeof (E4_CommandQueueDesc)); -+ int hipri; -+ unsigned long flags; -+ -+ PRINTF1 (DBG_DEVICE, DBG_CPROC, "restartcq: restarting cq %p\n", cq); -+ -+ spin_lock_irqsave (&dev->dev_requeue_lock, flags); -+ -+ while (read_reg32 (dev, CommandControl.CommandRequeuePtr) & E4_CommandRequeueBusy) -+ ; -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ hipri = (elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs)) & CQ_RevA_Priority) != 0; -+ else -+ hipri = (elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs)) & CQ_RevB_Priority) != 0; -+ -+ if (hipri) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_CPROC, "restartcq: restart cq %d as high pri\n", elan4_cq2num(cq)); -+ write_reg32 (dev, CommandControl.CommandRequeuePtr, cqdesc | E4_CommandRequeueHighPri); -+ } -+ else -+ { -+ PRINTF1 (DBG_DEVICE, DBG_CPROC, "restartcq: restart cq %d as low pri\n", elan4_cq2num(cq)); -+ write_reg32 (dev, CommandControl.CommandRequeuePtr, cqdesc); -+ } -+ pioflush_reg (dev); -+ -+ spin_unlock_irqrestore (&dev->dev_requeue_lock, flags); -+} -+ -+static void -+flushcq_intop (ELAN4_DEV *dev, void *arg) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_flush_lock, flags); -+ dev->dev_flush_finished |= (1 << (unsigned long) arg); -+ kcondvar_wakeupall (&dev->dev_flush_wait, &dev->dev_flush_lock); -+ spin_unlock_irqrestore (&dev->dev_flush_lock, flags); -+} -+void -+elan4_flushcq (ELAN4_DEV *dev, ELAN4_CQ *cq) -+{ -+ int flushqnum = elan4_cq2num(cq) & (COMMAND_INSERTER_CACHE_ENTRIES-1); -+ ELAN4_CQ *flushq = dev->dev_flush_cq[flushqnum]; -+ unsigned long flags; -+ -+ PRINTF (DBG_DEVICE, DBG_FLUSH, "elan4_flushcq: cqnum=%d\n", elan4_cq2num(cq)); -+ -+ spin_lock_irqsave (&dev->dev_flush_lock, flags); -+ -+ while (! (dev->dev_flush_finished & (1 << flushqnum))) -+ kcondvar_wait (&dev->dev_flush_wait, &dev->dev_flush_lock, &flags); -+ -+ dev->dev_flush_finished &= ~(1 << flushqnum); -+ -+ dev->dev_flush_op[flushqnum].op_function = flushcq_intop; -+ dev->dev_flush_op[flushqnum].op_arg = (void *) (unsigned long) flushqnum; -+ -+ elan4_queue_intop (dev, flushq, &dev->dev_flush_op[flushqnum]); -+ -+ while (! (dev->dev_flush_finished & (1 << flushqnum))) -+ kcondvar_wait (&dev->dev_flush_wait, &dev->dev_flush_lock, &flags); -+ -+ spin_unlock_irqrestore (&dev->dev_flush_lock, flags); -+} -+ -+void -+elan4_updatecq (ELAN4_DEV *dev, ELAN4_CQ *cq, unsigned perm, unsigned restart) -+{ -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (elan4_cq2num(cq) * sizeof (E4_CommandQueueDesc)); -+ E4_uint32 control = elan4_sdram_readl (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control)); -+ -+ /* Write the command queues control word, but ensure that the ChannelNotCompleted fields -+ * are not modified. We use this to just alter the RestartCount/Permissions fields */ -+ -+ elan4_sdram_writel (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control), -+ CQ_ControlValue (CQ_Context (control), restart ? restart : CQ_RestartCount (control), perm)); -+} -+ -+/* instruction cache flush */ -+static __inline__ void -+elan4_flush_icache_locked (ELAN4_DEV *dev) -+{ -+ int i, j; -+ -+ PRINTF0 (DBG_DEVICE, DBG_FLUSH, "elan4_flush_icache_locked: flushing icache\n"); -+ -+ for (i = 0; i < (E4_ICacheLines/E4_ICachePortSize); i++) -+ { -+ write_reg64 (dev, ICachePort_Cntl_Addr, i << E4_ICacheTagAddrShift); -+ for (j = 0; j < E4_ICachePortSize; j++) -+ write_reg64 (dev, ICachePort[j], E4_InvalidTagValue); -+ } -+ -+ /* -+ * Initialise the top of the ICache Set0 with a instruction which will -+ * cause a know trap fingerprint so that the application can identify it -+ * and ignore the trap. -+ */ -+ write_reg64 (dev, ICachePort_Cntl_Addr, E4_ICacheFixupOffset | E4_AccessICacheRams); -+ -+ /* Errata 24: must ensure that the DCache is flushed after loading -+ * code for the thread processor. */ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ elan4_sdram_flushcache (dev, 0, E4_CacheSize); -+ -+ pioflush_reg (dev); -+} -+ -+static void -+device_iflush_haltop (ELAN4_DEV *dev, void *arg) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_flush_lock, flags); -+ -+ elan4_flush_icache_locked (dev); -+ -+ dev->dev_iflush_queued = 0; -+ -+ kcondvar_wakeupall (&dev->dev_flush_wait, &dev->dev_flush_lock); -+ spin_unlock_irqrestore (&dev->dev_flush_lock, flags); -+} -+ -+void -+elan4_flush_icache_halted (ELAN4_CTXT *ctxt) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_flush_lock, flags); -+ -+ elan4_flush_icache_locked (dev); -+ -+ spin_unlock_irqrestore (&dev->dev_flush_lock, flags); -+} -+ -+void -+elan4_flush_icache (ELAN4_CTXT *ctxt) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_flush_lock, flags); -+ -+ PRINTF1 (DBG_DEVICE, DBG_FLUSH, "elan4_flush_icache: queued=%d\n", dev->dev_iflush_queued); -+ -+ if (! dev->dev_iflush_queued) -+ { -+ dev->dev_iflush_queued = 1; -+ -+ elan4_queue_haltop (dev, &dev->dev_iflush_haltop); -+ } -+ -+ while (dev->dev_iflush_queued) -+ kcondvar_wait (&dev->dev_flush_wait, &dev->dev_flush_lock, &flags); -+ -+ spin_unlock_irqrestore (&dev->dev_flush_lock, flags); -+} -+ -+/* device context operations */ -+static void -+device_cproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned cqnum) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ ELAN4_CPROC_TRAP *trap = &dev->dev_cproc_trap; -+ -+ elan4_extract_cproc_trap (dev, status, trap, cqnum); -+ -+ DBGCMD (DBG_DEVICE, DBG_FLUSH, elan4_display_cproc_trap (DBG_DEVICE, DBG_FLUSH, "device_cproc_trap", trap)); -+ -+ switch (CPROC_TrapType (trap->tr_status)) -+ { -+ case CommandProcInterruptQueueOverflow: -+ PRINTF (ctxt, DBG_FLUSH, "device_cproc_trap: cqnum=%d\n", cqnum); -+ -+ /* XXXX: we could either just hit restart (and hope) - or we could extract -+ * the event interrupt cookie out and "complete" the command before -+ * restarting it */ -+ elan4_restartcq (dev, dev->dev_flush_cq[cqnum]); -+ return; -+ -+ case CommandProcDmaQueueOverflow: -+ case CommandProcPermissionTrap: -+ handle_dma_flushops (dev, status, cqnum); -+ return; -+ -+ default: -+ printk ("device_cproc_trap: status=%llx control=%llx TrapType=%x cqnum=%d\n", (long long) trap->tr_status, -+ elan4_sdram_readq (dev, dev->dev_cqaddr + cqnum * sizeof (E4_CommandQueueDesc) + -+ offsetof (E4_CommandQueueDesc, CQ_Control)), -+ (int) CPROC_TrapType(trap->tr_status), cqnum); -+ panic ("device_cproc_trap"); -+ } -+} -+ -+static void -+device_tproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status) -+{ -+ ELAN4_TPROC_TRAP trap; -+ -+ elan4_extract_tproc_trap (ctxt->ctxt_dev, status, &trap); -+ -+ elan4_display_tproc_trap (DBG_CONSOLE, DBG_TRAP, "device_tproc_trap", &trap); -+ panic ("device_tproc_trap"); -+} -+ -+static void -+device_dproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit) -+{ -+ ELAN4_DPROC_TRAP trap; -+ -+ elan4_extract_dproc_trap (ctxt->ctxt_dev, status, &trap, unit); -+ -+ elan4_display_dproc_trap (DBG_CONSOLE, DBG_TRAP, "device_dproc_trap", &trap); -+ panic ("device_dproc_trap"); -+} -+ -+static void -+device_interrupt (ELAN4_CTXT *ctxt, E4_uint64 cookie) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) ctxt; -+ struct list_head *el,*nel; -+ unsigned long flags; -+ -+ PRINTF (ctxt, DBG_FLUSH, "device_interrupt: cookie=%llx\n", cookie); -+ -+ spin_lock_irqsave (&dev->dev_intop_lock, flags); -+ list_for_each_safe (el, nel, &dev->dev_intop_list) { -+ ELAN4_INTOP *op = list_entry (el, ELAN4_INTOP, op_link); -+ -+ if (op->op_cookie == cookie) -+ { -+ if ((op->op_cookie & INTOP_TYPE_MASK) == INTOP_ONESHOT) -+ list_del (&op->op_link); -+ -+ spin_unlock_irqrestore (&dev->dev_intop_lock, flags); -+ -+ (*op->op_function)(dev, op->op_arg); -+ return; -+ } -+ } -+ spin_unlock_irqrestore (&dev->dev_intop_lock, flags); -+ -+ panic ("device_interrupt: interrupt cookie %llx not found\n", cookie); -+} -+ -+static void -+device_iproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ ELAN4_IPROC_TRAP *trap = &dev->dev_iproc_trap; -+ -+ elan4_extract_iproc_trap (dev, status, trap, unit); -+ elan4_inspect_iproc_trap (trap); -+ -+ DBGCMD (ctxt, DBG_IPROC, elan4_display_iproc_trap (ctxt, DBG_IPROC, "device_iproc_trap", trap)); -+ -+ if (elan4_neterr_iproc_trap (dev, trap)) -+ return; -+ -+ elan4_display_iproc_trap (DBG_CONSOLE, DBG_TRAP, "device_iproc_trap", trap); -+ panic ("device_iproc_trap: unexpected trap\n"); -+} -+ -+ELAN4_TRAP_OPS device_trap_ops = -+{ -+ NULL, -+ device_cproc_trap, -+ device_dproc_trap, -+ device_tproc_trap, -+ device_iproc_trap, -+ device_interrupt, -+}; -+ -+/* -+ * elan4_initialise_device -+ * initialise the ELAN4_DEV struct - spinlocks,cvs etc. -+ * map the registers, sdram etc -+ */ -+int -+elan4_initialise_device (ELAN4_DEV *dev) -+{ -+ int i, bit; -+ -+ if (elan4_mainint_resched_ticks == 0) -+ elan4_mainint_resched_ticks = (hz/4); -+ -+ /* map the registers */ -+ switch (dev->dev_devinfo.dev_revision_id) -+ { -+ case PCI_REVISION_ID_ELAN4_REVA: -+ dev->dev_regs = elan4_map_device (dev, ELAN4_BAR_REGISTERS, ELAN4_REVA_REG_OFFSET, ELAN4_REG_SIZE, &dev->dev_regs_handle); -+ -+ dev->dev_rom = elan4_map_device (dev, ELAN4_BAR_REGISTERS, ELAN4_REVA_EBUS_OFFSET + ELAN4_REVA_EBUS_ROM_OFFSET, -+ ELAN4_REVA_EBUS_ROM_SIZE, &dev->dev_rom_handle); -+ break; -+ -+ case PCI_REVISION_ID_ELAN4_REVB: -+ dev->dev_regs = elan4_map_device (dev, ELAN4_BAR_REGISTERS, ELAN4_REVB_REG_OFFSET, ELAN4_REG_SIZE, &dev->dev_regs_handle); -+ dev->dev_rom = (ioaddr_t) 0; -+ dev->dev_i2c = elan4_map_device (dev, ELAN4_BAR_REGISTERS, ELAN4_REVB_I2C_OFFSET, ELAN4_REVB_I2C_SIZE, &dev->dev_i2c_handle); -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ /* XXXX: parse the ebus rom to determine the sdram configuration */ -+ { -+ extern long long sdram_cfg; -+ -+ if (sdram_cfg == 0) -+ dev->dev_sdram_cfg = SDRAM_STARTUP_VALUE; -+ else -+ dev->dev_sdram_cfg = sdram_cfg; -+ } -+ -+ for (bit = 0; ((1 << bit) & elan4_resource_len (dev, ELAN4_BAR_SDRAM)) == 0; bit++) -+ ; -+ -+ switch ((dev->dev_sdram_cfg >> SDRAM_RamSize_SH) & 3) -+ { -+ case 0: /* 64Mbit, 128Mbit, 256Mbit, 512Mbit or 1Gbit (16-bit output) */ -+ dev->dev_sdram_numbanks = 4; bit -= 2; -+ for (i = 0; i < dev->dev_sdram_numbanks; i++) -+ { -+ dev->dev_sdram_banks[i].b_base = (i << bit); -+ dev->dev_sdram_banks[i].b_size = (1 << bit); -+ } -+ break; -+ -+ case 1: /* 64Mbit, 128Mbit, 256Mbit or 512Mbit (8-bit output) */ -+ dev->dev_sdram_numbanks = 4; bit -= 2; -+ for (i = 0; i < dev->dev_sdram_numbanks; i++) -+ { -+ dev->dev_sdram_banks[i].b_base = ((i & 2) << (bit)) | ((i & 1) << (bit-1)); -+ dev->dev_sdram_banks[i].b_size = (1 << bit); -+ } -+ break; -+ -+ case 2: /* 2Gbit (16-bit output) or 1Gbit (8-bit output) */ -+ dev->dev_sdram_numbanks = 2; bit--; -+ for (i = 0; i < dev->dev_sdram_numbanks; i++) -+ { -+ dev->dev_sdram_banks[i].b_base = (i << bit); -+ dev->dev_sdram_banks[i].b_size = (1 << bit); -+ } -+ break; -+ -+ case 3: /* 4Gbit (16-bit output) or 2Gbit (8-bit output) */ -+ dev->dev_sdram_numbanks = 1; -+ dev->dev_sdram_banks[0].b_base = 0; -+ dev->dev_sdram_banks[0].b_size = (1 << bit); -+ break; -+ } -+ -+ elan4_sdram_init (dev); -+ -+ /* initialise locks for classes of interrupts */ -+ spin_lock_init (&dev->dev_trap_lock); -+ spin_lock_init (&dev->dev_intop_lock); -+ spin_lock_init (&dev->dev_haltop_lock); -+ spin_lock_init (&dev->dev_mainint_lock); -+ -+ /* initialise other locks */ -+ spin_lock_init (&dev->dev_i2c_lock); -+ -+ spin_lock_init (&dev->dev_mmulock); -+ spin_lock_init (&dev->dev_cqlock); -+ spin_lock_init (&dev->dev_ctxlock); -+ -+ spin_lock_init (&dev->dev_intmask_lock); -+ spin_lock_init (&dev->dev_syscontrol_lock); -+ -+ spin_lock_init (&dev->dev_ctxt_lock); -+ spin_lock_init (&dev->dev_flush_lock); -+ spin_lock_init (&dev->dev_requeue_lock); -+ -+ kmutex_init (&dev->dev_lock); -+ -+ kcondvar_init (&dev->dev_mainint_wait); -+ kcondvar_init (&dev->dev_flush_wait); -+ -+ /* initialsie lists */ -+ INIT_LIST_HEAD (&dev->dev_ctxt_list); -+ INIT_LIST_HEAD (&dev->dev_intop_list); -+ INIT_LIST_HEAD (&dev->dev_interruptq_list); -+ INIT_LIST_HEAD (&dev->dev_hc_list); -+ INIT_LIST_HEAD (&dev->dev_haltop_list); -+ INIT_LIST_HEAD (&dev->dev_dma_flushop[0].list); -+ INIT_LIST_HEAD (&dev->dev_dma_flushop[1].list); -+ -+ dev->dev_state = ELAN4_STATE_STOPPED; -+ -+ return (0); -+} -+ -+void -+elan4_finalise_device (ELAN4_DEV *dev) -+{ -+ kcondvar_destroy (&dev->dev_flush_wait); -+ kcondvar_destroy (&dev->dev_mainint_wait); -+ -+ kmutex_destroy (&dev->dev_lock); -+ -+ spin_lock_destroy (&dev->dev_requeue_lock); -+ spin_lock_destroy (&dev->dev_flush_lock); -+ spin_lock_destroy (&dev->dev_ctxt_lock); -+ -+ spin_lock_destroy (&dev->dev_syscontrol_lock); -+ spin_lock_destroy (&dev->dev_intmask_lock); -+ -+ spin_lock_destroy (&dev->dev_ctxlock); -+ spin_lock_destroy (&dev->dev_cqlock); -+ spin_lock_destroy (&dev->dev_mmulock); -+ -+ spin_lock_destroy (&dev->dev_i2c_lock); -+ -+ spin_lock_destroy (&dev->dev_mainint_lock); -+ spin_lock_destroy (&dev->dev_haltop_lock); -+ spin_lock_destroy (&dev->dev_intop_lock); -+ spin_lock_destroy (&dev->dev_trap_lock); -+ -+ while (! list_empty (&dev->dev_hc_list)) -+ { -+ ELAN4_HASH_CHUNK *hc = list_entry (dev->dev_hc_list.next, ELAN4_HASH_CHUNK, hc_link); -+ -+ list_del (&hc->hc_link); -+ -+ KMEM_FREE(hc, sizeof (ELAN4_HASH_CHUNK)); -+ } -+ -+ elan4_sdram_fini (dev); -+ -+ switch (dev->dev_devinfo.dev_revision_id) -+ { -+ case PCI_REVISION_ID_ELAN4_REVA: -+ elan4_unmap_device (dev, dev->dev_rom, ELAN4_REVA_EBUS_ROM_SIZE, &dev->dev_rom_handle); -+ elan4_unmap_device (dev, dev->dev_regs, ELAN4_REG_SIZE, &dev->dev_regs_handle); -+ break; -+ case PCI_REVISION_ID_ELAN4_REVB: -+ elan4_unmap_device (dev, dev->dev_i2c, ELAN4_REVB_I2C_SIZE, &dev->dev_i2c_handle); -+ elan4_unmap_device (dev, dev->dev_regs, ELAN4_REG_SIZE, &dev->dev_regs_handle); -+ break; -+ } -+} -+ -+static void -+initialise_cache (ELAN4_DEV *dev) -+{ -+ register int set, line; -+ -+ /* Initialise the cache to "map" the bottom of sdram - we will use -+ * this space for cache flushing, so require the cache to be set -+ * up so that cachelines for this are in the correct set. -+ * -+ * XXXX: for MPSAS we set bit 28, to ensure that any access to -+ * sdram causes the line to be filled first to expunge any -+ * Xs. */ -+ for (set = 0; set < E4_NumCacheSets; set++) -+ for (line = 0; line < E4_NumCacheLines; line++) -+ write_tag (dev, Tags[set][line], (((E4_uint64) set) << 29) | (1 << 28) | (line << 16)); -+} -+ -+#ifndef CONFIG_MPSAS -+static void -+initialise_cache_tags (ELAN4_DEV *dev, unsigned addr) -+{ -+ register int set, line; -+ -+ /* Initialise the whole cache to hold sdram at "addr" as direct mapped */ -+ -+ for (set = 0; set < E4_NumCacheSets; set++) -+ for (line = 0; line < E4_NumCacheLines; line++) -+ write_tag (dev, Tags[set][line], addr | (set << 13) | (1 << 11)); -+} -+ -+static void -+initialise_ecc (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank) -+{ -+ register int i, addr; -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ { -+ initialise_cache_tags (dev, E4_CacheSize); -+ for (addr = 0; addr < bank->b_size; addr += E4_CacheSize) -+ { -+ for (i = 0; i < E4_CacheSize; i += sizeof (E4_uint64)) -+ writeq (0xbeec000000000000ull | addr | i, bank->b_ioaddr + addr + i); -+ initialise_cache_tags (dev, addr); -+ } -+ } -+ else -+ { -+ /* Write the whole of this bank of sdram. */ -+ for (addr = 0; addr < bank->b_size; addr += sizeof (E4_uint64)) -+ writeq (0xbeec000000000000ull | addr, bank->b_ioaddr + addr); -+ -+ /* Now flush out the top out of the cache */ -+ for (addr = 0; addr < E4_CacheSize; addr += sizeof (E4_uint64)) -+ writeq (0xbeec000000000000ull | addr, bank->b_ioaddr + addr); -+ -+ /* Now read the top value of sdram to guarantee the write has occured before the ecc is enabled */ -+ readq (bank->b_ioaddr + bank->b_size - sizeof (E4_uint64)); -+ } -+} -+#endif -+ -+#ifdef CONFIG_MPSAS -+static void -+do_initdma (ELAN4_DEV *dev) -+{ -+#define VIRTUAL_ADDRESS 0x10000000ull -+ ELAN4_CQ *cq = dev->dev_flush_cq[0]; -+ E4_uint64 value; -+ E4_uint32 intreg; -+ E4_uint64 status; -+ -+ PRINTF (DBG_DEVICE, DBG_CONFIG, "elan: performing initialising dma\n"); -+ -+ DISABLE_INT_MASK (dev, INT_Dma0Proc | INT_Dma1Proc); -+ -+ /* initialise the context filter */ -+ elan4_attach_filter (&dev->dev_ctxt, 0); -+ -+ /* now issue a DMA - we expect this to trap */ -+ writeq (E4_DMA_TYPE_SIZE (128*4, DMA_DataTypeByte, 0, 0) | RUN_DMA_CMD, cq->cq_mapping + (0 << 3)); -+ writeq (0, cq->cq_mapping + (1 << 3)); -+ writeq (0, cq->cq_mapping + (2 << 3)); -+ writeq (dev->dev_tproc_space, cq->cq_mapping + (3 << 3)); -+ writeq (dev->dev_tproc_space, cq->cq_mapping + (4 << 3)); -+ writeq (0, cq->cq_mapping + (5 << 3)); -+ writeq (0, cq->cq_mapping + (6 << 3)); -+ -+ /* spin waiting for it to trap - then restart the dma processor */ -+ do { -+ value = read_reg64 (dev, IntAndMaskReg); -+ intreg = (value >> E4_INTERRUPT_REG_SHIFT); -+ } while ((intreg & (INT_Dma0Proc | INT_Dma1Proc)) == 0); -+ -+ /* check it trapped for the right reason */ -+ status = (intreg & INT_Dma0Proc) ? read_reg64 (dev, DProc0Status) : read_reg64 (dev, DProc1Status); -+ -+ if (DPROC_PrefetcherFault (status) || (DPROC_TrapType(status) != DmaProcFailCountError && DPROC_TrapType(status) != DmaProcPacketAckError)) -+ { -+ printk ("elan: bad dma trap, status = %lx\n", (long)status); -+ panic ("elan: bad dma trap\n"); -+ } -+ -+ PULSE_SCHED_RESTART (dev, SCH_RestartDma0Proc | SCH_RestartDma1Proc | SCH_RestartDmaPrefetchProc); -+ -+ elan4_detach _filter (&dev->dev_ctxt, 0); -+ -+ ENABLE_INT_MASK (dev, INT_Dma0Proc | INT_Dma1Proc); -+#undef VIRTUAL_ADDRESS -+} -+#endif -+ -+static int -+ebus_read_vpd (ELAN4_DEV *dev, unsigned char *data, unsigned int nob) -+{ -+ unsigned int pci_data_ptr; -+ unsigned int vpd_ptr; -+ register int i; -+ -+ if (read_ebus_rom (dev, 0) != 0x55 || read_ebus_rom (dev, 1) != 0xaa) -+ { -+ printk ("elan%d: invalid rom signature in ebus rom\n", dev->dev_instance); -+ return -EINVAL; -+ } -+ -+ pci_data_ptr = (read_ebus_rom (dev, 0x19) << 8) | read_ebus_rom (dev, 0x18); -+ -+ /* check the pci data structure */ -+ if (read_ebus_rom (dev, pci_data_ptr + 0) != 'P' || -+ read_ebus_rom (dev, pci_data_ptr + 1) != 'C' || -+ read_ebus_rom (dev, pci_data_ptr + 2) != 'I' || -+ read_ebus_rom (dev, pci_data_ptr + 3) != 'R') -+ { -+ printk ("elan%d: invalid pci data structure in ebus rom\n", dev->dev_instance); -+ return -EINVAL; -+ } -+ -+ /* extract the VPD pointer */ -+ vpd_ptr = (read_ebus_rom (dev, pci_data_ptr + 9) << 8) | read_ebus_rom (dev, pci_data_ptr + 8); -+ -+ if (vpd_ptr == 0) -+ { -+ printk ("elan%d: no vital product data in ebus rom\n", dev->dev_instance); -+ return -EINVAL; -+ } -+ -+ /* read the vpd data */ -+ for (i = 0; i < nob; i++) -+ data[i] = read_ebus_rom (dev, vpd_ptr + i); -+ -+ return 0; -+} -+ -+int -+elan4_read_vpd (ELAN4_DEV *dev, unsigned char *tag, unsigned char *result) -+{ -+ unsigned char vpd[I2C_ELAN_EEPROM_VPD_SIZE]; -+ unsigned char *ptr = vpd; -+ unsigned int finished = 0; -+ unsigned char *lim; -+ unsigned char name[3]; -+ unsigned char value[256]; -+ unsigned char type; -+ unsigned int len, len2; -+ register int i; -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ { -+ if (ebus_read_vpd (dev, vpd, I2C_ELAN_EEPROM_VPD_SIZE) < 0) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, unable to read serial number from EBUS rom\n", dev->dev_instance); -+ return -EINVAL ; -+ } -+ } -+ else -+ { -+ if (i2c_read_rom (dev, I2C_ELAN_EEPROM_VPD_BASEADDR, I2C_ELAN_EEPROM_VPD_SIZE, vpd) < 0) -+ { -+ PRINTF1 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, unable to read serial number from I2C rom\n", dev->dev_instance); -+ return -EINVAL; -+ } -+ } -+ -+ result[0] = 0; -+ while (! finished) -+ { -+ type = *ptr++; -+ -+ if (type & LARGE_RESOURCE_BIT) -+ { -+ len = *(ptr++); -+ len += *(ptr++) << 8; -+ -+ switch (type & ~LARGE_RESOURCE_BIT) -+ { -+ case LARGE_RESOURCE_STRING: -+ case LARGE_RESOURCE_VENDOR_DEFINED: -+ ptr += len; -+ break; -+ -+ case LARGE_RESOURCE_VITAL_PRODUCT_DATA: -+ for (lim = ptr + len; ptr < lim; ) -+ { -+ name[0] = *ptr++; -+ name[1] = *ptr++; -+ name[2] = '\0'; -+ len2 = *ptr++; -+ -+ for (i = 0; i < len2 && ptr < lim; i++) -+ value[i] = *ptr++; -+ value[i] = '\0'; -+ -+ PRINTF3 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, %s: $s\n", dev->dev_instance, name, value); -+ -+ if (tag != NULL) -+ { /* looking for just one tag */ -+ if (!strcmp (name, tag)) -+ strcpy(result, value); -+ } -+ else -+ { /* get all tags */ -+ strcat(result,name); -+ strcat(result,": "); -+ strcat(result,value); -+ strcat(result,"\n"); -+ } -+ } -+ break; -+ -+ default: -+ PRINTF2 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, unknown large resource %x\n", dev->dev_instance, type); -+ finished = 1; -+ break; -+ } -+ } -+ else -+ { -+ len = type & 0x7; -+ -+ switch (type >> 3) -+ { -+ case SMALL_RESOURCE_COMPATIBLE_DEVICE_ID: -+ ptr += len; -+ break; -+ -+ case SMALL_RESOURCE_VENDOR_DEFINED: -+ ptr += len; -+ break; -+ -+ case SMALL_RESOURCE_END_TAG: -+ finished = 1; -+ break; -+ -+ default: -+ PRINTF2 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, unknown small resource %x\n", dev->dev_instance, type >> 3); -+ finished = 1; -+ break; -+ } -+ } -+ } -+ -+ if ( result[0] == 0 ) { -+ if ( tag != 0 ) -+ PRINTF2 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, failed to find tag %s\n", dev->dev_instance, tag); -+ else -+ PRINTF1 (DBG_DEVICE, DBG_CONFIG, "elan%d: elan4_read_vpd, failed to find any tags\n", dev->dev_instance); -+ return -EINVAL; -+ } -+ -+ return (0); -+} -+ -+int -+elan4_start_device (ELAN4_DEV *dev) -+{ -+ E4_VirtualProcessEntry entry; -+ unsigned pagesizeval[2]; -+ unsigned hashsizeval[2]; -+ register int i, j, tbl, res; -+ unsigned attempts = 0; -+ E4_PAGE_SIZE_TABLE; -+ unsigned char serial[256]; -+ -+ PRINTF (DBG_DEVICE, DBG_ALL, "elan4_start_device: entered\n"); -+ -+ dev->dev_state = ELAN4_STATE_STARTING; -+ -+ tryagain: -+ /* Initialise the pci config space */ -+ if ((res = elan4_pciinit (dev)) < 0) -+ return (res); -+ -+ /* Display the serial number */ -+ if (elan4_read_vpd (dev, "SN", serial)) -+ printk("elan%d: SN: failed to read\n", dev->dev_instance); -+ else -+ printk("elan%d: SN: %s\n", dev->dev_instance, serial); -+ -+ /* initialise the interrupt mask to zero */ -+ SET_INT_MASK (dev, 0); -+ -+ /* Initialise the device registers */ -+ write_reg64 (dev, TlbLineValue, 0); -+ write_reg64 (dev, SysControlReg, 0); -+ -+ /* Initialise the SDRAM using the configuration value from the ROM */ -+ write_reg64 (dev, SDRamConfigReg, dev->dev_sdram_cfg | SDRAM_SETUP); -+ -+ /* Setup the linkport registers */ -+ write_reg64 (dev, LinkPortLock, 0); -+ write_reg64 (dev, LinkPortKey, LINK_PORT_LOCK_VALUE); -+ -+ /* Setup the tick rates, start the clock, and init the stats registers */ -+ write_ureg32 (dev, ClockTickRate.s.TickRates, ELAN4_CLOCK_TICK_RATE); -+ write_ureg64 (dev, Clock, 0); -+ write_ureg32 (dev, InstCount.s.StatsCount, 0); -+ for (i = 0; i < 8; i++) -+ write_ureg32 (dev, StatCounts[i].s.StatsCount, 0); -+ -+ /* Initialise the Link Control register - disable the TLB prefetcher on RevB -+ * as it can cause very occasional data corruption. */ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVB) -+ write_reg32 (dev, LinkControlReg, LCONT_REVB_DISABLE_TLB_PREFETCH); -+ else -+ write_reg32 (dev, LinkControlReg, 0); -+ -+ /* Initialise the Link Control Settings to set the PLL Reference Value */ -+ write_reg32 (dev, LinkContSettings, -+ (elan4_mod45disable ? LCONT_MOD45_DISABLE : 0) | -+ (3 << LCONT_CONFIG_PHASE_SHIFT) | -+ ((elan4_pll_div & LCONT_PLL_REF_VAL_BITS_MASK) << LCONT_PLL_REF_VAL_BITS_SHIFT) | -+ (LCONT_VOD_360 << LCONT_LVDS_VOLTAGE_BITS_SHIFT) | -+ (LCONT_TERM_AUTO_OHM << LCONT_LVDS_TERMINATION_SHIFT)); -+ -+ /* Clear the link error LED on RevB and above */ -+ if (dev->dev_devinfo.dev_revision_id != PCI_REVISION_ID_ELAN4_REVA) -+ write_i2c (dev, I2cStatus, read_i2c (dev, I2cStatus) | I2cCntl_ClearLinkError); -+ -+ initialise_cache (dev); -+ -+ /* Initialise the MMU hash table parameters */ -+ /* Select the largest elan pagesize which is spanned by the -+ * system pagesize for mmu table 0*/ -+ for (i = 0; i < E4_PAGE_SIZE_TABLE_SIZE; i++) -+ if (PageSizeTable[i] > PAGE_SHIFT) -+ break; -+ -+ pagesizeval[0] = i - 1; -+ hashsizeval[0] = elan4_hash_0_size_val; -+ -+ /* Select a suitable elan pagesize to match any "large" page -+ * support that the OS provides. */ -+ pagesizeval[1] = PAGE_SIZE_4M; -+ hashsizeval[1] = elan4_hash_1_size_val; -+ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ { -+ dev->dev_pagesizeval[tbl] = pagesizeval[tbl]; -+ dev->dev_pageshift[tbl] = PageSizeTable[pagesizeval[tbl]]; -+ dev->dev_hashsize[tbl] = (1 << hashsizeval[tbl])/sizeof (E4_HashTableEntry); -+ dev->dev_rsvd_hashmask[tbl] = ((1 << (27 - dev->dev_pageshift[tbl]))-1) & ~((1 << hashsizeval[tbl])-1); -+ dev->dev_rsvd_hashval[tbl] = 0xFFFFFFFF; -+ } -+ -+ PRINTF2 (DBG_DEVICE, DBG_CONFIG, "elan4_start_device: pageshifts %d,%d\n", dev->dev_pageshift[0], -+ NUM_HASH_TABLES == 2 ? dev->dev_pageshift[1] : 0); -+ -+ /* Initialise the control register to the desired value */ -+ dev->dev_syscontrol = (CONT_EN_ALL_SETS | CONT_MMU_ENABLE | CONT_CACHE_ALL | CONT_2K_NOT_1K_DMA_PACKETS | -+ (pagesizeval[0] << CONT_TABLE0_PAGE_SIZE_SHIFT) | (hashsizeval[0] << CONT_TABLE0_MASK_SIZE_SHIFT)); -+ -+ if (NUM_HASH_TABLES == 2) -+ dev->dev_syscontrol |= CONT_TWO_HASH_TABLES | (pagesizeval[1] << CONT_TABLE1_PAGE_SIZE_SHIFT) | (hashsizeval[1] << CONT_TABLE1_MASK_SIZE_SHIFT); -+ -+ write_reg64 (dev, SysControlReg, dev->dev_syscontrol); -+ -+ /* use direct mapped pci writes during sdram initialisation, since for -+ * cache flushing to work, we need to ensure that the cacheflush page -+ * never gets lines into the incorrect cache set. */ -+ SET_SYSCONTROL (dev, dev_direct_map_pci_writes, CONT_DIRECT_MAP_PCI_WRITES); -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVB) -+ elan4_sdram_setup_delay_lines(dev); -+ -+ for (i = res = 0; i < dev->dev_sdram_numbanks; i++) -+ if (dev->dev_sdram_banks[i].b_size) -+ res |= elan4_sdram_init_bank (dev, &dev->dev_sdram_banks[i]); -+ -+ if (! res) -+ { -+ if (dev->dev_devinfo.dev_device_id == PCI_REVISION_ID_ELAN4_REVB && ++attempts < 5) -+ { -+ printk ("elan%d: sdram not working, resetting\n", dev->dev_instance); -+ goto tryagain; -+ } -+ -+ printk ("elan%d: could not find any sdram banks\n", dev->dev_instance); -+ goto failed; -+ } -+ -+#ifndef CONFIG_MPSAS -+ PRINTF0 (DBG_DEVICE, DBG_CONFIG, "elan4_start_device: initialising for ECC\n"); -+ -+ for (i = 0 ; i < dev->dev_sdram_numbanks; i++) -+ if (dev->dev_sdram_banks[i].b_ioaddr) -+ initialise_ecc (dev, &dev->dev_sdram_banks[i]); -+#endif -+ -+ dev->dev_sdram_initial_ecc_val = read_reg64 (dev, SDRamECCStatus); -+ -+ /* Now enable ECC after we've scrubbed the memory */ -+ write_reg64 (dev, SDRamConfigReg, dev->dev_sdram_cfg | SDRAM_ENABLE_ECC); -+ -+ /* clear any errors, and flush the tlb/route cache */ -+ PULSE_SYSCONTROL (dev, CONT_TLB_FLUSH | CONT_ROUTE_FLUSH | CONT_CLEAR_LINKPORT_INT | CONT_CLEAR_SDRAM_ERROR); -+ -+ write_ureg32 (dev, InstCount.s.StatsCount, 0); -+ -+ /* Initialise the thread processor's register file */ -+ for (i = 0; i < 64; i++) -+ write_reg64 (dev, TProcRegs[i], 0); -+ -+ /* Initialise the thread processor's ICache tags */ -+ for (i = 0; i < (E4_ICacheLines/E4_ICachePortSize); i++) -+ { -+ write_reg64 (dev, ICachePort_Cntl_Addr, i << E4_ICacheTagAddrShift); -+ for (j = 0; j < E4_ICachePortSize; j++) -+ write_reg64 (dev, ICachePort[j], E4_InvalidTagValue); -+ } -+ -+ /* -+ * Initialise the ICache with a sethi %hi(addr << 7), %r0 -+ * writing 8 64 bit values per loop of sethi %g0 values ending in 77 for something different?? -+ */ -+ for (i = 0; i < E4_ICacheSizeInBytes; i += (E4_ICachePortSize << 3)) -+ { -+ write_reg64 (dev, ICachePort_Cntl_Addr, E4_AccessICacheRams | (i >> 3)); -+ -+ for (j = 0; j < E4_ICachePortSize; j++) -+ write_reg64 (dev, ICachePort[j], -+ (E4_uint64) (((E4_uint64)i << (4+7)) + ((E4_uint64)j << (1+7)) + (0x077)) | -+ (E4_uint64) (((E4_uint64)i << (4+7+32)) + ((E4_uint64)j << (1+7+32)) + (0x0e7)) << 32); -+ } -+ -+ /* -+ * Initialise the top of the ICache Set0 with a instruction which will -+ * cause a know trap fingerprint so that the application can identify it -+ * and ignore the trap. -+ */ -+ write_reg64 (dev, ICachePort_Cntl_Addr, E4_ICacheFixupOffset | E4_AccessICacheRams); -+ for (i = 0; i < E4_ICachePortSize; i++) -+ write_reg64 (dev, ICachePort[i], E4_ICacheFixupInsn | (E4_ICacheFixupInsn << 32)); -+ -+ /* create the buddy allocator for SDRAM */ -+ for (i = 0; i < dev->dev_sdram_numbanks; i++) -+ if (dev->dev_sdram_banks[i].b_ioaddr) -+ elan4_sdram_add_bank (dev, &dev->dev_sdram_banks[i]); -+ -+ dev->dev_ctxtableshift = elan4_ctxt_table_shift; -+ dev->dev_cqcount = (1 << elan4_ln2_max_cqs); -+#ifdef CONFIG_MTRR -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVB) -+ dev->dev_cqreorder = dev->dev_cqcount >> 1; -+ else -+ dev->dev_cqreorder = dev->dev_cqcount; -+#endif -+ -+ /* allocate the sdram for cache flushing whilst still in direct mapped mode */ -+ dev->dev_cacheflush_space = elan4_sdram_alloc (dev, E4_CacheSize); -+ -+ /* and longer need direct mapped pci writes */ -+ CLEAR_SYSCONTROL (dev, dev_direct_map_pci_writes, CONT_DIRECT_MAP_PCI_WRITES); -+ -+ /* allocate the hash tables, command queues, context tables etc */ -+ PRINTF0 (DBG_DEVICE, DBG_CONFIG, "elan4_start_device: allocating hash tables, command queueus, context tables\n"); -+ -+ dev->dev_comqlowpri = elan4_sdram_alloc (dev, (1 << COMMAND_RUN_QUEUE_BITS)); -+ dev->dev_comqhighpri = elan4_sdram_alloc (dev, (1 << COMMAND_RUN_QUEUE_BITS)); -+ dev->dev_cqaddr = elan4_sdram_alloc (dev, sizeof (E4_CommandQueueDesc) * dev->dev_cqcount); -+ dev->dev_dmaqhighpri = elan4_sdram_alloc (dev, E4_QueueSize(elan4_dmaq_highpri_size)); -+ dev->dev_dmaqlowpri = elan4_sdram_alloc (dev, E4_QueueSize(elan4_dmaq_lowpri_size)); -+ dev->dev_threadqhighpri = elan4_sdram_alloc (dev, E4_QueueSize(elan4_threadq_highpri_size)); -+ dev->dev_threadqlowpri = elan4_sdram_alloc (dev, E4_QueueSize(elan4_threadq_lowpri_size)); -+ dev->dev_interruptq = elan4_sdram_alloc (dev, E4_QueueSize(elan4_interruptq_size)); -+ -+ dev->dev_ctxtable = elan4_sdram_alloc (dev, (1 << dev->dev_ctxtableshift) * sizeof (E4_ContextControlBlock)); -+ dev->dev_faultarea = elan4_sdram_alloc (dev, CUN_Entries * sizeof (E4_FaultSave)); -+ dev->dev_inputtraparea = elan4_sdram_alloc (dev, sizeof (E4_IprocTrapState)); -+ -+ dev->dev_sdrampages[0] = elan4_sdram_alloc (dev, SDRAM_PAGE_SIZE); -+ dev->dev_sdrampages[1] = elan4_sdram_alloc (dev, SDRAM_PAGE_SIZE); -+ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ { -+ dev->dev_hashtable[tbl] = elan4_sdram_alloc (dev, dev->dev_hashsize[tbl] * sizeof (E4_HashTableEntry)); -+#ifndef CONFIG_MPSAS -+ /* Initialise hash tables to invalid (zero) */ -+ elan4_sdram_zeroq_sdram (dev, dev->dev_hashtable[tbl], dev->dev_hashsize[tbl] * sizeof (E4_HashTableEntry)); -+#endif -+ } -+ -+ /* Initialise all context filters to discard */ -+#ifdef CONFIG_MPSAS -+ if (sas_memset_dev (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM, dev->dev_ctxtable, -+ E4_FILTER_DISCARD_ALL, (1 << (dev->dev_ctxtableshift-1))) < 0) -+ { -+ for (i = 0; i < (1 << dev->dev_ctxtableshift); i++) -+ elan4_write_filter (dev, i, E4_FILTER_DISCARD_ALL); -+ } -+#else -+ for (i = 0; i < (1 << dev->dev_ctxtableshift); i++) -+ elan4_write_filter (dev, i, E4_FILTER_DISCARD_ALL); -+#endif -+ -+ PRINTF4 (DBG_DEVICE, DBG_CONFIG, "elan4_start_device: hashtables %x,%x, %x,%x\n", dev->dev_hashtable[0], -+ dev->dev_hashsize[0], dev->dev_hashtable[1], dev->dev_hashsize[1]); -+ -+ /* install the hash table pointers */ -+ PRINTF0 (DBG_DEVICE, DBG_CONFIG, "elan4_start_device: initialise registers with table addresses\n"); -+ write_reg64 (dev, MmuTableBasePtrs, (((E4_uint64) dev->dev_hashtable[0]) | ((E4_uint64) dev->dev_hashtable[1]) << 32)); -+ write_reg64 (dev, MmuFaultAndRootCntxPtr, (((E4_uint64) dev->dev_ctxtableshift) | -+ ((E4_uint64) dev->dev_ctxtable) | -+ ((E4_uint64) dev->dev_faultarea) << 32)); -+ write_reg64 (dev, InputTrapAndFilter, (((E4_uint64) dev->dev_ctxtableshift) | -+ ((E4_uint64) dev->dev_ctxtable) | -+ ((E4_uint64) dev->dev_inputtraparea) << 32)); -+ /* -+ * The run ptrs have this format: (Front << 32) | Back -+ * The base for both the front and back is uses the high bits of the back pointer. -+ * So writting just the base value is good enough. -+ */ -+ write_reg64 (dev, CommandLowPriRunPtrs, dev->dev_comqlowpri); -+ write_reg64 (dev, CommandHighPriRunPtrs, dev->dev_comqhighpri); -+ -+ /* Initialise the run queues */ -+ write_reg64 (dev, DProcHighPriPtrs, E4_QueueValue (dev->dev_dmaqhighpri, elan4_dmaq_highpri_size)); -+ write_reg64 (dev, DProcLowPriPtrs, E4_QueueValue (dev->dev_dmaqlowpri, elan4_dmaq_lowpri_size)); -+ write_reg64 (dev, TProcHighPriPtrs, E4_QueueValue (dev->dev_threadqhighpri, elan4_threadq_highpri_size)); -+ write_reg64 (dev, TProcLowPriPtrs, E4_QueueValue (dev->dev_threadqlowpri, elan4_threadq_lowpri_size)); -+ -+ /* Initialise the interrupt queue as "empty" - this is actually with one entry on it */ -+ write_reg64 (dev, MainIntQueuePtrs.Value, (((E4_uint64) E4_QueueFrontValue (dev->dev_interruptq, elan4_interruptq_size) << 32) | -+ ((E4_uint64) E4_QueueBackPointer(dev->dev_interruptq + E4_MainIntEntrySize)))); -+ -+ dev->dev_interruptq_nfptr = dev->dev_interruptq + E4_MainIntEntrySize; -+ -+ /* -+ * Flush the context filter before dropping the Discard all bits in the schedule status register. -+ * Also hit the SCH_RestartTProc to clear out X's from the trap state and -+ * hit the SCH_RestartDmaPrefetchProc to clear out X's from the prev register. -+ */ -+ PULSE_SCHED_RESTART (dev, SCH_ContextFilterFlush | SCH_RestartTProc | SCH_RestartDmaPrefetchProc); -+ -+ /* setup the schedule status register. */ -+ SET_SCHED_STATUS (dev, SCH_CProcTimeout6p2us | SCH_DProcTimeslice512us); -+ -+ /* -+ * Now initialise the inserter cache.s -+ * Bit 31 of the first word of the descriptor is a valid bit. This must be cleared. -+ * Bit 31 becomes a used bit in the descriptors in memory. -+ */ -+ for (i = 0; i < COMMAND_INSERTER_CACHE_ENTRIES; i++) -+ { -+ write_reg32 (dev, CommandControl.CommandQueueDescsBase, i); /* select a cache line */ -+ write_reg64 (dev, CommandCacheTestPort, 0); /* Mark it invalid */ -+ } -+ -+ /* Setup the pointer to the command descriptors */ -+ /* the table must be aligned on a CQ_CommandDescsAlignement boundary */ -+ /* since we've allocated a small table - we work out the offset of the */ -+ /* first entry in our table for mapping in the command ports later */ -+ dev->dev_cqoffset = (dev->dev_cqaddr & (CQ_CommandDescsAlignment-1)) / sizeof (E4_CommandQueueDesc); -+ -+ write_reg32 (dev, CommandControl.CommandQueueDescsBase, (dev->dev_cqaddr & ~(CQ_CommandDescsAlignment-1)) | COM_ENABLE_DEQUEUE); -+ -+ /* allocate the bitmaps for cq,ctxt allocation */ -+ KMEM_ZALLOC (dev->dev_cqamap, bitmap_t *, BT_BITOUL(dev->dev_cqcount/ELAN4_CQ_PER_CQA) * sizeof (bitmap_t), 1); -+ KMEM_ZALLOC (dev->dev_ctxmap, bitmap_t *, BT_BITOUL(1 << dev->dev_ctxtableshift) * sizeof (bitmap_t), 1); -+ -+ if (dev->dev_cqamap == NULL || dev->dev_ctxmap == NULL) -+ goto failed; -+ -+ /* Make every fourth context be invalid for ICache fixup. -+ * context 0 is also invalid - since it is used to indicate -+ * an invalid tag. */ -+ for (i = 0; i < (1 << dev->dev_ctxtableshift); i += 4) -+ BT_SET (dev->dev_ctxmap, i); -+ -+ /* initialise the halt operations */ -+ dev->dev_haltop_mask = 0; -+ dev->dev_haltop_active = 0; -+ -+ /* allocate the hash table shadow structures - and place all blocks on the free lists */ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ { -+ KMEM_ZALLOC (dev->dev_mmuhash[tbl], ELAN4_HASH_ENTRY *, dev->dev_hashsize[tbl] * sizeof (ELAN4_HASH_ENTRY), 1); -+ KMEM_ZALLOC (dev->dev_mmufree[tbl], ELAN4_HASH_ENTRY **, dev->dev_hashsize[tbl] * sizeof (ELAN4_HASH_ENTRY *), 1); -+ -+ if (dev->dev_mmuhash[tbl] == NULL || dev->dev_mmufree[tbl] == NULL) -+ goto failed; -+ -+ for (i = 0; i < dev->dev_hashsize[tbl]; i++) -+ { -+ dev->dev_mmuhash[tbl][i].he_entry = dev->dev_hashtable[tbl] + (i * sizeof (E4_HashTableEntry)); -+ dev->dev_mmufree[tbl][i] = &dev->dev_mmuhash[tbl][i]; -+ } -+ } -+ -+ /* setup the interrupt mask register */ -+ SET_INT_MASK (dev, (INT_MSI0 | INT_MSI1 | INT_MSI2 | INT_MSI3) & ~(INT_Discarding | INT_Halted)); -+ -+ /* start a thread to handle excessive main interrupts */ -+ if (kernel_thread_create (elan4_mainint_thread, (caddr_t) dev) == NULL) -+ goto failed; -+ dev->dev_mainint_started = 1; -+ -+ /* install the device context - and allocate the first 16 command queues */ -+ if (elan4_insertctxt (dev, &dev->dev_ctxt, &device_trap_ops) != 0) -+ goto failed; -+ -+ /* Allocate command queues, one for each entry in the inserter cache, -+ * we'll use these queues to flush the insert cache */ -+ for (i = 0; i < COMMAND_INSERTER_CACHE_ENTRIES; i++) -+ { -+ if ((dev->dev_flush_cq[i] = elan4_alloccq (&dev->dev_ctxt, CQ_Size1K, CQ_DmaStartEnableBit | CQ_InterruptEnableBit, -+ CQ_Priority)) == NULL) -+ goto failed; -+ -+ ASSERT (elan4_cq2num(dev->dev_flush_cq[i]) == i); -+ -+ dev->dev_flush_finished |= (1 << i); -+ } -+ -+ /* Allocate command queues for dma halt operations */ -+ if ((dev->dev_dma_flushop[0].cq = elan4_alloccq (&dev->dev_ctxt, CQ_Size1K, CQ_DmaStartEnableBit, 0)) == NULL || -+ (dev->dev_dma_flushop[1].cq = elan4_alloccq (&dev->dev_ctxt, CQ_Size1K, CQ_DmaStartEnableBit, CQ_Priority)) == NULL) -+ goto failed; -+ -+#ifdef CONFIG_MPSAS -+ elan4_sdram_flushcache (dev, 0, E4_CacheSize); -+#endif -+ -+ /* initialise halt operation for flushing the icache */ -+ dev->dev_iflush_haltop.op_function = device_iflush_haltop; -+ dev->dev_iflush_haltop.op_arg = dev; -+ dev->dev_iflush_haltop.op_mask = INT_TProcHalted; -+ -+ /* Allocate a route table, and create a valid route for vp==0, this is used -+ * when a DMA is removed from the dma run queue */ -+ if ((dev->dev_routetable = elan4_alloc_routetable (dev, 0)) == NULL) -+ goto failed; -+ -+ elan4_set_routetable (&dev->dev_ctxt, dev->dev_routetable); -+ -+ entry.Values[0] = FIRST_MYLINK; -+ entry.Values[1] = 0; -+ -+ elan4_write_route (dev, dev->dev_routetable, 0, &entry); -+ -+ /* map the sdram pages into the elan */ -+ dev->dev_tproc_suspend = DEVICE_TPROC_SUSPEND_ADDR; -+ dev->dev_tproc_space = DEVICE_TPROC_SPACE_ADDR; -+ -+ elan4mmu_pteload (&dev->dev_ctxt, 0, dev->dev_tproc_suspend, (dev->dev_sdrampages[0] >> PTE_PADDR_SHIFT) | PTE_SetPerm(PERM_LocExecute)); -+ elan4mmu_pteload (&dev->dev_ctxt, 0, dev->dev_tproc_space, (dev->dev_sdrampages[1] >> PTE_PADDR_SHIFT) | PTE_SetPerm(PERM_LocDataWrite)); -+ -+ /* and store the thread suspend sequence in it for use when a thread is removed from the run queue */ -+ elan4_sdram_writel (dev, dev->dev_sdrampages[0], DEVICE_TPROC_SUSPEND_INSTR); -+ -+#ifdef CONFIG_MPSAS -+ do_initdma (dev); -+#endif -+ -+ if (!elan4_neterr_init (dev)) -+ goto failed; -+ -+ elan4_configure_mtrr (dev); -+ -+ /* finally register the device with elanmod for rms */ -+ dev->dev_idx = elan_dev_register (&dev->dev_devinfo, &elan4_dev_ops, (void *) dev); -+ -+ dev->dev_state = ELAN4_STATE_STARTED; -+ -+ return (0); -+ -+ failed: -+ printk ("elan%d: failed to start elan4 device - stopping\n", dev->dev_instance); -+ -+ elan4_stop_device (dev); -+ return (-ENOMEM); -+} -+ -+void -+elan4_stop_device (ELAN4_DEV *dev) -+{ -+ unsigned long flags; -+ int i, tbl; -+ -+ dev->dev_state = ELAN4_STATE_STOPPING; -+ -+ elan_dev_deregister (&dev->dev_devinfo); -+ -+ elan4_unconfigure_mtrr (dev); -+ -+ elan4_neterr_destroy (dev); -+ -+ if (dev->dev_tproc_suspend) -+ elan4mmu_unload_range (&dev->dev_ctxt, 0, dev->dev_tproc_suspend, 1 << dev->dev_pageshift[0]); -+ -+ if (dev->dev_tproc_space) -+ elan4mmu_unload_range (&dev->dev_ctxt, 0, dev->dev_tproc_space, 1 << dev->dev_pageshift[0]); -+ -+ if (dev->dev_routetable) -+ { -+ elan4_set_routetable (&dev->dev_ctxt, NULL); -+ elan4_free_routetable (dev, dev->dev_routetable); -+ } -+ -+ for (i = 0; i < 2; i++) -+ if (dev->dev_dma_flushop[i].cq) -+ elan4_freecq (&dev->dev_ctxt, dev->dev_dma_flushop[i].cq); -+ -+ /* free of the device context - and insert cache flushing command queues */ -+ for (i = 0; i < COMMAND_INSERTER_CACHE_ENTRIES; i++) -+ if (dev->dev_flush_cq[i]) -+ elan4_freecq (&dev->dev_ctxt, dev->dev_flush_cq[i]); -+ -+ if (dev->dev_ctxt.ctxt_dev) -+ elan4_removectxt (dev, &dev->dev_ctxt); -+ -+ /* stop the mainint thread */ -+ spin_lock_irqsave (&dev->dev_mainint_lock, flags); -+ dev->dev_stop_threads = 1; -+ -+ while (dev->dev_mainint_started && !dev->dev_mainint_stopped) -+ { -+ kcondvar_wakeupall (&dev->dev_mainint_wait, &dev->dev_mainint_lock); -+ kcondvar_wait (&dev->dev_mainint_wait, &dev->dev_mainint_lock, &flags); -+ } -+ dev->dev_mainint_started = dev->dev_mainint_stopped = 0; -+ spin_unlock_irqrestore (&dev->dev_mainint_lock, flags); -+ -+ /* cancel any error interrupt timeouts */ -+ if (timer_fn_queued (&dev->dev_error_timeoutid)) -+ cancel_timer_fn (&dev->dev_error_timeoutid); -+ -+ if (dev->dev_devinfo.dev_revision_id != PCI_REVISION_ID_ELAN4_REVA && timer_fn_queued (&dev->dev_linkerr_timeoutid)) -+ cancel_timer_fn (&dev->dev_linkerr_timeoutid); -+ -+ /* reset the interrupt mask register to zero */ -+ if (dev->dev_regs) -+ SET_INT_MASK (dev, 0); -+ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ { -+ if (dev->dev_mmuhash[tbl]) -+ KMEM_FREE (dev->dev_mmuhash[tbl], dev->dev_hashsize[tbl] * sizeof (ELAN4_HASH_ENTRY)); -+ if (dev->dev_mmufree[tbl]) -+ KMEM_FREE (dev->dev_mmufree[tbl], dev->dev_hashsize[tbl] * sizeof (ELAN4_HASH_ENTRY *)); -+ if (dev->dev_hashtable[tbl]) -+ elan4_sdram_free (dev, dev->dev_hashtable[tbl], dev->dev_hashsize[tbl] * sizeof (E4_HashTableEntry)); -+ } -+ -+ if (dev->dev_cqamap) -+ KMEM_FREE (dev->dev_cqamap, BT_BITOUL (dev->dev_cqcount/ELAN4_CQ_PER_CQA) * sizeof (bitmap_t)); -+ if (dev->dev_ctxmap) -+ KMEM_FREE (dev->dev_ctxmap, BT_BITOUL(1 << dev->dev_ctxtableshift) * sizeof (bitmap_t)); -+ -+ if (dev->dev_comqlowpri) -+ elan4_sdram_free (dev, dev->dev_comqlowpri, (1 << COMMAND_RUN_QUEUE_BITS)); -+ if (dev->dev_comqhighpri) -+ elan4_sdram_free (dev, dev->dev_comqhighpri, (1 << COMMAND_RUN_QUEUE_BITS)); -+ if (dev->dev_cqaddr) -+ elan4_sdram_free (dev, dev->dev_cqaddr, sizeof (E4_CommandQueueDesc) * dev->dev_cqcount); -+ if (dev->dev_dmaqhighpri) -+ elan4_sdram_free (dev, dev->dev_dmaqhighpri, E4_QueueSize(elan4_dmaq_highpri_size)); -+ if (dev->dev_dmaqlowpri) -+ elan4_sdram_free (dev, dev->dev_dmaqlowpri, E4_QueueSize(elan4_dmaq_lowpri_size)); -+ if (dev->dev_threadqhighpri) -+ elan4_sdram_free (dev, dev->dev_threadqhighpri, E4_QueueSize(elan4_threadq_highpri_size)); -+ if (dev->dev_threadqlowpri) -+ elan4_sdram_free (dev, dev->dev_threadqlowpri, E4_QueueSize(elan4_threadq_lowpri_size)); -+ if (dev->dev_interruptq) -+ elan4_sdram_free (dev, dev->dev_interruptq, E4_QueueSize(elan4_interruptq_size)); -+ -+ if (dev->dev_ctxtable) -+ elan4_sdram_free (dev, dev->dev_ctxtable, (1 << dev->dev_ctxtableshift) * sizeof (E4_ContextControlBlock)); -+ if (dev->dev_faultarea) -+ elan4_sdram_free (dev, dev->dev_faultarea, CUN_Entries * sizeof (E4_FaultSave)); -+ if (dev->dev_inputtraparea) -+ elan4_sdram_free (dev, dev->dev_inputtraparea, sizeof (E4_IprocTrapState)); -+ -+ if (dev->dev_sdrampages[0]) -+ elan4_sdram_free (dev, dev->dev_sdrampages[0], SDRAM_PAGE_SIZE); -+ if (dev->dev_sdrampages[1]) -+ elan4_sdram_free (dev, dev->dev_sdrampages[1], SDRAM_PAGE_SIZE); -+ -+ for (i = 0; i < dev->dev_sdram_numbanks; i++) -+ if (dev->dev_sdram_banks[i].b_ioaddr) -+ elan4_sdram_fini_bank (dev, &dev->dev_sdram_banks[i]); -+ -+ elan4_pcifini (dev); -+ -+ dev->dev_state = ELAN4_STATE_STOPPED; -+ -+ if (dev->dev_ack_errors) -+ kfree(dev->dev_ack_errors); -+ if (dev->dev_dproc_timeout) -+ kfree(dev->dev_dproc_timeout); -+ if (dev->dev_cproc_timeout) -+ kfree(dev->dev_cproc_timeout); -+} -+ -+static __inline__ int -+compute_arity (int lvl, unsigned n, char *arity) -+{ -+ if (arity[lvl] == 0) -+ { -+ if (n <= 8) -+ arity[lvl] = n; -+ else -+ arity[lvl] = 4; -+ } -+ -+ return (arity[lvl]); -+} -+ -+int -+elan4_compute_position (ELAN_POSITION *pos, unsigned nodeid, unsigned numnodes, unsigned arityval) -+{ -+ int i, lvl, n; -+ char arity[ELAN_MAX_LEVELS]; -+ -+ if (nodeid >= numnodes) -+ return -EINVAL; -+ -+ for (i = 0; i < ELAN_MAX_LEVELS; i++, arityval >>= 4) -+ arity[i] = arityval & 7; -+ -+ for (lvl = 0, n = numnodes; n > compute_arity(lvl, n, arity) && lvl < ELAN_MAX_LEVELS; lvl++) -+ { -+ if ((n % arity[lvl]) != 0) -+ return -EINVAL; -+ -+ n /= arity[lvl]; -+ } -+ -+ if (arity[lvl] != n) -+ return -EINVAL; -+ -+ for (i = 0; i <= lvl; i++) -+ pos->pos_arity[i] = arity[lvl - i]; -+ -+ pos->pos_nodes = numnodes; -+ pos->pos_levels = lvl + 1; -+ pos->pos_nodeid = nodeid; -+ pos->pos_mode = ELAN_POS_MODE_SWITCHED; -+ -+ return 0; -+} -+ -+int -+elan4_get_position (ELAN4_DEV *dev, ELAN_POSITION *pos) -+{ -+ kmutex_lock (&dev->dev_lock); -+ *pos = dev->dev_position; -+ kmutex_unlock (&dev->dev_lock); -+ -+ return (pos->pos_mode); -+} -+ -+int -+elan4_set_position (ELAN4_DEV *dev, ELAN_POSITION *pos) -+{ -+ int forceLocal = 0; -+ int nnodes, i; -+ unsigned int *ack_errors; -+ unsigned int *dproc_timeout; -+ unsigned int *cproc_timeout; -+ -+ switch (pos->pos_mode) -+ { -+ case ELAN_POS_UNKNOWN: -+ break; -+ -+ case ELAN_POS_MODE_SWITCHED: -+ if (pos->pos_levels > ELAN_MAX_LEVELS) -+ return (-EINVAL); -+ -+ for (i = 0, nnodes = 1; i < pos->pos_levels; i++) -+ { -+ -+ if (pos->pos_arity[i] <= 0 || (i == 0 ? pos->pos_arity[i] > 8 : pos->pos_arity[i] >= 8)) /* allow an 8 way top-switch */ -+ return (-EINVAL); -+ -+ nnodes *= pos->pos_arity[i]; -+ } -+ -+ if (pos->pos_nodes > nnodes || pos->pos_nodeid >= pos->pos_nodes) -+ return (-EINVAL); -+ break; -+ -+ case ELAN_POS_MODE_LOOPBACK: -+ if (pos->pos_levels != 1 || pos->pos_nodes != 1 || pos->pos_nodeid != 0 || pos->pos_arity[0] != 1) -+ return (-EINVAL); -+ -+ forceLocal = 1; -+ break; -+ -+ case ELAN_POS_MODE_BACKTOBACK: -+ if (pos->pos_levels != 1 || pos->pos_nodes != 2 || pos->pos_nodeid >= 2 || pos->pos_arity[0] != 2) -+ return (-EINVAL); -+ -+ forceLocal = (pos->pos_nodeid == 0); -+ break; -+ -+ default: -+ return (-EINVAL); -+ } -+ -+ ack_errors = kmalloc(pos->pos_nodes * sizeof(unsigned int), GFP_KERNEL); -+ if (!ack_errors) -+ return (-EINVAL); -+ memset(ack_errors, 0, pos->pos_nodes * sizeof(unsigned int)); -+ dproc_timeout = kmalloc(pos->pos_nodes * sizeof(unsigned int), GFP_KERNEL); -+ if (!dproc_timeout) -+ { -+ kfree(ack_errors); -+ return (-EINVAL); -+ } -+ memset(dproc_timeout, 0, pos->pos_nodes * sizeof(unsigned int)); -+ cproc_timeout = kmalloc(pos->pos_nodes * sizeof(unsigned int), GFP_KERNEL); -+ if (!cproc_timeout) -+ { -+ kfree(ack_errors); -+ kfree(dproc_timeout); -+ return (-EINVAL); -+ } -+ memset(cproc_timeout, 0, pos->pos_nodes * sizeof(unsigned int)); -+ -+ kmutex_lock (&dev->dev_lock); -+ dev->dev_position = *pos; -+ dev->dev_ack_errors = ack_errors; -+ dev->dev_dproc_timeout = dproc_timeout; -+ dev->dev_cproc_timeout = cproc_timeout; -+ spin_lock_init(&dev->dev_error_routes_lock); -+ -+ if (forceLocal) -+ write_reg32 (dev, LinkContSettings, read_reg32 (dev, LinkContSettings) | LCONT_FORCE_COMMSCLK_LOCAL); -+ else -+ write_reg32 (dev, LinkContSettings, read_reg32 (dev, LinkContSettings) & ~LCONT_FORCE_COMMSCLK_LOCAL); -+ -+ pioflush_reg (dev); -+ kmutex_unlock (&dev->dev_lock); -+ -+ return (0); -+} -+ -+void -+elan4_get_params (ELAN4_DEV *dev, ELAN_PARAMS *params, unsigned short *mask) -+{ -+ kmutex_lock (&dev->dev_lock); -+ -+ *mask = dev->dev_devinfo.dev_params_mask; -+ memcpy (params, &dev->dev_devinfo.dev_params, sizeof (ELAN_PARAMS)); -+ -+ kmutex_unlock (&dev->dev_lock); -+} -+ -+void -+elan4_set_params (ELAN4_DEV *dev, ELAN_PARAMS *params, unsigned short mask) -+{ -+ int i; -+ -+ kmutex_lock (&dev->dev_lock); -+ for (i = 0; i < ELAN4_PARAM_COUNT; i++) -+ if (mask & (1 << i)) -+ dev->dev_devinfo.dev_params.values[i] = params->values[i]; -+ -+ dev->dev_devinfo.dev_params_mask |= mask; -+ kmutex_unlock (&dev->dev_lock); -+} -+ -+ -+EXPORT_SYMBOL(elan4_get_position); -+EXPORT_SYMBOL(elan4_set_position); -+ -+EXPORT_SYMBOL(elan4_queue_haltop); -+EXPORT_SYMBOL(elan4_queue_dma_flushop); -+EXPORT_SYMBOL(elan4_queue_mainintop); -+ -+EXPORT_SYMBOL(elan4_insertctxt); -+EXPORT_SYMBOL(elan4_removectxt); -+ -+EXPORT_SYMBOL(elan4_attach_filter); -+EXPORT_SYMBOL(elan4_detach_filter); -+EXPORT_SYMBOL(elan4_set_filter); -+EXPORT_SYMBOL(elan4_set_routetable); -+ -+EXPORT_SYMBOL(elan4_alloccq); -+EXPORT_SYMBOL(elan4_freecq); -+EXPORT_SYMBOL(elan4_restartcq); -+ -+EXPORT_SYMBOL(elan4_flush_icache); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/device_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/device_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/device_Linux.c 2005-06-01 23:12:54.606438040 -0400 -@@ -0,0 +1,2625 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: device_Linux.c,v 1.74.6.9 2005/01/18 14:44:11 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/device_Linux.c,v $*/ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#ifdef CONFIG_MTRR -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) -+typedef void irqreturn_t; -+#endif -+# define IRQ_NONE -+# define IRQ_HANDLED -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+#error please use a 2.4.0 series kernel or newer -+#endif -+ -+ -+#if defined(LINUX_SPARC) || defined(LINUX_PPC64) -+#define __io_remap_page_range(from,offset,size,prot) remap_page_range(from,offset,size,prot) -+#define __remap_page_range(from,offset,size,prot) remap_page_range(from,offset,size,prot) -+#elif defined(NO_RMAP) -+#define __io_remap_page_range(from,offset,size,prot) io_remap_page_range(from,offset,size,prot) -+#define __remap_page_range(from,offset,size,prot) remap_page_range(from,offset,size,prot) -+#else -+#define __io_remap_page_range(from,offset,size,prot) io_remap_page_range(vma,from,offset,size,prot) -+#define __remap_page_range(from,offset,size,prot) remap_page_range(vma,from,offset,size,prot) -+#endif -+ -+#ifndef pgprot_noncached -+static inline pgprot_t pgprot_noncached(pgprot_t _prot) -+{ -+ unsigned long prot = pgprot_val(_prot); -+#if defined(__powerpc__) -+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; -+#elif defined(__sparc__) -+ prot &= ~(_PAGE_CACHE); -+ prot |= _PAGE_IE; -+#endif -+ -+ return __pgprot(prot); -+} -+#endif -+ -+#ifndef pgprot_writecombine -+static inline pgprot_t pgprot_writecombine (pgprot_t _prot) -+{ -+ return _prot; -+} -+#endif -+ -+#define ELAN4_DRIVER_VERSION 0x103 /* 16 bit value */ -+ -+/* -+ * Function prototypes. -+ */ -+static int elan4_attach_device (int instance, struct pci_dev *pdev); -+static void elan4_detach_device (ELAN4_DEV *dev); -+ -+static int elan4_open (struct inode *inode, struct file *file); -+static int elan4_release(struct inode *inode, struct file *file); -+static int elan4_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg); -+static int elan4_mmap (struct file *file, struct vm_area_struct *vm_area); -+ -+static irqreturn_t elan4_irq (int irq, void *arg, struct pt_regs *regs); -+ -+static void elan4_shutdown_devices(int panicing); -+ -+static int disabled; /* bitmask of which devices not to start */ -+unsigned int elan4_pll_cfg = 0; -+int elan4_pll_div = 31; /* RevC PCB */ -+int elan4_mod45disable = 0; -+static int optimise_pci_bus = 1; /* 0 => don't, 1 => if ok, 2 => always */ -+static int default_features = 0; /* default values for dev_features */ -+ -+long long sdram_cfg = SDRAM_STARTUP_VALUE; -+static int sdram_cfg_lo; -+static int sdram_cfg_hi; -+int sdram_bank_limit; -+ -+MODULE_AUTHOR("Quadrics Ltd."); -+MODULE_DESCRIPTION("Elan 4 Device Driver"); -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(elan4_debug, "i"); -+MODULE_PARM(elan4_debug_toconsole, "i"); -+MODULE_PARM(elan4_debug_tobuffer, "i"); -+MODULE_PARM(elan4_debug_mmu, "i"); -+MODULE_PARM(elan4_pll_cfg, "i"); -+MODULE_PARM(elan4_pll_div, "i"); -+MODULE_PARM(elan4_mod45disable, "i"); -+MODULE_PARM(optimise_pci_bus, "i"); -+MODULE_PARM(default_features, "i"); -+ -+MODULE_PARM(disabled, "i"); -+MODULE_PARM(sdram_cfg_lo, "i"); -+MODULE_PARM(sdram_cfg_hi, "i"); -+MODULE_PARM(sdram_bank_limit, "i"); -+ -+MODULE_PARM(elan4_hash_0_size_val, "i"); -+MODULE_PARM(elan4_hash_1_size_val, "i"); -+MODULE_PARM(elan4_ctxt_table_shift, "i"); -+MODULE_PARM(elan4_ln2_max_cqs, "i"); -+MODULE_PARM(elan4_dmaq_highpri_size, "i"); -+MODULE_PARM(elan4_threadq_highpri_size, "i"); -+MODULE_PARM(elan4_dmaq_lowpri_size, "i"); -+MODULE_PARM(elan4_threadq_lowpri_size, "i"); -+MODULE_PARM(elan4_interruptq_size, "i"); -+ -+MODULE_PARM(elan4_mainint_punt_loops, "i"); -+MODULE_PARM(elan4_mainint_resched_ticks, "i"); -+ -+MODULE_PARM(user_p2p_route_options, "i"); -+MODULE_PARM(user_bcast_route_options, "i"); -+MODULE_PARM(user_dproc_retry_count, "i"); -+MODULE_PARM(user_cproc_retry_count, "i"); -+ -+/* -+ * Standard device entry points. -+ */ -+static struct file_operations elan4_fops = { -+ ioctl: elan4_ioctl, -+ mmap: elan4_mmap, -+ open: elan4_open, -+ release: elan4_release, -+}; -+ -+ELAN4_DEV *elan4_devices[ELAN4_MAX_CONTROLLER]; -+ -+#if defined(CONFIG_DEVFS_FS) -+static devfs_handle_t devfs_handle; -+#endif -+ -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+static int -+elan4_ioctl32_cmds[] = -+{ /* /dev/elan/control */ -+ ELAN4IO_DEVINFO, -+ ELAN4IO_GET_POSITION, -+ ELAN4IO_SET_POSITION, -+ ELAN4IO_GET_PARAMS, -+ ELAN4IO_SET_PARAMS, -+ -+ /* /dev/elan4/user */ -+ ELAN4IO_POSITION, -+ ELAN4IO_FREE, -+ ELAN4IO_ATTACH, -+ ELAN4IO_DETACH, -+ ELAN4IO_BLOCK_INPUTTER, -+ -+ ELAN4IO_ADD_P2PVP, -+ ELAN4IO_ADD_BCASTVP, -+ ELAN4IO_REMOVEVP, -+ ELAN4IO_SET_ROUTE, -+ ELAN4IO_RESET_ROUTE, -+ ELAN4IO_GET_ROUTE, -+ ELAN4IO_CHECK_ROUTE, -+ -+ ELAN4IO_ALLOCCQ, -+ ELAN4IO_FREECQ, -+ ELAN4IO_SETPERM32, -+ ELAN4IO_CLRPERM32, -+ ELAN4IO_TRAPSIG, -+ ELAN4IO_TRAPHANDLER32, -+ ELAN4IO_REQUIRED_MAPPINGS, -+ -+ ELAN4IO_RESUME_EPROC_TRAP, -+ ELAN4IO_RESUME_CPROC_TRAP, -+ ELAN4IO_RESUME_DPROC_TRAP, -+ ELAN4IO_RESUME_TPROC_TRAP, -+ ELAN4IO_RESUME_IPROC_TRAP, -+ -+ ELAN4IO_FLUSH_ICACHE, -+ -+ ELAN4IO_STOP_CTXT, -+ -+ ELAN4IO_ALLOC_INTCOOKIE, -+ ELAN4IO_FREE_INTCOOKIE, -+ ELAN4IO_ARM_INTCOOKIE, -+ ELAN4IO_WAIT_INTCOOKIE, -+ -+ ELAN4IO_ALLOC_TRAP_QUEUES, -+ ELAN4IO_NETERR_MSG, -+ ELAN4IO_NETERR_TIMER, -+ ELAN4IO_NETERR_FIXUP, -+ -+ ELAN4IO_DUMPCQ32, -+}; -+ -+static int elan4_ioctl32 (unsigned int fd, unsigned int cmd, -+ unsigned long arg, struct file *file); -+#endif -+ -+/* -+ * Standard device entry points. -+ */ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ -+#include -+ -+static int -+elan4_dump_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ if (event == DUMP_BEGIN) -+ elan4_shutdown_devices (FALSE); -+ -+ return (NOTIFY_DONE); -+} -+static struct notifier_block elan4_dump_notifier = -+{ -+ notifier_call: elan4_dump_event, -+ priority: 0, -+}; -+ -+#endif -+ -+static int -+elan4_reboot_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ if ((event == SYS_RESTART || event == SYS_HALT || event == SYS_POWER_OFF)) -+ elan4_shutdown_devices (0); -+ -+ return (NOTIFY_DONE); -+} -+ -+static struct notifier_block elan4_reboot_notifier = -+{ -+ notifier_call: elan4_reboot_event, -+ priority: 0, -+}; -+ -+static int -+elan4_panic_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ elan4_shutdown_devices (1); -+ -+ return (NOTIFY_DONE); -+} -+ -+static struct notifier_block elan4_panic_notifier = -+{ -+ notifier_call: elan4_panic_event, -+ priority: 0, -+}; -+ -+static int __init -+elan4_init (void) -+{ -+ int err; -+ struct pci_dev *pdev; -+ int count; -+#if defined(__ia64) -+ int seenRevA = 0; -+#endif -+ -+ if ((err = register_chrdev (ELAN4_MAJOR, ELAN4_NAME, &elan4_fops)) < 0) -+ return (err); -+ -+#if defined(CONFIG_DEVFS_FS) -+ devfs_handle = devfs_mk_dir (NULL, "elan4", NULL); -+#endif -+ -+ intcookie_init(); -+ elan4_debug_init(); -+ elan4_procfs_init(); -+ -+#ifdef CONFIG_MPSAS -+ sas_init(); -+#endif -+ -+ if (sdram_cfg_lo != 0 && sdram_cfg_hi != 0) -+ sdram_cfg = (((unsigned long long) sdram_cfg_hi) << 32) | ((unsigned long long) sdram_cfg_lo); -+ -+ for (count = 0, pdev = NULL; (pdev = pci_find_device(PCI_VENDOR_ID_QUADRICS, PCI_DEVICE_ID_ELAN4, pdev)) != NULL ; count++) -+ { -+#if defined(__ia64) -+ unsigned char revid; -+ -+ pci_read_config_byte (pdev, PCI_REVISION_ID, &revid); -+ -+ if (revid == PCI_REVISION_ID_ELAN4_REVA && seenRevA++ != 0 && pci_find_device (PCI_VENDOR_ID_HP, 0x122e, NULL)) -+ { -+ printk ("elan: only a single elan4a supported on rx2600\n"); -+ continue; -+ } -+#endif -+ -+ if (count < ELAN4_MAX_CONTROLLER) -+ elan4_attach_device (count, pdev); -+ } -+ -+ if (count >= ELAN4_MAX_CONTROLLER) -+ printk ("elan: found %d elan4 devices - only support %d\n", count, ELAN4_MAX_CONTROLLER); -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+ lock_kernel(); -+ { -+ extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); -+ register int i; -+ for (i = 0; i < sizeof (elan4_ioctl32_cmds)/sizeof(elan4_ioctl32_cmds[0]); i++) -+ register_ioctl32_conversion (elan4_ioctl32_cmds[i], elan4_ioctl32); -+ } -+ unlock_kernel(); -+#endif -+ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ register_dump_notifier (&elan4_dump_notifier); -+#endif -+ register_reboot_notifier (&elan4_reboot_notifier); -+ -+#if !defined(NO_PANIC_NOTIFIER) -+ notifier_chain_register (&panic_notifier_list, &elan4_panic_notifier); -+#endif -+ -+ return (0); -+} -+ -+#ifdef MODULE -+static void __exit -+elan4_exit (void) -+{ -+ int i; -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+ lock_kernel(); -+ { -+ extern void unregister_ioctl32_conversion(unsigned int cmd); -+ -+ for (i = 0; i < sizeof (elan4_ioctl32_cmds)/sizeof(elan4_ioctl32_cmds[0]); i++) -+ unregister_ioctl32_conversion (elan4_ioctl32_cmds[i]); -+ } -+ unlock_kernel(); -+#endif -+ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ unregister_dump_notifier (&elan4_dump_notifier); -+#endif -+ unregister_reboot_notifier (&elan4_reboot_notifier); -+ -+#if !defined(NO_PANIC_NOTIFIER) -+ notifier_chain_unregister (&panic_notifier_list, &elan4_panic_notifier); -+#endif -+ -+ for (i = 0; i < ELAN4_MAX_CONTROLLER; i++) -+ if (elan4_devices[i] != NULL) -+ elan4_detach_device (elan4_devices[i]); -+ -+ elan4_procfs_fini(); -+ elan4_debug_fini(); -+ intcookie_fini(); -+ -+#if defined(CONFIG_DEVFS_FS) -+ devfs_unregister (devfs_handle); -+#endif -+ -+ unregister_chrdev(ELAN4_MAJOR, ELAN4_NAME); -+} -+ -+module_init (elan4_init); -+module_exit (elan4_exit); -+ -+#else -+__initcall (elan4_init); -+#endif -+ -+/* -+ * Minor numbers encoded as : -+ * [5:0] device number -+ * [15:6] function number -+ */ -+#define ELAN4_DEVICE_MASK 0x3F -+#define ELAN4_DEVICE(inode) (MINOR((inode)->i_rdev) & ELAN4_DEVICE_MASK) -+ -+#define ELAN4_MINOR_CONTROL 0 -+#define ELAN4_MINOR_MEM 1 -+#define ELAN4_MINOR_USER 2 -+ -+#define ELAN4_MINOR_SHIFT 6 -+#define ELAN4_MINOR(inode) (MINOR((inode)->i_rdev) >> ELAN4_MINOR_SHIFT) -+ -+/* -+ * Called by init_module() for each card discovered on PCI. -+ */ -+static int -+elan4_attach_device (int instance, struct pci_dev *pdev) -+{ -+ ELAN4_DEV *dev; -+ int res; -+ -+ if ((dev = (ELAN4_DEV *) kmalloc (sizeof (ELAN4_DEV), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ memset (dev, 0, sizeof (ELAN4_DEV)); -+ -+ /* setup os dependent section of ELAN4_DEV */ -+ dev->dev_instance = instance; -+ dev->dev_osdep.pdev = pdev; -+ dev->dev_features = default_features; -+ -+ /* initialise the devinfo */ -+ pci_read_config_word (dev->dev_osdep.pdev, PCI_VENDOR_ID, &dev->dev_devinfo.dev_vendor_id); -+ pci_read_config_word (dev->dev_osdep.pdev, PCI_DEVICE_ID, &dev->dev_devinfo.dev_device_id); -+ pci_read_config_byte (dev->dev_osdep.pdev, PCI_REVISION_ID, &dev->dev_devinfo.dev_revision_id); -+ -+ dev->dev_devinfo.dev_rail = instance; -+ dev->dev_devinfo.dev_driver_version = ELAN4_DRIVER_VERSION; -+ dev->dev_devinfo.dev_num_down_links_value = 0; -+ -+ dev->dev_position.pos_mode = ELAN_POS_UNKNOWN; -+ -+ /* initialise the data structures and map the device */ -+ if ((res = elan4_initialise_device (dev)) != 0) -+ { -+ kfree (dev); -+ return res; -+ } -+ -+ /* add the interrupt handler */ -+ if (request_irq (pdev->irq, elan4_irq, SA_SHIRQ, "elan4", dev) != 0) -+ { -+ elan4_finalise_device (dev); -+ kfree (dev); -+ return -ENXIO; -+ } -+ -+ if (pci_request_regions(dev->dev_osdep.pdev, "elan4")) -+ { -+ free_irq (dev->dev_osdep.pdev->irq, dev); -+ kfree (dev); -+ return -ENODEV; -+ } -+ -+#if defined(CONFIG_DEVFS_FS) -+ { -+ char name[16]; -+ -+ sprintf (name, "control%d", dev->dev_instance); -+ dev->dev_osdep.devfs_control = devfs_register(devfs_handle, name, DEVFS_FL_NONE, ELAN4_MAJOR, -+ dev->dev_instance | (ELAN4_MINOR_CONTROL << ELAN4_MINOR_SHIFT), S_IFCHR | S_IRUSR | S_IWUSR, -+ &elan4_fops, NULL); -+ sprintf (name, "sdram%d", dev->dev_instance); -+ dev->dev_osdep.devfs_sdram = devfs_register(devfs_handle, name, DEVFS_FL_NONE, ELAN4_MAJOR, -+ dev->dev_instance | (ELAN4_MINOR_MEM << ELAN4_MINOR_SHIFT), S_IFCHR | S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH, -+ &elan4_fops, NULL); -+ sprintf (name, "user%d", dev->dev_instance); -+ dev->dev_osdep.devfs_user = devfs_register(devfs_handle, name, DEVFS_FL_NONE, ELAN4_MAJOR, -+ dev->dev_instance | (ELAN4_MINOR_USER << ELAN4_MINOR_SHIFT), S_IFCHR | S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH, -+ &elan4_fops, NULL); -+ } -+#endif -+ -+ /* add the procfs entry */ -+ elan4_procfs_device_init (dev); -+ -+ /* allow the device to be referenced now */ -+ elan4_devices[instance] = dev; -+ -+ if ((disabled & (1 << instance)) == 0) -+ { -+ if (elan4_start_device (dev) != 0) -+ { -+ printk ("elan%d: auto-start of device failed\n", dev->dev_instance); -+ -+ elan4_detach_device (dev); -+ return (-ENXIO); -+ } -+ -+ dev->dev_state = ELAN4_STATE_STARTED; -+ } -+ -+#if defined (__sparc) -+ printk ("elan%d: at pci %s (irq = %s)\n", instance, pdev->slot_name, __irq_itoa(pdev->irq)); -+#else -+ printk ("elan%d: at pci %s (irq = %d)\n", instance, pdev->slot_name, pdev->irq); -+#endif -+ -+ return (0); -+} -+ -+/* -+ * Called by cleanup_module() for each board found on PCI. -+ */ -+static void -+elan4_detach_device (ELAN4_DEV *dev) -+{ -+ /* stop the chip and free of resources */ -+ if (dev->dev_state == ELAN4_STATE_STARTED) -+ elan4_stop_device (dev); -+ -+ elan4_devices[dev->dev_instance] = NULL; -+ -+#if defined(CONFIG_DEVFS_FS) -+ devfs_unregister (dev->dev_osdep.devfs_control); -+ devfs_unregister (dev->dev_osdep.devfs_sdram); -+ devfs_unregister (dev->dev_osdep.devfs_user); -+#endif -+ -+ /* release the address space */ -+ pci_release_regions (dev->dev_osdep.pdev); -+ -+ /* release the interrupt */ -+ free_irq (dev->dev_osdep.pdev->irq, dev); -+ -+ /* remove the procfs entry */ -+ elan4_procfs_device_fini (dev); -+ -+ /* unmap the device and finalise the data structures */ -+ elan4_finalise_device (dev); -+ -+ kfree (dev); -+} -+ -+/* -+ * Maintain reference counts on the device -+ */ -+ELAN4_DEV * -+elan4_reference_device (int instance, int state) -+{ -+ ELAN4_DEV *dev = elan4_devices[instance]; -+ -+ if (dev == NULL) -+ return (NULL); -+ -+ kmutex_lock (&dev->dev_lock); -+ -+ if ((dev->dev_state & state) == 0) -+ { -+ kmutex_unlock (&dev->dev_lock); -+ return (NULL); -+ } -+ -+ dev->dev_references++; -+ kmutex_unlock (&dev->dev_lock); -+ -+#ifdef MODULE -+ MOD_INC_USE_COUNT; -+#endif -+ -+#ifdef CONFIG_MPSAS -+ sas_set_position(dev); -+#endif -+ -+ return (dev); -+} -+ -+void -+elan4_dereference_device (ELAN4_DEV *dev) -+{ -+ kmutex_lock (&dev->dev_lock); -+ dev->dev_references--; -+ kmutex_unlock (&dev->dev_lock); -+ -+#ifdef MODULE -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+static void -+elan4_shutdown_devices(int panicing) -+{ -+ ELAN4_DEV *dev; -+ unsigned long flags; -+ register int i; -+ -+ local_irq_save (flags); -+ for (i = 0; i < ELAN4_MAX_CONTROLLER; i++) -+ { -+ if ((dev = elan4_devices[i]) != NULL) -+ { -+ printk(KERN_INFO "elan%d: forcing link into reset\n", dev->dev_instance); -+ -+ /* set the inputters to discard everything */ -+ if (! panicing) spin_lock (&dev->dev_haltop_lock); -+ -+ if (dev->dev_discard_lowpri_count++ == 0) -+ elan4_set_schedstatus (dev, 0); -+ if (dev->dev_discard_highpri_count++ == 0) -+ elan4_set_schedstatus (dev, 0); -+ -+ if (! panicing) spin_unlock (&dev->dev_haltop_lock); -+ -+ /* ideally we'd like to halt all the outputters too, -+ * however this will prevent the kernel comms flushing -+ * to work correctly ..... -+ */ -+ } -+ } -+ local_irq_restore (flags); -+} -+ -+/* -+ * /dev/elan4/controlX - control device -+ * -+ */ -+static int -+control_open (struct inode *inode, struct file *file) -+{ -+ ELAN4_DEV *dev = elan4_reference_device (ELAN4_DEVICE(inode), ELAN4_STATE_STOPPED | ELAN4_STATE_STARTED); -+ CONTROL_PRIVATE *pr; -+ -+ if (dev == NULL) -+ return (-ENXIO); -+ -+ if ((pr = (CONTROL_PRIVATE *) kmalloc (sizeof (CONTROL_PRIVATE), GFP_KERNEL)) == NULL) -+ { -+ elan4_dereference_device (dev); -+ -+ return (-ENOMEM); -+ } -+ -+ PRINTF (DBG_USER, DBG_FILE, "control_open: dev=%p pr=%p\n", dev, pr); -+ -+ pr->pr_dev = dev; -+ pr->pr_boundary_scan = 0; -+ -+ file->private_data = (void *) pr; -+ -+ return (0); -+} -+ -+static int -+control_release (struct inode *inode, struct file *file) -+{ -+ CONTROL_PRIVATE *pr = (CONTROL_PRIVATE *) file->private_data; -+ ELAN4_DEV *dev = pr->pr_dev; -+ -+ PRINTF (DBG_DEVICE, DBG_FILE, "control_release: pr=%p\n", pr); -+ -+ //if (pr->pr_boundary_scan) -+ // elan4_clear_boundary_scan (dev, pr); -+ -+ elan4_dereference_device (dev); -+ -+ kfree (pr); -+ -+ return (0); -+} -+ -+static int -+control_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ CONTROL_PRIVATE *pr = (CONTROL_PRIVATE *) file->private_data; -+ -+ PRINTF (DBG_DEVICE, DBG_FILE, "control_ioctl: cmd=%x arg=%lx\n", cmd, arg); -+ -+ switch (cmd) -+ { -+ case ELAN4IO_DEVINFO: -+ if (copy_to_user ((void *) arg, &pr->pr_dev->dev_devinfo, sizeof (ELAN_DEVINFO))) -+ return (-EFAULT); -+ return (0); -+ -+ case ELAN4IO_GET_POSITION: -+ { -+ ELAN_POSITION pos; -+ -+ elan4_get_position (pr->pr_dev, &pos); -+ -+ if (copy_to_user ((void *) arg, &pos, sizeof (ELAN_POSITION))) -+ return (-EFAULT); -+ -+ return (0); -+ } -+ -+ case ELAN4IO_SET_POSITION: -+ { -+ ELAN_POSITION pos; -+ -+ if (copy_from_user (&pos, (void *) arg, sizeof (ELAN_POSITION))) -+ return (-EFAULT); -+ -+ return (elan4_set_position (pr->pr_dev, &pos)); -+ } -+ -+ case ELAN4IO_OLD_GET_PARAMS: -+ { -+ ELAN_PARAMS params; -+ unsigned short mask; -+ -+ elan4_get_params (pr->pr_dev, ¶ms, &mask); -+ -+ if (copy_to_user ((void *) arg, ¶ms, sizeof (ELAN_PARAMS))) -+ return (-EFAULT); -+ -+ return (0); -+ } -+ -+ case ELAN4IO_OLD_SET_PARAMS: -+ { -+ ELAN_PARAMS params; -+ -+ if (copy_from_user (¶ms, (void *) arg, sizeof (ELAN_PARAMS))) -+ return (-EFAULT); -+ -+ elan4_set_params (pr->pr_dev, ¶ms, 3); -+ -+ return (0); -+ } -+ -+ case ELAN4IO_SET_PARAMS: -+ { -+ ELAN4IO_PARAMS_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_PARAMS_STRUCT))) -+ return (-EFAULT); -+ -+ elan4_set_params (pr->pr_dev, &args.p_params, args.p_mask); -+ -+ return (0); -+ } -+ -+ case ELAN4IO_GET_PARAMS: -+ { -+ ELAN4IO_PARAMS_STRUCT args; -+ -+ elan4_get_params (pr->pr_dev, &args.p_params, &args.p_mask); -+ -+ if (copy_to_user ((void *) arg, &args, sizeof (ELAN_PARAMS))) -+ return (-EFAULT); -+ -+ return (0); -+ } -+ } -+ -+ return (-EINVAL); -+} -+ -+static int -+control_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ CONTROL_PRIVATE *pr = (CONTROL_PRIVATE *) file->private_data; -+ unsigned bar = OFF_TO_BAR (vma->vm_pgoff << PAGE_SHIFT); -+ unsigned long off = OFF_TO_OFFSET (vma->vm_pgoff << PAGE_SHIFT); -+ long len = vma->vm_end - vma->vm_start; -+ -+ PRINTF (DBG_USER, DBG_FILE, "control_mmap: pr=%p bar=%x off=%x\n", pr, bar, off); -+ -+ /* check bar number and translate the standard psuedo bars */ -+ switch (bar) -+ { -+ case ELAN4_BAR_SDRAM: -+ case ELAN4_BAR_REGISTERS: -+ break; -+ -+ default: -+ return (-EINVAL); -+ } -+ -+ if (off < 0 || (off + len) > pci_resource_len (pr->pr_dev->dev_osdep.pdev, bar)) -+ return (-EINVAL); -+ -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ if (__io_remap_page_range (vma->vm_start, pci_resource_start (pr->pr_dev->dev_osdep.pdev, bar) + off, len, vma->vm_page_prot)) -+ return (-EAGAIN); -+ -+ return (0); -+} -+ -+/* -+ * /dev/elan4/sdramX - sdram access device -+ */ -+static void -+mem_freepage (MEM_PRIVATE *pr, MEM_PAGE *pg) -+{ -+ PRINTF (DBG_USER, DBG_MEM, "mem_freepage: pr=%p pgoff=%lx pg=%p ref=%d\n", pr, pg->pg_pgoff, pg, pg->pg_ref); -+ -+ elan4_sdram_free (pr->pr_dev, pg->pg_addr, SDRAM_PAGE_SIZE); -+ kfree (pg); -+} -+ -+static MEM_PAGE * -+mem_getpage (MEM_PRIVATE *pr, unsigned long pgoff) -+{ -+ int hashval = MEM_HASH (pgoff); -+ MEM_PAGE *npg = NULL; -+ MEM_PAGE *pg; -+ -+ ASSERT ((pgoff & SDRAM_PGOFF_OFFSET) == 0); -+ -+ PRINTF (DBG_USER, DBG_MEM, "mem_getpage: pr=%p pgoff=%lx\n", pr, pgoff); -+ -+ again: -+ spin_lock (&pr->pr_lock); -+ for (pg = pr->pr_pages[hashval]; pg; pg = pg->pg_next) -+ if (pg->pg_pgoff == pgoff) -+ break; -+ -+ if (pg != NULL) -+ { -+ PRINTF (DBG_USER, DBG_MEM, "mem_getpage: pr=%p pgoff=%lx -> found %p addr=%x\n", pr, pgoff, pg, pg->pg_addr); -+ -+ pg->pg_ref++; -+ spin_unlock (&pr->pr_lock); -+ -+ if (npg != NULL) /* we'd raced and someone else had created */ -+ mem_freepage (pr, npg); /* this page - so free of our new one*/ -+ return (pg); -+ } -+ -+ if (npg != NULL) /* didn't find the page, so inset the */ -+ { /* new one we've just created */ -+ npg->pg_next = pr->pr_pages[hashval]; -+ pr->pr_pages[hashval] = npg; -+ -+ spin_unlock (&pr->pr_lock); -+ return (npg); -+ } -+ -+ spin_unlock (&pr->pr_lock); /* drop spinlock before creating a new page */ -+ -+ if ((npg = (MEM_PAGE *) kmalloc (sizeof (MEM_PAGE), GFP_KERNEL)) == NULL) -+ return (NULL); -+ -+ if ((npg->pg_addr = elan4_sdram_alloc (pr->pr_dev, SDRAM_PAGE_SIZE)) == 0) -+ { -+ kfree (npg); -+ return (NULL); -+ } -+ -+#ifndef CONFIG_MPSAS -+ /* zero the page before returning it to the user */ -+ elan4_sdram_zeroq_sdram (pr->pr_dev, npg->pg_addr, SDRAM_PAGE_SIZE); -+#endif -+ -+ npg->pg_pgoff = pgoff; -+ npg->pg_ref = 1; -+ -+ /* created a new page - so have to rescan before inserting it */ -+ goto again; -+} -+ -+static void -+mem_droppage (MEM_PRIVATE *pr, unsigned long pgoff, int dontfree) -+{ -+ MEM_PAGE **ppg; -+ MEM_PAGE *pg; -+ -+ spin_lock (&pr->pr_lock); -+ for (ppg = &pr->pr_pages[MEM_HASH(pgoff)]; *ppg; ppg = &(*ppg)->pg_next) -+ if ((*ppg)->pg_pgoff == pgoff) -+ break; -+ -+ pg = *ppg; -+ -+ ASSERT (*ppg != NULL); -+ -+ PRINTF (DBG_USER, DBG_MEM, "mem_droppage: pr=%p pgoff=%lx pg=%p ref=%d dontfree=%d\n", pr, pgoff, (*ppg), (*ppg)->pg_ref, dontfree); -+ -+ if (--pg->pg_ref == 0 && !dontfree) -+ { -+ *ppg = pg->pg_next; -+ -+ mem_freepage (pr, pg); -+ } -+ -+ spin_unlock (&pr->pr_lock); -+} -+ -+static int -+mem_open (struct inode *inode, struct file *file) -+{ -+ ELAN4_DEV *dev = elan4_reference_device (ELAN4_DEVICE(inode), ELAN4_STATE_STARTED); -+ MEM_PRIVATE *pr; -+ register int i; -+ -+ if (dev == NULL) -+ return (-ENXIO); -+ -+ if ((pr = (MEM_PRIVATE *) kmalloc (sizeof (MEM_PRIVATE), GFP_KERNEL)) == NULL) -+ { -+ elan4_dereference_device (dev); -+ return (-ENOMEM); -+ } -+ -+ spin_lock_init (&pr->pr_lock); -+ pr->pr_dev = dev; -+ for (i = 0; i < MEM_HASH_SIZE; i++) -+ pr->pr_pages[i] = NULL; -+ -+ file->private_data = (void *) pr; -+ -+ return (0); -+} -+ -+static int -+mem_release (struct inode *node, struct file *file) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) file->private_data; -+ MEM_PAGE *pg, *next; -+ int i; -+ -+ /* free off any pages that we'd allocated */ -+ spin_lock (&pr->pr_lock); -+ for (i = 0; i < MEM_HASH_SIZE; i++) -+ { -+ for (pg = pr->pr_pages[i]; pg; pg = next) -+ { -+ next = pg->pg_next; -+ mem_freepage (pr, pg); -+ } -+ } -+ spin_unlock (&pr->pr_lock); -+ -+ elan4_dereference_device (pr->pr_dev); -+ kfree (pr); -+ -+ return (0); -+} -+ -+static int -+mem_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return (-EINVAL); -+} -+ -+static void -+mem_vma_open (struct vm_area_struct *vma) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) vma->vm_private_data; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (DBG_USER, DBG_MEM, "mem_vma_open: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ mem_getpage (pr, pgoff & SDRAM_PGOFF_MASK); -+} -+ -+static void -+mem_vma_close (struct vm_area_struct *vma) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) vma->vm_private_data; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (DBG_USER, DBG_MEM, "mem_vma_close: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ /* NOTE: the call to close may not have the same vm_start/vm_end values as -+ * were passed into mmap()/open() - since if an partial unmap had occurred -+ * then the vma could have been shrunk or even split. -+ * -+ * if a the vma is split then an vma_open() will be called for the top -+ * portion - thus causing the reference counts to become incorrect. -+ * -+ * We drop the reference to any pages we're notified about - so they get freed -+ * earlier than when the device is finally released. -+ */ -+ for (pgoff = vma->vm_pgoff, addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ mem_droppage (pr, pgoff & SDRAM_PGOFF_MASK, 0); -+} -+ -+struct vm_operations_struct mem_vm_ops = { -+ open: mem_vma_open, -+ close: mem_vma_close, -+}; -+ -+static int -+mem_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ MEM_PRIVATE *pr = (MEM_PRIVATE *) file->private_data; -+ MEM_PAGE *pg; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (DBG_USER, DBG_MEM, "mem_mmap: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, file); -+ -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ { -+ if ((pg = mem_getpage (pr, pgoff & SDRAM_PGOFF_MASK)) == NULL) -+ goto failed; -+ -+ PRINTF (DBG_USER, DBG_MEM, "mem_mmap: addr %lx -> pg=%p sdram=%x+%x bar=%lx\n", -+ addr, pg, pg->pg_addr, (pgoff & SDRAM_PGOFF_OFFSET) * PAGE_SIZE, -+ pci_resource_start (pr->pr_dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ if (! (pr->pr_dev->dev_features & ELAN4_FEATURE_NO_WRITE_COMBINE)) -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ if (__io_remap_page_range (addr, pci_resource_start (pr->pr_dev->dev_osdep.pdev, ELAN4_BAR_SDRAM) + -+ pg->pg_addr + (pgoff & SDRAM_PGOFF_OFFSET) * PAGE_SIZE, PAGE_SIZE, vma->vm_page_prot)) -+ { -+ mem_droppage (pr, pgoff & SDRAM_PGOFF_MASK, 0); /* drop our reference to this page */ -+ goto failed; -+ } -+ -+#if defined(conditional_schedule) -+ conditional_schedule(); -+#endif -+ } -+ -+ /* Don't allow these pages to be swapped out of dumped */ -+ vma->vm_flags |= (VM_RESERVED | VM_IO); -+ -+ vma->vm_ops = &mem_vm_ops; -+ vma->vm_file = file; -+ vma->vm_private_data = (void *) pr; -+ -+ return (0); -+ -+ failed: -+ /* free of any pages we've already allocated/referenced */ -+ while (pgoff-- > vma->vm_pgoff) -+ mem_droppage (pr, pgoff & SDRAM_PGOFF_MASK, 0); -+ -+ return (-ENOMEM); -+} -+ -+/* -+ * /dev/elan4/userX - control device -+ * -+ */ -+static inline void -+user_private_free (USER_PRIVATE *pr) -+{ -+ ELAN4_DEV *dev = pr->pr_uctx->uctx_ctxt.ctxt_dev; -+ -+ ASSERT (atomic_read (&pr->pr_ref) == 0); -+ -+ user_free (pr->pr_uctx); -+ kfree (pr); -+ -+ elan4_dereference_device (dev); -+} -+ -+static void -+user_coproc_release (void *arg, struct mm_struct *mm) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_release: ref=%d\n", atomic_read (&pr->pr_ref)); -+ -+ elan4mmu_invalidate_ctxt (&pr->pr_uctx->uctx_ctxt); -+ -+ pr->pr_mm = NULL; -+ -+ if (atomic_dec_and_test (&pr->pr_ref)) -+ user_private_free (pr); -+} -+ -+static void -+user_coproc_sync_range (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_sync_range: start=%lx end=%lx\n", start, end); -+ -+ /* XXXX: this is intended to sync the modified bit from our page tables, -+ * into the main cpu's modified bits - however since we do not -+ * syncronize our modified bit on a coproc_invalidate_page() call, -+ * then it could get lost if we modify the page after the last -+ * modification and writepage has occurred. Hence we invalidate -+ * all translations and allow it to refault. -+ */ -+ -+ user_unload_main (pr->pr_uctx, start, end - start); -+} -+ -+static void -+user_coproc_invalidate_range (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_invalidate_range: start=%lx end=%lx\n", start, end); -+ -+ user_unload_main (pr->pr_uctx, start, end - start); -+} -+ -+static void -+user_coproc_update_range (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_update_range: start=%lx end=%lx\n", start, end); -+ -+#if defined(CONFIG_MPSAS) -+ if (((end - start) >> PAGE_SHIFT) > 16) -+ return; -+#endif -+ -+ user_update_main (pr->pr_uctx, mm, start, end - start); -+} -+ -+static void -+user_coproc_change_protection (void *arg, struct mm_struct *mm, unsigned long start, unsigned long end, pgprot_t newprot) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_change_protection: start=%lx end=%lx\n", start, end); -+ -+ user_unload_main (pr->pr_uctx, start, end - start); -+} -+ -+static void -+user_coproc_sync_page (void *arg, struct vm_area_struct *vma, unsigned long addr) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_sync_page: addr=%lx\n", addr); -+ -+ user_unload_main (pr->pr_uctx, addr & PAGE_MASK, PAGE_SIZE); -+} -+ -+static void -+user_coproc_invalidate_page (void *arg, struct vm_area_struct *vma, unsigned long addr) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_invalidate_page: addr=%lx\n", addr); -+ -+ user_unload_main (pr->pr_uctx, addr & PAGE_MASK, PAGE_SIZE); -+} -+ -+static void -+user_coproc_update_page (void *arg, struct vm_area_struct *vma, unsigned long addr) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) arg; -+ -+ PRINTF (pr->pr_uctx, DBG_IOPROC, "user_coproc_update_page: addr=%lx\n", addr); -+ -+ user_update_main (pr->pr_uctx, vma->vm_mm, addr & PAGE_MASK, PAGE_SIZE); -+} -+ -+static int -+user_open (struct inode *inode, struct file *file) -+{ -+ ELAN4_DEV *dev; -+ USER_PRIVATE *pr; -+ USER_CTXT *uctx; -+ -+ PRINTF (DBG_USER, DBG_FILE, "user_open: mm=%p users=%d count=%d\n", current->mm, -+ atomic_read (¤t->mm->mm_users), atomic_read (¤t->mm->mm_count)); -+ -+ if ((dev = elan4_reference_device (ELAN4_DEVICE(inode), ELAN4_STATE_STARTED)) == NULL) -+ return (-ENXIO); -+ -+ if ((pr = (USER_PRIVATE *) kmalloc (sizeof (USER_PRIVATE), GFP_KERNEL)) == NULL) -+ { -+ elan4_dereference_device (dev); -+ return (-ENOMEM); -+ } -+ -+ uctx = user_alloc (dev); -+ -+ if (IS_ERR(uctx)) -+ { -+ elan4_dereference_device (dev); -+ kfree (pr); -+ -+ return PTR_ERR(uctx); -+ } -+ -+ /* initialise refcnt to 2 - one for "file", one for the coproc ops */ -+ atomic_set (&pr->pr_ref, 2); -+ -+ pr->pr_uctx = uctx; -+ pr->pr_mm = current->mm; -+ -+ /* register a coproc callback to notify us of translation changes */ -+ pr->pr_coproc.arg = (void *) pr; -+ pr->pr_coproc.release = user_coproc_release; -+ pr->pr_coproc.sync_range = user_coproc_sync_range; -+ pr->pr_coproc.invalidate_range = user_coproc_invalidate_range; -+ pr->pr_coproc.update_range = user_coproc_update_range; -+ pr->pr_coproc.change_protection = user_coproc_change_protection; -+ pr->pr_coproc.sync_page = user_coproc_sync_page; -+ pr->pr_coproc.invalidate_page = user_coproc_invalidate_page; -+ pr->pr_coproc.update_page = user_coproc_update_page; -+ -+ spin_lock (¤t->mm->page_table_lock); -+ register_coproc_ops (current->mm, &pr->pr_coproc); -+ spin_unlock (¤t->mm->page_table_lock); -+ -+ file->private_data = (void *) pr; -+ -+ return (0); -+} -+ -+static int -+user_release (struct inode *inode, struct file *file) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ -+ PRINTF (pr->pr_uctx, DBG_FILE, "user_release: ref=%d\n", atomic_read (&pr->pr_ref)); -+ -+ if (atomic_dec_and_test (&pr->pr_ref)) -+ user_private_free (pr); -+ -+ return (0); -+} -+ -+static int -+user_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ USER_CTXT *uctx = pr->pr_uctx; -+ int res = 0; -+ -+ PRINTF (uctx, DBG_FILE, "user_ioctl: cmd=%x arg=%lx\n", cmd, arg); -+ -+ if (current->mm != pr->pr_mm) -+ return (-EINVAL); -+ -+ switch (cmd) -+ { -+ case ELAN4IO_DEVINFO: -+ if (copy_to_user ((void *) arg, &uctx->uctx_ctxt.ctxt_dev->dev_devinfo, sizeof (ELAN_DEVINFO))) -+ return (-EFAULT); -+ return (0); -+ -+ case ELAN4IO_POSITION: -+ { -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ -+ if (copy_to_user ((void *) arg, &dev->dev_position, sizeof (ELAN_POSITION))) -+ return (-EFAULT); -+ return (0); -+ } -+ -+ case ELAN4IO_FREE: -+ spin_lock (¤t->mm->page_table_lock); -+ if (pr->pr_mm != current->mm) -+ spin_unlock (¤t->mm->page_table_lock); -+ else -+ { -+ unregister_coproc_ops (current->mm, &pr->pr_coproc); -+ spin_unlock (¤t->mm->page_table_lock); -+ -+ user_coproc_release (pr, current->mm); -+ } -+ return (0); -+ -+ case ELAN4IO_ATTACH: -+ { -+ ELAN_CAPABILITY *cap; -+ -+ if ((cap = kmalloc (sizeof (ELAN_CAPABILITY), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (cap, (void *) arg, sizeof (ELAN_CAPABILITY))) -+ res = -EFAULT; -+ else if ((res = user_attach (uctx, cap)) == 0 && -+ copy_to_user ((void *) arg, cap, sizeof (ELAN_CAPABILITY))) -+ { -+ user_detach (uctx, cap); -+ res = -EFAULT; -+ } -+ -+ kfree (cap); -+ return (res); -+ } -+ -+ case ELAN4IO_DETACH: -+ { -+ ELAN_CAPABILITY *cap; -+ -+ if ((cap = kmalloc (sizeof (ELAN_CAPABILITY), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (cap, (void *) arg, sizeof (ELAN_CAPABILITY))) -+ res = -EFAULT; -+ else -+ user_detach (uctx, cap); -+ -+ kfree (cap); -+ return (res); -+ } -+ -+ case ELAN4IO_BLOCK_INPUTTER: -+ user_block_inputter (uctx, arg); -+ return (0); -+ -+ case ELAN4IO_ADD_P2PVP: -+ { -+ ELAN4IO_ADD_P2PVP_STRUCT *args; -+ -+ if ((args = kmalloc (sizeof (ELAN4IO_ADD_P2PVP_STRUCT), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (args, (void *) arg, sizeof (ELAN4IO_ADD_P2PVP_STRUCT))) -+ res = -EFAULT; -+ else -+ res = user_add_p2pvp (uctx, args->vp_process, &args->vp_capability); -+ -+ kfree (args); -+ return (res); -+ } -+ -+ case ELAN4IO_ADD_BCASTVP: -+ { -+ ELAN4IO_ADD_BCASTVP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ADD_BCASTVP_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_add_bcastvp (uctx, args.vp_process, args.vp_lowvp, args.vp_highvp)); -+ } -+ -+ case ELAN4IO_REMOVEVP: -+ return (user_removevp (uctx, arg)); -+ -+ case ELAN4IO_SET_ROUTE: -+ { -+ ELAN4IO_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_set_route (uctx, args.rt_process, &args.rt_route)); -+ } -+ -+ case ELAN4IO_RESET_ROUTE: -+ { -+ ELAN4IO_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_reset_route (uctx, args.rt_process)); -+ } -+ -+ case ELAN4IO_GET_ROUTE: -+ { -+ ELAN4IO_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ if ((res = user_get_route (uctx, args.rt_process, &args.rt_route)) == 0 && -+ copy_to_user ((void *) arg, &args, sizeof (ELAN4IO_ROUTE_STRUCT))) -+ res = -EFAULT; -+ -+ return (res); -+ } -+ -+ case ELAN4IO_CHECK_ROUTE: -+ { -+ ELAN4IO_ROUTE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ROUTE_STRUCT))) -+ return (-EFAULT); -+ -+ if ((res = user_check_route (uctx, args.rt_process, &args.rt_route, &args.rt_error)) == 0 && -+ copy_to_user ((void *) arg, &args, sizeof (ELAN4IO_ROUTE_STRUCT))) -+ res = -EFAULT; -+ -+ return (res); -+ } -+ -+ case ELAN4IO_ALLOCCQ: -+ { -+ ELAN4IO_ALLOCCQ_STRUCT args; -+ USER_CQ *ucq; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ALLOCCQ_STRUCT))) -+ return (-EFAULT); -+ -+ ucq = user_alloccq (uctx, args.cq_size & CQ_SizeMask, args.cq_perm & CQ_PermissionMask, -+ (args.cq_type & ELAN4IO_CQ_TYPE_REORDER) ? UCQ_REORDER : 0); -+ if (IS_ERR (ucq)) -+ return PTR_ERR (ucq); -+ -+ args.cq_indx = elan4_cq2idx (ucq->ucq_cq); -+ -+ if (copy_to_user ((void *) arg, &args, sizeof (ELAN4IO_ALLOCCQ_STRUCT))) -+ { -+ user_dropcq (uctx, ucq); -+ return (-EFAULT); -+ } -+ -+ /* don't drop the reference on the cq until the context is freed, -+ * or the caller explicitly frees the cq */ -+ return (0); -+ } -+ -+ case ELAN4IO_FREECQ: -+ { -+ USER_CQ *ucq; -+ unsigned indx; -+ -+ if (copy_from_user (&indx, (void *) arg, sizeof (unsigned))) -+ return (-EFAULT); -+ -+ if ((ucq = user_findcq (uctx, indx)) == NULL) /* can't free unallocated cq */ -+ return (-EINVAL); -+ -+ user_dropcq (uctx, ucq); /* drop the reference we've just taken */ -+ -+ if ((ucq->ucq_flags & UCQ_SYSTEM)) /* can't free device driver cq */ -+ return (-EINVAL); -+ -+ user_dropcq (uctx, ucq); /* and the one held from the alloccq call */ -+ -+ return (0); -+ } -+ -+ case ELAN4IO_DUMPCQ: -+ { -+ ELAN4IO_DUMPCQ_STRUCT args; -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ USER_CQ *ucq; -+ void *buf; -+ int i; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof(ELAN4IO_DUMPCQ_STRUCT))) -+ return (-EFAULT); -+ -+ if ((ucq = user_findcq (uctx, args.cq_indx)) == NULL) -+ return (-EINVAL); -+ -+ if (args.bufsize) -+ { -+ E4_uint32 usedBufSize = min(args.cq_size, args.bufsize); -+ -+ KMEM_ALLOC (buf, void *, usedBufSize, 0); -+ -+ if (buf == NULL) -+ return (-ENOMEM); -+ -+ for (i=0; iucq_cq->cq_space + i); -+ -+ if (copy_to_user((void *)args.buffer, buf, usedBufSize)) -+ { -+ KMEM_FREE(buf, args.bufsize); -+ return (-EFAULT); -+ } -+ KMEM_FREE(buf, usedBufSize); -+ args.bufsize = usedBufSize; -+ } -+ -+ args.cq_size = CQ_Size(ucq->ucq_cq->cq_size); -+ args.cq_space = ucq->ucq_cq->cq_space; -+ -+ -+ if (copy_to_user((void *)arg, &args, sizeof(ELAN4IO_DUMPCQ_STRUCT))) -+ { -+ return (-EFAULT); -+ } -+ -+ user_dropcq (uctx, ucq); /* drop the reference we've just taken */ -+ -+ return (0); -+ } -+ -+ case ELAN4IO_SETPERM: -+ { -+ ELAN4IO_PERM_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_PERM_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_setperm (uctx, args.ps_maddr, args.ps_eaddr, args.ps_len, args.ps_perm)); -+ } -+ -+ case ELAN4IO_CLRPERM: -+ { -+ ELAN4IO_PERM_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_PERM_STRUCT))) -+ return (-EFAULT); -+ -+ user_clrperm (uctx, args.ps_eaddr, args.ps_len); -+ return (0); -+ } -+ -+ case ELAN4IO_TRAPSIG: -+ { -+ ELAN4IO_TRAPSIG_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_TRAPSIG_STRUCT))) -+ return (-EFAULT); -+ -+ pr->pr_uctx->uctx_trap_pid = current->pid; -+ pr->pr_uctx->uctx_trap_signo = args.ts_signo; -+ -+ return (0); -+ } -+ -+ case ELAN4IO_TRAPHANDLER: -+ { -+ ELAN4IO_TRAPHANDLER_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_TRAPHANDLER_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_trap_handler (pr->pr_uctx, (ELAN4_USER_TRAP *)args.th_trapp, args.th_nticks)); -+ } -+ -+ case ELAN4IO_REQUIRED_MAPPINGS: -+ { -+ ELAN4IO_REQUIRED_MAPPINGS_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_REQUIRED_MAPPINGS_STRUCT))) -+ return (-EFAULT); -+ -+ pr->pr_uctx->uctx_upage_addr = args.rm_upage_addr; -+ pr->pr_uctx->uctx_trestart_addr = args.rm_trestart_addr; -+ -+ return (0); -+ } -+ -+ case ELAN4IO_ALLOC_TRAP_QUEUES: -+ { -+ ELAN4IO_ALLOC_TRAP_QUEUES_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_ALLOC_TRAP_QUEUES_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_alloc_trap_queues (uctx, args.tq_ndproc_traps, args.tq_neproc_traps, -+ args.tq_ntproc_traps, args.tq_nthreads, args.tq_ndmas)); -+ } -+ -+ case ELAN4IO_RESUME_EPROC_TRAP: -+ { -+ ELAN4IO_RESUME_EPROC_TRAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_RESUME_EPROC_TRAP_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_resume_eproc_trap (pr->pr_uctx, args.rs_addr)); -+ } -+ -+ case ELAN4IO_RESUME_CPROC_TRAP: -+ { -+ ELAN4IO_RESUME_CPROC_TRAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_RESUME_CPROC_TRAP_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_resume_cproc_trap (pr->pr_uctx, args.rs_indx)); -+ } -+ -+ case ELAN4IO_RESUME_DPROC_TRAP: -+ { -+ ELAN4IO_RESUME_DPROC_TRAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_RESUME_DPROC_TRAP_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_resume_dproc_trap (pr->pr_uctx, &args.rs_desc)); -+ } -+ -+ case ELAN4IO_RESUME_TPROC_TRAP: -+ { -+ ELAN4IO_RESUME_TPROC_TRAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_RESUME_TPROC_TRAP_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_resume_tproc_trap (pr->pr_uctx, &args.rs_regs)); -+ } -+ -+ case ELAN4IO_RESUME_IPROC_TRAP: -+ { -+ ELAN4IO_RESUME_IPROC_TRAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_RESUME_IPROC_TRAP_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_resume_iproc_trap (pr->pr_uctx, args.rs_channel, args.rs_trans, -+ &args.rs_header, &args.rs_data)); -+ } -+ -+ case ELAN4IO_FLUSH_ICACHE: -+ elan4_flush_icache (&uctx->uctx_ctxt); -+ return (0); -+ -+ case ELAN4IO_STOP_CTXT: -+ if (arg) -+ user_swapout (uctx, UCTX_USER_STOPPED); -+ else -+ user_swapin (uctx, UCTX_USER_STOPPED); -+ return (0); -+ -+ case ELAN4IO_ALLOC_INTCOOKIE_TABLE: -+ { -+ ELAN_CAPABILITY *cap; -+ INTCOOKIE_TABLE *tbl; -+ -+ if ((cap = kmalloc (sizeof (ELAN_CAPABILITY), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (cap, (void *) arg, sizeof (ELAN_CAPABILITY))) -+ res = -EFAULT; -+ else -+ { -+ tbl = intcookie_alloc_table(cap); -+ -+ if (tbl == NULL) -+ res = -ENOMEM; -+ else -+ { -+ /* Install the intcookie table we've just created */ -+ spin_lock (&uctx->uctx_spinlock); -+ if (uctx->uctx_intcookie_table != NULL) -+ res = -EBUSY; -+ else -+ uctx->uctx_intcookie_table = tbl; -+ spin_unlock (&uctx->uctx_spinlock); -+ -+ /* drop the table we created if there already was one */ -+ if (res != 0) -+ intcookie_free_table (tbl); -+ } -+ } -+ -+ kfree (cap); -+ -+ return (res); -+ } -+ -+ case ELAN4IO_FREE_INTCOOKIE_TABLE: -+ { -+ INTCOOKIE_TABLE *tbl; -+ -+ spin_lock (&uctx->uctx_spinlock); -+ tbl = uctx->uctx_intcookie_table; -+ uctx->uctx_intcookie_table = NULL; -+ spin_unlock (&uctx->uctx_spinlock); -+ -+ if (tbl != NULL) -+ intcookie_free_table (tbl); -+ -+ return (tbl == NULL ? -EINVAL : 0); -+ } -+ -+ case ELAN4IO_ALLOC_INTCOOKIE: -+ { -+ /* For backwards compatibility with the old libs (pre 1.8.0) -+ * we allocate an intcookie table on the first cookie -+ * alloc if one hasn't be created already -+ */ -+ if (uctx->uctx_intcookie_table == NULL) -+ { -+ ELAN_CAPABILITY *cap; -+ INTCOOKIE_TABLE *tbl; -+ -+ if ((cap = kmalloc (sizeof (ELAN_CAPABILITY), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ /* Create a dummy capability */ -+ elan_nullcap(cap); -+ -+ /* Must be unique for each process on a node */ -+ cap->cap_mycontext = (int) ELAN4_TASK_HANDLE(); -+ -+ /* Create a new intcookie table */ -+ tbl = intcookie_alloc_table(cap); -+ -+ /* Hang intcookie table off uctx */ -+ spin_lock (&uctx->uctx_spinlock); -+ if (uctx->uctx_intcookie_table == NULL) -+ { -+ uctx->uctx_intcookie_table = tbl; -+ spin_unlock (&uctx->uctx_spinlock); -+ } -+ else -+ { -+ spin_unlock (&uctx->uctx_spinlock); -+ intcookie_free_table(tbl); -+ } -+ -+ kfree(cap); -+ } -+ -+ return (intcookie_alloc (uctx->uctx_intcookie_table, arg)); -+ } -+ -+ case ELAN4IO_FREE_INTCOOKIE: -+ if (uctx->uctx_intcookie_table == NULL) -+ return -EINVAL; -+ else -+ return (intcookie_free (uctx->uctx_intcookie_table, arg)); -+ -+ case ELAN4IO_ARM_INTCOOKIE: -+ if (uctx->uctx_intcookie_table == NULL) -+ return -EINVAL; -+ else -+ return (intcookie_arm (uctx->uctx_intcookie_table, arg)); -+ -+ case ELAN4IO_WAIT_INTCOOKIE: -+ if (uctx->uctx_intcookie_table == NULL) -+ return -EINVAL; -+ else -+ return (intcookie_wait (uctx->uctx_intcookie_table, arg)); -+ -+ case ELAN4IO_FIRE_INTCOOKIE: -+ { -+ ELAN4IO_FIRECAP_STRUCT *args; -+ -+ if ((args = kmalloc (sizeof (ELAN4IO_FIRECAP_STRUCT), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (args, (void *) arg, sizeof (ELAN4IO_FIRECAP_STRUCT))) -+ res = -EFAULT; -+ else -+ res = intcookie_fire_cap (&args->fc_capability, args->fc_cookie); -+ -+ kfree (args); -+ -+ return (res); -+ } -+ -+ case ELAN4IO_NETERR_MSG: -+ { -+ ELAN4IO_NETERR_MSG_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_NETERR_MSG_STRUCT))) -+ return (-EFAULT); -+ -+ return (user_send_neterr_msg (uctx, args.nm_vp, args.nm_nctx, args.nm_retries, &args.nm_msg)); -+ } -+ -+ case ELAN4IO_NETERR_TIMER: -+ { -+ unsigned long ticks = ((unsigned long) arg * HZ) / 1000; -+ -+ PRINTF (uctx, DBG_NETERR, "elan4_neterr_timer: arg %ld inc %ld\n", arg, ticks); -+ -+ mod_timer (&uctx->uctx_neterr_timer, (jiffies + (ticks > 0 ? ticks : 1))); -+ return 0; -+ } -+ -+ case ELAN4IO_NETERR_FIXUP: -+ { -+ ELAN4IO_NETERR_FIXUP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_NETERR_FIXUP_STRUCT))) -+ return (-EFAULT); -+ -+ if (args.nf_sten) -+ return (user_neterr_sten (uctx, args.nf_vp, args.nf_cookie, args.nf_waitforeop)); -+ else -+ return (user_neterr_dma (uctx, args.nf_vp, args.nf_cookie, args.nf_waitforeop)); -+ } -+ default: -+ PRINTF (uctx, DBG_FILE, "user_ioctl: invalid ioctl %x\n", cmd); -+ return (-EINVAL); -+ } -+} -+ -+static void -+user_vma_open (struct vm_area_struct *vma) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) vma->vm_private_data; -+ USER_CTXT *uctx = pr->pr_uctx; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (uctx, DBG_FILE, "user_vma_open: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ elan4_getcqa (&uctx->uctx_ctxt, pgoff); -+} -+ -+static void -+user_vma_close (struct vm_area_struct *vma) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) vma->vm_private_data; -+ USER_CTXT *uctx = pr->pr_uctx; -+ unsigned long addr; -+ unsigned long pgoff; -+ -+ PRINTF (uctx, DBG_FILE, "user_vma_close: vm_mm=%p start=%lx end=%lx pgoff=%lx file=%p\n", -+ vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_file); -+ -+ /* NOTE: the same comments apply as mem_vma_close */ -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ if (elan4_getcqa (&uctx->uctx_ctxt, pgoff) != NULL) -+ { -+ elan4_putcqa (&uctx->uctx_ctxt, pgoff); /* drop the reference we've just taken */ -+ elan4_putcqa (&uctx->uctx_ctxt, pgoff); /* and the one held by the mmap */ -+ } -+} -+ -+struct vm_operations_struct user_vm_ops = { -+ open: user_vma_open, -+ close: user_vma_close, -+}; -+ -+static int -+user_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ USER_CTXT *uctx = pr->pr_uctx; -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ ELAN4_CQA *cqa; -+ unsigned long addr; -+ unsigned long pgoff; -+ int res; -+ ioaddr_t ioaddr; -+ -+ for (addr = vma->vm_start, pgoff = vma->vm_pgoff; addr < vma->vm_end; addr += PAGE_SIZE, pgoff++) -+ { -+ switch (pgoff) -+ { -+ default: -+ PRINTF (uctx, DBG_FILE, "user_mmap: command queue %ld mapping at %lx\n", pgoff, addr); -+ -+ if ((cqa = elan4_getcqa (&uctx->uctx_ctxt, pgoff)) == NULL) -+ { -+ res = -EINVAL; -+ goto failed; -+ } -+ -+ PRINTF (uctx, DBG_FILE, "user_mmap: cqa=%p idx=%d num=%d ref=%d\n", cqa, cqa->cqa_idx, cqa->cqa_cqnum, cqa->cqa_ref); -+ -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ if (! (dev->dev_features & ELAN4_FEATURE_NO_WRITE_COMBINE) && (cqa->cqa_type & CQ_Reorder) != 0) -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ PRINTF (uctx, DBG_FILE, "user_mmap: remap_page_range (%lx, %lx, %lx, %lx)\n", -+ addr, pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS) + -+ (cqa->cqa_cqnum + dev->dev_cqoffset) * CQ_CommandMappingSize, PAGE_SIZE, -+ vma->vm_page_prot); -+ -+ /* Don't allow these pages to be swapped out of dumped */ -+ vma->vm_flags |= (VM_RESERVED | VM_IO); -+ -+ if (__io_remap_page_range (addr, -+ pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS) + -+ (cqa->cqa_cqnum + dev->dev_cqoffset) * CQ_CommandMappingSize, -+ PAGE_SIZE, vma->vm_page_prot)) -+ { -+ PRINTF (uctx, DBG_FILE, "user_mmap: remap_page_range failed\n"); -+ -+ elan4_putcqa (&uctx->uctx_ctxt, pgoff); -+ res = -ENOMEM; -+ goto failed; -+ } -+ break; -+ -+ case ELAN4_OFF_USER_REGS: -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ /* Don't allow these pages to be swapped out of dumped */ -+ vma->vm_flags |= (VM_RESERVED | VM_IO); -+ -+ switch (dev->dev_devinfo.dev_revision_id) -+ { -+ case PCI_REVISION_ID_ELAN4_REVA: -+ ioaddr = pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS) + ELAN4_REVA_REG_OFFSET + offsetof(E4_Registers, uRegs); -+ break; -+ -+ case PCI_REVISION_ID_ELAN4_REVB: -+ ioaddr = pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS) + ELAN4_REVB_REG_OFFSET + offsetof(E4_Registers, uRegs); -+ break; -+ -+ default: -+ res = -EINVAL; -+ goto failed; -+ } -+ -+ PRINTF (uctx, DBG_FILE, "user_mmap: user_regs at %lx ioaddr %lx prot %lx\n", -+ addr, ioaddr, vma->vm_page_prot.pgprot); -+ -+ if (__io_remap_page_range (addr, (ioaddr & PAGEMASK), PAGE_SIZE, vma->vm_page_prot)) -+ { -+ res = -EAGAIN; -+ goto failed; -+ } -+ -+ break; -+ -+ case ELAN4_OFF_USER_PAGE: -+ PRINTF (uctx, DBG_FILE, "user_mmap: shared user page - kaddr=%lx uaddr=%lx phys=%lx\n", -+ uctx->uctx_upage, addr, kmem_to_phys (uctx->uctx_upage)); -+ -+ /* we do not want to have this area swapped out, lock it */ -+ vma->vm_flags |= VM_LOCKED; -+ -+ /* Mark the page as reserved or else the remap_page_range() doesn't remap it */ -+ SetPageReserved(pte_page(*find_pte_kernel((unsigned long) uctx->uctx_upage))); -+ -+ if (__remap_page_range (addr, kmem_to_phys (uctx->uctx_upage), PAGE_SIZE, vma->vm_page_prot)) -+ { -+ PRINTF (uctx, DBG_FILE, "user_mmap: remap_page_range (user_page) failed\n"); -+ res = -ENOMEM; -+ goto failed; -+ } -+ break; -+ -+ case ELAN4_OFF_TPROC_TRAMPOLINE: -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ PRINTF (uctx, DBG_FILE, "user_mmap: tproc trampoline - kaddr=%lx uaddr=%lx phys=%lx\n", uctx->uctx_trampoline, addr, -+ pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM) + uctx->uctx_trampoline + (addr & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT))); -+ -+ /* Don't allow these pages to be swapped out of dumped */ -+ vma->vm_flags |= (VM_RESERVED | VM_IO); -+ -+ if (__io_remap_page_range (addr, pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM) + -+ uctx->uctx_trampoline + (addr & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT)), -+ PAGE_SIZE, vma->vm_page_prot)) -+ { -+ PRINTF (uctx, DBG_FILE, "user_mmap: remap_page_range (tproc_trampoline) failed\n"); -+ res = -ENOMEM; -+ goto failed; -+ } -+ break; -+ -+ case ELAN4_OFF_DEVICE_STATS: -+ printk ("user_mmap: device_stats\n"); -+ break; -+ } -+ -+ } -+ -+ ASSERT (vma->vm_ops == NULL); -+ -+ /* Don't try to swap out physical pages.. */ -+ vma->vm_flags |= VM_RESERVED; -+ -+ /* -+ * Don't dump addresses that are not real memory to a core file. -+ */ -+ vma->vm_flags |= VM_IO; -+ -+ vma->vm_ops = &user_vm_ops; -+ vma->vm_file = file; -+ vma->vm_private_data = (void *) pr; -+ -+ return (0); -+ -+ failed: -+ for (addr -= PAGE_SIZE, pgoff--; addr >= vma->vm_start; addr -= PAGE_SIZE, pgoff--) -+ elan4_putcqa (&uctx->uctx_ctxt, pgoff); /* drop the reference we've just taken */ -+ return (res); -+} -+ -+/* driver entry points */ -+static int -+elan4_open (struct inode *inode, struct file *file) -+{ -+ PRINTF (DBG_USER, DBG_FILE, "elan4_open: device %d minor %d file=%p\n", ELAN4_DEVICE(inode), ELAN4_MINOR(inode), file); -+ -+ switch (ELAN4_MINOR (inode)) -+ { -+ case ELAN4_MINOR_CONTROL: -+ return (control_open (inode, file)); -+ case ELAN4_MINOR_MEM: -+ return (mem_open (inode, file)); -+ case ELAN4_MINOR_USER: -+ return (user_open (inode, file)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+static int -+elan4_release (struct inode *inode, struct file *file) -+{ -+ PRINTF (DBG_USER, DBG_FILE, "elan4_release: device %d minor %d file=%p\n", ELAN4_DEVICE(inode), ELAN4_MINOR(inode), file); -+ -+ switch (ELAN4_MINOR (inode)) -+ { -+ case ELAN4_MINOR_CONTROL: -+ return (control_release (inode, file)); -+ case ELAN4_MINOR_MEM: -+ return (mem_release (inode, file)); -+ case ELAN4_MINOR_USER: -+ return (user_release (inode, file)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+static int -+elan4_ioctl (struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ PRINTF (DBG_USER, DBG_FILE, "elan4_ioctl: device %d minor %d cmd %x\n", ELAN4_DEVICE(inode), ELAN4_MINOR(inode), cmd); -+ -+ switch (ELAN4_MINOR (inode)) -+ { -+ case ELAN4_MINOR_CONTROL: -+ return (control_ioctl (inode, file, cmd, arg)); -+ case ELAN4_MINOR_MEM: -+ return (mem_ioctl (inode, file, cmd, arg)); -+ case ELAN4_MINOR_USER: -+ return (user_ioctl (inode, file, cmd, arg)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+static int -+elan4_ioctl32 (unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) -+{ -+ struct inode *inode = file->f_dentry->d_inode; -+ extern int sys_ioctl (unsigned int fd, unsigned int cmd, unsigned long arg); -+ -+ PRINTF (DBG_USER, DBG_FILE, "elan4_ioctl32: device %d minor %d cmd %x\n", ELAN4_DEVICE(inode), ELAN4_MINOR(inode), cmd); -+ -+ if (ELAN4_MINOR (inode) == ELAN4_MINOR_USER) -+ { -+ USER_PRIVATE *pr = (USER_PRIVATE *) file->private_data; -+ USER_CTXT *uctx = pr->pr_uctx; -+ -+ if (current->mm != pr->pr_mm) -+ return -EINVAL; -+ -+ switch (cmd) -+ { -+ case ELAN4IO_SETPERM32: -+ { -+ ELAN4IO_PERM_STRUCT32 args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_PERM_STRUCT32))) -+ return (-EFAULT); -+ -+ PRINTF (DBG_USER, DBG_FILE, "user_ioctl32: setperm maddr=%x eaddr=%llx len=%llxx perm=%d\n", -+ args.ps_maddr, args.ps_eaddr,args.ps_len, args.ps_perm); -+ -+ return (user_setperm (uctx, args.ps_maddr, args.ps_eaddr, args.ps_len, args.ps_perm)); -+ } -+ -+ case ELAN4IO_CLRPERM32: -+ { -+ ELAN4IO_PERM_STRUCT32 args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_PERM_STRUCT32))) -+ return (-EFAULT); -+ -+ PRINTF (DBG_USER, DBG_FILE, "user_ioctl32: clrperm eaddr=%llx len=%ll\n", -+ args.ps_eaddr, args.ps_len); -+ -+ user_clrperm (uctx, args.ps_eaddr, args.ps_len); -+ return (0); -+ } -+ -+ case ELAN4IO_TRAPHANDLER32: -+ { -+ ELAN4IO_TRAPHANDLER_STRUCT32 args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (ELAN4IO_TRAPHANDLER_STRUCT32))) -+ return (-EFAULT); -+ -+ PRINTF (DBG_USER, DBG_FILE, "user_ioctl32: traphandler trapp=%x nticks=%d\n", -+ args.th_trapp, args.th_nticks); -+ -+ return (user_trap_handler (pr->pr_uctx, (ELAN4_USER_TRAP *)(unsigned long)args.th_trapp, args.th_nticks)); -+ } -+ } -+ } -+ -+ PRINTF (DBG_USER, DBG_FILE, "elan4_ioctl32: fd=%d cmd=%x arg=%lx file=%p\n", fd, cmd, arg, file); -+ return (sys_ioctl (fd, cmd, arg)); -+} -+#endif -+ -+ -+ -+static int -+elan4_mmap (struct file *file, struct vm_area_struct *vma) -+{ -+ PRINTF (DBG_USER, DBG_FILE, "elan4_mmap: instance %d minor %d start=%lx end=%lx pgoff=%lx\n", -+ ELAN4_DEVICE (file->f_dentry->d_inode), ELAN4_MINOR (file->f_dentry->d_inode), -+ vma->vm_start, vma->vm_end, vma->vm_pgoff); -+ -+ switch (ELAN4_MINOR (file->f_dentry->d_inode)) -+ { -+ case ELAN4_MINOR_CONTROL: -+ return (control_mmap (file, vma)); -+ case ELAN4_MINOR_MEM: -+ return (mem_mmap (file, vma)); -+ case ELAN4_MINOR_USER: -+ return (user_mmap (file, vma)); -+ default: -+ return (-ENXIO); -+ } -+} -+ -+void -+elan4_update_intel_p64h2 (ELAN4_DEV *dev, struct pci_dev *bridge) -+{ -+ u16 cnf; -+ -+ pci_read_config_word (bridge, 0x40 /* CNF */, &cnf); -+ -+ /* We expect the CNF register to be configured as follows -+ * -+ * [8] == 1 PMODE PCI Mode -+ * [7:6] == 2/3 PFREQ PCI Frequency (100/133) -+ * [5] == 0 RSDIS Restreaming Disable -+ * [4:3] == 0x PP Prefetch Policy -+ * [2] == 0 DTD Delayed Transaction Depth -+ * [1:0] == 10 MDT MaximumDelaedTransactions -+ */ -+ -+ if ((cnf & (1 << 8)) == 0) -+ printk ("elan%d: strangeness - elan reports PCI-X but P64H2 reports PCI mode !\n", dev->dev_instance); -+ else if ((cnf & 0xb7) != 0x82 && (cnf & 0xb7) != 0x84 && optimise_pci_bus < 2) -+ printk ("elan%d: P64H2 CNF is not configured as expected : RSDIS=%d PP=%d DTD=%d MDT=%d\n", -+ dev->dev_instance, (cnf >> 5) & 1, (cnf >> 3) & 3, (cnf >> 2) & 1, cnf & 3); -+ else -+ { -+ switch ((cnf >> 6) & 3) -+ { -+ case 2: /* PCI-X 100 */ -+ pci_write_config_word (bridge, 0xfc /* PC100 */, 0x7777); -+ -+ printk ("elan%d: optimise P64H2 : setting MDT=0, DTD=1, PFC=777 for PCI-X 100\n", dev->dev_instance); -+ -+ break; -+ -+ case 3: /* PCI-X 133 */ -+ pci_write_config_word (bridge, 0xfe /* PC133 */, 0x7777); -+ -+ printk ("elan%d: optimise P64H2 : setting MDT=0, DTD=1, PFC=777 for PCI-X 133\n", dev->dev_instance); -+ break; -+ } -+ -+ pci_write_config_word (bridge, 0x40 /* CNF */, (cnf & 0xfff8) | 0x4); /* DTD=1 MDT=0 */ -+ } -+} -+ -+int -+elan4_optimise_intel_p64h2 (ELAN4_DEV *dev, struct pci_dev *pdev) -+{ -+ struct pci_bus *bus = pdev->bus; -+ struct pci_dev *bridge = bus->self; -+ unsigned int devcount = 0; -+ u8 revision; -+ u32 ectrl; -+ struct list_head *el; -+ -+ pci_read_config_dword (pdev, PCI_ELAN_CONTROL, &ectrl); -+ -+ /* We can only run in PCI-Xmode with a B1 stepping P64H2 because of P64H2 Errata 3 */ -+ pci_read_config_byte (bridge, PCI_REVISION_ID, &revision); -+ if (revision < 0x04) -+ { -+ if ((ectrl & ECTRL_INITIALISATION_MODE) != Pci2_2) -+ { -+ static const char *p64h2_stepping[4] = {"UNKNOWN", "UNKNOWN", "UNKNOWN", "B0"}; -+ -+ printk ("elan%d: unable to use device because of P64H2 Errata 3 on\n" -+ " %s stepping part and running in a PCI-X slot\n", -+ dev->dev_instance, p64h2_stepping[revision]); -+ return -EINVAL; -+ } -+ } -+ -+ /* We can only alter the bus configuration registers if the Elan is the only device -+ * on the bus ... */ -+ list_for_each (el, &bus->devices) { -+ struct pci_dev *pcip = list_entry (el, struct pci_dev, bus_list); -+ -+ if (pcip == pdev || (pcip->vendor == PCI_VENDOR_ID_INTEL && pcip->device == 0x1462 /* P64H2 HOTPLUG */)) -+ continue; -+ -+ devcount++; -+ } -+ -+ if (devcount > 0 || !list_empty (&bus->children)) -+ { -+ printk ("elan%d: unable to optimise P64H2 settings as %s%s\n", dev->dev_instance, -+ (devcount > 0) ? "more than one device on bus" : "", -+ ! list_empty (&bus->children) ? "has child buses" : ""); -+ return 0; -+ } -+ -+#ifdef __ia64 -+ if ((ectrl & ECTRL_INITIALISATION_MODE) == PciX100to133MHz) -+ { -+ struct pci_dev *pcip; -+ unsigned int sioh_good = 0; -+ unsigned int sioh_downgrade = 0; -+ unsigned int snc_good = 0; -+ unsigned int snc_downgrade = 0; -+ -+ /* Search for the associated SIOH and SNC on ia64, -+ * if we have a C2 SIOH and a C0/C1 SNC, then we can -+ * reconfigure the P64H2 as follows: -+ * CNF:MDT = 0 -+ * CNF:DTD = 1 -+ * CNF:PC133 = 7777 -+ * -+ * if not, then issue a warning that down rev parts -+ * affect bandwidth. -+ */ -+ for (pcip = NULL; (pcip = pci_find_device (PCI_VENDOR_ID_INTEL, 0x500, pcip)); ) -+ { -+ pci_read_config_byte (pcip, PCI_REVISION_ID, &revision); -+ -+ if (revision >= 0x21) -+ snc_good++; -+ else -+ { -+ printk ("elan%d: SNC revision %x (%s)\n", dev->dev_instance, revision, -+ revision == 0x00 ? "A0" : revision == 0x01 ? "A1" : -+ revision == 0x02 ? "A2" : revision == 0x03 ? "A3" : -+ revision == 0x10 ? "B0" : revision == 0x20 ? "C0" : -+ revision == 0x21 ? "C1" : "UNKNOWN"); -+ -+ snc_downgrade++; -+ } -+ } -+ -+ for (pcip = NULL; (pcip = pci_find_device (PCI_VENDOR_ID_INTEL, 0x510, pcip)) != NULL; ) -+ { -+ pci_read_config_byte (pcip, PCI_REVISION_ID, &revision); -+ -+ -+ if (revision >= 0x22) -+ sioh_good++; -+ else -+ { -+ printk ("elan%d: SIOH revsision %x (%s)\n", dev->dev_instance, revision, -+ revision == 0x10 ? "C0" : revision == 0x20 ? "C0" : -+ revision == 0x21 ? "C1" : revision == 0x22 ? "C2" : "UNKNOWN"); -+ -+ sioh_downgrade++; -+ } -+ } -+ -+ if (optimise_pci_bus < 2 && (sioh_downgrade || snc_downgrade)) -+ printk ("elan%d: unable to optimise as SNC/SIOH below required C1/C2 steppings\n", dev->dev_instance); -+ else if (optimise_pci_bus < 2 && (sioh_good == 0 || snc_good == 0)) -+ printk ("elan%d: unable to optimise as cannot determine SNC/SIOH revision\n", dev->dev_instance); -+ else -+ elan4_update_intel_p64h2 (dev, bridge); -+ } -+#endif -+ -+#ifdef __i386 -+ if ((ectrl & ECTRL_INITIALISATION_MODE) == PciX100to133MHz) -+ elan4_update_intel_p64h2 (dev, bridge); -+#endif -+ return 0; -+} -+ -+int -+elan4_optimise_intel_pxh (ELAN4_DEV *dev, struct pci_dev *pdev) -+{ -+#ifdef __i386 -+ printk ("elan%d: unable to use device on this platform in 32 bit mode\n", dev->dev_instance); -+ -+ return -EINVAL; -+#endif -+ -+ dev->dev_features |= ELAN4_FEATURE_NO_DWORD_READ; -+ -+ return 0; -+} -+ -+void -+elan4_optimise_serverworks_ciobx2 (ELAN4_DEV *dev) -+{ -+ struct pci_dev *pdev = dev->dev_osdep.pdev; -+ struct pci_dev *pcip; -+ unsigned char bus; -+ unsigned int dor; -+ -+ /* Find the CIOBX2 for our bus number */ -+ for (pcip = NULL; (pcip = pci_find_device (PCI_VENDOR_ID_SERVERWORKS, 0x0101, pcip)) != NULL;) -+ { -+ pci_read_config_byte (pcip, 0x44 /* BUSNUM */, &bus); -+ -+ if (pdev->bus->number == bus) -+ { -+ printk ("elan%d: optimise CIOBX2 : setting DOR to disable read pipe lining\n", dev->dev_instance); -+ -+ pci_read_config_dword (pcip, 0x78 /* DOR */, &dor); -+ pci_write_config_dword (pcip, 0x78 /* DOR */, dor | (1 << 16)); -+ } -+ } -+} -+ -+int -+elan4_optimise_bus (ELAN4_DEV *dev) -+{ -+ struct pci_dev *pdev = dev->dev_osdep.pdev; -+ -+ if (pdev->bus && pdev->bus->self) -+ { -+ struct pci_dev *bridge = pdev->bus->self; -+ -+ if (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device == 0x1460 /* Intel P64H2 */) -+ return elan4_optimise_intel_p64h2 (dev, pdev); -+ -+ if ((bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device == 0x0329) /* Intel 6700PXH Fn 0 */ || -+ (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device == 0x032a) /* Intel 6700PXH Fn 2 */ || -+ (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device == 0x032c) /* Intel 6702PXH */ || -+ (bridge->vendor == PCI_VENDOR_ID_INTEL && bridge->device == 0x0320) /* Intel PXH-D */) -+ return elan4_optimise_intel_pxh (dev, pdev); -+ } -+ -+ if (pci_find_device (PCI_VENDOR_ID_HP, 0x122e, NULL) != NULL) /* on HP ZX1 set the relaxed ordering */ -+ dev->dev_pteval = PTE_RelaxedOrder; /* bit to get better DMA bandwidth. */ -+ -+ if (pci_find_device (PCI_VENDOR_ID_SERVERWORKS, 0x0101, NULL) != NULL) /* ServerWorks CIOBX2 */ -+ elan4_optimise_serverworks_ciobx2 (dev); -+ -+ return 0; -+} -+ -+int -+elan4_pciinit (ELAN4_DEV *dev) -+{ -+ int res; -+ u32 value; -+ u16 command; -+ u8 cacheline; -+ unsigned long flags; -+ -+ if (optimise_pci_bus && (res = elan4_optimise_bus (dev)) <0) -+ return (res); -+ -+ if ((res = pci_enable_device (dev->dev_osdep.pdev)) < 0) -+ return (res); -+ -+ pci_read_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, &value); -+ if ((value & ECTRL_INITIALISATION_MODE) == Pci2_2) -+ printk ("elan%d: is an elan4%c (PCI-2.2)\n", dev->dev_instance, 'a' + dev->dev_devinfo.dev_revision_id); -+ else -+ { -+ switch (value & ECTRL_INITIALISATION_MODE) -+ { -+ case PciX50To66MHz: -+ printk ("elan%d: is an elan4%c (PCI-X 50-66)\n", dev->dev_instance, 'a' + dev->dev_devinfo.dev_revision_id); -+ break; -+ -+ case PciX66to100MHz: -+ printk ("elan%d: is an elan4%c (PCI-X 66-100)\n", dev->dev_instance, 'a' + dev->dev_devinfo.dev_revision_id); -+ break; -+ -+ case PciX100to133MHz: -+ printk ("elan%d: is an elan4%c (PCI-X 100-133)\n", dev->dev_instance, 'a' + dev->dev_devinfo.dev_revision_id); -+ break; -+ -+ default: -+ printk ("elan%d: Invalid PCI-X mode\n", dev->dev_instance); -+ return (-EINVAL); -+ } -+ } -+ -+ /* initialise the elan pll control register */ -+ pci_read_config_dword (dev->dev_osdep.pdev, PCI_ELAN_PLL_CONTROL, &value); -+ -+ if (elan4_pll_cfg) -+ { -+ printk ("elan%d: setting pll control to %08x\n", dev->dev_instance, elan4_pll_cfg); -+ -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_PLL_CONTROL, elan4_pll_cfg); -+ } -+ else -+ { -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_PLL_CONTROL, -+ (value & ~ECTRL_SYS_CLOCK_RATIO_MASK) | ECTRL_SYS_CLOCK_RATIO_4_3); -+ else -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_PLL_CONTROL, -+ (value & ~ECTRL_SYS_CLOCK_RATIO_MASK) | ECTRL_SYS_CLOCK_RATIO_6_5 | SysPll_FeedForwardISel0 | SysPll_FeedForwardISel1); -+ } -+ -+ /* initialise the elan control register */ -+ pci_read_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, &value); -+ -+ value = ((15 << ECTRL_IPROC_HIGH_PRI_TIME_SHIFT) | -+ (15 << ECTRL_OTHER_HIGH_PRI_TIME_SHIFT) | -+ (value & ECTRL_28_NOT_30_BIT_LOCAL_BAR) | -+ (dev->dev_topaddrmode ? ECTRL_ExtraMasterAddrBits : 0) | -+ ECTRL_ENABLE_LATENCY_RESET | -+ ECTRL_ENABLE_WRITEBURSTS | -+ ECTRL_ENABLE_2_2READBURSTS); -+ -+#ifdef LINUX_SPARC -+ value &= ~(ECTRL_ENABLE_LATENCY_RESET | ECTRL_ENABLE_WRITEBURSTS); -+#endif -+ -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, value | ECTRL_SOFTWARE_INTERNAL_RESET); -+ -+ switch (dev->dev_devinfo.dev_revision_id) -+ { -+ case PCI_REVISION_ID_ELAN4_REVA: -+ /* Delay 10ms here if we've changed the sysclock ratio */ -+ /* to allow the PLL to stabalise before proceeding */ -+ udelay (10000); -+ break; -+ -+ case PCI_REVISION_ID_ELAN4_REVB: -+ { -+ unsigned char val = read_i2c (dev, I2cLedsValue); -+ -+ /* On RevB we have to explicitly reset the PLLs */ -+ pci_read_config_word (dev->dev_osdep.pdev, PCI_COMMAND, &command); -+ -+ write_i2c (dev, I2cLedsValue, val | 0x80); -+ udelay (1000); -+ -+ /* Issue the PLL counter reset and immediately inhibit all pci interaction -+ * while the PLL is recovering. The write to the PCI_COMMAND register has -+ * to occur within 50uS of the write to the i2c registers */ -+ local_irq_save (flags); -+ write_i2c (dev, I2cLedsValue, val & ~0x80); -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_COMMAND, (1 << 10) /* PCI_COMMAND_DISABLE_INT */); -+ local_irq_restore (flags); -+ -+ /* Wait for the write to occur and for the PLL to regain lock */ -+ udelay (20000); udelay (20000); -+ -+ /* Re-enable pci interaction and clear any spurious errors deteced */ -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_STATUS, PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR); -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_COMMAND, command); -+ break; -+ } -+ } -+ -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, value); -+ -+ /* Enable master accesses */ -+ pci_set_master (dev->dev_osdep.pdev); -+ -+ /* Verify that the memWrInvalidate bit is set */ -+ pci_read_config_word (dev->dev_osdep.pdev, PCI_COMMAND, &command); -+ pci_read_config_byte (dev->dev_osdep.pdev, PCI_CACHE_LINE_SIZE, &cacheline); -+ -+ if ((command & PCI_COMMAND_INVALIDATE) == 0) -+ { -+ printk ("elan%d: enable MemWrInvalidate (cacheline %d)\n", -+ dev->dev_instance, cacheline * 4); -+ -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_COMMAND, command | PCI_COMMAND_INVALIDATE); -+ } -+ -+ return (0); -+} -+ -+void -+elan4_pcifini (ELAN4_DEV *dev) -+{ -+ u32 value; -+ -+ pci_read_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, &value); -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, value | ECTRL_SOFTWARE_INTERNAL_RESET); -+ pci_write_config_dword (dev->dev_osdep.pdev, PCI_ELAN_CONTROL, value); -+ -+ pci_disable_device (dev->dev_osdep.pdev); -+} -+ -+void -+elan4_pcierror (ELAN4_DEV *dev) -+{ -+ struct pci_dev *pci = dev->dev_osdep.pdev; -+ u8 type; -+ u16 status, cmd; -+ u32 physlo, physhi, control; -+ -+ printk("elan%d: pci error has occurred\n", dev->dev_instance); -+ -+ pci_read_config_word (pci, PCI_STATUS, &status); -+ pci_read_config_word (pci, PCI_COMMAND, &cmd); -+ pci_read_config_dword (pci, PCI_ELAN_CONTROL, &control); -+ -+ if (control & ECTRL_REC_SPLIT_COMP_MESSAGE) -+ { -+ u32 message, attr; -+ -+ pci_write_config_dword (pci, PCI_ELAN_CONTROL, control & ~ECTRL_SELECT_SPLIT_MESS_ATTR); -+ pci_read_config_dword (pci, PCI_ELAN_SPLIT_MESSAGE_VALUE, &message); -+ pci_write_config_dword (pci, PCI_ELAN_CONTROL, control | ECTRL_SELECT_SPLIT_MESS_ATTR); -+ pci_read_config_dword (pci, PCI_ELAN_SPLIT_MESSAGE_VALUE, &attr); -+ -+ printk ("elan%d: pcierror - received split completion message - attr=%08x, message=%08x\n", -+ dev->dev_instance, attr, message); -+ -+ pci_write_config_dword (pci, PCI_ELAN_CONTROL, control | ECTRL_REC_SPLIT_COMP_MESSAGE); /* clear the error */ -+ } -+ else -+ { -+ pci_read_config_dword (pci, PCI_ELAN_PARITY_ADDR_LO, &physlo); -+ pci_read_config_dword (pci, PCI_ELAN_PARITY_ADDR_HI, &physhi); -+ pci_read_config_byte (pci, PCI_ELAN_PARITY_TYPE, &type); -+ -+ printk ("elan%d: pcierror - status %x cmd %4x physaddr %08x%08x type %x\n", -+ dev->dev_instance, status, cmd, physhi, physlo, type); -+ -+ if (status & PCI_STATUS_PARITY) -+ printk ("elan%d: parity error signalled (PERR)\n", dev->dev_instance); -+ if (status & PCI_STATUS_DETECTED_PARITY) -+ printk ("elan%d: detected parity error\n", dev->dev_instance); -+ if (status & PCI_STATUS_REC_MASTER_ABORT) -+ printk ("elan%d: received master abort\n", dev->dev_instance); -+ if (status & PCI_STATUS_REC_TARGET_ABORT) -+ printk ("elan%d: received target abort\n", dev->dev_instance); -+ if (status & PCI_STATUS_SIG_SYSTEM_ERROR) -+ printk ("elan%d: signalled SERR\n", dev->dev_instance); -+ if (status & PCI_STATUS_SIG_TARGET_ABORT) -+ printk ("elan%d: signalled target abort\n", dev->dev_instance); -+ -+ pci_write_config_word (pci, PCI_STATUS, status); /* clear the errors */ -+ } -+ -+ DISABLE_INT_MASK (dev, INT_PciMemErr); -+ -+#ifdef notdef -+ panic ("elan%d: pcierror\n", dev->dev_instance); /* better panic ! */ -+#endif -+} -+ -+static irqreturn_t -+elan4_irq (int irq, void *arg, struct pt_regs *regs) -+{ -+ if (elan4_1msi0 ((ELAN4_DEV *) arg)) -+ return IRQ_HANDLED; -+ else -+ return IRQ_NONE; -+} -+ -+ioaddr_t -+elan4_map_device (ELAN4_DEV *dev, unsigned bar, unsigned off, unsigned size, ELAN4_MAP_HANDLE *handle) -+{ -+ return (ioaddr_t) ioremap_nocache (pci_resource_start (dev->dev_osdep.pdev, bar) + off, size); -+} -+ -+void -+elan4_unmap_device (ELAN4_DEV *dev, ioaddr_t ptr, unsigned size, ELAN4_MAP_HANDLE *handle) -+{ -+ iounmap ((void *) ptr); -+} -+ -+unsigned long -+elan4_resource_len (ELAN4_DEV *dev, unsigned bar) -+{ -+ return (pci_resource_len (dev->dev_osdep.pdev, bar)); -+} -+ -+void -+elan4_configure_mtrr (ELAN4_DEV *dev) -+{ -+#ifdef CONFIG_MTRR -+ if (! (dev->dev_features & ELAN4_FEATURE_NO_WRITE_COMBINE)) -+ { -+ /* try and initialise the MTRR registers to enable write-combining */ -+ dev->dev_osdep.sdram_mtrr = mtrr_add (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM), -+ pci_resource_len (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM), -+ MTRR_TYPE_WRCOMB, 1); -+ if (dev->dev_osdep.sdram_mtrr < 0) -+ printk ("elan%d: cannot configure MTRR for sdram\n", dev->dev_instance); -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVB) -+ { -+ dev->dev_osdep.regs_mtrr = mtrr_add (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS) + -+ (dev->dev_cqoffset + dev->dev_cqreorder) * CQ_CommandMappingSize, -+ CQ_CommandMappingSize * (dev->dev_cqcount >> 1), -+ MTRR_TYPE_WRCOMB, 1); -+ -+ if (dev->dev_osdep.regs_mtrr < 0) -+ printk ("elan%d: cannot configure MTRR for command ports\n", dev->dev_instance); -+ } -+ } -+#endif -+} -+ -+void -+elan4_unconfigure_mtrr (ELAN4_DEV *dev) -+{ -+#ifdef CONFIG_MTRR -+ if (! (dev->dev_features & ELAN4_FEATURE_NO_WRITE_COMBINE)) -+ { -+ if (dev->dev_osdep.sdram_mtrr >=0 ) -+ mtrr_del (dev->dev_osdep.sdram_mtrr, pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM), -+ pci_resource_len (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVB && dev->dev_osdep.regs_mtrr >= 0) -+ mtrr_del (dev->dev_osdep.regs_mtrr, -+ pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS) + -+ (dev->dev_cqoffset + dev->dev_cqreorder) * CQ_CommandMappingSize, -+ CQ_CommandMappingSize * (dev->dev_cqcount >> 1)); -+ } -+#endif -+} -+ -+EXPORT_SYMBOL(elan4_reference_device); -+EXPORT_SYMBOL(elan4_dereference_device); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/i2c.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/i2c.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/i2c.c 2005-06-01 23:12:54.607437888 -0400 -@@ -0,0 +1,248 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: i2c.c,v 1.4 2004/01/07 13:37:45 jon Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/i2c.c,v $*/ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define I2C_POLL_LIMIT 8 -+ -+static int -+i2c_poll_busy (ELAN4_DEV *dev) -+{ -+ int t = 100; -+ int loop = 0; -+ volatile unsigned char val; -+ -+ /* wait for any led I2C operation to finish */ -+ while (((val = read_i2c (dev, I2cPortControl)) & I2cCntl_I2cPortBusy) && loop++ < I2C_POLL_LIMIT) -+ { -+ DELAY (t); -+ -+ if (t < 500000) -+ t <<= 1; -+ } -+ if (loop >= I2C_POLL_LIMIT) -+ { -+ printk ("elan%d: I2c has timed out waiting for I2cPortBusy to clear!\n", dev->dev_instance); -+ printk ("elan%d: I2cPortControl=%x I2cLedBase=%x I2cStatus=%x\n", -+ dev->dev_instance, val, read_i2c (dev, I2cLedBase), read_i2c (dev, I2cStatus)); -+ } -+ -+ return val; -+} -+ -+static int -+i2c_poll_stopped (ELAN4_DEV *dev) -+{ -+ int t = 100; -+ int loop = 0; -+ unsigned char val=0, newval; -+ -+ /* wait for any led I2C operation to finish. Must see it stopped at least twice */ -+ while (!(((newval = read_i2c (dev, I2cPortControl)) & I2cCntl_I2cStopped) && -+ (val & I2cCntl_I2cStopped)) && -+ (loop++ < I2C_POLL_LIMIT)) -+ { -+ DELAY (t); -+ -+ if (t < 500000) -+ t <<= 1; -+ val = newval; -+ } -+ -+ return val; -+} -+ -+int -+i2c_disable_auto_led_update (ELAN4_DEV *dev) -+{ -+ spin_lock (&dev->dev_i2c_lock); -+ -+ if (dev->dev_i2c_led_disabled++ == 0) -+ { -+ write_i2c (dev, I2cLedBase, read_i2c (dev, I2cLedBase) & ~I2cCntl_I2cUpdatingLedReg); -+ -+ if (! (i2c_poll_stopped (dev) & I2cCntl_I2cStopped)) -+ { -+ write_i2c (dev, I2cLedBase, read_i2c (dev, I2cLedBase) | I2cCntl_I2cUpdatingLedReg); -+ -+ spin_unlock (&dev->dev_i2c_lock); -+ -+ return -EAGAIN; -+ } -+ -+ write_i2c (dev, I2cStatus, read_i2c (dev, I2cStatus) & ~I2cCntl_SampleNewLedValues); -+ } -+ -+ spin_unlock (&dev->dev_i2c_lock); -+ -+ return 0; -+} -+ -+void -+i2c_enable_auto_led_update (ELAN4_DEV *dev) -+{ -+ spin_lock (&dev->dev_i2c_lock); -+ if (--dev->dev_i2c_led_disabled == 0) -+ { -+ write_i2c (dev, I2cLedBase, read_i2c (dev, I2cLedBase) | I2cCntl_I2cUpdatingLedReg); -+ write_i2c (dev, I2cStatus, read_i2c (dev, I2cStatus) | I2cCntl_SampleNewLedValues); -+ } -+ -+ spin_unlock (&dev->dev_i2c_lock); -+} -+ -+int -+i2c_write (ELAN4_DEV *dev, unsigned int address, unsigned int count, unsigned char *data) -+{ -+ int i; -+ -+ if (! (i2c_poll_busy (dev) & I2cCntl_I2cStopped)) -+ return -EAGAIN; -+ -+ write_i2c (dev, I2cWrData, I2C_WRITE_ADDR(address)); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ return -ENXIO; -+ -+ for (i = 0; i < count; i++) -+ { -+ write_i2c (dev, I2cWrData, data[i]); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite | (i == (count-1) ? I2cCntl_I2cPortGenStopBit : 0)); -+ } -+ -+ return 0; -+} -+ -+int -+i2c_read (ELAN4_DEV *dev, unsigned int address, unsigned int count, unsigned char *data) -+{ -+ int i; -+ -+ if (! (i2c_poll_busy (dev) & I2cCntl_I2cStopped)) -+ return -EAGAIN; /* not idle */ -+ -+ write_i2c (dev, I2cWrData, I2C_READ_ADDR(address)); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ return -ENXIO; -+ -+ for (i = 0; i < count; i++) -+ { -+ write_i2c (dev, I2cWrData, 0xff); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortRead | ((i == count-1) ? I2cCntl_I2cPortGenStopBit : 0)); -+ -+ i2c_poll_busy (dev); -+ -+ data[i] = read_i2c (dev, I2cRdData); -+ } -+ -+ return 0; -+} -+ -+int -+i2c_writereg (ELAN4_DEV *dev, unsigned int address, unsigned int reg, unsigned int count, unsigned char *data) -+{ -+ int i; -+ -+ if (! (i2c_poll_busy (dev) & I2cCntl_I2cStopped)) -+ return -EAGAIN; /* not idle */ -+ -+ write_i2c (dev, I2cWrData, I2C_WRITE_ADDR(address)); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ return -ENXIO; -+ -+ write_i2c (dev, I2cWrData, reg); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ return -ENXIO; -+ -+ for (i = 0; i < count; i++) -+ { -+ write_i2c (dev, I2cWrData, data[i]); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite | ((i == count-1) ? I2cCntl_I2cPortGenStopBit : 0)); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ printk (" i2c_writereg: off %d failed\n", i); -+ } -+ -+ return 0; -+} -+ -+int -+i2c_readreg (ELAN4_DEV *dev, unsigned int address, unsigned int reg, unsigned int count, unsigned char *data) -+{ -+ if (! (i2c_poll_busy (dev) & I2cCntl_I2cStopped)) -+ return -EAGAIN; /* not idle */ -+ -+ write_i2c (dev, I2cWrData, I2C_WRITE_ADDR(address)); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ return -ENXIO; -+ -+ write_i2c (dev, I2cWrData, reg); -+ write_i2c (dev, I2cPortControl, I2cCntl_I2cPortWrite | I2cCntl_I2cPortGenStopBit); -+ -+ if (i2c_poll_busy (dev) & I2cCntl_I2cPortAccFailed) -+ return -ENXIO; -+ -+ return i2c_read (dev, address, count, data); -+} -+ -+int -+i2c_read_rom (ELAN4_DEV *dev, unsigned int addr, unsigned int len, unsigned char *data) -+{ -+ unsigned int top = addr + len; -+ int res; -+ -+ if ((res = i2c_disable_auto_led_update (dev)) == 0) -+ { -+ /* read the rom in chunks that don't span the block boundary */ -+ while (addr < top) -+ { -+ unsigned int thisnob = top - addr; -+ unsigned int blocknob = I2C_24LC16B_BLOCKSIZE - I2C_24LC16B_BLOCKOFFSET(addr); -+ -+ if (thisnob > blocknob) -+ thisnob = blocknob; -+ -+ if ((res = i2c_readreg (dev, I2C_EEPROM_ADDR + I2C_24LC16B_BLOCKADDR(addr), -+ I2C_24LC16B_BLOCKOFFSET(addr), thisnob, data)) < 0) -+ break; -+ -+ addr += thisnob; -+ data += thisnob; -+ } -+ -+ i2c_enable_auto_led_update (dev); -+ } -+ return res; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/intcookie.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/intcookie.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/intcookie.c 2005-06-01 23:12:54.608437736 -0400 -@@ -0,0 +1,371 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: intcookie.c,v 1.14 2004/08/09 14:02:37 daniel Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/intcookie.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+static INTCOOKIE_TABLE *intcookie_tables; -+static spinlock_t intcookie_table_lock; -+ -+/* -+ * intcookie_drop_entry: -+ * drop the reference to a cookie held -+ * by the cookie table -+ */ -+static void -+intcookie_drop_entry (INTCOOKIE_ENTRY *ent) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&ent->ent_lock, flags); -+ if (--ent->ent_ref != 0) -+ { -+ ent->ent_fired = ent->ent_cookie; -+ kcondvar_wakeupall (&ent->ent_wait, &ent->ent_lock); -+ -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ } -+ else -+ { -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ -+ spin_lock_destroy (&ent->ent_lock); -+ kcondvar_destroy (&ent->ent_wait); -+ -+ KMEM_FREE (ent, sizeof (INTCOOKIE_ENTRY)); -+ } -+} -+ -+void -+intcookie_init() -+{ -+ spin_lock_init (&intcookie_table_lock); -+} -+ -+void -+intcookie_fini() -+{ -+ spin_lock_destroy (&intcookie_table_lock); -+} -+ -+INTCOOKIE_TABLE * -+intcookie_alloc_table (ELAN_CAPABILITY *cap) -+{ -+ INTCOOKIE_TABLE *tbl, *ntbl; -+ ELAN_CAPABILITY *ncap; -+ -+ KMEM_ZALLOC (ntbl, INTCOOKIE_TABLE *, sizeof (INTCOOKIE_TABLE), 1); -+ -+ if (ntbl == NULL) -+ return (NULL); -+ -+ KMEM_ALLOC (ncap, ELAN_CAPABILITY *, ELAN_CAP_SIZE(cap), 1); -+ -+ if (ncap == NULL) -+ { -+ KMEM_FREE (ntbl, sizeof (INTCOOKIE_TABLE)); -+ return (NULL); -+ } -+ -+ spin_lock (&intcookie_table_lock); -+ -+ for (tbl = intcookie_tables; tbl; tbl = tbl->tbl_next) -+ if (ELAN_CAP_MATCH (tbl->tbl_cap, cap) && tbl->tbl_cap->cap_mycontext == cap->cap_mycontext) -+ break; -+ -+ if (tbl != NULL) -+ tbl->tbl_ref++; -+ else -+ { -+ spin_lock_init (&ntbl->tbl_lock); -+ -+ ntbl->tbl_cap = ncap; -+ ntbl->tbl_ref = 1; -+ ntbl->tbl_entries = NULL; -+ -+ /* Save supplied cap */ -+ bcopy (cap, ncap, ELAN_CAP_SIZE(cap)); -+ -+ if ((ntbl->tbl_next = intcookie_tables) != NULL) -+ intcookie_tables->tbl_prev = ntbl; -+ intcookie_tables = ntbl; -+ ntbl->tbl_prev = NULL; -+ } -+ spin_unlock (&intcookie_table_lock); -+ -+ if (tbl == NULL) -+ return (ntbl); -+ else -+ { -+ KMEM_FREE (ntbl, sizeof (INTCOOKIE_TABLE)); -+ KMEM_FREE (ncap, ELAN_CAP_SIZE(cap)); -+ return (tbl); -+ } -+} -+ -+void -+intcookie_free_table (INTCOOKIE_TABLE *tbl) -+{ -+ INTCOOKIE_ENTRY *ent; -+ -+ spin_lock (&intcookie_table_lock); -+ if (tbl->tbl_ref > 1) -+ { -+ tbl->tbl_ref--; -+ spin_unlock (&intcookie_table_lock); -+ return; -+ } -+ -+ if (tbl->tbl_prev) -+ tbl->tbl_prev->tbl_next = tbl->tbl_next; -+ else -+ intcookie_tables = tbl->tbl_next; -+ if (tbl->tbl_next) -+ tbl->tbl_next->tbl_prev = tbl->tbl_prev; -+ -+ spin_unlock (&intcookie_table_lock); -+ -+ /* NOTE - table no longer visible to other threads -+ * no need to aquire tbl_lock */ -+ while ((ent = tbl->tbl_entries) != NULL) -+ { -+ if ((tbl->tbl_entries = ent->ent_next) != NULL) -+ ent->ent_next->ent_prev = NULL; -+ -+ intcookie_drop_entry (ent); -+ } -+ spin_lock_destroy (&tbl->tbl_lock); -+ -+ KMEM_FREE (tbl->tbl_cap, ELAN_CAP_SIZE(tbl->tbl_cap)); -+ KMEM_FREE (tbl, sizeof (INTCOOKIE_TABLE)); -+} -+ -+int -+intcookie_alloc (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie) -+{ -+ INTCOOKIE_ENTRY *ent, *nent; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (nent, INTCOOKIE_ENTRY *, sizeof (INTCOOKIE_ENTRY), 1); -+ -+ if (nent == NULL) -+ return (-ENOMEM); -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ kcondvar_init (&nent->ent_wait); -+ spin_lock_init (&nent->ent_lock); -+ -+ nent->ent_ref = 1; -+ nent->ent_cookie = cookie; -+ -+ if ((nent->ent_next = tbl->tbl_entries) != NULL) -+ tbl->tbl_entries->ent_prev = nent; -+ tbl->tbl_entries = nent; -+ nent->ent_prev = NULL; -+ } -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ if (ent == NULL) -+ return (0); -+ else -+ { -+ KMEM_FREE (nent, sizeof (INTCOOKIE_ENTRY)); -+ return (-EINVAL); -+ } -+} -+ -+int -+intcookie_free (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie) -+{ -+ INTCOOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (-EINVAL); -+ } -+ -+ if (ent->ent_prev == NULL) -+ tbl->tbl_entries = ent->ent_next; -+ else -+ ent->ent_prev->ent_next = ent->ent_next; -+ -+ if (ent->ent_next != NULL) -+ ent->ent_next->ent_prev = ent->ent_prev; -+ -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ intcookie_drop_entry (ent); -+ -+ return (0); -+} -+ -+/* -+ * intcookie_fire_cookie: -+ * fire the cookie - this is called from the event interrupt. -+ */ -+int -+intcookie_fire (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie) -+{ -+ INTCOOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (-EINVAL); -+ } -+ -+ spin_lock (&ent->ent_lock); -+ ent->ent_fired = cookie; -+ kcondvar_wakeupall (&ent->ent_wait, &ent->ent_lock); -+ spin_unlock (&ent->ent_lock); -+ -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ return (0); -+} -+ -+int -+intcookie_fire_cap (ELAN_CAPABILITY *cap, ELAN4_INTCOOKIE cookie) -+{ -+ int res; -+ INTCOOKIE_TABLE *tbl; -+ -+ spin_lock (&intcookie_table_lock); -+ -+ for (tbl = intcookie_tables; tbl; tbl = tbl->tbl_next) -+ if (ELAN_CAP_MATCH (tbl->tbl_cap, cap) && tbl->tbl_cap->cap_mycontext == cap->cap_mycontext) -+ break; -+ -+ if (tbl != NULL) -+ tbl->tbl_ref++; -+ -+ spin_unlock (&intcookie_table_lock); -+ -+ /* No matching table found */ -+ if (tbl == NULL) -+ return (-EINVAL); -+ -+ /* Fire the correct cookie */ -+ res = intcookie_fire (tbl, cookie); -+ -+ /* Decrement reference count (and free if necessary) */ -+ intcookie_free_table (tbl); -+ -+ return (res); -+} -+ -+/* -+ * intcookie_wait_cookie: -+ * deschedule on a cookie if it has not already fired. -+ * note - if the cookie is removed from the table, then -+ * we free it off when we're woken up. -+ */ -+int -+intcookie_wait (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie) -+{ -+ INTCOOKIE_ENTRY *ent; -+ unsigned long flags; -+ int res; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (-EINVAL); -+ } -+ -+ spin_lock (&ent->ent_lock); -+ spin_unlock (&tbl->tbl_lock); -+ -+ if (ent->ent_fired != 0) -+ { -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ return (0); -+ } -+ -+ ent->ent_ref++; -+ kcondvar_waitsig (&ent->ent_wait, &ent->ent_lock, &flags); -+ -+ res = ent->ent_fired ? 0 : -EINTR; -+ -+ if (--ent->ent_ref > 0) -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ else -+ { -+ spin_unlock_irqrestore (&ent->ent_lock, flags); -+ -+ spin_lock_destroy (&ent->ent_lock); -+ kcondvar_destroy (&ent->ent_wait); -+ -+ KMEM_FREE (ent, sizeof (INTCOOKIE_ENTRY)); -+ } -+ -+ return (res); -+} -+ -+int -+intcookie_arm (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie) -+{ -+ INTCOOKIE_ENTRY *ent; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&tbl->tbl_lock, flags); -+ for (ent = tbl->tbl_entries; ent; ent = ent->ent_next) -+ if (ent->ent_cookie == cookie) -+ break; -+ -+ if (ent == NULL) -+ { -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ return (-EINVAL); -+ } -+ -+ spin_lock (&ent->ent_lock); -+ ent->ent_fired = 0; -+ spin_unlock (&ent->ent_lock); -+ -+ spin_unlock_irqrestore (&tbl->tbl_lock, flags); -+ -+ return (0); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/Makefile 2005-06-01 23:12:54.608437736 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/elan4/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/elan4/Makefile -+# -+ -+list-multi := elan4.o -+elan4-objs := device.o i2c.o mmu.o sdram.o debug.o routetable.o trap.o user.o user_ddcq.o regions.o intcookie.o neterr.o device_Linux.o user_Linux.o procfs_Linux.o mmu_Linux.o -+export-objs := device.o device_Linux.o mmu.o mmu_Linux.o procfs_Linux.o routetable.o sdram.o trap.o -+obj-$(CONFIG_ELAN4) := elan4.o -+ -+elan4.o : $(elan4-objs) -+ $(LD) -r -o $@ $(elan4-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/elan4/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/Makefile.conf 2005-06-01 23:12:54.608437736 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = elan4.o -+MODULENAME = elan4 -+KOBJFILES = device.o i2c.o mmu.o sdram.o debug.o routetable.o trap.o user.o user_ddcq.o regions.o intcookie.o neterr.o device_Linux.o user_Linux.o procfs_Linux.o mmu_Linux.o -+EXPORT_KOBJS = device.o device_Linux.o mmu.o mmu_Linux.o procfs_Linux.o routetable.o sdram.o trap.o -+CONFIG_NAME = CONFIG_ELAN4 -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/elan4/mmu.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/mmu.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/mmu.c 2005-06-01 23:12:54.610437432 -0400 -@@ -0,0 +1,854 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: mmu.c,v 1.29.6.2 2005/01/18 16:58:12 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/mmu.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+ -+int elan4_debug_mmu; -+ -+/* Permission table - see ELAN4 MMU documentation */ -+u_char elan4_permtable[] = -+{ -+ 0x00, /* 0x000000 - Disable */ -+ 0x00, /* 0x000000 - Unused */ -+ 0x01, /* 0x000001 - Local Data Read */ -+ 0x03, /* 0x000011 - Local Data Write */ -+ 0x11, /* 0x010001 - Local Read */ -+ 0x10, /* 0x010000 - Local Execute */ -+ 0x05, /* 0x000101 - Read Only */ -+ 0x13, /* 0x010011 - Local Write */ -+ 0x20, /* 0x100000 - Local Event Access */ -+ 0x23, /* 0x100011 - Local Event Write Ac */ -+ 0xa3, /* 1x100011 - Remote Ev Loc Write */ -+ 0xaf, /* 1x101111 - Remote All */ -+ 0x07, /* 0x000111 - Remote Read Only */ -+ 0x0d, /* 0x001101 - Remote Write Only */ -+ 0x0f, /* 0x001111 - Remote Read/Write */ -+ 0xbf, /* 1x111111 - No Fault */ -+}; -+ -+u_char elan4_permreadonly[] = -+{ -+ PERM_Disabled, /* PERM_Disabled */ -+ PERM_Disabled, /* PERM_Unused */ -+ PERM_LocDataRead, /* PERM_LocDataRead */ -+ PERM_LocDataRead, /* PERM_LocDataWrite */ -+ PERM_LocRead, /* PERM_LocRead */ -+ PERM_LocExecute, /* PERM_LocExecute */ -+ PERM_ReadOnly, /* PERM_ReadOnly */ -+ PERM_LocRead, /* PERM_LocWrite */ -+ PERM_LocEventOnly, /* PERM_LocEventOnly */ -+ PERM_LocDataRead, /* PERM_LocEventWrite */ -+ PERM_LocDataRead, /* PERM_RemoteEvent */ -+ PERM_ReadOnly, /* PERM_RemoteAll */ -+ PERM_RemoteReadOnly, /* PERM_RemoteReadOnly */ -+ PERM_ReadOnly, /* PERM_RemoteWriteLocRead */ -+ PERM_ReadOnly, /* PERM_DataReadWrite */ -+ PERM_ReadOnly, /* PERM_NoFault */ -+}; -+ -+static void -+elan4mmu_synctag (ELAN4_DEV *dev, ELAN4_HASH_ENTRY *he, int tagidx) -+{ -+ E4_uint64 value = (he->he_tag[tagidx] & HE_TAG_VALID) ? he->he_tag[tagidx] & (TAG_ADDRESS_MASK | TAG_CONTEXT_MASK) : INVALID_CONTEXT; -+ -+ if (he->he_next) -+ value |= ((tagidx == 0) ? -+ ((he->he_next->he_entry >> TAG_CHAINPTR_HIGH_SHIFT) & TAG_CHAINPTR_30TO19_MASK) : -+ ((he->he_next->he_entry << TAG_CHAINPTR_LOW_SHIFT) & TAG_CHAINPTR_18TO6_MASK)); -+ else if (tagidx == 0) -+ value |= TAG_CHAINPTR_30TO19_MASK; -+ -+ MPRINTF (DBG_DEVICE, 4, "elan4mmu_synctag: he=%p tagidx=%d he->he_tag=%llx -> value=%llx\n", he, tagidx, he->he_tag[tagidx], value); -+ -+ elan4_sdram_writeq (dev, he->he_entry + E4MMU_TAG_OFFSET(tagidx), value); -+} -+ -+static void -+elan4mmu_chain_hents (ELAN4_DEV *dev, ELAN4_HASH_ENTRY *phe, ELAN4_HASH_ENTRY *he) -+{ -+ ASSERT ((elan4_sdram_readq (dev, phe->he_entry + E4MMU_TAG_OFFSET(0)) & TAG_CHAINPTR_30TO19_MASK) == TAG_CHAINPTR_30TO19_MASK); -+ -+ elan4_sdram_writeq (dev, phe->he_entry + E4MMU_TAG_OFFSET(1), -+ ((phe->he_tag[1] & (TAG_ADDRESS_MASK | TAG_CONTEXT_MASK)) | ((he->he_entry << TAG_CHAINPTR_LOW_SHIFT) & TAG_CHAINPTR_18TO6_MASK))); -+ elan4_sdram_writeq (dev, phe->he_entry + E4MMU_TAG_OFFSET(0), -+ ((phe->he_tag[0] & (TAG_ADDRESS_MASK | TAG_CONTEXT_MASK)) | ((he->he_entry >> TAG_CHAINPTR_HIGH_SHIFT) & TAG_CHAINPTR_30TO19_MASK))); -+} -+ -+static void -+elan4mmu_writepte (ELAN4_DEV *dev, ELAN4_HASH_ENTRY *he, int tagidx, int pteidx, E4_uint64 value) -+{ -+ /* -+ * NOTE - we can only change a valid PTE if we're upgrading it's permissions, -+ * any other changes should have invalidated it first. */ -+ -+ MPRINTF (DBG_DEVICE, 4, "elan4mmu_writepte: he=%p tagidx=%d pteidx=%x value=%llx\n", he, tagidx, pteidx, (unsigned long long) value); -+ -+ if (pteidx == 3) -+ { -+ elan4_sdram_writew (dev, he->he_entry + E4MMU_PTE3_WORD1_OFFSET(tagidx), (value >> 16) & 0xFFFF); -+ elan4_sdram_writew (dev, he->he_entry + E4MMU_PTE3_WORD2_OFFSET(tagidx), (value >> 32) & 0xFFFF); -+ elan4_sdram_writew (dev, he->he_entry + E4MMU_PTE3_WORD0_OFFSET(tagidx), (value >> 0) & 0xFFFF); -+ } -+ else -+ { -+ elan4_sdram_writew (dev, he->he_entry + E4MMU_PTE_HIGH_OFFSET(tagidx, pteidx), (value >> 32) & 0xFFFF); -+ elan4_sdram_writel (dev, he->he_entry + E4MMU_PTE_LOW_OFFSET(tagidx, pteidx), value & 0xFFFFFFFF); -+ } -+} -+ -+static void -+elan4mmu_invalidatepte (ELAN4_DEV *dev, ELAN4_HASH_ENTRY *he, int tagidx, int pteidx) -+{ -+ if (pteidx == 3) -+ elan4_sdram_writeb (dev, he->he_entry + E4MMU_PTE3_WORD0_OFFSET(tagidx), PTE_SetPerm (PERM_Disabled)); -+ else -+ elan4_sdram_writeb (dev, he->he_entry + E4MMU_PTE_LOW_OFFSET(tagidx, pteidx), PTE_SetPerm (PERM_Disabled)); -+} -+ -+static E4_uint64 -+elan4mmu_readpte (ELAN4_DEV *dev, ELAN4_HASH_ENTRY *he, int tagidx, int pteidx) -+{ -+ if (pteidx == 3) -+ return (((E4_uint64) elan4_sdram_readw (dev, he->he_entry + E4MMU_PTE3_WORD0_OFFSET(tagidx)) << 0) | -+ ((E4_uint64) elan4_sdram_readw (dev, he->he_entry + E4MMU_PTE3_WORD1_OFFSET(tagidx)) << 16) | -+ ((E4_uint64) elan4_sdram_readw (dev, he->he_entry + E4MMU_PTE3_WORD2_OFFSET(tagidx)) << 32)); -+ else -+ return ((E4_uint64) elan4_sdram_readl (dev, he->he_entry + E4MMU_PTE_LOW_OFFSET(tagidx, pteidx)) | -+ ((E4_uint64) elan4_sdram_readw (dev, he->he_entry + E4MMU_PTE_HIGH_OFFSET(tagidx, pteidx)) << 32)); -+} -+ -+ -+void -+elan4mmu_flush_tlb (ELAN4_DEV *dev) -+{ -+ PULSE_SYSCONTROL (dev, CONT_TLB_FLUSH); -+ -+ while (read_reg64 (dev, SysControlReg) & CONT_TLB_FLUSH) -+ DELAY (1); -+} -+ -+/* -+ * elanmmu_flush_tlb_hash - this flushes the hash copy entries and the elan -+ * tlb. However after the write to the hash copy entry if the elan was -+ * in the process of walking, then it could write the hash copy with a valid -+ * entry which we had just invalidated. However once we've seen the tlb flushed -+ * then if the walk engine had done a write - then we need to invaldate the -+ * hash copy entries again and reflush the tlb. -+ * -+ * If we're invalidating a lot of hash blocks, then the chances are that the -+ * walk engine will perform a write - so we flush the tlb first, then invalidate -+ * the hash copy entries, then flush the tlb again. -+ */ -+static void -+elan4mmu_flush_tlb_hash (ELAN4_DEV *dev, int tbl, unsigned baseidx, unsigned topidx) -+{ -+ int notmany = (abs(topidx - baseidx) < 5) ? 1 : 0; -+ int hashidx; -+ E4_uint32 reg; -+ -+ if (notmany) -+ PULSE_SYSCONTROL (dev, CONT_CLEAR_WALK_WROTE_TABLES); -+ else -+ elan4mmu_flush_tlb(dev); -+ -+ do { -+ for (hashidx = baseidx; hashidx <= topidx; hashidx++) -+ if (dev->dev_mmuhash[tbl][hashidx].he_tag[0] & HE_TAG_COPY) -+ { -+ ASSERT ((dev->dev_mmuhash[tbl][hashidx].he_tag[0] & HE_TAG_VALID) == 0); -+ ASSERT ((dev->dev_mmuhash[tbl][hashidx].he_tag[1] & HE_TAG_VALID) == 0); -+ -+ elan4mmu_synctag (dev, &dev->dev_mmuhash[tbl][hashidx], 0); -+ elan4mmu_synctag (dev, &dev->dev_mmuhash[tbl][hashidx], 1); -+ } -+ -+ PULSE_SYSCONTROL (dev, CONT_TLB_FLUSH); -+ -+ while ((reg = read_reg64 (dev, SysControlReg)) & CONT_TLB_FLUSH) -+ DELAY (1); -+ -+ } while (notmany-- && (reg & CONT_CLEAR_WALK_WROTE_TABLES) != 0); -+} -+ -+void -+elan4mmu_display_hent (ELAN4_DEV *dev, ELAN4_HASH_ENTRY *he, int hashidx) -+{ -+ int tagidx; -+ -+ elan4_debugf (DBG_DEVICE, DBG_MMU, "elan4mmu_display_hent: hashidx=%d he=%p entry at %lx\n", hashidx, he, he->he_entry); -+ elan4_debugf (DBG_DEVICE, DBG_MMU, " next=%p prev=%p chain=%p,%p\n", he->he_next, he->he_prev, he->he_chain[0], he->he_chain[1]); -+ for (tagidx = 0; tagidx < 2; tagidx++) -+ { -+ E4_uint64 tag = elan4_sdram_readq (dev, he->he_entry + E4MMU_TAG_OFFSET(tagidx)); -+ E4_uint64 pte0 = elan4_sdram_readq (dev, he->he_entry + E4MMU_PTE_LOW_OFFSET(tagidx, 0)); -+ E4_uint64 pte1 = elan4_sdram_readq (dev, he->he_entry + E4MMU_PTE_LOW_OFFSET(tagidx, 1)); -+ E4_uint64 pte2 = elan4_sdram_readq (dev, he->he_entry + E4MMU_PTE_LOW_OFFSET(tagidx, 2)); -+ E4_uint64 pte3 = ((pte0 >> 48) | (pte1 >> 32) | (pte2 >> 16)); -+ -+ elan4_debugf (DBG_DEVICE, DBG_MMU, " Tag %d (%llx,%08x) context=%04x vaddr=%llx\n", tagidx, he->he_tag[tagidx], he->he_pte[tagidx], (int) (tag & TAG_CONTEXT_MASK), (tag & TAG_ADDRESS_MASK)); -+ elan4_debugf (DBG_DEVICE, DBG_MMU, " Pte 0 - PPN=%llx PERM=%x TYPE=%x%s%s\n", (pte0 & PTE_PPN_MASK) >> PTE_PPN_SHIFT, -+ (int) (pte0 & PTE_PERM_MASK) >> PTE_PERM_SHIFT, (int)(pte0 & PTE_TYPE_MASK), (pte0 & PTE_MOD_MASK) ? " mod" : "", (pte0 & PTE_REF_MASK) ? " ref" : ""); -+ elan4_debugf (DBG_DEVICE, DBG_MMU, " Pte 1 - PPN=%llx PERM=%x TYPE=%x%s%s\n", (pte1 & PTE_PPN_MASK) >> PTE_PPN_SHIFT, -+ (int) (pte1 & PTE_PERM_MASK) >> PTE_PERM_SHIFT, (int)(pte1 & PTE_TYPE_MASK), (pte1 & PTE_MOD_MASK) ? " mod" : "", (pte1 & PTE_REF_MASK) ? " ref" : ""); -+ elan4_debugf (DBG_DEVICE, DBG_MMU, " Pte 2 - PPN=%llx PERM=%x TYPE=%x%s%s\n", (pte2 & PTE_PPN_MASK) >> PTE_PPN_SHIFT, -+ (int) (pte2 & PTE_PERM_MASK) >> PTE_PERM_SHIFT, (int)(pte2 & PTE_TYPE_MASK), (pte2 & PTE_MOD_MASK) ? " mod" : "", (pte2 & PTE_REF_MASK) ? " ref" : ""); -+ elan4_debugf (DBG_DEVICE, DBG_MMU, " Pte 3 - PPN=%llx PERM=%x TYPE=%x%s%s\n", (pte3 & PTE_PPN_MASK) >> PTE_PPN_SHIFT, -+ (int) (pte3 & PTE_PERM_MASK) >> PTE_PERM_SHIFT, (int)(pte3 & PTE_TYPE_MASK), (pte3 & PTE_MOD_MASK) ? " mod" : "", (pte3 & PTE_REF_MASK) ? " ref" : ""); -+ } -+} -+ -+static __inline__ ELAN4_HASH_ENTRY * -+he_ctxt_next (ELAN4_HASH_ENTRY *he, int ctxnum) -+{ -+ return ((he->he_tag[0] & TAG_CONTEXT_MASK) == ctxnum) ? he->he_chain[0] : he->he_chain[1]; -+} -+ -+static __inline__ ELAN4_HASH_ENTRY * -+he_ctxt_unlink (ELAN4_CTXT *ctxt, int tbl, int hashidx, ELAN4_HASH_ENTRY *prevhe, ELAN4_HASH_ENTRY *he, ELAN4_HASH_ENTRY *next) -+{ -+ /* Check whether either tag is in use by this context */ -+ if ((he->he_tag[0] & TAG_CONTEXT_MASK) == ctxt->ctxt_num || (he->he_tag[1] & TAG_CONTEXT_MASK) == ctxt->ctxt_num) -+ return he; -+ -+ if (prevhe == NULL) -+ ctxt->ctxt_mmuhash[tbl][hashidx] = next; -+ else -+ { -+ /* previous he, ensure that both chain pointers are changed is this ctxt is using both tags */ -+ ASSERT ((prevhe->he_tag[0] & TAG_CONTEXT_MASK) == ctxt->ctxt_num || (prevhe->he_tag[1] & TAG_CONTEXT_MASK) == ctxt->ctxt_num); -+ -+ if ((prevhe->he_tag[0] & TAG_CONTEXT_MASK) == ctxt->ctxt_num) -+ prevhe->he_chain[0] = next; -+ if ((prevhe->he_tag[1] & TAG_CONTEXT_MASK) == ctxt->ctxt_num) -+ prevhe->he_chain[1] = next; -+ } -+ -+ return prevhe; -+} -+ -+void -+elan4mmu_display (ELAN4_CTXT *ctxt, int tbl, const char *tag) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ ELAN4_HASH_ENTRY *he; -+ int hashidx; -+ -+ for (hashidx = 0; hashidx < dev->dev_hashsize[tbl]; hashidx++) -+ for (he = ctxt->ctxt_mmuhash[tbl][hashidx]; he != NULL; he = he_ctxt_next (he, ctxt->ctxt_num)) -+ { -+ elan4_debugf (DBG_DEVICE, DBG_MMU, "%s: hashidx=%d he=%p tags <%llx,%llx>\n", tag, hashidx, he, -+ (he->he_tag[0] & TAG_CONTEXT_MASK) == ctxt->ctxt_num ? E4MMU_TAG2VADDR (he->he_tag[0], hashidx, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1) : 0, -+ (he->he_tag[1] & TAG_CONTEXT_MASK) == ctxt->ctxt_num ? E4MMU_TAG2VADDR (he->he_tag[1], hashidx, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1) : 0); -+ elan4mmu_display_hent (dev, he, hashidx); -+ } -+} -+ -+static ELAN4_HASH_ENTRY * -+elan4mmu_alloc_hent (ELAN4_DEV *dev, int tbl, int hashidx, E4_uint64 newtag, int *tagidx) -+{ -+ ELAN4_HASH_ENTRY *he, *phe; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&dev->dev_mmulock, flags); -+ -+ /* 2nd see if there are any partial free blocks */ -+ if ((he = dev->dev_mmufree[tbl][hashidx]) != NULL) -+ { -+ *tagidx = ((he->he_tag[0] & TAG_CONTEXT_MASK) == INVALID_CONTEXT) ? 0 : 1; -+ -+ MPRINTF (DBG_DEVICE, 3, "elan4mmu_alloc_hent: allocate he=%p idx=%d%s\n", he, *tagidx, (he == &dev->dev_mmuhash[tbl][hashidx]) ? " hash-block" : ""); -+ -+ he->he_tag[*tagidx] = newtag | HE_TAG_VALID; -+ -+ elan4mmu_synctag (dev, he, *tagidx); -+ -+ if ((he->he_tag[(*tagidx) ^ 1] & TAG_CONTEXT_MASK) != INVALID_CONTEXT) -+ { -+ MPRINTF (DBG_DEVICE, 3, "elan4mmu_alloc_hent: block full - remove from freelist\n"); -+ dev->dev_mmufree[tbl][hashidx] = he->he_chain[*tagidx]; -+ } -+ -+ spin_unlock_irqrestore (&dev->dev_mmulock, flags); -+ return (he); -+ } -+ -+ if ((he = dev->dev_mmufreelist) != NULL) -+ dev->dev_mmufreelist = he->he_next; -+ else -+ { -+ ELAN4_HASH_CHUNK *hc; -+ sdramaddr_t entry; -+ -+ KMEM_ALLOC (hc, ELAN4_HASH_CHUNK *, sizeof (ELAN4_HASH_CHUNK), 0); -+ -+ if (hc == NULL) -+ { -+ spin_unlock_irqrestore (&dev->dev_mmulock, flags); -+ return ((ELAN4_HASH_ENTRY *) NULL); -+ } -+ -+ if ((entry = elan4_sdram_alloc (dev, sizeof (E4_HashTableEntry) * ELAN4_HENT_CHUNKS)) == (sdramaddr_t) 0) -+ { -+ spin_unlock_irqrestore (&dev->dev_mmulock, flags); -+ -+ KMEM_FREE (hc, sizeof (ELAN4_HASH_CHUNK)); -+ return ((ELAN4_HASH_ENTRY *) NULL); -+ } -+ -+ list_add_tail (&hc->hc_link, &dev->dev_hc_list); -+ -+ elan4_sdram_zeroq_sdram (dev, entry, sizeof (E4_HashTableEntry) * ELAN4_HENT_CHUNKS); -+ -+ /* no initialise all chunks and chain all but the first onto the freelist */ -+ for (i = 0; i < ELAN4_HENT_CHUNKS; i++, entry += sizeof (E4_HashTableEntry)) -+ { -+ hc->hc_hents[i].he_entry = entry; -+ -+ if (i == 0) -+ he = &hc->hc_hents[0]; -+ else -+ { -+ hc->hc_hents[i].he_next = dev->dev_mmufreelist; -+ dev->dev_mmufreelist = &hc->hc_hents[i]; -+ } -+ } -+ } -+ -+ /* Initialise hash entry, using slot 0 */ -+ *tagidx = 0; -+ -+ he->he_next = NULL; -+ he->he_prev = NULL; -+ he->he_chain[0] = NULL; -+ he->he_chain[1] = NULL; -+ he->he_tag[0] = newtag | HE_TAG_VALID; -+ he->he_tag[1] = E4MMU_TAG(0, INVALID_CONTEXT); -+ he->he_pte[0] = 0; -+ he->he_pte[1] = 0; -+ -+ elan4mmu_synctag (dev, he, 0); -+ -+ /* add slot 1 to freelist */ -+ he->he_chain[1] = dev->dev_mmufree[tbl][hashidx]; -+ dev->dev_mmufree[tbl][hashidx] = he; -+ -+ /* add to mmuhash lists */ -+ for (phe = &dev->dev_mmuhash[tbl][hashidx]; phe->he_next; phe = phe->he_next) -+ ; -+ phe->he_next = he; -+ he->he_prev = phe; -+ he->he_next = NULL; -+ -+ /* finally chain the hash block into the hash tables */ -+ elan4mmu_chain_hents (dev, phe, he); -+ -+ spin_unlock_irqrestore (&dev->dev_mmulock, flags); -+ return (he); -+} -+ -+static void -+elan4mmu_free_hent (ELAN4_DEV *dev, int tbl, int hashidx, ELAN4_HASH_ENTRY *he, int tagidx) -+{ -+ unsigned long flags; -+ int pteidx; -+ -+ /* Invalidate the tag, and zero all ptes */ -+ for (pteidx = 0; pteidx < 4; pteidx++) -+ if (HE_GET_PTE(he, tagidx, pteidx)) -+ elan4mmu_writepte (dev, he, tagidx, pteidx, 0); -+ -+ spin_lock_irqsave (&dev->dev_mmulock, flags); -+ -+ he->he_tag[tagidx] = E4MMU_TAG(0, INVALID_CONTEXT); -+ he->he_pte[tagidx] = 0; -+ -+ elan4mmu_synctag (dev, he, tagidx); -+ -+ if ((he->he_tag[tagidx^1] & TAG_CONTEXT_MASK) == INVALID_CONTEXT) /* Both tags are now free */ -+ { -+ if (he == &dev->dev_mmuhash[tbl][hashidx]) /* it's the hash block entry */ -+ { /* so as it's already on the freelist */ -+ he->he_chain[tagidx] = he->he_chain[tagidx^1]; /* just copy it's chain pointers */ -+ -+ MPRINTF (DBG_DEVICE, 3, "elan4mmu_free_hent: tbl=%d hashidx=%x tagidx=%d he=%p => all free but hashblk\n", tbl, hashidx, tagidx, he); -+ } -+ else -+ { -+ MPRINTF (DBG_DEVICE, 3, "elan4mmu_free_hent: tbl=%d hashidx=%x tagidx=%d he=%p => all free\n", tbl, hashidx, tagidx, he); -+ -+ /* XXXX - should remove it from the hash table, and -+ * place back on the anonymous freelist */ -+ he->he_chain[tagidx] = he->he_chain[tagidx^1]; -+ } -+ } -+ else -+ { -+ /* Other tag still in use */ -+ he->he_chain[tagidx] = dev->dev_mmufree[tbl][hashidx]; -+ dev->dev_mmufree[tbl][hashidx] = he; -+ -+ MPRINTF (DBG_DEVICE, 3, "elan4mmu_free_hent: tbl=%d hashidx=%x tagidx=%d he=%p => other tag in use\n", tbl, hashidx, tagidx, he); -+ } -+ spin_unlock_irqrestore (&dev->dev_mmulock, flags); -+} -+ -+ELAN4_HASH_ENTRY * -+elan4mmu_ptealloc (ELAN4_CTXT *ctxt, int tbl, E4_Addr vaddr, unsigned int *tagidxp) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned ctxnum = ctxt->ctxt_num; -+ unsigned hashidx = E4MMU_HASH_INDEX (ctxnum, vaddr, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1); -+ E4_uint64 newtag = E4MMU_TAG(vaddr, ctxnum); -+ ELAN4_HASH_ENTRY *he = &dev->dev_mmuhash[tbl][hashidx]; -+ unsigned tagidx; -+ -+ MPRINTF (ctxt, 2, "elan4mmu_ptealloc: tbl=%d ctxnum=%d vaddr=%llx -> hashidx %d\n", tbl, ctxnum, vaddr, hashidx); -+ -+ /* 1st) check whether we're reloading an existing entry */ -+ for (he = ctxt->ctxt_mmuhash[tbl][hashidx]; he != NULL; he = he_ctxt_next (he, ctxnum)) -+ { -+ ASSERT ((he->he_tag[0] & TAG_CONTEXT_MASK) == ctxnum || (he->he_tag[1] & TAG_CONTEXT_MASK) == ctxnum); -+ -+ for (tagidx = 0; tagidx < 2; tagidx++) -+ { -+ if ((he->he_tag[tagidx] & (TAG_ADDRESS_MASK | TAG_CONTEXT_MASK | HE_TAG_VALID)) == (newtag | HE_TAG_VALID)) -+ { -+ MPRINTF (ctxt, 2, "elan4mmu_ptealloc: return old he %p tagidx %d\n", he, tagidx); -+ -+ *tagidxp = tagidx; -+ return he; -+ } -+ } -+ } -+ -+ if ((he = elan4mmu_alloc_hent (dev, tbl, hashidx, newtag, &tagidx)) == NULL) -+ return NULL; -+ -+ /* chain onto context hash */ -+ if ((he->he_tag[tagidx ^ 1] & TAG_CONTEXT_MASK) == ctxnum) /* already chained using other link */ -+ { /* so ensure both slots are chained the same */ -+ he->he_chain[tagidx] = he->he_chain[tagidx^1]; -+ } -+ else -+ { -+ he->he_chain[tagidx] = ctxt->ctxt_mmuhash[tbl][hashidx]; -+ ctxt->ctxt_mmuhash[tbl][hashidx] = he; -+ } -+ -+ MPRINTF (ctxt, 2, "elan4mmu_ptealloc: return new he %p tagidx %d\n", he, tagidx); -+ -+ *tagidxp = tagidx; -+ -+ return he; -+} -+ -+int -+elan4mmu_pteload (ELAN4_CTXT *ctxt, int tbl, E4_Addr vaddr, E4_uint64 newpte) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned pteidx = E4MMU_SHIFT_ADDR(vaddr, dev->dev_pageshift[tbl]) & 3; -+ unsigned tagidx; -+ ELAN4_HASH_ENTRY *he; -+ -+ MPRINTF (ctxt, 0, "elan4mmu_pteload: ctx=%d tbl=%d pteidx=%d vaddr=%llx pte=%llx\n", -+ ctxt->ctxt_num, tbl, pteidx, (unsigned long long)vaddr, newpte); -+ -+ spin_lock (&ctxt->ctxt_mmulock); -+ -+ if ((he = elan4mmu_ptealloc (ctxt, tbl, vaddr, &tagidx)) == NULL) -+ { -+ spin_unlock (&ctxt->ctxt_mmulock); -+ return -ENOMEM; -+ } -+ -+ MPRINTF (ctxt, 1, "elan4mmu_pteload: %s he=%p tagidx=%d pteidx=%d\n", HE_GET_PTE(he,0,pteidx) ? "reloading" : "loading", he, tagidx, pteidx); -+ -+ ASSERT (HE_GET_PTE(he,tagidx,pteidx) == 0 || /* invalid -> valid */ -+ (elan4mmu_readpte (dev, he, tagidx, pteidx) & PTE_PPN_MASK) == (newpte & PTE_PPN_MASK)); /* or same phys address */ -+ -+ elan4mmu_writepte (dev, he, tagidx, pteidx, newpte); -+ -+ HE_SET_PTE(he, tagidx, pteidx, (newpte & PTE_PERM_TYPE_MASK)); -+ -+ spin_unlock (&ctxt->ctxt_mmulock); -+ return 0; -+} -+ -+void -+elan4mmu_unload_range (ELAN4_CTXT *ctxt, int tbl, E4_Addr start, unsigned long len) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned ctxnum = ctxt->ctxt_num; -+ unsigned long tagspan = (1 << (dev->dev_pageshift[tbl] + 2)); -+ E4_Addr end = start + len - 1; -+ int needflush = 0; -+ unsigned baseidx, topidx; -+ unsigned hashidx, tagidx, pteidx; -+ ELAN4_HASH_ENTRY *he, *prevhe, *next; -+ -+ MPRINTF (ctxt, 0, "elan4mmu_unload_range: tbl=%d start=%llx end=%llx len=%lx\n", tbl, start, end, len); -+ -+ /* determine how much of the hash table we've got to scan */ -+ -+ /* GNAT 6760: When we have a Main page size which maps onto multiple Elan pages -+ * we need to do something a bit more clever here or else it takes ms per page invalidate -+ * This change helps in the meantime -+ */ -+ /* if (len <= (1 << dev->dev_pageshift[tbl])) */ -+ if (len <= PAGE_SIZE) -+ { -+ baseidx = E4MMU_HASH_INDEX (ctxnum, start, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1); -+ topidx = E4MMU_HASH_INDEX (ctxnum, end, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1); -+ -+ if (baseidx != topidx) -+ { -+ /* GNAT 6760: Need to search whole of the hash table (slow!) */ -+ baseidx = 0; -+ topidx = dev->dev_hashsize[tbl] - 1; -+ } -+ } -+ else -+ { -+ baseidx = 0; -+ topidx = dev->dev_hashsize[tbl] - 1; -+ } -+ -+ MPRINTF (ctxt, 1, "elan4mmu_unload_range: baseidx=%d topidx=%d\n", baseidx, topidx); -+ -+ spin_lock (&ctxt->ctxt_mmulock); -+ -+ /* 1st - invalidate the tag for all hash blocks which are completely invalidated, -+ * and remember the first/last hash blocks */ -+ for (hashidx = baseidx; hashidx <= topidx; hashidx++) -+ for (he = ctxt->ctxt_mmuhash[tbl][hashidx]; he != NULL; he = he_ctxt_next (he, ctxnum)) -+ for (tagidx = 0; tagidx < 2; tagidx++) -+ if ((he->he_tag[tagidx] & TAG_CONTEXT_MASK) == ctxnum) -+ { -+ E4_Addr base = E4MMU_TAG2VADDR (he->he_tag[tagidx], hashidx, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1); -+ E4_Addr top = base + (tagspan -1); -+ -+ if (start < top && end > base) -+ { -+ unsigned bidx = (start <= base) ? 0 : (start & (tagspan-1)) >> dev->dev_pageshift[tbl]; -+ unsigned tidx = (end >= top) ? 3 : (end & (tagspan-1)) >> dev->dev_pageshift[tbl]; -+ -+ MPRINTF (ctxt, 1, "elan4mmu_unload_range: he=%p base=%llx top=%llx hashidx=%d bidx=%d tidx=%d\n", he, base, top, hashidx, bidx, tidx); -+ -+ for (pteidx = bidx; pteidx <= tidx; pteidx++) -+ if (HE_GET_PTE(he, tagidx, pteidx)) -+ { -+ elan4mmu_invalidatepte (dev, he, tagidx, pteidx); -+ needflush = 1; -+ } -+ } -+ else if (base >= start && top <= end) /* hash entry completely spanned */ -+ { /* so invalidate the tag */ -+ MPRINTF (ctxt, 1, "elan4mmu_unload_range: he=%p base=%llx top=%llx spanned\n", he, base, top); -+ -+ he->he_tag[tagidx] &= ~HE_TAG_VALID; -+ -+ elan4mmu_synctag (dev, he, tagidx); -+ needflush = 1; -+ } -+ } -+ -+ if (needflush) -+ { -+ /* 2nd invalidate the first/last hash blocks if they are partially invalidated -+ * and flush the tlb/hash copy blocks */ -+ elan4mmu_flush_tlb_hash (dev, tbl, baseidx, topidx); -+ -+ /* 3rd free off the hash entries which are completely invalidated */ -+ for (hashidx = baseidx; hashidx <= topidx; hashidx++) -+ for (prevhe = NULL, he = ctxt->ctxt_mmuhash[tbl][hashidx]; he != NULL; he = next) -+ { -+ next = he_ctxt_next (he, ctxnum); -+ -+ for (tagidx = 0; tagidx < 2; tagidx++) -+ if ((he->he_tag[tagidx] & TAG_CONTEXT_MASK) == ctxnum) -+ { -+ E4_Addr base = E4MMU_TAG2VADDR (he->he_tag[tagidx], hashidx, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1); -+ E4_Addr top = base + (tagspan -1); -+ -+ if (start < top && end > base) -+ { -+ unsigned bidx = (start <= base) ? 0 : (start & (tagspan-1)) >> dev->dev_pageshift[tbl]; -+ unsigned tidx = (end >= top) ? 3 : (end & (tagspan-1)) >> dev->dev_pageshift[tbl]; -+ -+ MPRINTF (ctxt, 1, "elan4mmu_unload_range: he=%p base=%llx top=%llx bidx=%d tidx=%d\n", he, base, top, bidx, tidx); -+ -+ for (pteidx = bidx; pteidx <= tidx; pteidx++) -+ if (HE_GET_PTE(he, tagidx, pteidx)) -+ { -+ HE_SET_PTE(he, tagidx, pteidx, 0); -+ -+ elan4mmu_writepte (dev, he, tagidx, pteidx, 0); -+ } -+ } -+ -+ if ((base >= start && top <= end) || he->he_pte[tagidx] == 0) /* hash entry completely spanned or all pte's cleared */ -+ { /* so invalidate the pte's and free it */ -+ -+ MPRINTF (ctxt, 1, "elan4mmu_unload_range: he=%p base=%llx top=%llx spanned or empty\n", he, base, top); -+ -+ elan4mmu_free_hent (dev, tbl, hashidx, he, tagidx); -+ } -+ } -+ -+ prevhe = he_ctxt_unlink (ctxt, tbl, hashidx, prevhe, he, next); -+ } -+ } -+ spin_unlock (&ctxt->ctxt_mmulock); -+} -+ -+void -+elan4mmu_invalidate_ctxt (ELAN4_CTXT *ctxt) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ int ctxnum = ctxt->ctxt_num; -+ ELAN4_HASH_ENTRY *he; -+ int tbl, hashidx, tagidx; -+ -+ MPRINTF (ctxt, 0, "elan4mmu_invalidate_ctxt: invalidating ctxnum=%d\n", ctxnum); -+ -+ spin_lock (&ctxt->ctxt_mmulock); -+ -+ /* 1st invalidate all tags belonging to me */ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ for (hashidx = 0; hashidx < dev->dev_hashsize[tbl]; hashidx++) -+ for (he = ctxt->ctxt_mmuhash[tbl][hashidx]; he != NULL; he = he_ctxt_next (he, ctxnum)) -+ for (tagidx = 0; tagidx < 2; tagidx++) -+ if ((he->he_tag[tagidx] & TAG_CONTEXT_MASK) == ctxnum) /* own tag block */ -+ { -+ MPRINTF (ctxt, 1, "elan4mmu_invalidate_ctxt: he=%p addr=%llx hashidx=%d tagidx=%d\n", -+ he, he->he_tag[tagidx] & TAG_ADDRESS_MASK, hashidx, tagidx); -+ -+ he->he_tag[tagidx] &= ~HE_TAG_VALID; -+ -+ elan4mmu_synctag (dev, he, tagidx); -+ } -+ -+ /* 2nd flush the tlb & cached hash block */ -+ elan4mmu_flush_tlb (dev); -+ -+ /* 3rd invalidate all pte's and free off the hash entries */ -+ for (tbl = 0; tbl < NUM_HASH_TABLES; tbl++) -+ for (hashidx = 0; hashidx < dev->dev_hashsize[tbl]; hashidx++) -+ while ((he = ctxt->ctxt_mmuhash[tbl][hashidx]) != NULL) -+ { -+ ctxt->ctxt_mmuhash[tbl][hashidx] = he_ctxt_next (he, ctxnum); -+ -+ for (tagidx = 0; tagidx < 2; tagidx++) -+ if ((he->he_tag[tagidx] & TAG_CONTEXT_MASK) == ctxnum) -+ elan4mmu_free_hent (dev, tbl, hashidx, he, tagidx); -+ } -+ spin_unlock (&ctxt->ctxt_mmulock); -+} -+ -+ELAN4_HASH_CACHE * -+elan4mmu_reserve (ELAN4_CTXT *ctxt, int tbl, E4_Addr start, unsigned int npages, int cansleep) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ E4_Addr end = start + (npages << dev->dev_pageshift[tbl]) - 1; -+ unsigned long tagshift = dev->dev_pageshift[tbl] + 2; -+ E4_Addr tagspan = 1 << tagshift; -+ E4_Addr base = (start & ~(tagspan-1)); -+ E4_Addr top = (end & ~(tagspan-1)) + (tagspan-1); -+ unsigned int nhes = (top - base + 1) >> tagshift; -+ ELAN4_HASH_CACHE *hc; -+ unsigned int tagidx, pteidx; -+ E4_Addr addr; -+ int i; -+ -+ MPRINTF (ctxt, 0, "elan4mmu_reserve: start=%llx npages=%d\n", start, npages); -+ MPRINTF (ctxt, 0, " pageshift=%d tagspan=%lx base=%llx top=%llx end=%llx nhes=%d\n", -+ dev->dev_pageshift[tbl], tagspan, base, top, end, nhes); -+ -+ KMEM_ALLOC (hc, ELAN4_HASH_CACHE *, offsetof (ELAN4_HASH_CACHE, hc_hes[nhes]), cansleep); -+ -+ if (hc == NULL) -+ return NULL; -+ -+ hc->hc_start = start; -+ hc->hc_end = end; -+ hc->hc_tbl = tbl; -+ -+ spin_lock (&ctxt->ctxt_mmulock); -+ for (addr = base, i = 0; i < nhes; addr += tagspan, i++) -+ { -+ unsigned bidx = (i == 0) ? (start & (tagspan-1)) >> dev->dev_pageshift[tbl] : 0; -+ unsigned tidx = (i == (nhes-1)) ? (end & (tagspan-1)) >> dev->dev_pageshift[tbl] : 3; -+ -+ -+ if ((hc->hc_hes[i] = elan4mmu_ptealloc (ctxt, tbl, addr & ~(tagspan-1), &tagidx)) == NULL) -+ goto failed; -+ -+ -+ MPRINTF (ctxt, 2, "elan4mmu_reserve: tbl=%d addr=%llx -> hashidx=%d tagidx=%d\n", tbl, addr & ~(tagspan-1), -+ E4MMU_HASH_INDEX (ctxt->ctxt_num, (addr & ~(tagspan-1)), dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1), tagidx); -+ -+ for (pteidx = bidx; pteidx <= tidx; pteidx++) -+ { -+ ASSERT (HE_GET_PTE (hc->hc_hes[i], tagidx, pteidx) == 0); -+ -+ MPRINTF (ctxt, 2, "elan4mmu_reserve: i=%d addr=%llx he=%p (tagidx=%d pteidx=%d)\n", -+ i, addr, hc->hc_hes[i], tagidx, pteidx); -+ -+ HE_SET_PTE (hc->hc_hes[i], tagidx, pteidx, PTE_PERM_TYPE_MASK); -+ } -+ } -+ spin_unlock (&ctxt->ctxt_mmulock); -+ -+ return hc; -+ -+ failed: -+ for (i--, addr -= tagspan; i >= 0; i--, addr -= tagspan) -+ { -+ unsigned bidx = (i == 0) ? (start & (tagspan-1)) >> dev->dev_pageshift[tbl] : 0; -+ unsigned tidx = (i == (nhes-1)) ? (end & (tagspan-1)) >> dev->dev_pageshift[tbl] : 3; -+ unsigned hashidx = E4MMU_HASH_INDEX (ctxt->ctxt_num, addr, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1); -+ unsigned tagidx = (addr == E4MMU_TAG2VADDR (hc->hc_hes[i]->he_tag[0], hashidx, dev->dev_pageshift[tbl], dev->dev_hashsize[tbl]-1)) ? 0 : 1; -+ -+ for (pteidx = bidx; pteidx <= tidx; pteidx++) -+ HE_SET_PTE(hc->hc_hes[i], tagidx, pteidx, 0); -+ -+ if (hc->hc_hes[i]->he_pte[tagidx] == 0) -+ elan4mmu_free_hent (dev, tbl, hashidx, hc->hc_hes[i], tagidx); -+ } -+ spin_unlock (&ctxt->ctxt_mmulock); -+ -+ KMEM_FREE (hc, offsetof (ELAN4_HASH_CACHE, hc_hes[nhes])); -+ -+ return NULL; -+} -+ -+void -+elan4mmu_release (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ E4_Addr start = hc->hc_start; -+ E4_Addr end = hc->hc_end; -+ unsigned long tagshift = dev->dev_pageshift[hc->hc_tbl] + 2; -+ E4_Addr tagspan = 1 << tagshift; -+ E4_Addr base = (start & ~(tagspan-1)); -+ E4_Addr top = (end & ~(tagspan-1)) + (tagspan-1); -+ unsigned int nhes = (top - base + 1) >> tagshift; -+ ELAN4_HASH_ENTRY *prevhe, *he, *next; -+ E4_Addr addr; -+ unsigned int pteidx; -+ int i; -+ -+ spin_lock (&ctxt->ctxt_mmulock); -+ -+ MPRINTF (ctxt, 0, "elan4mmu_release: base=%llx top=%llx\n", base, top); -+ -+ for (addr = base, i = 0; i < nhes; addr += tagspan, i++) -+ { -+ unsigned bidx = (i == 0) ? (start & (tagspan-1)) >> dev->dev_pageshift[hc->hc_tbl] : 0; -+ unsigned tidx = (i == (nhes-1)) ? (end & (tagspan-1)) >> dev->dev_pageshift[hc->hc_tbl] : 3; -+ unsigned hashidx = E4MMU_HASH_INDEX (ctxt->ctxt_num, addr, dev->dev_pageshift[hc->hc_tbl], dev->dev_hashsize[hc->hc_tbl]-1); -+ unsigned tagidx = (addr == E4MMU_TAG2VADDR (hc->hc_hes[i]->he_tag[0], hashidx, dev->dev_pageshift[hc->hc_tbl], dev->dev_hashsize[hc->hc_tbl]-1)) ? 0 : 1; -+ -+ for (pteidx = bidx; pteidx <= tidx; pteidx++) -+ { -+ elan4mmu_invalidatepte (dev, hc->hc_hes[i], tagidx, pteidx); -+ -+ HE_SET_PTE(hc->hc_hes[i], tagidx, pteidx, 0); -+ } -+ -+ MPRINTF (ctxt, 2, "elan4mmu_release: i=%d addr=%llx he=%p (hashidx=%d tagidx=%d pteidx=%d) pte=%x\n", -+ i, addr, hc->hc_hes[i], hashidx, tagidx, pteidx, hc->hc_hes[i]->he_pte[tagidx]); -+ -+ /* remove from context hash */ -+ for (prevhe = NULL, he = ctxt->ctxt_mmuhash[hc->hc_tbl][hashidx], next = he_ctxt_next (he, ctxt->ctxt_num); he != hc->hc_hes[i]; he = next) -+ next = he_ctxt_next (he, ctxt->ctxt_num); -+ -+ if (hc->hc_hes[i]->he_pte[tagidx] == 0) -+ elan4mmu_free_hent (dev, hc->hc_tbl, hashidx, hc->hc_hes[i], tagidx); -+ -+ prevhe = he_ctxt_unlink (ctxt, hc->hc_tbl, hashidx, prevhe, he, next); -+ } -+ spin_unlock (&ctxt->ctxt_mmulock); -+} -+ -+void -+elan4mmu_set_pte (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc, unsigned int idx, E4_uint64 newpte) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned int tbl = hc->hc_tbl; -+ unsigned int tagshift = dev->dev_pageshift[tbl] + 2; -+ E4_Addr tagspan = 1 << tagshift; -+ E4_Addr addr = hc->hc_start + (idx << dev->dev_pageshift[tbl]); -+ ELAN4_HASH_ENTRY *he = hc->hc_hes[(addr - (hc->hc_start & ~(tagspan-1))) >> tagshift]; -+ unsigned pteidx = E4MMU_SHIFT_ADDR(addr, dev->dev_pageshift[tbl]) & 3; -+ unsigned tagidx = he->he_tag[0] == (E4MMU_TAG (addr, ctxt->ctxt_num) | HE_TAG_VALID) ? 0 : 1; -+ -+ MPRINTF (ctxt, 2, "elan4mmu_set_pte: idx=%d addr=%llx he=%p (tagidx=%d pteidx=%d) newpte=%llx\n", idx, addr, he, tagidx, pteidx, newpte); -+ -+ ASSERT (he->he_tag[tagidx] == (E4MMU_TAG (addr, ctxt->ctxt_num) | HE_TAG_VALID)); -+ -+ elan4mmu_writepte (dev, he, tagidx, pteidx, newpte); -+} -+ -+E4_uint64 -+elan4mmu_get_pte (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc, unsigned int idx) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned int tbl = hc->hc_tbl; -+ unsigned int tagshift = dev->dev_pageshift[tbl] + 2; -+ E4_Addr tagspan = 1 << tagshift; -+ E4_Addr addr = hc->hc_start + (idx << dev->dev_pageshift[tbl]); -+ ELAN4_HASH_ENTRY *he = hc->hc_hes[(addr - (hc->hc_start & ~(tagspan-1))) >> tagshift]; -+ unsigned pteidx = E4MMU_SHIFT_ADDR(addr, dev->dev_pageshift[tbl]) & 3; -+ unsigned tagidx = he->he_tag[0] == (E4MMU_TAG (addr, ctxt->ctxt_num) | HE_TAG_VALID) ? 0 : 1; -+ -+ ASSERT (he->he_tag[tagidx] == (E4MMU_TAG (addr, ctxt->ctxt_num) | HE_TAG_VALID)); -+ -+ return elan4mmu_readpte (dev, he, tagidx, pteidx); -+} -+ -+void -+elan4mmu_clear_pte (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc, unsigned int idx) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ unsigned int tbl = hc->hc_tbl; -+ unsigned int tagshift = dev->dev_pageshift[tbl] + 2; -+ E4_Addr tagspan = 1 << tagshift; -+ E4_Addr addr = hc->hc_start + (idx << dev->dev_pageshift[tbl]); -+ ELAN4_HASH_ENTRY *he = hc->hc_hes[(addr - (hc->hc_start & ~(tagspan-1))) >> tagshift]; -+ unsigned pteidx = E4MMU_SHIFT_ADDR(addr, dev->dev_pageshift[tbl]) & 3; -+ unsigned tagidx = he->he_tag[0] == (E4MMU_TAG (addr, ctxt->ctxt_num) | HE_TAG_VALID) ? 0 : 1; -+ -+ MPRINTF (ctxt, 2, "elan4mmu_clear_pte: idx=%d addr=%llx he=%p (tagidx=%d pteidx=%d)\n", idx, addr, he, tagidx, pteidx); -+ -+ ASSERT (he->he_tag[tagidx] == (E4MMU_TAG (addr, ctxt->ctxt_num) | HE_TAG_VALID)); -+ -+ elan4mmu_invalidatepte (dev, he, tagidx, pteidx); -+} -+ -+EXPORT_SYMBOL(elan4mmu_flush_tlb); -+EXPORT_SYMBOL(elan4mmu_pteload); -+EXPORT_SYMBOL(elan4mmu_unload_range); -+EXPORT_SYMBOL(elan4mmu_reserve); -+EXPORT_SYMBOL(elan4mmu_release); -+EXPORT_SYMBOL(elan4mmu_set_pte); -+EXPORT_SYMBOL(elan4mmu_get_pte); -+EXPORT_SYMBOL(elan4mmu_clear_pte); -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/mmu_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/mmu_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/mmu_Linux.c 2005-06-01 23:12:54.611437280 -0400 -@@ -0,0 +1,265 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: mmu_Linux.c,v 1.8 2004/05/10 14:10:46 daniel Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/mmu_Linux.c,v $*/ -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+/* -+ * Convert a physical address into an pte. This should generate a "local" pte for -+ * physical addresses which are elan4 sdram or elan4 command queues. For elan4 -+ * registers and other addresses on the same bus, this should be the local pci -+ * bus address. All other addresses should access the physical address via the -+ * PCI bridge. -+ */ -+ -+#ifdef __alpha -+#define ioaddr2paddr(ioaddr) virt_to_phys((void *) __ioremap(ioaddr, PAGE_SIZE)) -+#elif defined(__ia64) -+#define ioaddr2paddr(ioaddr) ((ioaddr) & ~__IA64_UNCACHED_OFFSET) -+#else -+#define ioaddr2paddr(ioaddr) (ioaddr) -+#endif -+ -+int -+elan4mmu_categorise_paddr (ELAN4_DEV *dev, physaddr_t *physp) -+{ -+ physaddr_t sdram_base = ioaddr2paddr (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ physaddr_t sdram_top = ioaddr2paddr (pci_resource_end (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ physaddr_t regs_base = ioaddr2paddr (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS)); -+ physaddr_t regs_top = ioaddr2paddr (pci_resource_end (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS)); -+ physaddr_t phys = *physp; -+ int iscommand; -+ -+ if (phys >= sdram_base && phys <= sdram_top) -+ { -+ (*physp) = (phys ^ sdram_base); -+ return ELAN4MMU_PADDR_SDRAM; -+ } -+ -+ if (phys >= regs_base && phys < regs_top) -+ { -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ iscommand = (phys < (regs_base + ELAN4_REVA_REG_OFFSET)); -+ else -+ iscommand = (phys < (regs_base + ELAN4_REVB_I2C_OFFSET)); -+ -+ if (iscommand) -+ { -+ (*physp) = phys ^ regs_base; -+ -+ return ELAN4MMU_PADDR_COMMAND; -+ } -+ else -+ { -+ // XXXX (*physp) = phys2bus (phys); -+ -+ return ELAN4MMU_PADDR_LOCALPCI; -+ } -+ } -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+ if (VALID_PAGE (virt_to_page (phys_to_virt (phys)))) -+#else -+ if (virt_addr_valid (phys_to_virt (phys))) -+#endif -+ return ELAN4MMU_PADDR_PAGE; -+ -+ return ELAN4MMU_PADDR_OTHER; -+} -+ -+int -+elan4mmu_sdram_aliascheck (ELAN4_CTXT *ctxt, E4_Addr addr, physaddr_t phys) -+{ -+ ELAN4_DEV *dev = ctxt->ctxt_dev; -+ -+ /* -+ * On MPSAS we don't allocate a large enough context table, so -+ * if we see an address/context pair which would "alias" because -+ * they differ in unchecked hash bits to a previous pteload, -+ * then we kill the application. -+ */ -+ unsigned hashval = (E4MMU_SHIFT_ADDR(addr, (dev->dev_pageshift[0]) + 2) ^ E4MMU_CONTEXT_SCRAMBLE(ctxt->ctxt_num)); -+ -+ if (dev->dev_rsvd_hashval[0] == 0xFFFFFFFF) -+ dev->dev_rsvd_hashval[0] = hashval & dev->dev_rsvd_hashmask[0]; -+ -+ if ((hashval & dev->dev_rsvd_hashmask[0]) != dev->dev_rsvd_hashval[0]) -+ { -+ printk ("elan4mmu_sdram_aliascheck: vaddr=%016llx ctxnum=%x -> [%x] overlaps %x - %x [hashidx=%x]\n", (unsigned long long) addr, -+ ctxt->ctxt_num, hashval, hashval & dev->dev_rsvd_hashmask[0], dev->dev_rsvd_hashval[0], -+ E4MMU_HASH_INDEX (ctxt->ctxt_num, addr, dev->dev_pageshift[0], dev->dev_hashsize[0]-1)); -+ -+ return 0; -+ } -+ -+ if (((addr & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT)) != (phys & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT)))) -+ { -+ printk ("elan4mmu_sdram_aliascheck: vaddr=%016llx incorrectly alias sdram at %lx\n", (unsigned long long) addr, -+ phys ^ pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+int -+elan4mmu_alloc_topaddr (ELAN4_DEV *dev, physaddr_t paddr, unsigned type) -+{ -+#if defined(__i386) && !defined(CONFIG_X86_PAE) -+ if (dev->dev_topaddrvalid == 0) -+ { -+ dev->dev_topaddrvalid = 1; -+ -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_ELAN_TOPPHYSADDR(0), 0); -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_ELAN_TOPPHYSADDR(1), 0); -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_ELAN_TOPPHYSADDR(2), 0); -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_ELAN_TOPPHYSADDR(3), 0); -+ } -+ return (0); -+#else -+ register int i; -+ E4_uint16 match; -+ -+ if (dev->dev_topaddrmode) /* ExtraMasterAddrBits=1 => match {paddr[63:50],type[3:2]} */ -+ match = ((paddr >> 48) & ~3) | ((type >> 2) & 3); -+ else /* ExtraMasterAddrBits=0 => match {paddr[63:48]} */ -+ match = (paddr >> 48); -+ -+ MPRINTF (DBG_DEVICE, 2, "elan4mmu_alloc_topaddr: mode=%d paddr=%lx type=%x match=%x [%x %x.%x.%x.%x]\n", -+ dev->dev_topaddrmode, paddr, type, match, dev->dev_topaddrvalid, -+ dev->dev_topaddr[0], dev->dev_topaddr[1], dev->dev_topaddr[2], dev->dev_topaddr[3]); -+ -+ for (i = 0; i < 4; i++) -+ if ((dev->dev_topaddrvalid & (1 << i)) && dev->dev_topaddr[i] == match) -+ return (i); -+ -+ for (i = 0; i < 4; i++) -+ { -+ if ((dev->dev_topaddrvalid & (1 << i)) == 0) -+ { -+ MPRINTF (DBG_DEVICE, 2, "elan4mmu_alloc_topaddr: allocate slot %d for %x\n", i, match); -+ -+ dev->dev_topaddrvalid |= (1 << i); -+ dev->dev_topaddr[i] = match; -+ -+ pci_write_config_word (dev->dev_osdep.pdev, PCI_ELAN_TOPPHYSADDR(i), match); -+ return (i); -+ } -+ } -+ -+ panic ("elan4mmu_alloc_topaddr: all topaddrs in use\n"); -+ return (0); -+#endif -+} -+ -+E4_uint64 -+elan4mmu_phys2pte (ELAN4_DEV *dev, physaddr_t phys, unsigned perm) -+{ -+ physaddr_t sdram_base = ioaddr2paddr (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ physaddr_t sdram_top = ioaddr2paddr (pci_resource_end (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ physaddr_t regs_base = ioaddr2paddr (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS)); -+ physaddr_t regs_top = ioaddr2paddr (pci_resource_end (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS)); -+ int iscommand; -+ E4_uint64 pte; -+ unsigned type; -+ -+ if (phys >= sdram_base && phys <= sdram_top) -+ { -+ phys ^= sdram_base; -+ type = PTE_SetPerm (perm); -+ } -+ else if (phys >= regs_base && phys < regs_top) -+ { -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ iscommand = (phys < (regs_base + ELAN4_REVA_REG_OFFSET)); -+ else -+ iscommand = (phys < (regs_base + ELAN4_REVB_I2C_OFFSET)); -+ -+ if (iscommand) -+ { -+ phys ^= regs_base; -+ type = PTE_SetPerm (perm) | PTE_CommandQueue; -+ } -+ else -+ { -+ type = PTE_SetPerm (perm) | PTE_PciNotLocal; -+ // phys = phys2bus (phys); -+ } -+ } -+ else -+ { -+ type = PTE_SetPerm (perm) | PTE_PciNotLocal | dev->dev_pteval; -+ -+#ifdef LINUX_SPARC -+ /* XXXX if not local pci bus, then or in the bypass bit */ -+ phys |= 0xfffe000000000000; -+ type |= PTE_BigEndian; -+#endif -+ -+ -+#if defined(__alpha) -+ phys |= alpha_mv.pci_dac_offset; -+#endif -+ } -+ -+ if ((type & PTE_PciNotLocal) == 0) -+ pte = (phys >> PTE_PADDR_SHIFT) | type; -+ else -+ { -+ unsigned topaddr = elan4mmu_alloc_topaddr (dev, phys, type); -+ -+ if (dev->dev_topaddrmode) -+ pte = (phys >> PTE_PADDR_SHIFT) | (type & ~0xc) | (topaddr << 2); -+ else -+ pte = ((phys >> PTE_PADDR_SHIFT) & ~PTE_TOPADDR_MASK) | (((E4_uint64) topaddr) << 45) | type; -+ } -+ -+ return pte; -+} -+ -+physaddr_t -+elan4mmu_pte2phys (ELAN4_DEV *dev, E4_uint64 pte) -+{ -+ physaddr_t sdram_base = ioaddr2paddr (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ physaddr_t regs_base = ioaddr2paddr (pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS)); -+ physaddr_t phys; -+ -+ if (pte & PTE_PciNotLocal) -+ { -+ if (dev->dev_topaddrmode) -+ phys = ((physaddr_t)(dev->dev_topaddr[(pte >> 2) & 3] & 0xfffc) << 48) | ((pte & PTE_PPN_MASK) << PTE_PADDR_SHIFT); -+ else -+ phys = ((physaddr_t)(dev->dev_topaddr[(pte >> 45) & 3] & 0xffff) << 48)| ((pte & PTE_PPN_MASK & ~PTE_TOPADDR_MASK) << PTE_PADDR_SHIFT); -+ -+#ifdef LINUX_SPARC /* XXXX if not local pci bus, then or in the bypass bit */ -+ phys ^= 0xfffe000000000000; -+#endif -+ -+#if defined(__alpha) -+ phys ^= alpha_mv.pci_dac_offset; -+#endif -+ return phys; -+ } -+ -+ if (pte & PTE_CommandQueue) -+ return (regs_base | ((pte & PTE_PPN_MASK) << PTE_PADDR_SHIFT)); -+ -+ /* sdram */ -+ return (sdram_base | ((pte & PTE_PPN_MASK) << PTE_PADDR_SHIFT)); -+} -+ -+EXPORT_SYMBOL(elan4mmu_phys2pte); -+EXPORT_SYMBOL(elan4mmu_pte2phys); -Index: linux-2.4.21/drivers/net/qsnet/elan4/neterr.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/neterr.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/neterr.c 2005-06-01 23:12:54.612437128 -0400 -@@ -0,0 +1,270 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: neterr.c,v 1.4.6.3 2004/11/05 13:11:17 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/neterr.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+typedef struct neterr_inputq -+{ -+ E4_InputQueue inputq; /* input queue */ -+ E4_Event32 qevent; /* input queue event */ -+ E4_uint64 sent; /* # messages sent (cq flow control)*/ -+} NETERR_INPUTQ; -+ -+#define NETERR_NSLOTS 64 /* single page of queue space (4Kb) */ -+ -+#define NETERR_RETRIES 16 -+#define NETERR_CQ_SIZE CQ_Size8K -+#define NETERR_CQ_MSGS (CQ_Size(NETERR_CQ_SIZE) / (21*8)) -+#define NETERR_VP_COUNT 64 /* this *must* be > NETERR_CQ_MSGS */ -+#define NETERR_VP_BASE 1 /* use vp 1 upwards */ -+ -+void -+elan4_neterr_interrupt (ELAN4_DEV *dev, void *arg) -+{ -+ E4_Addr qfptr = elan4_sdram_readq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_fptr)); -+ E4_Addr qbptr = elan4_sdram_readq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_bptr)); -+ E4_Addr qfirst = DEVICE_NETERR_SLOTS_ADDR; -+ E4_Addr qlast = qfirst + (NETERR_NSLOTS-1) * ELAN4_NETERR_MSG_SIZE; -+ ELAN4_CQ *cq = dev->dev_neterr_intcq; -+ int count = 0; -+ ELAN4_CTXT *ctxt; -+ ELAN4_NETERR_MSG msg; -+ -+ while (qfptr != qbptr) -+ { -+ elan4_sdram_copyq_from_sdram (dev, dev->dev_neterr_slots + (qfptr - qfirst), &msg, ELAN4_NETERR_MSG_SIZE); -+ -+ ctxt = elan4_networkctxt (dev, msg.msg_context); -+ -+ if (ctxt != NULL && ctxt->ctxt_ops->op_neterrmsg) -+ ctxt->ctxt_ops->op_neterrmsg (ctxt, &msg); -+ else -+ PRINTF (DBG_DEVICE, DBG_NETERR, "elan4_neterr_interrupt: no process - sender %d.%d\n", msg.msg_sender.loc_node, msg.msg_sender.loc_context); -+ -+ count++; -+ -+ /* move on the from pointer */ -+ qfptr = (qfptr == qlast) ? qfirst : qfptr + ELAN4_NETERR_MSG_SIZE; -+ -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_fptr), qfptr); -+ } -+ -+ if (count == 0) -+ { -+ printk ("elan4_neterr_interrupt: spurious\n"); -+ return; -+ } -+ -+ /* Issue the waitevent to the interrupt queue */ -+ writeq (WAIT_EVENT_CMD | (DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, qevent)), cq->cq_mapping); -+ writeq ( E4_EVENT_INIT_VALUE (-32 * count, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0), cq->cq_mapping); -+ writeq ( DEVICE_NETERR_INTCQ_ADDR, cq->cq_mapping); -+ writeq (INTERRUPT_CMD | (dev->dev_neterr_intop.op_cookie << E4_MAIN_INT_SHIFT), cq->cq_mapping); -+ -+ pioflush_reg (dev); -+} -+ -+int -+elan4_neterr_init (ELAN4_DEV *dev) -+{ -+ unsigned int intqaddr; -+ E4_Addr qfirst, qlast; -+ -+ if ((dev->dev_neterr_inputq = elan4_sdram_alloc (dev, SDRAM_PAGE_SIZE)) == 0) -+ return 0; -+ -+ if ((dev->dev_neterr_slots = elan4_sdram_alloc (dev, roundup (NETERR_NSLOTS * ELAN4_NETERR_MSG_SIZE, SDRAM_PAGE_SIZE))) == 0) -+ return 0; -+ -+ if ((dev->dev_neterr_msgcq = elan4_alloccq (&dev->dev_ctxt, NETERR_CQ_SIZE, CQ_STENEnableBit | CQ_WriteEnableBit, CQ_Priority)) == NULL) -+ return 0; -+ -+ if ((dev->dev_neterr_intcq = elan4_alloccq (&dev->dev_ctxt, CQ_Size1K, CQ_WaitEventEnableBit | CQ_InterruptEnableBit, CQ_Priority)) == NULL) -+ return 0; -+ -+ intqaddr = (dev->dev_cqoffset + elan4_cq2num (dev->dev_neterr_intcq)) * CQ_CommandMappingSize; -+ qfirst = DEVICE_NETERR_SLOTS_ADDR; -+ qlast = qfirst + (NETERR_NSLOTS-1) * ELAN4_NETERR_MSG_SIZE; -+ -+ spin_lock_init (&dev->dev_neterr_lock); -+ -+ /* Register an interrupt operation */ -+ dev->dev_neterr_intop.op_function = elan4_neterr_interrupt; -+ dev->dev_neterr_intop.op_arg = NULL; -+ -+ elan4_register_intop (dev, &dev->dev_neterr_intop); -+ -+ /* Initialise the inputq descriptor and event */ -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_fptr), qfirst); -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_bptr), qfirst); -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_control), E4_InputQueueControl (qfirst, qlast, ELAN4_NETERR_MSG_SIZE)); -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, inputq.q_event), DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, qevent)); -+ -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, qevent.ev_CountAndType), E4_EVENT_INIT_VALUE (-32, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, qevent.ev_WritePtr), DEVICE_NETERR_INTCQ_ADDR); -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, qevent.ev_WriteValue), (dev->dev_neterr_intop.op_cookie << E4_MAIN_INT_SHIFT) | INTERRUPT_CMD); -+ -+ elan4_sdram_writeq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, sent), 0); -+ -+ /* Map them all into the device context */ -+ elan4mmu_pteload (&dev->dev_ctxt, 0, DEVICE_NETERR_INPUTQ_ADDR, (dev->dev_neterr_inputq >> PTE_PADDR_SHIFT) | PTE_SetPerm(PERM_RemoteAll)); -+ elan4mmu_pteload (&dev->dev_ctxt, 0, DEVICE_NETERR_INTCQ_ADDR, (intqaddr >> PTE_PADDR_SHIFT) | PTE_SetPerm(PERM_LocDataWrite) | PTE_CommandQueue); -+ elan4mmu_pteload (&dev->dev_ctxt, 0, DEVICE_NETERR_SLOTS_ADDR, (dev->dev_neterr_slots >> PTE_PADDR_SHIFT) | PTE_SetPerm(PERM_DataReadWrite)); -+ -+ /* finally attach to the neterr context */ -+ if (elan4_attach_filter (&dev->dev_ctxt, ELAN4_NETERR_CONTEXT_NUM) != 0) -+ panic ("elan4_neterr_init: failed to attach to neterr context\n"); -+ -+ /* and drop the context filter */ -+ elan4_set_filter (&dev->dev_ctxt, ELAN4_NETERR_CONTEXT_NUM, E4_FILTER_HIGH_PRI); -+ -+ return 1; -+} -+ -+void -+elan4_neterr_destroy (ELAN4_DEV *dev) -+{ -+ if (dev->dev_neterr_intcq) -+ { -+ elan4_detach_filter (&dev->dev_ctxt, ELAN4_NETERR_CONTEXT_NUM); -+ -+ elan4mmu_unload_range (&dev->dev_ctxt, 0, DEVICE_NETERR_SLOTS_ADDR, 1 << dev->dev_pageshift[0]); -+ elan4mmu_unload_range (&dev->dev_ctxt, 0, DEVICE_NETERR_INTCQ_ADDR, 1 << dev->dev_pageshift[0]); -+ elan4mmu_unload_range (&dev->dev_ctxt, 0, DEVICE_NETERR_INPUTQ_ADDR, 1 << dev->dev_pageshift[0]); -+ -+ spin_lock_destroy (&dev->dev_neterr_lock); -+ } -+ -+ if (dev->dev_neterr_intcq) -+ elan4_freecq (&dev->dev_ctxt, dev->dev_neterr_intcq); -+ dev->dev_neterr_intcq = NULL; -+ -+ if (dev->dev_neterr_msgcq) -+ elan4_freecq (&dev->dev_ctxt, dev->dev_neterr_msgcq); -+ dev->dev_neterr_msgcq = NULL; -+ -+ if (dev->dev_neterr_slots) -+ elan4_sdram_free (dev, dev->dev_neterr_slots, roundup (NETERR_NSLOTS * ELAN4_NETERR_MSG_SIZE, SDRAM_PAGE_SIZE)); -+ dev->dev_neterr_slots = 0; -+ -+ if (dev->dev_neterr_inputq) -+ elan4_sdram_free (dev, dev->dev_neterr_inputq, SDRAM_PAGE_SIZE); -+ dev->dev_neterr_inputq = 0; -+} -+ -+int -+elan4_neterr_sendmsg (ELAN4_DEV *dev, unsigned int nodeid, unsigned int retries, ELAN4_NETERR_MSG *msg) -+{ -+ ELAN4_CQ *cq = dev->dev_neterr_msgcq; -+ E4_uint64 sent; -+ E4_VirtualProcessEntry route; -+ unsigned int vp; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_neterr_lock, flags); -+ -+ sent = elan4_sdram_readq (dev, dev->dev_neterr_inputq + offsetof (NETERR_INPUTQ, sent)); -+ -+ PRINTF (DBG_DEVICE, DBG_NETERR, "elan4_neterr_sendmsg: nodeid=%d retries=%d cookie=%llx sender=%d,%d%s\n", -+ nodeid, retries, msg->msg_cookies[0], msg->msg_sender.loc_node, msg->msg_sender.loc_context, -+ (dev->dev_neterr_queued - sent) >= NETERR_CQ_MSGS ? " - no cq space" : ""); -+ -+ if ((dev->dev_neterr_queued - sent) >= NETERR_CQ_MSGS) -+ { -+ spin_unlock_irqrestore (&dev->dev_neterr_lock, flags); -+ return 0; -+ } -+ -+ vp = NETERR_VP_BASE + (dev->dev_neterr_queued % NETERR_VP_COUNT); -+ -+ if (elan4_generate_route (&dev->dev_position, &route, ELAN4_NETERR_CONTEXT_NUM, nodeid, nodeid, FIRST_SYSTEM_PACKET | FIRST_HIGH_PRI) < 0) -+ { -+ spin_unlock_irqrestore (&dev->dev_neterr_lock, flags); -+ return 0; -+ } -+ -+ elan4_write_route (dev, dev->dev_routetable, vp, &route); -+ -+ writeq ((GUARD_CMD | GUARD_CHANNEL(0) | GUARD_RESET(retries)), cq->cq_mapping); -+ writeq (NOP_CMD, cq->cq_mapping); -+ -+ writeq (OPEN_STEN_PKT_CMD | OPEN_PACKET (0, PACK_OK | RESTART_COUNT_ZERO, vp), cq->cq_mapping); -+ writeq (SEND_TRANS_CMD | (TR_INPUT_Q_GETINDEX << 16), cq->cq_mapping); -+ writeq ( DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, inputq), cq->cq_mapping); -+ -+ writeq (SEND_TRANS_CMD | (TR_WRITE (64 >> 3, 0, TR_DATATYPE_DWORD) << 16), cq->cq_mapping); -+ writeq ( 0 /* address */, cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[0], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[1], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[2], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[3], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[4], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[5], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[6], cq->cq_mapping); -+ writeq ( ((E4_uint64 *) msg)[7], cq->cq_mapping); -+ -+ writeq (SEND_TRANS_CMD | (TR_INPUT_Q_COMMIT << 16), cq->cq_mapping); -+ writeq ( DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, inputq), cq->cq_mapping); -+ writeq ( 0 /* cookie */, cq->cq_mapping); -+ -+ writeq (GUARD_CMD | GUARD_CHANNEL(0) | GUARD_RESET(NETERR_RETRIES), cq->cq_mapping); -+ writeq (WRITE_DWORD_CMD | (DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, sent)), cq->cq_mapping); -+ writeq ( ++dev->dev_neterr_queued, cq->cq_mapping); -+ -+ pioflush_reg (dev); -+ -+ spin_unlock_irqrestore (&dev->dev_neterr_lock, flags); -+ -+ return 1; -+} -+ -+int -+elan4_neterr_iproc_trap (ELAN4_DEV *dev, ELAN4_IPROC_TRAP *trap) -+{ -+ E4_IprocTrapHeader *hdrp = &trap->tr_transactions[trap->tr_trappedTrans]; -+ unsigned long flags; -+ -+ switch (IPROC_TrapValue (hdrp->IProcStatusCntxAndTrType)) -+ { -+ case InputEopErrorOnWaitForEop: -+ case InputEopErrorTrap: -+ case InputCrcErrorAfterPAckOk: -+ return 1; -+ -+ case InputEventEngineTrapped: -+ printk ("elan%d: device_iproc_trap: InputEventEngineTrapped - Trans=%x TrAddr=%llx\n", -+ dev->dev_instance, (int)IPROC_TransactionType (hdrp->IProcStatusCntxAndTrType), (long long) hdrp->TrAddr); -+ -+ if ((IPROC_TransactionType (hdrp->IProcStatusCntxAndTrType) & TR_OPCODE_MASK) == (TR_INPUT_Q_COMMIT & TR_OPCODE_MASK) && -+ hdrp->TrAddr == DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, inputq)) -+ { -+ spin_lock_irqsave (&dev->dev_neterr_lock, flags); -+ writeq ((DEVICE_NETERR_INPUTQ_ADDR + offsetof (NETERR_INPUTQ, qevent)) | SET_EVENT_CMD, dev->dev_neterr_msgcq->cq_mapping); -+ spin_unlock_irqrestore (&dev->dev_neterr_lock, flags); -+ return 1; -+ } -+ -+ default: -+ return 0; -+ } -+} -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/procfs_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/procfs_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/procfs_Linux.c 2005-06-01 23:12:54.613436976 -0400 -@@ -0,0 +1,1041 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: procfs_Linux.c,v 1.27.2.5 2005/01/18 14:36:17 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/elan4mod/procfs_Linux.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+/* -+ * -+ * procfs format for elan4: -+ * -+ * /proc/qsnet/elan4/config -+ * elan4_debug -+ * elan4_debug_toconsole -+ * elan4_debug_tobuffer -+ * elan4_debug_display_ctxt -+ * elan4_debug_ignore_ctxt -+ * elan4_debug_ignore_type -+ * elan4_debug_mmu -+ * elan4_mainint_punt_loops -+ * user_p2p_route_options -+ * user_bcast_route_options -+ * -+ * /proc/qsnet/elan4/deviceN -+ * stats -+ * position -+ * vpd -+ */ -+ -+struct proc_dir_entry *elan4_procfs_root; -+struct proc_dir_entry *elan4_config_root; -+ -+/* borrowed from fs/proc/proc_misc - helper for proc_read_int */ -+static int -+proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) -+{ -+ if (len <= off+count) *eof = 1; -+ *start = page + off; -+ len -= off; -+ if (len>count) len = count; -+ if (len<0) len = 0; -+ return len; -+} -+ -+static int -+proc_read_devinfo (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ int len = 0; -+ -+ if (! dev) -+ len = sprintf (page, "\n"); -+ else -+ { -+ len += sprintf (page + len, "dev_vendor_id 0x%x\n", dev->dev_devinfo.dev_vendor_id); -+ len += sprintf (page + len, "dev_device_id 0x%x\n", dev->dev_devinfo.dev_vendor_id); -+ len += sprintf (page + len, "dev_revision_id 0x%x\n", dev->dev_devinfo.dev_revision_id); -+ len += sprintf (page + len, "dev_instance 0x%x\n", dev->dev_devinfo.dev_instance); -+ len += sprintf (page + len, "dev_rail 0x%x\n", dev->dev_devinfo.dev_rail); -+ len += sprintf (page + len, "dev_driver_version 0x%x\n", dev->dev_devinfo.dev_driver_version); -+ len += sprintf (page + len, "dev_params_mask 0x%x\n", dev->dev_devinfo.dev_params_mask); -+ len += sprintf (page + len, "dev_params: \n"); -+ len += sprintf (page + len, " 0 - PciCmdQPadFlag 0x%x\n", dev->dev_devinfo.dev_params.values[0]); -+ len += sprintf (page + len, " 1 - EventCopyWinPt 0x%x\n", dev->dev_devinfo.dev_params.values[1]); -+ len += sprintf (page + len, " 2 - PciWriteCombining 0x%x\n", dev->dev_devinfo.dev_params.values[2]); -+ len += sprintf (page + len, " 3 - 0x%x\n", dev->dev_devinfo.dev_params.values[3]); -+ len += sprintf (page + len, " 4 - 0x%x\n", dev->dev_devinfo.dev_params.values[4]); -+ len += sprintf (page + len, " 5 - 0x%x\n", dev->dev_devinfo.dev_params.values[5]); -+ len += sprintf (page + len, " 6 - 0x%x\n", dev->dev_devinfo.dev_params.values[6]); -+ len += sprintf (page + len, " 7 - 0x%x\n", dev->dev_devinfo.dev_params.values[7]); -+ len += sprintf (page + len, " 8 - 0x%x\n", dev->dev_devinfo.dev_params.values[8]); -+ len += sprintf (page + len, " 9 - 0x%x\n", dev->dev_devinfo.dev_params.values[9]); -+ len += sprintf (page + len, " 10 - 0x%x\n", dev->dev_devinfo.dev_params.values[10]); -+ len += sprintf (page + len, " 11 - 0x%x\n", dev->dev_devinfo.dev_params.values[11]); -+ len += sprintf (page + len, "dev_num_down_links_value 0x%x\n", dev->dev_devinfo.dev_num_down_links_value); -+ -+ len += sprintf (page + len, "features 0x%x\n", dev->dev_features); -+ } -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static int -+proc_read_position (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ int len; -+ -+ if (dev->dev_position.pos_mode == ELAN_POS_UNKNOWN) -+ len = sprintf (page, "\n"); -+ else -+ len = sprintf (page, -+ "NodeId %d\n" -+ "NumLevels %d\n" -+ "NumNodes %d\n", -+ dev->dev_position.pos_nodeid, -+ dev->dev_position.pos_levels, -+ dev->dev_position.pos_nodes); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static int -+proc_write_position (struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ unsigned nodeid = ELAN_INVALID_NODE; -+ unsigned numnodes = 0; -+ char *page, *p; -+ int res; -+ ELAN_POSITION pos; -+ -+ if (count == 0) -+ return (0); -+ -+ if (count >= PAGE_SIZE) -+ return (-EINVAL); -+ -+ if ((page = (char *) __get_free_page (GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ MOD_INC_USE_COUNT; -+ -+ if (copy_from_user (page, buf, count)) -+ res = -EFAULT; -+ else -+ { -+ page[count] = '\0'; -+ -+ if (page[count-1] == '\n') -+ page[count-1] = '\0'; -+ -+ if (! strcmp (page, "")) -+ { -+ pos.pos_mode = ELAN_POS_UNKNOWN; -+ pos.pos_nodeid = ELAN_INVALID_NODE; -+ pos.pos_nodes = 0; -+ pos.pos_levels = 0; -+ } -+ else -+ { -+ for (p = page; *p; ) -+ { -+ while (isspace (*p)) -+ p++; -+ -+ if (! strncmp (p, "NodeId=", strlen("NodeId="))) -+ nodeid = simple_strtoul (p + strlen ("NodeId="), NULL, 0); -+ if (! strncmp (p, "NumNodes=", strlen ("NumNodes="))) -+ numnodes = simple_strtoul (p + strlen ("NumNodes="), NULL, 0); -+ -+ while (*p && !isspace(*p)) -+ p++; -+ } -+ -+ if (elan4_compute_position (&pos, nodeid, numnodes, dev->dev_devinfo.dev_num_down_links_value) != 0) -+ printk ("elan%d: invalid values for NodeId=%d NumNodes=%d\n", dev->dev_instance, nodeid, numnodes); -+ else -+ { -+ printk ("elan%d: setting NodeId=%d NumNodes=%d NumLevels=%d\n", dev->dev_instance, pos.pos_nodeid, -+ pos.pos_nodes, pos.pos_levels); -+ -+ if (elan4_set_position (dev, &pos) < 0) -+ printk ("elan%d: failed to set device position\n", dev->dev_instance); -+ } -+ } -+ } -+ -+ MOD_DEC_USE_COUNT; -+ free_page ((unsigned long) page); -+ -+ return (count); -+} -+ -+static int -+proc_read_temp (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ unsigned char values[2]; -+ int len; -+ -+ if (i2c_disable_auto_led_update (dev) < 0) -+ len = sprintf (page, ""); -+ else -+ { -+ if (i2c_read (dev, I2C_TEMP_ADDR, 2, values) < 0) -+ len = sprintf (page, ""); -+ else -+ len = sprintf (page, "%s%d%s\n", (values[0] & 0x80) ? "-" : "", -+ (values[0] & 0x80) ? -((signed char)values[0]) - 1 : values[0], -+ (values[1] & 0x80) ? ".5" : ".0"); -+ -+ i2c_enable_auto_led_update (dev); -+ } -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static int -+proc_read_eccerr (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char errstr[200]; -+ register int i, len = 0; -+ -+ *page = '\0'; -+ -+ for (i = 0; i < sizeof (dev->dev_sdramerrs)/sizeof(dev->dev_sdramerrs[0]); i++) -+ if (dev->dev_sdramerrs[i]) -+ len += sprintf (page + len, "%s occured %0d times\n", -+ elan4_sdramerr2str (dev, dev->dev_sdramerrs[i] & 0x000fffffffffffffULL, errstr), -+ (int) (dev->dev_sdramerrs[i] >> 52) + 1); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static int -+proc_read_vpd (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ int len; -+ -+ if ( elan4_read_vpd (dev, NULL, page) ) -+ len = sprintf (page, "no vpd tags found\n"); -+ else -+ len = strlen(page)+1; -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static struct device_info -+{ -+ char *name; -+ int (*read_func) (char *page, char **start, off_t off, int count, int *eof, void *data); -+ int (*write_func) (struct file *file, const char *buf, unsigned long count, void *data); -+ unsigned minrev; -+} device_info[] = { -+ {"devinfo", proc_read_devinfo, NULL, 0}, -+ {"position", proc_read_position, proc_write_position, 0}, -+ {"temp", proc_read_temp, NULL, 1}, -+ {"eccerr", proc_read_eccerr, NULL, 0}, -+ {"vpd", proc_read_vpd, NULL, 0}, -+}; -+ -+static int -+proc_read_link_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ -+ p += sprintf (p, "%20s %ld\n", "link_errors", dev->dev_stats.s_link_errors); -+ p += sprintf (p, "%20s %ld\n", "lock_errors", dev->dev_stats.s_lock_errors); -+ p += sprintf (p, "%20s %ld\n", "deskew_errors", dev->dev_stats.s_deskew_errors); -+ p += sprintf (p, "%20s %ld\n", "phase_errors", dev->dev_stats.s_phase_errors); -+ -+ p += sprintf (p, "%20s %ld\n", "data_errors", dev->dev_stats.s_data_errors); -+ p += sprintf (p, "%20s %ld\n", "fifo_overflow0", dev->dev_stats.s_fifo_overflow0); -+ p += sprintf (p, "%20s %ld\n", "fifo_overflow1", dev->dev_stats.s_fifo_overflow1); -+ p += sprintf (p, "%20s %ld\n", "mod45changed", dev->dev_stats.s_mod45changed); -+ p += sprintf (p, "%20s %ld\n", "pack_not_seen", dev->dev_stats.s_pack_not_seen); -+ -+ p += sprintf (p, "%20s %ld\n", "linkport_keyfail", dev->dev_stats.s_linkport_keyfail); -+ p += sprintf (p, "%20s %ld\n", "eop_reset", dev->dev_stats.s_eop_reset); -+ p += sprintf (p, "%20s %ld\n", "bad_length", dev->dev_stats.s_bad_length); -+ p += sprintf (p, "%20s %ld\n", "crc_error", dev->dev_stats.s_crc_error); -+ p += sprintf (p, "%20s %ld\n", "crc_bad", dev->dev_stats.s_crc_bad); -+ -+ p += sprintf (p, "%20s %ld\n", "cproc_timeout", dev->dev_stats.s_cproc_timeout); -+ p += sprintf (p, "%20s %ld\n", "dproc_timeout", dev->dev_stats.s_dproc_timeout); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static char * -+proc_sprintf_bucket_stat (char *p, char *name, unsigned long *stats, int *buckets) -+{ -+ int i; -+ -+ p += sprintf (p, "%20s ", name); -+ -+ for (i = 0; i < ELAN4_DEV_STATS_BUCKETS-1; i++) -+ p += sprintf (p, "%ld(<=%d) ", stats[i], buckets[i]); -+ p += sprintf (p, "%ld(>%d)\n", stats[i], buckets[i-1]); -+ -+ return p; -+} -+ -+static int -+proc_read_intr_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ -+ p += sprintf (p, "%20s %ld\n", "interrupts", dev->dev_stats.s_interrupts); -+ p += sprintf (p, "%20s %ld\n", "haltints", dev->dev_stats.s_haltints); -+ -+ p += sprintf (p, "%20s %ld\n", "mainint_punts", dev->dev_stats.s_mainint_punts); -+ p += sprintf (p, "%20s %ld\n", "mainint_rescheds", dev->dev_stats.s_mainint_rescheds); -+ -+ p = proc_sprintf_bucket_stat (p, "mainints", dev->dev_stats.s_mainints, MainIntBuckets); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_trap_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ -+ p += sprintf (p, "%20s %ld\n", "cproc_traps", dev->dev_stats.s_cproc_traps); -+ p += sprintf (p, "%20s %ld\n", "dproc_traps", dev->dev_stats.s_dproc_traps); -+ p += sprintf (p, "%20s %ld\n", "eproc_traps", dev->dev_stats.s_eproc_traps); -+ p += sprintf (p, "%20s %ld\n", "iproc_traps", dev->dev_stats.s_iproc_traps); -+ p += sprintf (p, "%20s %ld\n", "tproc_traps", dev->dev_stats.s_tproc_traps); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_cproc_trap_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ int i; -+ extern char *const CProcTrapNames[]; -+ -+ for (i = 0; i < sizeof (dev->dev_stats.s_cproc_trap_types)/sizeof(dev->dev_stats.s_cproc_trap_types[0]); i++) -+ p += sprintf (p, "%-40s %ld\n", CProcTrapNames[i], dev->dev_stats.s_cproc_trap_types[i]); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_dproc_trap_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ int i; -+ extern char *const DProcTrapNames[]; -+ -+ for (i = 0; i < sizeof (dev->dev_stats.s_dproc_trap_types)/sizeof(dev->dev_stats.s_dproc_trap_types[0]); i++) -+ p += sprintf (p, "%-40s %ld\n", DProcTrapNames[i], dev->dev_stats.s_dproc_trap_types[i]); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_eproc_trap_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ int i; -+ extern char *const EProcTrapNames[]; -+ -+ for (i = 0; i < sizeof (dev->dev_stats.s_eproc_trap_types)/sizeof(dev->dev_stats.s_eproc_trap_types[0]); i++) -+ p += sprintf (p, "%-40s %ld\n", EProcTrapNames[i], dev->dev_stats.s_eproc_trap_types[i]); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_iproc_trap_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ int i; -+ extern char *const IProcTrapNames[]; -+ -+ for (i = 0; i < sizeof (dev->dev_stats.s_iproc_trap_types)/sizeof(dev->dev_stats.s_iproc_trap_types[0]); i++) -+ p += sprintf (p, "%-40s %ld\n", IProcTrapNames[i], dev->dev_stats.s_iproc_trap_types[i]); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_tproc_trap_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ int i; -+ extern char *const TProcTrapNames[]; -+ -+ for (i = 0; i < sizeof (dev->dev_stats.s_tproc_trap_types)/sizeof(dev->dev_stats.s_tproc_trap_types[0]); i++) -+ p += sprintf (p, "%-40s %ld\n", TProcTrapNames[i], dev->dev_stats.s_tproc_trap_types[i]); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_sdram_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ -+ p += sprintf (p, "%20s %ld\n", "correctable_errors", dev->dev_stats.s_correctable_errors); -+ p += sprintf (p, "%20s %ld\n", "multiple_errors", dev->dev_stats.s_multiple_errors); -+ p += sprintf (p, "%20s %ldK\n", "sdram_bytes_free", dev->dev_stats.s_sdram_bytes_free/1024); -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+void -+elan4_ringbuf_store(ELAN4_ROUTE_RINGBUF *ringbuf, E4_VirtualProcessEntry *route, ELAN4_DEV *dev) -+{ -+ int newend; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->dev_error_routes_lock, flags); -+ bcopy(route, &ringbuf->routes[ringbuf->end], sizeof(E4_VirtualProcessEntry)); -+ newend = ringbuf->end + 1; -+ if (newend >= DEV_STASH_ROUTE_COUNT) -+ newend -= DEV_STASH_ROUTE_COUNT; -+ if (newend == ringbuf->start) -+ ringbuf->start += 1; -+ if (ringbuf->start >= DEV_STASH_ROUTE_COUNT) -+ ringbuf->start -= DEV_STASH_ROUTE_COUNT; -+ ringbuf->end = newend; -+ spin_unlock_irqrestore(&dev->dev_error_routes_lock, flags); -+} -+ -+static int -+proc_read_dproc_timeout_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ unsigned int *dproc_timeout; -+ -+ dproc_timeout = dev->dev_dproc_timeout; -+ -+ if (!dproc_timeout) -+ p += sprintf (p, "No stats available\n"); -+ else -+ { -+ int i; -+ -+ for (i=0; idev_position.pos_nodes; i++) -+ if (dproc_timeout[i] != 0) -+ p += sprintf (p, "Node %d: %u errors\n", i, dproc_timeout[i]); -+ } -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+elan4_route2str (E4_VirtualProcessEntry *route, char *routeStr) -+{ -+ int part = 0; -+ int shift; -+ int broadcast; -+ E4_uint64 value; -+ char *ptr = routeStr; -+ int b; -+ -+ /* unpack first */ -+ value = route->Values[part] & 0x7f; -+ if ( (value & 0x78) == 0) { -+ /* empty route */ -+ strcpy(routeStr,"Invalid lead route"); -+ return (-EINVAL); -+ } -+ -+ if ( value & 0x40 ) { -+ /* broad cast */ -+ strcpy(routeStr,"Broadcast"); -+ return (-EINVAL); -+ } else { -+ switch ((value & 0x30) >> 4) { -+ case 0: { *ptr++ = '0' + (value & 0x7); break; } -+ case 1: { *ptr++ = 'M'; break; } -+ case 2: { *ptr++ = 'U'; break; } -+ case 3: { *ptr++ = 'A'; break; } -+ } -+ } -+ -+ shift = 16; -+ broadcast = 0; -+ while ( 1 ) { -+ b = (route->Values[part] >> shift) & 0xf; -+ -+ if ( broadcast ) { -+ /* about to pick up the second byte of a broadcast pair */ -+ broadcast = 0; -+ } else { -+ if ( b & 0x8) { -+ /* output link */ -+ *ptr++ = '0' + (b & 0x7); -+ } else { -+ if ( b & 0x4) { -+ /* broad cast */ -+ broadcast = 1; -+ } else { -+ switch ( b & 0x3 ) { -+ case 0: { *ptr++ = 0 ; return (0); break; } -+ case 1: { *ptr++ = 'M'; break; } -+ case 2: { *ptr++ = 'U'; break; } -+ case 3: { *ptr++ = 'A'; break; } -+ } -+ } -+ } -+ } -+ -+ shift += 4; -+ if ( part != 0 ) { -+ if ( shift > 36) { -+ /* too far, now in the crc value */ -+ strcpy(routeStr,"Invalid route length"); -+ return (-EINVAL); -+ } -+ } else { -+ if ( shift >= 64) { -+ /* move to the next 64 bits */ -+ part = 1; -+ shift = 2; -+ } -+ } -+ } -+ -+ /* never reached */ -+ return (-EINVAL); -+} -+ -+ -+static int -+proc_read_dproc_timeout_routes (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ ELAN4_ROUTE_RINGBUF *ringbuf; -+ char routestr[33]; -+ -+ ringbuf = &dev->dev_dproc_timeout_routes; -+ -+ if (!ringbuf) -+ p += sprintf (p, "No stats available\n"); -+ else -+ { -+ int start; -+ int end; -+ int i; -+ unsigned long flags; -+ -+ memset(&routestr, 0, 33); -+ -+ spin_lock_irqsave(&dev->dev_error_routes_lock, flags); -+ -+ start = ringbuf->start; -+ end = ringbuf->end; -+ -+ if (end < start) -+ end = DEV_STASH_ROUTE_COUNT; -+ -+ for (i=start; iroutes[i], routestr); -+ p += sprintf (p, "Route %llx %llx->%s\n", ringbuf->routes[i].Values[0], ringbuf->routes[i].Values[1], routestr); -+ } -+ -+ if (ringbuf->end < start) -+ { -+ start = 0; -+ end = ringbuf->end; -+ for (i=start; iroutes[i], routestr); -+ p += sprintf (p, "Route %llx %llx->%s\n", ringbuf->routes[i].Values[0], ringbuf->routes[i].Values[1], routestr); -+ } -+ } -+ -+ spin_unlock_irqrestore(&dev->dev_error_routes_lock, flags); -+ } -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+ -+static int -+proc_read_cproc_timeout_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ unsigned int *cproc_timeout; -+ -+ cproc_timeout = dev->dev_cproc_timeout; -+ -+ if (!cproc_timeout) -+ p += sprintf (p, "No stats available\n"); -+ else -+ { -+ int i; -+ -+ for (i=0; idev_position.pos_nodes; i++) -+ if (cproc_timeout[i] != 0) -+ p += sprintf (p, "Node %d: %u errors\n", i, cproc_timeout[i]); -+ } -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_cproc_timeout_routes (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ ELAN4_ROUTE_RINGBUF *ringbuf; -+ char routestr[33]; -+ -+ ringbuf = &dev->dev_cproc_timeout_routes; -+ -+ if (!ringbuf) -+ p += sprintf (p, "No stats available\n"); -+ else -+ { -+ int start; -+ int end; -+ int i; -+ unsigned long flags; -+ -+ memset(&routestr, 0, 33); -+ -+ spin_lock_irqsave(&dev->dev_error_routes_lock, flags); -+ -+ start = ringbuf->start; -+ end = ringbuf->end; -+ -+ if (end < start) -+ end = DEV_STASH_ROUTE_COUNT; -+ -+ for (i=start; iroutes[i], routestr); -+ p += sprintf (p, "Route %llx %llx->%s\n", ringbuf->routes[i].Values[0], ringbuf->routes[i].Values[1], routestr); -+ } -+ -+ if (ringbuf->end < start) -+ { -+ start = 0; -+ end = ringbuf->end; -+ for (i=start; iroutes[i], routestr); -+ p += sprintf (p, "Route %llx %llx->%s\n", ringbuf->routes[i].Values[0], ringbuf->routes[i].Values[1], routestr); -+ } -+ } -+ -+ spin_unlock_irqrestore(&dev->dev_error_routes_lock, flags); -+ } -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_traperr_stats (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ unsigned int *ack_errors; -+ -+ ack_errors = dev->dev_ack_errors; -+ -+ if (!ack_errors) -+ p += sprintf (p, "No stats available\n"); -+ else -+ { -+ int i; -+ -+ for (i=0; idev_position.pos_nodes; i++) -+ if (ack_errors[i] != 0) -+ p += sprintf (p, "Node %d: %u errors\n", i, ack_errors[i]); -+ } -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static int -+proc_read_ackerror_routes (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ char *p = page; -+ ELAN4_ROUTE_RINGBUF *ringbuf; -+ char routestr[33]; -+ -+ ringbuf = &dev->dev_ack_error_routes; -+ -+ if (!ringbuf) -+ p += sprintf (p, "No stats available\n"); -+ else -+ { -+ int start; -+ int end; -+ int i; -+ unsigned long flags; -+ -+ memset(&routestr, 0, 33); -+ -+ spin_lock_irqsave(&dev->dev_error_routes_lock, flags); -+ -+ start = ringbuf->start; -+ end = ringbuf->end; -+ -+ if (end < start) -+ end = DEV_STASH_ROUTE_COUNT; -+ -+ for (i=start; iroutes[i], routestr); -+ p += sprintf (p, "Route %llx %llx->%s\n", ringbuf->routes[i].Values[0], ringbuf->routes[i].Values[1], routestr); -+ } -+ -+ if (ringbuf->end < start) -+ { -+ start = 0; -+ end = ringbuf->end; -+ for (i=start; iroutes[i], routestr); -+ p += sprintf (p, "Route %llx %llx->%s\n", ringbuf->routes[i].Values[0], ringbuf->routes[i].Values[1], routestr); -+ } -+ } -+ -+ spin_unlock_irqrestore(&dev->dev_error_routes_lock, flags); -+ } -+ -+ return (proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static struct stats_info -+{ -+ char *name; -+ int (*read_func) (char *page, char **start, off_t off, int count, int *eof, void *data); -+ int (*write_func) (struct file *file, const char *buf, unsigned long count, void *data); -+} stats_info[] = { -+ {"link", proc_read_link_stats, NULL}, -+ {"intr", proc_read_intr_stats, NULL}, -+ {"trap", proc_read_trap_stats, NULL}, -+ {"cproc", proc_read_cproc_trap_stats, NULL}, -+ {"dproc", proc_read_dproc_trap_stats, NULL}, -+ {"eproc", proc_read_eproc_trap_stats, NULL}, -+ {"iproc", proc_read_iproc_trap_stats, NULL}, -+ {"tproc", proc_read_tproc_trap_stats, NULL}, -+ {"sdram", proc_read_sdram_stats, NULL}, -+ {"trapdmaerr", proc_read_traperr_stats, NULL}, -+ {"dproctimeout", proc_read_dproc_timeout_stats, NULL}, -+ {"cproctimeout", proc_read_cproc_timeout_stats, NULL}, -+ {"dproctimeoutroutes", proc_read_dproc_timeout_routes, NULL}, -+ {"cproctimeoutroutes", proc_read_cproc_timeout_routes, NULL}, -+ {"ackerrroutes", proc_read_ackerror_routes, NULL}, -+}; -+ -+static int -+proc_read_sysconfig (char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ E4_uint32 syscontrol = dev->dev_syscontrol; -+ int len = 0; -+ -+ *eof = 1; -+ if (off != 0) -+ return (0); -+ -+ if (syscontrol & CONT_EN_ALL_SETS) -+ len += sprintf (page + len, "%sEN_ALL_SETS", len == 0 ? "" : " "); -+ if (syscontrol & CONT_MMU_ENABLE) -+ len += sprintf (page + len, "%sMMU_ENABLE", len == 0 ? "" : " "); -+ if (syscontrol & CONT_CACHE_HASH_TABLE) -+ len += sprintf (page + len, "%sCACHE_HASH_TABLE", len == 0 ? "" : " "); -+ if (syscontrol & CONT_CACHE_CHAINS) -+ len += sprintf (page + len, "%sCACHE_CHAINS", len == 0 ? "" : " "); -+ if (syscontrol & CONT_CACHE_ROOT_CNTX) -+ len += sprintf (page + len, "%sCACHE_ROOT_CNTX", len == 0 ? "" : " "); -+ if (syscontrol & CONT_CACHE_STEN_ROUTES) -+ len += sprintf (page + len, "%sCACHE_STEN_ROUTES", len == 0 ? "" : " "); -+ if (syscontrol & CONT_CACHE_DMA_ROUTES) -+ len += sprintf (page + len, "%sCACHE_DMA_ROUTES", len == 0 ? "" : " "); -+ if (syscontrol & CONT_INHIBIT_MAX_CHAIN_ITEMS) -+ len += sprintf (page + len, "%sINHIBIT_MAX_CHAIN_ITEMS", len == 0 ? "" : " "); -+ -+ len += sprintf (page + len, "%sTABLE0_MASK_SIZE=%d", len == 0 ? "" : " ", (syscontrol >> CONT_TABLE0_MASK_SIZE_SHIFT) & PAGE_MASK_MASK); -+ len += sprintf (page + len, "%sTABLE0_PAGE_SIZE=%d", len == 0 ? "" : " ", (syscontrol >> CONT_TABLE0_PAGE_SIZE_SHIFT) & PAGE_SIZE_MASK); -+ len += sprintf (page + len, "%sTABLE1_MASK_SIZE=%d", len == 0 ? "" : " ", (syscontrol >> CONT_TABLE1_MASK_SIZE_SHIFT) & PAGE_MASK_MASK); -+ len += sprintf (page + len, "%sTABLE1_PAGE_SIZE=%d", len == 0 ? "" : " ", (syscontrol >> CONT_TABLE1_PAGE_SIZE_SHIFT) & PAGE_SIZE_MASK); -+ -+ if (syscontrol & CONT_2K_NOT_1K_DMA_PACKETS) -+ len += sprintf (page + len, "%s2K_NOT_1K_DMA_PACKETS", len == 0 ? "" : " "); -+ if (syscontrol & CONT_ALIGN_ALL_DMA_PACKETS) -+ len += sprintf (page + len, "%sALIGN_ALL_DMA_PACKETS", len == 0 ? "" : " "); -+ if (syscontrol & CONT_DIRECT_MAP_PCI_WRITES) -+ len += sprintf (page + len, "%sDIRECT_MAP_PCI_WRITES", len == 0 ? "" : " "); -+ -+ len += sprintf (page + len, "\n"); -+ -+ *start = page; -+ return (len); -+} -+ -+static int -+proc_write_sysconfig (struct file *file, const char *ubuffer, unsigned long count, void *data) -+{ -+ ELAN4_DEV *dev = (ELAN4_DEV *) data; -+ unsigned long page = __get_free_page (GFP_KERNEL); -+ char *buffer = (char *)page; -+ int add = 0; -+ int sub = 0; -+ -+ count = MIN (count, PAGE_SIZE - 1); -+ if (copy_from_user (buffer, ubuffer, count)) -+ { -+ free_page (page); -+ return (-EFAULT); -+ } -+ -+ buffer[count] = 0; /* terminate string */ -+ -+ while (*buffer != 0) -+ { -+ char *ptr; -+ char *end; -+ int ch; -+ int val; -+ int op; -+ -+ ch = *buffer; -+ if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') -+ { -+ buffer++; -+ continue; -+ } -+ -+ op = *buffer; -+ if (op == '+' || op == '-') -+ buffer++; -+ -+ for (end = buffer; *end != 0; end++) -+ if (*end == ' ' || *end == '\t' || -+ *end == '\r' || *end == '\n') -+ break; -+ -+ if (end == buffer) -+ break; -+ -+ ch = *end; -+ *end = 0; -+ -+ for (ptr = buffer; *ptr != 0; ptr++) -+ if ('a' <= *ptr && *ptr <= 'z') -+ *ptr = *ptr + 'A' - 'a'; -+ -+ if (!strcmp (buffer, "EN_ALL_SETS")) -+ val = CONT_EN_ALL_SETS; -+ if (!strcmp (buffer, "CACHE_HASH_TABLE")) -+ val = CONT_CACHE_HASH_TABLE; -+ else if (!strcmp (buffer, "CACHE_CHAINS")) -+ val = CONT_CACHE_CHAINS; -+ else if (!strcmp (buffer, "CACHE_ROOT_CNTX")) -+ val = CONT_CACHE_ROOT_CNTX; -+ else if (!strcmp (buffer, "CACHE_STEN_ROUTES")) -+ val = CONT_CACHE_STEN_ROUTES; -+ else if (!strcmp (buffer, "CACHE_DMA_ROUTES")) -+ val = CONT_CACHE_DMA_ROUTES; -+ else if (!strcmp (buffer, "2K_NOT_1K_DMA_PACKETS")) -+ val = CONT_2K_NOT_1K_DMA_PACKETS; -+ else if (!strcmp (buffer, "ALIGN_ALL_DMA_PACKETS")) -+ val = CONT_ALIGN_ALL_DMA_PACKETS; -+ else -+ val = 0; -+ -+ if (op == '+') -+ add |= val; -+ else if (op == '-') -+ sub |= val; -+ -+ *end = ch; -+ buffer = end; -+ } -+ -+ if ((add | sub) & CONT_EN_ALL_SETS) -+ elan4_sdram_flushcache (dev, 0, E4_CacheSize); -+ -+ CHANGE_SYSCONTROL (dev, add, sub); -+ -+ if ((add | sub) & CONT_EN_ALL_SETS) -+ elan4_sdram_flushcache (dev, 0, E4_CacheSize); -+ -+ free_page (page); -+ return (count); -+} -+ -+static struct config_info -+{ -+ char *name; -+ int (*read_func) (char *page, char **start, off_t off, int count, int *eof, void *data); -+ int (*write_func) (struct file *file, const char *buf, unsigned long count, void *data); -+} config_info[] = { -+ {"sysconfig", proc_read_sysconfig, proc_write_sysconfig}, -+}; -+ -+void -+elan4_procfs_device_init (ELAN4_DEV *dev) -+{ -+ struct proc_dir_entry *p; -+ char name[NAME_MAX]; -+ int i; -+ -+ sprintf (name, "device%d", dev->dev_instance); -+ dev->dev_osdep.procdir = proc_mkdir (name, elan4_procfs_root); -+ -+ for (i = 0; i < sizeof (device_info)/sizeof (device_info[0]); i++) -+ { -+ if (dev->dev_devinfo.dev_revision_id < device_info[i].minrev) -+ continue; -+ -+ if ((p = create_proc_entry (device_info[i].name, 0, dev->dev_osdep.procdir)) != NULL) -+ { -+ p->read_proc = device_info[i].read_func; -+ p->write_proc = device_info[i].write_func; -+ p->data = dev; -+ p->owner = THIS_MODULE; -+ } -+ } -+ -+ dev->dev_osdep.configdir = proc_mkdir ("config", dev->dev_osdep.procdir); -+ for (i = 0; i < sizeof (config_info)/sizeof (config_info[0]); i++) -+ { -+ if ((p = create_proc_entry (config_info[i].name, 0, dev->dev_osdep.configdir)) != NULL) -+ { -+ p->read_proc = config_info[i].read_func; -+ p->write_proc = config_info[i].write_func; -+ p->data = dev; -+ p->owner = THIS_MODULE; -+ } -+ } -+ -+ dev->dev_osdep.statsdir = proc_mkdir ("stats", dev->dev_osdep.procdir); -+ for (i = 0; i < sizeof (stats_info)/sizeof (stats_info[0]); i++) -+ { -+ if ((p = create_proc_entry (stats_info[i].name, 0, dev->dev_osdep.statsdir)) != NULL) -+ { -+ p->read_proc = stats_info[i].read_func; -+ p->write_proc = stats_info[i].write_func; -+ p->data = dev; -+ p->owner = THIS_MODULE; -+ } -+ } -+} -+ -+void -+elan4_procfs_device_fini (ELAN4_DEV *dev) -+{ -+ char name[NAME_MAX]; -+ int i; -+ -+ for (i = 0; i < sizeof (stats_info)/sizeof (stats_info[0]); i++) -+ remove_proc_entry (stats_info[i].name, dev->dev_osdep.statsdir); -+ remove_proc_entry ("stats", dev->dev_osdep.procdir); -+ -+ for (i = 0; i < sizeof (config_info)/sizeof (config_info[0]); i++) -+ remove_proc_entry (config_info[i].name, dev->dev_osdep.configdir); -+ remove_proc_entry ("config", dev->dev_osdep.procdir); -+ -+ for (i = 0; i < sizeof (device_info)/sizeof (device_info[0]); i++) -+ { -+ if (dev->dev_devinfo.dev_revision_id < device_info[i].minrev) -+ continue; -+ -+ remove_proc_entry (device_info[i].name, dev->dev_osdep.procdir); -+ } -+ -+ sprintf (name, "device%d", dev->dev_instance); -+ remove_proc_entry (name, elan4_procfs_root); -+} -+ -+void -+elan4_procfs_init(void) -+{ -+ elan4_procfs_root = proc_mkdir("elan4", qsnet_procfs_root); -+ elan4_config_root = proc_mkdir("config", elan4_procfs_root); -+ -+ qsnet_proc_register_hex (elan4_config_root, "elan4_debug", &elan4_debug, 0); -+ qsnet_proc_register_hex (elan4_config_root, "elan4_debug_toconsole", &elan4_debug_toconsole, 0); -+ qsnet_proc_register_hex (elan4_config_root, "elan4_debug_tobuffer", &elan4_debug_tobuffer, 0); -+ qsnet_proc_register_int (elan4_config_root, "elan4_debug_mmu", &elan4_debug_mmu, 0); -+ qsnet_proc_register_int (elan4_config_root, "elan4_mainint_punt_loops", &elan4_mainint_punt_loops, 0); -+ qsnet_proc_register_hex (elan4_config_root, "user_p2p_route_options", &user_p2p_route_options, 0); -+ qsnet_proc_register_hex (elan4_config_root, "user_bcast_route_options", &user_bcast_route_options, 0); -+ qsnet_proc_register_int (elan4_config_root, "user_dproc_retry_count", &user_dproc_retry_count, 0); -+ qsnet_proc_register_int (elan4_config_root, "user_cproc_retry_count", &user_cproc_retry_count, 0); -+ qsnet_proc_register_int (elan4_config_root, "num_fault_save", &num_fault_save, 0); -+ qsnet_proc_register_int (elan4_config_root, "min_fault_pages", &min_fault_pages, 0); -+ qsnet_proc_register_int (elan4_config_root, "max_fault_pages", &max_fault_pages, 0); -+} -+ -+void -+elan4_procfs_fini(void) -+{ -+ remove_proc_entry ("max_fault_pages", elan4_config_root); -+ remove_proc_entry ("min_fault_pages", elan4_config_root); -+ remove_proc_entry ("num_fault_save", elan4_config_root); -+ remove_proc_entry ("user_cproc_retry_count", elan4_config_root); -+ remove_proc_entry ("user_dproc_retry_count", elan4_config_root); -+ remove_proc_entry ("user_bcast_route_options", elan4_config_root); -+ remove_proc_entry ("user_p2p_route_options", elan4_config_root); -+ remove_proc_entry ("elan4_mainint_punt_loops", elan4_config_root); -+ remove_proc_entry ("elan4_debug_mmu", elan4_config_root); -+ remove_proc_entry ("elan4_debug_tobuffer", elan4_config_root); -+ remove_proc_entry ("elan4_debug_toconsole", elan4_config_root); -+ remove_proc_entry ("elan4_debug", elan4_config_root); -+ -+ remove_proc_entry ("config", elan4_procfs_root); -+ remove_proc_entry ("elan4", qsnet_procfs_root); -+} -+ -+EXPORT_SYMBOL(elan4_procfs_root); -+EXPORT_SYMBOL(elan4_config_root); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/quadrics_version.h 2005-06-01 23:12:54.614436824 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/elan4/regions.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/regions.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/regions.c 2005-06-01 23:12:54.615436672 -0400 -@@ -0,0 +1,609 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: regions.c,v 1.18.2.1 2004/11/18 11:31:08 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/regions.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+/*================================================================================*/ -+/* elan address region management */ -+USER_RGN * -+user_findrgn_elan (USER_CTXT *uctx, E4_Addr addr, int tail) -+{ -+ USER_RGN *rgn; -+ USER_RGN *hirgn; -+ USER_RGN *lorgn; -+ E4_Addr base; -+ E4_Addr lastaddr; -+ int forward; -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_rgnlock) || kmutex_is_locked (&uctx->uctx_rgnmutex)); -+ -+ if (uctx->uctx_ergns == NULL) -+ return (NULL); -+ -+ rgn = uctx->uctx_ergnlast; -+ if (rgn == NULL) -+ rgn = uctx->uctx_ergns; -+ -+ forward = 0; -+ if ((base = rgn->rgn_ebase) < addr) -+ { -+ if (addr <= (base + rgn->rgn_len - 1)) -+ return (rgn); /* ergnlast contained addr */ -+ -+ hirgn = uctx->uctx_etail; -+ -+ if ((lastaddr = (hirgn->rgn_ebase + hirgn->rgn_len - 1)) < addr) -+ return (tail ? hirgn : NULL); /* addr is out of range */ -+ -+ if ((addr - base) > (lastaddr - addr)) -+ rgn = hirgn; -+ else -+ { -+ rgn = rgn->rgn_enext; -+ forward++; -+ } -+ } -+ else -+ { -+ lorgn = uctx->uctx_ergns; -+ -+ if (lorgn->rgn_ebase > addr) -+ return (lorgn); /* lowest regions is higher than addr */ -+ if ((addr - lorgn->rgn_ebase) < (base - addr)) -+ { -+ rgn = lorgn; /* search forward from head */ -+ forward++; -+ } -+ } -+ if (forward) -+ { -+ while ((rgn->rgn_ebase + rgn->rgn_len - 1) < addr) -+ rgn = rgn->rgn_enext; -+ -+ if (rgn->rgn_ebase <= addr) -+ uctx->uctx_ergnlast = rgn; -+ return (rgn); -+ } -+ else -+ { -+ while (rgn->rgn_ebase > addr) -+ rgn = rgn->rgn_eprev; -+ -+ if ((rgn->rgn_ebase + rgn->rgn_len - 1) < addr) -+ return (rgn->rgn_enext); -+ else -+ { -+ uctx->uctx_ergnlast = rgn; -+ return (rgn); -+ } -+ } -+} -+ -+static int -+user_addrgn_elan (USER_CTXT *uctx, USER_RGN *nrgn) -+{ -+ USER_RGN *rgn = user_findrgn_elan (uctx, nrgn->rgn_ebase, 1); -+ E4_Addr nbase = nrgn->rgn_ebase; -+ E4_Addr ntop = nbase + nrgn->rgn_len - 1; -+ E4_Addr base; -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_rgnlock) && kmutex_is_locked (&uctx->uctx_rgnmutex)); -+ -+ if (rgn == NULL) -+ { -+ uctx->uctx_ergns = uctx->uctx_etail = nrgn; -+ nrgn->rgn_enext = nrgn->rgn_eprev = NULL; -+ } -+ else -+ { -+ base = rgn->rgn_ebase; -+ -+ if ((base + rgn->rgn_len - 1) < nbase) /* top of region below requested address */ -+ { /* so insert after region (and hence at end */ -+ nrgn->rgn_eprev = rgn; /* of list */ -+ nrgn->rgn_enext = NULL; -+ rgn->rgn_enext = uctx->uctx_etail = nrgn; -+ } -+ else -+ { -+ if (nbase >= base || ntop >= base) /* overlapping region */ -+ return (-1); -+ -+ nrgn->rgn_enext = rgn; /* insert before region */ -+ nrgn->rgn_eprev = rgn->rgn_eprev; -+ rgn->rgn_eprev = nrgn; -+ if (uctx->uctx_ergns == rgn) -+ uctx->uctx_ergns = nrgn; -+ else -+ nrgn->rgn_eprev->rgn_enext = nrgn; -+ } -+ } -+ uctx->uctx_ergnlast = nrgn; -+ -+ return (0); -+} -+ -+static USER_RGN * -+user_removergn_elan (USER_CTXT *uctx, USER_RGN *rgn) -+{ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_rgnlock) && kmutex_is_locked (&uctx->uctx_rgnmutex)); -+ -+ uctx->uctx_ergnlast = rgn->rgn_enext; -+ if (rgn == uctx->uctx_etail) -+ uctx->uctx_etail = rgn->rgn_eprev; -+ else -+ rgn->rgn_enext->rgn_eprev = rgn->rgn_eprev; -+ -+ if (rgn == uctx->uctx_ergns) -+ uctx->uctx_ergns = rgn->rgn_enext; -+ else -+ rgn->rgn_eprev->rgn_enext = rgn->rgn_enext; -+ -+ return (rgn); -+} -+ -+USER_RGN * -+user_rgnat_elan (USER_CTXT *uctx, E4_Addr addr) -+{ -+ USER_RGN *rgn = user_findrgn_elan (uctx, addr, 0); -+ -+ if (rgn != NULL && rgn->rgn_ebase <= addr && addr <= (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ return (rgn); -+ -+ return (NULL); -+} -+ -+/* main address region management */ -+USER_RGN * -+user_findrgn_main (USER_CTXT *uctx, virtaddr_t addr, int tail) -+{ -+ USER_RGN *rgn; -+ USER_RGN *hirgn; -+ USER_RGN *lorgn; -+ virtaddr_t lastaddr; -+ virtaddr_t base; -+ int forward; -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_rgnlock) || kmutex_is_locked (&uctx->uctx_rgnmutex)); -+ -+ if (uctx->uctx_mrgns == NULL) -+ return (NULL); -+ -+ rgn = uctx->uctx_mrgnlast; -+ if (rgn == NULL) -+ rgn = uctx->uctx_mrgns; -+ -+ forward = 0; -+ if ((base = rgn->rgn_mbase) < addr) -+ { -+ if (addr <= (base + rgn->rgn_len - 1)) -+ return (rgn); /* ergnlast contained addr */ -+ -+ hirgn = uctx->uctx_mtail; -+ if ((lastaddr = hirgn->rgn_mbase + hirgn->rgn_len - 1) < addr) -+ return (tail ? hirgn : NULL); /* addr is out of range */ -+ -+ if ((addr - base) > (lastaddr - addr)) -+ rgn = hirgn; -+ else -+ { -+ rgn = rgn->rgn_mnext; -+ forward++; -+ } -+ } -+ else -+ { -+ lorgn = uctx->uctx_mrgns; -+ if (lorgn->rgn_mbase > addr) -+ return (lorgn); /* lowest regions is higher than addr */ -+ if ((addr - lorgn->rgn_mbase) < (base - addr)) -+ { -+ rgn = lorgn; /* search forward from head */ -+ forward++; -+ } -+ } -+ if (forward) -+ { -+ while ((rgn->rgn_mbase + rgn->rgn_len - 1) < addr) -+ rgn = rgn->rgn_mnext; -+ -+ if (rgn->rgn_mbase <= addr) -+ uctx->uctx_mrgnlast = rgn; -+ return (rgn); -+ } -+ else -+ { -+ while (rgn->rgn_mbase > addr) -+ rgn = rgn->rgn_mprev; -+ -+ if ((rgn->rgn_mbase + rgn->rgn_len - 1) < addr) -+ return (rgn->rgn_mnext); -+ else -+ { -+ uctx->uctx_mrgnlast = rgn; -+ return (rgn); -+ } -+ } -+} -+ -+static int -+user_addrgn_main (USER_CTXT *uctx, USER_RGN *nrgn) -+{ -+ USER_RGN *rgn = user_findrgn_main (uctx, nrgn->rgn_mbase, 1); -+ virtaddr_t nbase = nrgn->rgn_mbase; -+ virtaddr_t ntop = nbase + nrgn->rgn_len - 1; -+ virtaddr_t base; -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_rgnlock) && kmutex_is_locked (&uctx->uctx_rgnmutex)); -+ -+ if (rgn == NULL) -+ { -+ uctx->uctx_mrgns = uctx->uctx_mtail = nrgn; -+ nrgn->rgn_mnext = nrgn->rgn_mprev = NULL; -+ } -+ else -+ { -+ base = rgn->rgn_mbase; -+ -+ if ((base + rgn->rgn_len - 1) < nbase) /* top of region below requested address */ -+ { /* so insert after region (and hence at end */ -+ nrgn->rgn_mprev = rgn; /* of list */ -+ nrgn->rgn_mnext = NULL; -+ rgn->rgn_mnext = uctx->uctx_mtail = nrgn; -+ } -+ else -+ { -+ if (nbase >= base || ntop >= base) /* overlapping region */ -+ return (-1); -+ -+ nrgn->rgn_mnext = rgn; /* insert before region */ -+ nrgn->rgn_mprev = rgn->rgn_mprev; -+ rgn->rgn_mprev = nrgn; -+ if (uctx->uctx_mrgns == rgn) -+ uctx->uctx_mrgns = nrgn; -+ else -+ nrgn->rgn_mprev->rgn_mnext = nrgn; -+ } -+ } -+ uctx->uctx_mrgnlast = nrgn; -+ -+ return (0); -+} -+ -+static USER_RGN * -+user_removergn_main (USER_CTXT *uctx, USER_RGN *rgn) -+{ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_rgnlock) && kmutex_is_locked (&uctx->uctx_rgnmutex)); -+ -+ uctx->uctx_mrgnlast = rgn->rgn_mnext; -+ if (rgn == uctx->uctx_mtail) -+ uctx->uctx_mtail = rgn->rgn_mprev; -+ else -+ rgn->rgn_mnext->rgn_mprev = rgn->rgn_mprev; -+ -+ if (rgn == uctx->uctx_mrgns) -+ uctx->uctx_mrgns = rgn->rgn_mnext; -+ else -+ rgn->rgn_mprev->rgn_mnext = rgn->rgn_mnext; -+ -+ return (rgn); -+} -+ -+/* Remove whole region from both lists */ -+static void -+user_removergn (USER_CTXT *uctx, USER_RGN *rgn) -+{ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* XXXX tbl */, rgn->rgn_ebase, rgn->rgn_len); -+ -+ user_removergn_elan (uctx, rgn); -+ user_removergn_main (uctx, rgn); -+ -+ spin_unlock (&uctx->uctx_rgnlock); -+ -+ KMEM_FREE (rgn, sizeof (USER_RGN)); -+} -+ -+/* Remove all allocated regions */ -+void -+user_freergns (USER_CTXT *uctx) -+{ -+ kmutex_lock (&uctx->uctx_rgnmutex); -+ -+ while (uctx->uctx_mrgns) -+ user_removergn(uctx, uctx->uctx_mrgns); -+ -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ -+ ASSERT (uctx->uctx_ergns == NULL); -+} -+ -+USER_RGN * -+user_rgnat_main (USER_CTXT *uctx, virtaddr_t addr) -+{ -+ USER_RGN *rgn = user_findrgn_main (uctx, addr, 0); -+ -+ if (rgn != NULL && rgn->rgn_mbase <= addr && addr <= (rgn->rgn_mbase + rgn->rgn_len - 1)) -+ return (rgn); -+ return (NULL); -+} -+ -+int -+user_setperm (USER_CTXT *uctx, virtaddr_t maddr, E4_Addr eaddr, unsigned long len, unsigned perm) -+{ -+ USER_RGN *nrgn; -+ -+ PRINTF4 (uctx, DBG_PERM, "user_setperm: user %lx elan %llx len %lx perm %x\n", maddr, (long long) eaddr, len, perm); -+ -+ if ((maddr & PAGEOFFSET) || (eaddr & PAGEOFFSET) || (len & PAGEOFFSET)) -+ { -+ PRINTF0 (uctx, DBG_PERM, "user_setperm: alignment failure\n"); -+ return (-EINVAL); -+ } -+ -+ if ((maddr + len - 1) <= maddr || (eaddr + len - 1) <= eaddr) -+ { -+ PRINTF0 (uctx, DBG_PERM, "user_setperm: range failure\n"); -+ return (-EINVAL); -+ } -+ -+ KMEM_ALLOC (nrgn, USER_RGN *, sizeof (USER_RGN), 1); -+ -+ if (nrgn == NULL) -+ return (-ENOMEM); -+ -+ nrgn->rgn_mbase = maddr; -+ nrgn->rgn_ebase = eaddr; -+ nrgn->rgn_len = len; -+ nrgn->rgn_perm = perm; -+ -+ kmutex_lock (&uctx->uctx_rgnmutex); -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ if (user_addrgn_elan (uctx, nrgn) < 0) -+ { -+ PRINTF0 (uctx, DBG_PERM, "user_setperm: elan address exists\n"); -+ spin_unlock (&uctx->uctx_rgnlock); -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ -+ KMEM_FREE (nrgn, sizeof (USER_RGN)); -+ return (-EINVAL); -+ } -+ -+ if (user_addrgn_main (uctx, nrgn) < 0) -+ { -+ PRINTF0 (uctx, DBG_PERM, "user_setperm: main address exists\n"); -+ user_removergn_elan (uctx, nrgn); -+ -+ spin_unlock (&uctx->uctx_rgnlock); -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ -+ KMEM_FREE (nrgn, sizeof (USER_RGN)); -+ return (-EINVAL); -+ } -+ spin_unlock (&uctx->uctx_rgnlock); -+ -+ if ((perm & PERM_Preload)) -+ user_preload_main (uctx, maddr, len); -+ -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ -+ return (0); -+} -+ -+void -+user_clrperm (USER_CTXT *uctx, E4_Addr addr, unsigned long len) -+{ -+ E4_Addr raddr; -+ E4_Addr rtop; -+ USER_RGN *nrgn; -+ USER_RGN *rgn; -+ USER_RGN *rgn_next; -+ unsigned long ssize; -+ int res; -+ -+ PRINTF2 (uctx, DBG_PERM, "user_clrperm: elan %llx len %lx\n", addr, len); -+ -+ raddr = (addr & PAGEMASK); -+ rtop = ((addr + len - 1) & PAGEMASK) + (PAGESIZE-1); -+ -+ kmutex_lock (&uctx->uctx_rgnmutex); -+ -+ for (rgn = user_findrgn_elan (uctx, addr, 0); rgn != NULL; rgn = rgn_next) -+ { -+ if (rtop < rgn->rgn_ebase) /* rtop was in a gap */ -+ break; -+ -+ rgn_next = rgn->rgn_enext; /* Save next region pointer */ -+ -+ PRINTF (uctx, DBG_PERM, " elan %llx->%llx main %p->%p\n", -+ rgn->rgn_ebase, rgn->rgn_ebase + rgn->rgn_len-1, -+ rgn->rgn_mbase, rgn->rgn_mbase + rgn->rgn_len-1); -+ -+ if (raddr <= rgn->rgn_ebase && rtop >= (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ { -+ /* whole region is cleared */ -+ -+ PRINTF (uctx, DBG_PERM, " whole region\n"); -+ PRINTF (uctx, DBG_PERM, " unload elan %llx->%llx\n", rgn->rgn_ebase, rgn->rgn_ebase + rgn->rgn_len-1); -+ user_removergn (uctx, rgn); -+ } -+ else if (raddr <= rgn->rgn_ebase) -+ { -+ /* clearing at beginning, so shrink size and increment base ptrs */ -+ ssize = rtop - rgn->rgn_ebase + 1; -+ -+ PRINTF (uctx, DBG_PERM, " clear at beginning %x\n", ssize); -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ PRINTF (uctx, DBG_PERM, " unload elan %llx->%llx\n", rgn->rgn_ebase, rgn->rgn_ebase + ssize-1); -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* XXXX tbl */, rgn->rgn_ebase, ssize); -+ -+ rgn->rgn_mbase += ssize; -+ rgn->rgn_ebase += ssize; -+ rgn->rgn_len -= ssize; -+ -+ spin_unlock(&uctx->uctx_rgnlock); -+ } -+ else if (rtop >= (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ { -+ /* clearing at end, so just shrink length of region */ -+ ssize = (rgn->rgn_ebase + rgn->rgn_len - 1) - raddr + 1; -+ -+ PRINTF (uctx, DBG_PERM, " clear at end %x\n", ssize); -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ PRINTF (uctx, DBG_PERM, " unload elan %llx->%llx\n", raddr, raddr+ssize-1); -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* XXXX tbl */, raddr, ssize); -+ -+ rgn->rgn_len -= ssize; -+ -+ spin_unlock(&uctx->uctx_rgnlock); -+ } -+ else -+ { -+ /* the section to go is in the middle, so need to */ -+ /* split it into two regions */ -+ KMEM_ALLOC (nrgn, USER_RGN *, sizeof (USER_RGN), 1); -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ PRINTF (uctx, DBG_PERM, " unload elan %llx->%llx\n", raddr, rtop); -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* XXXX tbl */, raddr, rtop - raddr + 1); -+ -+ nrgn->rgn_mbase = rgn->rgn_mbase + (rtop - rgn->rgn_ebase + 1); -+ nrgn->rgn_ebase = rtop + 1; -+ nrgn->rgn_len = (rgn->rgn_ebase + rgn->rgn_len - 1) - rtop; -+ nrgn->rgn_perm = rgn->rgn_perm; -+ -+ PRINTF (uctx, DBG_PERM, " new elan %llx->%llx main %p->%p\n", -+ nrgn->rgn_ebase, nrgn->rgn_ebase + nrgn->rgn_len-1, -+ nrgn->rgn_mbase, nrgn->rgn_mbase + nrgn->rgn_len-1); -+ -+ rgn->rgn_len = (raddr - rgn->rgn_ebase); /* shrink original region */ -+ -+ PRINTF (uctx, DBG_PERM, " old elan %llx->%llx main %p->%p\n", -+ rgn->rgn_ebase, rgn->rgn_ebase + rgn->rgn_len-1, -+ rgn->rgn_mbase, rgn->rgn_mbase + rgn->rgn_len-1); -+ -+ res = user_addrgn_elan (uctx, nrgn); /* insert new region */ -+ ASSERT (res == 0); /* which cannot fail */ -+ -+ res = user_addrgn_main (uctx, nrgn); -+ ASSERT (res == 0); -+ -+ spin_unlock(&uctx->uctx_rgnlock); -+ } -+ } -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+} -+ -+int -+user_checkperm (USER_CTXT *uctx, E4_Addr raddr, unsigned long rsize, unsigned access) -+{ -+ USER_RGN *rgn; -+ -+ PRINTF3 (uctx, DBG_PERM, "user_checkperm: elan %lx len %lx access %x\n", raddr, rsize, access); -+ -+ if ((raddr + rsize - 1) < raddr) -+ return (-ENOMEM); -+ -+ kmutex_lock (&uctx->uctx_rgnmutex); -+ if ((rgn = user_rgnat_elan (uctx, raddr)) == (USER_RGN *) NULL) -+ { -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (-ENOMEM); -+ } -+ else -+ { -+ register int ssize; -+ -+ for (; rsize != 0; rsize -= ssize, raddr += ssize) -+ { -+ if (raddr > (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ { -+ rgn = rgn->rgn_enext; -+ -+ if (rgn == NULL || raddr != rgn->rgn_ebase) -+ { -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (-ENOMEM); -+ } -+ } -+ if ((raddr + rsize - 1) > (rgn->rgn_ebase + rgn->rgn_len - 1)) -+ ssize = ((rgn->rgn_ebase + rgn->rgn_len - 1) - raddr) + 1; -+ else -+ ssize = rsize; -+ -+ PRINTF4 (uctx, DBG_PERM, "user_checkperm : rgn %lx -> %lx perm %x access %x\n", -+ rgn->rgn_ebase, rgn->rgn_ebase + (E4_Addr)rgn->rgn_len, rgn->rgn_perm, access); -+ -+ if (ELAN4_INCOMPAT_ACCESS (rgn->rgn_perm, access)) -+ { -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (-EACCES); -+ } -+ } -+ } -+ -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ -+ return (0); -+} -+ -+virtaddr_t -+user_elan2main (USER_CTXT *uctx, E4_Addr addr) -+{ -+ USER_RGN *rgn; -+ virtaddr_t raddr; -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ if ((rgn = user_rgnat_elan (uctx, addr)) == (USER_RGN *) NULL) -+ raddr = (virtaddr_t) 0; -+ else -+ raddr = rgn->rgn_mbase + (addr - rgn->rgn_ebase); -+ -+ spin_unlock (&uctx->uctx_rgnlock); -+ -+ return (raddr); -+} -+ -+E4_Addr -+user_main2elan (USER_CTXT *uctx, virtaddr_t addr) -+{ -+ USER_RGN *rgn; -+ E4_Addr raddr; -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ if ((rgn = user_rgnat_main (uctx, addr)) == (USER_RGN *) NULL) -+ raddr = (virtaddr_t) 0; -+ else -+ raddr = rgn->rgn_ebase + (addr - rgn->rgn_mbase); -+ -+ spin_unlock (&uctx->uctx_rgnlock); -+ -+ return (raddr); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/routetable.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/routetable.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/routetable.c 2005-06-01 23:12:54.615436672 -0400 -@@ -0,0 +1,249 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: routetable.c,v 1.15 2004/07/20 09:29:40 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/routetable.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+ELAN4_ROUTE_TABLE * -+elan4_alloc_routetable (ELAN4_DEV *dev, unsigned size) -+{ -+ ELAN4_ROUTE_TABLE *tbl; -+ -+ KMEM_ZALLOC (tbl, ELAN4_ROUTE_TABLE *, sizeof (ELAN4_ROUTE_TABLE), 1); -+ -+ if (tbl == (ELAN4_ROUTE_TABLE *) NULL) -+ return (NULL); -+ -+ tbl->tbl_size = (size & E4_VPT_SIZE_MASK); -+ tbl->tbl_entries = elan4_sdram_alloc (dev, (E4_VPT_MIN_ENTRIES << tbl->tbl_size) * sizeof (E4_VirtualProcessEntry)); -+ -+ if (tbl->tbl_entries == 0) -+ { -+ KMEM_FREE (tbl, sizeof (ELAN4_ROUTE_TABLE)); -+ return ((ELAN4_ROUTE_TABLE *) NULL); -+ } -+ -+ spin_lock_init (&tbl->tbl_lock); -+ -+ /* zero the route table */ -+ elan4_sdram_zeroq_sdram (dev, tbl->tbl_entries, (E4_VPT_MIN_ENTRIES << tbl->tbl_size) * sizeof (E4_VirtualProcessEntry)); -+ -+ return (tbl); -+} -+ -+void -+elan4_free_routetable (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl) -+{ -+ elan4_sdram_free (dev, tbl->tbl_entries, (E4_VPT_MIN_ENTRIES << tbl->tbl_size) * sizeof (E4_VirtualProcessEntry)); -+ -+ spin_lock_destroy (&tbl->tbl_lock); -+ -+ KMEM_FREE (tbl, sizeof (ELAN4_ROUTE_TABLE)); -+} -+ -+void -+elan4_write_route (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl, unsigned vp, E4_VirtualProcessEntry *entry) -+{ -+ ASSERT (vp < (E4_VPT_MIN_ENTRIES << tbl->tbl_size)); -+ -+ elan4_sdram_writeq (dev, tbl->tbl_entries + (vp * sizeof (E4_VirtualProcessEntry)) + offsetof (E4_VirtualProcessEntry, Values[1]), entry->Values[1]); -+ elan4_sdram_writeq (dev, tbl->tbl_entries + (vp * sizeof (E4_VirtualProcessEntry)) + offsetof (E4_VirtualProcessEntry, Values[0]), entry->Values[0]); -+ pioflush_sdram (dev); -+} -+ -+void -+elan4_read_route (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl, unsigned vp, E4_VirtualProcessEntry *entry) -+{ -+ ASSERT (vp < (E4_VPT_MIN_ENTRIES << tbl->tbl_size)); -+ -+ entry->Values[0] = elan4_sdram_readq (dev, tbl->tbl_entries + (vp * sizeof (E4_VirtualProcessEntry)) + offsetof (E4_VirtualProcessEntry, Values[0])); -+ entry->Values[1] = elan4_sdram_readq (dev, tbl->tbl_entries + (vp * sizeof (E4_VirtualProcessEntry)) + offsetof (E4_VirtualProcessEntry, Values[1])); -+} -+ -+void -+elan4_invalidate_route (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl, unsigned vp) -+{ -+ ASSERT (vp < (E4_VPT_MIN_ENTRIES << tbl->tbl_size)); -+ -+ elan4_sdram_writeq (dev, tbl->tbl_entries + (vp * sizeof (E4_VirtualProcessEntry)) + offsetof (E4_VirtualProcessEntry, Values[0]), 0); -+ elan4_sdram_writeq (dev, tbl->tbl_entries + (vp * sizeof (E4_VirtualProcessEntry)) + offsetof (E4_VirtualProcessEntry, Values[1]), 0); -+ pioflush_sdram (dev); -+} -+ -+static void -+pack_them_routes (E4_VirtualProcessEntry *entry, E4_uint16 first, E4_uint8 *packed, unsigned ctx) -+{ -+ E4_uint64 value0 = first; -+ E4_uint64 value1 = ROUTE_CTXT_VALUE(ctx); -+ E4_uint32 ThirdRouteBCastVal; -+ register int i; -+ -+ for (i = 0; i < (ROUTE_NUM_PACKED >> 1); i++) -+ { -+ value0 |= ((E4_uint64) packed[i]) << ((i << 2) + ROUTE_PACKED_OFFSET); -+ value1 |= ((E4_uint64) packed[i+(ROUTE_NUM_PACKED >> 1)]) << ((i << 2)); -+ } -+ -+ /* DMA fix for large broadcast route values that fall into the double issue of route value 3 bug. */ -+ /* NOTE - this is only required when the link is running in Mod45 mode, it could be automatically -+ * disabled when Mod44 is detected */ -+ -+ /* First seach for the alignment type. The bug is only sensitive to an odd bcast aligment on the 3rd word. */ -+ for (i=4;i<16;i++) -+ if (((value0 >> (i*4)) & 0xc) == 4) -+ i++; -+ -+ if (i == 17) -+ { -+ ThirdRouteBCastVal = value1 & 0xcccccccc; -+ if (((value1 & 0xfffff0000000ULL) == 0ULL) && (ThirdRouteBCastVal == 0x04444444)) -+ value1 |= 0x140000000ULL; -+ else if (((value1 & 0xfffffff00000ULL) == 0ULL) && (ThirdRouteBCastVal == 0x00044444)) -+ value1 |= 0x1400000ULL; -+ else if (((value1 & 0xfffffffff000ULL) == 0ULL) && (ThirdRouteBCastVal == 0x00000444)) -+ value1 |= 0x14000ULL; -+ else if (((value1 & 0xfffffffffff0ULL) == 0ULL) && (ThirdRouteBCastVal == 0x00000004)) -+ value1 |= 0x140ULL; -+ } -+ -+ entry->Values[0] = value0; -+ entry->Values[1] = value1; -+} -+ -+int -+elan4_generate_route (ELAN_POSITION *pos, E4_VirtualProcessEntry *route, unsigned ctx, unsigned lowid, unsigned highid, unsigned options) -+{ -+ unsigned int broadcast = (lowid != highid); -+ unsigned int noadaptive = 0; -+ int padbcast = 0; -+ E4_uint16 first; -+ int rb; -+ E4_uint8 packed[ROUTE_NUM_PACKED]; -+ int level, llink, hlink; -+ -+ regenerate_routes: -+ first = 0; -+ rb = 0; -+ -+ switch (pos->pos_mode) -+ { -+ case ELAN_POS_MODE_LOOPBACK: -+ if (lowid != highid || lowid != pos->pos_nodeid) -+ return (-EINVAL); -+ -+ route->Values[0] = FIRST_MYLINK; -+ route->Values[1] = ROUTE_CTXT_VALUE (ctx); -+ return (0); -+ -+ case ELAN_POS_MODE_BACKTOBACK: -+ if (lowid != highid || lowid == pos->pos_nodeid) -+ return (-EINVAL); -+ -+ route->Values[0] = FIRST_MYLINK; -+ route->Values[1] = ROUTE_CTXT_VALUE (ctx); -+ return (0); -+ -+ case ELAN_POS_MODE_SWITCHED: -+ { -+ unsigned char *arityp = &pos->pos_arity[pos->pos_levels - 1]; -+ unsigned int spanned = *arityp; -+ unsigned int broadcasting = 0; -+ -+ bzero (packed, sizeof (packed)); -+ -+ /* XXXX compute noadaptive ? */ -+ -+ for (level = 0; -+ level < pos->pos_levels && ! ((pos->pos_nodeid / spanned) == (lowid / spanned) && -+ (pos->pos_nodeid / spanned) == (highid / spanned)); -+ level++, spanned *= *(--arityp)) -+ { -+ if (first == 0) -+ first = (broadcast || noadaptive) ? FIRST_BCAST_TREE : FIRST_ADAPTIVE; -+ else if (broadcast && padbcast) -+ { -+ padbcast = 0; -+ packed[rb++] = PACKED_BCAST0(4, 4); -+ packed[rb++] = PACKED_BCAST1(4, 4); -+ } -+ else -+ packed[rb++] = (broadcast || noadaptive) ? PACKED_BCAST_TREE : PACKED_ADAPTIVE; -+ } -+ -+ while (level >= 0) -+ { -+ spanned /= *arityp; -+ -+ llink = (lowid / spanned) % *arityp; -+ hlink = (highid / spanned) % *arityp; -+ -+ if (llink != hlink || broadcasting) -+ { -+ broadcasting = 1; -+ -+ if (first == 0) -+ first = FIRST_BCAST (hlink, llink); -+ else -+ { -+ packed[rb++] = PACKED_BCAST0(hlink, llink); -+ -+ if ((rb % 4) == 0 && PACKED_BCAST1(hlink, llink) == 0) -+ { -+ padbcast = 1; -+ goto regenerate_routes; -+ } -+ -+ packed[rb++] = PACKED_BCAST1(hlink, llink); -+ } -+ } -+ else -+ { -+ if (first == 0) -+ first = FIRST_ROUTE(llink); -+ else -+ packed[rb++] = PACKED_ROUTE(llink); -+ } -+ -+ level--; -+ arityp++; -+ } -+ -+ pack_them_routes (route, first | (options & FIRST_OPTIONS_MASK), packed, ctx); -+ return (0); -+ } -+ } -+ -+ return (-EINVAL); -+} -+ -+int -+elan4_check_route (ELAN_POSITION *postiion, ELAN_LOCATION location, E4_VirtualProcessEntry *route, unsigned flags) -+{ -+ /* XXXX - TBD */ -+ return (0); -+} -+ -+EXPORT_SYMBOL(elan4_alloc_routetable); -+EXPORT_SYMBOL(elan4_free_routetable); -+EXPORT_SYMBOL(elan4_write_route); -+EXPORT_SYMBOL(elan4_read_route); -+EXPORT_SYMBOL(elan4_invalidate_route); -+EXPORT_SYMBOL(elan4_generate_route); -+EXPORT_SYMBOL(elan4_check_route); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/sdram.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/sdram.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/sdram.c 2005-06-01 23:12:54.617436368 -0400 -@@ -0,0 +1,1034 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: sdram.c,v 1.29.6.1 2004/11/29 11:39:13 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/sdram.c,v $*/ -+ -+#include -+ -+#include -+#include -+ -+EXPORT_SYMBOL_GPL(elan4_sdram_readb); -+EXPORT_SYMBOL_GPL(elan4_sdram_readw); -+EXPORT_SYMBOL_GPL(elan4_sdram_readl); -+EXPORT_SYMBOL_GPL(elan4_sdram_readq); -+EXPORT_SYMBOL_GPL(elan4_sdram_writeb); -+EXPORT_SYMBOL_GPL(elan4_sdram_writew); -+EXPORT_SYMBOL_GPL(elan4_sdram_writel); -+EXPORT_SYMBOL_GPL(elan4_sdram_writeq); -+EXPORT_SYMBOL_GPL(elan4_sdram_zerob_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_zerow_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_zerol_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_zeroq_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyb_from_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyw_from_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyl_from_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyq_from_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyb_to_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyw_to_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyl_to_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_copyq_to_sdram); -+EXPORT_SYMBOL_GPL(elan4_sdram_alloc); -+EXPORT_SYMBOL_GPL(elan4_sdram_free); -+EXPORT_SYMBOL_GPL(elan4_sdram_flushcache); -+ -+#define SDRAM_MIN_BANK_SIZE ((1 << 15) * 8) /* 256 Kbytes */ -+ -+static inline ELAN4_SDRAM_BANK * -+sdramaddr_to_bank (ELAN4_DEV *dev, sdramaddr_t saddr) -+{ -+ register int i; -+ -+ for (i = 0; i < dev->dev_sdram_numbanks; i++) -+ { -+ ELAN4_SDRAM_BANK *bank = &dev->dev_sdram_banks[i]; -+ -+ if (saddr >= bank->b_base && saddr < (bank->b_base + bank->b_size)) -+ return (bank); -+ } -+ printk ("sdramaddr_to_bank: sdram address %lx not in a sdram bank\n", saddr); -+ BUG(); -+ -+ return (NULL); /* NOTREACHED */ -+} -+ -+static inline int -+sdramaddr_to_bankoffset (ELAN4_DEV *dev, sdramaddr_t saddr) -+{ -+ return (saddr & (sdramaddr_to_bank (dev, saddr)->b_size-1)); -+} -+ -+static inline int -+sdramaddr_to_bit(ELAN4_DEV *dev, int indx, sdramaddr_t saddr) -+{ -+ return (sdramaddr_to_bankoffset(dev, saddr) >> (SDRAM_MIN_BLOCK_SHIFT+(indx))); -+} -+ -+static inline ioaddr_t -+sdramaddr_to_ioaddr (ELAN4_DEV *dev, sdramaddr_t saddr) -+{ -+ ELAN4_SDRAM_BANK *bank = sdramaddr_to_bank (dev, saddr); -+ -+ return (bank->b_ioaddr + (saddr - bank->b_base)); -+} -+ -+unsigned char -+elan4_sdram_readb (ELAN4_DEV *dev, sdramaddr_t off) -+{ -+ return (__elan4_readb (dev, sdramaddr_to_ioaddr(dev, off))); -+} -+ -+unsigned short -+elan4_sdram_readw (ELAN4_DEV *dev, sdramaddr_t off) -+{ -+ return (__elan4_readw (dev, sdramaddr_to_ioaddr(dev, off))); -+} -+ -+unsigned int -+elan4_sdram_readl (ELAN4_DEV *dev, sdramaddr_t off) -+{ -+ return (__elan4_readl (dev, sdramaddr_to_ioaddr(dev, off))); -+} -+ -+unsigned long long -+elan4_sdram_readq (ELAN4_DEV *dev, sdramaddr_t off) -+{ -+ return (readq (sdramaddr_to_ioaddr(dev, off))); -+} -+ -+void -+elan4_sdram_writeb (ELAN4_DEV *dev, sdramaddr_t off, unsigned char val) -+{ -+ writeb (val, sdramaddr_to_ioaddr(dev, off)); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_writew (ELAN4_DEV *dev, sdramaddr_t off, unsigned short val) -+{ -+ writew (val, sdramaddr_to_ioaddr(dev, off)); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_writel (ELAN4_DEV *dev, sdramaddr_t off, unsigned int val) -+{ -+ writel (val, sdramaddr_to_ioaddr(dev, off)); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_writeq (ELAN4_DEV *dev, sdramaddr_t off, unsigned long long val) -+{ -+ writeq (val, sdramaddr_to_ioaddr(dev, off)); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_zerob_sdram (ELAN4_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ ioaddr_t lim = dest + nbytes; -+ -+ for (; dest < lim; dest += sizeof (u8)) -+ writeb (0, dest); -+} -+ -+void -+elan4_sdram_zerow_sdram (ELAN4_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ ioaddr_t lim = dest + nbytes; -+ -+ for (; dest < lim; dest += sizeof (u8)) -+ writeb (0, dest); -+} -+ -+void -+elan4_sdram_zerol_sdram (ELAN4_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ ioaddr_t lim = dest + nbytes; -+ -+ for (; dest < lim; dest += sizeof (u32)) -+ writel (0, dest); -+} -+ -+void -+elan4_sdram_zeroq_sdram (ELAN4_DEV *dev, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ ioaddr_t lim = dest + nbytes; -+ -+#ifdef CONFIG_MPSAS -+ if (sas_memset_dev (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM, to, 0, nbytes) == 0) -+ return; -+#endif -+ -+ for (; dest < lim; dest += sizeof (u64)) -+ writeq (0, dest); -+} -+ -+void -+elan4_sdram_copyb_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+ ioaddr_t src = sdramaddr_to_ioaddr (dev, from); -+ u8 *dest = (u8 *) to; -+ ioaddr_t lim = src + nbytes; -+ -+ for (; src < lim; src += sizeof (u8)) -+ *dest++ = __elan4_readb (dev, src); -+} -+ -+void -+elan4_sdram_copyw_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+ ioaddr_t src = sdramaddr_to_ioaddr (dev, from); -+ u16 *dest = (u16 *) to; -+ ioaddr_t lim = src + nbytes; -+ -+ for (; src < lim; src += sizeof (u16)) -+ *dest++ = __elan4_readw (dev, src); -+} -+ -+void -+elan4_sdram_copyl_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+ ioaddr_t src = sdramaddr_to_ioaddr (dev, from); -+ u32 *dest = (u32 *) to; -+ ioaddr_t lim = src + nbytes; -+ -+ for (; src < lim; src += sizeof (u32)) -+ *dest++ = __elan4_readl (dev, src); -+} -+ -+void -+elan4_sdram_copyq_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes) -+{ -+ ioaddr_t src = sdramaddr_to_ioaddr (dev, from); -+ u64 *dest = (u64 *) to; -+ ioaddr_t lim = src + nbytes; -+ -+#ifdef CONFIG_MPSAS -+ if (sas_copyfrom_dev (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM, from, (unsigned long) to, nbytes) == 0) -+ return; -+#endif -+ -+ for (; src < lim; src += sizeof (u64)) -+ *dest++ = readq (src); -+} -+ -+void -+elan4_sdram_copyb_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ u8 *src = (u8 *) from; -+ ioaddr_t lim = dest + nbytes; -+ -+ for (; dest < lim; dest += sizeof (u8)) -+ writeb (*src++, dest); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_copyw_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ u16 *src = (u16 *) from; -+ ioaddr_t lim = dest + nbytes; -+ -+ for (; dest < lim; dest += sizeof (u16)) -+ writew (*src++, dest); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_copyl_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ u32 *src = (u32 *) from; -+ ioaddr_t lim = dest + nbytes; -+ -+ for (; dest < lim; dest += sizeof (u16)) -+ writew (*src++, dest); -+ -+ mb(); -+} -+ -+void -+elan4_sdram_copyq_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes) -+{ -+ ioaddr_t dest = sdramaddr_to_ioaddr (dev, to); -+ u64 *src = (u64 *) from; -+ ioaddr_t lim = dest + nbytes; -+ -+#ifdef CONFIG_MPSAS -+ if (sas_copyto_dev (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM, to, (unsigned long) from, nbytes) == 0) -+ return; -+#endif -+ -+ for (; dest < lim; dest += sizeof (u64)) -+ writeq (*src++, dest); -+ -+ mb(); -+} -+ -+/* sdram buddy allocator */ -+typedef struct sdramblock -+{ -+ sdramaddr_t next; -+ sdramaddr_t prev; -+} sdramblock_t; -+ -+static inline sdramaddr_t -+read_next (ELAN4_DEV *dev, sdramaddr_t block) -+{ -+ return __elan4_readl (dev, sdramaddr_to_ioaddr (dev, block + offsetof (sdramblock_t, next))); -+} -+ -+static inline sdramaddr_t -+read_prev (ELAN4_DEV *dev, sdramaddr_t block) -+{ -+ return __elan4_readl (dev, sdramaddr_to_ioaddr (dev, block + offsetof (sdramblock_t, prev))); -+} -+ -+static inline void -+write_next (ELAN4_DEV *dev, sdramaddr_t block, sdramaddr_t val) -+{ -+ writel (val, sdramaddr_to_ioaddr (dev, block + offsetof (sdramblock_t, next))); -+} -+ -+static inline void -+write_prev (ELAN4_DEV *dev, sdramaddr_t block, sdramaddr_t val) -+{ -+ writel (val, sdramaddr_to_ioaddr (dev, block + offsetof (sdramblock_t, prev))); -+} -+ -+static inline void -+freelist_insert (ELAN4_DEV *dev, int idx, sdramaddr_t block) -+{ -+ sdramaddr_t next = dev->dev_sdram_freelists[(idx)]; -+ -+ /* -+ * block->prev = NULL; -+ * block->next = next; -+ * if (next != NULL) -+ * next->prev = block; -+ * freelist = block; -+ */ -+ write_prev (dev, block, (sdramaddr_t) 0); -+ write_next (dev, block, next); -+ if (next != (sdramaddr_t) 0) -+ write_prev (dev, next, block); -+ dev->dev_sdram_freelists[idx] = block; -+ -+ dev->dev_sdram_freecounts[idx]++; -+ dev->dev_stats.s_sdram_bytes_free += (SDRAM_MIN_BLOCK_SIZE << idx); -+ -+ mb(); -+} -+ -+static inline void -+freelist_remove (ELAN4_DEV *dev,int idx, sdramaddr_t block) -+{ -+ /* -+ * if (block->prev) -+ * block->prev->next = block->next; -+ * else -+ * dev->dev_sdram_freelists[idx] = block->next; -+ * if (block->next) -+ * block->next->prev = block->prev; -+ */ -+ sdramaddr_t blocknext = read_next (dev, block); -+ sdramaddr_t blockprev = read_prev (dev, block); -+ -+ if (blockprev) -+ write_next (dev, blockprev, blocknext); -+ else -+ dev->dev_sdram_freelists[idx] = blocknext; -+ if (blocknext) -+ write_prev (dev, blocknext, blockprev); -+ -+ dev->dev_sdram_freecounts[idx]--; -+ dev->dev_stats.s_sdram_bytes_free -= (SDRAM_MIN_BLOCK_SIZE << idx); -+ -+ mb(); -+} -+ -+static inline void -+freelist_removehead(ELAN4_DEV *dev, int idx, sdramaddr_t block) -+{ -+ sdramaddr_t blocknext = read_next (dev, block); -+ -+ if ((dev->dev_sdram_freelists[idx] = blocknext) != 0) -+ write_prev (dev, blocknext, 0); -+ -+ dev->dev_sdram_freecounts[idx]--; -+ dev->dev_stats.s_sdram_bytes_free -= (SDRAM_MIN_BLOCK_SIZE << idx); -+ -+ mb(); -+} -+ -+#ifdef DEBUG -+static int -+display_blocks (ELAN4_DEV *dev, int indx, char *string) -+{ -+ sdramaddr_t block; -+ int nbytes = 0; -+ -+ PRINTF (DBG_DEVICE, DBG_SDRAM, "%s - indx %d\n", string, indx); -+ for (block = dev->dev_sdram_freelists[indx]; block != (sdramaddr_t) 0; block = read_next (dev, block)) -+ { -+ PRINTF (DBG_DEVICE, DBG_SDRAM, " %x\n", block); -+ nbytes += (SDRAM_MIN_BLOCK_SIZE << indx); -+ } -+ -+ return (nbytes); -+} -+ -+void -+elan4_sdram_display (ELAN4_DEV *dev, char *string) -+{ -+ int indx; -+ int nbytes = 0; -+ -+ PRINTF (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_display: dev=%p\n", dev); -+ for (indx = 0; indx < SDRAM_NUM_FREE_LISTS; indx++) -+ if (dev->dev_sdram_freelists[indx] != (sdramaddr_t) 0) -+ nbytes += display_blocks (dev, indx, string); -+ PRINTF (DBG_DEVICE, DBG_SDRAM, "\n%d bytes free - %d pages free\n", nbytes, nbytes/SDRAM_PAGE_SIZE); -+} -+ -+void -+elan4_sdram_verify (ELAN4_DEV *dev) -+{ -+ int indx, size, nbits, i, b; -+ sdramaddr_t block; -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; indx < SDRAM_NUM_FREE_LISTS; indx++, size <<= 1) -+ { -+ unsigned count = 0; -+ -+ for (block = dev->dev_sdram_freelists[indx]; block; block = read_next (dev, block), count++) -+ { -+ ELAN4_SDRAM_BANK *bank = sdramaddr_to_bank (dev, block); -+ unsigned off = sdramaddr_to_bankoffset (dev, block); -+ int bit = sdramaddr_to_bit (dev, indx, block); -+ -+ if ((block & (size-1)) != 0) -+ printk ("elan4_sdram_verify: block=%lx indx=%x - not aligned\n", block, indx); -+ -+ if (bank == NULL || off > bank->b_size) -+ printk ("elan4_sdram_verify: block=%lx indx=%x - outside bank\n", block, indx); -+ else if (BT_TEST (bank->b_bitmaps[indx], bit) == 0) -+ printk ("elan4_sdram_verify: block=%lx indx=%x - bit not set\n", block, indx); -+ else -+ { -+ for (i = indx-1, nbits = 2; i >= 0; i--, nbits <<= 1) -+ { -+ bit = sdramaddr_to_bit (dev, i, block); -+ -+ for (b = 0; b < nbits; b++) -+ if (BT_TEST(bank->b_bitmaps[i], bit + b)) -+ printk ("elan4_sdram_verify: block=%lx indx=%x - also free i=%d bit=%x\n", block, indx, i, bit+b); -+ } -+ } -+ } -+ -+ if (dev->dev_sdram_freecounts[indx] != count) -+ printk ("elan4_sdram_verify: indx=%x expected %d got %d\n", indx, dev->dev_sdram_freecounts[indx], count); -+ } -+} -+ -+#endif -+ -+static void -+free_block (ELAN4_DEV *dev, sdramaddr_t block, int indx) -+{ -+ ELAN4_SDRAM_BANK *bank = sdramaddr_to_bank (dev, block); -+ unsigned bit = sdramaddr_to_bit (dev, indx, block); -+ unsigned size = SDRAM_MIN_BLOCK_SIZE << indx; -+ -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "free_block: block=%x indx=%d bit=%x\n", block, indx, bit); -+ -+ ASSERT ((block & (size-1)) == 0); -+ ASSERT (BT_TEST (bank->b_bitmaps[indx], bit) == 0); -+ -+ while (BT_TEST (bank->b_bitmaps[indx], bit ^ 1)) -+ { -+ sdramaddr_t buddy = block ^ size; -+ -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "free_block: merge block=%x buddy=%x indx=%d\n", block, buddy, indx); -+ -+ BT_CLEAR (bank->b_bitmaps[indx], bit ^ 1); -+ -+ freelist_remove (dev, indx, buddy); -+ -+ block = (block < buddy) ? block : buddy; -+ indx++; -+ size <<= 1; -+ bit >>= 1; -+ } -+ -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "free_block: free block=%x indx=%d bit=%x\n", block, indx, bit); -+ -+ freelist_insert (dev, indx, block); -+ -+ BT_SET (bank->b_bitmaps[indx], bit); -+} -+ -+void -+elan4_sdram_init (ELAN4_DEV *dev) -+{ -+ int indx; -+ -+ spin_lock_init (&dev->dev_sdram_lock); -+ -+ for (indx = 0; indx < SDRAM_NUM_FREE_LISTS; indx++) -+ { -+ dev->dev_sdram_freelists[indx] = (sdramaddr_t) 0; -+ dev->dev_sdram_freecounts[indx] = 0; -+ } -+} -+ -+void -+elan4_sdram_fini (ELAN4_DEV *dev) -+{ -+ spin_lock_destroy (&dev->dev_sdram_lock); -+} -+ -+#ifdef CONFIG_MPSAS -+/* size of Elan SDRAM in simulation */ -+#define SDRAM_used_addr_bits (16) -+#define SDRAM_SIMULATION_BANK_SIZE ((1 << SDRAM_used_addr_bits) * 8) /* 128 kbytes */ -+ -+static int -+elan4_sdram_probe_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank) -+{ -+ printk ("elan%d: memory bank %d is %d Kb\n", dev->dev_instance, (int) (bank - dev->dev_sdram_banks), (int) (SDRAM_SIMULATION_BANK_SIZE / 1024)); -+ -+ bank->b_size = SDRAM_SIMULATION_BANK_SIZE; -+ -+ return 1; -+} -+ -+#else -+ -+static void -+initialise_cache_tags (ELAN4_DEV *dev, unsigned addr) -+{ -+ register int set, line; -+ -+ mb(); -+ -+ /* Initialise the whole cache to hold sdram at "addr" as direct mapped */ -+ -+ for (set = 0; set < E4_NumCacheSets; set++) -+ for (line = 0; line < E4_NumCacheLines; line++) -+ write_tag (dev, Tags[set][line], addr | (set << 13) | (1 << 11)); -+ -+ read_tag (dev, Tags[set][line]); /* read it back to guarantee the memory system is quite again */ -+ mb(); -+} -+ -+static __inline__ int -+sdram_GreyToBinary(int GreyVal, int NoOfBits) -+{ -+ int Bit; -+ int BinaryVal=0; -+ for (Bit=(1 << (NoOfBits-1)); Bit != 0; Bit >>= 1) -+ BinaryVal ^= (GreyVal & Bit) ^ ((BinaryVal >> 1) & Bit); -+ return (BinaryVal); -+} -+ -+static __inline__ int -+sdram_BinaryToGrey(int BinaryVal) -+{ -+ return (BinaryVal ^ (BinaryVal >> 1)); -+} -+ -+void -+elan4_sdram_setup_delay_lines (ELAN4_DEV *dev) -+{ -+ /* This is used to fix the SDRAM delay line values */ -+ int i, AutoGenDelayValue=0; -+ int NewDelayValue; -+ -+ if (dev->dev_sdram_cfg & SDRAM_FIXED_DELAY_ENABLE) /* already setup. */ -+ return; -+ -+ /* now get an average of 10 dll values */ -+ for (i=0;i<10;i++) -+ AutoGenDelayValue += sdram_GreyToBinary(SDRAM_GET_DLL_DELAY(read_reg64 (dev, SDRamConfigReg)), -+ SDRAM_FIXED_DLL_DELAY_BITS); -+ -+ NewDelayValue = SDRAM_DLL_CORRECTION_FACTOR + (AutoGenDelayValue / 10); /* Mean of 10 values */ -+ -+ dev->dev_sdram_cfg = (dev->dev_sdram_cfg & ~(SDRAM_FIXED_DLL_DELAY_MASK << SDRAM_FIXED_DLL_DELAY_SHIFT)) | -+ SDRAM_FIXED_DELAY_ENABLE | SDRAM_FIXED_DLL_DELAY(sdram_BinaryToGrey(NewDelayValue)); -+ -+ write_reg64 (dev, SDRamConfigReg, dev->dev_sdram_cfg); /* Put back the new value */ -+ -+ pioflush_reg (dev); -+} -+ -+static int -+elan4_sdram_probe_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank) -+{ -+ unsigned long mappedsize = bank->b_size; -+ ioaddr_t ioaddr; -+ unsigned long long value, size; -+ register int i; -+ extern int sdram_bank_limit; -+ -+ if (mappedsize > SDRAM_MAX_BLOCK_SIZE) -+ mappedsize = SDRAM_MAX_BLOCK_SIZE; -+ -+ while ((ioaddr = elan4_map_device (dev, ELAN4_BAR_SDRAM, bank->b_base, mappedsize, &bank->b_handle)) == 0) -+ { -+ if (mappedsize <= (64*1024*1024)) /* boards normally populated with 64mb, so winge if we can't see this much */ -+ printk ("elan%d: could not map bank %d size %dMb\n", dev->dev_instance, (int)(bank - dev->dev_sdram_banks), (int)mappedsize/(1024*1024)); -+ -+ if ((mappedsize >>= 1) < (1024*1024)) -+ return 0; -+ } -+ -+ /* first probe to see if the memory bank is present */ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ initialise_cache_tags (dev, E4_CacheSize); -+ -+ for (i = 0; i < 64; i++) -+ { -+ unsigned long long pattern = (1ull << i); -+ -+ writeq (pattern, ioaddr); /* write pattern at base */ -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ initialise_cache_tags (dev, 0); -+ -+ writeq (~pattern, ioaddr + E4_CacheSize); /* write ~pattern at cachesize */ -+ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ initialise_cache_tags (dev, E4_CacheSize); -+ -+ writeq (~pattern, ioaddr + 2*E4_CacheSize); /* write ~pattern at 2*cachesize */ -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ initialise_cache_tags (dev, 2*E4_CacheSize); -+ -+ value = readq (ioaddr); /* read pattern back at 0 */ -+ -+ if (value != pattern) -+ { -+ printk ("elan%d: sdram bank %d not present\n", dev->dev_instance, (int) (bank - dev->dev_sdram_banks)); -+ elan4_unmap_device (dev, ioaddr, mappedsize, &bank->b_handle); -+ return 0; -+ } -+ } -+ -+ /* sdram bank is present, so work out it's size. We store the maximum size at the base -+ * and then store the address at each address on every power of two address until -+ * we reach the minimum mappable size (PAGESIZE), we then read back the value at the -+ * base to determine the bank size */ -+ writeq (mappedsize, ioaddr); -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ initialise_cache_tags (dev, 0); -+ -+ for (size = mappedsize >> 1; size > PAGE_SIZE; size >>= 1) -+ { -+ writeq (size, ioaddr + size); -+ if (dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) -+ initialise_cache_tags (dev, size); -+ } -+ -+ if ((size = readq (ioaddr)) < SDRAM_MIN_BANK_SIZE) -+ { -+ printk ("elan%d: memory bank %d dubious\n", dev->dev_instance, (int) (bank - dev->dev_sdram_banks)); -+ elan4_unmap_device (dev, ioaddr, mappedsize, &bank->b_handle); -+ return 0; -+ } -+ -+ if (sdram_bank_limit == 0 || size <= (sdram_bank_limit * 1024 * 1024)) -+ printk ("elan%d: memory bank %d is %d Mb\n", dev->dev_instance, (int) (bank - dev->dev_sdram_banks), (int) (size / (1024*1024))); -+ else -+ { -+ size = (sdram_bank_limit * 1024 * 1024); -+ printk ("elan%d: limit bank %d to %d Mb\n", dev->dev_instance, (int) (bank - dev->dev_sdram_banks), (int) (size / (1024*1024))); -+ } -+ -+ bank->b_size = size; -+ -+ elan4_unmap_device (dev, ioaddr, mappedsize, &bank->b_handle); -+ return 1; -+} -+#endif -+ -+int -+elan4_sdram_init_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank) -+{ -+ int indx, size; -+ -+ bank->b_ioaddr = 0; -+ -+ if (! elan4_sdram_probe_bank (dev, bank)) -+ return 0; -+ -+ if ((bank->b_ioaddr = elan4_map_device (dev, ELAN4_BAR_SDRAM, bank->b_base, bank->b_size, &bank->b_handle)) == (ioaddr_t) 0) -+ { -+ printk ("elan%d: could not map sdrambank %d\n", dev->dev_instance, (int) (bank - dev->dev_sdram_banks)); -+ return 0; -+ } -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size <= bank->b_size; indx++, size <<= 1) /* allocate the buddy allocator bitmaps */ -+ KMEM_ZALLOC (bank->b_bitmaps[indx], bitmap_t *, sizeof (bitmap_t) * BT_BITOUL(bank->b_size/size), 1); -+ -+ return 1; -+} -+ -+void -+elan4_sdram_fini_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank) -+{ -+ int indx, size; -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size <= bank->b_size; indx++, size <<= 1) -+ KMEM_FREE (bank->b_bitmaps[indx], sizeof (bitmap_t) * BT_BITOUL(bank->b_size/size)); -+ -+ elan4_unmap_device (dev, bank->b_ioaddr, bank->b_size, &bank->b_handle); -+} -+ -+void -+elan4_sdram_add_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank) -+{ -+ sdramaddr_t base = bank->b_base; -+ sdramaddr_t top = bank->b_base + bank->b_size; -+ register int indx; -+ register unsigned long size; -+ -+ /* align to the minimum block size */ -+ base = (base + SDRAM_MIN_BLOCK_SIZE - 1) & ~((sdramaddr_t) SDRAM_MIN_BLOCK_SIZE-1); -+ top &= ~((sdramaddr_t) SDRAM_MIN_BLOCK_SIZE-1); -+ -+ /* don't allow 0 as a valid "base" */ -+ if (base == 0) -+ base = SDRAM_MIN_BLOCK_SIZE; -+ -+ /* carve the bottom to the biggest boundary */ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; indx < SDRAM_NUM_FREE_LISTS; indx++, size <<= 1) -+ { -+ if ((base & size) == 0) -+ continue; -+ -+ if ((base + size) > top) -+ break; -+ -+ free_block (dev, base, indx); -+ -+ base += size; -+ } -+ -+ /* carve the top down to the biggest boundary */ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; indx < SDRAM_NUM_FREE_LISTS; indx++, size <<= 1) -+ { -+ if ((top & size) == 0) -+ continue; -+ -+ if ((top - size) < base) -+ break; -+ -+ free_block (dev, (top - size), indx); -+ -+ top -= size; -+ } -+ -+ /* now free of the space in between */ -+ while (base < top) -+ { -+ free_block (dev, base, (SDRAM_NUM_FREE_LISTS-1)); -+ -+ base += SDRAM_MAX_BLOCK_SIZE; -+ } -+} -+ -+sdramaddr_t -+elan4_sdram_alloc (ELAN4_DEV *dev, int nbytes) -+{ -+ sdramaddr_t block; -+ register int i, indx; -+ unsigned long size; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_sdram_lock, flags); -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size < nbytes; indx++, size <<= 1) -+ ; -+ -+ PRINTF2 (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_alloc: nbytes=%d indx=%d\n", nbytes, indx); -+ -+ /* need to split a bigger block up */ -+ for (i = indx; i < SDRAM_NUM_FREE_LISTS; i++, size <<= 1) -+ if (dev->dev_sdram_freelists[i]) -+ break; -+ -+ if (i == SDRAM_NUM_FREE_LISTS) -+ { -+ spin_unlock_irqrestore (&dev->dev_sdram_lock, flags); -+ printk ("elan4_sdram_alloc: %d bytes failed\n", nbytes); -+ return ((sdramaddr_t) 0); -+ } -+ -+ PRINTF2 (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_alloc: use block=%x indx=%d\n", dev->dev_sdram_freelists[i], i); -+ -+ /* remove the block from the free list */ -+ freelist_removehead (dev, i, (block = dev->dev_sdram_freelists[i])); -+ -+ /* clear the approriate bit in the bitmap */ -+ BT_CLEAR (sdramaddr_to_bank (dev, block)->b_bitmaps[i], sdramaddr_to_bit (dev,i, block)); -+ -+ /* and split it up as required */ -+ while (i-- > indx) -+ free_block (dev, block + (size >>= 1), i); -+ -+ spin_unlock_irqrestore (&dev->dev_sdram_lock, flags); -+ -+ ASSERT ((block & ((SDRAM_MIN_BLOCK_SIZE << (indx))-1)) == 0); -+ -+#ifdef CONFIG_MPSAS -+ elan4_sdram_zeroq_sdram (dev, block, sizeof (sdramblock_t)); -+#endif -+ -+ return ((sdramaddr_t) block); -+} -+ -+void -+elan4_sdram_free (ELAN4_DEV *dev, sdramaddr_t block, int nbytes) -+{ -+ register int indx; -+ unsigned long size; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->dev_sdram_lock, flags); -+ -+ for (indx = 0, size = SDRAM_MIN_BLOCK_SIZE; size < nbytes; indx++, size <<= 1) -+ ; -+ -+ PRINTF2 (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_free: indx=%d block=%x\n", indx, block); -+ -+ free_block (dev, block, indx); -+ -+ spin_unlock_irqrestore (&dev->dev_sdram_lock, flags); -+} -+ -+void -+elan4_sdram_flushcache (ELAN4_DEV *dev, sdramaddr_t addr, int len) -+{ -+ int set, off; -+ -+ SET_SYSCONTROL (dev, dev_direct_map_pci_writes, CONT_DIRECT_MAP_PCI_WRITES); -+ -+ /* -+ * if flushing more than a single set (8K), then you have to flush the whole cache. -+ * NOTE - in the real world we will probably want to generate a burst across -+ * the pci bus. -+ */ -+ if (len >= E4_CacheSetSize) -+ { -+ PRINTF3 (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_flushcache: addr=%x len=%x (%x) => whole cache\n", addr, len, addr + len); -+ -+#ifdef CONFIG_MPSAS -+ elan4_sdram_zeroq_sdram (dev, dev->dev_cacheflush_space, E4_CacheSize); -+#else -+ for (set = 0; set < E4_NumCacheSets; set++) -+ for (off = 0; off < E4_CacheSetSize; off += E4_CacheLineSize) -+ elan4_sdram_writeq (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize) + off, 0); -+#endif -+ } -+ else -+ { -+ unsigned base = addr & ~(E4_CACHELINE_SIZE-1); -+ unsigned top = (addr + len + (E4_CACHELINE_SIZE-1)) & ~(E4_CACHELINE_SIZE-1); -+ unsigned baseoff = base & (E4_CacheSetSize-1); -+ unsigned topoff = top & (E4_CacheSetSize-1); -+ -+ if ((base ^ top) & E4_CacheSetSize) /* wraps */ -+ { -+ PRINTF7 (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_flushcache: addr=%x len=%x (%x) => split cache (%x,%x %x,%x)\n", -+ addr, len, addr + len, 0, topoff, baseoff, E4_CacheSetSize); -+ -+#ifdef CONFIG_MPSAS -+ for (set = 0; set < E4_NumCacheSets; set++) -+ { -+ elan4_sdram_zeroq_sdram (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize), topoff); -+ elan4_sdram_zeroq_sdram (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize) + baseoff, E4_CacheSetSize - baseoff); -+ } -+#else -+ for (set = 0; set < E4_NumCacheSets; set++) -+ { -+ for (off = 0; off < (top & (E4_CacheSetSize-1)); off += E4_CACHELINE_SIZE) -+ elan4_sdram_writeq (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize) + off, 0); -+ -+ for (off = (base & (E4_CacheSetSize-1)); off < E4_CacheSetSize; off += E4_CACHELINE_SIZE) -+ elan4_sdram_writeq (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize) + off, 0); -+ } -+#endif -+ } -+ else -+ { -+ PRINTF5 (DBG_DEVICE, DBG_SDRAM, "elan4_sdram_flushcache: addr=%x len=%x (%x) => part cache (%x,%x)\n", -+ addr, len, addr + len, baseoff, topoff); -+ -+#ifdef CONFIG_MPSAS -+ for (set = 0; set < E4_NumCacheSets; set++) -+ elan4_sdram_zeroq_sdram (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize) + baseoff, topoff - baseoff); -+#else -+ for (set = 0; set < E4_NumCacheSets; set++) -+ for (off = (base & (E4_CacheSetSize-1)); off < (top & (E4_CacheSetSize-1)); off += E4_CACHELINE_SIZE) -+ elan4_sdram_writeq (dev, dev->dev_cacheflush_space + (set * E4_CacheSetSize) + off, 0); -+#endif -+ } -+ } -+ pioflush_sdram (dev); -+ -+ CLEAR_SYSCONTROL (dev, dev_direct_map_pci_writes, CONT_DIRECT_MAP_PCI_WRITES); -+} -+ -+static char * -+get_correctableErr_bitpos(uint SyndromeBits) -+{ -+ switch (SyndromeBits) -+ { -+ case 0x00: return ("NoErr"); -+ case 0x31: return ("00"); -+ case 0x32: return ("01"); -+ case 0xc4: return ("02"); -+ case 0xc8: return ("03"); -+ case 0x26: return ("04"); -+ case 0x91: return ("05"); -+ case 0x89: return ("06"); -+ case 0x64: return ("07"); -+ case 0xc1: return ("08"); -+ case 0xf2: return ("09"); -+ case 0x34: return ("10"); -+ case 0xf8: return ("11"); -+ case 0xf1: return ("12"); -+ case 0xc2: return ("13"); -+ case 0xf4: return ("14"); -+ case 0x38: return ("15"); -+ case 0xd6: return ("16"); -+ case 0xa1: return ("17"); -+ case 0x79: return ("18"); -+ case 0xa4: return ("19"); -+ case 0xd9: return ("20"); -+ case 0xa2: return ("21"); -+ case 0x76: return ("22"); -+ case 0xa8: return ("23"); -+ case 0xe6: return ("24"); -+ case 0x51: return ("25"); -+ case 0xb9: return ("26"); -+ case 0x54: return ("27"); -+ case 0xe9: return ("28"); -+ case 0x52: return ("29"); -+ case 0xb6: return ("30"); -+ case 0x58: return ("31"); -+ case 0x13: return ("32"); -+ case 0x23: return ("33"); -+ case 0x4c: return ("34"); -+ case 0x8c: return ("35"); -+ case 0x62: return ("36"); -+ case 0x19: return ("37"); -+ case 0x98: return ("38"); -+ case 0x46: return ("39"); -+ case 0x1c: return ("40"); -+ case 0x2f: return ("41"); -+ case 0x43: return ("42"); -+ case 0x8f: return ("43"); -+ case 0x1f: return ("44"); -+ case 0x2c: return ("45"); -+ case 0x4f: return ("46"); -+ case 0x83: return ("47"); -+ case 0x6d: return ("48"); -+ case 0x1a: return ("49"); -+ case 0x97: return ("50"); -+ case 0x4a: return ("51"); -+ case 0x9d: return ("52"); -+ case 0x2a: return ("53"); -+ case 0x67: return ("54"); -+ case 0x8a: return ("55"); -+ case 0x6e: return ("56"); -+ case 0x15: return ("57"); -+ case 0x9b: return ("58"); -+ case 0x45: return ("59"); -+ case 0x9e: return ("60"); -+ case 0x25: return ("61"); -+ case 0x6b: return ("62"); -+ case 0x85: return ("63"); -+ case 0x01: return ("C0"); -+ case 0x02: return ("C1"); -+ case 0x04: return ("C2"); -+ case 0x08: return ("C3"); -+ case 0x10: return ("C4"); -+ case 0x20: return ("C5"); -+ case 0x40: return ("C6"); -+ case 0x80: return ("C7"); -+ -+ case 0x07: case 0x0b: case 0x0d: case 0x0e: case 0x3d: case 0x3e: case 0x70: case 0x7c: // T -+ case 0xb0: case 0xbc: case 0xc7: case 0xcb: case 0xd0: case 0xd3: case 0xe0: case 0xe3: // T -+ return ("triple"); -+ -+ case 0x0f: case 0x55: case 0x5a: case 0xa5: case 0xaa: case 0xf0: case 0xff: // Q -+ return ("quadruple"); -+ -+ case 0x16: case 0x29: case 0x37: case 0x3b: case 0x49: case 0x57: case 0x5b: case 0x5d: case 0x5e: case 0x61: // M -+ case 0x68: case 0x73: case 0x75: case 0x7a: case 0x7f: case 0x86: case 0x92: case 0x94: case 0xa7: case 0xab: // M -+ case 0xad: case 0xae: case 0xb3: case 0xb5: case 0xba: case 0xbf: case 0xcd: case 0xce: case 0xd5: case 0xda: // M -+ case 0xdc: case 0xdf: case 0xe5: case 0xea: case 0xec: case 0xef: case 0xf7: case 0xfb: case 0xfd: case 0xfe: // M -+ return ("multiple"); -+ -+ default: // all other cases -+ return ("double"); -+ } -+} -+ -+char * -+elan4_sdramerr2str (ELAN4_DEV *dev, E4_uint64 status, char *str) -+{ -+ E4_uint64 StartupSyndrome = dev->dev_sdram_initial_ecc_val; -+ int RisingDQSsyndrome = ((ECC_RisingDQSSyndrome(status) == ECC_RisingDQSSyndrome(StartupSyndrome)) ? -+ 0 : ECC_RisingDQSSyndrome(status)); -+ int FallingDQSsyndrome = ((ECC_FallingDQSSyndrome(status) == ECC_FallingDQSSyndrome(StartupSyndrome)) ? -+ 0 : ECC_FallingDQSSyndrome(status)); -+ E4_uint64 Addr = ECC_Addr(status); -+ int Bank = (Addr >> 6) & 3; -+ int Cas = ((Addr >> 3) & 7) | ((Addr >> (8 - 3)) & 0xf8) | ((Addr >> (25 - 8)) & 0x100) | -+ ((Addr >> (27 - 9)) & 0x200) | ((Addr >> (29 - 10)) & 0xc00); -+ int Ras = ((Addr >> 13) & 0xfff) | ((Addr >> (26 - 12)) & 0x1000) | ((Addr >> (28 - 13)) & 0x2000) | -+ ((Addr >> (30 - 14)) & 0x4000); -+ -+ sprintf (str, "Addr=%07llx Bank=%x Ras=%x Cas=%x Falling DQS=%s Rising DQS=%s Syndrome=%x%s%s%s%s", /* 41 + 16 + 8 + 15 + 24 + 13 + 22 + 10 + 10 == 151 */ -+ (long long)Addr, Bank, Ras, Cas, -+ get_correctableErr_bitpos(FallingDQSsyndrome), -+ get_correctableErr_bitpos(RisingDQSsyndrome), -+ (int)ECC_Syndrome(status), -+ ECC_UncorrectableErr(status) ? " Uncorrectable" : "", -+ ECC_MultUncorrectErrs(status) ? " Multiple-Uncorrectable" : "", -+ ECC_CorrectableErr(status) ? " Correctable" : "", -+ ECC_MultCorrectErrs(status) ? " Multiple-Correctable" : ""); -+ -+ return str; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/trap.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/trap.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/trap.c 2005-06-01 23:12:54.619436064 -0400 -@@ -0,0 +1,778 @@ -+/* -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: trap.c,v 1.19.10.2 2004/11/03 14:24:32 duncant Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/trap.c,v $*/ -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+char * const PermTypes[16] = -+{ -+ "Disabled", "Unused", "LocalDataRead", "LocalDataWrite", -+ "LocalRead", "LocalExecute", "ReadOnly", "LocalWrite", -+ "LocalEventOnly", "LocalEventWrite", "RemoteEvent", "RemoteAll", -+ "RemoteReadOnly", "RemoteWriteOnly", "DataReadWrite", "NoFault", -+}; -+ -+char * const AccTypes[] = -+{ -+ "LocalDataRead ", "LocalDataWrite", "RemoteRead ", "RemoteWrite ", -+ "Execute ", "LocalEvent ", "Unused ", "RemoteEvent " -+}; -+char * const DataTypes[] = {"Byte ", "HWord", "Word ", "DWord"}; -+char * const PhysTypes[] = {"Special Read", "Special Write", "Physical Read", "Physical Write"}; -+ -+char * const EProcTrapNames[] = { -+ "EventProcNoFault", -+ "EventProcAddressAlignment", -+ "EventProcMemoryFault", -+ "EventProcCountWrapError", -+}; -+ -+char * const CProcTrapNames[] = { -+ "CommandProcNoFault", -+ "CommandProcInserterError", -+ "CommandProcPermissionTrap", -+ "CommandProcSendTransInvalid", -+ "CommandProcSendTransExpected", -+ "CommandProcDmaQueueOverflow", -+ "CommandProcInterruptQueueOverflow", -+ "CommandProcMemoryFault", -+ "CommandProcRouteFetchFault", -+ "CommandProcFailCountZero", -+ "CommandProcAddressAlignment", -+ "CommandProcWaitTrap", -+ "CommandProcMultipleGuards", -+ "CommandProcOpenOnGuardedChan", -+ "CommandProcThreadQueueOverflow", -+ "CommandProcBadData", -+}; -+ -+char *const CProcInsertError[] = { -+ "No Error", -+ "Overflowed", -+ "Invalid Write Size", -+ "Invalid Write Order", -+}; -+ -+char * const DProcTrapNames[] = { -+ "DmaProcNoFault", -+ "DmaProcRouteFetchFault", -+ "DmaProcFailCountError", -+ "DmaProcPacketAckError", -+ "DmaProcRunQueueReadFault", -+ "DmaProcQueueOverFlow", -+}; -+ -+char *const IProcTrapNames[] = { -+ "InputNoFault", -+ "InputAddressAlignment", -+ "InputMemoryFault", -+ "InputInvalidTransType", -+ "InputDmaQueueOverflow", -+ "InputEventEngineTrapped", -+ "InputCrcErrorAfterPAckOk", -+ "InputEopErrorOnWaitForEop", -+ "InputEopErrorTrap", -+ "InputDiscardAfterAckOk", -+}; -+ -+char *const TProcTrapNames[] = { -+ "HaltThread", -+ "TrapForTooManyInstructions", -+ "InstAccessException", -+ "Unimplemented", -+ "DataAccessException", -+ "DataAlignmentError", -+ "TrapForUsingBadData", -+}; -+ -+#define declare_spaces(space, str) char space[64]; do { int i; for (i = 0; i < strlen(str); i++) spaces[i] = ' '; space[i] = '\0'; } while (0) -+#define declare_prefix(space, spaces, str) char space[64]; do { strcpy (space, spaces); strcat (space, str); } while (0) -+ -+void -+elan4_display_farea (void *type, int mode, char *str, E4_FaultSave *farea) -+{ -+ E4_uint32 FSR = FaultSaveFSR(farea->FSRAndFaultContext); -+ -+ declare_spaces(spaces, str); -+ -+ elan4_debugf (type, mode, "%s Fault occurred at %016llx for context %4x\n", str, -+ farea->FaultAddress, FaultSaveContext(farea->FSRAndFaultContext)); -+ -+ if (FSR & AT_VirtualWriteAccBit) /* Virtual write access */ -+ elan4_debugf (type, mode, "%s FSR=%x: Virtual Write. DWSize=0x%x EndP=0x%x Access=%s DT=%s\n", -+ spaces, FSR, FSR & AT_VirtualWriteSizeMask, -+ (FSR >> AT_VirtualWriteEndPtrShift) & AT_VirtualWriteEndPtrMask, -+ AccTypes[(FSR >> AT_PermBitsShift) & AT_PermBitsMask], -+ DataTypes[(FSR >> AT_BlkDataTyShift) & AT_BlkDataTyMask]); -+ else if (FSR & AT_VirtualReadAccBit) /* Virtual read access */ -+ elan4_debugf (type, mode, "%s FSR=%x: Virtual Read. DWSize=0x%x Access=%s DT=%s\n", -+ spaces, FSR, FSR & AT_VirtualReadSizeMask, -+ AccTypes[(FSR >> AT_PermBitsShift) & AT_PermBitsMask], -+ DataTypes[(FSR >> AT_BlkDataTyShift) & AT_BlkDataTyMask]); -+ else -+ elan4_debugf (type, mode, "%s FSR=%x: %s. Size=0x%x\n", spaces, -+ FSR, PhysTypes[(FSR >> AT_SelBitsShift) & AT_SelBitsMask], -+ FSR & AT_OtherSizeMask); -+ elan4_debugf (type, mode, "%s FSR: %s %s%s %sWalking\n", spaces, -+ (FSR & AT_NonAlloc) ? "NonAlloc" : "Alloc", -+ (FSR & AT_DmaData) ? "Dma " : "", -+ (FSR & FSR_WalkForThread) ? "ThreadAcc" : "UnitsAcc", -+ (FSR & FSR_Walking) ? "" : "Not"); -+ PRINTF (type, mode, "%s FSR: %s%sHashTable=%s\n", spaces, -+ (FSR & FSR_NoTranslationsFound) ? "NoTranslationsFound " : "", -+ (FSR & FSR_WalkingProtectionFault) ? "WalkingProtectionFault " : "", -+ (FSR & FSR_HashTable1) ? "1" : "0"); -+ if (FSR & (FSR_RouteVProcErr | FSR_FaultForBadData)) -+ elan4_debugf (type, mode, "%s FSR: %s%s\n", spaces, -+ (FSR & FSR_RouteVProcErr) ? "RouteVProcErr " : "", -+ (FSR & FSR_FaultForBadData) ? "FaultForBadData " : ""); -+} -+ -+void -+elan4_display_eproc_trap (void *type, int mode, char *str, ELAN4_EPROC_TRAP *trap) -+{ -+ declare_spaces (spaces, str); -+ -+ elan4_debugf (type, mode, "%s Status=%016llx %s EventAddr=%016llx CountAndType=%016llx\n", str, -+ trap->tr_status, EProcTrapNames[EPROC_TrapType(trap->tr_status)], -+ trap->tr_eventaddr, trap->tr_event.ev_CountAndType); -+ elan4_debugf (type, mode, "%s Param=%016llx.%016llx\n", spaces, -+ trap->tr_event.ev_Params[0], trap->tr_event.ev_Params[1]); -+ -+ elan4_display_farea (type, mode, strcat (spaces, EPROC_Port0Fault(trap->tr_status) ? " EPROC0" : " EPROC1"), &trap->tr_faultarea); -+} -+ -+void -+elan4_display_cproc_trap (void *type, int mode, char *str, ELAN4_CPROC_TRAP *trap) -+{ -+ declare_spaces(spaces, str); -+ -+ elan4_debugf (type, mode, "%s Status=%llx %s Command=%llx\n", str, trap->tr_status, -+ CProcTrapNames[CPROC_TrapType(trap->tr_status)], trap->tr_command); -+ elan4_debugf (type, mode, "%s Desc=%016llx %016llx %016llx %016llx\n", str, -+ trap->tr_qdesc.CQ_QueuePtrs, trap->tr_qdesc.CQ_HoldingValue, -+ trap->tr_qdesc.CQ_AckBuffers, trap->tr_qdesc.CQ_Control); -+ -+ switch (CPROC_TrapType (trap->tr_status)) -+ { -+ case CommandProcInserterError: -+ elan4_debugf (type, mode, "%s %s\n", str, CProcInsertError[CQ_RevB_ErrorType(trap->tr_qdesc.CQ_QueuePtrs)]); -+ break; -+ -+ case CommandProcWaitTrap: -+ elan4_display_eproc_trap (type, mode, spaces, &trap->tr_eventtrap); -+ break; -+ -+ default: -+ elan4_display_farea (type, mode, spaces, &trap->tr_faultarea); -+ break; -+ } -+} -+ -+void -+elan4_display_dproc_trap (void *type, int mode, char *str, ELAN4_DPROC_TRAP *trap) -+{ -+ declare_spaces (spaces, str); -+ -+ elan4_debugf (type, mode, "%s status %llx - %s\n", str, -+ trap->tr_status, DProcTrapNames[DPROC_TrapType(trap->tr_status)]); -+ -+ elan4_debugf (type, mode, "%s DESC %016llx %016llx %016llx %016llx\n", spaces, trap->tr_desc.dma_typeSize, -+ trap->tr_desc.dma_cookie, trap->tr_desc.dma_vproc, trap->tr_desc.dma_srcAddr); -+ elan4_debugf (type, mode, "%s %016llx %016llx %016llx\n", spaces, trap->tr_desc.dma_dstAddr, -+ trap->tr_desc.dma_srcEvent, trap->tr_desc.dma_dstEvent); -+ -+ if (DPROC_PrefetcherFault (trap->tr_status)) -+ elan4_display_farea (type, mode, spaces, &trap->tr_prefetchFault); -+} -+ -+void -+elan4_display_tproc_trap (void *type, int mode, char *str, ELAN4_TPROC_TRAP *trap) -+{ -+ register int i; -+ declare_spaces (spaces, str); -+ -+ elan4_debugf (type, mode, "%s PC=%016llx nPC=%016llx State=%016llx Status=%016llx -%s%s%s%s\n", str, -+ trap->tr_pc, trap->tr_npc, trap->tr_state, trap->tr_status, -+ (trap->tr_state & TS_TrapForTooManyInstructions) ? " TrapForTooManyInstructions" : "", -+ (trap->tr_state & TS_Unimplemented) ? " Unimplemented" : "", -+ (trap->tr_state & TS_DataAlignmentError) ? " DataAlignmentError" : "", -+ (trap->tr_state & TS_InstAccessException) ? " InstAccessException" : "", -+ (trap->tr_state & TS_DataAccessException) ? " DataAlignmentError" : ""); -+ -+ for (i = 0; i < 64; i += 4) -+ elan4_debugf (type, mode, "%s r%d - %016llx %016llx %016llx %016llx\n", spaces, i, -+ trap->tr_regs[i], trap->tr_regs[i+1], trap->tr_regs[i+2], trap->tr_regs[i+3]); -+ -+ if (trap->tr_state & TS_InstAccessException) -+ { -+ declare_prefix (prefix, spaces, "Inst"); -+ -+ elan4_display_farea (type, mode, prefix, &trap->tr_instFault); -+ } -+ -+ if (trap->tr_state & TS_DataAccessException) -+ { -+ declare_prefix (prefix, spaces, "Data"); -+ elan4_display_farea (type, mode, prefix, &trap->tr_dataFault); -+ } -+} -+ -+void -+elan4_display_iproc_trap (void *type, int mode, char *str, ELAN4_IPROC_TRAP *trap) -+{ -+ register int i; -+ declare_spaces (spaces, str); -+ -+ for (i = 0; i < trap->tr_numTransactions; i++) -+ { -+ E4_IprocTrapHeader *hdrp = &trap->tr_transactions[i]; -+ E4_uint64 status = hdrp->IProcStatusCntxAndTrType; -+ E4_Addr addr = hdrp->TrAddr; -+ char *typeString; -+ char buffer[256]; -+ char *ptr = buffer; -+ -+ if (IPROC_EOPTrap(status)) -+ { -+ switch (IPROC_EOPType(status)) -+ { -+ case EOP_GOOD: typeString = "EopGood"; break; -+ case EOP_BADACK: typeString = "EopBadAck"; break; -+ case EOP_ERROR_RESET: typeString = "EopReset"; break; -+ default: typeString = "EopBad"; break; -+ } -+ -+ ptr += sprintf (ptr, "%15s Cntx=%-6d", typeString, IPROC_NetworkContext(status)); -+ } -+ else -+ { -+ if (IPROC_BadLength(status)) -+ typeString = "BadLength"; -+ else if (IPROC_TransCRCStatus(status) == CRC_STATUS_DISCARD) -+ typeString = "DiscardCrc"; -+ else if (IPROC_TransCRCStatus(status) == CRC_STATUS_ERROR) -+ typeString = "ErrorCrc Remote Network error"; -+ else if (IPROC_TransCRCStatus(status) == CRC_STATUS_BAD) -+ typeString = "BadCrc Cable error into this node."; -+ else -+ { -+ if ((IPROC_TransactionType(status) & TR_BLOCK_OPCODE_MASK) == TR_WRITEBLOCK) -+ typeString = "WriteBlock"; -+ else -+ { -+ switch (IPROC_TransactionType(status) & TR_OPCODE_MASK) -+ { -+ case TR_SETEVENT_IDENTIFY & TR_OPCODE_MASK: typeString = "SetEvent"; break; -+ case TR_REMOTEDMA & TR_OPCODE_MASK: typeString = "RemoteDma"; break; -+ case TR_SENDDISCARD & TR_OPCODE_MASK: typeString = "SendDiscard"; break; -+ case TR_GTE & TR_OPCODE_MASK: typeString = "GTE"; break; -+ case TR_LT & TR_OPCODE_MASK: typeString = "LT"; break; -+ case TR_EQ & TR_OPCODE_MASK: typeString = "EQ"; break; -+ case TR_NEQ & TR_OPCODE_MASK: typeString = "NEQ"; break; -+ case TR_IDENTIFY & TR_OPCODE_MASK: typeString = "Idenfity"; break; -+ case TR_ADDWORD & TR_OPCODE_MASK: typeString = "AddWord"; break; -+ case TR_INPUT_Q_COMMIT & TR_OPCODE_MASK: typeString = "InputQCommit"; break; -+ case TR_TESTANDWRITE & TR_OPCODE_MASK: typeString = "TestAndWrite"; break; -+ case TR_INPUT_Q_GETINDEX & TR_OPCODE_MASK: typeString = "InputQGetIndex"; break; -+ case TR_TRACEROUTE_TRANS & TR_OPCODE_MASK: typeString = "TraceRoute"; break; -+ default: typeString = "Unknown"; break; -+ } -+ } -+ } -+ -+ ptr += sprintf (ptr, "%15s Cntx=%-6d Addr=%016llx", typeString, IPROC_NetworkContext(status), (unsigned long long) addr); -+ } -+ -+ -+ if (IPROC_TrapValue(status) != InputNoFault) -+ { -+ ptr += sprintf (ptr, " TrType=%2d ChanTrapped=%x GoodAck=%x BadAck=%x InputterChan=%d", IPROC_TrapValue(status), -+ IPROC_ChannelTrapped(status), IPROC_GoodAckSent(status), IPROC_BadAckSent(status), -+ IPROC_InputterChan(status)); -+ if (IPROC_EOPTrap(status)) -+ ptr += sprintf (ptr, " EOPType=%d", IPROC_EOPType(status)); -+ else -+ ptr += sprintf (ptr, " %s%s%s%s", -+ IPROC_FirstTrans(status) ? " FirstTrans" : "", -+ IPROC_LastTrans(status) ? " LastTrans" : "", -+ (IPROC_TransactionType(status) & TR_WAIT_FOR_EOP) ? " WaitForEop" : "", -+ (IPROC_GoodAckSent(status) & (1 << IPROC_Channel(status))) ? " AckSent" : ""); -+ } -+ -+ elan4_debugf (type, mode, "%s %s\n", str, buffer); -+ -+ str = spaces; -+ } -+ -+ elan4_display_farea (type, mode, spaces, &trap->tr_faultarea); -+} -+ -+#define elan4_sdram_copy_faultarea(dev, unit, farea) \ -+ elan4_sdram_copyq_from_sdram ((dev), (dev)->dev_faultarea + (unit) * sizeof (E4_FaultSave), (E4_uint64 *) farea, sizeof (E4_FaultSave)); -+ -+void -+elan4_extract_eproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_EPROC_TRAP *trap, int iswaitevent) -+{ -+ /* only one of the memory ports can fault at a time */ -+ ASSERT (EPROC_TrapType(status) != EventProcMemoryFault || (EPROC_Port0Fault(status) ^ EPROC_Port1Fault(status)) == 1); -+ -+ trap->tr_status = status; -+ -+ if (EPROC_Port0Fault(status)) -+ elan4_sdram_copy_faultarea (dev, CUN_EventProc0, &trap->tr_faultarea); -+ if (EPROC_Port1Fault(status)) -+ elan4_sdram_copy_faultarea (dev, CUN_EventProc1, &trap->tr_faultarea); -+ -+ if (iswaitevent) -+ { -+ /* -+ * for waitevents the Event address is always taken from the command processor -+ * -+ * if we trapped during the copy then we take the "Event" from the event processor -+ * since we need to complete the copy. Otherwise we'll be reissuing the original -+ * command again -+ */ -+ E4_uint32 fsr = FaultSaveFSR(trap->tr_faultarea.FSRAndFaultContext); -+ -+ trap->tr_eventaddr = read_reg64 (dev, CommandHold) ^ WAIT_EVENT_CMD; -+ -+ if (EPROC_TrapType(trap->tr_status) == EventProcMemoryFault && -+ (AT_Perm(fsr) == AT_PermLocalDataRead || AT_Perm(fsr) == AT_PermLocalDataWrite)) -+ { -+ trap->tr_event.ev_CountAndType = read_reg64 (dev, EventCountAndType); -+ trap->tr_event.ev_Params[0] = read_reg64 (dev, EventParameters[0]); -+ trap->tr_event.ev_Params[1] = read_reg64 (dev, EventParameters[1]); -+ } -+ else -+ { -+ trap->tr_event.ev_Params[0] = read_reg64 (dev, CommandCopy[5]); -+ trap->tr_event.ev_CountAndType = read_reg64 (dev, CommandCopy[4]); -+ trap->tr_event.ev_Params[1] = read_reg64 (dev, CommandCopy[6]); -+ -+ } -+ } -+ else -+ { -+ trap->tr_eventaddr = read_reg64 (dev, EventAddress); -+ trap->tr_event.ev_CountAndType = read_reg64 (dev, EventCountAndType); -+ trap->tr_event.ev_Params[0] = read_reg64 (dev, EventParameters[0]); -+ trap->tr_event.ev_Params[1] = read_reg64 (dev, EventParameters[1]); -+ } -+ -+ BumpDevStat (dev, s_eproc_trap_types[EPROC_TrapType(status)]); -+} -+ -+int -+cproc_open_extract_vp (ELAN4_DEV *dev, ELAN4_CQ *cq) -+{ -+ /* cq = ucq->ucq_cq */ -+ if ((cq->cq_perm & CQ_STENEnableBit) != 0) -+ { -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (elan4_cq2num(cq) * sizeof (E4_CommandQueueDesc)); -+ E4_uint64 queuePtrs = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs)); -+ sdramaddr_t insertPtr = (queuePtrs & CQ_PtrMask); -+ sdramaddr_t commandPtr = CQ_CompletedPtr (queuePtrs); -+ unsigned int cqSize = CQ_Size ((queuePtrs >> CQ_SizeShift) & CQ_SizeMask); -+ E4_uint64 openCommand = 0; -+ -+ if (dev->dev_devinfo.dev_revision_id != PCI_REVISION_ID_ELAN4_REVA && (queuePtrs & CQ_RevB_ReorderingQueue)) -+ { -+ E4_uint32 oooMask = elan4_sdram_readl (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_HoldingValue)); -+ -+ for (; (oooMask & 1) != 0; oooMask >>= 1) -+ insertPtr = (insertPtr & ~(cqSize-1)) | ((insertPtr + sizeof (E4_uint64)) & (cqSize-1)); -+ } -+ -+ while (commandPtr != insertPtr) -+ { -+ E4_uint64 command = elan4_sdram_readq (dev, commandPtr); -+ unsigned int cmdSize; -+ -+ switch (__categorise_command (command, &cmdSize)) -+ { -+ case 0: -+ (void) __whole_command (&commandPtr, insertPtr, cqSize, cmdSize); -+ break; -+ -+ case 1: /* open */ -+ return (command >> 32); -+ -+ break; /* Not reached */ -+ -+ case 2: -+ if (openCommand == 0) -+ (void) __whole_command (&commandPtr, insertPtr, cqSize, cmdSize); -+ /* Else we should have stopped by now */ -+ else ASSERT(1==2); -+ case 3: -+ printk ("cproc_open_extract_vp: invalid command %llx\n", command); -+ return -1; -+ } -+ } /* while */ -+ } -+ -+ return -1; -+} -+ -+void -+elan4_extract_cproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_CPROC_TRAP *trap, unsigned cqnum) -+{ -+ /* extract the state from the device */ -+ elan4_sdram_copy_faultarea (dev, CUN_CommandProc, &trap->tr_faultarea); -+ -+ trap->tr_status = status; -+ trap->tr_command = read_reg64 (dev, CommandHold); -+ -+ elan4_sdram_copyq_from_sdram (dev, dev->dev_cqaddr + (cqnum * sizeof (E4_CommandQueueDesc)), &trap->tr_qdesc, sizeof (E4_CommandQueueDesc)); -+ -+ if (CPROC_TrapType (status) == CommandProcWaitTrap) -+ elan4_extract_eproc_trap (dev, read_reg64 (dev, EProcStatus), &trap->tr_eventtrap, 1); -+ -+ BumpDevStat (dev, s_cproc_trap_types[CPROC_TrapType(status)]); -+ -+ if (PackValue(trap->tr_qdesc.CQ_AckBuffers, 0) == PackTimeout || PackValue(trap->tr_qdesc.CQ_AckBuffers, 1) == PackTimeout) -+ BumpDevStat (dev, s_cproc_timeout); -+} -+ -+void -+elan4_extract_dproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_DPROC_TRAP *trap, unsigned unit) -+{ -+ trap->tr_status = status; -+ -+ if (unit == 0) -+ { -+ trap->tr_desc.dma_typeSize = read_reg64 (dev, Dma0Desc.dma_typeSize); -+ trap->tr_desc.dma_cookie = read_reg64 (dev, Dma0Desc.dma_cookie); -+ trap->tr_desc.dma_vproc = read_reg64 (dev, Dma0Desc.dma_vproc); -+ trap->tr_desc.dma_srcAddr = read_reg64 (dev, Dma0Desc.dma_srcAddr); -+ trap->tr_desc.dma_dstAddr = read_reg64 (dev, Dma0Desc.dma_dstAddr); -+ trap->tr_desc.dma_srcEvent = read_reg64 (dev, Dma0Desc.dma_srcEvent); -+ trap->tr_desc.dma_dstEvent = read_reg64 (dev, Dma0Desc.dma_dstEvent); -+ -+ elan4_sdram_copy_faultarea (dev, CUN_DProcPA0, &trap->tr_packAssemFault); -+ } -+ else -+ { -+ trap->tr_desc.dma_typeSize = read_reg64 (dev, Dma1Desc.dma_typeSize); -+ trap->tr_desc.dma_cookie = read_reg64 (dev, Dma1Desc.dma_cookie); -+ trap->tr_desc.dma_vproc = read_reg64 (dev, Dma1Desc.dma_vproc); -+ trap->tr_desc.dma_srcAddr = read_reg64 (dev, Dma1Desc.dma_srcAddr); -+ trap->tr_desc.dma_dstAddr = read_reg64 (dev, Dma1Desc.dma_dstAddr); -+ trap->tr_desc.dma_srcEvent = read_reg64 (dev, Dma1Desc.dma_srcEvent); -+ trap->tr_desc.dma_dstEvent = read_reg64 (dev, Dma1Desc.dma_dstEvent); -+ -+ elan4_sdram_copy_faultarea (dev, CUN_DProcPA1, &trap->tr_packAssemFault); -+ } -+ -+ if (DPROC_PrefetcherFault (trap->tr_status)) -+ elan4_sdram_copy_faultarea (dev, (CUN_DProcData0 | DPROC_FaultUnitNo(trap->tr_status)), &trap->tr_prefetchFault); -+ -+ if (DPROC_PacketTimeout (trap->tr_status)) -+ BumpDevStat (dev, s_dproc_timeout); -+ -+ BumpDevStat (dev, s_dproc_trap_types[DPROC_TrapType(status)]); -+} -+ -+void -+elan4_extract_tproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_TPROC_TRAP *trap) -+{ -+ int i; -+ -+ trap->tr_status = status; -+ trap->tr_state = read_reg64 (dev, Thread_Trap_State); -+ trap->tr_pc = read_reg64 (dev, PC_W); -+ trap->tr_npc = read_reg64 (dev, nPC_W); -+ trap->tr_dirty = read_reg64 (dev, DirtyBits); -+ trap->tr_bad = read_reg64 (dev, BadBits); -+ -+#ifdef CONFIG_MPSAS -+ if (sas_copyfrom_dev (dev->dev_osdep.pdev, ELAN4_BAR_REGISTERS, -+ ((dev->dev_devinfo.dev_revision_id == PCI_REVISION_ID_ELAN4_REVA) ? ELAN4_REVA_REG_OFFSET : ELAN4_REVB_REG_OFFSET) + -+ offsetof (E4_Registers, Regs.TProcRegs), (unsigned long) &trap->tr_regs, 64*sizeof (E4_uint64)) < 0) -+ { -+ for (i = 0; i < 64; i++) -+ if (trap->tr_dirty & ((E4_uint64) 1 << i)) -+ trap->tr_regs[i] = read_reg64 (dev, TProcRegs[i]); -+ } -+ -+ for (i = 0; i < 64; i++) -+ if (! (trap->tr_dirty & ((E4_uint64) 1 << i))) -+ trap->tr_regs[i] = 0xdeadbabedeadbabeULL; -+#else -+ for (i = 0; i < 64; i++) -+ { -+ if (trap->tr_dirty & ((E4_uint64) 1 << i)) -+ trap->tr_regs[i] = read_reg64 (dev, TProcRegs[i]); -+ else -+ trap->tr_regs[i] = 0xdeadbabedeadbabeULL; -+ } -+#endif -+ -+ if (trap->tr_state & TS_DataAccessException) -+ elan4_sdram_copy_faultarea (dev, CUN_TProcData0 | TS_DataPortNo (trap->tr_state), &trap->tr_dataFault); -+ -+ if (trap->tr_state & TS_InstAccessException) -+ elan4_sdram_copy_faultarea (dev, CUN_TProcInst, &trap->tr_instFault); -+ -+ for (i = 0; i < 7; i++) -+ if (trap->tr_state & (1 << i)) -+ BumpDevStat (dev, s_tproc_trap_types[i]); -+} -+ -+void -+elan4_extract_iproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_IPROC_TRAP *trap, unsigned unit) -+{ -+ sdramaddr_t hdroff = dev->dev_inputtraparea + offsetof (E4_IprocTrapState, TrHeader[0][unit]); -+ sdramaddr_t dataoff = dev->dev_inputtraparea + offsetof (E4_IprocTrapState, TrData[0][unit]); -+ register int i, j; -+ int CurrUnitNo = (unit >= 2) ? CUN_IProcHighPri : CUN_IProcLowPri; -+ sdramaddr_t CurrFaultArea = dev->dev_faultarea + (CurrUnitNo * sizeof (E4_FaultSave)); -+ -+ /* Finally copy the fault area */ -+ elan4_sdram_copy_faultarea (dev, CurrUnitNo, &trap->tr_faultarea); -+ -+ /* -+ * Clear out the fault save area after reading to allow a fault on the write of the back pointer of -+ * an InputQCommit to be obsurved if a simultaneous event proc trap occurs. -+ */ -+ elan4_sdram_writeq (dev, CurrFaultArea + offsetof(E4_FaultSave, FSRAndFaultContext), 0x0ULL); -+ elan4_sdram_writeq (dev, CurrFaultArea + offsetof(E4_FaultSave, FaultAddress), 0x0ULL); -+ -+ /* copy the transaction headers */ -+ trap->tr_transactions[0].IProcStatusCntxAndTrType = status; -+ trap->tr_transactions[0].TrAddr = elan4_sdram_readq (dev, hdroff + offsetof (E4_IprocTrapHeader, TrAddr)); -+ -+ for (i = 0; !IPROC_EOPTrap(trap->tr_transactions[i].IProcStatusCntxAndTrType);) -+ { -+ if (IPROC_BadLength (trap->tr_transactions[i].IProcStatusCntxAndTrType)) -+ BumpDevStat (dev, s_bad_length); -+ else if (IPROC_TransCRCStatus (trap->tr_transactions[i].IProcStatusCntxAndTrType) == CRC_STATUS_BAD) -+ BumpDevStat (dev, s_crc_bad); -+ else if (IPROC_TransCRCStatus (trap->tr_transactions[i].IProcStatusCntxAndTrType) == CRC_STATUS_ERROR) -+ BumpDevStat (dev, s_crc_error); -+ -+ BumpDevStat (dev, s_iproc_trap_types[IPROC_TrapValue (trap->tr_transactions[i].IProcStatusCntxAndTrType)]); -+ -+ hdroff += NO_OF_INPUT_CHANNELS*sizeof (E4_IprocTrapHeader); -+ -+ if (++i == MAX_TRAPPED_TRANS) -+ break; -+ -+ elan4_sdram_copyq_from_sdram (dev, hdroff, &trap->tr_transactions[i], sizeof (E4_IprocTrapHeader)); -+ } -+ -+ if (IPROC_EOPType (trap->tr_transactions[i].IProcStatusCntxAndTrType) == EOP_ERROR_RESET) -+ BumpDevStat (dev, s_eop_reset); -+ -+ /* Remember the number of transactions we've copied */ -+ trap->tr_numTransactions = i + 1; -+ -+ /* Copy all the data blocks in one go */ -+ for (i = 0; i < MIN (trap->tr_numTransactions, MAX_TRAPPED_TRANS); i++, dataoff += NO_OF_INPUT_CHANNELS*sizeof (E4_IprocTrapData)) -+ { -+ if (IPROC_BadLength(status) || IPROC_TransCRCStatus (status) != CRC_STATUS_GOOD) -+ elan4_sdram_copyq_from_sdram (dev, dataoff, trap->tr_dataBuffers[i].Data, TRANS_DATA_DWORDS*sizeof(E4_uint64)); -+ else -+ { -+ int trtype = IPROC_TransactionType(trap->tr_transactions[i].IProcStatusCntxAndTrType); -+ int ndwords = (trtype & TR_SIZE_MASK) >> TR_SIZE_SHIFT; -+ -+ elan4_sdram_copyq_from_sdram (dev, dataoff, trap->tr_dataBuffers[i].Data, ndwords*sizeof(E4_uint64)); -+ -+ for (j = ndwords; j < TRANS_DATA_DWORDS; j++) -+ trap->tr_dataBuffers[i].Data[j] = 0xbeec0f212345678ull; -+ } -+ } -+ -+} -+ -+void -+elan4_inspect_iproc_trap (ELAN4_IPROC_TRAP *trap) -+{ -+ int i; -+ -+ trap->tr_flags = 0; -+ trap->tr_trappedTrans = TR_TRANS_INVALID; -+ trap->tr_waitForEopTrans = TR_TRANS_INVALID; -+ trap->tr_identifyTrans = TR_TRANS_INVALID; -+ -+ if (trap->tr_numTransactions > MAX_TRAPPED_TRANS) -+ trap->tr_flags = TR_FLAG_TOOMANY_TRANS; -+ -+ /* -+ * Now scan all the transactions received -+ */ -+ for (i = 0; i < MIN(trap->tr_numTransactions, MAX_TRAPPED_TRANS) ; i++) -+ { -+ E4_IprocTrapHeader *hdrp = &trap->tr_transactions[i]; -+ E4_uint64 status = hdrp->IProcStatusCntxAndTrType; -+ -+ if (trap->tr_identifyTrans == TR_TRANS_INVALID) -+ { -+ switch (IPROC_TransactionType (status) & (TR_OPCODE_MASK | TR_SIZE_MASK)) -+ { -+ case TR_IDENTIFY & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_REMOTEDMA & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_SETEVENT_IDENTIFY & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_INPUT_Q_COMMIT & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_ADDWORD & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_TESTANDWRITE & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ trap->tr_identifyTrans = i; -+ break; -+ } -+ } -+ -+ if (IPROC_TrapValue(status) == InputNoFault) /* We're looking at transactions stored before the trap */ -+ continue; /* these should only be identifies */ -+ -+ if (trap->tr_trappedTrans == TR_TRANS_INVALID) /* Remember the transaction which caused the */ -+ trap->tr_trappedTrans = i; /* trap */ -+ -+ if (IPROC_GoodAckSent (status) & (1 << IPROC_InputterChan (status))) -+ trap->tr_flags |= TR_FLAG_ACK_SENT; -+ -+ if (IPROC_EOPTrap(status)) /* Check for EOP */ -+ { -+ ASSERT (i == trap->tr_numTransactions - 1); -+ -+ switch (IPROC_EOPType(status)) -+ { -+ case EOP_GOOD: -+ /* if we get an EOP_GOOD then the outputer should have received a PAckOk. */ -+ /* unless it was a flood, in which case someone must have sent an ack */ -+ /* but not necessarily us */ -+ break; -+ -+ case EOP_BADACK: -+ /* if we get an EOP_BADACK then the outputer did not receive a PAckOk even if -+ * we sent a PAckOk. WFlag this to ignore the AckSent. */ -+ trap->tr_flags |= TR_FLAG_EOP_BAD; -+ break; -+ -+ case EOP_ERROR_RESET: -+ /* if we get an EOP_ERROR_RESET then the outputer may or may not have got a PAckOk. */ -+ trap->tr_flags |= TR_FLAG_EOP_ERROR; -+ break; -+ -+ default: -+ printk ("elan4_inspect_iproc_trap: unknown eop type %d", IPROC_EOPType(status)); -+ BUG(); -+ /* NOTREACHED */ -+ } -+ continue; -+ } -+ else -+ { -+ if (IPROC_BadLength(status) || (IPROC_TransCRCStatus (status) == CRC_STATUS_ERROR || -+ IPROC_TransCRCStatus (status) == CRC_STATUS_BAD)) -+ { -+ { -+ register int j; -+ if (IPROC_BadLength(status)) -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "LinkError: Trapped on bad length data. status=%016llx Address=%016llx\n", -+ status, hdrp->TrAddr); -+ else -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "LinkError: Trapped with bad CRC. status=%016llx Address=%016llx\n", -+ status, hdrp->TrAddr); -+ for (j = 0; j < TRANS_DATA_DWORDS; j++) -+ PRINTF2 (DBG_DEVICE, DBG_INTR, "LinkError: DataBuffers[%d] : %016llx\n", j, trap->tr_dataBuffers[i].Data[j]); -+ } -+ -+ trap->tr_flags |= TR_FLAG_BAD_TRANS; -+ continue; -+ } -+ -+ if (IPROC_TransCRCStatus (status) == CRC_STATUS_DISCARD) -+ continue; -+ -+ if ((((IPROC_TransactionType(status) & TR_BLOCK_OPCODE_MASK) == TR_WRITEBLOCK) || -+ (IPROC_TransactionType(status) == TR_TRACEROUTE_TRANS)) && -+ (trap->tr_flags & TR_FLAG_ACK_SENT) && trap->tr_identifyTrans == TR_TRANS_INVALID) -+ { -+ /* -+ * Writeblock after the ack is sent without an identify transaction - this is -+ * considered to be a DMA packet and requires the next packet to be nacked - since -+ * the DMA processor will send this in a deterministic time and there's an upper -+ * limit on the network latency (the output timeout) we just need to hold the context -+ * filter up for a while. -+ */ -+ trap->tr_flags |= TR_FLAG_DMA_PACKET; -+ } -+ -+ if (IPROC_LastTrans(status) && (IPROC_TransactionType(status) & TR_WAIT_FOR_EOP)) -+ { -+ /* -+ * WaitForEop transactions - if we have to do network error fixup -+ * then we may need to execute/ignore this transaction dependant -+ * on whether the source will be resending it. -+ */ -+ trap->tr_waitForEopTrans = i; -+ } -+ -+ /* -+ * This is a special case caused by a minor input processor bug. -+ * If simultaneous InputMemoryFault and InputEventEngineTrapped occur then the chip will probably return -+ * InputEventEngineTrapped even though the write of the back pointer has not occured and must be done by -+ * the trap handler. -+ * In this case the fault address will equal q->q_bptr. If there has been only EventEngineTrap then the -+ * the fault address should be zero as the trap handler now always zeros this after every input trap. -+ */ -+ if ((IPROC_TransactionType (status) & TR_OPCODE_MASK) == (TR_INPUT_Q_COMMIT & TR_OPCODE_MASK) && -+ trap->tr_faultarea.FaultAddress == hdrp->TrAddr + offsetof(E4_InputQueue, q_bptr) && -+ IPROC_TrapValue(status) == InputEventEngineTrapped) -+ { -+ hdrp->IProcStatusCntxAndTrType = (status & 0xFFFFFFF0FFFFFFFFull) | ((E4_uint64) InputMemoryFault << 32); -+ } -+ } -+ -+ PRINTF (DBG_DEVICE, DBG_INTR, "inspect[%d] status=%llx TrapValue=%d -> flags %x\n", i, status, IPROC_TrapValue(status), trap->tr_flags); -+ } -+} -+ -+E4_uint64 -+elan4_trapped_open_command (ELAN4_DEV *dev, ELAN4_CQ *cq) -+{ -+ sdramaddr_t cqdesc = dev->dev_cqaddr + elan4_cq2num(cq) * sizeof (E4_CommandQueueDesc); -+ E4_uint64 cqcontrol = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control)); -+ E4_uint32 extractOff = CQ_ExtractPtr (cqcontrol) & (CQ_Size(cq->cq_size)-1); -+ -+ if (extractOff == 0) -+ extractOff = CQ_Size(cq->cq_size) - sizeof (E4_uint64); -+ else -+ extractOff -= sizeof (E4_uint64); -+ -+ return (elan4_sdram_readq (dev, cq->cq_space + extractOff)); -+} -+ -+EXPORT_SYMBOL(elan4_extract_eproc_trap); -+EXPORT_SYMBOL(elan4_display_eproc_trap); -+EXPORT_SYMBOL(elan4_extract_cproc_trap); -+EXPORT_SYMBOL(elan4_display_cproc_trap); -+EXPORT_SYMBOL(elan4_extract_dproc_trap); -+EXPORT_SYMBOL(elan4_display_dproc_trap); -+EXPORT_SYMBOL(elan4_extract_tproc_trap); -+EXPORT_SYMBOL(elan4_display_tproc_trap); -+EXPORT_SYMBOL(elan4_extract_iproc_trap); -+EXPORT_SYMBOL(elan4_inspect_iproc_trap); -+EXPORT_SYMBOL(elan4_display_iproc_trap); -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/user.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/user.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/user.c 2005-06-01 23:12:54.624435304 -0400 -@@ -0,0 +1,3352 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: user.c,v 1.68.2.9 2004/12/20 16:56:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/user.c,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+/* allow this code to compile against an Eagle elanmod */ -+#ifdef __ELANMOD_DEVICE_H -+#define elan_attach_cap(cap,rnum,args,func) elanmod_attach_cap(cap,args,func) -+#define elan_detach_cap(cap,rnum) elanmod_detach_cap(cap) -+#endif -+ -+#define NETERR_MSGS 16 -+ -+int user_p2p_route_options = FIRST_TIMEOUT(3); -+int user_bcast_route_options = FIRST_TIMEOUT(3); -+int user_dproc_retry_count = 15; -+int user_cproc_retry_count = 2; -+ -+int num_fault_save = 30; -+int min_fault_pages = 1; -+int max_fault_pages = 128; -+ -+static int -+user_validate_cap (USER_CTXT *uctx, ELAN_CAPABILITY *cap, unsigned use) -+{ -+ /* Don't allow a user process to attach to system context */ -+ if (ELAN4_SYSTEM_CONTEXT (cap->cap_lowcontext) || ELAN4_SYSTEM_CONTEXT (cap->cap_highcontext)) -+ { -+ PRINTF3 (DBG_DEVICE, DBG_VP,"user_validate_cap: lctx %x hctx %x high %x\n", cap->cap_lowcontext, cap->cap_highcontext, ELAN4_KCOMM_BASE_CONTEXT_NUM); -+ PRINTF0 (DBG_DEVICE, DBG_VP,"user_validate_cap: user process cant attach to system cap\n"); -+ return (EINVAL); -+ } -+ -+ return elanmod_classify_cap(&uctx->uctx_position, cap, use); -+} -+ -+static __inline__ void -+__user_signal_trap (USER_CTXT *uctx) -+{ -+ switch (uctx->uctx_trap_state) -+ { -+ case UCTX_TRAP_IDLE: -+ PRINTF (uctx, DBG_TRAP, "user_signal_trap: deliver signal %d to pid %d\n", uctx->uctx_trap_signo, uctx->uctx_trap_pid); -+ -+ if (uctx->uctx_trap_signo) -+ kill_proc (uctx->uctx_trap_pid, uctx->uctx_trap_signo, 1); -+ break; -+ -+ case UCTX_TRAP_SLEEPING: -+ PRINTF (uctx, DBG_TRAP, "user_signal_trap: wakeup sleeping trap handler\n"); -+ -+ kcondvar_wakeupone (&uctx->uctx_wait, &uctx->uctx_spinlock); -+ break; -+ } -+ uctx->uctx_trap_state = UCTX_TRAP_SIGNALLED; -+} -+ -+static void -+user_signal_timer (unsigned long arg) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) arg; -+ unsigned long flags; -+ -+ PRINTF (uctx, DBG_TRAP, "user_signal_timer: state=%d pid=%d signal=%d (now %d start %d)\n", -+ uctx->uctx_trap_state, uctx->uctx_trap_pid, uctx->uctx_trap_signo, jiffies, -+ uctx->uctx_int_start); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ __user_signal_trap (uctx); -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+#define MAX_INTS_PER_TICK 50 -+#define MIN_INTS_PER_TICK 20 -+ -+static void -+user_signal_trap (USER_CTXT *uctx) -+{ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_spinlock)); -+ -+ PRINTF (uctx, DBG_TRAP, "user_signal_trap: state=%d pid=%d signal=%d%s\n", uctx->uctx_trap_state, -+ uctx->uctx_trap_pid, uctx->uctx_trap_signo, timer_pending(&uctx->uctx_int_timer) ? " (timer-pending)" : ""); -+ -+ uctx->uctx_int_count++; -+ -+ if (timer_pending (&uctx->uctx_int_timer)) -+ return; -+ -+ if (uctx->uctx_int_count > ((int)(jiffies - uctx->uctx_int_start) * MAX_INTS_PER_TICK)) -+ { -+ PRINTF (uctx, DBG_TRAP, "user_signal_trap: deferring signal for %d ticks (count %d ticks %d -> %d)\n", -+ uctx->uctx_int_delay + 1, uctx->uctx_int_count, (int) (jiffies - uctx->uctx_int_start), -+ ((int)(jiffies - uctx->uctx_int_start) * MAX_INTS_PER_TICK)); -+ -+ /* We're interrupting too fast, so defer this signal */ -+ uctx->uctx_int_timer.expires = jiffies + (++uctx->uctx_int_delay); -+ -+ add_timer (&uctx->uctx_int_timer); -+ } -+ else -+ { -+ __user_signal_trap (uctx); -+ -+ PRINTF (uctx, DBG_TRAP, "user_signal_trap: check signal for %d ticks (count %d ticks %d -> %d)\n", -+ uctx->uctx_int_delay + 1, uctx->uctx_int_count, (int) (jiffies - uctx->uctx_int_start), -+ (int)(jiffies - uctx->uctx_int_start) * MIN_INTS_PER_TICK); -+ -+ if (uctx->uctx_int_count < ((int) (jiffies - uctx->uctx_int_start)) * MIN_INTS_PER_TICK) -+ { -+ PRINTF (uctx, DBG_TRAP, "user_signal_trap: reset interrupt throttle (count %d ticks %d)\n", -+ uctx->uctx_int_count, (int) (jiffies - uctx->uctx_int_start)); -+ -+ uctx->uctx_int_start = jiffies; -+ uctx->uctx_int_count = 0; -+ uctx->uctx_int_delay = 0; -+ } -+ } -+} -+ -+static void -+user_neterr_timer (unsigned long arg) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ uctx->uctx_status |= UCTX_NETERR_TIMER; -+ -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_flush_dma_runqueue (ELAN4_DEV *dev, USER_CTXT *uctx, int qfull) -+{ -+ E4_uint64 qptrs = read_reg64 (dev, DProcLowPriPtrs); -+ E4_uint32 qsize = E4_QueueSize (E4_QueueSizeValue (qptrs)); -+ E4_uint32 qfptr = E4_QueueFrontPointer (qptrs); -+ E4_uint32 qbptr = E4_QueueBackPointer (qptrs); -+ E4_DProcQueueEntry qentry; -+ -+ while ((qfptr != qbptr) || qfull) -+ { -+ E4_uint64 typeSize = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_typeSize)); -+ -+ if (DMA_Context (typeSize) == uctx->uctx_ctxt.ctxt_num) -+ { -+ elan4_sdram_copyq_from_sdram (dev, qfptr, &qentry, sizeof (E4_DProcQueueEntry)); -+ -+ PRINTF4 (uctx, DBG_SWAP, "user_flush_dma_runqueue: %016llx %016llx %016llx %016llx\n", qentry.Desc.dma_typeSize, -+ qentry.Desc.dma_cookie, qentry.Desc.dma_vproc, qentry.Desc.dma_srcAddr); -+ PRINTF3 (uctx, DBG_SWAP, " %016llx %016llx %016llx\n", qentry.Desc.dma_dstAddr, -+ qentry.Desc.dma_srcEvent, qentry.Desc.dma_dstEvent); -+ -+ if (RING_QUEUE_REALLY_FULL (uctx->uctx_dmaQ)) -+ uctx->uctx_status |= UCTX_DPROC_QUEUE_OVERFLOW; -+ else -+ { -+ *RING_QUEUE_BACK (uctx->uctx_dmaQ, uctx->uctx_dmas) = qentry.Desc; -+ (void) RING_QUEUE_ADD (uctx->uctx_dmaQ); -+ } -+ -+ qentry.Desc.dma_typeSize = DMA_ShMemWrite | dev->dev_ctxt.ctxt_num; -+ qentry.Desc.dma_cookie = 0; -+ qentry.Desc.dma_vproc = 0; -+ qentry.Desc.dma_srcAddr = 0; -+ qentry.Desc.dma_dstAddr = 0; -+ qentry.Desc.dma_srcEvent = 0; -+ qentry.Desc.dma_dstEvent = 0; -+ -+ elan4_sdram_copyq_to_sdram (dev, &qentry, qfptr, sizeof (E4_DProcQueueEntry)); -+ } -+ -+ qfptr = (qfptr & ~(qsize-1)) | ((qfptr + sizeof (E4_DProcQueueEntry)) & (qsize-1)); -+ qfull = 0; -+ } -+} -+ -+static void -+user_flush_thread_runqueue (ELAN4_DEV *dev, USER_CTXT *uctx, int qfull) -+{ -+ E4_uint64 qptrs = read_reg64 (dev, TProcLowPriPtrs); -+ E4_uint32 qsize = E4_QueueSize (E4_QueueSizeValue (qptrs)); -+ E4_uint32 qfptr = E4_QueueFrontPointer (qptrs); -+ E4_uint32 qbptr = E4_QueueBackPointer (qptrs); -+ E4_TProcQueueEntry qentry; -+ -+ while ((qfptr != qbptr) || qfull) -+ { -+ E4_uint64 context = elan4_sdram_readq (dev, qfptr + offsetof (E4_TProcQueueEntry, Context)); -+ -+ if (TPROC_Context (context) == uctx->uctx_ctxt.ctxt_num) -+ { -+ elan4_sdram_copyq_from_sdram (dev, qfptr, &qentry, sizeof (E4_TProcQueueEntry)); -+ -+ PRINTF (uctx, DBG_SWAP, "user_flush_thread_runqueue: %016llx %016llx %016llx %016llx\n", qentry.Regs.Registers[0], -+ qentry.Regs.Registers[1], qentry.Regs.Registers[2], qentry.Regs.Registers[3]); -+ PRINTF (uctx, DBG_SWAP, " %016llx %016llx %016llx\n", -+ qentry.Regs.Registers[4], qentry.Regs.Registers[5], qentry.Regs.Registers[6]); -+ -+ if (RING_QUEUE_REALLY_FULL (uctx->uctx_threadQ)) -+ uctx->uctx_status |= UCTX_TPROC_QUEUE_OVERFLOW; -+ else -+ { -+ *RING_QUEUE_BACK (uctx->uctx_threadQ, uctx->uctx_threads) = qentry.Regs; -+ (void) RING_QUEUE_ADD (uctx->uctx_threadQ); -+ } -+ -+ /* change the thread to execute the suspend sequence */ -+ qentry.Regs.Registers[0] = dev->dev_tproc_suspend; -+ qentry.Regs.Registers[1] = dev->dev_tproc_space; -+ qentry.Context = dev->dev_ctxt.ctxt_num; -+ -+ elan4_sdram_copyq_to_sdram (dev, &qentry, qfptr, sizeof (E4_TProcQueueEntry)); -+ } -+ -+ qfptr = (qfptr & ~(qsize-1)) | ((qfptr + sizeof (E4_TProcQueueEntry)) & (qsize-1)); -+ qfull = 0; -+ } -+} -+ -+static void -+user_flush_dmas (ELAN4_DEV *dev, void *arg, int qfull) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) arg; -+ unsigned long flags; -+ -+ ASSERT ((read_reg32 (dev, InterruptReg) & INT_DProcHalted) != 0); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if ((uctx->uctx_status & (UCTX_SWAPPED_REASONS|UCTX_STOPPED_REASONS)) == 0) -+ { -+ PRINTF1 (uctx, DBG_SWAP, "user_flush_dmas: status %x - no more reasons\n", uctx->uctx_status); -+ -+ uctx->uctx_status &= ~UCTX_STOPPING; -+ -+ user_signal_trap (uctx); -+ } -+ else -+ { -+ user_flush_dma_runqueue (dev, uctx, qfull); -+ -+ uctx->uctx_status = (uctx->uctx_status | UCTX_STOPPED) & ~UCTX_STOPPING; -+ -+ PRINTF1 (uctx, DBG_SWAP, "user_flush_dmas: statux %x - stopped\n", uctx->uctx_status); -+ -+ kcondvar_wakeupall (&uctx->uctx_wait, &uctx->uctx_spinlock); -+ } -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_flush (ELAN4_DEV *dev, void *arg) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) arg; -+ struct list_head *entry; -+ unsigned long flags; -+ -+ ASSERT ((read_reg32 (dev, InterruptReg) & (INT_Halted|INT_Discarding)) == (INT_Halted|INT_Discarding)); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if ((uctx->uctx_status & (UCTX_SWAPPED_REASONS|UCTX_STOPPED_REASONS)) == 0) -+ { -+ PRINTF1 (uctx, DBG_SWAP, "user_flush: status %x - no more reasons\n", uctx->uctx_status); -+ -+ uctx->uctx_status &= ~UCTX_STOPPING; -+ -+ user_signal_trap (uctx); -+ } -+ else -+ { -+ PRINTF1 (uctx, DBG_SWAP, "user_flush: status %x - flushing context\n", uctx->uctx_status); -+ -+ list_for_each (entry, &uctx->uctx_cqlist) { -+ USER_CQ *ucq = list_entry (entry, USER_CQ, ucq_link); -+ -+ if (ucq->ucq_state == UCQ_RUNNING) -+ { -+ /* NOTE: since the inserter can still be running we modify the permissions -+ * to zero then when the extractor starts up again it will trap */ -+ PRINTF1 (uctx, DBG_SWAP, "user_flush: stopping cq indx=%d\n", elan4_cq2idx(ucq->ucq_cq)); -+ -+ elan4_updatecq (dev, ucq->ucq_cq, 0, 0); -+ } -+ } -+ -+ user_flush_thread_runqueue (dev, uctx, TPROC_LowRunQueueFull(read_reg64 (dev, TProcStatus))); -+ -+ /* since we can't determine whether the dma run queue is full or empty, we use a dma -+ * halt operation to do the flushing - as the reason for halting the dma processor -+ * will be released when we return, we keep it halted until the flush has completed */ -+ elan4_queue_dma_flushop (dev, &uctx->uctx_dma_flushop, 0); -+ -+ if (uctx->uctx_status & UCTX_EXITING) -+ elan4_flush_icache_halted (&uctx->uctx_ctxt); -+ } -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_set_filter (USER_CTXT *uctx, E4_uint32 state) -+{ -+ struct list_head *entry; -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_spinlock)); -+ -+ list_for_each (entry, &uctx->uctx_cent_list) { -+ USER_CTXT_ENTRY *cent = list_entry (entry, USER_CTXT_ENTRY, cent_link); -+ -+ elan4_set_filter (&uctx->uctx_ctxt, cent->cent_cap->cap_mycontext, state); -+ } -+} -+ -+static void -+user_start_nacking (USER_CTXT *uctx, unsigned reason) -+{ -+ PRINTF2 (uctx, DBG_SWAP, "user_start_nacking: status %x reason %x\n", uctx->uctx_status, reason); -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_spinlock)); -+ -+ if (UCTX_NACKING(uctx)) -+ uctx->uctx_status |= reason; -+ else -+ { -+ uctx->uctx_status |= reason; -+ -+ user_set_filter (uctx, E4_FILTER_STATS | E4_FILTER_DISCARD_ALL); -+ } -+} -+ -+static void -+user_stop_nacking (USER_CTXT *uctx, unsigned reason) -+{ -+ PRINTF2 (uctx, DBG_SWAP, "user_stop_nacking: status %x reason %x\n", uctx->uctx_status, reason); -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_spinlock)); -+ -+ uctx->uctx_status &= ~reason; -+ -+ if (! UCTX_NACKING (uctx)) -+ user_set_filter (uctx, E4_FILTER_STATS); -+} -+ -+static void -+user_start_stopping (USER_CTXT *uctx, unsigned reason) -+{ -+ ELAN4_DEV *dev =uctx->uctx_ctxt.ctxt_dev; -+ -+ PRINTF2 (uctx, DBG_SWAP, "user_start_stopping: status %x reason %x\n", uctx->uctx_status, reason); -+ -+ ASSERT (! (uctx->uctx_status & UCTX_STOPPED)); -+ -+ user_start_nacking (uctx, reason); -+ -+ if ((uctx->uctx_status & UCTX_STOPPING) != 0) -+ return; -+ -+ uctx->uctx_status |= UCTX_STOPPING; -+ -+ /* queue the halt operation to remove all threads/dmas/cqs from the run queues */ -+ /* and also flush through the context filter change */ -+ elan4_queue_haltop (dev, &uctx->uctx_haltop); -+} -+ -+static void -+user_stop_stopping (USER_CTXT *uctx, unsigned reason) -+{ -+ PRINTF2 (uctx, DBG_SWAP, "user_stop_stopping: status %x reason %x\n", uctx->uctx_status, reason); -+ -+ user_stop_nacking (uctx, reason); -+ -+ if (UCTX_RUNNABLE (uctx)) -+ { -+ uctx->uctx_status &= ~UCTX_STOPPED; -+ -+ PRINTF1 (uctx, DBG_SWAP, "user_stop_stopping: no more reasons => %x\n", uctx->uctx_status); -+ -+ user_signal_trap (uctx); -+ } -+} -+ -+void -+user_swapout (USER_CTXT *uctx, unsigned reason) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ PRINTF2 (uctx, DBG_SWAP, "user_swapout: status %x reason %x\n", uctx->uctx_status, reason); -+ -+ user_start_nacking (uctx, reason); -+ -+ while (uctx->uctx_status & (UCTX_SWAPPING|UCTX_STOPPING) && /* wait for someone else to finish */ -+ uctx->uctx_trap_count > 0) /* and for trap handlers to notice */ -+ { /* and exit */ -+ PRINTF1 (uctx, DBG_SWAP, "user_swapout: waiting for %d trap handlers to exit/previous swapout\n", uctx->uctx_trap_count); -+ -+ kcondvar_wakeupall (&uctx->uctx_wait, &uctx->uctx_spinlock); -+ kcondvar_wait (&uctx->uctx_wait, &uctx->uctx_spinlock, &flags); -+ } -+ -+ if (uctx->uctx_status & UCTX_SWAPPED) /* already swapped out */ -+ { -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return; -+ } -+ -+ uctx->uctx_status |= (UCTX_SWAPPING|UCTX_STOPPING); /* mark the context as swapping & stopping */ -+ -+ /* queue the halt operation to remove all threads/dmas/cqs from the run queues */ -+ /* and also flush through the context filter change */ -+ elan4_queue_haltop (dev, &uctx->uctx_haltop); -+ -+ while (! (uctx->uctx_status & UCTX_STOPPED)) -+ kcondvar_wait (&uctx->uctx_wait, &uctx->uctx_spinlock, &flags); -+ -+ /* all state has been removed from the elan - we can now "tidy" it up */ -+ -+ PRINTF0 (uctx, DBG_SWAP, "user_swapout: swapped out\n"); -+ -+ uctx->uctx_status = (uctx->uctx_status & ~UCTX_SWAPPING) | UCTX_SWAPPED; -+ -+ kcondvar_wakeupall (&uctx->uctx_wait, &uctx->uctx_spinlock); -+ -+ PRINTF1 (uctx, DBG_SWAP, "user_swapout: all done - status %x\n", uctx->uctx_status); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+void -+user_swapin (USER_CTXT *uctx, unsigned reason) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ ASSERT (uctx->uctx_status & UCTX_SWAPPED_REASONS); -+ -+ PRINTF2 (uctx, DBG_SWAP, "user_swapin: status %x reason %x\n", uctx->uctx_status, reason); -+ -+ while (uctx->uctx_status & (UCTX_SWAPPING|UCTX_STOPPING)) /* wait until other threads have */ -+ kcondvar_wait (&uctx->uctx_wait, &uctx->uctx_spinlock, &flags); /* completed their swap operation */ -+ -+ ASSERT (uctx->uctx_status & (UCTX_SWAPPED | UCTX_STOPPED)); -+ -+ user_stop_nacking (uctx, reason); -+ -+ if (! (uctx->uctx_status & UCTX_SWAPPED_REASONS)) -+ { -+ uctx->uctx_status &= ~UCTX_SWAPPED; -+ -+ /* no longer swapped out - wakeup anyone sleeping waiting for swapin */ -+ kcondvar_wakeupall (&uctx->uctx_wait, &uctx->uctx_spinlock); -+ -+ if (! (uctx->uctx_status & UCTX_STOPPED_REASONS)) -+ { -+ uctx->uctx_status &= ~UCTX_STOPPED; -+ user_signal_trap (uctx); -+ } -+ } -+ -+ PRINTF1 (uctx, DBG_SWAP, "user_swapin: all done - status %x\n", uctx->uctx_status); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+void -+user_destroy_callback (void *arg, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) arg; -+ -+ PRINTF (uctx, DBG_VP, "user_destroy_callback: %s\n", map == NULL ? "cap destoyed" : "map destroyed"); -+} -+ -+int -+user_attach (USER_CTXT *uctx, ELAN_CAPABILITY *cap) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ USER_CTXT_ENTRY *cent; -+ unsigned long flags; -+ int ctype, res; -+ -+ if ((ctype = user_validate_cap (uctx, cap, ELAN_USER_ATTACH)) < 0) -+ return ctype; -+ -+ if ((ctype == ELAN_CAP_RMS) && (res = elan_attach_cap (cap, dev->dev_devinfo.dev_rail, uctx, user_destroy_callback)) != 0) -+ { -+ /* NOTE: elan_attach_cap returns +ve errnos */ -+ return -res; -+ } -+ -+ KMEM_ALLOC (cent, USER_CTXT_ENTRY *, sizeof (USER_CTXT_ENTRY), 1); -+ if (cent == NULL) -+ { -+ if (ctype == ELAN_CAP_RMS) -+ elan_detach_cap (cap, dev->dev_devinfo.dev_rail); -+ -+ return -ENOMEM; -+ } -+ -+ KMEM_ALLOC (cent->cent_cap, ELAN_CAPABILITY *, ELAN_CAP_SIZE(cap), 1); -+ if (cent->cent_cap == NULL) -+ { -+ if (ctype == ELAN_CAP_RMS) -+ elan_detach_cap (cap, dev->dev_devinfo.dev_rail); -+ -+ KMEM_FREE (cent, sizeof (USER_CTXT_ENTRY)); -+ return -ENOMEM; -+ } -+ -+ bcopy (cap, cent->cent_cap, ELAN_CAP_SIZE(cap)); -+ -+ if ((res = elan4_attach_filter (&uctx->uctx_ctxt, cap->cap_mycontext)) != 0) -+ { -+ if (ctype == ELAN_CAP_RMS) -+ elan_detach_cap (cap, dev->dev_devinfo.dev_rail); -+ -+ KMEM_FREE (cent->cent_cap, ELAN_CAP_SIZE (cap)); -+ KMEM_FREE (cent, sizeof (USER_CTXT_ENTRY)); -+ -+ return res; -+ } -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ list_add_tail (¢->cent_link, &uctx->uctx_cent_list); -+ -+ if (! UCTX_NACKING (uctx)) -+ user_set_filter (uctx, E4_FILTER_STATS); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (0); -+ -+} -+ -+void -+user_detach (USER_CTXT *uctx, ELAN_CAPABILITY *cap) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ struct list_head *entry; -+ struct list_head *next; -+ struct list_head list; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&list); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ PRINTF (uctx, DBG_NETWORK_CTX, cap ? "user_detach: network context %d\n" : "user_detach: all network contexts\n", cap ? cap->cap_mycontext : 0); -+ -+ list_for_each_safe (entry, next, &uctx->uctx_cent_list) { -+ USER_CTXT_ENTRY *cent = list_entry (entry, USER_CTXT_ENTRY, cent_link); -+ -+ if (cap == NULL || ELAN_CAP_MATCH (cap, cent->cent_cap)) -+ { -+ PRINTF1 (uctx, DBG_NETWORK_CTX, "user_detach: detach from network context %d\n", cent->cent_cap->cap_mycontext); -+ -+ elan4_detach_filter (&uctx->uctx_ctxt, cent->cent_cap->cap_mycontext); -+ -+ list_del (¢->cent_link); -+ list_add_tail (¢->cent_link, &list); -+ } -+ } -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ while (! list_empty (&list)) -+ { -+ USER_CTXT_ENTRY *cent = list_entry (list.next, USER_CTXT_ENTRY, cent_link); -+ -+ list_del (¢->cent_link); -+ -+ if (user_validate_cap (uctx, cent->cent_cap, ELAN_USER_DETACH) == ELAN_CAP_RMS) -+ elan_detach_cap (cent->cent_cap, dev->dev_devinfo.dev_rail); -+ -+ KMEM_FREE (cent->cent_cap, ELAN_CAP_SIZE (cent->cent_cap)); -+ KMEM_FREE (cent, sizeof (USER_CTXT_ENTRY)); -+ } -+} -+ -+void -+user_block_inputter (USER_CTXT *uctx, unsigned blocked) -+{ -+ unsigned long flags; -+ int isblocked; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ isblocked = (uctx->uctx_status & UCTX_USER_FILTERING); -+ -+ if (blocked && !isblocked) -+ user_start_nacking (uctx, UCTX_USER_FILTERING); -+ -+ if (!blocked && isblocked) -+ user_stop_nacking (uctx, UCTX_USER_FILTERING); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static USER_VPSEG * -+user_install_vpseg (USER_CTXT *uctx, unsigned process, unsigned entries) -+{ -+ struct list_head *entry; -+ USER_VPSEG *seg; -+ -+ ASSERT (kmutex_is_locked (&uctx->uctx_vpseg_lock)); -+ -+ list_for_each (entry, &uctx->uctx_vpseg_list) { -+ seg = list_entry (entry, USER_VPSEG, vps_link); -+ -+ if (process <= (seg->vps_process + seg->vps_entries-1) && -+ (process + entries - 1) >= seg->vps_process) -+ return ((USER_VPSEG *) NULL); -+ } -+ -+ KMEM_ZALLOC (seg, USER_VPSEG *, sizeof (USER_VPSEG), 1); -+ -+ if (seg == (USER_VPSEG *) NULL) -+ return ((USER_VPSEG *) NULL); -+ -+ seg->vps_process = process; -+ seg->vps_entries = entries; -+ -+ list_add_tail (&seg->vps_link, &uctx->uctx_vpseg_list); -+ -+ return (seg); -+} -+ -+static void -+user_remove_vpseg (USER_CTXT *uctx, USER_VPSEG *seg) -+{ -+ ASSERT (kmutex_is_locked (&uctx->uctx_vpseg_lock)); -+ -+ list_del (&seg->vps_link); -+ -+ switch (seg->vps_type) -+ { -+ case USER_VPSEG_P2P: -+ /* These pointers (union) are only valid for P2P segs */ -+ if (seg->vps_p2p_routes) -+ KMEM_FREE (seg->vps_p2p_routes, sizeof (E4_VirtualProcessEntry) * seg->vps_entries); -+ -+ if (seg->vps_p2p_cap) -+ KMEM_FREE (seg->vps_p2p_cap, ELAN_CAP_SIZE(seg->vps_p2p_cap)); -+ -+ break; -+ -+ case USER_VPSEG_BCAST: -+ ; -+ } -+ -+ KMEM_FREE (seg, sizeof (USER_VPSEG)); -+} -+ -+static USER_VPSEG * -+user_find_vpseg (USER_CTXT *uctx, unsigned low, unsigned high) -+{ -+ struct list_head *entry; -+ -+ ASSERT (kmutex_is_locked (&uctx->uctx_vpseg_lock)); -+ -+ list_for_each (entry, &uctx->uctx_vpseg_list) { -+ USER_VPSEG *seg = list_entry (entry, USER_VPSEG, vps_link); -+ -+ if (seg->vps_process <= low && (seg->vps_process + seg->vps_entries) > high) -+ return (seg); -+ } -+ -+ return ((USER_VPSEG *) NULL); -+} -+ -+static ELAN_LOCATION -+user_process2location (USER_CTXT *uctx, USER_VPSEG *seg, unsigned process) -+{ -+ ELAN_LOCATION location; -+ int nnodes, nctxs; -+ int nodeOff, ctxOff, vpOff; -+ -+ location.loc_node = ELAN_INVALID_NODE; -+ location.loc_context = -1; -+ -+ if (seg == NULL) -+ seg = user_find_vpseg (uctx, process, process); -+ -+ if (seg == NULL || (seg->vps_type != USER_VPSEG_P2P)) -+ return (location); -+ -+ nnodes = ELAN_CAP_NUM_NODES (seg->vps_p2p_cap); -+ nctxs = ELAN_CAP_NUM_CONTEXTS (seg->vps_p2p_cap); -+ -+ switch (seg->vps_p2p_cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ for (nodeOff = 0, vpOff = 0; nodeOff < nnodes; nodeOff++) -+ { -+ for (ctxOff = 0; ctxOff < nctxs; ctxOff++) -+ { -+ if ((seg->vps_p2p_cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (seg->vps_p2p_cap->cap_bitmap, ctxOff + (nodeOff * nctxs))) -+ { -+ if (vpOff++ == (process - seg->vps_process)) -+ { -+ location.loc_node = seg->vps_p2p_cap->cap_lownode + nodeOff; -+ location.loc_context = seg->vps_p2p_cap->cap_lowcontext + ctxOff; -+ goto found; -+ } -+ } -+ } -+ } -+ break; -+ -+ case ELAN_CAP_TYPE_CYCLIC: -+ for (ctxOff = 0, vpOff = 0; ctxOff < nctxs; ctxOff++) -+ { -+ for (nodeOff = 0; nodeOff < nnodes; nodeOff++) -+ { -+ if ((seg->vps_p2p_cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (seg->vps_p2p_cap->cap_bitmap, nodeOff + (ctxOff * nnodes))) -+ { -+ if (vpOff++ == (process - seg->vps_process)) -+ { -+ location.loc_node = seg->vps_p2p_cap->cap_lownode + nodeOff; -+ location.loc_context = seg->vps_p2p_cap->cap_lowcontext + ctxOff; -+ goto found; -+ } -+ } -+ } -+ } -+ break; -+ } -+ -+ found: -+ return (location); -+} -+ -+static unsigned -+user_location2process (USER_CTXT *uctx, ELAN_LOCATION location) -+{ -+ unsigned int process = ELAN_INVALID_PROCESS; -+ struct list_head *entry; -+ int nnodes, nctxs; -+ int nodeOff, ctxOff, vpOff; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ list_for_each (entry, &uctx->uctx_vpseg_list) { -+ USER_VPSEG *seg = list_entry (entry, USER_VPSEG, vps_link); -+ -+ if (seg->vps_type != USER_VPSEG_P2P) -+ continue; -+ -+ if (location.loc_node >= seg->vps_p2p_cap->cap_lownode && location.loc_node <= seg->vps_p2p_cap->cap_highnode && -+ location.loc_context >= seg->vps_p2p_cap->cap_lowcontext && location.loc_context <= seg->vps_p2p_cap->cap_highcontext) -+ { -+ nnodes = ELAN_CAP_NUM_NODES (seg->vps_p2p_cap); -+ nctxs = ELAN_CAP_NUM_CONTEXTS (seg->vps_p2p_cap); -+ -+ switch (seg->vps_p2p_cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ for (nodeOff = 0, vpOff = 0; nodeOff < nnodes; nodeOff++) -+ { -+ for (ctxOff = 0; ctxOff < nctxs; ctxOff++) -+ { -+ if ((seg->vps_p2p_cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (seg->vps_p2p_cap->cap_bitmap, ctxOff + (nodeOff * nctxs))) -+ { -+ if (location.loc_node == seg->vps_p2p_cap->cap_lownode + nodeOff && -+ location.loc_context == seg->vps_p2p_cap->cap_lowcontext + ctxOff) -+ { -+ process = seg->vps_process + vpOff; -+ goto found; -+ } -+ vpOff++; -+ } -+ } -+ } -+ break; -+ -+ case ELAN_CAP_TYPE_CYCLIC: -+ for (ctxOff = 0, vpOff = 0; ctxOff < nctxs; ctxOff++) -+ { -+ for (nodeOff = 0; nodeOff < nnodes; nodeOff++) -+ { -+ if ((seg->vps_p2p_cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (seg->vps_p2p_cap->cap_bitmap, nodeOff + (ctxOff * nnodes))) -+ { -+ if (location.loc_node == seg->vps_p2p_cap->cap_lownode + nodeOff && -+ location.loc_context == seg->vps_p2p_cap->cap_lowcontext + ctxOff) -+ { -+ process = seg->vps_process + vpOff; -+ goto found; -+ } -+ vpOff++; -+ } -+ } -+ } -+ break; -+ } -+ } -+ } -+ found: -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return (process); -+} -+ -+static void -+user_loadroute_vpseg (USER_CTXT *uctx, USER_VPSEG *seg, ELAN_POSITION *pos) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ ELAN_CAPABILITY *cap = seg->vps_p2p_cap; -+ unsigned nnodes = ELAN_CAP_NUM_NODES (cap); -+ unsigned nctxs = ELAN_CAP_NUM_CONTEXTS (cap); -+ E4_VirtualProcessEntry route; -+ unsigned nodeOff; -+ unsigned ctxOff; -+ unsigned vpOff; -+ -+ switch (cap->cap_type & ELAN_CAP_TYPE_MASK) -+ { -+ case ELAN_CAP_TYPE_BLOCK: -+ for (nodeOff = 0, vpOff = 0; nodeOff < nnodes; nodeOff++) -+ { -+ for (ctxOff = 0; ctxOff < nctxs; ctxOff++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, ctxOff + (nodeOff * nctxs))) -+ { -+ if (seg->vps_p2p_routes != NULL) -+ route = seg->vps_p2p_routes[vpOff]; -+ else if (elan4_generate_route (&uctx->uctx_position, &route, cap->cap_lowcontext + ctxOff, -+ cap->cap_lownode + nodeOff, cap->cap_lownode + nodeOff, user_p2p_route_options) < 0) -+ { -+ vpOff++; -+ continue; -+ } -+ -+ PRINTF5 (uctx, DBG_VP, "user_loadroute_vpseg: virtual process %d -> node %d context %d [%016llx.%016llx]\n", -+ seg->vps_process + vpOff, cap->cap_lownode + nodeOff, cap->cap_lowcontext + ctxOff, -+ route.Values[0], route.Values[1]); -+ -+ elan4_write_route (dev, uctx->uctx_routetable, seg->vps_process + vpOff, &route); -+ -+ vpOff++; -+ } -+ } -+ } -+ break; -+ -+ case ELAN_CAP_TYPE_CYCLIC: -+ for (ctxOff = 0, vpOff = 0; ctxOff < nctxs; ctxOff++) -+ { -+ for (nodeOff = 0; nodeOff < nnodes; nodeOff++) -+ { -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) || BT_TEST (cap->cap_bitmap, nodeOff + (ctxOff * nnodes))) -+ { -+ if (seg->vps_p2p_routes != NULL) -+ route = seg->vps_p2p_routes[vpOff]; -+ else if (elan4_generate_route (&uctx->uctx_position, &route, cap->cap_lowcontext + ctxOff, -+ cap->cap_lownode + nodeOff, cap->cap_lownode + nodeOff, user_p2p_route_options) < 0) -+ { -+ vpOff++; -+ continue; -+ } -+ -+ PRINTF5 (uctx, DBG_VP, "user_loadroute_vpseg: virtual process %d -> node %d context %d [%016llx.%016llx]\n", -+ seg->vps_process + vpOff, cap->cap_lownode + nodeOff, cap->cap_lowcontext + ctxOff, -+ route.Values[0], route.Values[1]); -+ -+ elan4_write_route (dev, uctx->uctx_routetable, seg->vps_process + vpOff, &route); -+ -+ vpOff++; -+ } -+ } -+ } -+ break; -+ } -+} -+ -+static int -+user_loadroute_bcast (USER_CTXT *uctx, USER_VPSEG *seg) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ ELAN_POSITION *pos = &uctx->uctx_position; -+ E4_VirtualProcessEntry route; -+ USER_VPSEG *aseg; -+ int res; -+ ELAN_LOCATION low; -+ ELAN_LOCATION high; -+ -+ if ((aseg = user_find_vpseg (uctx, seg->vps_bcast_lowvp, seg->vps_bcast_highvp)) == NULL || aseg->vps_type != USER_VPSEG_P2P) -+ return (-EINVAL); -+ -+#ifdef use_elanmod -+ if ((res = user_validate_cap (dev, aseg->vps_p2p_cap, ELAN_USER_BROADCAST)) < 0) -+ return (res); -+#endif -+ -+ low = user_process2location (uctx, aseg, seg->vps_bcast_lowvp); -+ high = user_process2location (uctx, aseg, seg->vps_bcast_highvp); -+ -+ if (low.loc_context != high.loc_context) -+ return (-EINVAL); -+ -+ /* NOTE: if loopback can only broadcast to ourself - -+ * if back-to-back can only broadcast to other node */ -+ if ((pos->pos_mode == ELAN_POS_MODE_LOOPBACK && low.loc_node != high.loc_node && low.loc_node != pos->pos_nodeid) || -+ (pos->pos_mode == ELAN_POS_MODE_BACKTOBACK && low.loc_node != high.loc_node && low.loc_node == pos->pos_nodeid)) -+ { -+ return (-EINVAL); -+ } -+ -+ if ((res = elan4_generate_route (pos, &route, low.loc_context, low.loc_node, high.loc_node, user_bcast_route_options)) < 0) -+ return (res); -+ -+ PRINTF (uctx, DBG_VP, "user_loadroute_bcast: virtual process %d -> nodes %d.%d context %d [%016llx.%016llx]\n", -+ seg->vps_process, low.loc_node, high.loc_node, low.loc_context, route.Values[0], route.Values[1]); -+ -+ elan4_write_route (dev, uctx->uctx_routetable, seg->vps_process, &route); -+ return (0); -+} -+ -+int -+user_add_p2pvp (USER_CTXT *uctx, unsigned process, ELAN_CAPABILITY *cap) -+{ -+ USER_VPSEG *seg; -+ ELAN_CAPABILITY *ncap; -+ unsigned entries; -+ -+ if ((cap->cap_type & ELAN_CAP_TYPE_NO_BITMAP) == 0) -+ entries = bt_nbits (cap->cap_bitmap , ELAN_CAP_BITMAPSIZE(cap)); -+ else -+ entries = ELAN_CAP_BITMAPSIZE(cap); -+ -+ if ((process + entries) > (E4_VPT_MIN_ENTRIES << uctx->uctx_routetable->tbl_size)) -+ return (-EINVAL); -+ -+ KMEM_ALLOC (ncap, ELAN_CAPABILITY *, ELAN_CAP_SIZE (cap), 1); -+ -+ if (ncap == NULL) -+ return (-ENOMEM); -+ -+ bcopy (cap, ncap, ELAN_CAP_SIZE (cap)); -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_install_vpseg (uctx, process, entries)) == NULL) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ seg->vps_type = USER_VPSEG_P2P; -+ seg->vps_p2p_cap = ncap; -+ seg->vps_p2p_routes = NULL; -+ -+ user_loadroute_vpseg (uctx, seg, &uctx->uctx_position); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return (0); -+} -+ -+int -+user_add_bcastvp (USER_CTXT *uctx, unsigned process, unsigned lowvp, unsigned highvp) -+{ -+ USER_VPSEG *seg; -+ int res; -+ -+ if (lowvp > highvp || process >= (E4_VPT_MIN_ENTRIES << uctx->uctx_routetable->tbl_size)) -+ return (-EINVAL); -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_install_vpseg (uctx, process, 1)) == NULL) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ seg->vps_type = USER_VPSEG_BCAST; -+ seg->vps_bcast_lowvp = lowvp; -+ seg->vps_bcast_highvp = highvp; -+ -+ if ((res = user_loadroute_bcast (uctx, seg)) < 0) -+ user_remove_vpseg (uctx, seg); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (res); -+} -+ -+int -+user_removevp (USER_CTXT *uctx, unsigned process) -+{ -+ USER_VPSEG *seg; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if (process == ELAN_INVALID_PROCESS) -+ seg = list_entry (uctx->uctx_vpseg_list.next, USER_VPSEG, vps_link); -+ else -+ seg = user_find_vpseg (uctx, process, process); -+ -+ if (seg == NULL) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ do { -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ int i; -+ -+ for (i = 0; i < seg->vps_entries; i++) -+ elan4_invalidate_route (dev, uctx->uctx_routetable, seg->vps_process + i); -+ -+ user_remove_vpseg (uctx, seg); -+ -+ } while (process == ELAN_INVALID_PROCESS && (seg = list_entry (uctx->uctx_vpseg_list.next, USER_VPSEG, vps_link)) != NULL); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return (0); -+} -+ -+int -+user_set_route (USER_CTXT *uctx, unsigned process, E4_VirtualProcessEntry *route) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ USER_VPSEG *seg; -+ ELAN_LOCATION location; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_find_vpseg (uctx, process, process)) == NULL || seg->vps_type != USER_VPSEG_P2P) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ /* check that the route supplied is valid and goes to the correct place */ -+ location = user_process2location (uctx, seg, process); -+ -+ if (elan4_check_route (&uctx->uctx_position, location, route, 0) != 0) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ if (seg->vps_p2p_routes == NULL) -+ KMEM_ZALLOC (seg->vps_p2p_routes, E4_VirtualProcessEntry *, sizeof (E4_VirtualProcessEntry) * seg->vps_entries, 1); -+ -+ if (seg->vps_p2p_routes == NULL) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-ENOMEM); -+ } -+ -+ seg->vps_p2p_routes[process - seg->vps_process].Values[0] = route->Values[0]; -+ seg->vps_p2p_routes[process - seg->vps_process].Values[1] = ROUTE_CTXT_VALUE(location.loc_context) | (route->Values[1] & ~ROUTE_CTXT_MASK); -+ -+ PRINTF (uctx, DBG_ROUTE, "user_set_route: vp=%d -> %016llx%016llx\n", process, -+ seg->vps_p2p_routes[process - seg->vps_process].Values[1], seg->vps_p2p_routes[process - seg->vps_process].Values[0]); -+ -+ elan4_write_route (dev, uctx->uctx_routetable, process, &seg->vps_p2p_routes[process - seg->vps_process]); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return (0); -+} -+ -+int -+user_reset_route (USER_CTXT *uctx, unsigned process) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ E4_VirtualProcessEntry route; -+ ELAN_LOCATION location; -+ USER_VPSEG *seg; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_find_vpseg (uctx, process, process)) == NULL || seg->vps_type != USER_VPSEG_P2P) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ if (seg->vps_p2p_routes != NULL) -+ { -+ seg->vps_p2p_routes[process - seg->vps_process].Values[0] = 0; -+ seg->vps_p2p_routes[process - seg->vps_process].Values[1] = 0; -+ } -+ -+ /* generate the default route to this location */ -+ location = user_process2location (uctx, seg, process); -+ -+ PRINTF (uctx, DBG_ROUTE, "user_reset_route: vp=%d\n", process); -+ -+ if (elan4_generate_route (&uctx->uctx_position, &route, location.loc_context, location.loc_node, location.loc_node, 0) < 0) -+ elan4_invalidate_route (dev, uctx->uctx_routetable, process); -+ else -+ elan4_write_route (dev, uctx->uctx_routetable, process, &route); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return (0); -+} -+ -+int -+user_get_route (USER_CTXT *uctx, unsigned process, E4_VirtualProcessEntry *route) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ USER_VPSEG *seg; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_find_vpseg (uctx, process, process)) == NULL || seg->vps_type != USER_VPSEG_P2P) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ elan4_read_route (dev, uctx->uctx_routetable, process, route); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (0); -+} -+ -+int -+user_check_route (USER_CTXT *uctx, unsigned process, E4_VirtualProcessEntry *route, unsigned *error) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ USER_VPSEG *seg; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_find_vpseg (uctx, process, process)) == NULL || seg->vps_type != USER_VPSEG_P2P) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ elan4_read_route (dev, uctx->uctx_routetable, process, route); -+ -+ *error = elan4_check_route (&uctx->uctx_position, user_process2location (uctx, seg, process), route, 0); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (0); -+} -+ -+int -+user_send_neterr_msg (USER_CTXT *uctx, unsigned int vp, unsigned int nctx, unsigned int retries, ELAN4_NETERR_MSG *msg) -+{ -+ USER_VPSEG *seg; -+ ELAN_LOCATION location; -+ unsigned long flags; -+ int res, found = 0; -+ struct list_head *el; -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ /* determine the location of the virtual process */ -+ if ((seg = user_find_vpseg (uctx, vp, vp)) == NULL) -+ { -+ PRINTF (uctx, DBG_NETERR, "user_send_neterr_msg: vp=%d has no vpseg\n", vp); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return -EINVAL; -+ } -+ -+ switch (seg->vps_type) -+ { -+ case USER_VPSEG_P2P: -+ location = user_process2location (uctx, seg, vp); -+ break; -+ -+ case USER_VPSEG_BCAST: -+ PRINTF (uctx, DBG_NETERR, "user_send_neterr_msg: vp=%d is a bcast vp\n", vp); -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return -EINVAL; -+ } -+ -+ /* check that we're attached to the network context */ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ list_for_each (el , &uctx->uctx_cent_list) { -+ USER_CTXT_ENTRY *cent = list_entry (el, USER_CTXT_ENTRY, cent_link); -+ -+ if (cent->cent_cap->cap_mycontext == nctx) -+ found++; -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ if (! found) -+ { -+ PRINTF (uctx, DBG_NETERR, "user_send_neterr_msg: nctx=%d not attached\n", nctx); -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return -EINVAL; -+ } -+ -+ /* Update the fields which the user might have "faked" */ -+ msg->msg_context = location.loc_context; -+ msg->msg_sender.loc_node = uctx->uctx_position.pos_nodeid; -+ msg->msg_sender.loc_context = nctx; -+ -+ res = elan4_neterr_sendmsg (uctx->uctx_ctxt.ctxt_dev, location.loc_node, retries, msg); -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ return (res); -+} -+ -+ -+static int -+user_resolvevp (USER_CTXT *uctx, unsigned process) -+{ -+ int res = 0; -+ USER_VPSEG *seg; -+ ELAN_LOCATION location; -+ E4_VirtualProcessEntry route; -+ -+ PRINTF1 (uctx, DBG_VP, "user_resolvevp: process=%d\n", process); -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ -+ if ((seg = user_find_vpseg (uctx, process, process)) == NULL) -+ { -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (-EINVAL); -+ } -+ -+ switch (seg->vps_type) -+ { -+ case USER_VPSEG_P2P: -+#ifdef use_elanmod -+ if ((res = user_validate_cap (uctx, seg->vps_p2p_cap, ELAN_USER_P2P)) != 0) -+ break; -+#endif -+ -+ location = user_process2location (uctx, seg, process); -+ -+ PRINTF (uctx, DBG_VP, "user_resolvevp: vp=%d -> node=%d ctx=%d\n", process, location.loc_node, location.loc_context); -+ -+ if (seg->vps_p2p_routes != NULL && seg->vps_p2p_routes[process - seg->vps_process].Values[0] != 0) -+ route = seg->vps_p2p_routes[process - seg->vps_process]; -+ else if ((res = elan4_generate_route (&uctx->uctx_position, &route, location.loc_context, location.loc_node, location.loc_node, user_p2p_route_options)) < 0) -+ break;; -+ -+ elan4_write_route (uctx->uctx_ctxt.ctxt_dev, uctx->uctx_routetable, process, &route); -+ break; -+ -+ case USER_VPSEG_BCAST: -+ res = user_loadroute_bcast (uctx, seg); -+ break; -+ -+ default: -+ res = -EINVAL; -+ break; -+ } -+ -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ return (res); -+} -+ -+static void -+user_eproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (RING_QUEUE_REALLY_FULL (uctx->uctx_eprocTrapQ) || (uctx->uctx_status & UCTX_STOPPED)) -+ { -+ PRINTF (uctx, DBG_EPROC, "user_eproc_trap: %s\n", (uctx->uctx_status & UCTX_STOPPED) ? "context stopped" : "trap queue overflow"); -+ -+ uctx->uctx_status |= UCTX_EPROC_QUEUE_ERROR; -+ } -+ else -+ { -+ elan4_extract_eproc_trap (ctxt->ctxt_dev, status, RING_QUEUE_BACK (uctx->uctx_eprocTrapQ, uctx->uctx_eprocTraps), 0); -+ -+ DBGCMD (ctxt, DBG_EPROC, elan4_display_eproc_trap (ctxt, DBG_EPROC, "user_eproc_trap", RING_QUEUE_BACK(uctx->uctx_eprocTrapQ, uctx->uctx_eprocTraps))); -+ -+ if (RING_QUEUE_ADD (uctx->uctx_eprocTrapQ)) -+ user_start_stopping (uctx, UCTX_EPROC_QUEUE_FULL); -+ } -+ -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_cproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned cqnum) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ USER_CQ *ucq = NULL; -+ struct list_head *entry; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ list_for_each (entry, &uctx->uctx_cqlist) { -+ ucq = list_entry (entry, USER_CQ, ucq_link); -+ -+ if (elan4_cq2num(ucq->ucq_cq) == cqnum) -+ break; -+ } -+ -+ ASSERT (ucq != NULL); -+ -+ if (ucq->ucq_state != UCQ_RUNNING && CPROC_TrapType (status) == CommandProcInserterError) -+ { -+ PRINTF (ctxt, DBG_TRAP, "user_cproc_trap CommandProcInserterError\n"); -+ ucq->ucq_errored++; -+ } -+ else -+ { -+ int vp; -+ -+ ASSERT (ucq->ucq_state == UCQ_RUNNING); -+ -+ elan4_extract_cproc_trap (ctxt->ctxt_dev, status, &ucq->ucq_trap, cqnum); -+ -+ DBGCMD (ctxt, DBG_CPROC, elan4_display_cproc_trap (ctxt, DBG_CPROC, "user_cproc_trap", &ucq->ucq_trap)); -+ -+ ucq->ucq_state = UCQ_TRAPPED; -+ -+ if ((vp = cproc_open_extract_vp(uctx->uctx_ctxt.ctxt_dev, ucq->ucq_cq)) != -1) -+ { -+ E4_VirtualProcessEntry route; -+ -+ elan4_read_route(uctx->uctx_ctxt.ctxt_dev, uctx->uctx_routetable, vp, &route); -+ elan4_ringbuf_store(&uctx->uctx_ctxt.ctxt_dev->dev_cproc_timeout_routes, &route, uctx->uctx_ctxt.ctxt_dev); -+ } -+ } -+ -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_dproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (RING_QUEUE_REALLY_FULL (uctx->uctx_dprocTrapQ) || (uctx->uctx_status & UCTX_STOPPED)) -+ { -+ PRINTF (uctx, DBG_DPROC, "user_dproc_trap: %s\n", (uctx->uctx_status & UCTX_STOPPED) ? "context stopped" : "trap queue overflow"); -+ -+ uctx->uctx_status |= UCTX_DPROC_QUEUE_ERROR; -+ } -+ else -+ { -+ ELAN4_DPROC_TRAP *trap = RING_QUEUE_BACK (uctx->uctx_dprocTrapQ, uctx->uctx_dprocTraps); -+ -+ elan4_extract_dproc_trap (ctxt->ctxt_dev, status, trap, unit); -+ -+ if ((DPROC_PacketTimeout (trap->tr_status)) || (DPROC_TrapType (trap->tr_status) == DmaProcFailCountError)) -+ { -+ E4_VirtualProcessEntry route; -+ -+ elan4_read_route(ctxt->ctxt_dev, uctx->uctx_routetable, trap->tr_desc.dma_vproc, &route); -+ -+ if ((route.Values[0] != 0) || (route.Values[1] != 0)) -+ { -+ elan4_ringbuf_store(&uctx->uctx_ctxt.ctxt_dev->dev_dproc_timeout_routes, &route, uctx->uctx_ctxt.ctxt_dev); -+ } -+ } -+ else if (DPROC_TrapType (trap->tr_status) == DmaProcPacketAckError) -+ { -+ E4_VirtualProcessEntry route; -+ -+ elan4_read_route(ctxt->ctxt_dev, uctx->uctx_routetable, trap->tr_desc.dma_vproc, &route); -+ -+ if ((route.Values[0] != 0) || (route.Values[1] != 0)) -+ { -+ elan4_ringbuf_store(&uctx->uctx_ctxt.ctxt_dev->dev_ack_error_routes, &route, uctx->uctx_ctxt.ctxt_dev); -+ } -+ } -+ else -+ -+ DBGCMD (ctxt, DBG_DPROC, elan4_display_dproc_trap (ctxt, DBG_DPROC, "user_dproc_trap", trap)); -+ -+ if (!DPROC_PrefetcherFault (status) && DPROC_TrapType(status) == DmaProcFailCountError && !RING_QUEUE_FULL (uctx->uctx_dmaQ)) -+ { -+ trap->tr_desc.dma_typeSize |= DMA_FailCount (user_dproc_retry_count); -+ -+ *RING_QUEUE_BACK (uctx->uctx_dmaQ, uctx->uctx_dmas) = trap->tr_desc; -+ -+ (void) RING_QUEUE_ADD (uctx->uctx_dmaQ); -+ } -+ else -+ { -+ if (RING_QUEUE_ADD (uctx->uctx_dprocTrapQ)) -+ user_start_stopping (uctx, UCTX_DPROC_QUEUE_FULL); -+ } -+ } -+ -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_tproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (RING_QUEUE_REALLY_FULL (uctx->uctx_tprocTrapQ) || (uctx->uctx_status & UCTX_STOPPED)) -+ { -+ PRINTF (uctx, DBG_TPROC, "user_tproc_trap: %s\n", (uctx->uctx_status & UCTX_STOPPED) ? "context stopped" : "trap queue overflow"); -+ -+ uctx->uctx_status |= UCTX_TPROC_QUEUE_ERROR; -+ } -+ else -+ { -+ elan4_extract_tproc_trap (ctxt->ctxt_dev, status, RING_QUEUE_BACK (uctx->uctx_tprocTrapQ, uctx->uctx_tprocTraps)); -+ -+ DBGCMD (ctxt, DBG_TPROC, elan4_display_tproc_trap (ctxt, DBG_TPROC, "user_tproc_trap", RING_QUEUE_BACK (uctx->uctx_tprocTrapQ, uctx->uctx_tprocTraps))); -+ -+ if (RING_QUEUE_ADD (uctx->uctx_tprocTrapQ)) -+ user_start_stopping (uctx, UCTX_TPROC_QUEUE_FULL); -+ } -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_iproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ USER_IPROC_TRAP *utrap = &uctx->uctx_iprocTrap[unit & 1]; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ ASSERT (utrap->ut_state == UTS_IPROC_RUNNING); -+ -+ elan4_extract_iproc_trap (ctxt->ctxt_dev, status, &utrap->ut_trap, unit); -+ DBGCMD (ctxt, DBG_IPROC, elan4_display_iproc_trap (ctxt, DBG_IPROC, "user_iproc_trap", &utrap->ut_trap)); -+ -+ utrap->ut_state = UTS_IPROC_TRAPPED; -+ -+ user_start_nacking (uctx, unit ? UCTX_IPROC_CH0_TRAPPED : UCTX_IPROC_CH1_TRAPPED); -+ -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_interrupt (ELAN4_CTXT *ctxt, E4_uint64 cookie) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ PRINTF1 (uctx, DBG_TRAP, "user_interrupt: cookie=%llx\n", cookie); -+ -+ switch (cookie) -+ { -+ case ELAN4_INT_COOKIE_DDCQ: -+ uctx->uctx_ddcq_intr--; -+ -+ user_signal_trap (uctx); -+ break; -+ -+ default: -+ if (uctx->uctx_intcookie_table == NULL || intcookie_fire (uctx->uctx_intcookie_table, cookie) != 0) -+ { -+ PRINTF2 (uctx, DBG_TRAP, "user_interrupt: cookie=%llx %s\n", cookie, uctx->uctx_intcookie_table ? "not found" : "no table"); -+ uctx->uctx_status |= UCTX_EPROC_QUEUE_ERROR; -+ user_signal_trap (uctx); -+ } -+ break; -+ } -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+static void -+user_neterrmsg (ELAN4_CTXT *ctxt, ELAN4_NETERR_MSG *msg) -+{ -+ USER_CTXT *uctx = (USER_CTXT *) ctxt; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (! RING_QUEUE_FULL (uctx->uctx_msgQ)) -+ { -+ memcpy (RING_QUEUE_BACK (uctx->uctx_msgQ, uctx->uctx_msgs), msg, sizeof (ELAN4_NETERR_MSG)); -+ -+ (void) RING_QUEUE_ADD (uctx->uctx_msgQ); -+ -+ user_signal_trap (uctx); -+ } -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+} -+ -+ELAN4_TRAP_OPS user_trap_ops = -+{ -+ user_eproc_trap, -+ user_cproc_trap, -+ user_dproc_trap, -+ user_tproc_trap, -+ user_iproc_trap, -+ user_interrupt, -+ user_neterrmsg, -+}; -+ -+static int -+deliver_trap (ELAN4_USER_TRAP *utrapp, int type, unsigned proc, void *trap, ...) -+{ -+ register int i, len; -+ va_list ap; -+ -+ PRINTF (NULL, DBG_TRAP, "deliver_trap: type=%d proc=%d\n", type, proc); -+ -+ switch (proc) -+ { -+ case UTS_CPROC: len = sizeof (ELAN4_CPROC_TRAP); break; -+ case UTS_DPROC: len = sizeof (ELAN4_DPROC_TRAP); break; -+ case UTS_EPROC: len = sizeof (ELAN4_EPROC_TRAP); break; -+ case UTS_IPROC: len = sizeof (ELAN4_IPROC_TRAP); break; -+ case UTS_TPROC: len = sizeof (ELAN4_TPROC_TRAP); break; -+ case UTS_NETERR_MSG: len = sizeof (ELAN4_NETERR_MSG); break; -+ default: len = 0; break; -+ } -+ -+ if (put_user (type, &utrapp->ut_type) || put_user (proc, &utrapp->ut_proc) || copy_to_user (&utrapp->ut_trap, trap, len)) -+ return (UTS_EFAULT); -+ -+ va_start (ap, trap); -+ for (i = 0; i < sizeof (utrapp->ut_args)/sizeof (utrapp->ut_args[0]); i++) -+ if (put_user (va_arg (ap, unsigned long), &utrapp->ut_args[i])) -+ return (UTS_EFAULT); -+ va_end (ap); -+ -+ return (type); -+} -+ -+static int -+user_pagefault (USER_CTXT *uctx, E4_FaultSave *farea) -+{ -+ E4_Addr addr = farea->FaultAddress; -+ E4_uint32 fsr = FaultSaveFSR(farea->FSRAndFaultContext); -+ FAULT_SAVE *entry; -+ FAULT_SAVE **predp; -+ int count; -+ -+ PRINTF2 (uctx, DBG_FAULT, "user_pagefault: addr=%llx fsr %x\n", (unsigned long long) addr, fsr); -+ -+ if ((fsr & FSR_FaultForBadData) != 0) /* Memory ECC error during walk */ -+ { -+ PRINTF0 (uctx, DBG_FAULT, "user_pagefault: ECC error during walk\n"); -+ return (-EFAULT); -+ } -+ -+ if ((fsr & FSR_FaultForMaxChainCount) != 0) /* Have walked a chain of 1024 items */ -+ { -+ PRINTF0 (uctx, DBG_FAULT, "user_pagefault: pte chain too long\n"); -+ return (-EFAULT); -+ } -+ -+ if (uctx->uctx_num_fault_save) -+ { -+ spin_lock (&uctx->uctx_fault_lock); -+ for( predp = &uctx->uctx_fault_list; (entry = *predp)->next != NULL; predp = &entry->next) -+ { -+ if (entry->addr == (addr & ~((E4_Addr) PAGE_SIZE-1))) -+ break; -+ } -+ -+ *predp = entry->next; -+ entry->next = uctx->uctx_fault_list; -+ uctx->uctx_fault_list = entry; -+ -+ if (entry->addr == (addr & ~((E4_Addr) PAGE_SIZE-1))) -+ { -+ if ((entry->count <<= 1) > max_fault_pages) -+ entry->count = max_fault_pages; -+ } -+ else -+ entry->count = min_fault_pages; -+ -+ entry->addr = (addr & ~((E4_Addr) PAGE_SIZE-1))+(entry->count * PAGE_SIZE); -+ count = entry->count; -+ spin_unlock (&uctx->uctx_fault_lock); -+ -+ if (user_load_range (uctx, addr & ~((E4_Addr) PAGE_SIZE-1), count * PAGESIZE, fsr) == 0) -+ return 0; -+ -+ /* else pre-faulting has failed, try just this page */ -+ } -+ -+ return (user_load_range (uctx, addr & ~((E4_Addr) PAGE_SIZE-1), PAGE_SIZE, fsr)); -+ -+} -+ -+static int -+queue_dma_for_retry (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, E4_DMA *dma) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (RING_QUEUE_FULL (uctx->uctx_dmaQ)) -+ { -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (deliver_trap (utrapp, UTS_QUEUE_OVERFLOW, UTS_NOPROC, NULL, UCTX_DPROC_QUEUE_OVERFLOW)); -+ } -+ -+ *RING_QUEUE_BACK (uctx->uctx_dmaQ, uctx->uctx_dmas) = *dma; -+ -+ (void) RING_QUEUE_ADD (uctx->uctx_dmaQ); -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+queue_thread_for_retry (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, E4_ThreadRegs *regs) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (RING_QUEUE_FULL (uctx->uctx_threadQ)) -+ { -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (deliver_trap (utrapp, UTS_QUEUE_OVERFLOW, UTS_NOPROC, NULL, UCTX_TPROC_QUEUE_OVERFLOW)); -+ } -+ -+ *RING_QUEUE_BACK (uctx->uctx_threadQ, uctx->uctx_threads) = *regs; -+ (void) RING_QUEUE_ADD (uctx->uctx_threadQ); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+fixup_eproc_trap (USER_CTXT *uctx, ELAN4_EPROC_TRAP *trap, int waitevent) -+{ -+ E4_FaultSave *farea = &trap->tr_faultarea; -+ E4_uint32 fsr = FaultSaveFSR(farea->FSRAndFaultContext); -+ E4_uint64 CountAndType; -+ E4_uint64 CopySource; -+ E4_uint64 CopyDest; -+ -+ /* -+ * Event processor can trap as follows : -+ * 1) Event location read (faddr == event location & Event Permission) -+ * 2) Event location write (faddr == event location & Event Permission) -+ * 3) Copy Source read Read Access -+ * 4) Copy/Write dest write other -+ * -+ * NOTE - it is possible to see both 3) and 4) together - but only with physical errors. -+ */ -+ if (AT_Perm(fsr) == AT_PermLocalDataRead || AT_Perm(fsr) == AT_PermLocalDataWrite) -+ { -+ /* -+ * We complete the copy/write by issuing a waitevent 0 of the approriate type. -+ * - NB mask off bottom bits of EventAddr in case of partial setevent -+ */ -+ E4_uint64 EventAddr = trap->tr_eventaddr & ~((E4_uint64) E4_EVENT_ALIGN-1); -+ -+ if (! user_ddcq_check (uctx, 4)) -+ return (0); -+ -+ if ((trap->tr_event.ev_CountAndType & E4_EVENT_COPY_TYPE_MASK) == E4_EVENT_WRITE) -+ { -+ /* case 4) faulted on write word to destination */ -+ -+ CountAndType = trap->tr_event.ev_CountAndType & E4_EVENT_TYPE_MASK; -+ -+ PRINTF (uctx, DBG_TRAP, "fixup_eproc_trap: write Event=%llx CountAndType=%llx\n", EventAddr, CountAndType); -+ PRINTF (uctx, DBG_TRAP, " WritePtr=%llx WriteValue=%llx\n", -+ trap->tr_event.ev_WritePtr, trap->tr_event.ev_WriteValue); -+ -+ user_ddcq_waitevent (uctx, EventAddr, CountAndType, trap->tr_event.ev_WritePtr, trap->tr_event.ev_WriteValue); -+ } -+ else -+ { -+ /* case 3) or case 4) faulted on read/write of copy */ -+ if (AT_Perm (fsr) == AT_PermLocalDataRead) -+ { -+ CountAndType = (trap->tr_event.ev_CountAndType & E4_EVENT_DATA_TYPE_MASK) | EPROC_CopySize(trap->tr_status); -+ CopySource = trap->tr_event.ev_CopySource - EVENT_COPY_BLOCK_SIZE; -+ CopyDest = trap->tr_event.ev_CopyDest; -+ } -+ else -+ { -+ CountAndType = ((trap->tr_event.ev_CountAndType & E4_EVENT_DATA_TYPE_MASK) | -+ ((EPROC_CopySize(trap->tr_status) + EVENT_COPY_NDWORDS) & E4_EVENT_COPY_SIZE_MASK)); -+ CopySource = trap->tr_event.ev_CopySource - EVENT_COPY_BLOCK_SIZE; -+ CopyDest = trap->tr_event.ev_CopyDest - EVENT_COPY_BLOCK_SIZE; -+ } -+ -+ PRINTF (uctx, DBG_TRAP, "fixup_eproc_trap: copy Event=%llx CountAndType=%llx\n", EventAddr, CountAndType); -+ PRINTF (uctx, DBG_TRAP, " CopySource=%llx CopyDest=%llx\n", CopySource, CopyDest); -+ -+ user_ddcq_waitevent (uctx, EventAddr, CountAndType, CopySource, CopyDest); -+ } -+ } -+ else -+ { -+ E4_uint64 EventAddr = trap->tr_eventaddr & ~((E4_uint64) E4_EVENT_ALIGN-1); -+ E4_uint32 EventCount = trap->tr_eventaddr & (E4_EVENT_ALIGN-1); -+ -+ /* case 1) or 2) - just reissue the event */ -+ if (! waitevent) -+ PRINTF (uctx, DBG_TRAP, "fixup_eproc_trap: setevent EventAddr=%llx EventCount=%x\n", EventAddr, EventCount); -+ else -+ { -+ PRINTF (uctx, DBG_TRAP, "fixup_eproc_trap: waitevent Event=%llx CountAndType=%llx\n", EventAddr, trap->tr_event.ev_CountAndType); -+ PRINTF (uctx, DBG_TRAP, " Param[0]=%llx Param[1]=%llx\n", -+ trap->tr_event.ev_Params[0], trap->tr_event.ev_Params[1]); -+ } -+ -+ if (! user_ddcq_check (uctx, waitevent ? 4 : 2)) -+ return (0); -+ -+ if (waitevent) -+ user_ddcq_waitevent (uctx, EventAddr, trap->tr_event.ev_CountAndType, -+ trap->tr_event.ev_Params[0], trap->tr_event.ev_Params[1]); -+ else -+ user_ddcq_seteventn (uctx, EventAddr, EventCount); -+ } -+ -+ return (1); -+} -+ -+ -+static int -+resolve_eproc_trap (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, ELAN4_EPROC_TRAP *trap) -+{ -+ switch (EPROC_TrapType (trap->tr_status)) -+ { -+ case EventProcNoFault: -+ PRINTF (uctx, DBG_TRAP, "resolve_eproc_trap: EventProcNoFault\n"); -+ -+ return (UTS_FINISHED); -+ -+ case EventProcAddressAlignment: -+ return (deliver_trap (utrapp, UTS_ALIGNMENT_ERROR, UTS_EPROC, trap)); -+ -+ case EventProcMemoryFault: -+ PRINTF (uctx, DBG_TRAP, "resolve_eproc_trap: EventProcMemoryFault @ %llx\n", trap->tr_faultarea.FaultAddress); -+ -+ if (user_pagefault (uctx, &trap->tr_faultarea) != 0) -+ return (deliver_trap (utrapp, UTS_INVALID_ADDR, UTS_EPROC, trap)); -+ -+ return (UTS_FINISHED); -+ -+ case EventProcCountWrapError: -+ return (deliver_trap (utrapp, UTS_BAD_TRAP, UTS_EPROC, trap)); -+ -+ default: -+ printk ("resolve_eproc_trap: bad trap type %d\n", EPROC_TrapType (trap->tr_status)); -+ BUG(); -+ } -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+resolve_cproc_trap (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, USER_CQ *ucq) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ ELAN4_CPROC_TRAP *trap = &ucq->ucq_trap; -+ E4_uint64 command; -+ int res; -+ -+ PRINTF2 (uctx, DBG_CPROC, "resolve_cproc_trap: cq %p is trapped - Status %lx\n", ucq, trap->tr_status); -+ -+ switch (CPROC_TrapType (trap->tr_status)) -+ { -+ case CommandProcDmaQueueOverflow: -+ PRINTF (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcDmaQueueOverflow\n"); -+ /* -+ * XXXX: should wait for the queue to become emptier if we're -+ * responsible for it being very full -+ */ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ -+ case CommandProcInterruptQueueOverflow: -+ PRINTF (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcInterruptQueueOverflow\n"); -+ /* -+ * XXXX: should wait for the queue to become emptier if we're -+ * responsible for it being very full -+ */ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ -+ case CommandProcWaitTrap: -+ PRINTF0 (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcWaitTrap\n"); -+ -+ if ((res = resolve_eproc_trap (uctx, utrapp, &trap->tr_eventtrap)) != UTS_FINISHED) -+ { -+ ucq->ucq_state = UCQ_STOPPED; -+ -+ return (res); -+ } -+ -+ if (fixup_eproc_trap (uctx, &trap->tr_eventtrap, 1) == 0) -+ return UTS_RESCHEDULE; -+ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ -+ case CommandProcMemoryFault: -+ PRINTF1 (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcMemoryFault at %llx\n", trap->tr_faultarea.FaultAddress); -+ if (user_pagefault (uctx, &trap->tr_faultarea) != 0) -+ { -+ ucq->ucq_state = UCQ_STOPPED; -+ -+ return (deliver_trap (utrapp, UTS_INVALID_ADDR, UTS_CPROC, trap, elan4_cq2idx(ucq->ucq_cq))); -+ } -+ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ -+ case CommandProcRouteFetchFault: -+ command = elan4_trapped_open_command (dev, ucq->ucq_cq); -+ -+ PRINTF1 (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcRouteFetchFault to vp %d\n", (int) (command >> 32)); -+ -+ if (user_resolvevp (uctx, (unsigned) (command >> 32)) != 0) -+ { -+ ucq->ucq_state = UCQ_STOPPED; -+ -+ return (deliver_trap (utrapp, UTS_INVALID_VPROC, UTS_CPROC, trap, elan4_cq2idx(ucq->ucq_cq), (long) (command >> 32))); -+ } -+ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ -+ case CommandProcFailCountZero: -+ PRINTF0 (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcFailCountZero - reset failcount\n"); -+ -+ /* NOTE - we must not modify the ChannelNotCompleted bits - so modify */ -+ /* the restart count with a part-word store */ -+ elan4_updatecq (dev, ucq->ucq_cq, ucq->ucq_cq->cq_perm, user_cproc_retry_count); -+ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ -+ case CommandProcAddressAlignment: -+ ucq->ucq_state = UCQ_STOPPED; -+ -+ return (deliver_trap (utrapp, UTS_ALIGNMENT_ERROR, UTS_CPROC, trap, elan4_cq2idx(ucq->ucq_cq))); -+ -+ case CommandProcPermissionTrap: -+ { -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (elan4_cq2num(ucq->ucq_cq) * sizeof (E4_CommandQueueDesc)); -+ E4_uint64 control = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_Control)); -+ -+ PRINTF (uctx, DBG_CPROC, "resolve_cproc_trap: CommandProcPermissionTrap - %s\n", -+ (control & CQ_PermissionMask) != ucq->ucq_cq->cq_perm ? "resume from stop" : "permission denied"); -+ -+ if ((control & CQ_PermissionMask) == ucq->ucq_cq->cq_perm) -+ return (deliver_trap (utrapp, UTS_PERMISSION_DENIED, UTS_CPROC, trap, elan4_cq2idx(ucq->ucq_cq))); -+ -+ elan4_updatecq (dev, ucq->ucq_cq, ucq->ucq_cq->cq_perm, 0); -+ -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ break; -+ } -+ -+ case CommandProcBadData: -+ ucq->ucq_state = UCQ_STOPPED; -+ -+ return (deliver_trap (utrapp, UTS_INVALID_COMMAND, UTS_CPROC, trap, elan4_cq2idx(ucq->ucq_cq))); -+ -+ default: -+ ucq->ucq_state = UCQ_STOPPED; -+ -+ return (deliver_trap (utrapp, UTS_BAD_TRAP, UTS_CPROC, trap, elan4_cq2idx(ucq->ucq_cq))); -+ } -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+resolve_dproc_trap (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, ELAN4_DPROC_TRAP *trap) -+{ -+ ELAN_LOCATION location; -+ int node; -+ -+ if (DPROC_PrefetcherFault (trap->tr_status)) -+ { -+ PRINTF (uctx, DBG_DPROC, "resolve_dproc_trap: PrefetcherFault at %llx\n", trap->tr_prefetchFault.FaultAddress); -+ -+ if (user_pagefault (uctx, &trap->tr_prefetchFault) != 0) -+ return (deliver_trap (utrapp, UTS_INVALID_ADDR, UTS_DPROC, trap)); -+ -+ return (queue_dma_for_retry (uctx, utrapp, &trap->tr_desc)); -+ } -+ -+ switch (DPROC_TrapType (trap->tr_status)) -+ { -+ case DmaProcRouteFetchFault: -+ PRINTF (uctx, DBG_DPROC, "resolve_dproc_trap: DmaProcRouteFetchFault vp %d\n", trap->tr_desc.dma_vproc); -+ -+ if (user_resolvevp (uctx, trap->tr_desc.dma_vproc) != 0) -+ return (deliver_trap (utrapp, UTS_INVALID_VPROC, UTS_DPROC, trap, trap->tr_desc.dma_vproc)); -+ -+ return (queue_dma_for_retry (uctx, utrapp, &trap->tr_desc /* immediate */)); -+ -+ case DmaProcFailCountError: -+ PRINTF (uctx, DBG_DPROC, "resolve_dproc_trap: DmaProcFailCountError - vp %d cookie %llx\n", -+ trap->tr_desc.dma_vproc, trap->tr_desc.dma_cookie); -+ -+ trap->tr_desc.dma_typeSize |= DMA_FailCount (user_dproc_retry_count); -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ location = user_process2location(uctx, NULL, trap->tr_desc.dma_vproc); -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ node = location.loc_node; -+ -+ if ((node >= 0) && (node <= uctx->uctx_ctxt.ctxt_dev->dev_position.pos_nodes)) -+ { -+ kmutex_lock(&uctx->uctx_ctxt.ctxt_dev->dev_lock); -+ uctx->uctx_ctxt.ctxt_dev->dev_dproc_timeout[node]++; -+ kmutex_unlock(&uctx->uctx_ctxt.ctxt_dev->dev_lock); -+ } -+ -+ return (queue_dma_for_retry (uctx, utrapp, &trap->tr_desc /* XXXX - backoff for some time later */)); -+ -+ case DmaProcPacketAckError: -+ PRINTF (uctx, DBG_DPROC, "resolve_dproc_trap: DmaProcPacketAckError - %d%s\n", DPROC_PacketAckValue (trap->tr_status), -+ DPROC_PacketTimeout (trap->tr_status) ? " timeout" : ""); -+ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ location = user_process2location(uctx, NULL, trap->tr_desc.dma_vproc); -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ node = location.loc_node; -+ -+ if ((node >= 0) && (node <= uctx->uctx_ctxt.ctxt_dev->dev_position.pos_nodes)) -+ { -+ kmutex_lock(&uctx->uctx_ctxt.ctxt_dev->dev_lock); -+ uctx->uctx_ctxt.ctxt_dev->dev_ack_errors[node]++; -+ kmutex_unlock(&uctx->uctx_ctxt.ctxt_dev->dev_lock); -+ } -+ -+ return (queue_dma_for_retry (uctx, utrapp, &trap->tr_desc /* XXXX - backoff for some time later */)); -+ -+ case DmaProcQueueOverflow: -+ PRINTF (uctx, DBG_DPROC, "resolve_dproc_trap: DmaProcQueueOverflow\n"); -+ return (queue_dma_for_retry (uctx, utrapp, &trap->tr_desc /* XXXX - backoff for some time later */)); -+ -+ case DmaProcRunQueueReadFault: -+ return (deliver_trap (utrapp, UTS_BAD_TRAP, UTS_DPROC, trap)); -+ -+ default: -+ printk ("resolve_dproc_trap: unknown trap type : %d\n", DPROC_TrapType(trap->tr_status)); -+ BUG(); -+ } -+ return UTS_FINISHED; -+} -+ -+int -+resolve_tproc_trap (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, ELAN4_TPROC_TRAP *trap) -+{ -+ PRINTF (uctx, DBG_TPROC, "resolve_tproc_trap: trap state = %lx\n", trap->tr_state); -+ -+ if (trap->tr_state & TS_TrapForTooManyInstructions) -+ return (deliver_trap (utrapp, UTS_BAD_TRAP, UTS_TPROC, trap)); -+ -+ if (trap->tr_state & TS_Unimplemented) -+ return (deliver_trap (utrapp, UTS_UNIMP_INSTR, UTS_TPROC, trap)); -+ -+ if (trap->tr_state & TS_DataAlignmentError) -+ return (deliver_trap (utrapp, UTS_ALIGNMENT_ERROR, UTS_TPROC, trap)); -+ -+ if ((trap->tr_state & TS_InstAccessException) && user_pagefault (uctx, &trap->tr_instFault) != 0) -+ return (deliver_trap (utrapp, UTS_INVALID_ADDR, UTS_TPROC, trap)); -+ -+ if ((trap->tr_state & TS_DataAccessException) && user_pagefault (uctx, &trap->tr_dataFault) != 0) -+ return (deliver_trap (utrapp, UTS_INVALID_ADDR, UTS_TPROC, trap)); -+ -+ /* If we're restarting from trap - then just need to re-issue it */ -+ if (trap->tr_pc == uctx->uctx_trestart_addr || (trap->tr_state & TS_TrappedFlag)) -+ { -+ PRINTF (uctx, DBG_TPROC, "resolve_tproc_trap: trapped in trap code PC=%llx SP=%llx\n", trap->tr_pc, trap->tr_regs[1]); -+ -+ trap->tr_regs[0] = uctx->uctx_trestart_addr; -+ } -+ else -+ { -+ E4_uint64 *sp = (E4_uint64 *) user_elan2main (uctx, trap->tr_regs[1]); -+ int i, reload; -+ -+ /* need to store the register on the stack see */ -+ /* lib_tproc_trampoline_elan4_thread.S for stack layout */ -+#define TS_STACK_OFF(REG) ((((REG)&7)) - (((REG)>>3)*8) - 8) -+ for (reload = 0, i = 0; i < 64; i++) -+ { -+ if (trap->tr_dirty & ((E4_uint64) 1 << i)) -+ { -+ PRINTF (uctx, DBG_TPROC, "resolve_tproc_trap: %%r%d [%016llx] -> %p\n", i, trap->tr_regs[i], &sp[TS_STACK_OFF(i)]); -+ -+ sulonglong ((u64 *) &sp[TS_STACK_OFF(i)], trap->tr_regs[i]); -+ -+ reload |= (1 << (i >> 3)); -+ } -+ } -+#undef TS_STACK_OFF -+ -+ PRINTF (uctx, DBG_TPROC, "resolve_tproc_trap: pc %llx npc %llx\n", trap->tr_pc, trap->tr_npc); -+ PRINTF (uctx, DBG_TPROC, "resolve_tproc_trap: CC %x reload %x\n", (int) (trap->tr_state >> TS_XCCshift), reload); -+ -+ trap->tr_regs[0] = uctx->uctx_trestart_addr; -+ trap->tr_regs[2] = trap->tr_pc; -+ trap->tr_regs[3] = trap->tr_npc; -+ trap->tr_regs[4] = (trap->tr_state >> TS_XCCshift) & TS_XCCmask; -+ trap->tr_regs[5] = reload; -+ } -+ -+ return (queue_thread_for_retry (uctx, utrapp, (E4_ThreadRegs *) trap->tr_regs)); -+} -+ -+static int -+resolve_iproc_trap (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, int channel) -+{ -+ USER_IPROC_TRAP *utrap = &uctx->uctx_iprocTrap[channel]; -+ ELAN4_IPROC_TRAP *trap = &utrap->ut_trap; -+ unsigned long flags; -+ -+ elan4_inspect_iproc_trap (trap); -+ -+ if (trap->tr_flags & TR_FLAG_TOOMANY_TRANS) -+ return (deliver_trap (utrapp, UTS_INVALID_TRANS, UTS_IPROC, trap, channel)); -+ -+ ASSERT (trap->tr_trappedTrans >= 0 && trap->tr_trappedTrans < trap->tr_numTransactions); -+ -+ switch (IPROC_TrapValue (trap->tr_transactions[trap->tr_trappedTrans].IProcStatusCntxAndTrType)) -+ { -+ case InputMemoryFault: -+ if (user_pagefault (uctx, &trap->tr_faultarea) != 0) -+ { -+ utrap->ut_state = UTS_IPROC_STOPPED; -+ -+ return (deliver_trap (utrapp, UTS_INVALID_ADDR, UTS_IPROC, trap, channel)); -+ } -+ break; -+ -+ case InputDmaQueueOverflow: -+ case InputEventEngineTrapped: -+ /* nothing to do for these 2 - restarting will simulate the transactions */ -+ break; -+ -+ case InputEopErrorOnWaitForEop: -+ case InputEopErrorTrap: -+ break; -+ -+ case InputCrcErrorAfterPAckOk: -+ PRINTF (DBG_DEVICE, DBG_IPROC, "InputCrcErrorAfterPAckOk: flags %x\n", trap->tr_flags); -+ -+ ASSERT ((trap->tr_flags & TR_FLAG_ACK_SENT) && ((trap->tr_flags & (TR_FLAG_DMA_PACKET|TR_FLAG_BAD_TRANS)) || -+ ((trap->tr_flags & TR_FLAG_EOP_ERROR) && trap->tr_identifyTrans == TR_TRANS_INVALID))); -+ break; -+ -+ case InputDiscardAfterAckOk: -+ return (deliver_trap (utrapp, UTS_INVALID_TRANS, UTS_IPROC, trap, channel)); -+ -+ case InputAddressAlignment: -+ return (deliver_trap (utrapp, UTS_ALIGNMENT_ERROR, UTS_IPROC, trap, channel)); -+ -+ case InputInvalidTransType: -+ return (deliver_trap (utrapp, UTS_INVALID_TRANS, UTS_IPROC, trap, channel)); -+ -+ default: -+ printk ("resolve_iproc_trap: unknown trap type %d\n", IPROC_TrapValue (trap->tr_transactions[trap->tr_trappedTrans].IProcStatusCntxAndTrType)); -+ BUG(); -+ /* NOTREACHED */ -+ } -+ -+ if (! (trap->tr_flags & TR_FLAG_ACK_SENT) || (trap->tr_flags & TR_FLAG_EOP_BAD)) -+ { -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ utrap->ut_state = UTS_IPROC_RUNNING; -+ -+ user_stop_nacking (uctx, channel ? UCTX_IPROC_CH0_TRAPPED : UCTX_IPROC_CH1_TRAPPED); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ } -+ else if ((trap->tr_flags & (TR_FLAG_DMA_PACKET | TR_FLAG_BAD_TRANS)) || ((trap->tr_flags & TR_FLAG_EOP_ERROR) && (trap->tr_identifyTrans == TR_TRANS_INVALID))) -+ { -+ /* -+ * TR_FLAG_DMA_PACKET means a DMA packet has faulted. -+ * -+ * TR_FLAG_BAD_TRANS means we have a transaction with a bad CRC after the transaction -+ * which sent the ack - this implies it's an overlapped ack DMA packet -+ * -+ * TR_FLAG_EOP_ERROR means we've received an EOP reset - if we hadn't seen an identify -+ * transaction then it's a DMA packet. -+ * -+ * To ensure that the DMA processor works correctly the next packet must be NACKed to -+ * cause it to resend this one. -+ */ -+ PRINTF (uctx, DBG_IPROC, "resolve_iproc_trap: %s during DMA packet\n", -+ (trap->tr_flags & TR_FLAG_BAD_TRANS) ? "BadTransaction" : (trap->tr_flags & TR_FLAG_EOP_ERROR) ? "EopError" : "trap"); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ if (trap->tr_flags & TR_FLAG_DMA_PACKET) -+ { -+ if (! (trap->tr_flags & TR_FLAG_BAD_TRANS)) -+ utrap->ut_state = UTS_IPROC_EXECUTE_PACKET; -+ else -+ { -+ kcondvar_t waithere; -+ -+ /* We must ensure that the next packet is always nacked, so -+ * we wait here for an output timeout before dropping the -+ * context filter - we just pause here for 4 mS */ -+ kcondvar_init (&waithere); -+ kcondvar_timedwait (&waithere, &uctx->uctx_spinlock, &flags, lbolt + (HZ/250) + 1);; -+ kcondvar_destroy (&waithere); -+ -+ utrap->ut_state = UTS_IPROC_RUNNING; -+ -+ user_stop_nacking (uctx, channel ? UCTX_IPROC_CH0_TRAPPED : UCTX_IPROC_CH1_TRAPPED); -+ } -+ } -+ else -+ { -+ utrap->ut_state = UTS_IPROC_RUNNING; -+ -+ user_stop_nacking (uctx, channel ? UCTX_IPROC_CH0_TRAPPED : UCTX_IPROC_CH1_TRAPPED); -+ } -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ } -+ else if (trap->tr_flags & TR_FLAG_EOP_ERROR) -+ { -+ PRINTF (uctx, DBG_IPROC, "resolve_iproc_trap: EopError with identify\n"); -+ -+ utrap->ut_state = UTS_IPROC_NETWORK_ERROR; -+ } -+ else -+ { -+ PRINTF (uctx, DBG_IPROC, "resolve_iproc_trap: execute packet\n"); -+ -+ utrap->ut_state = UTS_IPROC_EXECUTE_PACKET; -+ } -+ -+ return UTS_FINISHED; -+} -+ -+ -+static int -+resolve_cproc_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ struct list_head *entry; -+ int res = UTS_FINISHED; -+ -+ kmutex_lock (&uctx->uctx_cqlock); -+ list_for_each (entry, &uctx->uctx_cqlist) { -+ USER_CQ *ucq = list_entry (entry, USER_CQ, ucq_link); -+ -+ if (ucq->ucq_state == UCQ_TRAPPED) -+ { -+ res = resolve_cproc_trap (uctx, utrapp, ucq); -+ -+ if (res != UTS_FINISHED) -+ break; -+ } -+ -+ if (ucq->ucq_errored) -+ { -+ ucq->ucq_errored = 0; -+ res = deliver_trap (utrapp, UTS_CPROC_ERROR, UTS_CPROC, &ucq->ucq_trap, elan4_cq2idx(ucq->ucq_cq)); -+ break; -+ } -+ } -+ kmutex_unlock (&uctx->uctx_cqlock); -+ -+ return (res); -+} -+ -+static int -+resolve_eproc_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ unsigned long flags; -+ int res; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ while (! RING_QUEUE_EMPTY (uctx->uctx_eprocTrapQ)) -+ { -+ ELAN4_EPROC_TRAP trap = *RING_QUEUE_FRONT (uctx->uctx_eprocTrapQ, uctx->uctx_eprocTraps); -+ -+ (void) RING_QUEUE_REMOVE (uctx->uctx_eprocTrapQ); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ if ((res = resolve_eproc_trap (uctx, utrapp, &trap)) != UTS_FINISHED) -+ return (res); -+ -+ if (fixup_eproc_trap (uctx, &trap, 0) == 0) -+ { -+ PRINTF (uctx, DBG_EPROC, "resolve_eproc_trap: could not fixup eproc trap - requeue it\n"); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (RING_QUEUE_REALLY_FULL(uctx->uctx_eprocTrapQ)) -+ uctx->uctx_status |= UCTX_EPROC_QUEUE_OVERFLOW; -+ else -+ { -+ *RING_QUEUE_FRONT(uctx->uctx_eprocTrapQ, uctx->uctx_eprocTraps) = trap; -+ -+ (void) RING_QUEUE_ADD_FRONT(uctx->uctx_eprocTrapQ); -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return UTS_RESCHEDULE; -+ } -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ } -+ -+ if (uctx->uctx_status & UCTX_EPROC_QUEUE_FULL) -+ user_stop_stopping (uctx, UCTX_EPROC_QUEUE_FULL); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (UTS_FINISHED); -+} -+ -+static int -+resolve_dproc_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ unsigned long flags; -+ int res; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ while (! RING_QUEUE_EMPTY (uctx->uctx_dprocTrapQ)) -+ { -+ ELAN4_DPROC_TRAP trap = *RING_QUEUE_FRONT(uctx->uctx_dprocTrapQ, uctx->uctx_dprocTraps); -+ -+ (void) RING_QUEUE_REMOVE (uctx->uctx_dprocTrapQ); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ if ((res = resolve_dproc_trap (uctx, utrapp, &trap)) != UTS_FINISHED) -+ return (res); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ } -+ -+ if (uctx->uctx_status & UCTX_DPROC_QUEUE_FULL) -+ user_stop_stopping (uctx, UCTX_DPROC_QUEUE_FULL); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (UTS_FINISHED); -+} -+ -+static int -+resolve_tproc_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ unsigned long flags; -+ int res; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ while (! RING_QUEUE_EMPTY (uctx->uctx_tprocTrapQ)) -+ { -+ ELAN4_TPROC_TRAP trap = *RING_QUEUE_FRONT(uctx->uctx_tprocTrapQ, uctx->uctx_tprocTraps); -+ -+ (void) RING_QUEUE_REMOVE (uctx->uctx_tprocTrapQ); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ if ((res = resolve_tproc_trap (uctx, utrapp, &trap)) != UTS_FINISHED) -+ return (res); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ } -+ -+ if (uctx->uctx_status & UCTX_TPROC_QUEUE_FULL) -+ user_stop_stopping (uctx, UCTX_TPROC_QUEUE_FULL); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (UTS_FINISHED); -+} -+ -+static int -+resolve_iproc_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ unsigned long flags; -+ int i, res; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ for (i = 0; i < 2; i++) -+ if (uctx->uctx_iprocTrap[i].ut_state == UTS_IPROC_TRAPPED) -+ { -+ uctx->uctx_iprocTrap[i].ut_state = UTS_IPROC_RESOLVING; -+ spin_unlock_irqrestore(&uctx->uctx_spinlock, flags); -+ -+ if ((res = resolve_iproc_trap (uctx, utrapp, i)) != UTS_FINISHED) -+ return (res); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+resolve_all_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ int res; -+ -+ if ((res = resolve_iproc_traps (uctx, utrapp)) != UTS_FINISHED || -+ (res = resolve_cproc_traps (uctx, utrapp)) != UTS_FINISHED || -+ (res = resolve_eproc_traps (uctx, utrapp)) != UTS_FINISHED || -+ (res = resolve_dproc_traps (uctx, utrapp)) != UTS_FINISHED || -+ (res = resolve_tproc_traps (uctx, utrapp)) != UTS_FINISHED) -+ return (res); -+ -+ if (uctx->uctx_status & UCTX_OVERFLOW_REASONS) -+ return (deliver_trap (utrapp, UTS_QUEUE_OVERFLOW, UTS_NOPROC, NULL, uctx->uctx_status)); -+ -+ if (uctx->uctx_status & UCTX_ERROR_REASONS) -+ return (deliver_trap (utrapp, UTS_QUEUE_ERROR, UTS_NOPROC, NULL, uctx->uctx_status)); -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+execute_iproc_traps (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ for (i = 0; i < 2; i++) -+ switch (uctx->uctx_iprocTrap[i].ut_state) -+ { -+ case UTS_IPROC_EXECUTE_PACKET: -+ uctx->uctx_iprocTrap[i].ut_state = UTS_IPROC_EXECUTING; -+ spin_unlock_irqrestore(&uctx->uctx_spinlock, flags); -+ -+ return (deliver_trap (utrapp, UTS_EXECUTE_PACKET, UTS_IPROC, &uctx->uctx_iprocTrap[i].ut_trap, i)); -+ -+ case UTS_IPROC_NETWORK_ERROR: -+ spin_unlock_irqrestore(&uctx->uctx_spinlock, flags); -+ -+ return (deliver_trap (utrapp, UTS_NETWORK_ERROR_TRAP, UTS_IPROC, &uctx->uctx_iprocTrap[i].ut_trap, i)); -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (UTS_FINISHED); -+} -+ -+static int -+progress_neterr (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (! RING_QUEUE_EMPTY (uctx->uctx_msgQ)) -+ { -+ ELAN4_NETERR_MSG msg = *RING_QUEUE_FRONT (uctx->uctx_msgQ, uctx->uctx_msgs); -+ -+ (void) RING_QUEUE_REMOVE (uctx->uctx_msgQ); -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return deliver_trap (utrapp, UTS_NETWORK_ERROR_MSG, UTS_NETERR_MSG, &msg, user_location2process (uctx, msg.msg_sender)); -+ } -+ -+ if (uctx->uctx_status & UCTX_NETERR_TIMER) -+ { -+ uctx->uctx_status &= ~UCTX_NETERR_TIMER; -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return deliver_trap (utrapp, UTS_NETWORK_ERROR_TIMER, UTS_NOPROC, NULL); -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (UTS_FINISHED); -+} -+ -+static void -+restart_command_queues (USER_CTXT *uctx) -+{ -+ struct list_head *entry; -+ -+ ASSERT (SPINLOCK_HELD (&uctx->uctx_spinlock)); -+ -+ list_for_each (entry, &uctx->uctx_cqlist) { -+ USER_CQ *ucq = list_entry (entry, USER_CQ, ucq_link); -+ -+ if (ucq->ucq_state == UCQ_NEEDS_RESTART) -+ { -+ ucq->ucq_state = UCQ_RUNNING; -+ -+ elan4_restartcq (uctx->uctx_ctxt.ctxt_dev, ucq->ucq_cq); -+ } -+ } -+} -+ -+static int -+restart_dmas (USER_CTXT *uctx) -+{ -+ PRINTF (uctx, DBG_TRAP, "restart_dmas: back=%d front=%d\n", uctx->uctx_dmaQ.q_back, uctx->uctx_dmaQ.q_front); -+ -+ while (! RING_QUEUE_EMPTY (uctx->uctx_dmaQ)) -+ { -+ if (! user_ddcq_check (uctx, 7)) -+ return (0); -+ -+ user_ddcq_run_dma (uctx, RING_QUEUE_FRONT(uctx->uctx_dmaQ, uctx->uctx_dmas)); -+ -+ (void) RING_QUEUE_REMOVE (uctx->uctx_dmaQ); -+ } -+ -+ return (1); -+} -+ -+static int -+restart_threads (USER_CTXT *uctx) -+{ -+ PRINTF (uctx, DBG_TRAP, "restart_threads: back=%d front=%d\n", uctx->uctx_threadQ.q_back, uctx->uctx_threadQ.q_front); -+ -+ while (! RING_QUEUE_EMPTY (uctx->uctx_threadQ)) -+ { -+ if (! user_ddcq_check (uctx, 7)) -+ return (0); -+ -+ user_ddcq_run_thread (uctx, RING_QUEUE_FRONT(uctx->uctx_threadQ, uctx->uctx_threads)); -+ -+ (void) RING_QUEUE_REMOVE (uctx->uctx_threadQ); -+ } -+ -+ return (1); -+} -+ -+int -+user_resume_eproc_trap (USER_CTXT *uctx, E4_Addr addr) -+{ -+ PRINTF2 (uctx, DBG_RESUME, "user_resume_eproc_trap: addr=%llx -> %s\n", addr, user_ddcq_check(uctx, 2) ? "success" : "EAGAIN"); -+ -+ if (! user_ddcq_check (uctx, 2)) -+ return (-EAGAIN); -+ -+ user_ddcq_setevent (uctx, addr); -+ -+ return (0); -+} -+ -+int -+user_resume_cproc_trap (USER_CTXT *uctx, unsigned indx) -+{ -+ struct list_head *entry; -+ unsigned long flags; -+ -+ PRINTF1 (uctx, DBG_RESUME, "user_resume_cproc_trap: indx=%d\n", indx); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ list_for_each (entry, &uctx->uctx_cqlist) { -+ USER_CQ *ucq = list_entry (entry, USER_CQ, ucq_link); -+ -+ if (elan4_cq2idx(ucq->ucq_cq) == indx && ucq->ucq_state == UCQ_STOPPED && !(ucq->ucq_flags & UCQ_SYSTEM)) -+ { -+ ucq->ucq_state = UCQ_NEEDS_RESTART; -+ -+ user_signal_trap (uctx); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (0); -+ } -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (-EINVAL); -+} -+ -+int -+user_resume_dproc_trap (USER_CTXT *uctx, E4_DMA *dma) -+{ -+ unsigned long flags; -+ int res = 0; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (RING_QUEUE_FULL (uctx->uctx_dmaQ)) -+ res = -ENOMEM; -+ else -+ { -+ *RING_QUEUE_BACK (uctx->uctx_dmaQ, uctx->uctx_dmas) = *dma; -+ (void) RING_QUEUE_ADD (uctx->uctx_dmaQ); -+ -+ user_signal_trap (uctx); -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (res); -+} -+ -+int -+user_resume_tproc_trap (USER_CTXT *uctx, E4_ThreadRegs *regs) -+{ -+ unsigned long flags; -+ int res = 0; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (RING_QUEUE_FULL (uctx->uctx_threadQ)) -+ res = -ENOMEM; -+ else -+ { -+ *RING_QUEUE_BACK (uctx->uctx_threadQ, uctx->uctx_threads) = *regs; -+ (void) RING_QUEUE_ADD (uctx->uctx_threadQ); -+ -+ user_signal_trap (uctx); -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (res); -+} -+ -+int -+user_resume_iproc_trap (USER_CTXT *uctx, unsigned channel, unsigned trans, -+ E4_IprocTrapHeader *hdrp, E4_IprocTrapData *datap) -+{ -+ unsigned long flags; -+ int res = 0; -+ -+ if (channel >= 2) -+ return (-EINVAL); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (uctx->uctx_iprocTrap[channel].ut_state != UTS_IPROC_STOPPED && -+ uctx->uctx_iprocTrap[channel].ut_state != UTS_IPROC_EXECUTING && -+ uctx->uctx_iprocTrap[channel].ut_state != UTS_IPROC_NETWORK_ERROR) -+ res = -EINVAL; -+ else -+ { -+ ELAN4_IPROC_TRAP *trap = &uctx->uctx_iprocTrap[channel].ut_trap; -+ -+ if (trans < trap->tr_numTransactions) -+ { -+ PRINTF1 (uctx, DBG_RESUME, "user_resume_iproc_trap: trans=%d -> execute\n", trans); -+ -+ uctx->uctx_iprocTrap[channel].ut_state = UTS_IPROC_EXECUTE_PACKET; -+ trap->tr_trappedTrans = trans; -+ trap->tr_transactions[trans] = *hdrp; -+ trap->tr_dataBuffers[trans] = *datap; -+ } -+ else -+ { -+ PRINTF1 (uctx, DBG_RESUME, "user_resume_iproc_trap: trans=%d -> running\n", trans); -+ -+ uctx->uctx_iprocTrap[channel].ut_state = UTS_IPROC_RUNNING; -+ -+ user_stop_nacking (uctx, channel ? UCTX_IPROC_CH0_TRAPPED : UCTX_IPROC_CH1_TRAPPED); -+ } -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (res); -+} -+ -+int -+__categorise_command (E4_uint64 command, int *cmdSize) -+{ -+ switch (command & 0x3) -+ { -+ case RUN_THREAD_CMD: *cmdSize = 7; break; -+ -+ default: -+ switch (command & 0x7) -+ { -+ case WRITE_DWORD_CMD: *cmdSize = 2; break; -+ case ADD_DWORD_CMD: *cmdSize = 2; break; -+ -+ default: -+ switch (command & 0xF) -+ { -+ case OPEN_STEN_PKT_CMD: -+ *cmdSize = 1; -+ return 1; -+ -+ case COPY64_CMD: *cmdSize = 2; break; -+ case GUARD_CMD: *cmdSize = 1; break; -+ case INTERRUPT_CMD: *cmdSize = 1; break; -+ case RUN_DMA_CMD: *cmdSize = 7; break; -+ -+ default: -+ switch (command & 0x1f) -+ { -+ case SEND_TRANS_CMD: -+ *cmdSize = 2 + (((command >> 16) & TR_SIZE_MASK) >> TR_SIZE_SHIFT); -+ return 2; -+ -+ case SET_EVENT_CMD: *cmdSize = 1; break; -+ case SET_EVENTN_CMD: *cmdSize = 2; break; -+ case WAIT_EVENT_CMD: *cmdSize = 4; break; -+ -+ default: -+ switch (command & 0x3f) -+ { -+ case NOP_CMD: *cmdSize = 1; break; -+ case MAKE_EXT_CLEAN_CMD: *cmdSize = 1; break; -+ default: -+ return 3; -+ } -+ break; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+int -+__whole_command (sdramaddr_t *commandPtr, sdramaddr_t insertPtr, unsigned int cqSize, unsigned int cmdSize) -+{ -+ /* Move onto next command */ -+ while (cmdSize-- && (*commandPtr) != insertPtr) -+ *commandPtr = ((*commandPtr) & ~(cqSize-1)) | (((*commandPtr) + sizeof (E4_uint64)) & (cqSize-1)); -+ -+ return cmdSize == -1; -+} -+ -+int -+user_neterr_sten (USER_CTXT *uctx, unsigned int vp, E4_uint64 cookie, int waitforeop) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ int found = 0; -+ struct list_head *el; -+ -+ user_swapout (uctx, UCTX_NETERR_FIXUP); -+ -+ kmutex_lock (&uctx->uctx_cqlock); -+ list_for_each (el, &uctx->uctx_cqlist) { -+ USER_CQ *ucq = list_entry (el, USER_CQ, ucq_link); -+ -+ if ((ucq->ucq_cq->cq_perm & CQ_STENEnableBit) != 0) -+ { -+ sdramaddr_t cqdesc = dev->dev_cqaddr + (elan4_cq2num(ucq->ucq_cq) * sizeof (E4_CommandQueueDesc)); -+ E4_uint64 queuePtrs = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_QueuePtrs)); -+ sdramaddr_t insertPtr = (queuePtrs & CQ_PtrMask); -+ sdramaddr_t commandPtr = CQ_CompletedPtr (queuePtrs); -+ unsigned int cqSize = CQ_Size ((queuePtrs >> CQ_SizeShift) & CQ_SizeMask); -+ E4_uint64 openCommand = 0; -+ -+ if (dev->dev_devinfo.dev_revision_id != PCI_REVISION_ID_ELAN4_REVA && (queuePtrs & CQ_RevB_ReorderingQueue)) -+ { -+ E4_uint32 oooMask = elan4_sdram_readl (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_HoldingValue)); -+ -+ for (; (oooMask & 1) != 0; oooMask >>= 1) -+ insertPtr = (insertPtr & ~(cqSize-1)) | ((insertPtr + sizeof (E4_uint64)) & (cqSize-1)); -+ } -+ -+ while (commandPtr != insertPtr) -+ { -+ E4_uint64 command = elan4_sdram_readq (dev, commandPtr); -+ sdramaddr_t identifyPtr; -+ unsigned int cmdSize; -+ -+ switch (__categorise_command (command, &cmdSize)) -+ { -+ case 0: -+ (void) __whole_command (&commandPtr, insertPtr, cqSize, cmdSize); -+ break; -+ -+ case 1: -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: cq=%d OPEN %llx\n", elan4_cq2num (ucq->ucq_cq), command); -+ -+ if ((command >> 32) == vp) -+ openCommand = command; -+ -+ (void) __whole_command (&commandPtr, insertPtr, cqSize, cmdSize); -+ break; -+ -+ case 2: -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: cq=%d SENDTRANS %llx\n", elan4_cq2num (ucq->ucq_cq), command); -+ -+ if (openCommand == 0) -+ (void) __whole_command (&commandPtr, insertPtr, cqSize, cmdSize); -+ else -+ { -+ switch ((command >> 16) & (TR_OPCODE_MASK | TR_SIZE_MASK)) -+ { -+ case TR_IDENTIFY & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_REMOTEDMA & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: TR_IDENTIFY/TR_REMOTEDMA\n"); -+ identifyPtr = (commandPtr & ~(cqSize-1)) | ((commandPtr + sizeof (E4_uint64)) & (cqSize-1)); -+ break; -+ -+ case TR_SETEVENT_IDENTIFY & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ case TR_INPUT_Q_COMMIT & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: TR_SETEVENT_IDENTIFY/TR_INPUT_Q_COMMIT\n"); -+ identifyPtr = (commandPtr & ~(cqSize-1)) | ((commandPtr + 2*sizeof (E4_uint64)) & (cqSize-1)); -+ break; -+ -+ case TR_ADDWORD & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: TR_ADDWORD\n"); -+ identifyPtr = (commandPtr & ~(cqSize-1)) | ((commandPtr + 3*sizeof (E4_uint64)) & (cqSize-1)); -+ break; -+ -+ case TR_TESTANDWRITE & (TR_OPCODE_MASK | TR_SIZE_MASK): -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: TR_TESTANDWRITE\n"); -+ identifyPtr = (commandPtr & ~(cqSize-1)) | ((commandPtr + 4*sizeof (E4_uint64)) & (cqSize-1)); -+ break; -+ -+ default: -+ identifyPtr = 0; -+ } -+ -+ if (! __whole_command (&commandPtr, insertPtr, cqSize, cmdSize)) -+ { -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: not whole command\n"); -+ openCommand = 0; -+ } -+ -+ else if (identifyPtr) -+ { -+ E4_uint64 tcookie = elan4_sdram_readq (dev, identifyPtr); -+ -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: cookie=%llx [%llx]\n", tcookie, cookie); -+ -+ if (tcookie == cookie) -+ { -+ unsigned int vchan = (openCommand >> 4) & 0x1f; -+ -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: cookie matches - vchan=%d\n", vchan); -+ -+ if (! waitforeop) -+ { -+ /* Alter the CQ_AckBuffer for this channel to indicate an -+ * ack was received */ -+ E4_uint64 value = elan4_sdram_readq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_AckBuffers)); -+ E4_uint64 nvalue = ((value & ~((E4_uint64)0xf << ((vchan & 0xf) << 2))) | -+ ((E4_uint64) PackOk << ((vchan & 0xf) << 2))); -+ -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: CQ_AckBuffers %llx -> %llx\n", value, nvalue); -+ -+ elan4_sdram_writeq (dev, cqdesc + offsetof (E4_CommandQueueDesc, CQ_AckBuffers), nvalue); -+ pioflush_sdram (dev); -+ } -+ -+ found++; -+ } -+ openCommand = 0; -+ } -+ -+ if ((command >> 16) & TR_LAST_AND_SEND_ACK) -+ openCommand = 0; -+ } -+ break; -+ -+ case 3: -+ PRINTF (uctx, DBG_NETERR, "user_neterr_sten: invalid command %llx\n", command); -+ kmutex_unlock (&uctx->uctx_cqlock); -+ return -EINVAL; -+ } -+ -+ } -+ } -+ } -+ kmutex_unlock (&uctx->uctx_cqlock); -+ -+ user_swapin (uctx, UCTX_NETERR_FIXUP); -+ -+ return found; -+} -+ -+int -+user_neterr_dma (USER_CTXT *uctx, unsigned int vp, E4_uint64 cookie, int waitforeop) -+{ -+ unsigned long flags; -+ int found = 0; -+ int idx; -+ -+ user_swapout (uctx, UCTX_NETERR_FIXUP); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ RING_QUEUE_ITERATE (uctx->uctx_dmaQ, idx) { -+ E4_DMA *dma = &uctx->uctx_dmas[idx]; -+ -+ if (dma->dma_vproc == vp && dma->dma_cookie == cookie) -+ { -+ PRINTF (uctx, DBG_NETERR, "user_neterr_dma: dmaQ matches %s\n", waitforeop ? "waitforeop" : "remove remoteness"); -+ -+ if (! waitforeop) -+ { -+ dma->dma_dstEvent = 0; -+ dma->dma_typeSize = DMA_ShMemWrite | DMA_Context (dma->dma_typeSize); -+ } -+ found++; -+ } -+ } -+ -+ RING_QUEUE_ITERATE (uctx->uctx_dprocTrapQ, idx) { -+ ELAN4_DPROC_TRAP *trap = &uctx->uctx_dprocTraps[idx]; -+ -+ if (trap->tr_desc.dma_vproc == vp && trap->tr_desc.dma_cookie == cookie) -+ { -+ PRINTF (uctx, DBG_NETERR, "user_neterr_dma: dmaTrapQ matches %s\n", waitforeop ? "waitforeop" : "remove remoteness"); -+ -+ if (! waitforeop) -+ { -+ trap->tr_desc.dma_dstEvent = 0; -+ trap->tr_desc.dma_typeSize = DMA_ShMemWrite | DMA_Context (trap->tr_desc.dma_typeSize); -+ } -+ found++; -+ } -+ } -+ -+ /* The device driver command queue should be empty at this point ! */ -+ if (user_ddcq_flush (uctx) == 0) -+ found = -EAGAIN; -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ /* The device driver command queue should be empty at this point ! */ -+ if (user_ddcq_flush (uctx) == 0) -+ found = -EAGAIN; -+ -+ user_swapin (uctx, UCTX_NETERR_FIXUP); -+ -+ return found; -+} -+ -+int -+user_trap_handler (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, int nticks) -+{ -+ unsigned long entered = jiffies; -+ unsigned int need_reenter = 0; -+ unsigned long flags; -+ int res; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ PRINTF1 (uctx, DBG_TRAP, "user_trap_handler: entered state=%d\n", uctx->uctx_trap_state); -+ -+ uctx->uctx_trap_count++; -+ -+ for (;;) -+ { -+ if (uctx->uctx_status & UCTX_SWAPPED_REASONS) -+ { -+ PRINTF0 (uctx, DBG_TRAP, "user_trap_handler: exiting on swapped reasons\n"); -+ -+ res = UTS_FINISHED; -+ goto no_more_to_do; -+ } -+ -+ if ((long) (jiffies - entered) > HZ) -+ { -+ PRINTF0 (uctx, DBG_TRAP, "user_trap_handler: exiting for reschedule\n"); -+ res = UTS_RESCHEDULE; -+ goto no_more_to_do; -+ } -+ -+ switch (uctx->uctx_trap_state) -+ { -+ case UCTX_TRAP_ACTIVE: -+ uctx->uctx_trap_state = UCTX_TRAP_SLEEPING; -+ -+ if (nticks == 0 || need_reenter || kcondvar_timedwaitsig (&uctx->uctx_wait, &uctx->uctx_spinlock, &flags, lbolt + nticks) != CV_RET_NORMAL) -+ { -+ PRINTF0 (uctx, DBG_TRAP, "user_trap_handler: exiting by kcondvar_timedwaitsig\n"); -+ -+ res = UTS_FINISHED; -+ goto no_more_to_do; -+ } -+ -+ /* Have slept above, so resample entered */ -+ entered = jiffies; -+ -+ uctx->uctx_trap_state = UCTX_TRAP_SIGNALLED; -+ continue; -+ -+ case UCTX_TRAP_IDLE: -+ case UCTX_TRAP_SIGNALLED: -+ uctx->uctx_trap_state = UCTX_TRAP_ACTIVE; -+ break; -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ PRINTF2 (uctx, DBG_TRAP, "user_trap_handler: resolve traps - state=%d status=%x\n", uctx->uctx_trap_state, uctx->uctx_status); -+ -+ switch ((res = resolve_all_traps (uctx, utrapp))) -+ { -+ case UTS_FINISHED: -+ break; -+ -+ case UTS_RESCHEDULE: -+ need_reenter++; -+ break; -+ -+ default: -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ goto no_more_to_do; -+ } -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (! user_ddcq_flush (uctx)) -+ { -+ PRINTF0 (uctx, DBG_TRAP, "user_trap_handler: ddcq not flushed - re-enter\n"); -+ need_reenter++; -+ continue; -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ if ((res = progress_neterr (uctx, utrapp)) != UTS_FINISHED) -+ { -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ goto no_more_to_do; -+ } -+ -+ if ((res = execute_iproc_traps (uctx, utrapp)) != UTS_FINISHED) -+ { -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ goto no_more_to_do; -+ } -+ -+ PRINTF2 (uctx, DBG_TRAP, "user_trap_handler: restart items - state=%d status=%x\n", uctx->uctx_trap_state, uctx->uctx_status); -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ if (UCTX_RUNNABLE (uctx)) -+ { -+ restart_command_queues (uctx); -+ -+ if (! restart_threads (uctx) || ! restart_dmas (uctx)) -+ { -+ PRINTF0 (uctx, DBG_TRAP, "user_trap_handler: ddcq full - re-enter\n"); -+ need_reenter++; -+ } -+ } -+ } -+ no_more_to_do: -+ uctx->uctx_trap_state = UCTX_TRAP_IDLE; -+ -+ /* -+ * Always ensure that the command queue is flushed with a flow control -+ * write, so that on the next trap we (hopefully) find it empty and so -+ * can immediately restart the context. Also if we need to be re-enter -+ * the trap handler and don't have an interrupt outstanding, then issue -+ * one now. -+ */ -+ user_ddcq_flush (uctx); -+ if (need_reenter && uctx->uctx_ddcq_intr == 0) -+ { -+ uctx->uctx_ddcq_intr++; -+ user_ddcq_intr (uctx); -+ } -+ -+ if (--uctx->uctx_trap_count == 0 && (uctx->uctx_status & UCTX_SWAPPING)) -+ kcondvar_wakeupall (&uctx->uctx_wait, &uctx->uctx_spinlock); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ PRINTF2 (uctx, DBG_TRAP, "user_trap_handler: finished state=%d res=%d\n", uctx->uctx_trap_state, res); -+ -+ return (res == UTS_EFAULT ? -EFAULT : 0); -+} -+ -+USER_CQ * -+user_alloccq (USER_CTXT *uctx, unsigned cqsize, unsigned perm, unsigned uflags) -+{ -+ USER_CQ *ucq; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (ucq, USER_CQ *, sizeof (USER_CQ), 1); -+ -+ if (ucq == (USER_CQ *) NULL) -+ return ERR_PTR(-ENOMEM); -+ -+ /* NOTE - do not allow the user to create high-priority queues as we only flush through the low-priority run queues */ -+ if ((ucq->ucq_cq = elan4_alloccq (&uctx->uctx_ctxt, cqsize, perm, (uflags & UCQ_REORDER) ? CQ_Reorder : 0)) == NULL) -+ { -+ KMEM_FREE (ucq, sizeof (USER_CQ)); -+ -+ PRINTF2 (uctx, DBG_CQ, "user_alloccq: failed elan4_allocq cqsize %d uflags %x\n", cqsize, uflags); -+ -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ atomic_set (&ucq->ucq_ref, 1); -+ -+ ucq->ucq_state = UCQ_RUNNING; -+ ucq->ucq_flags = uflags; -+ -+ PRINTF3 (uctx, DBG_CQ, "user_alloccq: ucq=%p idx=%d cqnum=%d\n", ucq, elan4_cq2idx (ucq->ucq_cq), elan4_cq2num(ucq->ucq_cq)); -+ -+ /* chain it onto the context */ -+ kmutex_lock (&uctx->uctx_cqlock); -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ list_add (&ucq->ucq_link, &uctx->uctx_cqlist); -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ kmutex_unlock (&uctx->uctx_cqlock); -+ -+ return (ucq); -+} -+ -+USER_CQ * -+user_findcq (USER_CTXT *uctx, unsigned idx) -+{ -+ struct list_head *entry; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ list_for_each (entry, &uctx->uctx_cqlist) { -+ USER_CQ *ucq = list_entry (entry, USER_CQ, ucq_link); -+ -+ if (elan4_cq2idx(ucq->ucq_cq) == idx) -+ { -+ atomic_inc (&ucq->ucq_ref); -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ return (ucq); -+ } -+ } -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return (NULL); -+} -+ -+void -+user_dropcq (USER_CTXT *uctx, USER_CQ *ucq) -+{ -+ unsigned long flags; -+ -+ PRINTF2 (uctx, DBG_CQ, "user_dropcq: ucq=%p ref=%d\n", ucq, atomic_read (&ucq->ucq_ref)); -+ -+ kmutex_lock (&uctx->uctx_cqlock); -+ if (! atomic_dec_and_test (&ucq->ucq_ref)) -+ { -+ kmutex_unlock (&uctx->uctx_cqlock); -+ return; -+ } -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ list_del (&ucq->ucq_link); -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ kmutex_unlock (&uctx->uctx_cqlock); -+ -+ elan4_freecq (&uctx->uctx_ctxt, ucq->ucq_cq); -+ -+ KMEM_FREE (ucq, sizeof (USER_CQ)); -+} -+ -+int -+user_alloc_trap_queues (USER_CTXT *uctx, unsigned ndproc_traps, unsigned neproc_traps, -+ unsigned ntproc_traps, unsigned nthreads, unsigned ndmas) -+{ -+ ELAN4_DPROC_TRAP *dprocs; -+ ELAN4_EPROC_TRAP *eprocs; -+ ELAN4_TPROC_TRAP *tprocs; -+ E4_DMA *dmas; -+ E4_ThreadRegs *threads; -+ ELAN4_NETERR_MSG *msgs; -+ unsigned long flags; -+ -+ int nmsgs = NETERR_MSGS; -+ -+ /* bounds check the values that have been passed in */ -+ if (ndproc_traps < 2 || ndproc_traps > 10000 || -+ ntproc_traps < 1 || ntproc_traps > 100 || -+ neproc_traps < 6 || neproc_traps > 10000 || -+ nthreads < 2 || nthreads > 10000 || -+ ndmas < 2 || ndmas > 10000) -+ return -EINVAL; -+ -+ if (uctx->uctx_dmas != NULL) -+ return -EBUSY; -+ -+ KMEM_ZALLOC (dprocs, ELAN4_DPROC_TRAP *, ndproc_traps * sizeof (ELAN4_DPROC_TRAP), 1); -+ KMEM_ZALLOC (eprocs, ELAN4_EPROC_TRAP *, neproc_traps * sizeof (ELAN4_EPROC_TRAP), 1); -+ KMEM_ZALLOC (tprocs, ELAN4_TPROC_TRAP *, ntproc_traps * sizeof (ELAN4_TPROC_TRAP), 1); -+ KMEM_ZALLOC (threads, E4_ThreadRegs *, nthreads * sizeof (E4_ThreadRegs), 1); -+ KMEM_ZALLOC (dmas, E4_DMA *, ndmas * sizeof (E4_DMA), 1); -+ KMEM_ZALLOC (msgs, ELAN4_NETERR_MSG *, nmsgs * sizeof (ELAN4_NETERR_MSG), 1); -+ -+ if (dprocs == NULL || eprocs == NULL || tprocs == NULL || dmas == NULL || threads == NULL || msgs == NULL) -+ { -+ if (dprocs != NULL) KMEM_FREE (dprocs, ndproc_traps * sizeof (ELAN4_DPROC_TRAP)); -+ if (eprocs != NULL) KMEM_FREE (eprocs, neproc_traps * sizeof (ELAN4_EPROC_TRAP)); -+ if (tprocs != NULL) KMEM_FREE (tprocs, ntproc_traps * sizeof (ELAN4_TPROC_TRAP)); -+ if (threads != NULL) KMEM_FREE (threads, nthreads * sizeof (E4_ThreadRegs)); -+ if (dmas != NULL) KMEM_FREE (dmas, ndmas * sizeof (E4_DMA)); -+ if (msgs != NULL) KMEM_FREE (msgs, nmsgs * sizeof (ELAN4_NETERR_MSG)); -+ -+ return -ENOMEM; -+ } -+ -+ spin_lock_irqsave (&uctx->uctx_spinlock, flags); -+ -+ uctx->uctx_dprocTraps = dprocs; -+ uctx->uctx_eprocTraps = eprocs; -+ uctx->uctx_tprocTraps = tprocs; -+ uctx->uctx_threads = threads; -+ uctx->uctx_dmas = dmas; -+ uctx->uctx_msgs = msgs; -+ -+ RING_QUEUE_INIT (uctx->uctx_dprocTrapQ, ndproc_traps, 1 /* 1 for 2nd dma */); -+ RING_QUEUE_INIT (uctx->uctx_tprocTrapQ, ntproc_traps, 0); -+ RING_QUEUE_INIT (uctx->uctx_eprocTrapQ, neproc_traps, 5 /* 1 for command, 2 for dma, 2 for inputter */); -+ RING_QUEUE_INIT (uctx->uctx_threadQ, nthreads, 1); -+ RING_QUEUE_INIT (uctx->uctx_dmaQ, ndmas, 1); -+ RING_QUEUE_INIT (uctx->uctx_msgQ, nmsgs, 0); -+ -+ spin_unlock_irqrestore (&uctx->uctx_spinlock, flags); -+ -+ return 0; -+} -+ -+USER_CTXT * -+user_alloc (ELAN4_DEV *dev) -+{ -+ USER_CTXT *uctx; -+ int res; -+ int i; -+ -+ /* Allocate and initialise the context private data */ -+ KMEM_ZALLOC (uctx, USER_CTXT *, sizeof (USER_CTXT), 1); -+ -+ if (uctx == NULL) -+ return ERR_PTR(-ENOMEM); -+ -+ if (elan4_get_position (dev, &uctx->uctx_position) == ELAN_POS_UNKNOWN) -+ { -+ KMEM_FREE (uctx, sizeof (USER_CTXT)); -+ return ERR_PTR(-EAGAIN); -+ } -+ -+ if ((res = elan4_insertctxt (dev, &uctx->uctx_ctxt, &user_trap_ops)) != 0) -+ { -+ KMEM_FREE (uctx, sizeof (USER_CTXT)); -+ return ERR_PTR(res); -+ } -+ -+ KMEM_GETPAGES (uctx->uctx_upage, ELAN4_USER_PAGE *, btopr (sizeof (ELAN4_USER_PAGE)), 1); -+ if (uctx->uctx_upage == NULL) -+ { -+ elan4_removectxt (dev, &uctx->uctx_ctxt); -+ KMEM_FREE (uctx, sizeof (USER_CTXT)); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if ((uctx->uctx_trampoline = elan4_sdram_alloc (dev, SDRAM_PAGE_SIZE)) == 0) -+ { -+ KMEM_FREEPAGES (uctx->uctx_upage, btopr (sizeof (ELAN4_USER_PAGE))); -+ elan4_removectxt (dev, &uctx->uctx_ctxt); -+ -+ KMEM_FREE (uctx, sizeof (USER_CTXT)); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if ((uctx->uctx_routetable = elan4_alloc_routetable (dev, 4 /* 512 << 4 == 8192 entries */)) == NULL) -+ { -+ elan4_sdram_free (dev, uctx->uctx_trampoline, SDRAM_PAGE_SIZE); -+ KMEM_FREEPAGES (uctx->uctx_upage, btopr (sizeof (ELAN4_USER_PAGE))); -+ elan4_removectxt (dev, &uctx->uctx_ctxt); -+ -+ KMEM_FREE (uctx, sizeof (USER_CTXT)); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ elan4_set_routetable (&uctx->uctx_ctxt, uctx->uctx_routetable); -+ -+ /* initialise the trap and swap queues to be really full */ -+ RING_QUEUE_INIT (uctx->uctx_dprocTrapQ, 0, 1); -+ RING_QUEUE_INIT (uctx->uctx_tprocTrapQ, 0, 1); -+ RING_QUEUE_INIT (uctx->uctx_eprocTrapQ, 0, 1); -+ RING_QUEUE_INIT (uctx->uctx_threadQ, 0, 1); -+ RING_QUEUE_INIT (uctx->uctx_dmaQ, 0, 1); -+ -+ INIT_LIST_HEAD (&uctx->uctx_cent_list); -+ INIT_LIST_HEAD (&uctx->uctx_vpseg_list); -+ INIT_LIST_HEAD (&uctx->uctx_cqlist); -+ -+ uctx->uctx_haltop.op_function = user_flush; -+ uctx->uctx_haltop.op_arg = uctx; -+ uctx->uctx_haltop.op_mask = INT_Halted|INT_Discarding; -+ -+ uctx->uctx_dma_flushop.op_function = user_flush_dmas; -+ uctx->uctx_dma_flushop.op_arg = uctx; -+ -+ kmutex_init (&uctx->uctx_vpseg_lock); -+ kmutex_init (&uctx->uctx_cqlock); -+ kmutex_init (&uctx->uctx_rgnmutex); -+ -+ spin_lock_init (&uctx->uctx_spinlock); -+ spin_lock_init (&uctx->uctx_rgnlock); -+ spin_lock_init (&uctx->uctx_fault_lock); -+ -+ kcondvar_init (&uctx->uctx_wait); -+ -+ if ((uctx->uctx_ddcq = user_alloccq (uctx, CQ_Size1K, CQ_EnableAllBits, UCQ_SYSTEM)) == NULL) -+ { -+ user_free (uctx); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ uctx->uctx_trap_count = 0; -+ uctx->uctx_trap_state = UCTX_TRAP_IDLE; -+ uctx->uctx_status = 0 /* UCTX_DETACHED | UCTX_SWAPPED | UCTX_STOPPED */; -+ -+ init_timer (&uctx->uctx_int_timer); -+ -+ uctx->uctx_int_timer.function = user_signal_timer; -+ uctx->uctx_int_timer.data = (unsigned long) uctx; -+ uctx->uctx_int_start = jiffies; -+ uctx->uctx_int_count = 0; -+ uctx->uctx_int_delay = 0; -+ -+ init_timer (&uctx->uctx_neterr_timer); -+ uctx->uctx_neterr_timer.function = user_neterr_timer; -+ uctx->uctx_neterr_timer.data = (unsigned long) uctx; -+ -+ uctx->uctx_upage->upage_ddcq_completed = 0; -+ uctx->uctx_ddcq_completed = 0; -+ uctx->uctx_ddcq_insertcnt = 0; -+ -+ uctx->uctx_num_fault_save = num_fault_save; -+ if (uctx->uctx_num_fault_save) -+ { -+ KMEM_ZALLOC (uctx->uctx_faults, FAULT_SAVE *, (sizeof(FAULT_SAVE) * uctx->uctx_num_fault_save), 1); -+ if ( uctx->uctx_faults == NULL) -+ { -+ user_free (uctx); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ for (i = 0; i < uctx->uctx_num_fault_save; i++) -+ uctx->uctx_faults[i].next = (i == (uctx->uctx_num_fault_save-1) ? NULL : &uctx->uctx_faults[i+1]); -+ -+ } -+ uctx->uctx_fault_list = uctx->uctx_faults; -+ -+ return (uctx); -+} -+ -+void -+user_free (USER_CTXT *uctx) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ -+ user_swapout (uctx, UCTX_EXITING); -+ -+ /* Detach from all input contexts */ -+ user_detach (uctx, NULL); -+ -+ /* since we're single threaded here - (called from close()) */ -+ /* we don't need to hold the lock to drop the command queues */ -+ /* since they cannot be mapped into user space */ -+ while (! list_empty (&uctx->uctx_cqlist)) -+ user_dropcq (uctx, list_entry (uctx->uctx_cqlist.next, USER_CQ, ucq_link)); -+ -+ /* Free off all of vpseg_list */ -+ kmutex_lock (&uctx->uctx_vpseg_lock); -+ while (! list_empty (&uctx->uctx_vpseg_list)) -+ user_remove_vpseg(uctx, list_entry (uctx->uctx_vpseg_list.next, USER_VPSEG, vps_link)); -+ kmutex_unlock (&uctx->uctx_vpseg_lock); -+ -+ if (timer_pending (&uctx->uctx_int_timer)) -+ del_timer_sync (&uctx->uctx_int_timer); -+ -+ if (timer_pending (&uctx->uctx_neterr_timer)) -+ del_timer_sync (&uctx->uctx_neterr_timer); -+ -+ if (uctx->uctx_dprocTraps) -+ KMEM_FREE (uctx->uctx_dprocTraps, uctx->uctx_dprocTrapQ.q_size * sizeof (ELAN4_DPROC_TRAP)); -+ if (uctx->uctx_tprocTraps) -+ KMEM_FREE (uctx->uctx_tprocTraps, uctx->uctx_tprocTrapQ.q_size * sizeof (ELAN4_TPROC_TRAP)); -+ if (uctx->uctx_eprocTraps) -+ KMEM_FREE (uctx->uctx_eprocTraps, uctx->uctx_eprocTrapQ.q_size * sizeof (ELAN4_EPROC_TRAP)); -+ if (uctx->uctx_dmas) -+ KMEM_FREE (uctx->uctx_dmas, uctx->uctx_dmaQ.q_size * sizeof (E4_DMA)); -+ if (uctx->uctx_msgs) -+ KMEM_FREE (uctx->uctx_msgs, NETERR_MSGS * sizeof (ELAN4_NETERR_MSG)); -+ if (uctx->uctx_threads) -+ KMEM_FREE (uctx->uctx_threads, uctx->uctx_threadQ.q_size * sizeof (E4_ThreadRegs)); -+ if (uctx->uctx_faults) -+ KMEM_FREE (uctx->uctx_faults, (sizeof(FAULT_SAVE) * uctx->uctx_num_fault_save)); -+ -+ if (uctx->uctx_intcookie_table) -+ intcookie_free_table (uctx->uctx_intcookie_table); -+ -+ elan4_set_routetable (&uctx->uctx_ctxt, NULL); -+ elan4_free_routetable (dev, uctx->uctx_routetable); -+ -+ /* Free off all USER_RGNs */ -+ user_freergns(uctx); -+ -+ elan4_sdram_free (dev, uctx->uctx_trampoline, SDRAM_PAGE_SIZE); -+ -+ /* Clear the PG_Reserved bit before free to avoid a memory leak */ -+ ClearPageReserved(pte_page(*find_pte_kernel((unsigned long) uctx->uctx_upage))); -+ KMEM_FREEPAGES (uctx->uctx_upage, btopr (sizeof (ELAN4_USER_PAGE))); -+ -+ elan4_removectxt (dev, &uctx->uctx_ctxt); -+ -+ kcondvar_destroy (&uctx->uctx_wait); -+ -+ spin_lock_destroy (&uctx->uctx_rgnlock); -+ spin_lock_destroy (&uctx->uctx_spinlock); -+ -+ kmutex_destroy (&uctx->uctx_rgnmutex); -+ kmutex_destroy (&uctx->uctx_cqlock); -+ kmutex_destroy (&uctx->uctx_vpseg_lock); -+ -+ KMEM_FREE (uctx, sizeof (USER_CTXT)); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/user_ddcq.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/user_ddcq.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/user_ddcq.c 2005-06-01 23:12:54.625435152 -0400 -@@ -0,0 +1,226 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: user_ddcq.c,v 1.15 2004/06/23 11:06:05 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/user_ddcq.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#if PAGE_SIZE < CQ_CommandMappingSize -+# define ELAN4_COMMAND_QUEUE_MAPPING PAGE_SIZE -+#else -+# define ELAN4_COMMAND_QUEUE_MAPPING CQ_CommandMappingSize -+#endif -+ -+/* The user device driver command queue is used for re-issuing -+ * trapped items. It is allocated as a 1K command queue, and -+ * we insert command flow writes event 256 words. -+ */ -+#define USER_CTRLFLOW_COUNT 256 -+ -+/* Flow control of the device driver command queue is handled by periodically -+ * inserting dword writes into the command stream. When you need to know -+ * that the queue has been flushed, then you insert an extra contorl flow -+ * write into the command queue. Should the queue not be flushed, but the -+ * trap handler be returning to user space, then it will also insert and -+ * extra interrupt command to ensure that it is re-entered after the queue -+ * has been flushed. -+ * -+ * Note - we account the space for the interrupt command on each control -+ * flow write so that we do not overflow the queue even if we end up -+ * inserting an interrupt for every command flow write. In general only -+ * a single interrupt should get inserted.... -+ */ -+ -+#define user_ddcq_command_write(value,off) do { \ -+ PRINTF(uctx, DBG_DDCQ, "user_ddcq_command_write: cmdptr=%x off=%d value=%llx\n", cmdptr, off, value);\ -+ writeq(value, cmdptr + (off << 3)); \ -+} while (0) -+ -+#define user_ddcq_command_space(uctx) \ -+ ((CQ_Size (uctx->uctx_ddcq->ucq_cq->cq_size)>>3) - ((uctx)->uctx_ddcq_insertcnt - (uctx)->uctx_upage->upage_ddcq_completed)) -+ -+#define user_ddcq_command_flow_write(uctx) do { \ -+ E4_uint64 iptr = (uctx)->uctx_ddcq_insertcnt; \ -+ ioaddr_t cmdptr = (uctx)->uctx_ddcq->ucq_cq->cq_mapping + ((iptr<<3) & ((ELAN4_COMMAND_QUEUE_MAPPING >> 1)-1));\ -+\ -+ (uctx)->uctx_ddcq_completed = ((uctx)->uctx_ddcq_insertcnt += 3);\ -+\ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_command_flow_write: completed=%llx [%llx] addr=%llx\n", (uctx)->uctx_ddcq_completed, \ -+ (uctx)->uctx_upage->upage_ddcq_completed, (uctx)->uctx_upage_addr); \ -+ user_ddcq_command_write (GUARD_CMD | GUARD_ALL_CHANNELS, 0);\ -+ user_ddcq_command_write (WRITE_DWORD_CMD | (uctx)->uctx_upage_addr, 1);\ -+ user_ddcq_command_write ((uctx)->uctx_ddcq_completed, 2);\ -+} while (0) -+ -+#define user_ddcq_command_flow_intr(uctx) do { \ -+ E4_uint64 iptr = (uctx)->uctx_ddcq_insertcnt; \ -+ ioaddr_t cmdptr = (uctx)->uctx_ddcq->ucq_cq->cq_mapping + ((iptr<<3) & ((ELAN4_COMMAND_QUEUE_MAPPING >> 1)-1));\ -+\ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_command_flow_intr: completed=%llx [%llx] addr=%llx\n", (uctx)->uctx_ddcq_completed, \ -+ (uctx)->uctx_upage->upage_ddcq_completed, (uctx)->uctx_upage_addr); \ -+ user_ddcq_command_write (INTERRUPT_CMD | ELAN4_INT_COOKIE_DDCQ, 3);\ -+} while (0) -+ -+#define user_ddcq_command_prologue(uctx, count) do { \ -+ E4_uint64 iptr = (uctx)->uctx_ddcq_insertcnt; \ -+ ioaddr_t cmdptr = (uctx)->uctx_ddcq->ucq_cq->cq_mapping + ((iptr<<3) & ((ELAN4_COMMAND_QUEUE_MAPPING >> 1)-1));\ -+ PRINTF(uctx, DBG_DDCQ, "user_ddcq_command_prologue: iptr=%llx cmdptr=%x\n", iptr, cmdptr); -+ -+#define user_ddcq_command_epilogue(uctx, count, extra) \ -+ (uctx)->uctx_ddcq_insertcnt = iptr + (count);\ -+\ -+ PRINTF(uctx, DBG_DDCQ, "user_ddcq_command_epilogue: iptr=%llx + %x + %x - completed %llx\n", iptr, count, extra, (uctx)->uctx_ddcq_completed);\ -+ if (((iptr) + (count) + (extra)) > ((uctx)->uctx_ddcq_completed + USER_CTRLFLOW_COUNT))\ -+ user_ddcq_command_flow_write(uctx); \ -+} while (0) -+ -+int -+user_ddcq_check (USER_CTXT *uctx, unsigned num) -+{ -+ PRINTF (uctx, DBG_DDCQ, "user_check_ddcq: insert=%llx completed=%llx num=%d\n", -+ uctx->uctx_ddcq_insertcnt, uctx->uctx_upage->upage_ddcq_completed, num); -+ -+ /* Ensure that there is enough space for the command we want to issue, -+ * PLUS the guard/writeword for the control flow flush. -+ * PLUS the interrupt command for rescheduling */ -+ if (user_ddcq_command_space (uctx) > (num + 4)) -+ { -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_check: loads of space\n"); -+ -+ return (1); -+ } -+ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_check: not enough space - reschedule\n"); -+ -+ uctx->uctx_trap_state = UCTX_TRAP_SIGNALLED; -+ return (0); -+} -+ -+int -+user_ddcq_flush (USER_CTXT *uctx) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ USER_CQ *ucq = uctx->uctx_ddcq; -+ -+ switch (ucq->ucq_state) -+ { -+ case UCQ_TRAPPED: -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_flush: command queue is trapped\n"); -+ return (0); -+ -+ case UCQ_NEEDS_RESTART: -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_flush: restarting command queue\n"); -+ -+ if (UCTX_RUNNABLE (uctx)) -+ { -+ ucq->ucq_state = UCQ_RUNNING; -+ elan4_restartcq (dev, ucq->ucq_cq); -+ } -+ break; -+ } -+ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_flush: insertcnt=%llx completed=%llx [%llx]\n", -+ uctx->uctx_ddcq_insertcnt, uctx->uctx_ddcq_completed, uctx->uctx_upage->upage_ddcq_completed); -+ -+ if (uctx->uctx_ddcq_completed != uctx->uctx_ddcq_insertcnt) -+ user_ddcq_command_flow_write (uctx); -+ -+ return (uctx->uctx_ddcq_completed == uctx->uctx_upage->upage_ddcq_completed); -+} -+ -+void -+user_ddcq_intr (USER_CTXT *uctx) -+{ -+ user_ddcq_command_flow_intr (uctx); -+} -+ -+void -+user_ddcq_run_dma (USER_CTXT *uctx, E4_DMA *dma) -+{ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_run_dma: cookie=%llx vproc=%llx\n", dma->dma_cookie, dma->dma_vproc); -+ -+ user_ddcq_command_prologue(uctx, 7) { -+ -+ user_ddcq_command_write ((dma->dma_typeSize & ~DMA_ContextMask) | RUN_DMA_CMD, 0); -+ user_ddcq_command_write (dma->dma_cookie, 1); -+ user_ddcq_command_write (dma->dma_vproc, 2); -+ user_ddcq_command_write (dma->dma_srcAddr, 3); -+ user_ddcq_command_write (dma->dma_dstAddr, 4); -+ user_ddcq_command_write (dma->dma_srcEvent, 5); -+ user_ddcq_command_write (dma->dma_dstEvent, 6); -+ -+ } user_ddcq_command_epilogue (uctx, 7, 0); -+} -+ -+void -+user_ddcq_run_thread (USER_CTXT *uctx, E4_ThreadRegs *regs) -+{ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_run_thread: PC=%llx SP=%llx\n", regs->Registers[0], regs->Registers[1]); -+ -+ user_ddcq_command_prologue(uctx, 7) { -+ -+ user_ddcq_command_write (regs->Registers[0] | RUN_THREAD_CMD, 0); -+ user_ddcq_command_write (regs->Registers[1], 1); -+ user_ddcq_command_write (regs->Registers[2], 2); -+ user_ddcq_command_write (regs->Registers[3], 3); -+ user_ddcq_command_write (regs->Registers[4], 4); -+ user_ddcq_command_write (regs->Registers[5], 5); -+ user_ddcq_command_write (regs->Registers[6], 6); -+ -+ } user_ddcq_command_epilogue (uctx, 7, 0); -+} -+ -+void -+user_ddcq_setevent (USER_CTXT *uctx, E4_Addr addr) -+{ -+ user_ddcq_command_prologue (uctx, 1) { -+ -+ user_ddcq_command_write (SET_EVENT_CMD | addr, 0); -+ -+ } user_ddcq_command_epilogue (uctx, 1, 0); -+} -+ -+void -+user_ddcq_seteventn (USER_CTXT *uctx, E4_Addr addr, E4_uint32 count) -+{ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_seteventn: addr=%llx count=%lx\n", addr, count); -+ -+ user_ddcq_command_prologue (uctx, 2) { -+ -+ user_ddcq_command_write (SET_EVENTN_CMD, 0); -+ user_ddcq_command_write (addr | count, 1); -+ -+ } user_ddcq_command_epilogue (uctx, 2, 0); -+} -+ -+void -+user_ddcq_waitevent (USER_CTXT *uctx, E4_Addr addr, E4_uint64 CountAndType, E4_uint64 Param0, E4_uint64 Param1) -+{ -+ PRINTF (uctx, DBG_DDCQ, "user_ddcq_waitevent: addr=%llx CountAndType=%llx Param=%llx,%llx\n", addr, CountAndType, Param0, Param1); -+ -+ user_ddcq_command_prologue (uctx, 4) { -+ -+ user_ddcq_command_write (WAIT_EVENT_CMD | addr, 0); -+ user_ddcq_command_write (CountAndType, 1); -+ user_ddcq_command_write (Param0, 2); -+ user_ddcq_command_write (Param1, 3); -+ -+ } user_ddcq_command_epilogue (uctx, 4, 0); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/elan4/user_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/elan4/user_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/elan4/user_Linux.c 2005-06-01 23:12:54.626435000 -0400 -@@ -0,0 +1,377 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: user_Linux.c,v 1.25.2.4 2005/01/18 14:36:10 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/user_Linux.c,v $*/ -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+static int -+user_pteload (USER_CTXT *uctx, E4_Addr addr, physaddr_t phys, int perm) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ E4_uint64 newpte = elan4mmu_phys2pte (dev, phys, perm); -+ -+ /* -+ * On MPSAS we don't allocate a large enough context table, so -+ * if we see an address/context pair which would "alias" because -+ * they differ in unchecked hash bits to a previous pteload, -+ * then we kill the application. -+ */ -+ { -+ unsigned hashval = (E4MMU_SHIFT_ADDR(addr, (dev->dev_pageshift[0]) + 2) ^ E4MMU_CONTEXT_SCRAMBLE(uctx->uctx_ctxt.ctxt_num)); -+ -+ if (dev->dev_rsvd_hashval[0] == 0xFFFFFFFF) -+ dev->dev_rsvd_hashval[0] = hashval & dev->dev_rsvd_hashmask[0]; -+ -+ if ((hashval & dev->dev_rsvd_hashmask[0]) != dev->dev_rsvd_hashval[0]) -+ { -+ printk ("user_pteload: vaddr=%016llx ctxnum=%x -> [%x] overlaps %x - %x [hashidx=%x]\n", (unsigned long long) addr, -+ uctx->uctx_ctxt.ctxt_num, hashval, hashval & dev->dev_rsvd_hashmask[0], dev->dev_rsvd_hashval[0], -+ E4MMU_HASH_INDEX (uctx->uctx_ctxt.ctxt_num, addr, dev->dev_pageshift[0], dev->dev_hashsize[0]-1)); -+ -+ return -EFAULT; -+ } -+ } -+ -+ if ((newpte & (PTE_PciNotLocal | PTE_CommandQueue)) == 0 && -+ ((addr & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT)) != (phys & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT)))) -+ { -+ printk ("user_pteload: vaddr=%016llx incorrectly alias sdram at %lx\n", (unsigned long long) addr, -+ phys ^ pci_resource_start (dev->dev_osdep.pdev, ELAN4_BAR_SDRAM)); -+ return -EFAULT; -+ } -+ -+ if (newpte & PTE_PciNotLocal) -+ PRINTF (uctx, DBG_FAULT, "user_pteload: addr=%llx -> pte=%llx (pci)\n", addr, newpte); -+ else if (newpte & PTE_CommandQueue) -+ PRINTF (uctx, DBG_FAULT, "user_pteload: addr=%llx -> pte=%llx (command)\n", addr, newpte); -+ else -+ PRINTF (uctx, DBG_FAULT, "user_pteload: addr=%llx -> pte=%llx (sdram)\n", addr, newpte); -+ -+ elan4mmu_pteload (&uctx->uctx_ctxt, 0, addr, newpte); -+ -+ return (0); -+} -+ -+int -+user_load_range (USER_CTXT *uctx, E4_Addr eaddr, unsigned long nbytes, E4_uint32 fsr) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ struct mm_struct *mm = current->mm; -+ int writeable = (AT_Perm(fsr) == AT_PermLocalDataWrite || -+ AT_Perm(fsr) == AT_PermRemoteWrite || -+ AT_Perm(fsr) == AT_PermLocalEvent || -+ AT_Perm(fsr) == AT_PermRemoteEvent); -+ struct vm_area_struct *vma; -+ int i, perm; -+ unsigned long len; -+ unsigned long maddr; -+ physaddr_t phys; -+ -+ kmutex_lock (&uctx->uctx_rgnmutex); -+ -+ while (nbytes > 0) -+ { -+ USER_RGN *rgn = user_rgnat_elan (uctx, eaddr); -+ -+ if (rgn == NULL || ELAN4_INCOMPAT_ACCESS (rgn->rgn_perm, AT_Perm (fsr))) -+ { -+ PRINTF (uctx, DBG_FAULT, "user_load_range: eaddr=%llx -> %s\n", eaddr, rgn == NULL ? "no mapping" : "no permission"); -+ -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (rgn == NULL ? -EFAULT : -EPERM); -+ } -+ -+ if (writeable) -+ perm = rgn->rgn_perm; -+/* This is the correct code but it breaks the Eagle libraries (1.6.X) - backed out (addy 24.08.04) -+ else if (AT_Perm(fsr) == AT_PermExecute && (rgn->rgn_perm & PERM_Mask) != PERM_LocExecute) -+*/ -+ else if (AT_Perm(fsr) == AT_PermExecute) -+ perm = PERM_LocRead | (rgn->rgn_perm & ~PERM_Mask); -+ else -+ perm = ELAN4_PERM_READONLY (rgn->rgn_perm & PERM_Mask) | (rgn->rgn_perm & ~PERM_Mask); -+ -+ PRINTF (uctx, DBG_FAULT, "user_load_range: rgn=%p [%llx.%lx.%x]\n", rgn, rgn->rgn_ebase, rgn->rgn_mbase, rgn->rgn_len); -+ -+ len = ((rgn->rgn_ebase + rgn->rgn_len) - eaddr); -+ if (len > nbytes) -+ len = nbytes; -+ nbytes -= len; -+ -+ maddr = rgn->rgn_mbase + (eaddr - rgn->rgn_ebase); -+ -+ PRINTF (uctx, DBG_FAULT, "user_load_range: eaddr=%llx->%llx -> %lx->%lx len=%x perm=%x\n", eaddr, -+ eaddr + len, maddr, maddr + len, len, perm); -+ -+ down_read (&mm->mmap_sem); -+ while (len > 0) -+ { -+ if ((vma = find_vma_intersection (mm, maddr, maddr + PAGE_SIZE)) == NULL || -+ (writeable && !(vma->vm_flags & VM_WRITE))) -+ { -+ PRINTF (DBG_USER, DBG_FAULT, "ctxt_pagefault: %s %lx\n", vma ? "no writeble at" : "no vma for", maddr); -+ up_read (&mm->mmap_sem); -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (-EFAULT); -+ } -+ -+ spin_lock (&mm->page_table_lock); -+ { -+ pte_t *ptep_ptr; -+ pte_t ptep_value; -+ -+ ptep_ptr = find_pte_map (mm, maddr); -+ if (ptep_ptr) { -+ ptep_value = *ptep_ptr; -+ pte_unmap(ptep_ptr); -+ } -+ -+ PRINTF (uctx, DBG_FAULT, "user_load_range: %lx %s %s\n", maddr, writeable ? "writeable" : "readonly", -+ !ptep_ptr ? "invalid" : pte_none(ptep_value) ? "none " : !pte_present(ptep_value) ? "swapped " : -+ writeable && !pte_write(ptep_value) ? "COW" : "OK"); -+ -+ if (ptep_ptr == NULL || pte_none(ptep_value) || !pte_present(ptep_value) || (writeable && !pte_write(ptep_value)) || !pte_read (ptep_value)) -+ { -+ spin_unlock (&mm->page_table_lock); -+ -+ make_pages_present(maddr, maddr + PAGE_SIZE); -+ -+ spin_lock (&mm->page_table_lock); -+ -+ ptep_ptr = find_pte_map (mm, maddr); -+ if (ptep_ptr) { -+ ptep_value = *ptep_ptr; -+ pte_unmap(ptep_ptr); -+ } -+ -+ if (ptep_ptr == NULL || pte_none(ptep_value) || !pte_present(ptep_value) || (writeable && !pte_write(ptep_value)) || !pte_read (ptep_value)) -+ { -+ spin_unlock (&mm->page_table_lock); -+ up_read (&mm->mmap_sem); -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (-EFAULT); -+ } -+ } -+ -+ if (writeable) -+ pte_mkdirty(ptep_value); -+ pte_mkyoung (ptep_value); -+ -+ phys = pte_phys (ptep_value); -+ -+ for (i = 0; i < PAGE_SIZE; i += (1 << dev->dev_pageshift[0])) -+ { -+ if (user_pteload (uctx, eaddr, phys, perm) < 0) -+ { -+ spin_unlock (&mm->page_table_lock); -+ up_read (&mm->mmap_sem); -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ return (-EFAULT); -+ } -+ -+ eaddr += (1 << dev->dev_pageshift[0]); -+ phys += (1 << dev->dev_pageshift[0]); -+ } -+ } -+ spin_unlock (&mm->page_table_lock); -+ -+ maddr += PAGE_SIZE; -+ len -= PAGE_SIZE; -+ } -+ up_read (&mm->mmap_sem); -+ } -+ kmutex_unlock (&uctx->uctx_rgnmutex); -+ -+ PRINTF (uctx, DBG_FAULT, "user_load_range: alldone\n"); -+ -+ return (0); -+} -+ -+void -+user_preload_main (USER_CTXT *uctx, virtaddr_t addr, unsigned long len) -+{ -+ virtaddr_t lim = addr + len - 1; -+ struct vm_area_struct *vma; -+ -+ down_read (¤t->mm->mmap_sem); -+ -+ if ((vma = find_vma (current->mm, addr)) != NULL) -+ { -+ do { -+ unsigned long start = vma->vm_start; -+ unsigned long end = vma->vm_end; -+ -+ if ((start-1) >= lim) -+ break; -+ -+ if (start < addr) start = addr; -+ if ((end-1) > lim) end = lim+1; -+ -+ if (vma->vm_flags & VM_IO) -+ continue; -+ -+ user_unload_main (uctx, start, end - start); -+ -+ make_pages_present (start, end); -+ -+ user_update_main (uctx, current->mm, start, end - start); -+ -+ } while ((vma = find_vma (current->mm, vma->vm_end)) != NULL); -+ } -+ up_read (¤t->mm->mmap_sem); -+} -+ -+static void -+user_update_range (USER_CTXT *uctx, int tbl, struct mm_struct *mm, virtaddr_t maddr, E4_Addr eaddr, unsigned long len, int perm) -+{ -+ ELAN4_DEV *dev = uctx->uctx_ctxt.ctxt_dev; -+ int roperm = ELAN4_PERM_READONLY(perm & PERM_Mask) | (perm & ~PERM_Mask); -+ int nbytes; -+ -+ while (len > 0) -+ { -+ pte_t *ptep_ptr; -+ pte_t ptep_value; -+ -+ ptep_ptr = find_pte_map (mm, maddr); -+ if (ptep_ptr) { -+ ptep_value = *ptep_ptr; -+ pte_unmap(ptep_ptr); -+ } -+ -+ PRINTF (uctx, DBG_IOPROC, "user_update_range: %llx (%lx) %s\n", eaddr, maddr, -+ !ptep_ptr ? "invalid" : pte_none(ptep_value) ? "none " : !pte_present(ptep_value) ? "swapped " : -+ !pte_write(ptep_value) ? "RO/COW" : "OK"); -+ -+ if (ptep_ptr && !pte_none(ptep_value) && pte_present(ptep_value) && pte_read (ptep_value)) { -+ physaddr_t phys_value = pte_phys(ptep_value); -+ for (nbytes = 0; nbytes < PAGE_SIZE; nbytes += (1 << dev->dev_pageshift[0])) -+ { -+ user_pteload (uctx, eaddr, phys_value, pte_write (ptep_value) ? perm : roperm); -+ -+ eaddr += (1 << dev->dev_pageshift[0]); -+ phys_value += (1 << dev->dev_pageshift[0]); -+ } -+ } -+ -+ maddr += PAGE_SIZE; -+ len -= PAGE_SIZE; -+ } -+} -+ -+void -+user_update_main (USER_CTXT *uctx, struct mm_struct *mm, virtaddr_t start, unsigned long len) -+{ -+ USER_RGN *rgn; -+ unsigned long ssize; -+ virtaddr_t end = start + len - 1; -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ PRINTF (uctx, DBG_IOPROC, "user_update_main: start=%lx end=%lx\n", start, end); -+ -+ for (rgn = user_findrgn_main (uctx, start, 0); rgn != NULL; rgn = rgn->rgn_mnext) -+ { -+ if (end < rgn->rgn_mbase) -+ break; -+ -+ if (start <= rgn->rgn_mbase && end >= (rgn->rgn_mbase + rgn->rgn_len - 1)) -+ { -+ PRINTF (uctx, DBG_IOPROC, "user_update_main: whole %lx -> %lx\n", rgn->rgn_mbase, rgn->rgn_mbase + rgn->rgn_len - 1); -+ -+ user_update_range (uctx, 0 /* tbl */, mm, rgn->rgn_mbase, rgn->rgn_ebase, rgn->rgn_len, rgn->rgn_perm); -+ } -+ else if (start <= rgn->rgn_mbase) -+ { -+ ssize = end - rgn->rgn_mbase + 1; -+ -+ PRINTF (uctx, DBG_IOPROC, "user_update_main: start %lx -> %lx\n", rgn->rgn_mbase, rgn->rgn_mbase + ssize); -+ -+ user_update_range (uctx, 0 /* tbl */, mm, rgn->rgn_mbase, rgn->rgn_ebase, ssize, rgn->rgn_perm); -+ } -+ else if (end >= (rgn->rgn_mbase + rgn->rgn_len - 1)) -+ { -+ ssize = (rgn->rgn_mbase + rgn->rgn_len) - start; -+ -+ PRINTF (uctx, DBG_IOPROC, "user_update_main: end %lx -> %lx\n", start, start + ssize); -+ -+ user_update_range (uctx, 0 /* tbl */, mm, start, rgn->rgn_ebase + (start - rgn->rgn_mbase), ssize, rgn->rgn_perm); -+ } -+ else -+ { -+ PRINTF (uctx, DBG_IOPROC, "user_update_main: middle %lx -> %lx\n", start, end); -+ -+ user_update_range (uctx, 0 /* tbl */, mm, start, rgn->rgn_ebase + (start - rgn->rgn_mbase), len, rgn->rgn_perm); -+ } -+ } -+ spin_unlock (&uctx->uctx_rgnlock); -+} -+ -+void -+user_unload_main (USER_CTXT *uctx, virtaddr_t start, unsigned long len) -+{ -+ USER_RGN *rgn; -+ unsigned long ssize; -+ virtaddr_t end = start + len - 1; -+ -+ spin_lock (&uctx->uctx_rgnlock); -+ -+ PRINTF (uctx, DBG_IOPROC, "user_unload_main: start=%lx end=%lx\n", start, end); -+ -+ for (rgn = user_findrgn_main (uctx, start, 0); rgn != NULL; rgn = rgn->rgn_mnext) -+ { -+ if (end < rgn->rgn_mbase) -+ break; -+ -+ if (start <= rgn->rgn_mbase && end >= (rgn->rgn_mbase + rgn->rgn_len - 1)) -+ { -+ PRINTF (uctx, DBG_IOPROC, "user_unload_main: whole %lx -> %lx\n", rgn->rgn_mbase, rgn->rgn_mbase + rgn->rgn_len - 1); -+ -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* tbl */, rgn->rgn_ebase, rgn->rgn_len); -+ } -+ else if (start <= rgn->rgn_mbase) -+ { -+ ssize = end - rgn->rgn_mbase + 1; -+ -+ PRINTF (uctx, DBG_IOPROC, "user_unload_main: start %lx -> %lx\n", rgn->rgn_mbase, rgn->rgn_mbase + ssize); -+ -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* tbl */, rgn->rgn_ebase, ssize); -+ } -+ else if (end >= (rgn->rgn_mbase + rgn->rgn_len - 1)) -+ { -+ ssize = (rgn->rgn_mbase + rgn->rgn_len) - start; -+ -+ PRINTF (uctx, DBG_IOPROC, "user_unload_main: end %lx -> %lx\n", start, start + ssize); -+ -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* tbl */, rgn->rgn_ebase + (start - rgn->rgn_mbase), ssize); -+ } -+ else -+ { -+ -+ PRINTF (uctx, DBG_IOPROC, "user_unload_main: middle %lx -> %lx\n", start, end); -+ -+ elan4mmu_unload_range (&uctx->uctx_ctxt, 0 /* tbl */, rgn->rgn_ebase + (start - rgn->rgn_mbase), len); -+ } -+ } -+ spin_unlock (&uctx->uctx_rgnlock); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/asm_elan4_thread.S -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/asm_elan4_thread.S 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/asm_elan4_thread.S 2005-06-01 23:12:54.626435000 -0400 -@@ -0,0 +1,78 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: asm_elan4_thread.S,v 1.1 2003/09/23 13:55:11 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/asm_elan4_thread.S,v $*/ -+ -+#include -+#include -+ -+/* -+ * c_reschedule (E4_uint64 *commandport) -+ */ -+ .global c_reschedule -+c_reschedule: -+ add %sp, -128, %sp -+ st64 %r16, [%sp] // preserve call preserved registers -+ st64 %r24, [%sp + 64] // - see CALL_USED_REGISTERS. -+ mov %r16,%r16 // BUG FIX: E4 RevA -+ mov %r24,%r24 // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ -+ mov %r7, %r18 // (%r2) return pc -+1: call 2f -+ mov %sp, %r17 // (%r1) SP -+2: add %r7, (3f-1b), %r16 // (%r0) PC -+ mov NOP_CMD, %r23 // "nop" command -+ st64suspend %r16, [%r8] -+3: ld64 [%sp], %r16 -+ ld64 [%sp + 64], %r24 // restore call preserved register -+ jmpl %r2+8, %r0 // and return -+ add %sp, 128, %sp -+ -+ -+/* -+ * c_waitevent (E4_uint64 *commandport, E4_Event *event, E4_uint64 count) -+ */ -+ .global c_waitevent -+c_waitevent: -+ add %sp, -192, %sp -+ st64 %r16, [%sp + 64] // preserve call preserved registers -+ st64 %r24, [%sp + 128] // - see CALL_USED_REGISTERS. -+ mov %r16,%r16 // BUG FIX: E4 RevA -+ mov %r24,%r24 // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ -+ mov %r7, %r18 // (%r2) return pc -+1: call 2f -+ mov %sp, %r17 // (%r1) SP -+2: add %r7, (3f-1b), %r16 // (%r0) PC -+ st32 %r16, [%sp] // event source block -+ mov MAKE_EXT_CLEAN_CMD, %r23 // "flush command queue desc" command -+ st8 %r23, [%sp+56] // event source block -+ mov %r16,%r16 // BUG FIX: E4 RevA -+ mov %r23,%r23 // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ -+ -+ or %r9, WAIT_EVENT_CMD, %r16 -+ sll8 %r10, 32, %r17 -+ or %r17, E4_EVENT_TYPE_VALUE(E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, 8), %r17 -+ mov %sp, %r18 -+ mov %r8, %r19 -+ -+ st32suspend %r16, [%r8] -+ -+3: ld64 [%sp + 64], %r16 // restore call preserved register -+ ld64 [%sp + 128], %r24 -+ jmpl %r2+8, %r0 // and return -+ add %sp, 192, %sp -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/assym_elan4.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/assym_elan4.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/assym_elan4.h 2005-06-01 23:12:54.627434848 -0400 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: genassym_elan4.c,v 1.3 2004/04/25 11:26:07 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/genassym_elan4.c,v $*/ -+ -+/* Generated by genassym_elan4 - do not modify */ -+ -+#define EP4_RCVR_THREAD_STALL 0 -+#define EP4_RCVR_PENDING_TAILP 128 -+#define EP4_RCVR_PENDING_HEAD 136 -+#define EP4_RCVR_DEBUG 176 -+#define EP4_RXD_NEXT 664 -+#define EP4_RXD_QUEUED 728 -+#define EP4_RXD_DEBUG 944 -Index: linux-2.4.21/drivers/net/qsnet/ep/cm.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/cm.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/cm.c 2005-06-01 23:12:54.632434088 -0400 -@@ -0,0 +1,3000 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: cm.c,v 1.83.2.6 2005/01/13 12:37:57 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/cm.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "debug.h" -+#include "cm.h" -+#include -+ -+#include -+ -+#if defined(LINUX) -+#include "conf_linux.h" -+#endif -+ -+int BranchingRatios[CM_MAX_LEVELS]; -+ -+int MachineId = -1; -+int BrokenLevel = -1; /* Simulates Broken Network */ -+int RejoinCheck = 1; -+int RejoinPanic = 0; -+ -+static int -+SegmentNo (CM_RAIL *cmRail, u_int nodeid, u_int lvl) -+{ -+ int i; -+ -+ ASSERT (lvl < cmRail->NumLevels); -+ -+ for (i = 0; i < lvl; i++) -+ nodeid /= cmRail->Levels[i].NumSegs; -+ -+ return (nodeid % cmRail->Levels[lvl].NumSegs); -+} -+ -+static int -+ClusterIds (CM_RAIL *cmRail, int clvl, int *clmin, int *clmax) -+{ -+ int clid = cmRail->Rail->Position.pos_nodeid - cmRail->Levels[clvl].MinNodeId; -+ -+ if (clvl == 0) -+ *clmin = *clmax = clid; -+ else -+ { -+ *clmin = cmRail->Levels[clvl - 1].MinNodeId - cmRail->Levels[clvl].MinNodeId; -+ *clmax = *clmin + cmRail->Levels[clvl - 1].NumNodes - 1; -+ } -+ return (clid); -+} -+ -+#if defined(PER_CPU_TIMEOUT) -+static void -+__Schedule_Discovery (CM_RAIL *cmRail) /* we urgently need to schedule discovery */ -+{ -+ cmRail->NextDiscoverTime = lbolt; -+ -+ if (cmRail->NextRunTime == 0 || AFTER (cmRail->NextRunTime, cmRail->NextDiscoverTime)) -+ cmRail->NextRunTime = cmRail->NextDiscoverTime; -+} -+ -+static void -+__Schedule_Heartbeat (CM_RAIL *cmRail) -+{ -+ cmRail->NextHeartbeatTime = lbolt; -+ -+ if (cmRail->NextRunTime == 0 || AFTER (cmRail->NextRunTime, cmRail->NextHeartbeatTime)) -+ cmRail->NextRunTime = cmRail->NextHeartbeatTime; -+} -+#else -+ -+static void -+__Schedule_Timer (CM_RAIL *cmRail, long tick) -+{ -+ if (! timer_pending (&cmRail->HeartbeatTimer) || AFTER (cmRail->NextRunTime, tick)) -+ { -+ cmRail->NextRunTime = tick; -+ -+ mod_timer (&cmRail->HeartbeatTimer, tick); -+ } -+} -+ -+static void -+__Schedule_Discovery (CM_RAIL *cmRail) /* we urgently need to schedule discovery */ -+{ -+ __Schedule_Timer (cmRail, cmRail->NextDiscoverTime = lbolt); -+} -+ -+static void -+__Schedule_Heartbeat (CM_RAIL *cmRail) -+{ -+ __Schedule_Timer (cmRail, cmRail->NextHeartbeatTime = lbolt); -+} -+#endif -+ -+static int -+MsgBusy (CM_RAIL *cmRail, int msgNumber) -+{ -+ switch (ep_outputq_state (cmRail->Rail, cmRail->MsgQueue, msgNumber)) -+ { -+ case EP_OUTPUTQ_BUSY: /* still busy */ -+ return 1; -+ -+ case EP_OUTPUTQ_FAILED: /* NACKed */ -+ { -+#if defined(DEBUG_PRINTF) -+ CM_MSG *msg = ep_outputq_msg (cmRail->Rail, cmRail->MsgQueue, msgNumber); -+ uint8_t type = msg->Hdr.Type; -+ uint16_t nmaps = msg->Hdr.NumMaps; -+ int16_t off = msg->Payload.Statemaps[CM_MSG_MAP(0)].offset; -+ -+ CPRINTF4 (((type == CM_MSG_TYPE_DISCOVER_LEADER) || (type == CM_MSG_TYPE_DISCOVER_SUBORDINATE)) ? 6 : 3, /* we expect broadcasts to be NACKed */ -+ "%s: msg %d type %d failed%s\n", cmRail->Rail->Name, msgNumber, type, -+ (type != CM_MSG_TYPE_HEARTBEAT) ? "" : nmaps == 0 ? ": null heartbeat" : -+ off == STATEMAP_RESET ? ": heartbeat with R statemaps" : ": heartbeat with statemaps"); -+#endif -+ return 0; -+ } -+ -+ case EP_OUTPUTQ_FINISHED: -+ return 0; -+ -+ default: -+ panic ("MsgBusy - bad return code from ep_outputq_state\n"); -+ /* NOTREACHED */ -+ } -+ return 0; -+} -+ -+static void -+LaunchMessage (CM_RAIL *cmRail, int msgNumber, int vp, int qnum, int retries, int type, int lvl, int nmaps) -+{ -+ CM_MSG *msg = ep_outputq_msg (cmRail->Rail, cmRail->MsgQueue, msgNumber); -+ CM_HDR *hdr = &msg->Hdr; -+ -+ ASSERT (nmaps >= 0 && nmaps <= CM_MSG_MAXMAPS); -+ ASSERT (SPINLOCK_HELD (&cmRail->Lock)); -+ -+ hdr->Version = CM_MSG_VERSION; -+ hdr->ParamHash = cmRail->ParamHash; -+ hdr->Timestamp = cmRail->Timestamp; -+ hdr->Checksum = 0; -+ hdr->NodeId = cmRail->Rail->Position.pos_nodeid; -+ hdr->MachineId = MachineId; -+ hdr->NumMaps = nmaps; -+ hdr->Level = lvl; -+ hdr->Type = type; -+ hdr->Checksum = CheckSum ((char *)msg + CM_MSG_BASE(nmaps), CM_MSG_SIZE(nmaps)); -+ -+ if (BrokenLevel != -1 && (lvl >= ((BrokenLevel >> (cmRail->Rail->Number*4)) & 0xf))) /* Simulate broken network? */ -+ return; -+ -+ if (ep_outputq_send (cmRail->Rail, cmRail->MsgQueue, msgNumber, -+ CM_MSG_SIZE(nmaps), vp, qnum, retries)); -+ IncrStat (cmRail, LaunchMessageFail); -+} -+ -+static int -+SendMessage (CM_RAIL *cmRail, int nodeId, int lvl, int type) -+{ -+ int msgNumber = CM_NUM_NODE_MSG_BUFFERS + cmRail->NextSpareMsg; -+ int n = CM_NUM_SPARE_MSG_BUFFERS; -+ int retries; -+ -+ ASSERT (type == CM_MSG_TYPE_IMCOMING || /* other types must use SendToSgmt */ -+ type == CM_MSG_TYPE_REJOIN); -+ -+ while (n-- > 0 && MsgBusy (cmRail, msgNumber)) /* search for idle "spare" buffer */ -+ { -+ if (++(cmRail->NextSpareMsg) == CM_NUM_SPARE_MSG_BUFFERS) -+ cmRail->NextSpareMsg = 0; -+ -+ msgNumber = CM_NUM_NODE_MSG_BUFFERS + cmRail->NextSpareMsg; -+ } -+ -+ if (n == 0) /* all "spare" message buffers busy */ -+ { -+ CPRINTF3 (3, "%s: all spare message buffers busy: trying to send type %d to %d\n", -+ cmRail->Rail->Name, type, nodeId); -+ return (0); -+ } -+ -+ /* NB IMCOMING may be echoed by MANY nodes, so we don't (and musn't) have any retries */ -+ retries = (type == CM_MSG_TYPE_IMCOMING) ? 0 : CM_P2P_DMA_RETRIES; -+ -+ LaunchMessage (cmRail, msgNumber, EP_VP_NODE (nodeId), EP_SYSTEMQ_INTR, /* eager receive */ -+ retries, type, lvl, 0); -+ -+ if (++(cmRail->NextSpareMsg) == CM_NUM_SPARE_MSG_BUFFERS) /* check this one last next time */ -+ cmRail->NextSpareMsg = 0; -+ -+ return (1); -+} -+ -+static int -+SendToSgmt (CM_RAIL *cmRail, CM_SGMT *sgmt, int type) -+{ -+ bitmap_t seg; -+ int offset; -+ int nmaps; -+ int sidx; -+ int clvl; -+ -+ ASSERT (sgmt->Level <= cmRail->TopLevel); -+ -+ if (MsgBusy (cmRail, sgmt->MsgNumber)) /* previous message still busy */ -+ { -+ CPRINTF3 (3, "%s: node message buffer busy: trying to send type %d to %d\n", -+ cmRail->Rail->Name, type, sgmt->NodeId); -+ -+ return (0); -+ } -+ -+ switch (type) -+ { -+ case CM_MSG_TYPE_RESOLVE_LEADER: -+ case CM_MSG_TYPE_DISCOVER_LEADER: -+ ASSERT (sgmt->State == CM_SGMT_ABSENT); -+ ASSERT (sgmt->Level == ((cmRail->Role == CM_ROLE_LEADER_CANDIDATE) ? cmRail->TopLevel : cmRail->TopLevel - 1)); -+ ASSERT (sgmt->Level < cmRail->NumLevels); -+ ASSERT (sgmt->Sgmt == cmRail->Levels[sgmt->Level].MySgmt); -+ -+ /* broadcast to me and all my peers at this level (== my segment in the level above) */ -+ sidx = (sgmt->Level == cmRail->NumLevels - 1) ? 0 : cmRail->Levels[sgmt->Level + 1].MySgmt; -+ -+ LaunchMessage (cmRail, sgmt->MsgNumber, EP_VP_BCAST (sgmt->Level + 1, sidx), -+ EP_SYSTEMQ_INTR, 0, /* eager rx; no retries */ -+ type, sgmt->Level, 0); -+ return (1); -+ -+ case CM_MSG_TYPE_DISCOVER_SUBORDINATE: -+ ASSERT (sgmt->Sgmt != cmRail->Levels[sgmt->Level].MySgmt); -+ ASSERT (sgmt->State == CM_SGMT_WAITING); -+ ASSERT (sgmt->Level > 0); /* broadcasting just to subtree */ -+ -+ LaunchMessage (cmRail, sgmt->MsgNumber, EP_VP_BCAST (sgmt->Level, sgmt->Sgmt), -+ EP_SYSTEMQ_INTR, 0, /* eager rx; no retries */ -+ CM_MSG_TYPE_DISCOVER_SUBORDINATE, sgmt->Level, 0); -+ return (1); -+ -+ case CM_MSG_TYPE_NOTIFY: -+ ASSERT (sgmt->State == CM_SGMT_PRESENT); -+ -+ LaunchMessage (cmRail, sgmt->MsgNumber, EP_VP_NODE (sgmt->NodeId), -+ EP_SYSTEMQ_INTR, CM_P2P_DMA_RETRIES, /* eager rx; lots of retries */ -+ CM_MSG_TYPE_NOTIFY, sgmt->Level, 0); -+ return (1); -+ -+ case CM_MSG_TYPE_HEARTBEAT: -+ { -+ CM_MSG *msg = ep_outputq_msg (cmRail->Rail, cmRail->MsgQueue, sgmt->MsgNumber); -+ CM_HDR *hdr = &msg->Hdr; -+ -+ ASSERT (sgmt->State == CM_SGMT_PRESENT); -+ -+ hdr->AckSeq = sgmt->AckSeq; -+ -+ if (!sgmt->MsgAcked) /* Current message not acknowledged */ -+ { -+ /* must have been something significant to require an ack */ -+ ASSERT (sgmt->SendMaps); -+ ASSERT (sgmt->NumMaps > 0); -+ -+ CPRINTF3 (3, "%s: retrying heartbeat to %d (%d entries)\n", cmRail->Rail->Name, sgmt->NodeId, sgmt->NumMaps); -+ -+ IncrStat (cmRail, RetryHeartbeat); -+ -+ nmaps = sgmt->NumMaps; -+ } -+ else -+ { -+ nmaps = 0; -+ -+ if (sgmt->SendMaps) /* can send maps */ -+ { -+ for (clvl = sgmt->Level; clvl < cmRail->NumLevels; clvl++) -+ { -+ if (!sgmt->Maps[clvl].OutputMapValid) -+ continue; -+ -+ while ((offset = statemap_findchange (sgmt->Maps[clvl].OutputMap, &seg, 1)) >= 0) -+ { -+ CM_STATEMAP_ENTRY *map = &msg->Payload.Statemaps[CM_MSG_MAP(nmaps)]; -+ -+ sgmt->Maps[clvl].SentChanges = 1; -+ -+ map->level = clvl; -+ map->offset = offset; -+ map->seg[0] = seg & 0xffff; -+ map->seg[1] = (seg >> 16) & 0xffff; -+#if (BT_ULSHIFT == 6) -+ map->seg[2] = (seg >> 32) & 0xffff; -+ map->seg[3] = (seg >> 48) & 0xffff; -+#elif (BT_ULSHIFT != 5) -+#error "Bad value for BT_ULSHIFT" -+#endif -+ if (++nmaps == CM_MSG_MAXMAPS) -+ goto msg_full; -+ } -+ -+ if (sgmt->Maps[clvl].SentChanges) -+ { -+ CM_STATEMAP_ENTRY *map = &msg->Payload.Statemaps[CM_MSG_MAP(nmaps)]; -+ -+ sgmt->Maps[clvl].SentChanges = 0; -+ -+ map->level = clvl; -+ map->offset = STATEMAP_NOMORECHANGES; -+ -+ if (++nmaps == CM_MSG_MAXMAPS) -+ goto msg_full; -+ } -+ } -+ } -+ -+ ASSERT (nmaps < CM_MSG_MAXMAPS); -+ -+ msg_full: -+ sgmt->NumMaps = nmaps; /* remember how many incase we retry */ -+ -+ if (nmaps == 0) /* no changes to send */ -+ hdr->Seq = sgmt->MsgSeq; /* this one can be dropped */ -+ else -+ { -+ hdr->Seq = ++(sgmt->MsgSeq); /* on to next message number */ -+ sgmt->MsgAcked = 0; /* need this one to be acked before I can send another */ -+ -+ IncrStat (cmRail, MapChangesSent); -+ } -+ } -+ -+ LaunchMessage (cmRail, sgmt->MsgNumber, EP_VP_NODE (sgmt->NodeId), -+ EP_SYSTEMQ_POLLED, CM_P2P_DMA_RETRIES, /* polled receive, lots of retries */ -+ CM_MSG_TYPE_HEARTBEAT, sgmt->Level, nmaps); -+ -+ IncrStat (cmRail, HeartbeatsSent); -+ -+ return (1); -+ } -+ -+ default: /* other types must use SendMessage */ -+ printk ("SendToSgmt: invalid type %d\n", type); -+ ASSERT (0); -+ -+ return (1); -+ } -+} -+ -+static char * -+GlobalStatusString (statemap_t *map, int idx) -+{ -+ char *strings[] = {"....", "S...", "C...", "R...", -+ ".s..", "Ss..", "Cs..", "Rs..", -+ "..r.", "S.r.", "C.r.", "R.r.", -+ ".sr.", "Ssr.", "Csr.", "Rsr.", -+ "...R", "S..R", "C..R", "R..R", -+ ".s.R", "Ss.R", "Cs.R", "Rs.R", -+ "..rR", "S.rR", "C.rR", "R.rR", -+ ".srR", "SsrR", "CsrR", "RsrR"}; -+ -+ return (strings[statemap_getbits (map, idx * CM_GSTATUS_BITS, CM_GSTATUS_BITS)]); -+} -+ -+static char * -+MapString (char *name, statemap_t *map, int nnodes, char *trailer) -+{ -+ static char *space; -+ int i; -+ -+ if (space == NULL) -+ KMEM_ALLOC (space, char *, EP_MAX_NODES*(CM_GSTATUS_BITS+1), 0); -+ -+ if (space == NULL) -+ return (""); -+ else -+ { -+ char *ptr = space; -+ -+ sprintf (space, "%s ", name); ptr += strlen (ptr); -+ for (i = 0; i < nnodes; i++, ptr += strlen (ptr)) -+ sprintf (ptr, "%s%s", i == 0 ? "" : ",", GlobalStatusString (map, i)); -+ sprintf (ptr, " %s", trailer); -+ return (space); -+ } -+} -+ -+void -+DisplayMap (DisplayInfo *di, CM_RAIL *cmRail, char *name, statemap_t *map, int nnodes, char *trailer) -+{ -+ char linebuf[256]; -+ char *ptr = linebuf; -+ int i; -+ -+#define NODES_PER_LINE 32 -+ for (i = 0; i < nnodes; i++) -+ { -+ if (ptr == linebuf) -+ { -+ sprintf (ptr, "%4d", i); -+ ptr += strlen (ptr); -+ } -+ -+ sprintf (ptr, ",%s", GlobalStatusString (map, i)); -+ ptr += strlen (ptr); -+ -+ if ((i % NODES_PER_LINE) == (NODES_PER_LINE-1) || (i == (nnodes-1))) -+ { -+ (di->func)(di->arg, "%s: %s %s %s\n", cmRail->Rail->Name, name, linebuf, trailer); -+ ptr = linebuf; -+ } -+ } -+#undef NODES_PER_LINE -+} -+ -+void -+DisplayNodeMaps (DisplayInfo *di, CM_RAIL *cmRail) -+{ -+ int lvl; -+ int clvl; -+ char mapname[128]; -+ -+ (di->func)(di->arg, "%s: Node %d maps...\n", cmRail->Rail->Name, cmRail->Rail->Position.pos_nodeid); -+ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ { -+ int nnodes = cmRail->Levels[clvl].NumNodes; -+ -+ (di->func)(di->arg, "%s: Cluster level %d: Connected %ld - %s%s\n", -+ cmRail->Rail->Name, clvl, cmRail->Levels[clvl].Connected, -+ cmRail->Levels[clvl].Online ? "Online" : "Offline", -+ cmRail->Levels[clvl].Restarting ? ", Restarting" : ""); -+ -+ for (lvl = 0; lvl < cmRail->TopLevel && lvl <= clvl; lvl++) -+ { -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ -+ sprintf (mapname, "%10s%2d", "Level", lvl); -+ DisplayMap (di, cmRail, mapname, level->SubordinateMap[clvl], nnodes, -+ level->SubordinateMapValid[clvl] ? "" : "(invalid)"); -+ } -+ -+ sprintf (mapname, "%12s", "Local"); -+ DisplayMap (di, cmRail, mapname, cmRail->Levels[clvl].LocalMap, nnodes, ""); -+ -+ sprintf (mapname, "%12s", "Subtree"); -+ DisplayMap (di, cmRail, mapname, cmRail->Levels[clvl].SubTreeMap, nnodes, -+ cmRail->Levels[clvl].SubTreeMapValid ? "" : "(invalid)"); -+ -+ sprintf (mapname, "%12s", "Global"); -+ DisplayMap (di, cmRail, mapname, cmRail->Levels[clvl].GlobalMap, nnodes, -+ cmRail->Levels[clvl].GlobalMapValid ? "" : "(invalid)"); -+ -+ sprintf (mapname, "%12s", "LastGlobal"); -+ DisplayMap (di, cmRail, mapname, cmRail->Levels[clvl].LastGlobalMap, nnodes, ""); -+ } -+} -+ -+void -+DisplayNodeSgmts (DisplayInfo *di, CM_RAIL *cmRail) -+{ -+ int lvl; -+ int sidx; -+ -+ (di->func)(di->arg, "%s: Node %d segments...\n", cmRail->Rail->Name, cmRail->NodeId); -+ -+ for (lvl = 0; lvl <= cmRail->TopLevel && lvl < cmRail->NumLevels; lvl++) -+ { -+ (di->func)(di->arg, " level %d: ", lvl); -+ -+ for (sidx = 0; sidx < ((lvl == cmRail->TopLevel) ? 1 : cmRail->Levels[lvl].NumSegs); sidx++) -+ { -+ CM_SGMT *sgmt = &cmRail->Levels[lvl].Sgmts[sidx]; -+ -+ if (sgmt->State == CM_SGMT_PRESENT) -+ (di->func)(di->arg, "[%d, in: %d out: %d %s%s]", -+ sgmt->NodeId, -+ sgmt->AckSeq, -+ sgmt->MsgSeq, -+ sgmt->MsgAcked ? "A" : "-", -+ sgmt->SendMaps ? "!" : "-"); -+ else -+ (di->func)(di->arg, "[%s]", (sgmt->State == CM_SGMT_ABSENT ? "absent" : -+ sgmt->State == CM_SGMT_WAITING ? "waiting" : -+ sgmt->State == CM_SGMT_COMING ? "coming" : "UNKNOWN")); -+ } -+ (di->func)(di->arg, "\n"); -+ } -+} -+ -+ -+static void -+StartConnecting (CM_RAIL *cmRail, CM_SGMT *sgmt, int NodeId, int Timestamp) -+{ -+ int clvl; -+ -+ CPRINTF4 (2, "%s: lvl %d subtree %d node %d -> connecting\n", cmRail->Rail->Name, sgmt->Level, sgmt->Sgmt, NodeId); -+ -+ /* Only reconnect the same guy if he was reborn */ -+ ASSERT (sgmt->State != CM_SGMT_PRESENT || -+ (sgmt->NodeId == NodeId && sgmt->Timestamp != Timestamp)); -+ -+ /* After we've connected to a new peer, we wait to receive -+ * STATEMAP_RESET before we accumulate changes and we wait for a -+ * complete map to be received before we propagate changes to other -+ * nodes. -+ * -+ * If I'm the subordinate, I can start sending maps right away, since -+ * the leader is ready for them already. If I'm the leader, I hold off -+ * sending maps until I've seen the subordinate's first heartbeat, -+ * because the subordinate might miss my NOTIFY message, still think -+ * she's a leader candidate and ignore my heartbeats. -+ */ -+ sgmt->SendMaps = (sgmt->Level == cmRail->TopLevel); /* I can send maps to my leader (she NOTIFIED me) */ -+ -+ for (clvl = sgmt->Level; clvl < cmRail->NumLevels; clvl++) -+ { -+ statemap_reset (sgmt->Maps[clvl].CurrentInputMap); -+ statemap_reset (sgmt->Maps[clvl].InputMap); -+ statemap_reset (sgmt->Maps[clvl].OutputMap); -+ -+ sgmt->Maps[clvl].InputMapValid = 0; -+ sgmt->Maps[clvl].OutputMapValid = 0; -+ sgmt->Maps[clvl].SentChanges = 0; -+ -+ if (sgmt->Level == cmRail->TopLevel) /* connection to leader */ -+ { -+ ASSERT (sgmt->Sgmt == 0); -+ ASSERT (cmRail->Role == CM_ROLE_SUBORDINATE); -+ -+ if (cmRail->Levels[clvl].SubTreeMapValid) /* already got a subtree map to send up */ -+ { -+ statemap_setmap (sgmt->Maps[clvl].OutputMap, cmRail->Levels[clvl].SubTreeMap); -+ sgmt->Maps[clvl].OutputMapValid = 1; -+ -+ statemap_clearchanges (cmRail->Levels[clvl].SubTreeMap); -+ } -+ } -+ else /* connection to subordinate */ -+ { -+ ASSERT (sgmt->Sgmt != cmRail->Levels[sgmt->Level].MySgmt); -+ -+ if (cmRail->Levels[clvl].GlobalMapValid) /* already got a global map to broadcast */ -+ { -+ statemap_setmap (sgmt->Maps[clvl].OutputMap, cmRail->Levels[clvl].GlobalMap); -+ sgmt->Maps[clvl].OutputMapValid = 1; -+ } -+ } -+ } -+ -+ /* Initialise sequence counters */ -+ sgmt->MsgSeq = sgmt->AckSeq = 0; -+ sgmt->MsgAcked = 1; /* ready to send a new sequenced message */ -+ -+ sgmt->State = CM_SGMT_PRESENT; -+ sgmt->NodeId = NodeId; -+ sgmt->UpdateTick = lbolt; -+ sgmt->Timestamp = Timestamp; -+} -+ -+static void -+StartSubTreeDiscovery (CM_RAIL *cmRail, CM_SGMT *sgmt) -+{ -+ sgmt->State = CM_SGMT_WAITING; -+ sgmt->UpdateTick = lbolt; -+ sgmt->WaitingTick = lbolt; -+ -+ if (sgmt->Level > 0) -+ __Schedule_Discovery (cmRail); -+} -+ -+void -+StartSubordinateDiscovery (CM_RAIL *cmRail) -+{ -+ int i; -+ int lvl = cmRail->TopLevel - 1; -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ -+ ASSERT (lvl >= 0 && lvl < cmRail->NumLevels); -+ -+ for (i = 0; i < level->NumSegs; i++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[i]; -+ -+ if (i != level->MySgmt) /* No-one should connect here */ -+ StartSubTreeDiscovery (cmRail, sgmt); -+ } -+} -+ -+void -+StartLeaderDiscovery (CM_RAIL *cmRail) -+{ -+ int i; -+ int clvl; -+ CM_LEVEL *level = &cmRail->Levels[cmRail->TopLevel]; -+ -+ ASSERT (cmRail->TopLevel < cmRail->NumLevels); -+ -+ for (clvl = cmRail->TopLevel; clvl < cmRail->NumLevels; clvl++) -+ { -+ cmRail->Levels[clvl].GlobalMapValid = 0; -+ cmRail->Levels[clvl].SubTreeMapValid = 0; -+ level->SubordinateMapValid[clvl] = 0; -+ } -+ -+ for (i = 0; i < level->NumSegs; i++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[i]; -+ -+ sgmt->State = CM_SGMT_ABSENT; -+ } -+ -+ cmRail->DiscoverStartTick = lbolt; -+ cmRail->Role = CM_ROLE_LEADER_CANDIDATE; -+ -+ __Schedule_Discovery (cmRail); -+} -+ -+static void -+RaiseTopLevel (CM_RAIL *cmRail) -+{ -+ ASSERT (cmRail->NumLevels != 0); -+ ASSERT (cmRail->TopLevel < cmRail->NumLevels); -+ -+ CPRINTF2 (2, "%s: RaiseTopLevel %d\n", cmRail->Rail->Name, cmRail->TopLevel + 1); -+ -+ if (++cmRail->TopLevel == cmRail->NumLevels) /* whole machine leader? */ -+ cmRail->Role = CM_ROLE_LEADER; -+ else -+ StartLeaderDiscovery (cmRail); /* look for my leader */ -+ -+ StartSubordinateDiscovery (cmRail); /* and any direct subordinates */ -+} -+ -+static void -+LowerTopLevel (CM_RAIL *cmRail, int lvl) -+{ -+ ASSERT (cmRail->NumLevels != 0); -+ ASSERT (lvl < cmRail->NumLevels); -+ -+ CPRINTF2 (2, "%s: LowerTopLevel %d\n", cmRail->Rail->Name, lvl); -+ -+ if (lvl == 0) -+ cmRail->Timestamp = lbolt; -+ -+ cmRail->TopLevel = lvl; -+ -+ StartLeaderDiscovery (cmRail); /* look for my leader */ -+} -+ -+static int -+IShouldLead (CM_RAIL *cmRail, CM_MSG *msg) -+{ -+ /* NB, this function MUST be consistently calculated on any nodes, just -+ * from the info supplied in the message. Otherwise leadership -+ * arbitration during concurrent discovery will fail. -+ */ -+ return (cmRail->NodeId < msg->Hdr.NodeId); -+} -+ -+static int -+SumCheck (CM_MSG *msg) -+{ -+ CM_HDR *hdr = &msg->Hdr; -+ uint16_t sum = hdr->Checksum; -+ uint16_t nmaps = hdr->NumMaps; -+ -+ if (nmaps > CM_MSG_MAXMAPS) { -+ printk ("SumCheck: nmaps %d > CM_MSG_MAXMAPS\n", nmaps); -+ return 0; -+ } -+ -+ if ((hdr->Type != CM_MSG_TYPE_HEARTBEAT) && nmaps != 0) { -+ printk ("SumCheck: type(%d) not HEARTBEAT and nmaps(%d) != 0\n", hdr->Type, nmaps); -+ return 0; -+ } -+ -+ hdr->Checksum = 0; -+ -+ if (CheckSum ((char *)msg + CM_MSG_BASE(nmaps), CM_MSG_SIZE(nmaps)) != sum) { -+ printk ("SumCheck: checksum failed %x %x\n", CheckSum ((char *)msg + CM_MSG_BASE(nmaps), CM_MSG_SIZE(nmaps)), sum); -+ -+ return 0; -+ } -+ -+ return 1; -+} -+ -+static void -+ProcessMessage (EP_RAIL *rail, void *arg, void *msgbuf) -+{ -+ CM_RAIL *cmRail = (CM_RAIL *) arg; -+ CM_MSG *msg = (CM_MSG *) msgbuf; -+ CM_HDR *hdr = &msg->Hdr; -+ int lvl; -+ int sidx; -+ CM_LEVEL *level; -+ CM_SGMT *sgmt; -+ bitmap_t seg; -+ int i; -+ int delay; -+ static long tlast; -+ static int count; -+ -+ /* Poll the message Version field until the message has completely -+ * arrived in main memory. */ -+ for (delay = 1; hdr->Version == EP_SYSTEMQ_UNRECEIVED && delay < EP_SYSTEMQ_UNRECEIVED_TLIMIT; delay <<= 1) -+ DELAY (delay); -+ -+ /* Display a message every 60 seconds if we see an "old" format message */ -+ if (hdr->Version == EP_SYSTEMQ_UNRECEIVED && (((lbolt - tlast) > 60*HZ) ? (count = 0) : ++count) < 1) -+ { -+ printk ("%s: received old protocol message (type %d from node %d)\n", cmRail->Rail->Name, -+ ((uint8_t *) msg)[20], ((uint16_t *) msg)[4]); -+ -+ tlast = lbolt; -+ goto finished; -+ } -+ -+ if (hdr->Version != CM_MSG_VERSION || hdr->ParamHash != cmRail->ParamHash || hdr->MachineId != MachineId) -+ { -+ CPRINTF8 (1, "%s: invalid message : Version %08x (%08x) ParamHash %08x (%08x) MachineId %04x (%04x) Nodeid %d\n", cmRail->Rail->Name, -+ hdr->Version, CM_MSG_VERSION, hdr->ParamHash, cmRail->ParamHash, hdr->MachineId, MachineId, hdr->NodeId); -+ goto finished; -+ } -+ -+ if (!SumCheck (msg)) -+ { -+ printk ("%s: checksum failed on msg from %d?\n", cmRail->Rail->Name, hdr->NodeId); -+ goto finished; -+ } -+ -+ if (hdr->NodeId == cmRail->NodeId) /* ignore my own broadcast */ -+ { -+ CPRINTF3 (6, "%s: node %d type %d: ignored (MESSAGE FROM ME)\n", -+ cmRail->Rail->Name, hdr->NodeId, hdr->Type); -+ -+ if (hdr->Type != CM_MSG_TYPE_DISCOVER_LEADER && hdr->Type != CM_MSG_TYPE_RESOLVE_LEADER) -+ printk ("%s: node %d type %d: ignored (MESSAGE FROM ME)\n", -+ cmRail->Rail->Name, hdr->NodeId, hdr->Type); -+ goto finished; -+ } -+ -+ lvl = hdr->Level; -+ level = &cmRail->Levels[lvl]; -+ -+ if (BrokenLevel != -1 && (lvl >= ((BrokenLevel >> (cmRail->Rail->Number*4)) & 0xf))) /* Simulate broken network? */ -+ goto finished; -+ -+ if (lvl >= cmRail->NumLevels || /* from outer space */ -+ hdr->NodeId < level->MinNodeId || /* from outside this level's subtree */ -+ hdr->NodeId >= level->MinNodeId + level->NumNodes) -+ { -+ printk ("%s: lvl %d node %d type %d: ignored (%s)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId, hdr->Type, -+ lvl >= cmRail->NumLevels ? "level too big for machine" : "outside subtree"); -+ goto finished; -+ } -+ -+ sidx = SegmentNo (cmRail, hdr->NodeId, lvl); -+ sgmt = &level->Sgmts[sidx]; -+ -+ switch (hdr->Type) -+ { -+ case CM_MSG_TYPE_RESOLVE_LEADER: -+ if (lvl >= cmRail->TopLevel) -+ { -+ CPRINTF4 (6, "%s: lvl %d sidx %d node %d RESOLVE_LEADER: ignored (above my level)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ break; -+ } -+ -+ /* someone else thinks they lead at the same level as me */ -+ CPRINTF4 (1, "%s: lvl %d sidx %d node %d RESOLVE_LEADER: !REJOIN (putsch)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ printk ("%s: lvl %d sidx %d node %d RESOLVE_LEADER: !REJOIN (putsch)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ -+ SendMessage (cmRail, hdr->NodeId, lvl, CM_MSG_TYPE_REJOIN); -+ break; -+ -+ case CM_MSG_TYPE_DISCOVER_LEADER: -+ if (lvl > cmRail->TopLevel) -+ { -+ CPRINTF4 (6, "%s: lvl %d sidx %d node %d DISCOVER_LEADER: ignored (above my level)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ break; -+ } -+ -+ if (sidx == level->MySgmt) /* someone I led thinks they lead some of my subtrees */ -+ { -+ CPRINTF4 (1, "%s: lvl %d sidx %d node %d DISCOVER_LEADER: !REJOIN (putsch)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ printk ("%s: lvl %d sidx %d node %d DISCOVER_LEADER: !REJOIN (putsch)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ SendMessage (cmRail, hdr->NodeId, hdr->Level, CM_MSG_TYPE_REJOIN); -+ break; -+ } -+ -+ if (lvl < cmRail->TopLevel) /* I'm the leader of this level */ -+ { -+ if (sgmt->State == CM_SGMT_PRESENT && /* someone thinks someone I lead is dead */ -+ sgmt->NodeId != hdr->NodeId) -+ { -+ /* My subordinate's death could be noticed by one of her peers -+ * before I do. If she _is_ dead, I'll notice before long and -+ * NOTIFY this discover. If this discover completes before I -+ * detect my subordinate's death, the discovering node will -+ * try to take over from me, and then I'll RESET her. -+ */ -+ CPRINTF4 (6, "%s: lvl %d sidx %d node %d DISCOVER_LEADER: ignored (got established subordinate)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ return; -+ } -+ -+ if (sgmt->State != CM_SGMT_PRESENT || /* New connection */ -+ sgmt->Timestamp != hdr->Timestamp) /* new incarnation */ -+ StartConnecting (cmRail, sgmt, hdr->NodeId, hdr->Timestamp); -+ -+ CPRINTF4 (2, "%s: lvl %d sidx %d node %d DISCOVER_LEADER: !NOTIFY)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ SendToSgmt (cmRail, sgmt, CM_MSG_TYPE_NOTIFY); -+ break; -+ } -+ -+ ASSERT (lvl == cmRail->TopLevel); -+ -+ if (cmRail->Role == CM_ROLE_SUBORDINATE) -+ { -+ /* I think my leader is alive, in which case she'll NOTIFY this -+ * DISCOVER. If she's dead, I'll start to become a leader -+ * candidate and handle this appropriately. -+ */ -+ CPRINTF3 (6, "%s: lvl %d node %d DISCOVER: ignored (I'm a subordinate)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ break; -+ } -+ -+ ASSERT (cmRail->Role == CM_ROLE_LEADER_CANDIDATE); -+ -+ /* A peer at this level is bidding for leadership along with me */ -+ if (IShouldLead (cmRail, msg)) -+ { -+ CPRINTF3 (6, "%s: lvl %d node %d DISCOVER: but I should lead\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ -+ /* So there _is_ someone there; She'll be seeing my DISCOVER -+ * messages and extending her discovery period, so that when I -+ * become leader, I'll NOTIFY her. In the meantime I'll flag her -+ * activity, so she remains WAITING. -+ */ -+ sgmt->UpdateTick = lbolt; -+ break; -+ } -+ -+ /* Defer to sender... */ -+ CPRINTF3 (6, "%s: lvl %d node %d DISCOVER: delaying me becoming leader\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ -+ StartLeaderDiscovery (cmRail); -+ break; -+ -+ case CM_MSG_TYPE_DISCOVER_SUBORDINATE: -+ if (lvl <= cmRail->TopLevel) -+ { -+ CPRINTF3 (6, "%s: lvl %d node %d DISCOVER_SUBORDINATE: ignored (from my subtree)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ break; -+ } -+ -+ if (cmRail->Role != CM_ROLE_LEADER_CANDIDATE) -+ { -+ CPRINTF3 (6, "%s: lvl %d node %d DISCOVER_SUBORDINATE: ignored (I'm not looking for a leader)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ break; -+ } -+ -+ if (hdr->Level > cmRail->BroadcastLevel && AFTER (lbolt, cmRail->BroadcastLevelTick + EP_WITHDRAW_TIMEOUT)) -+ { -+ CPRINTF3 (6, "%s: lvl %d node %d DISCOVER_SUBORDINATE: ignored (broadcast level too low)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ break; -+ } -+ -+ CPRINTF3 (2, "%s: lvl %d node %d DISCOVER_SUBORDINATE: !IMCOMING\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ -+ SendMessage (cmRail, hdr->NodeId, hdr->Level, CM_MSG_TYPE_IMCOMING); -+ break; -+ -+ case CM_MSG_TYPE_IMCOMING: -+ if (lvl > cmRail->TopLevel || /* from peer or node above me */ -+ sgmt->State == CM_SGMT_PRESENT || /* already got a subtree */ -+ sgmt->State == CM_SGMT_ABSENT) /* already written off this subtree */ -+ { -+ CPRINTF4 (2, "%s: lvl %d sidx %d node %d IMCOMING: ignored\n", cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ break; -+ } -+ -+ CPRINTF4 (2, "%s: lvl %d sidx %d node %d IMCOMING: waiting...\n", cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ sgmt->State = CM_SGMT_COMING; -+ sgmt->UpdateTick = lbolt; -+ break; -+ -+ case CM_MSG_TYPE_NOTIFY: -+ if (cmRail->Role != CM_ROLE_LEADER_CANDIDATE || /* I'm not looking for a leader */ -+ lvl != cmRail->TopLevel) /* at this level */ -+ { -+ /* If this person really should be my leader, my existing leader -+ * will time out, and I'll discover this one. */ -+ CPRINTF4 (2, "%s: lvl %d node %d NOTIFY: ignored (%s)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId, -+ lvl < cmRail->TopLevel ? "already leader" : -+ lvl > cmRail->TopLevel ? "lvl too high" : "already subordinate"); -+ break; -+ } -+ -+ CPRINTF3 (2, "%s: lvl %d node %d NOTIFY: becoming subordinate\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ -+ cmRail->Role = CM_ROLE_SUBORDINATE; /* Now I've found my level */ -+ StartConnecting (cmRail, &level->Sgmts[0], hdr->NodeId, hdr->Timestamp); -+ break; -+ -+ case CM_MSG_TYPE_HEARTBEAT: -+ if (lvl > cmRail->TopLevel) -+ { -+ CPRINTF3 (2, "%s: lvl %d node %d H/BEAT: ignored (lvl too high)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ break; -+ } -+ -+ if (lvl == cmRail->TopLevel) /* heartbeat from my leader */ -+ { -+ if (cmRail->Role == CM_ROLE_LEADER_CANDIDATE) /* but I've not got one */ -+ { -+ /* I'm probably a new incarnation of myself; I'll keep doing -+ * discovery until my previous existence's leader NOTIFY's me. -+ * If I was this node's leader, she'll time me out (I'm not -+ * sending heartbeats to her) and we'll fight it out for -+ * leadership. */ -+ CPRINTF3 (2, "%s: lvl %d node %d H/BEAT ignored (no leader)\n", -+ cmRail->Rail->Name, lvl, hdr->NodeId); -+ break; -+ } -+ sidx = 0; -+ sgmt = &level->Sgmts[0]; -+ } -+ -+ if (sgmt->State != CM_SGMT_PRESENT || /* not fully connected with this guy */ -+ sgmt->NodeId != hdr->NodeId || /* someone else impersonating my peer */ -+ sgmt->Timestamp != hdr->Timestamp) /* new incarnation of my peer */ -+ { -+ CPRINTF4 (1, "%s: lvl %d sidx %d node %d H/BEAT: !REJOIN\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId); -+ -+ printk ("%s: lvl %d sidx %d node %d H/BEAT: !REJOIN %s\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, -+ sgmt->State != CM_SGMT_PRESENT ? "not present" : -+ sgmt->NodeId != hdr->NodeId ? "someone else" : "new incarnation"); -+ -+ SendMessage (cmRail, hdr->NodeId, hdr->Level, CM_MSG_TYPE_REJOIN); -+ break; -+ } -+ -+ if (!((hdr->Seq == sgmt->AckSeq) || /* NOT duplicate message or */ -+ (hdr->Seq == (CM_SEQ)(sgmt->AckSeq + 1))) || /* expected message */ -+ !((hdr->AckSeq == sgmt->MsgSeq) || /* NOT expected ack or */ -+ (hdr->AckSeq == (CM_SEQ)(sgmt->MsgSeq - 1)))) /* duplicate ack */ -+ { -+ CPRINTF9 (1, "%s: lvl %d sidx %d node %d type %d: H/BEAT !REJOIN (out-of-seq) M(%d,a%d) S%d,A%d\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type, -+ (int)hdr->Seq, (int)hdr->AckSeq, (int)sgmt->MsgSeq, (int)sgmt->AckSeq); -+ -+ printk ("%s: lvl %d sidx %d node %d type %d: H/BEAT !REJOIN (out-of-seq) M(%d,a%d) S%d,A%d\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type, -+ (int)hdr->Seq, (int)hdr->AckSeq, (int)sgmt->MsgSeq, (int)sgmt->AckSeq); -+ -+ SendMessage (cmRail, hdr->NodeId, hdr->Level, CM_MSG_TYPE_REJOIN); -+ break; -+ } -+ -+ IncrStat (cmRail, HeartbeatsRcvd); -+ -+ sgmt->UpdateTick = lbolt; -+ sgmt->SendMaps = 1; -+ -+ if (sgmt->MsgSeq == hdr->AckSeq) /* acking current message */ -+ sgmt->MsgAcked = 1; /* can send the next one */ -+ -+ if (hdr->Seq == sgmt->AckSeq) /* discard duplicate (or NULL heartbeat) */ -+ { -+ CPRINTF6 (6, "%s: lvl %d sidx %d node %d type %d: %s H/BEAT\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type, -+ hdr->NumMaps == 0 ? "null" : "duplicate"); -+ break; -+ } -+ -+ CPRINTF7 (6, "%s: lvl %d sidx %d node %d type %d: seq %d maps %d H/BEAT\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type, hdr->Seq, hdr->NumMaps); -+ -+ sgmt->AckSeq = hdr->Seq; /* ready to receive next one */ -+ -+ for (i = 0; i < hdr->NumMaps; i++) -+ { -+ CM_STATEMAP_ENTRY *map = &msg->Payload.Statemaps[CM_MSG_MAP(i)]; -+ int clvl = map->level; -+ -+ if (clvl < 0) /* end of message */ -+ break; -+ -+ if (clvl < sgmt->Level) /* bad level */ -+ { -+ CPRINTF6 (1, "%s: lvl %d sidx %d node %d type %d: H/BEAT !REJOIN (bad clevel %d)\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type, clvl); -+ -+ SendMessage (cmRail, hdr->NodeId, hdr->Level, CM_MSG_TYPE_REJOIN); -+ goto finished; -+ } -+ -+ if (map->offset == STATEMAP_NOMORECHANGES) /* end of atomic changes */ -+ { -+ if (!sgmt->Maps[clvl].InputMapValid || /* not set InputMap yet */ -+ statemap_changed (sgmt->Maps[clvl].CurrentInputMap)) /* previously applied changes */ -+ { -+ CPRINTF3 (4, "%s: received new clvl %d map from %d\n", cmRail->Rail->Name, clvl, sgmt->NodeId); -+ -+ statemap_setmap (sgmt->Maps[clvl].InputMap, sgmt->Maps[clvl].CurrentInputMap); -+ sgmt->Maps[clvl].InputMapValid = 1; -+ -+ statemap_clearchanges (sgmt->Maps[clvl].CurrentInputMap); -+ } -+ continue; -+ } -+ -+ seg = ((bitmap_t)map->seg[0]) -+ | (((bitmap_t)map->seg[1]) << 16) -+#if (BT_ULSHIFT == 6) -+ | (((bitmap_t)map->seg[2]) << 32) -+ | (((bitmap_t)map->seg[3]) << 48) -+#elif (BT_ULSHIFT != 5) -+#error "Bad value for BT_ULSHIFT" -+#endif -+ ; -+ statemap_setseg (sgmt->Maps[clvl].CurrentInputMap, map->offset, seg); -+ } -+ break; -+ -+ case CM_MSG_TYPE_REJOIN: -+ CPRINTF5 (1, "%s: lvl %d sidx %d node %d type %d: REJOIN\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type); -+ printk ("%s: lvl %d sidx %d node %d type %d: REJOIN\n", -+ cmRail->Rail->Name, lvl, sidx, hdr->NodeId, hdr->Type); -+ -+ LowerTopLevel (cmRail, 0); -+ -+ IncrStat (cmRail, RejoinRequest); -+ break; -+ -+ default: -+ printk ("%s: lvl=%d unknown message type %d\n", cmRail->Rail->Name, lvl, hdr->Type); -+ break; -+ } -+ finished: -+ hdr->Version = EP_SYSTEMQ_UNRECEIVED; -+} -+ -+static void -+PollInputQueues (CM_RAIL *cmRail) -+{ -+ ep_poll_inputq (cmRail->Rail, cmRail->IntrQueue, 0, ProcessMessage, cmRail); -+ ep_poll_inputq (cmRail->Rail, cmRail->PolledQueue, 0, ProcessMessage, cmRail); -+} -+ -+static void -+IntrQueueCallback (EP_RAIL *rail, void *arg) -+{ -+ CM_RAIL *cmRail = (CM_RAIL *) arg; -+ unsigned long flags; -+ -+ /* If the lock is held, then don't bother spinning for it, -+ * since the messages will be received at this, or the -+ * next heartbeat */ -+ local_irq_save (flags); -+ if (spin_trylock (&cmRail->Lock)) -+ { -+ if (AFTER (lbolt, cmRail->NextRunTime + MSEC2TICKS(CM_TIMER_SCHEDULE_TIMEOUT))) -+ printk ("%s: heartbeat timer stuck - scheduled\n", cmRail->Rail->Name); -+ else -+ ep_poll_inputq (rail, cmRail->IntrQueue, 0, ProcessMessage, cmRail); -+ spin_unlock (&cmRail->Lock); -+ } -+ local_irq_restore (flags); -+} -+ -+char * -+sprintClPeers (char *str, CM_RAIL *cmRail, int clvl) -+{ -+ int clLo = cmRail->Levels[clvl].MinNodeId; -+ int clHi = clLo + cmRail->Levels[clvl].NumNodes - 1; -+ int subClLo = (clvl == 0) ? cmRail->NodeId : cmRail->Levels[clvl - 1].MinNodeId; -+ int subClHi = subClLo + ((clvl == 0) ? 0 : cmRail->Levels[clvl - 1].NumNodes - 1); -+ -+ if (subClHi == clHi) -+ sprintf (str, "[%d-%d]", clLo, subClLo - 1); -+ else if (subClLo == clLo) -+ sprintf (str, "[%d-%d]", subClHi + 1, clHi); -+ else -+ sprintf (str, "[%d-%d][%d-%d]", clLo, subClLo - 1, subClHi + 1, clHi); -+ -+ return (str); -+} -+ -+static void -+RestartComms (CM_RAIL *cmRail, int clvl) -+{ -+ int base; -+ int nodeId; -+ int lstat; -+ int numClNodes; -+ int subClMin; -+ int subClMax; -+ int myClId; -+ int thisClId; -+ -+ myClId = ClusterIds (cmRail, clvl, &subClMin, &subClMax); -+ base = myClId * CM_GSTATUS_BITS; -+ numClNodes = cmRail->Levels[clvl].NumNodes; -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, -+ CM_GSTATUS_CLOSING | CM_GSTATUS_MAY_START | CM_GSTATUS_RESTART, CM_GSTATUS_BITS); -+ cmRail->Levels[clvl].Restarting = 1; -+ -+ if (cmRail->Levels[clvl].Online) -+ { -+ cmRail->Levels[clvl].Online = 0; -+ -+ for (thisClId = 0; thisClId < numClNodes; thisClId++) -+ { -+ if (thisClId == subClMin) /* skip sub-cluster; it's just someone in this cluster */ -+ { /* that wants me to restart */ -+ thisClId = subClMax; -+ continue; -+ } -+ -+ nodeId = cmRail->Levels[clvl].MinNodeId + thisClId; -+ base = thisClId * CM_GSTATUS_BITS; -+ lstat = statemap_getbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_BITS); -+ -+ if ((lstat & CM_GSTATUS_ACK_MASK) == CM_GSTATUS_MAY_RUN) -+ { -+ switch (ep_disconnect_node (cmRail->Rail, nodeId)) -+ { -+ case EP_NODE_CONNECTING: -+ /* gstat must == RUNNING */ -+ cmRail->Levels[clvl].Connected--; -+ break; -+ case EP_NODE_DISCONNECTED: -+ /* CLOSING || STARTING || (lstat & RESTART) */ -+ break; -+ } -+ } -+ } -+ } -+} -+ -+static void -+UpdateGlobalStatus (CM_RAIL *cmRail) -+{ -+ char clNodeStr[32]; /* [%d-%d][%d-%d] */ -+ int nodeId; -+ int offset; -+ int base; -+ bitmap_t gstat; -+ bitmap_t lgstat; -+ bitmap_t lstat; -+ int clvl; -+ int numClNodes; -+ int subClMin; -+ int subClMax; -+ int myClId; -+ int thisClId; -+ int lastClId; -+ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ { -+ if (!cmRail->Levels[clvl].GlobalMapValid || /* not got the global map yet */ -+ !statemap_changed (cmRail->Levels[clvl].GlobalMap)) /* no changes to respond to */ -+ { -+ CPRINTF2 (6, "%s: Got invalid or unchanged clvl %d global map\n", cmRail->Rail->Name, clvl); -+ continue; -+ } -+ -+ CPRINTF2 (5, "%s: Got valid changed clvl %d global map\n", cmRail->Rail->Name, clvl); -+ -+ lastClId = -1; -+ myClId = ClusterIds (cmRail, clvl, &subClMin, &subClMax); -+ numClNodes = cmRail->Levels[clvl].NumNodes; -+ -+ while ((offset = statemap_findchange (cmRail->Levels[clvl].GlobalMap, &gstat, 1)) >= 0) -+ { -+ /* -+ * Check every node that this segment covers - however -+ * if the last node we checked in the previous segmemt -+ * is also the first node in this segment, then skip -+ * it. -+ */ -+ if ((thisClId = (offset/CM_GSTATUS_BITS)) == lastClId) -+ thisClId++; -+ lastClId = (offset + BT_NBIPUL - 1)/CM_GSTATUS_BITS; -+ -+ /* check each node that might have changed */ -+ for ( ; thisClId <= lastClId && thisClId < numClNodes; thisClId++) -+ { -+ base = thisClId * CM_GSTATUS_BITS; -+ nodeId = cmRail->Levels[clvl].MinNodeId + thisClId; -+ -+ if (thisClId >= subClMin && thisClId <= subClMax) /* skip sub-cluster */ -+ continue; -+ -+ /* This isn't me; I need to sense what this node is driving -+ * (just the starting and running bits) and respond -+ * appropriately... -+ */ -+ lgstat = statemap_getbits (cmRail->Levels[clvl].LastGlobalMap, base, CM_GSTATUS_BITS) & CM_GSTATUS_STATUS_MASK; -+ gstat = statemap_getbits (cmRail->Levels[clvl].GlobalMap, base, CM_GSTATUS_BITS) & CM_GSTATUS_STATUS_MASK; -+ -+ if (lgstat == gstat) /* no change in peer state */ -+ continue; -+ -+ CPRINTF5 (3, "%s: Node %d: lgstat %s, gstat %s, lstat %s\n", cmRail->Rail->Name, nodeId, -+ GlobalStatusString (cmRail->Levels[clvl].LastGlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].GlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].LocalMap, thisClId)); -+ -+ /* What I'm currently driving as my acknowledgement */ -+ lstat = statemap_getbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_BITS); -+ -+ switch (gstat) -+ { -+ case CM_GSTATUS_STARTING: -+ if ((lgstat == CM_GSTATUS_ABSENT || lgstat == CM_GSTATUS_CLOSING) && lstat == CM_GSTATUS_MAY_START) -+ { -+ CPRINTF2 (1, "%s: ===================node %d STARTING\n", cmRail->Rail->Name, nodeId); -+ -+ ASSERT (cmRail->Rail->Nodes[nodeId].State == EP_NODE_DISCONNECTED); -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_MAY_RUN, CM_GSTATUS_BITS); -+ continue; -+ } -+ break; -+ -+ case CM_GSTATUS_RUNNING: -+ if ((lgstat == CM_GSTATUS_ABSENT && lstat == CM_GSTATUS_MAY_START) || -+ (lgstat == CM_GSTATUS_STARTING && lstat == CM_GSTATUS_MAY_RUN)) -+ { -+ CPRINTF3 (1, "%s: ===================node %d%s RUNNING\n", cmRail->Rail->Name, nodeId, -+ lgstat == CM_GSTATUS_ABSENT ? " Already" : ""); -+ -+ ASSERT (cmRail->Rail->Nodes[nodeId].State == EP_NODE_DISCONNECTED); -+ -+ if (cmRail->Levels[clvl].Online) -+ { -+ ep_connect_node (cmRail->Rail, nodeId); -+ -+ cmRail->Levels[clvl].Connected++; -+ } -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_MAY_RUN, CM_GSTATUS_BITS); -+ continue; -+ } -+ break; -+ -+ case CM_GSTATUS_CLOSING: -+ CPRINTF4 (1, "%s: ===================node %d CLOSING%s%s\n", cmRail->Rail->Name, nodeId, -+ (lstat & CM_GSTATUS_RESTART) ? " for Restart" : "", -+ cmRail->Levels[clvl].Online ? "" : " (offline)"); -+ -+ if ((lstat & CM_GSTATUS_ACK_MASK) == CM_GSTATUS_MAY_RUN) -+ { -+ switch (ep_disconnect_node (cmRail->Rail, nodeId)) -+ { -+ case EP_NODE_CONNECTING: -+ cmRail->Levels[clvl].Connected--; -+ /* DROPTHROUGH */ -+ case EP_NODE_DISCONNECTED: -+ lstat = CM_GSTATUS_MAY_START; -+ break; -+ } -+ } -+ -+ if ((lstat & CM_GSTATUS_ACK_MASK) == CM_GSTATUS_MAY_START) /* clear restart if we've disconnected */ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_MAY_START, CM_GSTATUS_BITS); -+ continue; -+ -+ default: -+ break; -+ } -+ -+ /* "unexpected" state change forces me to ask her to restart */ -+ if (! (lstat & CM_GSTATUS_RESTART)) /* not requesting restart already */ -+ { -+ CPRINTF5 (1, "%s: ===================node %d %s, old %s new %s\n", cmRail->Rail->Name, nodeId, -+ (gstat == CM_GSTATUS_ABSENT) ? "ABSENT" : "REQUEST RESTART", -+ GlobalStatusString (cmRail->Levels[clvl].LastGlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].GlobalMap, thisClId)); -+ -+ /* request restart */ -+ if (cmRail->Levels[clvl].Online && lstat == CM_GSTATUS_MAY_RUN) -+ { -+ switch (ep_disconnect_node (cmRail->Rail, nodeId)) -+ { -+ case EP_NODE_CONNECTING: -+ cmRail->Levels[clvl].Connected--; -+ /* DROPTHROUGH */ -+ case EP_NODE_DISCONNECTED: -+ lstat = CM_GSTATUS_MAY_START; -+ break; -+ } -+ } -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, lstat | CM_GSTATUS_RESTART, CM_GSTATUS_BITS); -+ continue; -+ } -+ -+ continue; -+ } -+ } -+ -+ /* Now check myself - see what everyone else thinks I'm doing */ -+ base = myClId * CM_GSTATUS_BITS; -+ lstat = statemap_getbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_BITS); -+ gstat = statemap_getbits (cmRail->Levels[clvl].GlobalMap, base, CM_GSTATUS_BITS); -+ lgstat = statemap_getbits (cmRail->Levels[clvl].LastGlobalMap, base, CM_GSTATUS_BITS); -+ -+ if (lgstat == gstat) /* my state in this cluster hasn't changed */ -+ { -+ CPRINTF3 (6, "%s: my clvl %d global status unchanged from %s\n", cmRail->Rail->Name, -+ clvl, GlobalStatusString (cmRail->Levels[clvl].GlobalMap, myClId)); -+ goto all_done; -+ } -+ -+ if ((gstat & CM_GSTATUS_RESTART) != 0) /* someone wants me to restart */ -+ { -+ if ((lstat & CM_GSTATUS_STATUS_MASK) == CM_GSTATUS_CLOSING) /* I'm already restarting */ -+ goto all_done; -+ -+ CPRINTF2 (1, "%s: ===================RESTART REQUEST from %s\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ printk ("%s: Restart Request from %s\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ RestartComms (cmRail, clvl); -+ goto all_done; -+ } -+ -+ CPRINTF6 (5, "%s: clvl %d: lgstat %s gstat %s, lstat %s%s\n", cmRail->Rail->Name, clvl, -+ GlobalStatusString (cmRail->Levels[clvl].LastGlobalMap, myClId), -+ GlobalStatusString (cmRail->Levels[clvl].GlobalMap, myClId), -+ GlobalStatusString (cmRail->Levels[clvl].LocalMap, myClId), -+ (gstat != lstat) ? " (IGNORED)" : ""); -+ -+ if (gstat != lstat) /* not everyone agrees with me */ -+ goto all_done; -+ -+ switch (lstat) -+ { -+ default: -+ ASSERT (0); /* I never drive this */ -+ -+ case CM_GSTATUS_CLOSING | CM_GSTATUS_MAY_START: /* I can restart now (have seen restart go away) */ -+ ASSERT (!cmRail->Levels[clvl].Online); -+ -+ CPRINTF2 (1,"%s: ===================NODES %s AGREE I MAY START\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ printk ("%s: ===================NODES %s AGREE I MAY START\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, -+ CM_GSTATUS_STARTING | CM_GSTATUS_MAY_RUN, CM_GSTATUS_BITS); -+ goto all_done; -+ -+ case CM_GSTATUS_STARTING | CM_GSTATUS_MAY_RUN: -+ ASSERT (!cmRail->Levels[clvl].Online); -+ -+ CPRINTF2 (1, "%s: ===================NODES %s AGREE I MAY RUN\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ printk ("%s: ===================NODES %s AGREE I MAY RUN\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, -+ CM_GSTATUS_RUNNING | CM_GSTATUS_MAY_RUN, CM_GSTATUS_BITS); -+ goto all_done; -+ -+ case CM_GSTATUS_RUNNING | CM_GSTATUS_MAY_RUN: -+ if (! cmRail->Levels[clvl].Online) -+ { -+ CPRINTF2 (1, "%s: ===================NODES %s AGREE I'M RUNNING\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ printk ("%s: ===================NODES %s AGREE I'M RUNNING\n", cmRail->Rail->Name, -+ sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ cmRail->Levels[clvl].Online = 1; -+ -+ for (thisClId = 0; thisClId < numClNodes; thisClId++) -+ { -+ if (thisClId == subClMin) /* skip sub-cluster */ -+ { -+ thisClId = subClMax; -+ continue; -+ } -+ -+ nodeId = cmRail->Levels[clvl].MinNodeId + thisClId; -+ -+ base = thisClId * CM_GSTATUS_BITS; -+ lstat = statemap_getbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_BITS); -+ gstat = statemap_getbits (cmRail->Levels[clvl].GlobalMap, base, CM_GSTATUS_BITS) & CM_GSTATUS_STATUS_MASK; -+ -+ /* Only connect to her if I see her as running and I'm not requesting her -+ * to restart - this means that I was offline when I saw her transition -+ * to running and haven't seen her in a "bad" state since. */ -+ if (gstat == CM_GSTATUS_RUNNING && ! (lstat & CM_GSTATUS_RESTART)) -+ { -+ CPRINTF5 (1, "%s: node %d lgstat %s gstat %s, lstat %s -> CONNECT\n", cmRail->Rail->Name, nodeId, -+ GlobalStatusString (cmRail->Levels[clvl].LastGlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].GlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].LocalMap, thisClId)); -+ -+ if (lstat == CM_GSTATUS_MAY_START) -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_MAY_RUN, CM_GSTATUS_BITS); -+ -+ ep_connect_node (cmRail->Rail, nodeId); -+ -+ cmRail->Levels[clvl].Connected++; -+ } -+ } -+ } -+ goto all_done; -+ } -+ -+ all_done: -+ statemap_setmap (cmRail->Levels[clvl].LastGlobalMap, cmRail->Levels[clvl].GlobalMap); -+ } -+} -+ -+static void -+ReduceGlobalMap (CM_RAIL *cmRail, int clvl) -+{ -+ int lvl; -+ int sidx; -+ int recompute; -+ CM_LEVEL *level; -+ int cTopLevel; -+ int cRole; -+ -+ if (clvl < cmRail->TopLevel) -+ { -+ cTopLevel = clvl + 1; -+ cRole = CM_ROLE_LEADER; -+ } -+ else -+ { -+ cTopLevel = cmRail->TopLevel; -+ cRole = cmRail->Role; -+ } -+ -+ /* Update cmRail->Levels[*].SubordinateMap[clvl] for all subordinate levels */ -+ for (lvl = 0; lvl < cTopLevel; lvl++) -+ { -+ level = &cmRail->Levels[lvl]; -+ -+ /* We need to recompute this level's statemap if... -+ * . Previous level's statemap has changes to propagate OR -+ * . This level's statemap has not been computed yet OR -+ * . A subordinate at this level has sent me a change. -+ * Note that we can only do this if all subordinates from this -+ * level down are present with valid statemaps, or absent (i.e. not -+ * timing out). -+ */ -+ -+ ASSERT (lvl == 0 || cmRail->Levels[lvl - 1].SubordinateMapValid[clvl]); -+ -+ recompute = !level->SubordinateMapValid[clvl] || -+ (lvl > 0 && statemap_changed (cmRail->Levels[lvl - 1].SubordinateMap[clvl])); -+ -+ for (sidx = 0; sidx < level->NumSegs; sidx++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[sidx]; -+ -+ if (!(sgmt->State == CM_SGMT_ABSENT || /* absent nodes contribute zeros */ -+ (sgmt->State == CM_SGMT_PRESENT && /* present nodes MUST have received a map to contribute */ -+ sgmt->Maps[clvl].InputMapValid))) -+ { -+ CPRINTF5 (5, "%s: waiting for clvl %d lvl %d seg %d node %d\n", cmRail->Rail->Name, -+ clvl, lvl, sidx, sgmt->NodeId); -+ -+ /* Gotta wait for this guy, so we can't compute this level, -+ * or any higher levels. */ -+ return; -+ } -+ -+ if (statemap_changed (sgmt->Maps[clvl].InputMap)) -+ { -+ ASSERT (sgmt->Maps[clvl].InputMapValid); -+ -+ recompute = 1; -+ -+ CPRINTF7 (5, "%s: %s clvl %d map from @ %d %d (%d) - %s\n", -+ cmRail->Rail->Name, sgmt->State == CM_SGMT_ABSENT ? "newly absent" : "got new", -+ clvl, lvl, sidx, sgmt->NodeId, -+ MapString ("Input", sgmt->Maps[clvl].InputMap, cmRail->Levels[clvl].NumNodes, "")); -+ } -+ } -+ -+ if (recompute) -+ { -+ if (lvl == 0) -+ statemap_reset (cmRail->Levels[clvl].TmpMap); -+ else -+ { -+ ASSERT (cmRail->Levels[lvl - 1].SubordinateMapValid[clvl]); -+ -+ statemap_copy (cmRail->Levels[clvl].TmpMap, cmRail->Levels[lvl - 1].SubordinateMap[clvl]); -+ statemap_clearchanges (cmRail->Levels[lvl - 1].SubordinateMap[clvl]); -+ } -+ -+ for (sidx = 0; sidx < level->NumSegs; sidx++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[sidx]; -+ -+ if (sgmt->State != CM_SGMT_ABSENT) /* absent nodes contribute zeroes */ -+ { -+ ASSERT (sgmt->State == CM_SGMT_PRESENT); -+ ASSERT (sgmt->Maps[clvl].InputMapValid); -+ statemap_ormap (cmRail->Levels[clvl].TmpMap, sgmt->Maps[clvl].InputMap); -+ } -+ statemap_clearchanges (sgmt->Maps[clvl].InputMap); -+ } -+ -+ statemap_setmap (level->SubordinateMap[clvl], cmRail->Levels[clvl].TmpMap); -+ level->SubordinateMapValid[clvl] = 1; -+ -+ CPRINTF4 (5, "%s: recompute clvl %d level %d statemap - %s\n", cmRail->Rail->Name, clvl, lvl, -+ MapString ("level", level->SubordinateMap[clvl], cmRail->Levels[clvl].NumNodes, "")); -+ } -+ } -+ -+ if (cRole == CM_ROLE_LEADER_CANDIDATE) /* don't know this cluster's leader yet */ -+ return; -+ -+ ASSERT (cTopLevel == 0 || cmRail->Levels[cTopLevel - 1].SubordinateMapValid[clvl]); -+ -+ /* Update SubTreeMap */ -+ -+ if (!cmRail->Levels[clvl].SubTreeMapValid || -+ statemap_changed (cmRail->Levels[clvl].LocalMap) || -+ (cTopLevel > 0 && statemap_changed (cmRail->Levels[cTopLevel - 1].SubordinateMap[clvl]))) -+ { -+ statemap_copy (cmRail->Levels[clvl].TmpMap, cmRail->Levels[clvl].LocalMap); -+ statemap_clearchanges (cmRail->Levels[clvl].LocalMap); -+ -+ if (cTopLevel > 0) -+ { -+ statemap_ormap (cmRail->Levels[clvl].TmpMap, cmRail->Levels[cTopLevel - 1].SubordinateMap[clvl]); -+ statemap_clearchanges (cmRail->Levels[cTopLevel - 1].SubordinateMap[clvl]); -+ } -+ -+ statemap_setmap (cmRail->Levels[clvl].SubTreeMap, cmRail->Levels[clvl].TmpMap); -+ cmRail->Levels[clvl].SubTreeMapValid = 1; -+ -+ CPRINTF3 (5, "%s: recompute clvl %d subtree map - %s\n", cmRail->Rail->Name, clvl, -+ MapString ("subtree", cmRail->Levels[clvl].SubTreeMap, cmRail->Levels[clvl].NumNodes, "")); -+ } -+ -+ if (cRole == CM_ROLE_SUBORDINATE) /* got a leader (Not me) */ -+ { /* => send SubTreeMap to her */ -+ CM_SGMT *leader = &cmRail->Levels[cmRail->TopLevel].Sgmts[0]; -+ -+ ASSERT (leader->State == CM_SGMT_PRESENT); -+ ASSERT (cmRail->Levels[clvl].SubTreeMapValid); -+ -+ if (!leader->Maps[clvl].OutputMapValid || -+ statemap_changed (cmRail->Levels[clvl].SubTreeMap)) -+ { -+ statemap_setmap (leader->Maps[clvl].OutputMap, cmRail->Levels[clvl].SubTreeMap); -+ leader->Maps[clvl].OutputMapValid = 1; -+ -+ statemap_clearchanges (cmRail->Levels[clvl].SubTreeMap); -+ -+ CPRINTF3 (5, "%s: sending clvl %d subtree map to leader (%d)\n", cmRail->Rail->Name, clvl, leader->NodeId); -+ } -+ } -+} -+ -+void -+BroadcastGlobalMap (CM_RAIL *cmRail, int clvl) -+{ -+ int lvl; -+ int sidx; -+ CM_LEVEL *level; -+ CM_SGMT *leader; -+ int cTopLevel; -+ int cRole; -+ -+ if (clvl < cmRail->TopLevel) -+ { -+ cTopLevel = clvl + 1; -+ cRole = CM_ROLE_LEADER; -+ } -+ else -+ { -+ cTopLevel = cmRail->TopLevel; -+ cRole = cmRail->Role; -+ } -+ -+ switch (cRole) -+ { -+ default: -+ ASSERT (0); -+ -+ case CM_ROLE_LEADER_CANDIDATE: /* don't know this cluster's leader yet */ -+ return; -+ -+ case CM_ROLE_LEADER: /* cluster leader: */ -+ ASSERT (clvl < cmRail->TopLevel); /* set GlobalMap from SubTreeMap */ -+ -+ if (!cmRail->Levels[clvl].SubTreeMapValid) /* can't set global map */ -+ return; -+ -+ if (cmRail->Levels[clvl].GlobalMapValid && /* already set global map */ -+ !statemap_changed (cmRail->Levels[clvl].SubTreeMap)) /* no changes to propagate */ -+ return; -+ -+ statemap_setmap (cmRail->Levels[clvl].GlobalMap, cmRail->Levels[clvl].SubTreeMap); -+ cmRail->Levels[clvl].GlobalMapValid = 1; -+ statemap_clearchanges (cmRail->Levels[clvl].SubTreeMap); -+ -+ CPRINTF2 (5, "%s: whole cluster %d leader setting global map\n", cmRail->Rail->Name, clvl); -+ -+ UpdateGlobalStatus (cmRail); -+ break; -+ -+ case CM_ROLE_SUBORDINATE: /* cluster subordinate: */ -+ ASSERT (clvl >= cmRail->TopLevel); /* receive GlobalMap from leader */ -+ ASSERT (cmRail->TopLevel < cmRail->NumLevels); -+ -+ leader = &cmRail->Levels[cmRail->TopLevel].Sgmts[0]; -+ ASSERT (leader->State == CM_SGMT_PRESENT); -+ -+ if (!leader->Maps[clvl].InputMapValid) /* can't set global map */ -+ return; -+ -+ if (cmRail->Levels[clvl].GlobalMapValid && /* already set global map */ -+ !statemap_changed (leader->Maps[clvl].InputMap)) /* no changes to propagate */ -+ return; -+ -+ statemap_setmap (cmRail->Levels[clvl].GlobalMap, leader->Maps[clvl].InputMap); -+ cmRail->Levels[clvl].GlobalMapValid = 1; -+ statemap_clearchanges (leader->Maps[clvl].InputMap); -+ -+ CPRINTF3 (5, "%s: getting clvl %d global map from leader (%d)\n", cmRail->Rail->Name, clvl, leader->NodeId); -+ -+ UpdateGlobalStatus (cmRail); -+ break; -+ } -+ -+ CPRINTF3 (5, "%s: clvl %d %s\n", cmRail->Rail->Name, clvl, -+ MapString ("global", cmRail->Levels[clvl].GlobalMap, cmRail->Levels[clvl].NumNodes, "")); -+ -+ /* Broadcast global map to all subordinates */ -+ for (lvl = 0; lvl < cTopLevel; lvl++) -+ { -+ level = &cmRail->Levels[lvl]; -+ -+ for (sidx = 0; sidx < level->NumSegs; sidx++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[sidx]; -+ -+ if (sgmt->State == CM_SGMT_PRESENT) -+ { -+ statemap_setmap (sgmt->Maps[clvl].OutputMap, cmRail->Levels[clvl].GlobalMap); -+ sgmt->Maps[clvl].OutputMapValid = 1; -+ -+ CPRINTF5 (5, "%s: sending clvl %d global map to subordinate %d %d (%d)\n", -+ cmRail->Rail->Name, clvl, lvl, sidx, sgmt->NodeId); -+ } -+ } -+ } -+} -+ -+static void -+CheckPeerPulse (CM_RAIL *cmRail, CM_SGMT *sgmt) -+{ -+ int clvl, sendRejoin; -+ -+ switch (sgmt->State) -+ { -+ case CM_SGMT_ABSENT: -+ break; -+ -+ case CM_SGMT_WAITING: /* waiting for a subtree */ -+ if (!AFTER (lbolt, sgmt->UpdateTick + MSEC2TICKS(CM_DISCOVER_TIMEOUT))) -+ break; -+ -+ CPRINTF3 (2, "%s: lvl %d subtree %d contains no live nodes\n", cmRail->Rail->Name, -+ sgmt->Level, (int) (sgmt - &cmRail->Levels[sgmt->Level].Sgmts[0])); -+ -+ sgmt->State = CM_SGMT_ABSENT; -+ for (clvl = sgmt->Level; clvl < cmRail->NumLevels; clvl++) -+ { -+ statemap_zero (sgmt->Maps[clvl].InputMap); /* need to start propagating zeros (flags change) */ -+ sgmt->Maps[clvl].InputMapValid = 1; /* and must indicate that the map is now valid */ -+ } -+ break; -+ -+ case CM_SGMT_COMING: /* lost/waiting subtree sent me IMCOMING */ -+ ASSERT (sgmt->Level > 0); /* we only do subtree discovery below our own level */ -+ -+ if (AFTER (lbolt, sgmt->WaitingTick + MSEC2TICKS(CM_WAITING_TIMEOUT))) -+ { -+ CPRINTF3 (1, "%s: lvl %d subtree %d waiting too long\n", cmRail->Rail->Name, -+ sgmt->Level, (int) (sgmt - &cmRail->Levels[sgmt->Level].Sgmts[0])); -+ printk ("%s: lvl %d subtree %d waiting too long\n", cmRail->Rail->Name, -+ sgmt->Level, (int) (sgmt - &cmRail->Levels[sgmt->Level].Sgmts[0])); -+ -+ sgmt->State = CM_SGMT_ABSENT; -+ for (clvl = sgmt->Level; clvl < cmRail->NumLevels; clvl++) -+ { -+ statemap_zero (sgmt->Maps[clvl].InputMap); /* need to start propagating zeros (flags change) */ -+ sgmt->Maps[clvl].InputMapValid = 1; /* and must indicate that the map is now valid */ -+ } -+ break; -+ } -+ -+ if (!AFTER (lbolt, sgmt->UpdateTick + MSEC2TICKS(CM_DISCOVER_TIMEOUT))) -+ break; -+ -+ CPRINTF3 (2, "%s: lvl %d subtree %d hasn't connected yet\n", cmRail->Rail->Name, -+ sgmt->Level, (int) (sgmt - &cmRail->Levels[sgmt->Level].Sgmts[0])); -+ -+ sgmt->State = CM_SGMT_WAITING; -+ sgmt->UpdateTick = lbolt; -+ -+ if (sgmt->Level > 0) -+ __Schedule_Discovery (cmRail); -+ break; -+ -+ case CM_SGMT_PRESENT: -+ if (!AFTER (lbolt, sgmt->UpdateTick + MSEC2TICKS(CM_HEARTBEAT_TIMEOUT))) -+ break; -+ -+ if (sgmt->Level == cmRail->TopLevel) /* leader died */ -+ { -+ sendRejoin = (sgmt->State == CM_SGMT_PRESENT && sgmt->AckSeq == 0); -+ -+ CPRINTF4 (1, "%s: leader (%d) node %d JUST DIED%s\n", -+ cmRail->Rail->Name, sgmt->Level, sgmt->NodeId, -+ sendRejoin ? ": !REJOIN" : ""); -+ -+ printk ("%s: lvl %d leader (%d) JUST DIED%s\n", -+ cmRail->Rail->Name, sgmt->Level, sgmt->NodeId, -+ sendRejoin ? ": !REJOIN" : ""); -+ -+ if (sendRejoin) -+ { -+ /* she's not sent us any heartbeats even though she responded to a discover -+ * so tell her to rejoin the tree at the bottom, this will mean that she -+ * has to run the heartbeat timer before being able to rejoin the tree. */ -+ SendMessage (cmRail, sgmt->NodeId, sgmt->Level, CM_MSG_TYPE_REJOIN); -+ } -+ -+ StartLeaderDiscovery (cmRail); -+ break; -+ } -+ -+ sendRejoin = (sgmt->State == CM_SGMT_PRESENT && sgmt->AckSeq == 0); -+ -+ CPRINTF5 (2, "%s: lvl %d subordinate %d (%d) JUST DIED%s\n", cmRail->Rail->Name, -+ sgmt->Level, (int) (sgmt - &cmRail->Levels[sgmt->Level].Sgmts[0]), sgmt->NodeId, -+ sendRejoin ? ": !REJOIN" : ""); -+ printk ("%s: lvl %d subordinate %d (%d) JUST DIED%s\n", cmRail->Rail->Name, -+ sgmt->Level, (int) (sgmt - &cmRail->Levels[sgmt->Level].Sgmts[0]), sgmt->NodeId, -+ sendRejoin ? ": !REJOIN" : ""); -+ -+ if (sendRejoin) -+ { -+ /* she's not sent us any heartbeats even though she responded to a discover -+ * so tell her to rejoin the tree at the bottom, this will mean that she -+ * has to run the heartbeat timer before being able to rejoin the tree. */ -+ SendMessage (cmRail, sgmt->NodeId, sgmt->Level, CM_MSG_TYPE_REJOIN); -+ } -+ -+ StartSubTreeDiscovery (cmRail, sgmt); -+ break; -+ -+ default: -+ ASSERT (0); -+ } -+} -+ -+static void -+CheckPeerPulses (CM_RAIL *cmRail) -+{ -+ int lvl; -+ int sidx; -+ -+ /* check children are alive */ -+ for (lvl = 0; lvl < cmRail->TopLevel; lvl++) -+ for (sidx = 0; sidx < cmRail->Levels[lvl].NumSegs; sidx++) -+ CheckPeerPulse (cmRail, &cmRail->Levels[lvl].Sgmts[sidx]); -+ -+ /* check leader is alive */ -+ if (cmRail->Role == CM_ROLE_SUBORDINATE) -+ { -+ ASSERT (cmRail->TopLevel < cmRail->NumLevels); -+ ASSERT (cmRail->Levels[cmRail->TopLevel].Sgmts[0].State == CM_SGMT_PRESENT); -+ -+ CheckPeerPulse (cmRail, &cmRail->Levels[cmRail->TopLevel].Sgmts[0]); -+ } -+} -+ -+static void -+SendHeartbeats (CM_RAIL *cmRail) -+{ -+ int lvl; -+ -+ /* Send heartbeats to my children */ -+ for (lvl = 0; lvl < cmRail->TopLevel; lvl++) -+ { -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ int sidx; -+ -+ for (sidx = 0; sidx < level->NumSegs; sidx++) -+ { -+ CM_SGMT *sgmt = &cmRail->Levels[lvl].Sgmts[sidx]; -+ -+ if (sgmt->State == CM_SGMT_PRESENT) -+ SendToSgmt (cmRail, sgmt, CM_MSG_TYPE_HEARTBEAT); -+ } -+ } -+ -+ /* Send heartbeat to my leader */ -+ if (cmRail->Role == CM_ROLE_SUBORDINATE) -+ { -+ ASSERT (cmRail->TopLevel < cmRail->NumLevels); -+ SendToSgmt (cmRail, &cmRail->Levels[cmRail->TopLevel].Sgmts[0], CM_MSG_TYPE_HEARTBEAT); -+ } -+} -+ -+static int -+BroadcastDiscover (CM_RAIL *cmRail) -+{ -+ int sidx; -+ int lvl; -+ int msgType; -+ CM_LEVEL *level; -+ int urgent; -+ -+ ASSERT (cmRail->TopLevel <= cmRail->NumLevels); -+ ASSERT ((cmRail->Role == CM_ROLE_LEADER) ? (cmRail->TopLevel == cmRail->NumLevels) : -+ (cmRail->Role == CM_ROLE_SUBORDINATE) ? (cmRail->Levels[cmRail->TopLevel].Sgmts[0].State == CM_SGMT_PRESENT) : -+ (cmRail->Role == CM_ROLE_LEADER_CANDIDATE)); -+ -+ if (cmRail->Role != CM_ROLE_LEADER_CANDIDATE) /* got a leader/lead whole machine */ -+ { -+ urgent = 0; /* non-urgent leader discovery */ -+ lvl = cmRail->TopLevel - 1; /* on nodes I lead (resolves leader conflicts) */ -+ msgType = CM_MSG_TYPE_RESOLVE_LEADER; -+ } -+ else -+ { -+ urgent = 1; /* urgent leader discovery */ -+ lvl = cmRail->TopLevel; /* on nodes I'd like to lead */ -+ msgType = CM_MSG_TYPE_DISCOVER_LEADER; -+ } -+ -+ if (lvl >= 0) -+ { -+ if (lvl > cmRail->BroadcastLevel) -+ { -+ /* Unable to broadcast at this level in the spanning tree, so we -+ * just continue doing discovery until we are able to broadcast */ -+ CPRINTF4 (6, "%s: broadcast level %d too low to discover %d at level %d\n", -+ cmRail->Rail->Name, cmRail->BroadcastLevel, msgType, lvl); -+ -+ cmRail->DiscoverStartTick = lbolt; -+ } -+ else -+ { -+ level = &cmRail->Levels[lvl]; -+ SendToSgmt (cmRail, &level->Sgmts[level->MySgmt], msgType); -+ } -+ } -+ -+ while (lvl > 0) -+ { -+ level = &cmRail->Levels[lvl]; -+ -+ for (sidx = 0; sidx < level->NumSegs; sidx++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[sidx]; -+ -+ if (sgmt->State == CM_SGMT_WAITING) -+ { -+ ASSERT (sidx != level->MySgmt); -+ /* Do subordinate discovery. Existing subordinates will -+ * ignore it, but leader candidates will send IMCOMING. -+ * This is always urgent since we'll assume a subtree is -+ * absent if I don't get IMCOMING within the timeout. -+ */ -+ SendToSgmt (cmRail, sgmt, CM_MSG_TYPE_DISCOVER_SUBORDINATE); -+ urgent = 1; -+ } -+ } -+ lvl--; -+ } -+ -+ return (urgent); -+} -+ -+static void -+CheckBroadcast (CM_RAIL *cmRail) -+{ -+ int clvl; -+ -+ for (clvl = cmRail->NumLevels-1; clvl >= 0 && cmRail->Rail->SwitchBroadcastLevel < cmRail->Levels[clvl].SwitchLevel; clvl--) -+ ; -+ -+ if (cmRail->OfflineReasons || cmRail->Rail->System->Shutdown) -+ clvl = -1; -+ -+ /* if the level at which we can broadcast drops, then we must rejoin the -+ * spanning tree at the highest level for which broadcast is good. */ -+ if (cmRail->BroadcastLevel > clvl && clvl < (int)(cmRail->Role == CM_ROLE_LEADER ? cmRail->TopLevel - 1 : cmRail->TopLevel)) -+ { -+ printk ("%s: REJOINING at level %d because %s\n", cmRail->Rail->Name, clvl+1, -+ (cmRail->OfflineReasons & CM_OFFLINE_MANAGER) ? "of manager thread" : -+ (cmRail->OfflineReasons & CM_OFFLINE_PROCFS) ? "force offline" : -+ cmRail->Rail->System->Shutdown ? "system shutdown" : "broadcast level changed"); -+ LowerTopLevel (cmRail, clvl+1); -+ } -+ -+ if (cmRail->BroadcastLevel != clvl) -+ { -+ cmRail->BroadcastLevel = clvl; -+ cmRail->BroadcastLevelTick = lbolt; -+ } -+ -+ /* schedule the update thread, to withdraw from comms with -+ * nodes "outside" of the valid broadcastable range. */ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ { -+ if (cmRail->BroadcastLevel < clvl) -+ { -+ if (AFTER (lbolt, cmRail->BroadcastLevelTick + EP_WITHDRAW_TIMEOUT) && -+ !(cmRail->Levels[clvl].OfflineReasons & CM_OFFLINE_BROADCAST)) -+ { -+ printk ("%s: Withdraw at Level %d\n", cmRail->Rail->Name, clvl); -+ cmRail->Levels[clvl].OfflineReasons |= CM_OFFLINE_BROADCAST; -+ } -+ } -+ else -+ { -+ if (cmRail->Levels[clvl].OfflineReasons & CM_OFFLINE_BROADCAST) -+ { -+ printk ("%s: Rejoin at Level %d\n", cmRail->Rail->Name, clvl); -+ cmRail->Levels[clvl].OfflineReasons &= ~CM_OFFLINE_BROADCAST; -+ } -+ } -+ } -+ -+} -+ -+static void -+CheckManager (CM_RAIL *cmRail) -+{ -+ long time, state = ep_kthread_state (&cmRail->Rail->System->ManagerThread, &time); -+ -+ if (state == KT_STATE_RUNNING && BEFORE (lbolt, time + MSEC2TICKS(CM_THREAD_RUNNING_TIMEOUT))) -+ state = KT_STATE_SLEEPING; -+ if (state != KT_STATE_SLEEPING && BEFORE (lbolt, time + MSEC2TICKS(CM_THREAD_SCHEDULE_TIMEOUT))) -+ state = KT_STATE_SLEEPING; -+ -+ if ((cmRail->OfflineReasons & CM_OFFLINE_MANAGER) && state == KT_STATE_SLEEPING) -+ { -+ printk ("%s: manager thread unstuck\n", cmRail->Rail->Name); -+ -+ cmRail->OfflineReasons &= ~CM_OFFLINE_MANAGER; -+ } -+ -+ if (!(cmRail->OfflineReasons & CM_OFFLINE_MANAGER) && state != KT_STATE_SLEEPING) -+ { -+ printk ("%s: manager thread stuck - %s\n", cmRail->Rail->Name, -+ state == KT_STATE_SCHEDULED ? "scheduled" : -+ state == KT_STATE_RUNNING ? "running" : -+ state == KT_STATE_STALLED ? "stalled" : "unknown"); -+ -+ cmRail->OfflineReasons |= CM_OFFLINE_MANAGER; -+ } -+} -+ -+static void -+CheckOfflineReasons (CM_RAIL *cmRail, int clvl) -+{ -+ int subClMin, subClMax, myClId; -+ char clNodeStr[32]; /* [%d-%d][%d-%d] */ -+ -+ if (cmRail->Levels[clvl].OfflineReasons) -+ { -+ if (cmRail->Levels[clvl].Online) -+ { -+ printk ("%s: Withdraw from %s\n", cmRail->Rail->Name, sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ RestartComms (cmRail, clvl); -+ } -+ } -+ else -+ { -+ if (cmRail->Levels[clvl].Restarting && cmRail->Levels[clvl].Connected == 0) -+ { -+ printk ("%s: Rejoin with %s\n", cmRail->Rail->Name, sprintClPeers (clNodeStr, cmRail, clvl)); -+ -+ myClId = ClusterIds (cmRail, clvl, &subClMin, &subClMax); -+ -+ ASSERT (statemap_getbits (cmRail->Levels[clvl].LocalMap, myClId * CM_GSTATUS_BITS, CM_GSTATUS_BITS) == -+ (CM_GSTATUS_CLOSING | CM_GSTATUS_MAY_START | CM_GSTATUS_RESTART)); -+ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, myClId * CM_GSTATUS_BITS, -+ CM_GSTATUS_CLOSING | CM_GSTATUS_MAY_START, CM_GSTATUS_BITS); -+ -+ cmRail->Levels[clvl].Restarting = 0; -+ } -+ } -+} -+ -+void -+DoHeartbeatWork (CM_RAIL *cmRail) -+{ -+ long now = lbolt; -+ int clvl; -+ -+ if ((RejoinCheck || RejoinPanic) && -+ AFTER (now, cmRail->NextRunTime + MSEC2TICKS (CM_TIMER_SCHEDULE_TIMEOUT))) /* If I've been unresponsive for too long */ -+ { -+ /* I'd better reconnect to the network because I've not been playing the game */ -+ CPRINTF4 (1, "%s: REJOINING because I was too slow (heartbeat) [%ld,%ld,(%ld)]\n", cmRail->Rail->Name, now, cmRail->NextRunTime, (long int)MSEC2TICKS (CM_TIMER_SCHEDULE_TIMEOUT)); -+ printk ("%s: REJOINING because I was too slow (heartbeat) [%ld,%ld,(%ld)]\n", cmRail->Rail->Name, now, cmRail->NextRunTime, (long int)MSEC2TICKS (CM_TIMER_SCHEDULE_TIMEOUT)); -+ -+ LowerTopLevel (cmRail, 0); -+ -+ IncrStat (cmRail, RejoinTooSlow); -+ -+ if (RejoinPanic) -+ panic ("ep: REJOINING because I was too slow (heartbeat)\n"); -+ } -+ -+ PollInputQueues (cmRail); -+ -+ if (cmRail->NextDiscoverTime && ! BEFORE (now, cmRail->NextDiscoverTime)) -+ { -+ if (BroadcastDiscover (cmRail)) /* urgent discovery required? */ -+ cmRail->NextDiscoverTime = now + MSEC2TICKS (CM_URGENT_DISCOVER_INTERVAL); -+ else -+ cmRail->NextDiscoverTime = now + MSEC2TICKS (CM_PERIODIC_DISCOVER_INTERVAL); -+ -+ if (cmRail->Role == CM_ROLE_LEADER_CANDIDATE && AFTER (now, cmRail->DiscoverStartTick + MSEC2TICKS (CM_DISCOVER_TIMEOUT))) -+ RaiseTopLevel (cmRail); -+ } -+ -+ if (cmRail->NextHeartbeatTime && ! BEFORE (now, cmRail->NextHeartbeatTime)) -+ { -+ CheckPosition (cmRail->Rail); -+ CheckPeerPulses (cmRail); -+ CheckBroadcast (cmRail); -+ CheckManager (cmRail); -+ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ { -+ CheckOfflineReasons (cmRail, clvl); -+ ReduceGlobalMap (cmRail, clvl); -+ BroadcastGlobalMap (cmRail, clvl); -+ } -+ -+ SendHeartbeats (cmRail); -+ -+ /* Compute the next heartbeat time, but "drift" it towards the last -+ * periodic discovery time we saw from the whole machine leader */ -+ cmRail->NextHeartbeatTime = now + MSEC2TICKS (CM_HEARTBEAT_INTERVAL); -+ } -+ -+ if (cmRail->NextDiscoverTime && AFTER (cmRail->NextHeartbeatTime, cmRail->NextDiscoverTime)) -+ cmRail->NextRunTime = cmRail->NextDiscoverTime; -+ else -+ cmRail->NextRunTime = cmRail->NextHeartbeatTime; -+} -+ -+#define CM_SVC_INDICATOR_OFFSET(CMRAIL,CLVL,IND,NODEID) ( ( CMRAIL->Levels[CLVL].NumNodes * CM_GSTATUS_BITS ) \ -+ + ( CMRAIL->Levels[CLVL].NumNodes * IND ) \ -+ + ( NODEID - CMRAIL->Levels[CLVL].MinNodeId ) ) -+int -+cm_svc_indicator_set (EP_RAIL *rail, int svc_indicator) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ int clvl; -+ -+ EPRINTF2 (DBG_SVC,"cm_svc_indicator_set: rail %p ind %d\n", rail, svc_indicator); -+ -+ if (svc_indicator < 0 || svc_indicator >= EP_SVC_NUM_INDICATORS) -+ { -+ EPRINTF1 (DBG_SVC,"cm_svc_indicator_set: service indicator %d not registered\n", svc_indicator); -+ return (-1); -+ } -+ -+ if (rail->State == EP_RAIL_STATE_UNINITIALISED) -+ return (-2); -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) { -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, cmRail->NodeId), 1, 1); -+ EPRINTF3 (DBG_SVC,"cm_svc_indicator_set: clvl %d nodeId %d offset %d\n", clvl, cmRail->NodeId, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, cmRail->NodeId)); -+ } -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ -+ return (0); -+} -+ -+int -+cm_svc_indicator_clear (EP_RAIL *rail, int svc_indicator) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ int clvl; -+ -+ EPRINTF2 (DBG_SVC, "cm_svc_indicator_clear: rail %p ind %d\n", rail, svc_indicator); -+ -+ if (svc_indicator < 0 || svc_indicator >= EP_SVC_NUM_INDICATORS) -+ { -+ EPRINTF1 (DBG_SVC, "cm_svc_indicator_clear: service indicator %d not registered\n", svc_indicator); -+ return (-1); -+ } -+ -+ if (rail->State == EP_RAIL_STATE_UNINITIALISED) -+ return (-2); -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) { -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, cmRail->NodeId), 0, 1); -+ EPRINTF3 (DBG_SVC, "cm_svc_indicator_clear: clvl %d nodeId %d offset %d\n", clvl, cmRail->NodeId, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, cmRail->NodeId)); -+ } -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ -+ return (0); -+} -+ -+int -+cm_svc_indicator_is_set (EP_RAIL *rail, int svc_indicator, int nodeId) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ int clvl; -+ bitmap_t bits; -+ -+ EPRINTF4 (DBG_SVC, "cm_svc_indicator_is_set: rail %p ind %d nodeId %d (me=%d)\n", rail, svc_indicator, nodeId, cmRail->NodeId); -+ -+ if (svc_indicator < 0 || svc_indicator > EP_SVC_NUM_INDICATORS) -+ { -+ EPRINTF1 (DBG_SVC, "cm_svc_indicator_is_set: service indicator %d not registered\n", svc_indicator); -+ return (0); -+ } -+ -+ if (rail->State == EP_RAIL_STATE_UNINITIALISED) -+ return (0); -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ if (nodeId >= cmRail->Levels[clvl].MinNodeId && nodeId < (cmRail->Levels[clvl].MinNodeId + cmRail->Levels[clvl].NumNodes)) -+ break; -+ -+ if ( clvl == cmRail->NumLevels) { -+ EPRINTF1 (DBG_SVC, "cm_svc_indicator_is_set: node out of range %d \n", nodeId); -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ return (0); -+ } -+ -+ if ( cmRail->NodeId == nodeId ) -+ bits = statemap_getbits (cmRail->Levels[clvl].LocalMap, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, nodeId), 1); -+ else -+ bits = statemap_getbits (cmRail->Levels[clvl].GlobalMap, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, nodeId), 1); -+ -+ EPRINTF4 (DBG_SVC, "cm_svc_indicator_is_set: clvl %d nodeId %d offset %d %x\n", clvl, nodeId, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, nodeId), bits); -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ -+ return ( (bits == 0) ? (0) : (1) ); -+} -+ -+int -+cm_svc_indicator_bitmap (EP_RAIL *rail, int svc_indicator, bitmap_t * bitmap, int low, int nnodes) -+{ -+ /* or in the bit map */ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ int nodeId, clvl; -+ bitmap_t bits; -+ unsigned long flags; -+ int clip_out_low, clip_out_high; -+ int curr_low, curr_high; -+ int check_low, check_high; -+ -+ EPRINTF4 (DBG_SVC, "cm_svc_indicator_bitmap: rail %p ind %d low %d high %d\n", rail, svc_indicator, low, (low + nnodes)); -+ -+ if (svc_indicator < 0 || svc_indicator >= EP_SVC_NUM_INDICATORS) -+ { -+ EPRINTF1 (DBG_SVC, "cm_svc_indicator_bitmap: service indicator %d not registered\n", svc_indicator); -+ return (-1); -+ } -+ -+ if (rail->State != EP_RAIL_STATE_RUNNING) -+ return (-2); -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+ clip_out_low = clip_out_high = -1; /* all in */ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) { -+ -+ /* curr_high/low is the range of the current lvl */ -+ curr_low = cmRail->Levels[clvl].MinNodeId; -+ curr_high = cmRail->Levels[clvl].MinNodeId + cmRail->Levels[clvl].NumNodes; -+ -+ /* find out how much of low high is in this range and only check that part */ -+ check_low = ( low < curr_low) ? curr_low : low; -+ check_high = ( (low + nnodes) > curr_high) ? curr_high : (low + nnodes); -+ -+ EPRINTF6 (DBG_SVC, "cm_svc_indicator_bitmap: curr(%d,%d) check(%d,%d) clip(%d,%d)\n", curr_low, curr_high, check_low, check_high, clip_out_low, clip_out_high); -+ -+ for(nodeId = check_low; nodeId < check_high; nodeId++) { -+ -+ if ( (clip_out_low <= nodeId) && (nodeId <= clip_out_high)) -+ nodeId = clip_out_high; /* step over the cliped out section */ -+ else { -+ -+ if ( cmRail->NodeId == nodeId ) -+ bits = statemap_getbits (cmRail->Levels[clvl].LocalMap, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, nodeId), 1); -+ else -+ bits = statemap_getbits (cmRail->Levels[clvl].GlobalMap, CM_SVC_INDICATOR_OFFSET (cmRail, clvl, svc_indicator, nodeId), 1); -+ -+ if ( bits ) { -+ EPRINTF2 (DBG_SVC, "cm_svc_indicator_bitmap: its set nodeId %d (clvl %d)\n", nodeId, clvl); -+ BT_SET ( bitmap , nodeId - low ); -+ } -+ } -+ } -+ -+ /* widen the clip out range */ -+ clip_out_low = curr_low; -+ clip_out_high = curr_high -1; -+ } -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ -+ return (0); -+} -+ -+#if defined(PER_CPU_TIMEOUT) -+static void -+cm_percpu_timeout (void *arg) -+{ -+ CM_RAIL *cmRail = (CM_RAIL *) arg; -+ CM_TIMEOUT_DATA *hbd = &cmRail->HeartbeatTimeoutsData[current_cpu()]; -+ long now = lbolt; -+ unsigned delay = now - hbd->ScheduledAt; -+ unsigned long flags; -+ -+ if (delay > hbd->WorstDelay) -+ hbd->WorstDelay = delay; -+ if (hbd->BestDelay == 0 || delay < hbd->BestDelay) -+ hbd->BestDelay = delay; -+ -+ if (cmRail->HeartbeatTimeoutsShouldStop) -+ { -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ cmRail->HeartbeatTimeoutsStopped |= (1 << current_cpu()); -+ kcondvar_wakeupall (&cmRail->HeartbeatTimeoutsWait, &cmRail->Lock); -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ return; -+ } -+ -+ if (cmRail->NextRunTime == 0 || AFTER (cmRail->NextRunTime, lbolt)) -+ hbd->EarlyCount++; -+ else if (cmRail->HeartbeatTimeoutRunning) -+ hbd->MissedCount++; -+ else -+ { -+ local_irq_save (flags); -+ -+ if (! spin_trylock (&cmRail->HeartbeatTimeoutsLock)) -+ hbd->WastedCount++; -+ else -+ { -+ cmRail->HeartbeatTimeoutRunning = 1; -+ hbd->WorkCount++; -+ -+ spin_lock (&cmRail->Lock); -+ -+ if ((delay = (lbolt - cmRail->NextRunTime)) > hbd->WorstHearbeatDelay) -+ hbd->WorstHearbeatDelay = delay; -+ if ((delay = (lbolt - now) > hbd->WorstLockDelay)) -+ hbd->WorstLockDelay = delay; -+ -+ DoHeartbeatWork (cmRail); -+ -+ spin_unlock (&cmRail->Lock); -+ spin_unlock (&cmRail->HeartbeatTimeoutsLock); -+ -+ cmRail->HeartbeatTimeoutRunning = 0; -+ } -+ local_irq_restore (flags); -+ } -+ -+ hbd->ScheduledAt = lbolt + MSEC2TICKS (CM_PERCPU_TIMEOUT_INTERVAL); -+ timeout_cpu (cm_percpu_timeout, cmRail, MSECS2TICKS (CM_PERCPU_TIMEOUT_INTERVAL), CALLOUT_TYPE|CALLOUT_NOMALLOC); -+} -+ -+static void -+StartPerCpuTimeouts (CM_RAIL *cmRail) -+{ -+ register int c; -+ -+ spin_lock_init (&cmRail->HeartbeatTimeoutsLock); -+ -+ KMEM_ZALLOC (cmRail->HeartbeatTimeoutsData, CM_TIMEOUT_DATA *, ncpus * sizeof (CM_TIMEOUT_DATA), 1); -+ -+ for (c = 0; c < cpus_in_box; c++) -+ { -+ if (cpu_to_processor (c)) -+ { -+ if (current_cpu() != c) -+ { -+ thread_bind (current_thread(), cpu_to_processor(c)); -+ mpsleep (current_thread(), 0, "StartPerCpuTimeouts", 1, NULL, 0); -+ -+ if (current_cpu() != c) -+ panic ("ep: StartPerCpuTimeouts - failed to switch cpu\n"); -+ } -+ -+ cmRail->HeartbeatTimeoutsStarted |= (1 << c); -+ cmRail->HeartbeatTimeoutsData[c].ScheduledAt = lbolt + c; -+ -+ timeout_cpu (cm_percpu_timeout, cmRail, c, CALLOUT_TYPE|CALLOUT_NOMALLOC); -+ } -+ } -+ -+ thread_bind(current_thread(), NULL); -+} -+ -+static void -+StopPerCpuTimeouts (CM_RAIL *cmRail) -+{ -+ register int c; -+ unsigned long flags; -+ -+ cmRail->HeartbeatTimeoutsShouldStop = 1; -+ -+ for (c = 0; c < cpus_in_box; c++) -+ { -+ if (cmRail->HeartbeatTimeoutsStarted & (1 << c)) -+ { -+ printk ("%s: stopping cpu_timeout on cpu %d\n", cmRail->Rail->Name, c); -+ -+ if (untimeout_cpu (cm_percpu_timeout, cmRail, c, CALLOUT_TYPE|CALLOUT_NOMALLOC, NULL)) -+ cmRail->HeartbeatTimeoutsStopped |= (1 << c); -+ } -+ } -+ thread_bind(current_thread(), NULL); -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ while (cmRail->HeartbeatTimeoutsStopped != cmRail->HeartbeatTimeoutsStarted) -+ kcondvar_wait (&cmRail->HeartbeatTimeoutsWait, &cmRail->Lock, &flags); -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ -+ cmRail->HeartbeatTimeoutsStarted = 0; -+ cmRail->HeartbeatTimeoutsStopped = 0; -+ cmRail->HeartbeatTimeoutsShouldStop = 0; -+ -+ KMEM_FREE (cmRail->HeartbeatTimeoutsData, ncpus * sizeof (CM_TIMEOUT_DATA)); -+ -+ spin_lock_destroy (&cmRail->HeartbeatTimeoutsLock); -+} -+ -+#else -+ -+static void -+cm_heartbeat_timer (unsigned long arg) -+{ -+ CM_RAIL *cmRail = (CM_RAIL *) arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+ ASSERT (cmRail->Rail->State == EP_RAIL_STATE_RUNNING); -+ -+ DoHeartbeatWork (cmRail); -+ -+ __Schedule_Timer (cmRail, cmRail->NextRunTime); -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+} -+ -+#endif /* defined(PER_CPU_TIMEOUT) */ -+ -+ -+ -+void -+DisplayRailDo (DisplayInfo *di, EP_RAIL *rail) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ int i, j; -+ -+ if (rail->State != EP_RAIL_STATE_RUNNING) -+ return; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+ (di->func)(di->arg, "NodeId=%d NodeLevel=%d NumLevels=%d NumNodes=%d\n", -+ cmRail->NodeId, cmRail->TopLevel, cmRail->NumLevels, cmRail->Rail->Position.pos_nodes); -+ -+ (di->func)(di->arg, "["); -+ -+ for (i = 0; i < cmRail->NumLevels; i++) -+ { -+ if (i > 0) -+ (di->func)(di->arg, ","); -+ -+ if (i < cmRail->TopLevel) -+ { -+ (di->func)(di->arg, "L "); -+ -+ for (j = 0; j < cmRail->Levels[i].NumSegs; j++) -+ switch (cmRail->Levels[i].Sgmts[j].State) -+ { -+ case CM_SGMT_PRESENT: (di->func)(di->arg, "p%-4d", cmRail->Levels[i].Sgmts[j].NodeId); break; -+ case CM_SGMT_WAITING: (di->func)(di->arg, "w%4s", ""); break; -+ case CM_SGMT_COMING: (di->func)(di->arg, "c%4s", ""); break; -+ case CM_SGMT_ABSENT: (di->func)(di->arg, ".%4s", ""); break; -+ default: (di->func)(di->arg, "?%4s", ""); break; -+ } -+ } -+ else -+ switch (cmRail->Role) -+ { -+ case CM_ROLE_LEADER_CANDIDATE: -+ (di->func)(di->arg,"l "); -+ for (j = 0; j < cmRail->Levels[i].NumSegs; j++) -+ (di->func)(di->arg," "); -+ break; -+ -+ case CM_ROLE_SUBORDINATE: -+ switch (cmRail->Levels[i].Sgmts[0].State) -+ { -+ case CM_SGMT_PRESENT: (di->func)(di->arg, "p%-4d", cmRail->Levels[i].Sgmts[0].NodeId); break; -+ case CM_SGMT_WAITING: (di->func)(di->arg, "w%4s", ""); break; -+ case CM_SGMT_COMING: (di->func)(di->arg, "c%4s", ""); break; -+ case CM_SGMT_ABSENT: (di->func)(di->arg, ".%4s", ""); break; -+ default: (di->func)(di->arg, "?%4s", ""); break; -+ } -+ for (j = 1; j < cmRail->Levels[i].NumSegs; j++) -+ (di->func)(di->arg, " "); -+ break; -+ -+ default: -+ (di->func)(di->arg, "####"); -+ break; -+ } -+ } -+ (di->func)(di->arg, "]\n"); -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+} -+ -+void -+DisplayRail (EP_RAIL *rail) -+{ -+ if (rail->State == EP_RAIL_STATE_RUNNING) -+ DisplayRailDo (&di_ep_debug, rail); -+} -+ -+void -+DisplayStatus (EP_RAIL *rail) -+{ -+ if (rail->State == EP_RAIL_STATE_RUNNING) -+ { -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+ DisplayNodeMaps (&di_ep_debug, cmRail); -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ } -+} -+ -+void -+DisplaySegs (EP_RAIL *rail) -+{ -+ if (rail->State == EP_RAIL_STATE_RUNNING) -+ { -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+ DisplayNodeSgmts (&di_ep_debug, cmRail); -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ } -+} -+ -+static void -+LoadBroadcastRoute (CM_RAIL *cmRail, int lvl, int sidx) -+{ -+ EP_RAIL *rail = cmRail->Rail; -+ int nsegs = cmRail->Levels[0].NumSegs; -+ int vp = EP_VP_BCAST(lvl, sidx); -+ int nodes = 1; -+ int baseNode; -+ int i; -+ -+ ASSERT (lvl > 0 && lvl <= cmRail->NumLevels); -+ ASSERT (sidx == 0 || lvl < cmRail->NumLevels); -+ -+ ASSERT (vp >= EP_VP_BCAST_BASE && vp < EP_VP_BCAST_BASE + EP_VP_BCAST_COUNT); -+ -+ for (i = 1; i <= lvl; i++) -+ { -+ nodes *= nsegs; -+ nsegs = (i == cmRail->NumLevels) ? 1 : cmRail->Levels[i].NumSegs; -+ } -+ -+ baseNode = ((cmRail->NodeId / (nodes * nsegs)) * nsegs + sidx) * nodes; -+ -+ CPRINTF5 (2, "%s: broadcast vp lvl %d sidx %d [%d,%d]\n", -+ cmRail->Rail->Name, lvl, sidx, baseNode, baseNode + nodes - 1); -+ -+ rail->Operations.LoadSystemRoute (rail, vp, baseNode, baseNode + nodes - 1); -+} -+ -+static void -+LoadRouteTable (CM_RAIL *cmRail) -+{ -+ EP_RAIL *rail = cmRail->Rail; -+ int i, j; -+ -+ if (cmRail->NumNodes > EP_MAX_NODES) -+ { -+ printk ("More nodes (%d) than point-to-point virtual process table entries (%d)\n", cmRail->NumNodes, EP_MAX_NODES); -+ panic ("LoadRouteTable\n"); -+ } -+ -+ for (i = 0; i < cmRail->NumNodes; i++) -+ rail->Operations.LoadSystemRoute (rail, EP_VP_NODE(i), i, i); -+ -+ /* Generate broadcast routes for subtrees */ -+ for (i = 1; i < cmRail->NumLevels; i++) -+ for (j = 0; j < cmRail->Levels[i].NumSegs; j++) -+ LoadBroadcastRoute (cmRail, i, j); -+ -+ /* Generate broadcast route for whole machine */ -+ LoadBroadcastRoute (cmRail, cmRail->NumLevels, 0); -+ -+ /* Finally invalidate all the data routes */ -+ for (i = 0; i < cmRail->NumNodes; i++) -+ rail->Operations.UnloadNodeRoute (cmRail->Rail, i); -+} -+ -+void -+cm_node_disconnected (EP_RAIL *rail, unsigned nodeId) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ int base, lstat, lgstat; -+ int clvl, subClMin, subClMax; -+ int thisClId, myClId; -+ unsigned long flags; -+ -+ ASSERT (nodeId != cmRail->NodeId); -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ if (nodeId >= cmRail->Levels[clvl].MinNodeId && nodeId < (cmRail->Levels[clvl].MinNodeId + cmRail->Levels[clvl].NumNodes)) -+ break; -+ -+ myClId = ClusterIds (cmRail, clvl, &subClMin, &subClMax); -+ thisClId = nodeId - cmRail->Levels[clvl].MinNodeId; -+ base = thisClId * CM_GSTATUS_BITS; -+ lstat = statemap_getbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_BITS); -+ lgstat = statemap_getbits (cmRail->Levels[clvl].LastGlobalMap, base, CM_GSTATUS_BITS) & CM_GSTATUS_STATUS_MASK; -+ -+ ASSERT ((lstat & CM_GSTATUS_ACK_MASK) == CM_GSTATUS_MAY_RUN); -+ -+ CPRINTF7 (2, "%s: cm_node_disconnected: Node %d: clvl %d, lgstat %s, gstat %s, lstat %s -> %sMAY_START\n", -+ cmRail->Rail->Name, nodeId, clvl, -+ GlobalStatusString (cmRail->Levels[clvl].LastGlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].GlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].LocalMap, thisClId), -+ ((lgstat != CM_GSTATUS_CLOSING) && (lstat & CM_GSTATUS_RESTART)) ? "RESTART|" : ""); -+ -+ switch (lgstat) -+ { -+ case CM_GSTATUS_CLOSING: -+ /* delayed ack of closing - set MAY_START and clear RESTART */ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_MAY_START, CM_GSTATUS_BITS); -+ break; -+ case CM_GSTATUS_STARTING: -+ case CM_GSTATUS_RUNNING: -+ IASSERT (! cmRail->Levels[clvl].Online || lstat & CM_GSTATUS_RESTART); -+ break; -+ case CM_GSTATUS_ABSENT: -+ IASSERT (lstat & CM_GSTATUS_RESTART); -+ } -+ -+ cmRail->Levels[clvl].Connected--; -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+} -+ -+void -+cm_restart_node (EP_RAIL *rail, unsigned nodeId) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ int base, lstat, lgstat; -+ int clvl, subClMin, subClMax; -+ int thisClId, myClId; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ if (nodeId == rail->Position.pos_nodeid) -+ { -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ RestartComms (cmRail, clvl); -+ } -+ else -+ { -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ if (nodeId >= cmRail->Levels[clvl].MinNodeId && nodeId < (cmRail->Levels[clvl].MinNodeId + cmRail->Levels[clvl].NumNodes)) -+ break; -+ -+ myClId = ClusterIds (cmRail, clvl, &subClMin, &subClMax); -+ thisClId = nodeId - cmRail->Levels[clvl].MinNodeId; -+ base = thisClId * CM_GSTATUS_BITS; -+ lstat = statemap_getbits (cmRail->Levels[clvl].LocalMap, base, CM_GSTATUS_BITS); -+ lgstat = statemap_getbits (cmRail->Levels[clvl].LastGlobalMap, base, CM_GSTATUS_BITS) & CM_GSTATUS_STATUS_MASK; -+ -+ CPRINTF6 (2, "%s: cm_restart_node: Node %d: clvl %d, lgstat %s, gstat %s, lstat %s\n", -+ cmRail->Rail->Name, nodeId, clvl, -+ GlobalStatusString (cmRail->Levels[clvl].LastGlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].GlobalMap, thisClId), -+ GlobalStatusString (cmRail->Levels[clvl].LocalMap, thisClId)); -+ -+ if (lgstat != CM_GSTATUS_CLOSING) -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, base, lstat | CM_GSTATUS_RESTART, CM_GSTATUS_BITS); -+ } -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+} -+ -+void -+cm_force_offline (EP_RAIL *rail, int offline, unsigned int reason) -+{ -+ CM_RAIL *cmRail = rail->ClusterRail; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ if (offline) -+ cmRail->OfflineReasons |= reason; -+ else -+ cmRail->OfflineReasons &= ~reason; -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+} -+ -+static void -+cm_remove_rail (EP_SUBSYS *subsys, EP_SYS *epsys, EP_RAIL *rail) -+{ -+ CM_SUBSYS *sys = (CM_SUBSYS *) subsys; -+ CM_RAIL *cmRail = sys->Rails[rail->Number]; -+ int i, lvl, clvl; -+ -+ cm_procfs_rail_fini (cmRail); -+ -+ sys->Rails[rail->Number] = NULL; -+ rail->ClusterRail = NULL; -+ -+#if defined(PER_CPU_TIMEOUT) -+ StopPerCpuTimeouts (cmRail); -+#else -+ del_timer_sync (&cmRail->HeartbeatTimer); -+#endif -+ cmRail->NextRunTime = 0; -+ cmRail->NextDiscoverTime = 0; -+ cmRail->NextHeartbeatTime = 0; -+ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ { -+ for (lvl = 0; lvl <= clvl; lvl++) -+ { -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ -+ statemap_destroy (level->SubordinateMap[clvl]); -+ -+ for (i = 0; i < level->NumSegs; i++) -+ { -+ statemap_destroy (level->Sgmts[i].Maps[clvl].CurrentInputMap); -+ statemap_destroy (level->Sgmts[i].Maps[clvl].InputMap); -+ statemap_destroy (level->Sgmts[i].Maps[clvl].OutputMap); -+ } -+ } -+ -+ cmRail->Levels[clvl].Online = 0; -+ -+ statemap_destroy (cmRail->Levels[clvl].TmpMap); -+ statemap_destroy (cmRail->Levels[clvl].GlobalMap); -+ statemap_destroy (cmRail->Levels[clvl].LastGlobalMap); -+ statemap_destroy (cmRail->Levels[clvl].SubTreeMap); -+ statemap_destroy (cmRail->Levels[clvl].LocalMap); -+ } -+ -+ spin_lock_destroy (&cmRail->Lock); -+ -+ ep_free_inputq (cmRail->Rail, cmRail->PolledQueue); -+ ep_free_inputq (cmRail->Rail, cmRail->IntrQueue); -+ ep_free_outputq (cmRail->Rail, cmRail->MsgQueue); -+ -+ KMEM_FREE (cmRail, sizeof (CM_RAIL)); -+} -+ -+static int -+cm_add_rail (EP_SUBSYS *subsys, EP_SYS *epsys, EP_RAIL *rail) -+{ -+ CM_SUBSYS *sys = (CM_SUBSYS *) subsys; -+ ELAN_POSITION *pos = &rail->Position; -+ CM_RAIL *cmRail; -+ int lvl, n, nn, clvl, span, i; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (cmRail, CM_RAIL *, sizeof (CM_RAIL), 1); -+ -+ if (cmRail == NULL) -+ return (ENOMEM); -+ -+ cmRail->Rail = rail; -+ cmRail->NodeId = pos->pos_nodeid; -+ cmRail->NumNodes = pos->pos_nodes; -+ -+ spin_lock_init (&cmRail->Lock); -+ -+ if ((cmRail->IntrQueue = ep_alloc_inputq (rail, EP_SYSTEMQ_INTR, sizeof (CM_MSG), CM_INPUTQ_ENTRIES, IntrQueueCallback, cmRail)) == NULL || -+ (cmRail->PolledQueue = ep_alloc_inputq (rail, EP_SYSTEMQ_POLLED, sizeof (CM_MSG), CM_INPUTQ_ENTRIES, NULL, 0)) == NULL || -+ (cmRail->MsgQueue = ep_alloc_outputq (rail, sizeof (CM_MSG), CM_NUM_MSG_BUFFERS)) == NULL) -+ { -+ goto failed; -+ } -+ -+ /* point to first "spare" message buffer */ -+ cmRail->NextSpareMsg = 0; -+ -+ /* Compute the branching ratios from the switcy arity */ -+ for (lvl = 0; lvl < CM_MAX_LEVELS; lvl++) -+ BranchingRatios[lvl] = (lvl < pos->pos_levels) ? pos->pos_arity[pos->pos_levels - lvl - 1] : 4; -+ -+ /* now determine the number of levels of hierachy we have */ -+ /* and how many nodes per level there are */ -+ for (lvl = 0, nn = 1, n = pos->pos_nodes; -+ n > 1; -+ nn *= BranchingRatios[lvl], n = n / BranchingRatios[lvl], lvl++) -+ { -+ int nSegs = (n > BranchingRatios[lvl]) ? BranchingRatios[lvl] : n; -+ int nNodes = nn * nSegs; -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ -+ for (clvl = 0, span = pos->pos_arity[pos->pos_levels - clvl - 1]; -+ span < nNodes && clvl < pos->pos_levels - 1; -+ clvl++, span *= pos->pos_arity[pos->pos_levels - clvl - 1]) -+ ; -+ -+ level->SwitchLevel = clvl; -+ level->MinNodeId = (pos->pos_nodeid / nNodes) * nNodes; -+ level->NumNodes = nNodes; -+ level->NumSegs = nSegs; -+ } -+ -+ cmRail->NumLevels = lvl; -+ cmRail->BroadcastLevel = lvl-1; -+ -+ CPRINTF4 (2, "%s: NodeId=%d NumNodes=%d NumLevels=%d\n", -+ rail->Name, pos->pos_nodeid, pos->pos_nodes, cmRail->NumLevels); -+ -+ LoadRouteTable (cmRail); -+ -+ /* Init SGMT constants */ -+ for (lvl = 0; lvl < cmRail->NumLevels; lvl++) -+ { -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ -+ level->MySgmt = SegmentNo (cmRail, cmRail->NodeId, lvl); -+ -+ for (i = 0; i < CM_SGMTS_PER_LEVEL; i++) -+ { -+ CM_SGMT *sgmt = &level->Sgmts[i]; -+ -+ sgmt->MsgNumber = lvl * CM_SGMTS_PER_LEVEL + i; -+ sgmt->Level = lvl; -+ sgmt->Sgmt = i; -+ } -+ } -+ -+ /* Init maps for each cluster level */ -+ for (clvl = 0; clvl < cmRail->NumLevels; clvl++) -+ { -+ int nNodes = cmRail->Levels[clvl].NumNodes; -+ int mapBits = (nNodes * CM_GSTATUS_BITS) + (nNodes * EP_SVC_NUM_INDICATORS); -+ int clmin; -+ int clmax; -+ int clid = ClusterIds (cmRail, clvl, &clmin, &clmax); -+ -+ for (lvl = 0; lvl <= clvl; lvl++) -+ { -+ CM_LEVEL *level = &cmRail->Levels[lvl]; -+ -+ level->SubordinateMap[clvl] = statemap_create (mapBits); -+ -+ for (i = 0; i < level->NumSegs; i++) -+ { -+ level->Sgmts[i].Maps[clvl].CurrentInputMap = statemap_create (mapBits); -+ level->Sgmts[i].Maps[clvl].InputMap = statemap_create (mapBits); -+ level->Sgmts[i].Maps[clvl].OutputMap = statemap_create (mapBits); -+ } -+ } -+ -+ cmRail->Levels[clvl].Online = 0; -+ -+ cmRail->Levels[clvl].TmpMap = statemap_create (mapBits); -+ cmRail->Levels[clvl].GlobalMap = statemap_create (mapBits); -+ cmRail->Levels[clvl].LastGlobalMap = statemap_create (mapBits); -+ cmRail->Levels[clvl].SubTreeMap = statemap_create (mapBits); -+ cmRail->Levels[clvl].LocalMap = statemap_create (mapBits); -+ -+ /* Flag everyone outside my next lower cluster as sensed offline... */ -+ for (i = 0; i < clmin; i++) -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, i * CM_GSTATUS_BITS, CM_GSTATUS_MAY_START, CM_GSTATUS_BITS); -+ -+ for (i = clmax + 1; i < nNodes; i++) -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, i * CM_GSTATUS_BITS, CM_GSTATUS_MAY_START, CM_GSTATUS_BITS); -+ -+ /* ...and set my own state */ -+ statemap_setbits (cmRail->Levels[clvl].LocalMap, clid * CM_GSTATUS_BITS, -+ CM_GSTATUS_CLOSING | CM_GSTATUS_MAY_START, CM_GSTATUS_BITS); -+ } -+ -+ /* compute parameter hash to add to messages */ -+ cmRail->ParamHash = EP_PROTOCOL_VERSION; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_PERIODIC_DISCOVER_INTERVAL; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_URGENT_DISCOVER_INTERVAL; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_HEARTBEAT_INTERVAL; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_P2P_DMA_RETRIES; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_P2P_MSG_RETRIES; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_BCAST_MSG_RETRIES; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_TIMER_SCHEDULE_TIMEOUT; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_HEARTBEAT_TIMEOUT; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_DISCOVER_TIMEOUT; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + BT_NBIPUL; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + CM_GSTATUS_BITS; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + EP_SVC_NUM_INDICATORS; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + cmRail->NumLevels; -+ cmRail->ParamHash = cmRail->ParamHash * 127 + cmRail->NumNodes; -+ for (i = 0; i < cmRail->NumLevels; i++) -+ cmRail->ParamHash = cmRail->ParamHash * 127 + BranchingRatios[i]; -+ -+#if defined(PER_CPU_TIMEOUT) -+ StartPerCpuTimeouts (cmRail); -+#endif -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+#if !defined(PER_CPU_TIMEOUT) -+ /* Initialise the timer, but don't add it yet, since -+ * __Schedule_Heartbeat() will do this. */ -+ -+ init_timer (&cmRail->HeartbeatTimer); -+ -+ cmRail->HeartbeatTimer.function = cm_heartbeat_timer; -+ cmRail->HeartbeatTimer.data = (unsigned long) cmRail; -+ cmRail->HeartbeatTimer.expires = lbolt + hz; -+#endif -+ -+ /* start sending heartbeats */ -+ __Schedule_Heartbeat (cmRail); -+ -+ /* start discovering who else is out there */ -+ LowerTopLevel (cmRail, 0); -+ -+ /* connect to myself straight away - I know I'm here */ -+ ep_connect_node (rail, cmRail->NodeId); -+ -+ /* add to all rails */ -+ sys->Rails[rail->Number] = cmRail; -+ rail->ClusterRail = (void *) cmRail; -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ -+ /* Enable the input queues */ -+ ep_enable_inputq (rail, cmRail->PolledQueue); -+ ep_enable_inputq (rail, cmRail->IntrQueue); -+ -+ /* Create the procfs entries */ -+ cm_procfs_rail_init (cmRail); -+ -+ return 0; -+ -+ failed: -+ cm_remove_rail (subsys, epsys, rail); -+ return -ENOMEM; -+} -+ -+static void -+cm_fini (EP_SUBSYS *subsys, EP_SYS *epsys) -+{ -+ CM_SUBSYS *sys = (CM_SUBSYS *) subsys; -+ -+ cm_procfs_fini(sys); -+ -+ KMEM_FREE (sys, sizeof (CM_SUBSYS)); -+} -+ -+int -+cm_init (EP_SYS *sys) -+{ -+ CM_SUBSYS *subsys; -+ -+ KMEM_ZALLOC (subsys, CM_SUBSYS *, sizeof (CM_SUBSYS), 1); -+ -+ if (subsys == NULL) -+ return (ENOMEM); -+ -+ subsys->Subsys.Sys = sys; -+ subsys->Subsys.Name = "cm"; -+ subsys->Subsys.Destroy = cm_fini; -+ subsys->Subsys.AddRail = cm_add_rail; -+ subsys->Subsys.RemoveRail = cm_remove_rail; -+ -+ ep_subsys_add (sys, &subsys->Subsys); -+ -+ cm_procfs_init (subsys); -+ -+ /* -+ * Initialise the machineid if it wasn't specified by -+ * the modules.conf file - otherwise truncate it to -+ * 16 bits. -+ */ -+ if (MachineId != -1) -+ MachineId = (uint16_t) MachineId; -+ else -+ { -+#if defined(LINUX_ALPHA) -+ MachineId = (uint16_t)((5 << 12) | HZ); -+#elif defined(LINUX_SPARC) -+ MachineId = (uint16_t)((4 << 12) | HZ); -+#elif defined(LINUX_I386) -+ MachineId = (uint16_t)((3 << 12) | HZ); -+#elif defined( LINUX_IA64) -+ MachineId = (uint16_t)((2 << 12) | HZ); -+#elif defined(LINUX_X86_64) -+ MachineId = (uint16_t)((1 << 12) | HZ); -+#else -+ MachineId = (uint16_t)((0 << 12) | HZ); -+#endif -+ } -+ -+ return (0); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/cm.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/cm.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/cm.h 2005-06-01 23:12:54.633433936 -0400 -@@ -0,0 +1,412 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_CM_H -+#define __ELAN_CM_H -+ -+#ident "@(#)$Id: cm.h,v 1.14.2.1 2004/11/12 10:54:50 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/cm.h,v $*/ -+ -+#include -+ -+#if defined(DIGITAL_UNIX) -+/* -+ * On Tru64 - SMP doesn't mean Symmetric - cpu 0 is a master cpu and is responsible -+ * for handling all PCI interrupts and "funneled" operations. When a kernel thread -+ * is made runnable, the scheduler will choose which cpu it will run on at that time, -+ * and will only execute a higher priority thread from another cpu's run queue when -+ * it becomes totally idle (apparently also including user processes). Also the -+ * assert_wait_mesg_timo function uses a per-cpu timeout - these can only get executed -+ * at "preemptable" places - so again have no guarantee on when they will execute if -+ * they happen to be queued on a "hogged" cpu. The combination of these mean that the Tru64 -+ * is incapable of scheduling a high priority kernel thread within a deterministic time -+ * of when it should have become runnable - wonderfull. -+ * -+ * Hence the solution Compaq have proposed it to schedule a timeout onto all of the -+ * cpu's timeouts lists at the maximum frequency that we could want to execute code, -+ * then to handle the scheduling of work between these ourselves. With a bit of luck -+ * ..... at least one cpu will be sufficiently unloaded to allow us to get a chance -+ * to do our important work. -+ * -+ * However ..... this still is not reliable, since timeouts under Tru64 are still -+ * only run when the currently running kernel thread "co-operates" by calling one -+ * of a number of functions which is permitted to run the "lwc"s AND is not holding -+ * any spinlocks AND is running ai IPL 0. However Compaq are unable to provide -+ * any upper limit on the time between the "lwc"'s being run and so it is possible -+ * for all 4 cpus to not run them for an unbounded time. -+ * -+ * The solution proposed is to use the RM_TEMP_BACKDOOR hook which was added to -+ * hardclock() to "solve" this problem for Memory Channel. However, since it -+ * is called within the clock interrupt it is not permissible to aquire any -+ * spinlocks, nor to run for "too long". This means that it is not possible to -+ * call the heartbeat algorithm from this hook. -+ * -+ * Our solution to these limitations is to use the hook to cause an elan interrupt -+ * to be delivered, by issueing a mis-aligned SetEvent command - this causes the device -+ * to trap and ep_cprocTrap() can then run the heartbeat code. However there is a lock -+ * order violation between the elan_dev::IntrLock and ep_dev::Lock, so we have to -+ * use a trylock and if we fail, then hope that when the interrupt is delievered again -+ * some time later we will succeed. -+ * -+ * However this only works if the kernel is able to respond to the Elan interrupt, -+ * so we panic inside the RM_TEMP_BACKDOOR hook if the SetEvent's interrupt has -+ * not been taken for more than an CM_TIMER_SCHEDULE_TIMEOUT interval. -+ * -+ * In fact this is exactly the mechanism that other operating systems use to -+ * execute timeouts, since the hardclock interrupt posts a low priority -+ * "soft interrupt" which "pre-eempts" the currently running thread and then -+ * executes the timeouts.To block timeouts you use splsoftclock() the same as -+ * in Tru64. -+ */ -+#define PER_CPU_TIMEOUT TRUE -+#endif -+ -+ -+#define CM_SGMTS_PER_LEVEL 8 /* maximum nodes in each segment */ -+#define CM_MAX_LEVELS 6 /* maximum depth of tree */ -+ -+/* message buffers/dmas/events etc */ -+#define CM_NUM_NODE_MSG_BUFFERS (CM_MAX_LEVELS * CM_SGMTS_PER_LEVEL) /* subordinates and leader */ -+#define CM_NUM_SPARE_MSG_BUFFERS 8 /* spare msg buffers for non-connected nodes */ -+#define CM_NUM_MSG_BUFFERS (CM_NUM_NODE_MSG_BUFFERS + CM_NUM_SPARE_MSG_BUFFERS) -+ -+#define CM_INPUTQ_ENTRIES 128 /* # entries in input queue */ -+ -+#define CM_PERIODIC_DISCOVER_INTERVAL (5000) /* 5s (infrequent resolution of established leader conflicts) */ -+#define CM_URGENT_DISCOVER_INTERVAL (50) /* 0.05s (more frequently than heartbeats 'cause they don't retry) */ -+#define CM_HEARTBEAT_INTERVAL (125) /* 0.125s */ -+#define CM_TIMER_SCHEDULE_TIMEOUT (4000) /* 4s Maximum time before a timer that's secheduled to run gets to run (eg blocked in interrupt handlers etc) */ -+#define CM_THREAD_SCHEDULE_TIMEOUT (30000) /* 30s Maximum time before a thread that's scheduled to run gets to run */ -+#define CM_THREAD_RUNNING_TIMEOUT (30000) /* 30s Don't expect the manager thread to be running longer than this */ -+ -+#ifdef PER_CPU_TIMEOUT -+#define CM_PERCPU_TIMEOUT_INTERVAL (50) /* 0.05s (must be less than all above intervals) */ -+#define CM_PACEMAKER_INTERVAL (500) /* 0.05s */ -+ -+#define CM_HEARTBEAT_OVERDUE (250) /* 0.25s Maximum time a timeout can be overdue before taking extreme action */ -+#endif -+ -+#define CM_P2P_DMA_RETRIES 31 -+ -+/* We expect at least 1 point-to-point message in CM_P2P_MSG_RETRIES -+ * attempts to send one to be successfully received */ -+#define CM_P2P_MSG_RETRIES 8 -+ -+/* We expect at least 1 broadcast message in CM_BCAST_MSG_RETRIES attempts -+ * to send one to be successfully received. */ -+#define CM_BCAST_MSG_RETRIES 40 -+ -+/* Heartbeat timeout allows for a node stalling and still getting its -+ * heartbeat. The 2 is to allow for unsynchronised polling times. */ -+#define CM_HEARTBEAT_TIMEOUT (CM_TIMER_SCHEDULE_TIMEOUT + (2 + CM_P2P_MSG_RETRIES) * CM_HEARTBEAT_INTERVAL) -+ -+/* Discover timeout must be > CM_HEARTBEAT_TIMEOUT to guarantee that people -+ * who don't see discovery are considered dead by their leader. This -+ * ensures that by the time a node "discovers" it is a leader of a segment, -+ * the previous leader of that segment will have been deemed to be dead by -+ * its the parent segment's leader */ -+#define CM_DISCOVER_TIMEOUT (CM_TIMER_SCHEDULE_TIMEOUT + (2 + CM_BCAST_MSG_RETRIES) * CM_URGENT_DISCOVER_INTERVAL) -+ -+#define CM_WAITING_TIMEOUT (CM_DISCOVER_TIMEOUT * 100) -+ -+/* -+ * Convert all timeouts specified in mS into "ticks" -+ */ -+#define MSEC2TICKS(MSEC) (((MSEC)*HZ)/1000) -+ -+ -+/* statemap entry */ -+typedef struct cm_state_entry -+{ -+ int16_t level; /* cluster level to apply to */ -+ int16_t offset; /* from statemap_findchange() */ -+ uint16_t seg[BT_NBIPUL/16]; /* ditto */ -+} CM_STATEMAP_ENTRY; -+ -+/* offset is >= 0 for a change to apply and */ -+#define STATEMAP_NOMORECHANGES (-1) /* end of a set of updates */ -+#define STATEMAP_RESET (-2) /* reset the target map */ -+#define STATEMAP_NOOP (-3) /* null token */ -+ -+/* CM message format */ -+typedef int8_t CM_SEQ; /* heartbeat sequence numbers; at least 2 bits, signed */ -+ -+/* -+ * The message header is received into the last 64 byte block of -+ * the input queue and the Version *MUST* be the last word of the -+ * block to ensure that we can see that the whole of the message -+ * has reached main memory after we've seen the input queue pointer -+ * have been updated. -+ */ -+typedef struct ep_cm_hdr -+{ -+ uint32_t Pad0; -+ uint32_t Pad1; -+ -+ uint8_t Type; -+ uint8_t Level; -+ CM_SEQ Seq; /* precision at least 2 bits each*/ -+ CM_SEQ AckSeq; -+ -+ uint16_t NumMaps; -+ uint16_t MachineId; -+ -+ uint16_t NodeId; -+ uint16_t Checksum; -+ -+ uint32_t Timestamp; -+ uint32_t ParamHash; -+ uint32_t Version; -+} CM_HDR; -+ -+#define CM_HDR_SIZE sizeof (CM_HDR) -+ -+typedef struct cm_msg -+{ -+ union { -+ CM_STATEMAP_ENTRY Statemaps[1]; /* piggy-backed statemap updates start here */ -+ uint8_t Space[EP_SYSTEMQ_MSG_MAX - CM_HDR_SIZE]; -+ } Payload; -+ -+ CM_HDR Hdr; -+} CM_MSG; -+ -+/* The maximum number of statemap entries that can fit within an EP_CM_MSG_BUFFER */ -+#define CM_MSG_MAXMAPS (offsetof (CM_MSG, Hdr) / sizeof (CM_STATEMAP_ENTRY)) -+#define CM_MSG_MAP(mapno) (CM_MSG_MAXMAPS - (mapno) - 1) -+ -+/* The actual special message base & size, including 'nmaps' piggy-backed statemap entries */ -+#define CM_MSG_BASE(nmaps) (nmaps == 0 ? offsetof (CM_MSG, Hdr) : offsetof (CM_MSG, Payload.Statemaps[CM_MSG_MAXMAPS - nmaps])) -+#define CM_MSG_SIZE(nmaps) (sizeof (CM_MSG) - CM_MSG_BASE(nmaps)) -+ -+#define CM_MSG_VERSION 0xcad00005 -+#define CM_MSG_TYPE_RESOLVE_LEADER 0 -+#define CM_MSG_TYPE_DISCOVER_LEADER 1 -+#define CM_MSG_TYPE_NOTIFY 2 -+#define CM_MSG_TYPE_DISCOVER_SUBORDINATE 3 -+#define CM_MSG_TYPE_IMCOMING 4 -+#define CM_MSG_TYPE_HEARTBEAT 5 -+#define CM_MSG_TYPE_REJOIN 6 -+ -+/* CM machine segment */ -+typedef struct cm_sgmtMaps -+{ -+ u_char InputMapValid; /* Input map has been set */ -+ u_char OutputMapValid; /* Output map has been set */ -+ u_char SentChanges; /* got an outstanding STATEMAP_NOMORECHANGES to send */ -+ statemap_t *OutputMap; /* state to send */ -+ statemap_t *InputMap; /* state received */ -+ statemap_t *CurrentInputMap; /* state being received */ -+} CM_SGMTMAPS; -+ -+typedef struct cm_sgmt -+{ -+ u_char State; -+ u_char SendMaps; -+ u_char MsgAcked; -+ CM_SEQ MsgSeq; -+ CM_SEQ AckSeq; -+ u_int NodeId; -+ long UpdateTick; -+ long WaitingTick; -+ uint32_t Timestamp; -+ CM_SGMTMAPS Maps[CM_MAX_LEVELS]; /* Maps[i] == state for cluster level i */ -+ u_short MsgNumber; /* msg buffer to use */ -+ u_short NumMaps; /* # maps in message buffer */ -+ u_short Level; -+ u_short Sgmt; -+} CM_SGMT; -+ -+#define CM_SGMT_ABSENT 0 /* no one there at all */ -+#define CM_SGMT_WAITING 1 /* waiting for subtree to connect */ -+#define CM_SGMT_COMING 2 /* expecting a subtree to reconnect */ -+#define CM_SGMT_PRESENT 3 /* connected */ -+ -+typedef struct cm_level -+{ -+ int SwitchLevel; -+ u_int MinNodeId; -+ u_int NumNodes; -+ u_int NumSegs; -+ u_int MySgmt; -+ -+ /* SubordinateMap[i] == OR of all subordinate maps on this level and down for cluster level i */ -+ u_char SubordinateMapValid[CM_MAX_LEVELS]; -+ statemap_t *SubordinateMap[CM_MAX_LEVELS]; -+ -+ /* maps/flags for this cluster level */ -+ u_int Online:1; /* I've gone online (seen myself running) */ -+ u_int Restarting:1; /* driving my owm restart bit */ -+ u_char OfflineReasons; /* forced offline by broadcast */ -+ -+ u_char GlobalMapValid; -+ u_char SubTreeMapValid; -+ u_long Connected; -+ -+ statemap_t *LocalMap; /* state bits I drive */ -+ statemap_t *SubTreeMap; /* OR of my and my subtree states */ -+ statemap_t *GlobalMap; /* OR of all node states */ -+ statemap_t *LastGlobalMap; /* last map I saw */ -+ statemap_t *TmpMap; /* scratchpad */ -+ -+ CM_SGMT Sgmts[CM_SGMTS_PER_LEVEL]; -+} CM_LEVEL; -+ -+#define CM_ROLE_LEADER_CANDIDATE 0 -+#define CM_ROLE_LEADER 1 -+#define CM_ROLE_SUBORDINATE 2 -+ -+/* global status bits */ -+#define CM_GSTATUS_STATUS_MASK 0x03 /* bits nodes drive to broadcast their status */ -+#define CM_GSTATUS_ABSENT 0x00 /* Off the network */ -+#define CM_GSTATUS_STARTING 0x01 /* I'm waiting for everyone to see me online */ -+#define CM_GSTATUS_RUNNING 0x03 /* up and running */ -+#define CM_GSTATUS_CLOSING 0x02 /* I'm waiting for everyone to see me offline */ -+ -+#define CM_GSTATUS_ACK_MASK 0x0c /* bits node drive to ack other status */ -+#define CM_GSTATUS_MAY_START 0x04 /* Everyone thinks I may not start */ -+#define CM_GSTATUS_MAY_RUN 0x08 /* Everyone thinks I may not run */ -+ -+#define CM_GSTATUS_RESTART 0x10 /* Someone thinks I should restart */ -+#define CM_GSTATUS_BITS 5 -+ -+#define CM_GSTATUS_BASE(node) ((node) * CM_GSTATUS_BITS) -+ -+#if defined(PER_CPU_TIMEOUT) -+typedef struct cm_timeout_data -+{ -+ long ScheduledAt; /* lbolt timeout was scheduled to run at */ -+ -+ unsigned long EarlyCount; /* # times run early than NextRun */ -+ unsigned long MissedCount; /* # times run on time - but someone else was running it */ -+ unsigned long WastedCount; /* # times we failed to get the spinlock */ -+ unsigned long WorkCount; /* # times we're the one running */ -+ -+ unsigned long WorstDelay; /* worst scheduling delay */ -+ unsigned long BestDelay; /* best scheduling delay */ -+ -+ unsigned long WorstLockDelay; /* worst delay before getting rail->Lock */ -+ -+ unsigned long WorstHearbeatDelay; /* worst delay before calling DoHeartbeatWork */ -+} CM_TIMEOUT_DATA; -+#endif -+ -+typedef struct cm_rail -+{ -+ EP_RAIL *Rail; /* rail we're associated with */ -+ struct list_head Link; /* and linked on the CM_SUBSYS */ -+ -+ uint32_t ParamHash; /* hash of critical parameters */ -+ uint32_t Timestamp; -+ long DiscoverStartTick; /* when discovery start */ -+ -+ unsigned int NodeId; /* my node id */ -+ unsigned int NumNodes; /* and number of nodes */ -+ unsigned int NumLevels; /* number of levels computed from machine size */ -+ int BroadcastLevel; -+ long BroadcastLevelTick; -+ unsigned int TopLevel; /* level at which I'm not a leader */ -+ unsigned char Role; /* state at TopLevel */ -+ -+ EP_INPUTQ *PolledQueue; /* polled input queue */ -+ EP_INPUTQ *IntrQueue; /* intr input queue */ -+ EP_OUTPUTQ *MsgQueue; /* message */ -+ unsigned int NextSpareMsg; /* next "spare" message buffer to use */ -+ -+ EP_CM_RAIL_STATS Stats; /* statistics */ -+ -+ kmutex_t Mutex; -+ spinlock_t Lock; -+ -+ long NextHeartbeatTime; /* next time to check/send heartbeats */ -+ long NextDiscoverTime; /* next time to progress discovery */ -+ long NextRunTime; /* the earlier of the above two or intr requires inputq poll*/ -+ -+ unsigned int OfflineReasons; /* forced offline by procfs/manager thread stuck */ -+ -+#if defined(PER_CPU_TIMEOUT) -+ spinlock_t HeartbeatTimeoutsLock; /* spinlock to sequentialise per-cpu timeouts */ -+ long HeartbeatTimeoutsStarted; /* bitmap of which timeouts have started */ -+ long HeartbeatTimeoutsStopped; /* bitmap of which timeouts have stopped */ -+ long HeartbeatTimeoutsShouldStop; /* flag to indicate timeouts should stop */ -+ kcondvar_t HeartbeatTimeoutsWait; /* place to sleep waiting for timeouts to stop */ -+ long HeartbeatTimeoutRunning; /* someone is running the timeout - don't try for the lock */ -+ -+ long HeartbeatTimeoutOverdue; /* heartbeat seen as overdue - interrupt requested */ -+ -+ CM_TIMEOUT_DATA *HeartbeatTimeoutsData; /* per timeout data */ -+#else -+ struct timer_list HeartbeatTimer; /* timer for heartbeat/discovery */ -+#endif -+ -+ CM_LEVEL Levels[CM_MAX_LEVELS]; -+} CM_RAIL; -+ -+/* OfflineReasons (both per-rail and */ -+#define CM_OFFLINE_BROADCAST (1 << 0) -+#define CM_OFFLINE_PROCFS (1 << 1) -+#define CM_OFFLINE_MANAGER (1 << 2) -+ -+typedef struct cm_subsys -+{ -+ EP_SUBSYS Subsys; -+ CM_RAIL *Rails[EP_MAX_RAILS]; -+} CM_SUBSYS; -+ -+extern int MachineId; -+ -+extern void cm_node_disconnected (EP_RAIL *rail, unsigned nodeId); -+extern void cm_restart_node (EP_RAIL *rail, unsigned nodeId); -+extern void cm_restart_comms (CM_RAIL *cmRail); -+extern int cm_init (EP_SYS *sys); -+ -+extern void DisplayRail(EP_RAIL *rail); -+extern void DisplaySegs (EP_RAIL *rail); -+extern void DisplayStatus (EP_RAIL *rail); -+ -+typedef struct proc_private -+{ -+ struct nodeset_private *pr_next; -+ EP_RAIL *pr_rail; -+ char *pr_data; -+ int pr_data_len; -+ unsigned pr_off; -+ unsigned pr_len; -+ DisplayInfo pr_di; -+} PROC_PRIVATE; -+ -+extern void proc_character_fill (long mode, char *fmt, ...); -+extern int proc_release (struct inode *inode, struct file *file); -+extern ssize_t proc_read (struct file *file, char *buf, size_t count, loff_t *ppos); -+ -+ -+extern void DisplayNodeMaps (DisplayInfo *di, CM_RAIL *cmRail); -+extern void DisplayNodeSgmts (DisplayInfo *di, CM_RAIL *cmRail); -+extern void DisplayRailDo (DisplayInfo *di, EP_RAIL *rail); -+ -+extern int cm_read_cluster(EP_RAIL *rail,char *page); -+extern void cm_force_offline (EP_RAIL *rail, int offline, unsigned int reason); -+ -+extern int cm_svc_indicator_set (EP_RAIL *rail, int svc_indicator); -+extern int cm_svc_indicator_clear (EP_RAIL *rail, int svc_indicator); -+extern int cm_svc_indicator_is_set (EP_RAIL *rail, int svc_indicator, int nodeId); -+extern int cm_svc_indicator_bitmap (EP_RAIL *rail, int svc_indicator, bitmap_t * bitmap, int low, int nnodes); -+ -+/* cm_procfs.c */ -+extern void cm_procfs_init (CM_SUBSYS *subsys); -+extern void cm_procfs_fini (CM_SUBSYS *subsys); -+extern void cm_procfs_rail_init (CM_RAIL *rail); -+extern void cm_procfs_rail_fini (CM_RAIL *rail); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN_CM_H */ -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/cm_procfs.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/cm_procfs.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/cm_procfs.c 2005-06-01 23:12:54.633433936 -0400 -@@ -0,0 +1,254 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2005 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: cm_procfs.c,v 1.5 2004/05/14 09:23:13 daniel Exp $" -+/* $Source: /cvs/master/quadrics/epmod/cm_procfs.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "debug.h" -+#include "cm.h" -+#include -+ -+#include -+ -+extern char *sprintClPeers (char *str, CM_RAIL *cmRail, int clvl); -+ -+static int -+proc_read_cluster(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ CM_RAIL *cmRail = (CM_RAIL *) data; -+ char *p = page; -+ -+ page[0] = 0; -+ -+ if (cmRail->Rail->State != EP_RAIL_STATE_RUNNING) -+ p += sprintf(p, "\n"); -+ else -+ { -+ CM_LEVEL *cmLevel; -+ unsigned long flags; -+ int i, j; -+ char clNodeStr[32]; /* [%d-%d][%d-%d] */ -+ char seperate_with; -+ -+ struct { int val; char *name; } bitvals[] = { -+ {CM_OFFLINE_BROADCAST, "Broadcast"}, -+ {CM_OFFLINE_PROCFS, "Offline"}, -+ {CM_OFFLINE_MANAGER, "Manager"}}; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ -+ for (i = 0; i < cmRail->NumLevels; i++) -+ { -+ cmLevel = &cmRail->Levels[i]; -+ -+ p += sprintf(p, "%23s %7s ", sprintClPeers (clNodeStr, cmRail, i), cmLevel->Online?"Online":"Offline"); -+ -+ if ((cmLevel->Online ) | ( cmLevel->Connected > 0)) -+ p += sprintf(p, "Connected=%lu ", cmLevel->Connected); -+ -+ seperate_with = '<'; -+ -+ if ( cmLevel->Restarting ) { -+ p += sprintf(p, "%cRestarting", seperate_with); -+ seperate_with = ','; -+ } -+ -+ if ( ! (cmLevel->GlobalMapValid & cmLevel->SubTreeMapValid )) { -+ p += sprintf(p, "%cMap Not Valid", seperate_with); -+ seperate_with = ','; -+ } -+ -+ if ( cmLevel->OfflineReasons ) { -+ for (j = 0; j < sizeof (bitvals)/sizeof(bitvals[0]); j++) -+ if (cmLevel->OfflineReasons & bitvals[j].val) { -+ p += sprintf(p, "%c%s", seperate_with, bitvals[j].name); -+ seperate_with = ','; -+ } -+ } -+ if ( cmRail->OfflineReasons ) { -+ for (j = 0; j < sizeof (bitvals)/sizeof(bitvals[0]); j++) -+ if (cmRail->OfflineReasons & bitvals[j].val) { -+ p += sprintf(p, "%c%s", seperate_with, bitvals[j].name); -+ seperate_with = ','; -+ } -+ } -+ -+ if ( seperate_with != '<' ) -+ p += sprintf(p,">\n"); -+ else -+ p += sprintf(p,"\n"); -+ } -+ -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ } -+ -+ return qsnet_proc_calc_metrics (page, start, off, count, eof, p - page); -+} -+ -+static struct rail_info -+{ -+ char *name; -+ int (*read_func) (char *page, char **start, off_t off, int count, int *eof, void *data); -+ int (*write_func) (struct file *file, const char *buf, unsigned long count, void *data); -+} rail_info[] = { -+ {"cluster", proc_read_cluster, NULL}, -+}; -+ -+struct proc_dir_entry *svc_indicators_root; -+ -+typedef struct svc_indicator_data -+{ -+ int svc_indicator; -+ EP_RAIL *rail; -+} SVC_INDICATOR_DATA; -+ -+static SVC_INDICATOR_DATA svc_indicator_data[EP_SVC_NUM_INDICATORS][EP_MAX_RAILS]; -+static char *svc_indicator_names[EP_SVC_NUM_INDICATORS] = EP_SVC_NAMES; -+ -+static int -+proc_read_svc_indicator_rail_bitmap (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ SVC_INDICATOR_DATA *svc_data = (SVC_INDICATOR_DATA *)data; -+ unsigned int nnodes = ep_numnodes (ep_system()); -+ bitmap_t *bitmap; -+ -+ KMEM_ZALLOC (bitmap, bitmap_t *, (BT_BITOUL(EP_MAX_NODES) * sizeof (bitmap_t)), 1); -+ -+ cm_svc_indicator_bitmap (svc_data->rail, svc_data->svc_indicator, bitmap, 0, nnodes); -+ -+ ep_sprintf_bitmap (page, PAGESIZE, bitmap, 0, 0, nnodes); -+ -+ KMEM_FREE (bitmap, (BT_BITOUL(EP_MAX_NODES) * sizeof (bitmap_t))); -+ -+ strcat (page, "\n"); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+static int -+proc_read_svc_indicator_bitmap(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ unsigned int num = (unsigned long) data; -+ EP_SYS *sys = ep_system(); -+ unsigned int nnodes = ep_numnodes (sys); -+ bitmap_t *bitmap; -+ -+ KMEM_ALLOC(bitmap, bitmap_t *, (BT_BITOUL(EP_MAX_NODES) * sizeof (bitmap_t)), 1); -+ -+ ep_svc_indicator_bitmap (sys, num, bitmap, 0, nnodes); -+ -+ ep_sprintf_bitmap (page, PAGESIZE, bitmap, 0, 0, nnodes); -+ -+ KMEM_FREE (bitmap, (BT_BITOUL(EP_MAX_NODES) * sizeof (bitmap_t))); -+ -+ strcat (page, "\n"); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+void -+cm_procfs_rail_init (CM_RAIL *cmRail) -+{ -+ EP_RAIL *rail = cmRail->Rail; -+ struct proc_dir_entry *p; -+ int i; -+ -+ for (i = 0; i < sizeof (rail_info)/sizeof (rail_info[0]); i++) -+ { -+ if ((p = create_proc_entry (rail_info[i].name, 0, cmRail->Rail->ProcDir)) != NULL) -+ { -+ p->read_proc = rail_info[i].read_func; -+ p->write_proc = rail_info[i].write_func; -+ p->data = cmRail; -+ p->owner = THIS_MODULE; -+ } -+ } -+ -+ if ((rail->SvcIndicatorDir = proc_mkdir ("svc_indicators", cmRail->Rail->ProcDir)) != NULL) -+ { -+ for (i = 0; i < EP_SVC_NUM_INDICATORS; i++) -+ { -+ if ((p = create_proc_entry (svc_indicator_names[i], 0, rail->SvcIndicatorDir)) != NULL) -+ { -+ svc_indicator_data[i][rail->Number].svc_indicator = i; -+ svc_indicator_data[i][rail->Number].rail = rail; -+ -+ p->write_proc = NULL; -+ p->read_proc = proc_read_svc_indicator_rail_bitmap; -+ p->data = (void *)&svc_indicator_data[i][rail->Number]; -+ p->owner = THIS_MODULE; -+ } -+ } -+ } -+} -+ -+void -+cm_procfs_rail_fini (CM_RAIL *cmRail) -+{ -+ EP_RAIL *rail = cmRail->Rail; -+ int i; -+ -+ if (rail->SvcIndicatorDir) -+ { -+ for (i = 0; i < EP_SVC_NUM_INDICATORS; i++) -+ remove_proc_entry (svc_indicator_names[i], rail->SvcIndicatorDir); -+ -+ remove_proc_entry ("svc_indicators", cmRail->Rail->ProcDir); -+ } -+ -+ for (i = 0; i < sizeof (rail_info)/sizeof (rail_info[0]); i++) -+ remove_proc_entry (rail_info[i].name, cmRail->Rail->ProcDir); -+} -+ -+void -+cm_procfs_init (CM_SUBSYS *subsys) -+{ -+ struct proc_dir_entry *p; -+ int i; -+ -+ qsnet_proc_register_hex (ep_config_root, "machine_id", &MachineId, 0); -+ -+ if ((svc_indicators_root = proc_mkdir("svc_indicators", ep_procfs_root)) != NULL) -+ { -+ for (i = 0; i < EP_SVC_NUM_INDICATORS; i++) -+ { -+ if ((p = create_proc_entry (svc_indicator_names[i], 0, svc_indicators_root)) != NULL) -+ { -+ p->write_proc = NULL; -+ p->read_proc = proc_read_svc_indicator_bitmap; -+ p->data = (void *)(long) i; -+ p->owner = THIS_MODULE; -+ } -+ } -+ -+ } -+} -+ -+void -+cm_procfs_fini (CM_SUBSYS *subsys) -+{ -+ int i; -+ -+ if (svc_indicators_root) -+ { -+ for (i = 0; i < EP_SVC_NUM_INDICATORS; i++) -+ remove_proc_entry (svc_indicator_names[i], svc_indicators_root); -+ -+ remove_proc_entry ("svc_indicators", ep_procfs_root); -+ } -+ -+ remove_proc_entry ("machine_id", ep_config_root); -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/commands_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/commands_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/commands_elan4.c 2005-06-01 23:12:54.634433784 -0400 -@@ -0,0 +1,173 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: commands_elan4.c,v 1.2 2003/10/23 15:07:53 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/commands_elan4.c,v $*/ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "debug.h" -+ -+#include -+ -+static __inline__ void -+elan4_command_write (ELAN4_CQ *cq, E4_uint64 val, unsigned off) -+{ -+ writeq (val, cq->cq_mapping + offsetof (E4_CommandPort, Command[off])); -+} -+ -+void -+elan4_nop_cmd (ELAN4_CQ *cq, E4_uint64 tag) -+{ -+ elan4_command_write (cq, tag | NOP_CMD, 0); -+} -+ -+void -+elan4_write_dword_cmd (ELAN4_CQ *cq, E4_Addr addr, E4_uint64 data) -+{ -+ elan4_command_write (cq, addr | WRITE_DWORD_CMD, 0); -+ elan4_command_write (cq, data, 1); -+} -+ -+void -+elan4_add_dword_cmd (ELAN4_CQ *cq, E4_Addr addr, E4_uint64 data) -+{ -+ elan4_command_write (cq, addr | ADD_DWORD_CMD, 0); -+ elan4_command_write (cq, data, 1); -+} -+ -+void -+elan4_copy64_cmd (ELAN4_CQ *cq, E4_Addr from, E4_Addr to, E4_uint32 datatype) -+{ -+ elan4_command_write (cq, from | (datatype << COPY64_DATA_TYPE_SHIFT) | COPY64_CMD, 0); -+ elan4_command_write (cq, to | (datatype << COPY64_DATA_TYPE_SHIFT), 1); -+} -+ -+void -+elan4_interrupt_cmd (ELAN4_CQ *cq, E4_uint64 cookie) -+{ -+ elan4_command_write (cq, (cookie << E4_MAIN_INT_SHIFT) | INTERRUPT_CMD, 0); -+} -+ -+ -+void -+elan4_run_thread_cmd (ELAN4_CQ *cq, E4_ThreadRegs *regs) -+{ -+ elan4_command_write (cq, regs->Registers[0] | RUN_THREAD_CMD, 0); -+ elan4_command_write (cq, regs->Registers[1], 1); -+ elan4_command_write (cq, regs->Registers[2], 2); -+ elan4_command_write (cq, regs->Registers[3], 3); -+ elan4_command_write (cq, regs->Registers[4], 4); -+ elan4_command_write (cq, regs->Registers[5], 5); -+ elan4_command_write (cq, regs->Registers[6], 6); -+} -+ -+void -+elan4_run_dma_cmd (ELAN4_CQ *cq, E4_DMA *dma) -+{ -+ E4_uint64 *dmaptr = (E4_uint64 *) dma; -+ -+ elan4_command_write (cq, dmaptr[0] | RUN_DMA_CMD, 0); -+ elan4_command_write (cq, dmaptr[1], 1); -+ elan4_command_write (cq, dmaptr[2], 2); -+ elan4_command_write (cq, dmaptr[3], 3); -+ elan4_command_write (cq, dmaptr[4], 4); -+ elan4_command_write (cq, dmaptr[5], 5); -+ elan4_command_write (cq, dmaptr[6], 6); -+} -+ -+void -+elan4_set_event_cmd (ELAN4_CQ *cq, E4_Addr event) -+{ -+ elan4_command_write (cq, event | SET_EVENT_CMD, 0); -+} -+ -+void -+elan4_set_eventn_cmd (ELAN4_CQ *cq, E4_Addr event, E4_uint32 count) -+{ -+ elan4_command_write (cq, SET_EVENTN_CMD,0); -+ elan4_command_write (cq, event | count, 1); -+} -+ -+void -+elan4_wait_event_cmd (ELAN4_CQ *cq, E4_Addr event, E4_uint64 candt, E4_uint64 param0, E4_uint64 param1) -+{ -+ elan4_command_write (cq, event | WAIT_EVENT_CMD, 0); -+ elan4_command_write (cq, candt, 1); -+ elan4_command_write (cq, param0, 2); -+ elan4_command_write (cq, param1, 3); -+} -+ -+void -+elan4_open_packet (ELAN4_CQ *cq, E4_uint64 command) -+{ -+ elan4_command_write (cq, command | OPEN_STEN_PKT_CMD, 0); -+} -+ -+void -+elan4_guard (ELAN4_CQ *cq, E4_uint64 command) -+{ -+ elan4_command_write (cq, command | GUARD_CMD, 0); -+} -+ -+void -+elan4_sendtrans0 (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr) -+{ -+ elan4_command_write (cq, (trtype << 16) | SEND_TRANS_CMD, 0); -+ elan4_command_write (cq, addr, 1); -+} -+ -+void -+elan4_sendtrans1 (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, E4_uint64 p0) -+{ -+ elan4_command_write (cq, (trtype << 16) | SEND_TRANS_CMD, 0); -+ elan4_command_write (cq, addr, 1); -+ elan4_command_write (cq, p0, 2); -+} -+ -+void -+elan4_sendtrans2 (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, E4_uint64 p0, E4_uint64 p1) -+{ -+ elan4_command_write (cq, (trtype << 16) | SEND_TRANS_CMD, 0); -+ elan4_command_write (cq, addr, 1); -+ elan4_command_write (cq, p0, 2); -+ elan4_command_write (cq, p1, 3); -+} -+ -+void -+elan4_sendtransn (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, ...) -+{ -+ E4_uint32 ndword = ((trtype & TR_SIZE_MASK) >> TR_SIZE_SHIFT); -+ va_list ap; -+ register int i; -+ -+ elan4_command_write (cq, (trtype << 16) | SEND_TRANS_CMD, 0); -+ elan4_command_write (cq, addr, 1); -+ -+ va_start (ap, addr); -+ for (i = 2; i < ndword+2; i++) -+ elan4_command_write (cq, va_arg (ap, E4_uint64), i); -+ va_end (ap); -+} -+ -+void -+elan4_sendtransp (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, E4_uint64 *ptr) -+{ -+ E4_uint32 ndword = ((trtype &TR_SIZE_MASK) >> TR_SIZE_SHIFT); -+ register int i; -+ -+ elan4_command_write (cq, (trtype << 16) | SEND_TRANS_CMD, 0); -+ elan4_command_write (cq, addr, 1); -+ for (i = 2; i < ndword+2; i++) -+ elan4_command_write (cq, *ptr++, i); -+} -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/conf_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/conf_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/conf_linux.c 2005-06-01 23:12:54.635433632 -0400 -@@ -0,0 +1,309 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: conf_linux.c,v 1.37.2.3 2005/01/18 14:47:35 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/conf_linux.c,v $ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "cm.h" -+ -+#include "conf_linux.h" -+ -+#include -+#include -+#include -+#include -+ -+/* Module parameters */ -+unsigned int epdebug = 0; -+unsigned int epdebug_console = 0; -+unsigned int epdebug_cmlevel = 0; -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+unsigned int epdebug_check_sum = 0; -+#endif -+int disabled = 0; -+int sdram_assert = 0; -+int assfail_mode = 0; -+int txd_stabilise = 7; -+int portals_envelopes = 0; -+ -+/* External module parameters */ -+extern int MaxSwitchLevels; -+extern int RejoinCheck; -+extern int RejoinPanic; -+extern int PositionCheck; -+extern int MachineId; -+ -+/* Module globals */ -+EP_SYS epsys; -+ -+#ifdef MODULE -+MODULE_AUTHOR("Quadrics Ltd"); -+MODULE_DESCRIPTION("Elan Kernel Comms"); -+ -+MODULE_LICENSE("GPL"); -+ -+MODULE_PARM(epdebug, "i"); -+MODULE_PARM(epdebug_console, "i"); -+MODULE_PARM(epdebug_cmlevel, "i"); -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+MODULE_PARM(epdebug_check_sum, "i"); -+#endif -+MODULE_PARM(disabled, "i"); -+ -+MODULE_PARM(MachineId, "i"); -+MODULE_PARM(RejoinPanic, "i"); -+MODULE_PARM(RejoinCheck, "i"); -+MODULE_PARM(PositionCheck, "i"); -+MODULE_PARM(MaxSwitchLevels, "i"); -+ -+MODULE_PARM(sdram_assert, "i"); -+MODULE_PARM(assfail_mode, "i"); -+MODULE_PARM(txd_stabilise, "i"); -+MODULE_PARM(portals_envelopes,"i"); -+ -+/* epcomms.c large message service functions */ -+EXPORT_SYMBOL(ep_alloc_xmtr); -+EXPORT_SYMBOL(ep_free_xmtr); -+EXPORT_SYMBOL(ep_transmit_message); -+EXPORT_SYMBOL(ep_multicast_message); -+EXPORT_SYMBOL(ep_transmit_rpc); -+ -+EXPORT_SYMBOL(ep_alloc_rcvr); -+EXPORT_SYMBOL(ep_free_rcvr); -+EXPORT_SYMBOL(ep_queue_receive); -+EXPORT_SYMBOL(ep_requeue_receive); -+EXPORT_SYMBOL(ep_rpc_put); -+EXPORT_SYMBOL(ep_rpc_get); -+EXPORT_SYMBOL(ep_complete_rpc); -+EXPORT_SYMBOL(ep_complete_receive); -+ -+EXPORT_SYMBOL(ep_poll_transmits); -+EXPORT_SYMBOL(ep_enable_txcallbacks); -+EXPORT_SYMBOL(ep_disable_txcallbacks); -+ -+/* epcomms.c functions for accessing fields of rxds/txds */ -+EXPORT_SYMBOL(ep_rxd_arg); -+EXPORT_SYMBOL(ep_rxd_len); -+EXPORT_SYMBOL(ep_rxd_isrpc); -+EXPORT_SYMBOL(ep_rxd_envelope); -+EXPORT_SYMBOL(ep_rxd_payload); -+EXPORT_SYMBOL(ep_rxd_node); -+EXPORT_SYMBOL(ep_rxd_status); -+EXPORT_SYMBOL(ep_rxd_statusblk); -+EXPORT_SYMBOL(ep_txd_node); -+EXPORT_SYMBOL(ep_txd_statusblk); -+ -+/* kmap.c, nmh.c - handling mapping of pages into network memory */ -+EXPORT_SYMBOL(ep_dvma_reserve); -+EXPORT_SYMBOL(ep_dvma_release); -+EXPORT_SYMBOL(ep_dvma_load); -+EXPORT_SYMBOL(ep_dvma_unload); -+EXPORT_SYMBOL(ep_nmd_subset); -+EXPORT_SYMBOL(ep_nmd_merge); -+ -+EXPORT_SYMBOL(ep_system); -+ -+/* kcomm.c */ -+EXPORT_SYMBOL(ep_nodeid); -+EXPORT_SYMBOL(ep_numnodes); -+EXPORT_SYMBOL(ep_waitfor_nodeid); -+ -+/* railhints.c */ -+EXPORT_SYMBOL(ep_pickRail); -+EXPORT_SYMBOL(ep_xmtr_bcastrail); -+EXPORT_SYMBOL(ep_xmtr_prefrail); -+EXPORT_SYMBOL(ep_xmtr_availrails); -+EXPORT_SYMBOL(ep_xmtr_noderails); -+EXPORT_SYMBOL(ep_rcvr_prefrail); -+EXPORT_SYMBOL(ep_rcvr_availrails); -+EXPORT_SYMBOL(ep_rxd_railmask); -+ -+EXPORT_SYMBOL(ep_svc_indicator_bitmap); -+EXPORT_SYMBOL(ep_svc_indicator_is_set); -+EXPORT_SYMBOL(ep_svc_indicator_clear); -+EXPORT_SYMBOL(ep_svc_indicator_set); -+ -+/* cm.c */ -+EXPORT_SYMBOL(cm_svc_indicator_clear); -+EXPORT_SYMBOL(cm_svc_indicator_set); -+EXPORT_SYMBOL(cm_svc_indicator_is_set); -+EXPORT_SYMBOL(cm_svc_indicator_bitmap); -+ -+#endif -+ -+EP_SYS * -+ep_system() -+{ -+ return (&epsys); -+} -+ -+void -+ep_mod_inc_usecount() -+{ -+ MOD_INC_USE_COUNT; -+} -+ -+void -+ep_mod_dec_usecount() -+{ -+ MOD_DEC_USE_COUNT; -+} -+ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ -+#include -+ -+static int -+ep_dump_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ if (event == DUMP_BEGIN) -+ ep_shutdown (&epsys); -+ -+ return (NOTIFY_DONE); -+} -+static struct notifier_block ep_dump_notifier = -+{ -+ notifier_call: ep_dump_event, -+ priority: 0, -+}; -+ -+#endif -+ -+static int -+ep_reboot_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ if ((event == SYS_RESTART || event == SYS_HALT || event == SYS_POWER_OFF)) -+ ep_shutdown (&epsys); -+ -+ return (NOTIFY_DONE); -+} -+ -+static struct notifier_block ep_reboot_notifier = -+{ -+ notifier_call: ep_reboot_event, -+ priority: 0, -+}; -+ -+static int -+ep_panic_event (struct notifier_block *self, unsigned long event, void *buffer) -+{ -+ ep_shutdown (&epsys); -+ -+ return (NOTIFY_DONE); -+} -+ -+static struct notifier_block ep_panic_notifier = -+{ -+ notifier_call: ep_panic_event, -+ priority: 0, -+}; -+ -+/* -+ * Module configuration. -+ */ -+#ifdef MODULE -+static int __init ep_init(void) -+#else -+__initfunc(int ep_init(void)) -+#endif -+{ -+ register int rmask = 0; -+ -+ ep_procfs_init (); -+ -+ ep_sys_init (&epsys); -+ -+#if defined(CONFIG_ELAN4) || defined(CONFIG_ELAN4_MODULE) -+ rmask = ep4_create_rails (&epsys, disabled); -+#endif -+ -+ /* If we've brought up an elan4 rail, then disable all elan3 rails. */ -+ if ((rmask & ~disabled) != 0) -+ disabled = ~rmask; -+ -+#if defined(CONFIG_ELAN3) || defined(CONFIG_ELAN3_MODULE) -+ rmask = ep3_create_rails (&epsys, disabled); -+#endif -+ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ register_dump_notifier (&ep_dump_notifier); -+#endif -+ register_reboot_notifier (&ep_reboot_notifier); -+ -+#if !defined(NO_PANIC_NOTIFIER) -+ notifier_chain_register (&panic_notifier_list, &ep_panic_notifier); -+#endif -+ -+ return (0); -+} -+ -+/* -+ * Module removal. -+ */ -+#ifdef MODULE -+static void -+__exit ep_exit(void) -+{ -+ register int i; -+ -+#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE) -+ unregister_dump_notifier (&ep_dump_notifier); -+#endif -+ unregister_reboot_notifier (&ep_reboot_notifier); -+ -+#if !defined(NO_PANIC_NOTIFIER) -+ notifier_chain_unregister (&panic_notifier_list, &ep_panic_notifier); -+#endif -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ { -+ if (epsys.Rails[i]) -+ { -+ switch (epsys.Rails[i]->State) -+ { -+ case EP_RAIL_STATE_UNINITIALISED: -+ break; -+ -+ case EP_RAIL_STATE_STARTED: -+ case EP_RAIL_STATE_RUNNING: -+ case EP_RAIL_STATE_INCOMPATIBLE: -+ /* remove per-rail CM proc entries */ -+ ep_stop_rail (epsys.Rails[i]); -+ break; -+ } -+ -+ /* remove EP proc rail entries after per-rail CM entries */ -+ ep_procfs_rail_fini (epsys.Rails[i]); -+ ep_destroy_rail (epsys.Rails[i]); -+ } -+ } -+ -+ ep_sys_fini (&epsys); -+ -+ ep_procfs_fini (); -+} -+ -+/* Declare the module init and exit functions */ -+module_init(ep_init); -+module_exit(ep_exit); -+ -+#endif -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/conf_linux.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/conf_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/conf_linux.h 2005-06-01 23:12:54.635433632 -0400 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: conf_linux.h,v 1.6 2003/10/02 14:16:07 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/conf_linux.h,v $*/ -+ -+#ifndef __ELAN_CONF_LINUX_H -+#define __ELAN_CONF_LINUX_H -+ -+extern void ep_procfs_init(void); -+extern void ep_procfs_fini(void); -+extern void ep_procfs_rail_init(EP_RAIL *rail); -+extern void ep_procfs_rail_fini(EP_RAIL *rail); -+ -+extern void ep_procfs_svc_indicator_create(int svc_indicator, char *name); -+extern void ep_procfs_svc_indicator_remove(int svc_indicator, char *name); -+ -+#endif /* __ELAN_CONF_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/debug.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/debug.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/debug.c 2005-06-01 23:12:54.635433632 -0400 -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: debug.c,v 1.28.2.1 2004/11/12 10:54:50 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/debug.c,v $*/ -+ -+#include -+ -+#include -+ -+#include "debug.h" -+ -+DisplayInfo di_ep_debug = {ep_debugf, DBG_DEBUG}; -+ -+/* -+ * Generate a partial bitmap string, for the bitmap from offset "off" for "count" bits, -+ * to allow for displaying of subsets, treat entry 0 of the bitmap as having value "base". -+ */ -+int -+ep_sprintf_bitmap (char *str, unsigned nbytes, bitmap_t *bitmap, int base, int off, int nbits) -+{ -+ char entry[12]; /* space for N-N */ -+ register int i, j, len; -+ register int notstart = off; -+ register int notfirst = 0; -+ char *p = str; -+ -+ for (i = off; i < nbits; i++) -+ { -+ if (BT_TEST (bitmap, i)) -+ { -+ for (j = i+1; j < nbits; j++) -+ if (! BT_TEST (bitmap, j)) -+ break; -+ -+ if (j == (i+1)) -+ len = (int)sprintf (entry, "%d", base + i); -+ else -+ len = (int)sprintf (entry, "%d-%d", base + i, base + j-1); -+ -+ /* NOTE the 2 is for: one for comma, one for (possible) closing bracket */ -+ if ((p - str) <= (nbytes - (len+3))) -+ p += (int)sprintf (p, "%c%s", notfirst++ ? ',' : notstart ? ' ' : '[', entry); -+ else -+ { -+ /* no more space on this line, so move onto next */ -+ sprintf (p, "%c", notfirst++ ? ',' : '['); -+ -+ return (i); -+ } -+ -+ i = j; -+ } -+ } -+ -+ if (!notfirst) -+ sprintf (str, ""); -+ else -+ strcpy (p, "]"); -+ -+ return (-1); -+} -+ -+void -+ep_display_bitmap (char *prefix, char *tag, bitmap_t *bitmap, unsigned base, unsigned nbits) -+{ -+ /* Tru64 kernel printf() truncates lines at 128 bytes - the man pages for printf (9) -+ * do not mention this restriction, nor that it does not terminate the line with a -+ * carriage return, this is pretty naff. -+ * Linux has a similar limit though is much more generous at 1024 - and you can just -+ * look at the code to see why this has been done. -+ * -+ * Our nodeset information could well be longer than 128 characters, so we're going to -+ * have to split it into a number of lines. */ -+ -+#define LINEBUF_SIZE 128 -+ char *p, linebuf[LINEBUF_SIZE+1]; /* +1 for null termination */ -+ int i, noff, off = 0; -+ -+ do { -+ if (off == 0) -+ p = linebuf + (int)sprintf (linebuf, "%s: %s ", prefix, tag); -+ else -+ { -+ p = linebuf + (int)sprintf (linebuf, "%s: ", prefix); -+ for (i = 0; tag[i] != '\0'; i++) -+ *p++ = ' '; -+ } -+ -+ noff = ep_sprintf_bitmap (p, &linebuf[LINEBUF_SIZE-1]-p, bitmap, base, off, nbits); -+ -+ printk ("%s\n", linebuf); -+ -+ } while ((off = noff) != -1); -+ -+#undef LINEBUF_SIZE -+} -+ -+void -+ep_debugf (long mode, char *fmt, ...) -+{ -+ va_list ap; -+ char prefix[32]; -+ -+ va_start (ap, fmt); -+#if defined(LINUX) -+ sprintf (prefix, "[%08d.%04d] ", (int) lbolt, current->pid); -+#else -+ sprintf (prefix, "[%08d.----] ", (int) lbolt); -+#endif -+ qsnet_vdebugf ((mode & epdebug_console ? QSNET_DEBUG_CONSOLE: 0) | QSNET_DEBUG_BUFFER, prefix, fmt, ap); -+ va_end (ap); -+} -+ -+int -+ep_assfail (EP_RAIL *rail, const char *ex, const char *func, const char *file, const int line) -+{ -+ qsnet_debugf (QSNET_DEBUG_BUFFER, "ep: assertion failure: %s, function: %s, file %s, line: %d\n", ex, func, file, line); -+ -+ printk (KERN_EMERG "ep: assertion failure: %s, function: %s, file %s, line: %d\n", ex, func, file, line); -+ -+ if (panicstr) -+ return (0); -+ -+ if (assfail_mode & 1) /* return to BUG() */ -+ return 1; -+ -+ if (assfail_mode & 2) -+ panic ("ep: assertion failure: %s, function: %s, file %s, line: %d\n", ex, func, file, line); -+ if (assfail_mode & 4) -+ epdebug = 0; -+ -+ return 0; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/debug_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/debug_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/debug_elan4.c 2005-06-01 23:12:54.636433480 -0400 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: debug_elan4.c,v 1.1 2004/05/19 10:21:04 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/debug_elan4.c,v $*/ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "conf_linux.h" -+#include "debug.h" -+ -+static void -+ep4_display_ecqs (EP4_RAIL *rail) -+{ -+ struct list_head *el; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ for (i = 0; i r_ecq_list[i]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ ep_debugf (DBG_DEBUG, "ECQ: type %d: avail %d cqnum %d\n", i, ecq->ecq_avail, elan4_cq2num (ecq->ecq_cq)); -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+} -+ -+void -+ep4_debug_rail (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP_SYS *sys = rail->r_generic.System; -+ -+ ep_debugf (DBG_DEBUG, "ep%d: is elan4 %d rev %c\n", rail->r_generic.Number, -+ rail->r_generic.Devinfo.dev_instance, 'a' + rail->r_generic.Devinfo.dev_revision_id); -+ -+ ep4_display_ecqs (rail); -+ -+ ep_display_alloc (&sys->Allocator); -+ ep_display_rmap (sys->Allocator.ResourceMap); -+ -+ ep_display_alloc (&rail->r_generic.ElanAllocator); -+ ep_display_alloc (&rail->r_generic.MainAllocator); -+ -+ ep_display_rmap (rail->r_generic.ElanAllocator.ResourceMap); -+} -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/debug.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/debug.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/debug.h 2005-06-01 23:12:54.636433480 -0400 -@@ -0,0 +1,109 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_EPDEBUG_H -+#define _ELAN3_EPDEBUG_H -+ -+#ident "$Id: debug.h,v 1.18.2.1 2004/11/12 10:54:50 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/debug.h,v $ */ -+ -+extern unsigned int epdebug; -+extern unsigned int epdebug_console; -+extern unsigned int epdebug_cmlevel; -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+extern unsigned int epdebug_check_sum; -+#endif -+#define DBG_CONFIG 0x00000001 /* Module configuration */ -+#define DBG_PROBE 0x00000002 -+#define DBG_ROUTETABLE 0x00000004 -+#define DBG_STATEMAP 0x00000008 -+ -+#define DBG_CM 0x00000020 -+#define DBG_XMTR 0x00000040 -+#define DBG_RCVR 0x00000080 -+#define DBG_FORWARD 0x00000100 -+#define DBG_DISCON 0x00000200 -+#define DBG_EPTRAP 0x00000400 -+#define DBG_COMMAND 0x00000800 -+#define DBG_RETRY 0x00001000 -+#define DBG_DEBUG 0x00002000 -+#define DBG_NETWORK_ERROR 0x00004000 -+#define DBG_MSGSYS 0x00008000 -+#define DBG_MANAGER 0x00010000 -+#define DBG_KMAP 0x00020000 -+#define DBG_FAILOVER 0x00040000 -+#define DBG_MAPNMD 0x00080000 -+#define DBG_KMSG 0x00100000 -+#define DBG_SVC 0x00200000 -+#define DBG_STABILISE 0x00400000 -+ -+#if defined(DEBUG_PRINTF) -+ -+# define EPRINTF0(m,fmt) ((epdebug&(m)) ? ep_debugf(m,fmt) : (void)0) -+# define EPRINTF1(m,fmt,a) ((epdebug&(m)) ? ep_debugf(m,fmt,a) : (void)0) -+# define EPRINTF2(m,fmt,a,b) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b) : (void)0) -+# define EPRINTF3(m,fmt,a,b,c) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c) : (void)0) -+# define EPRINTF4(m,fmt,a,b,c,d) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d) : (void)0) -+# define EPRINTF5(m,fmt,a,b,c,d,e) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d,e) : (void)0) -+# define EPRINTF6(m,fmt,a,b,c,d,e,f) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d,e,f) : (void)0) -+# define EPRINTF7(m,fmt,a,b,c,d,e,f,g) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d,e,f,g) : (void)0) -+# define EPRINTF8(m,fmt,a,b,c,d,e,f,g,h) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d,e,f,g,h) : (void)0) -+# define EPRINTF9(m,fmt,a,b,c,d,e,f,g,h,i) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d,e,f,g,h,i) : (void)0) -+# define EPRINTF10(m,fmt,a,b,c,d,e,f,g,h,i,j) ((epdebug&(m)) ? ep_debugf(m,fmt,a,b,c,d,e,f,g,h,i,j) : (void)0) -+ -+# define CPRINTF0(lvl,fmt) (((lvl) <= epdebug_cmlevel) ? EPRINTF0(DBG_CM,fmt) : (void)0) -+# define CPRINTF1(lvl,fmt,a) (((lvl) <= epdebug_cmlevel) ? EPRINTF1(DBG_CM,fmt,a) : (void)0) -+# define CPRINTF2(lvl,fmt,a,b) (((lvl) <= epdebug_cmlevel) ? EPRINTF2(DBG_CM,fmt,a,b) : (void)0) -+# define CPRINTF3(lvl,fmt,a,b,c) (((lvl) <= epdebug_cmlevel) ? EPRINTF3(DBG_CM,fmt,a,b,c) : (void)0) -+# define CPRINTF4(lvl,fmt,a,b,c,d) (((lvl) <= epdebug_cmlevel) ? EPRINTF4(DBG_CM,fmt,a,b,c,d) : (void)0) -+# define CPRINTF5(lvl,fmt,a,b,c,d,e) (((lvl) <= epdebug_cmlevel) ? EPRINTF5(DBG_CM,fmt,a,b,c,d,e) : (void)0) -+# define CPRINTF6(lvl,fmt,a,b,c,d,e,f) (((lvl) <= epdebug_cmlevel) ? EPRINTF6(DBG_CM,fmt,a,b,c,d,e,f) : (void)0) -+# define CPRINTF7(lvl,fmt,a,b,c,d,e,f,g) (((lvl) <= epdebug_cmlevel) ? EPRINTF7(DBG_CM,fmt,a,b,c,d,e,f,g) : (void)0) -+# define CPRINTF8(lvl,fmt,a,b,c,d,e,f,g,h) (((lvl) <= epdebug_cmlevel) ? EPRINTF8(DBG_CM,fmt,a,b,c,d,e,f,g,h) : (void)0) -+# define CPRINTF9(lvl,fmt,a,b,c,d,e,f,g,h,i) (((lvl) <= epdebug_cmlevel) ? EPRINTF9(DBG_CM,fmt,a,b,c,d,e,f,g,h,i) : (void)0) -+ -+#if defined __GNUC__ -+extern void ep_debugf (long mode, char *fmt, ...) __attribute__ ((format (printf,2,3))); -+#else -+extern void ep_debugf (long mode, char *fmt, ...); -+#endif -+ -+#else -+ -+# define EPRINTF0(m,fmt) (0) -+# define EPRINTF1(m,fmt,a) (0) -+# define EPRINTF2(m,fmt,a,b) (0) -+# define EPRINTF3(m,fmt,a,b,c) (0) -+# define EPRINTF4(m,fmt,a,b,c,d) (0) -+# define EPRINTF5(m,fmt,a,b,c,d,e) (0) -+# define EPRINTF6(m,fmt,a,b,c,d,e,f) (0) -+# define EPRINTF7(m,fmt,a,b,c,d,e,f,g) (0) -+# define EPRINTF8(m,fmt,a,b,c,d,e,f,g,h) (0) -+# define EPRINTF9(m,fmt,a,b,c,d,e,f,g,h,i) (0) -+# define EPRINTF9(m,fmt,a,b,c,d,e,f,g,h,i,j) (0) -+ -+# define CPRINTF0(lvl,fmt) (0) -+# define CPRINTF1(lvl,fmt,a) (0) -+# define CPRINTF2(lvl,fmt,a,b) (0) -+# define CPRINTF3(lvl,fmt,a,b,c) (0) -+# define CPRINTF4(lvl,fmt,a,b,c,d) (0) -+# define CPRINTF5(lvl,fmt,a,b,c,d,e) (0) -+# define CPRINTF6(lvl,fmt,a,b,c,d,e,f) (0) -+# define CPRINTF7(lvl,fmt,a,b,c,d,e,f,g) (0) -+# define CPRINTF8(lvl,fmt,a,b,c,d,e,f,g,h) (0) -+# define CPRINTF9(lvl,fmt,a,b,c,d,e,f,g,h,i) (0) -+ -+#endif /* DEBUG */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* _ELAN3_EPDEBUG_H */ -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_asm_elan4_thread.S -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_asm_elan4_thread.S 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_asm_elan4_thread.S 2005-06-01 23:12:54.637433328 -0400 -@@ -0,0 +1,133 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcomms_asm_elan4_thread.S,v 1.5 2004/04/25 11:25:43 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_asm_elan4_thread.S,v $*/ -+ -+#include -+#include -+ -+#include "assym_elan4.h" -+ -+/* XXXXX - registers.h */ -+#define E4_MAIN_INT_SHIFT 14 -+ -+/* -+ * c_waitevent_interrupt (E4_uint64 *commandport, E4_Event *event, E4_uint64 count, E4_uint64 intcookie) -+ */ -+ .global c_waitevent_interrupt -+c_waitevent_interrupt: -+ add %sp, -192, %sp -+ st64 %r16, [%sp + 64] // preserve call preserved registers -+ st64 %r24, [%sp + 128] // - see CALL_USED_REGISTERS. -+ mov %r16,%r16 // BUG FIX: E4 RevA -+ mov %r24,%r24 // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ -+ mov %r7, %r18 // (%r2) return pc -+1: call 2f -+ mov %sp, %r17 // (%r1) SP -+2: add %r7, (3f-1b), %r16 // (%r0) PC -+ st32 %r16, [%sp] // event source block -+ mov MAKE_EXT_CLEAN_CMD, %r23 -+ st8 %r23, [%sp+56] // event source block -+ mov %r16,%r16 // BUG FIX: E4 RevA -+ mov %r23,%r23 // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ -+ or %r9, WAIT_EVENT_CMD, %r16 ! WAIT_EVENT_CMD | event -+ sll8 %r10, 32, %r17 -+ or %r17, E4_EVENT_TYPE_VALUE(E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, 8), %r17 ! ev_CountAndType -+ mov %sp, %r18 ! ev_Source -+ mov %r8, %r19 ! ev_Dest -+ sll8 %r11, E4_MAIN_INT_SHIFT, %r20 -+ or %r20, INTERRUPT_CMD, %r20 ! INTERRUPT_CMD | (cookie << E4_MAIN_INT_SHIFT) -+ mov NOP_CMD, %r21 -+ mov NOP_CMD, %r22 -+ mov NOP_CMD, %r23 -+ -+ st64suspend %r16, [%r8] -+ -+3: ld64 [%sp + 64], %r16 // restore call preserved register -+ ld64 [%sp + 128], %r24 -+ jmpl %r2+8, %r0 // and return -+ add %sp, 192, %sp -+ -+ -+#define EP4_RCVR_PENDING_STALLED 1 /* indicates thread has stalled for no descriptor (rcvr_pending_head) */ -+ -+#define RXD_DEBUG(VAL,RXD,TMP) \ -+ mov VAL, TMP; \ -+ st8 TMP, [RXD + EP4_RXD_DEBUG] -+ -+ -+ /* -+ * %r2 - rcvr elan -+ * %r3 - rxd elan -+ */ -+ .global c_queue_rxd -+c_queue_rxd: -+ RXD_DEBUG(1, %r3, %r23) -+ -+ ld16 [%r2 + EP4_RCVR_PENDING_TAILP], %r18 /* r18 == tailp, r19 = head */ -+ add %r3, EP4_RXD_NEXT, %r4 -+ -+ st8 %r0, [%r3 + EP4_RXD_NEXT] /* rxd->rxd_next = NULL */ -+ st8 %r4, [%r2 + EP4_RCVR_PENDING_TAILP] /* tailp = &rxd->rxd_next */ -+ st8 %r3, [%r18] /* *tailp = rxd */ -+ -+ cmp %r19, EP4_RCVR_PENDING_STALLED /* thread stalled ? */ -+ beq 1f -+ mov %r18, %r16 /* must have used %r16, %r19, %r23 */ -+ mov %r3, %r23 -+ -+ RXD_DEBUG(2, %r3, %r23) -+ -+ st8suspend %r16, [%r3 + EP4_RXD_QUEUED] /* no - mark as queued - all done */ -+ -+1: st8 %r16, [%r3 + EP4_RXD_QUEUED] /* mark as queued */ -+ -+ RXD_DEBUG(3, %r3, %r23) -+ -+ mov %r3, %r8 /* return rxd from c_stall_thread */ -+ ba .epcomms_resume_thread /* resume the thread */ -+ ld64 [%r2 + EP4_RCVR_THREAD_STALL], %r0 -+ -+ /* -+ * c_stall_thread (EP4_RCVR_ELAN *rcvrElan) -+ */ -+ .global c_stall_thread -+c_stall_thread: -+ add %sp, -192, %sp -+ st64 %r16, [%sp + 64] // preserve call preserved registers -+ st64 %r24, [%sp + 128] // - see CALL_USED_REGISTERS. -+ mov %r16,%r16 // BUG FIX: E4 RevA -+ mov %r24,%r24 // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ nop // BUG FIX: E4 RevA -+ -+ mov EP4_RCVR_PENDING_STALLED, %r9 // Mark rcvr as stalled -+ st8 %r9, [%r8 + EP4_RCVR_PENDING_HEAD] -+ -+ // XXXX _ TBD should generate interrupt -+ -+ mov %r1, %r17 // SP -+ mov %r7, %r23 // return pc -+ -+ st64suspend %r16, [%r8 + EP4_RCVR_THREAD_STALL] -+ -+.epcomms_resume_thread: -+ /* %r8 == rxdElan */ -+ -+ ld64 [%sp + 64], %r16 // restore call preserved register -+ ld64 [%sp + 128], %r24 -+ jmpl %r7+8, %r0 // and return -+ add %sp, 192, %sp -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms.c 2005-06-01 23:12:54.637433328 -0400 -@@ -0,0 +1,484 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcomms.c,v 1.71.2.6 2004/11/30 12:02:16 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms.c,v $ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "cm.h" -+#include "debug.h" -+ -+static void -+ep_comms_thread (void *arg) -+{ -+ EP_COMMS_SUBSYS *subsys = (EP_COMMS_SUBSYS *) arg; -+ struct list_head *el; -+ -+ kernel_thread_init ("ep_comms"); -+ -+ /* since ep_alloc_xmtr() has incremented the module use count, -+ * we would be preventing the module from being unloaded, so -+ * we decrement the use count since this thread must terminate -+ * during unload of the module. -+ */ -+ ep_mod_dec_usecount(); -+ -+ for (;;) -+ { -+ long nextRunTime = 0; -+ -+ /* NOTE - subsys->Lock serializes us against flush/relocations -+ * caused by rail nodeset transitions. -+ */ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ nextRunTime = ep_check_xmtr (list_entry (el, EP_XMTR, Link), nextRunTime); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ nextRunTime = ep_check_rcvr (list_entry (el, EP_RCVR, Link), nextRunTime); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ ep_csum_rxds (subsys); -+#endif -+ nextRunTime = ep_forward_rxds (subsys, nextRunTime); -+ -+ if (ep_kthread_sleep (&subsys->Thread, nextRunTime) < 0) -+ break; -+ } -+ -+ ep_mod_inc_usecount(); -+ -+ ep_kthread_stopped (&subsys->Thread); -+ kernel_thread_exit(); -+} -+ -+int -+ep_comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *rail) -+{ -+ EP_COMMS_SUBSYS *subsys = (EP_COMMS_SUBSYS *) s; -+ EP_COMMS_RAIL *commsRail; -+ struct list_head *el; -+ -+ printk ("%s: vendorid=%x deviceid=%x\n", rail->Name, rail->Devinfo.dev_vendor_id, rail->Devinfo.dev_device_id); -+ -+ switch (rail->Devinfo.dev_device_id) -+ { -+#if defined(CONFIG_ELAN3) || defined(CONFIG_ELAN3_MODULE) -+ case PCI_DEVICE_ID_ELAN3: -+ commsRail = ep3comms_add_rail (s, sys, rail); -+ break; -+#endif -+#if defined(CONFIG_ELAN4) || defined(CONFIG_ELAN4_MODULE) -+ case PCI_DEVICE_ID_ELAN4: -+ commsRail = ep4comms_add_rail (s, sys, rail); -+ break; -+#endif -+ default: -+ return 0; -+ } -+ -+ if (commsRail == NULL) -+ return 1; -+ -+ commsRail->Rail = rail; -+ commsRail->Subsys = subsys; -+ -+ kmutex_lock (&subsys->Lock); -+ list_add_tail (&commsRail->Link, &subsys->Rails); -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ EP_RAIL_OP (commsRail, Rcvr.AddRail) (rcvr, commsRail); -+ } -+ -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ EP_RAIL_OP (commsRail, Xmtr.AddRail) (xmtr, commsRail); -+ } -+ -+ kmutex_unlock (&subsys->Lock); -+ -+ return 0; -+} -+ -+void -+ep_comms_del_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *rail) -+{ -+ EP_COMMS_SUBSYS *subsys = (EP_COMMS_SUBSYS *) s; -+ EP_COMMS_RAIL *commsRail = NULL; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ /* find out rail entry and remove from system list */ -+ list_for_each (el, &subsys->Rails) { -+ if ((commsRail = list_entry (el, EP_COMMS_RAIL, Link))->Rail == rail) -+ break; -+ } -+ -+ list_del (&commsRail->Link); -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ EP_RAIL_OP(commsRail, Rcvr.DelRail) (rcvr, commsRail); -+ } -+ -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ EP_RAIL_OP(commsRail,Xmtr.DelRail) (xmtr, commsRail); -+ } -+ -+ kmutex_unlock (&subsys->Lock); -+ -+ EP_RAIL_OP (commsRail, DelRail) (commsRail); -+} -+ -+void -+ep_comms_fini (EP_SUBSYS *s, EP_SYS *sys) -+{ -+ EP_COMMS_SUBSYS *subsys = (EP_COMMS_SUBSYS *) s; -+ -+ ep_kthread_stop (&subsys->Thread); -+ ep_kthread_destroy (&subsys->Thread); -+ -+ if (subsys->ForwardXmtr) -+ ep_free_xmtr (subsys->ForwardXmtr); -+ -+ spin_lock_destroy (&subsys->ForwardDescLock); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ spin_lock_destroy (&subsys->CheckSumDescLock); -+#endif -+ -+ kmutex_destroy (&subsys->Lock); -+ -+ KMEM_FREE (subsys, sizeof (EP_COMMS_SUBSYS)); -+} -+ -+int -+ep_comms_init (EP_SYS *sys) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ -+ KMEM_ZALLOC (subsys, EP_COMMS_SUBSYS *, sizeof (EP_COMMS_SUBSYS), 1); -+ -+ if (subsys == NULL) -+ return (ENOMEM); -+ -+ INIT_LIST_HEAD (&subsys->Rails); -+ INIT_LIST_HEAD (&subsys->Receivers); -+ INIT_LIST_HEAD (&subsys->Transmitters); -+ INIT_LIST_HEAD (&subsys->ForwardDescList); -+ -+ kmutex_init (&subsys->Lock); -+ spin_lock_init (&subsys->ForwardDescLock); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ INIT_LIST_HEAD (&subsys->CheckSumDescList); -+ spin_lock_init (&subsys->CheckSumDescLock); -+#endif -+ -+ subsys->Subsys.Sys = sys; -+ subsys->Subsys.Name = "epcomms"; -+ subsys->Subsys.Destroy = ep_comms_fini; -+ subsys->Subsys.AddRail = ep_comms_add_rail; -+ subsys->Subsys.RemoveRail = ep_comms_del_rail; -+ -+ ep_subsys_add (sys, &subsys->Subsys); -+ ep_kthread_init (&subsys->Thread); -+ -+ if ((subsys->ForwardXmtr = ep_alloc_xmtr (subsys->Subsys.Sys)) == NULL) -+ goto failed; -+ -+ if (kernel_thread_create (ep_comms_thread, subsys) == NULL) -+ goto failed; -+ ep_kthread_started (&subsys->Thread); -+ -+ return (0); -+ -+ failed: -+ ep_subsys_del (sys, &subsys->Subsys); -+ ep_comms_fini (&subsys->Subsys, sys); -+ -+ return (ENOMEM); -+} -+ -+void -+ep_comms_display (EP_SYS *sys, char *how) -+{ -+ EP_COMMS_SUBSYS *subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (sys, EPCOMMS_SUBSYS_NAME); -+ struct list_head *el; -+ -+ if (how == NULL || !strncmp (how, "rail", 4)) -+ { -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ EP_RAIL_OP(commsRail, DisplayRail) (commsRail); -+ } -+ kmutex_unlock (&subsys->Lock); -+ } -+ -+ if (how == NULL || !strncmp (how, "xmtr", 4)) -+ list_for_each (el, &subsys->Transmitters) -+ ep_display_xmtr (&di_ep_debug, list_entry (el, EP_XMTR, Link)); -+ -+ if (how == NULL || !strncmp (how, "rcvr", 4)) -+ list_for_each (el, &subsys->Receivers) -+ ep_display_rcvr (&di_ep_debug, list_entry (el, EP_RCVR, Link), (how && how[4] == ',') ? 1 : 0); -+} -+ -+int -+ep_svc_indicator_set (EP_SYS *epsys, int svc_indicator) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ struct list_head *el; -+ -+ EPRINTF1 (DBG_SVC,"ep_svc_indicator_set: %d \n",svc_indicator); -+ -+ if (svc_indicator < 0 || svc_indicator > EP_SVC_NUM_INDICATORS) -+ return (EP_EINVAL); -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (epsys, "epcomms")) == NULL) { -+ EPRINTF0 (DBG_SVC,"ep_svc_indicator_set: ep_subsys_find failed\n"); -+ return (EP_EINVAL); -+ } -+ -+ -+ kmutex_lock (&subsys->Lock); /* walking rails list and setting info on Rail */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ cm_svc_indicator_set(commsRail->Rail, svc_indicator); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ EPRINTF1 (DBG_SVC,"ep_svc_indicator_set: %d success\n",svc_indicator); -+ return (EP_SUCCESS); -+} -+ -+int -+ep_svc_indicator_clear (EP_SYS *epsys, int svc_indicator) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ struct list_head *el; -+ -+ EPRINTF1 (DBG_SVC,"ep_svc_indicator_clear: %d \n",svc_indicator); -+ -+ if (svc_indicator < 0 || svc_indicator >= EP_SVC_NUM_INDICATORS) -+ return (EP_EINVAL); -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (epsys, "epcomms")) == NULL) { -+ EPRINTF0 (DBG_SVC,"ep_svc_indicator_clear: ep_subsys_find failed\n"); -+ return (EP_EINVAL); -+ } -+ -+ kmutex_lock (&subsys->Lock); /* walking rails list and setting info on Rail */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ cm_svc_indicator_clear(commsRail->Rail, svc_indicator); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ EPRINTF1 (DBG_SVC,"ep_svc_indicator_clear: %d success\n",svc_indicator); -+ return (EP_SUCCESS); -+} -+ -+int -+ep_svc_indicator_is_set (EP_SYS *epsys, int svc_indicator, int nodeId) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ struct list_head *el; -+ int set = 0; -+ -+ EPRINTF2 (DBG_SVC,"ep_svc_indicator_is_set: svc %d node %d \n", svc_indicator, nodeId); -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (epsys, "epcomms")) == NULL) { -+ EPRINTF0 (DBG_SVC,"ep_svc_indicator_is_set: ep_subsys_find failed\n"); -+ return (0); -+ } -+ -+ kmutex_lock (&subsys->Lock); /* walking rails list and setting info on Rail */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ set |= cm_svc_indicator_is_set(commsRail->Rail, svc_indicator, nodeId); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ EPRINTF3 (DBG_SVC,"ep_svc_indicator_is_set: svc %d node %d returning %d\n", svc_indicator, nodeId, set); -+ return set; -+} -+ -+int -+ep_svc_indicator_bitmap (EP_SYS *epsys, int svc_indicator, bitmap_t * bitmap, int low, int nnodes) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ struct list_head *el; -+ -+ EPRINTF1 (DBG_SVC,"ep_svc_indicator_bitmap: svc %d\n", svc_indicator); -+ -+ if (svc_indicator < 0 || svc_indicator >= EP_SVC_NUM_INDICATORS) -+ return (-1); -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (epsys, "epcomms")) == NULL) { -+ EPRINTF0 (DBG_SVC,"ep_svc_indicator_bitmap: ep_subsys_find failed\n"); -+ return (-2); -+ } -+ -+ /* clear bitmap */ -+ bt_zero (bitmap, nnodes); -+ -+ kmutex_lock (&subsys->Lock); /* walking rails list and setting info on Rail */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ /* this will or in each bit map */ -+ cm_svc_indicator_bitmap (commsRail->Rail, svc_indicator, bitmap, low, nnodes); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ return (0); -+} -+ -+int -+ep_xmtr_svc_indicator_bitmap (EP_XMTR *xmtr, int svc_indicator, bitmap_t * bitmap, int low, int nnodes) -+{ -+ int i; -+ -+ EPRINTF1 (DBG_SVC,"ep_xmtr_svc_indicator_bitmap: svc %d\n", svc_indicator); -+ -+ if (svc_indicator < 0 || svc_indicator >= EP_SVC_NUM_INDICATORS) -+ return (-1); -+ -+ /* clear bitmap */ -+ bt_zero (bitmap, nnodes); -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ { -+ if (xmtr->RailMask & (1 << i) ) -+ { -+ /* this will or in each bit map */ -+ cm_svc_indicator_bitmap (xmtr->Rails[i]->CommsRail->Rail, svc_indicator, bitmap, low, nnodes); -+ } -+ } -+ -+ return (0); -+} -+ -+EP_RAILMASK -+ep_svc_indicator_railmask (EP_SYS *epsys, int svc_indicator, int nodeId) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ struct list_head *el; -+ EP_RAILMASK rmask=0; -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (epsys, "epcomms")) == NULL) -+ return (rmask); -+ -+ kmutex_lock (&subsys->Lock); /* walking rails list and reading info from Rail */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ if ( cm_svc_indicator_is_set(commsRail->Rail, svc_indicator,nodeId)) -+ rmask |= EP_RAIL2RAILMASK(commsRail->Rail->Number); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ return (rmask); -+} -+ -+EP_RAILMASK -+ep_xmtr_svc_indicator_railmask (EP_XMTR *xmtr, int svc_indicator, int nodeId) -+{ -+ EP_RAILMASK rmask=0; -+ EP_COMMS_RAIL *commsRail; -+ int i; -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ { -+ if (xmtr->RailMask & (1 << i) ) -+ { -+ commsRail = xmtr->Rails[i]->CommsRail; -+ -+ if ( cm_svc_indicator_is_set(commsRail->Rail, svc_indicator,nodeId)) -+ rmask |= EP_RAIL2RAILMASK(commsRail->Rail->Number); -+ } -+ } -+ -+ EPRINTF3 (DBG_SVC, "ep_xmtr_svc_indicator_railmask: svc %d node %d mask 0x%x\n", svc_indicator, nodeId, rmask); -+ -+ return (rmask); -+} -+ -+EP_RAILMASK -+ep_rcvr_railmask (EP_SYS *epsys, EP_SERVICE service) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ EP_RAILMASK rmask=0; -+ struct list_head *el; -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (epsys, "epcomms")) == NULL) -+ return (rmask); -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Service == service) -+ rmask |= rcvr->RailMask; -+ } -+ kmutex_unlock(&subsys->Lock); -+ -+ return (rmask); -+} -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+uint32_t -+ep_calc_check_sum (EP_SYS *sys, EP_ENVELOPE *env, EP_NMD *nmd, int nFrags) -+{ -+ EP_NMH *nmh; -+ int i; -+ uint16_t check_data = 0; -+ uint16_t check_env = 0; -+ -+ for (i = 0; i < nFrags; i++) { -+ /* find the nmh for this frag */ -+ nmh = ep_nmh_find (&sys->MappingTable, &nmd[i]); -+ -+ ASSERT( nmh != NULL); -+ -+ /* add the next frag to the check sum */ -+ check_data = nmh->nmh_ops->op_calc_check_sum (sys, nmh, &nmd[i], check_data); -+ } -+ -+ check_env = rolling_check_sum ((char *) env, offsetof(EP_ENVELOPE, CheckSum), 0); -+ -+ return (EP_ENVELOPE_CHECK_SUM | ( (check_env & 0x7FFF) << 16) | (check_data & 0xFFFF)); -+} -+#endif -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan3.c 2005-06-01 23:12:54.638433176 -0400 -@@ -0,0 +1,191 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcomms_elan3.c,v 1.60 2004/08/03 11:34:34 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_elan3.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "kcomm_elan3.h" -+#include "epcomms_elan3.h" -+ -+void -+ep3comms_flush_callback (void *arg, statemap_t *map) -+{ -+ EP_COMMS_RAIL *commsRail = (EP_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->Subsys; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[commsRail->Rail->Number]) -+ ep3xmtr_flush_callback (xmtr, (EP3_XMTR_RAIL *) xmtr->Rails[commsRail->Rail->Number]); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[commsRail->Rail->Number]) -+ ep3rcvr_flush_callback (rcvr, (EP3_RCVR_RAIL *) rcvr->Rails[commsRail->Rail->Number]); -+ } -+ kmutex_unlock (&subsys->Lock); -+} -+ -+void -+ep3comms_failover_callback (void *arg, statemap_t *map) -+{ -+ EP_COMMS_RAIL *commsRail = (EP_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->Subsys; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[commsRail->Rail->Number]) -+ ep3xmtr_failover_callback (xmtr, (EP3_XMTR_RAIL *) xmtr->Rails[commsRail->Rail->Number]); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[commsRail->Rail->Number]) -+ ep3rcvr_failover_callback (rcvr, (EP3_RCVR_RAIL *) rcvr->Rails[commsRail->Rail->Number]); -+ } -+ kmutex_unlock (&subsys->Lock); -+} -+ -+void -+ep3comms_disconnect_callback (void *arg, statemap_t *map) -+{ -+ EP_COMMS_RAIL *commsRail = (EP_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->Subsys; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[commsRail->Rail->Number]) -+ ep3xmtr_disconnect_callback (xmtr, (EP3_XMTR_RAIL *) xmtr->Rails[commsRail->Rail->Number]); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[commsRail->Rail->Number]) -+ ep3rcvr_disconnect_callback (rcvr, (EP3_RCVR_RAIL *) rcvr->Rails[commsRail->Rail->Number]); -+ } -+ kmutex_unlock (&subsys->Lock); -+} -+ -+EP_COMMS_RAIL * -+ep3comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ ELAN3_DEV *dev = rail->Device; -+ EP3_COMMS_RAIL *commsRail; -+ EP3_InputQueue qdesc; -+ int i; -+ -+ KMEM_ZALLOC (commsRail, EP3_COMMS_RAIL *, sizeof (EP3_COMMS_RAIL), TRUE); -+ -+ if (commsRail == NULL) -+ return NULL; -+ -+ commsRail->Generic.Ops.DelRail = ep3comms_del_rail; -+ commsRail->Generic.Ops.DisplayRail = ep3comms_display_rail; -+ commsRail->Generic.Ops.Rcvr.AddRail = ep3rcvr_add_rail; -+ commsRail->Generic.Ops.Rcvr.DelRail = ep3rcvr_del_rail; -+ commsRail->Generic.Ops.Rcvr.Check = ep3rcvr_check; -+ commsRail->Generic.Ops.Rcvr.QueueRxd = ep3rcvr_queue_rxd; -+ commsRail->Generic.Ops.Rcvr.RpcPut = ep3rcvr_rpc_put; -+ commsRail->Generic.Ops.Rcvr.RpcGet = ep3rcvr_rpc_get; -+ commsRail->Generic.Ops.Rcvr.RpcComplete = ep3rcvr_rpc_complete; -+ -+ commsRail->Generic.Ops.Rcvr.StealRxd = ep3rcvr_steal_rxd; -+ -+ commsRail->Generic.Ops.Rcvr.FillOutRailStats = ep3rcvr_fillout_rail_stats; -+ -+ commsRail->Generic.Ops.Rcvr.DisplayRcvr = ep3rcvr_display_rcvr; -+ commsRail->Generic.Ops.Rcvr.DisplayRxd = ep3rcvr_display_rxd; -+ -+ commsRail->Generic.Ops.Xmtr.AddRail = ep3xmtr_add_rail; -+ commsRail->Generic.Ops.Xmtr.DelRail = ep3xmtr_del_rail; -+ commsRail->Generic.Ops.Xmtr.Check = ep3xmtr_check; -+ commsRail->Generic.Ops.Xmtr.BindTxd = ep3xmtr_bind_txd; -+ commsRail->Generic.Ops.Xmtr.UnbindTxd = ep3xmtr_unbind_txd; -+ commsRail->Generic.Ops.Xmtr.PollTxd = ep3xmtr_poll_txd; -+ commsRail->Generic.Ops.Xmtr.CheckTxdState = ep3xmtr_check_txd_state; -+ -+ commsRail->Generic.Ops.Xmtr.DisplayXmtr = ep3xmtr_display_xmtr; -+ commsRail->Generic.Ops.Xmtr.DisplayTxd = ep3xmtr_display_txd; -+ -+ commsRail->Generic.Ops.Xmtr.FillOutRailStats = ep3xmtr_fillout_rail_stats; -+ -+ /* Allocate the input queues at their fixed elan address */ -+ if (! (commsRail->QueueDescs = ep_alloc_memory_elan (r, EP_EPCOMMS_QUEUE_BASE, roundup (EP_MSG_NSVC * sizeof (EP3_InputQueue), PAGESIZE), EP_PERM_ALL, 0))) -+ { -+ KMEM_FREE (commsRail, sizeof (EP3_COMMS_RAIL)); -+ return NULL; -+ } -+ -+ qdesc.q_state = E3_QUEUE_FULL; -+ qdesc.q_base = 0; -+ qdesc.q_top = 0; -+ qdesc.q_fptr = 0; -+ qdesc.q_bptr = 0; -+ qdesc.q_size = 0; -+ qdesc.q_event.ev_Count = 0; -+ qdesc.q_event.ev_Type = 0; -+ -+ /* Initialise all queue entries to be full */ -+ for (i = 0; i < EP_MSG_NSVC; i++) -+ elan3_sdram_copyl_to_sdram (dev, &qdesc, commsRail->QueueDescs + (i * sizeof (EP3_InputQueue)), sizeof (EP3_InputQueue)); -+ -+ ep_register_callback (r, EP_CB_FLUSH_FILTERING, ep3comms_flush_callback, commsRail); -+ ep_register_callback (r, EP_CB_FLUSH_FLUSHING, ep3comms_flush_callback, commsRail); -+ ep_register_callback (r, EP_CB_FAILOVER, ep3comms_failover_callback, commsRail); -+ ep_register_callback (r, EP_CB_DISCONNECTING, ep3comms_disconnect_callback, commsRail); -+ -+ return (EP_COMMS_RAIL *) commsRail; -+} -+ -+void -+ep3comms_del_rail (EP_COMMS_RAIL *r) -+{ -+ EP3_COMMS_RAIL *commsRail = (EP3_COMMS_RAIL *) r; -+ EP_RAIL *rail = commsRail->Generic.Rail; -+ -+ ep_remove_callback (rail, EP_CB_FLUSH_FILTERING, ep3comms_flush_callback, commsRail); -+ ep_remove_callback (rail, EP_CB_FLUSH_FLUSHING, ep3comms_flush_callback, commsRail); -+ ep_remove_callback (rail, EP_CB_FAILOVER, ep3comms_failover_callback, commsRail); -+ ep_remove_callback (rail, EP_CB_DISCONNECTING, ep3comms_disconnect_callback, commsRail); -+ -+ ep_free_memory_elan (rail, EP_EPCOMMS_QUEUE_BASE); -+ -+ KMEM_FREE (commsRail, sizeof (EP3_COMMS_RAIL)); -+} -+ -+void -+ep3comms_display_rail (EP_COMMS_RAIL *r) -+{ -+ -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan3.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_elan3.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan3.h 2005-06-01 23:12:54.639433024 -0400 -@@ -0,0 +1,330 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __EPCOMMS_ELAN3_H -+#define __EPCOMMS_ELAN3_H -+ -+#ident "@(#)$Id: epcomms_elan3.h,v 1.27.2.1 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_elan3.h,v $ */ -+ -+#define EP3_DMAFAILCOUNT 3 -+ -+ -+/* Main/Elan spinlock */ -+typedef struct ep3_spinlock_elan -+{ -+ volatile E3_uint32 sl_lock; /* main wants a lock */ -+ volatile E3_uint32 sl_seq; /* thread owns this word */ -+ /* NOTE: The lock/seq words must be within the same 32-byte Elan cache-line */ -+ E3_uint64 sl_pad[14]; /* pad to 64-bytes */ -+} EP3_SPINLOCK_ELAN; -+ -+/* Declare this as a main memory cache block for efficiency */ -+typedef struct ep3_spinlock_main { -+ volatile E3_uint32 sl_seq; /* copy of seq number updated by Elan */ -+ volatile E3_uint32 sl_pad[15]; /* pad to 64-bytes */ -+} EP3_SPINLOCK_MAIN; -+ -+#if defined (__ELAN3__) -+ -+extern void ep3_spinblock (EP3_SPINLOCK_ELAN *, EP3_SPINLOCK_MAIN *); -+ -+#define EP3_SPINENTER(SLE,SL) \ -+do {\ -+ (SLE)->sl_seq++; \ -+ if ((SLE)->sl_lock) \ -+ ep3_spinblock(SLE, SL);\ -+} while (0) -+ -+#define EP3_SPINEXIT(SLE,SL) \ -+do {\ -+ (SL)->sl_seq = (SLE)->sl_seq;\ -+} while (0) -+ -+#else -+ -+#define EP3_SPINENTER(DEV,SLE,SL) do { \ -+ E3_uint32 seq; \ -+\ -+ mb();\ -+ elan3_sdram_writel (DEV, (SLE) + offsetof (EP3_SPINLOCK_ELAN, sl_lock), 1);\ -+ mb();\ -+ seq = elan3_sdram_readl (DEV, (SLE) + offsetof (EP3_SPINLOCK_ELAN, sl_seq));\ -+ while (seq != (SL)->sl_seq)\ -+ {\ -+ while ((SL)->sl_seq == (seq - 1))\ -+ {\ -+ mb();\ -+\ -+ DELAY (1); \ -+ }\ -+ seq = elan3_sdram_readl (DEV, (SLE) + offsetof (EP3_SPINLOCK_ELAN, sl_seq));\ -+ }\ -+} while (0) -+ -+#define EP3_SPINEXIT(DEV,SLE,SL) do { \ -+ wmb(); \ -+ elan3_sdram_writel (DEV, (SLE) + offsetof (EP3_SPINLOCK_ELAN, sl_lock), 0);\ -+ mmiob(); \ -+} while (0) -+ -+#endif /* ! __ELAN3__ */ -+ -+/* per-rail elan memory portion receive descriptor */ -+typedef struct ep3_rxd_rail_elan -+{ -+ E3_DMA Dmas[EP_MAXFRAG+1]; /* Dma's for fetching data/putting data & status blk */ -+ E3_Event ChainEvent[EP_MAXFRAG]; /* Events to chain dmas */ -+ E3_BlockCopyEvent DataEvent; /* message received block event */ -+ E3_BlockCopyEvent DoneEvent; /* RPC status block event */ -+ -+ EP_NMD Data; /* Network mapping handle for receive data */ -+ -+ E3_Addr RxdMain; /* pointer to main memory portion */ -+ -+ E3_Addr Next; /* linked list when on pending list (elan address) */ -+ -+ E3_uint64 MainAddr; /* kernel address of ep_rxd_main */ -+} EP3_RXD_RAIL_ELAN; -+ -+#define EP3_RXD_RAIL_ELAN_SIZE roundup (sizeof (EP3_RXD_RAIL_ELAN), E3_DMA_ALIGN) -+ -+/* per-rail main memory portion of receive descriptor */ -+typedef struct ep3_rxd_rail_main -+{ -+ E3_uint32 DataEvent; /* dest for done event */ -+ E3_uint32 DoneEvent; /* dest for done event */ -+} EP3_RXD_RAIL_MAIN; -+ -+#define EP3_RXD_RAIL_MAIN_SIZE roundup (sizeof(EP3_RXD_RAIL_MAIN), sizeof (E3_uint32)) -+ -+#if !defined(__ELAN3__) -+/* Kernel memory portion of per-rail receive descriptor */ -+typedef struct ep3_rxd_rail -+{ -+ EP_RXD_RAIL Generic; /* generic rxd rail */ -+ -+ EP3_COOKIE DataCookie; /* Event cookie */ -+ EP3_COOKIE DoneCookie; /* Event cookie */ -+ EP3_COOKIE ChainCookie[EP_MAXFRAG]; /* Event cookie */ -+ -+ sdramaddr_t RxdElan; /* per-rail elan receive descriptor */ -+ E3_Addr RxdElanAddr; /* and elan address */ -+ -+ EP3_RXD_RAIL_MAIN *RxdMain; /* per-rail main receive descriptor */ -+ E3_Addr RxdMainAddr; /* and elan address */ -+ -+ EP_BACKOFF Backoff; /* dma backoff */ -+} EP3_RXD_RAIL; -+ -+#define EP3_NUM_RXD_PER_BLOCK 16 -+ -+typedef struct ep3_rxd_rail_block -+{ -+ struct list_head Link; -+ -+ EP3_RXD_RAIL Rxd[EP3_NUM_RXD_PER_BLOCK]; -+} EP3_RXD_RAIL_BLOCK; -+ -+#endif /* ! __ELAN3__ */ -+ -+typedef struct ep3_rcvr_rail_elan /* Elan memory service structure */ -+{ -+ EP3_SPINLOCK_ELAN ThreadLock; /* elan memory portion of spin lock */ -+ EP3_SPINLOCK_ELAN PendingLock; /* spin lock for pending rx list */ -+ -+ E3_Addr PendingDescs; /* list of pending receive descriptors */ -+ E3_uint32 ThreadShouldHalt; /* marks that the thread should halt */ -+ -+ E3_uint64 MainAddr; /* kernel address of ep_rcvr (for StallThreadForNoDescs)*/ -+} EP3_RCVR_RAIL_ELAN; -+ -+typedef struct ep3_rcvr_rail_main /* Main memory service strucure */ -+{ -+ EP3_SPINLOCK_MAIN ThreadLock; /* main memory portion of spin lock */ -+ EP3_SPINLOCK_MAIN PendingLock; /* spinlock for pending rx list */ -+ -+ volatile unsigned PendingDescsTailp; /* next pointer of last receive descriptor on pending list */ -+} EP3_RCVR_RAIL_MAIN; -+ -+#if !defined(__ELAN3__) -+ -+typedef struct ep3_rcvr_rail_stats -+{ -+ unsigned long some_stat; -+} EP3_RCVR_RAIL_STATS; -+ -+typedef struct ep3_rcvr_rail -+{ -+ EP_RCVR_RAIL Generic; /* generic portion */ -+ -+ EP3_RCVR_RAIL_MAIN *RcvrMain; -+ E3_Addr RcvrMainAddr; -+ sdramaddr_t RcvrElan; -+ E3_Addr RcvrElanAddr; -+ -+ sdramaddr_t InputQueueBase; /* base of receive queue */ -+ E3_Addr InputQueueAddr; /* elan address of receive queue */ -+ -+ E3_Addr ThreadStack; /* Thread processor stack */ -+ E3_Addr ThreadWaiting; /* Elan thread is waiting as no receive descriptors pending (sp stored here ) */ -+ E3_Addr ThreadHalted; /* Elan thread is waiting as it was requested to halt */ -+ -+ struct list_head FreeDescList; /* freelist of per-rail receive descriptors */ -+ unsigned int FreeDescCount; /* and number on free list */ -+ unsigned int TotalDescCount; /* total number created */ -+ spinlock_t FreeDescLock; /* and lock for free list */ -+ struct list_head DescBlockList; /* list of receive descriptor blocks */ -+ -+ unsigned int FreeDescWaiting; /* waiting for descriptors to be freed */ -+ kcondvar_t FreeDescSleep; /* and sleep here */ -+ -+ unsigned int CleanupWaiting; /* waiting for cleanup */ -+ kcondvar_t CleanupSleep; /* and sleep here */ -+ -+ EP3_RCVR_RAIL_STATS stats; /* elan3 specific rcvr_rail stats */ -+} EP3_RCVR_RAIL; -+ -+#endif /* ! __ELAN3__ */ -+ -+/* per-rail portion of transmit descriptor */ -+typedef struct ep3_txd_rail_elan -+{ -+ EP_ENVELOPE Envelope; /* message envelope */ -+ EP_PAYLOAD Payload; /* message payload */ -+ -+ E3_BlockCopyEvent EnveEvent; /* envelope event */ -+ E3_BlockCopyEvent DataEvent; /* data transfer event */ -+ E3_BlockCopyEvent DoneEvent; /* rpc done event */ -+} EP3_TXD_RAIL_ELAN; -+ -+#define EP3_TXD_RAIL_ELAN_SIZE roundup (sizeof (EP3_TXD_RAIL_ELAN), E3_BLK_ALIGN) -+ -+typedef struct ep3_txd_rail_main -+{ -+ E3_uint32 EnveEvent; /* dest for envelope event */ -+ E3_uint32 DataEvent; /* dest for data transfer event */ -+ E3_uint32 DoneEvent; /* dest for rpc done event */ -+} EP3_TXD_RAIL_MAIN; -+ -+#define EP3_TXD_RAIL_MAIN_SIZE roundup (sizeof(EP3_TXD_RAIL_MAIN), E3_BLK_ALIGN) -+ -+#if !defined(__ELAN3__) -+ -+typedef struct ep3_txd_rail -+{ -+ EP_TXD_RAIL Generic; /* generic txd rail */ -+ -+ EP3_COOKIE EnveCookie; /* Event cookies */ -+ EP3_COOKIE DataCookie; -+ EP3_COOKIE DoneCookie; -+ -+ sdramaddr_t TxdElan; /* Elan TX descriptor */ -+ E3_Addr TxdElanAddr; /* and elan address */ -+ -+ EP3_TXD_RAIL_MAIN *TxdMain; /* Elan Main memory tx descriptor */ -+ E3_Addr TxdMainAddr; /* and elan address */ -+ -+ EP_BACKOFF Backoff; /* dma backoff */ -+} EP3_TXD_RAIL; -+ -+ -+#define EP3_NUM_TXD_PER_BLOCK 16 -+ -+typedef struct ep3_txd_rail_block -+{ -+ struct list_head Link; -+ -+ EP3_TXD_RAIL Txd[EP3_NUM_TXD_PER_BLOCK]; -+} EP3_TXD_RAIL_BLOCK; -+ -+typedef struct ep3_xmtr_rail_stats -+{ -+ unsigned long some_stat; -+} EP3_XMTR_RAIL_STATS; -+ -+typedef struct ep3_xmtr_rail -+{ -+ EP_XMTR_RAIL Generic; /* generic portion */ -+ -+ struct list_head FreeDescList; /* freelist of per-rail receive descriptors */ -+ unsigned int FreeDescCount; /* and number on free list */ -+ unsigned int TotalDescCount; -+ spinlock_t FreeDescLock; /* and lock for free list */ -+ struct list_head DescBlockList; /* list of receive descriptor blocks */ -+ -+ unsigned int FreeDescWaiting; /* waiting for descriptors to be freed */ -+ kcondvar_t FreeDescSleep; /* and sleep here */ -+ -+ EP3_XMTR_RAIL_STATS stats; /* elan3 specific xmtr rail stats */ -+} EP3_XMTR_RAIL; -+ -+typedef struct ep3_comms_rail -+{ -+ EP_COMMS_RAIL Generic; /* generic comms rail */ -+ sdramaddr_t QueueDescs; /* input queue descriptors */ -+} EP3_COMMS_RAIL; -+ -+/* epcommxTx_elan3.c */ -+extern void ep3xmtr_flush_callback (EP_XMTR *xmtr, EP3_XMTR_RAIL *xmtrRail); -+extern void ep3xmtr_failover_callback (EP_XMTR *xmtr, EP3_XMTR_RAIL *xmtrRail); -+extern void ep3xmtr_disconnect_callback (EP_XMTR *xmtr, EP3_XMTR_RAIL *xmtrRail); -+ -+/* epcommsRx_elan3.c */ -+extern void CompleteEnvelope (EP3_RAIL *rail, E3_Addr rxdMainAddr, E3_uint32 PAckVal); -+extern void StallThreadForNoDescs (EP3_RAIL *rail, E3_Addr rcvrElanAddr, E3_Addr sp); -+extern void StallThreadForHalted (EP3_RAIL *rail, E3_Addr rcvrElanAddr, E3_Addr sp); -+ -+extern void ep3rcvr_flush_callback (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail); -+extern void ep3rcvr_failover_callback (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail); -+extern void ep3rcvr_disconnect_callback (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail); -+ -+/* epcomms_elan3.c */ -+extern EP_COMMS_RAIL *ep3comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *r); -+extern void ep3comms_del_rail (EP_COMMS_RAIL *r); -+extern void ep3comms_display_rail (EP_COMMS_RAIL *r); -+ -+/* epcommsTx_elan3.c */ -+extern int ep3xmtr_bind_txd (EP_TXD *txd, EP_XMTR_RAIL *xmtrRail, unsigned int phase); -+extern void ep3xmtr_unbind_txd (EP_TXD *txd, unsigned int phase); -+extern int ep3xmtr_poll_txd (EP_XMTR_RAIL *xmtrRail, EP_TXD_RAIL *txdRail, int how); -+extern long ep3xmtr_check (EP_XMTR_RAIL *xmtrRail, long nextRunTime); -+extern void ep3xmtr_add_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail); -+extern void ep3xmtr_del_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail); -+extern int ep3xmtr_check_txd_state(EP_TXD *txd); -+ -+extern void ep3xmtr_display_xmtr (DisplayInfo *di, EP_XMTR_RAIL *xmtrRail); -+extern void ep3xmtr_display_txd (DisplayInfo *di, EP_TXD_RAIL *txdRail); -+ -+extern void ep3xmtr_fillout_rail_stats (EP_XMTR_RAIL *xmtr_rail, char *str); -+ -+/* epcommsRx_elan3.c */ -+extern int ep3rcvr_queue_rxd (EP_RXD *rxd, EP_RCVR_RAIL *rcvrRail); -+extern void ep3rcvr_rpc_put (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+extern void ep3rcvr_rpc_get (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+extern void ep3rcvr_rpc_complete (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+ -+extern EP_RXD *ep3rcvr_steal_rxd (EP_RCVR_RAIL *rcvrRail); -+ -+extern long ep3rcvr_check (EP_RCVR_RAIL *rcvrRail, long nextRunTime); -+extern void ep3rcvr_add_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *rail); -+extern void ep3rcvr_del_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *rail); -+ -+extern void ep3rcvr_display_rcvr (DisplayInfo *di, EP_RCVR_RAIL *rcvrRail); -+extern void ep3rcvr_display_rxd (DisplayInfo *di, EP_RXD_RAIL *rxdRail); -+ -+extern void ep3rcvr_fillout_rail_stats (EP_RCVR_RAIL *rcvr_rail, char *str); -+ -+#endif /* !defined(__ELAN3__) */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __EPCOMMS_ELAN3_H */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan3_thread.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_elan3_thread.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan3_thread.c 2005-06-01 23:12:54.640432872 -0400 -@@ -0,0 +1,296 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcomms_elan3_thread.c,v 1.4 2004/01/20 11:03:15 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_elan3_thread.c,v $ */ -+ -+//#include -+ -+typedef char int8_t; -+typedef unsigned char uint8_t; -+typedef short int16_t; -+typedef unsigned short uint16_t; -+typedef int int32_t; -+typedef unsigned int uint32_t; -+typedef long long int64_t; -+typedef unsigned long long uint64_t; -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "epcomms_elan3.h" -+ -+#ifndef offsetof -+#define offsetof(s, m) (unsigned long)(&(((s *)0)->m)) -+#endif -+ -+EP3_RAIL_ELAN *rail; -+EP3_RCVR_RAIL_ELAN *r; -+EP3_RCVR_RAIL_MAIN *rm; -+ -+void -+ep3comms_rcvr (EP3_RAIL_ELAN *rail, EP3_RCVR_RAIL_ELAN *rcvrElan, EP3_RCVR_RAIL_MAIN *rcvrMain, -+ EP3_InputQueue *q, unsigned int *cookies) -+{ -+ int count = 1; -+ E3_Addr nfptr = q->q_fptr + q->q_size; -+ E3_uint32 tmp; -+ int i; -+ E3_Addr buffer; -+ int len; -+ E3_DMA *dma; -+ E3_Event *event; -+ -+ /* clear the queue state to allow envelopes to arrive */ -+ q->q_state = 0; -+ -+ for (;;) -+ { -+ if (! rcvrElan->ThreadShouldHalt) -+ c_waitevent ((E3_Event *) &q->q_event, count); /* HALT POINT */ -+ -+ if (rcvrElan->ThreadShouldHalt && nfptr == q->q_bptr) -+ { -+ asm volatile ("mov %0, %%g1" : /* no outputs */ : "r" (rcvrElan)); -+ asm volatile ("ta %0" : /* no outputs */ : "i" (EP3_UNIMP_THREAD_HALTED)); /* HALT POINT */ -+ continue; -+ } -+ -+ count = 0; -+ do { -+ /* Process the message at nfptr */ -+ EP_ENVELOPE *env = (EP_ENVELOPE *) nfptr; -+ EP3_RXD_RAIL_ELAN *rxd; -+ int ack; -+ -+ EP3_SPINENTER(&rcvrElan->ThreadLock, &rcvrMain->ThreadLock); /* HALT POINT */ -+ -+ while ((rxd = (EP3_RXD_RAIL_ELAN *)rcvrElan->PendingDescs) == 0) -+ { -+ /* no receive descriptors, so trap to the kernel to wait -+ * for receive descriptor to be queued, we pass the rcvr -+ * in %g1, so that the trap handler can restart us. */ -+ EP3_SPINEXIT(&rcvrElan->ThreadLock, &rcvrMain->ThreadLock); -+ asm volatile ("mov %0, %%g1" : /* no outputs */ : "r" (rcvrElan)); -+ asm volatile ("ta %0" : /* no outputs */ : "i" (EP3_UNIMP_TRAP_NO_DESCS)); /* HALT POINT */ -+ EP3_SPINENTER(&rcvrElan->ThreadLock, &rcvrMain->ThreadLock); /* HALT POINT */ -+ } -+ -+ if (env->Version != EP_ENVELOPE_VERSION) -+ { -+ /* This envelope has been cancelled - so just consume it */ -+ EP3_SPINEXIT(&rcvrElan->ThreadLock, &rcvrMain->ThreadLock); -+ goto consume_envelope; -+ } -+ -+ dma = rxd->Dmas; -+ event = rxd->ChainEvent; -+ -+ if (EP_IS_MULTICAST(env->Attr)) -+ { -+ dma->dma_type = E3_DMA_TYPE (DMA_BYTE, DMA_READ, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dma->dma_size = BT_BITOUL(EP_MAX_NODES) * sizeof (bitmap_t); -+ dma->dma_source = env->TxdMain.nmd_addr + offsetof (EP_TXD_MAIN, Bitmap); -+ dma->dma_dest = (E3_Addr) &((EP_RXD_MAIN *) rxd->RxdMain)->Bitmap; -+ dma->dma_destEvent = (E3_Addr) event; -+ dma->dma_destCookieVProc = DMA_COOKIE_THREAD | DMA_COOKIE (cookies[env->NodeId], EP_VP_DATA (rail->NodeId)); -+ dma->dma_srcEvent = env->TxdRail + offsetof (EP3_TXD_RAIL_ELAN, DataEvent); -+ dma->dma_srcCookieVProc = DMA_COOKIE_THREAD | DMA_REMOTE_COOKIE (cookies[env->NodeId], EP_VP_DATA (env->NodeId)); -+ -+ event->ev_Count = 1; -+ -+ dma++; event++; -+ } -+ -+ if (env->nFrags == 0) -+ { -+ /* Generate a "get" DMA to accept the envelope and fire the rx handler */ -+ dma->dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_READ, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dma->dma_size = 0; -+ dma->dma_destEvent = (E3_Addr) &rxd->DataEvent; -+ dma->dma_destCookieVProc = DMA_COOKIE_THREAD | DMA_COOKIE (cookies[env->NodeId], EP_VP_DATA (rail->NodeId)); -+ dma->dma_srcEvent = env->TxdRail + offsetof (EP3_TXD_RAIL_ELAN, DataEvent); -+ dma->dma_srcCookieVProc = DMA_COOKIE_THREAD | DMA_REMOTE_COOKIE (cookies[env->NodeId], EP_VP_DATA (env->NodeId)); -+ len = 0; -+ } -+ else -+ { -+ /* Generate the DMA chain to fetch the data */ -+ for (i = 0, buffer = rxd->Data.nmd_addr, len = 0; i < env->nFrags; i++, dma++, event++) -+ { -+ dma->dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_READ, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dma->dma_size = env->Frags[i].nmd_len; -+ dma->dma_source = env->Frags[i].nmd_addr; -+ dma->dma_dest = buffer; -+ dma->dma_destEvent = (E3_Addr) event; -+ dma->dma_destCookieVProc = DMA_COOKIE_THREAD | DMA_COOKIE (cookies[env->NodeId], EP_VP_DATA (rail->NodeId)); -+ dma->dma_srcEvent = env->TxdRail + offsetof (EP3_TXD_RAIL_ELAN, DataEvent); -+ dma->dma_srcCookieVProc = DMA_COOKIE_THREAD | DMA_REMOTE_COOKIE (cookies[env->NodeId], EP_VP_DATA (env->NodeId)); -+ -+ event->ev_Count = 1; -+ -+ buffer += dma->dma_size; -+ len += dma->dma_size; -+ } -+ -+ /* Point the last dma at the done event */ -+ (--dma)->dma_destEvent = (E3_Addr) &rxd->DataEvent; -+ -+ if (rxd->Data.nmd_len < len) -+ { -+ /* The receive descriptor was too small for the message */ -+ /* complete the message anyway, but don't transfer any */ -+ /* data, we set the length to EP_MSG_TOO_BIG */ -+ for (i = 0, dma = rxd->Dmas; i < env->nFrags; i++, dma++) -+ dma->dma_size = 0; -+ -+ len = EP_MSG_TOO_BIG; -+ } -+ } -+ -+ /* Store the received message length in the rxdElan for CompleteEnvelope */ -+ rxd->Data.nmd_len = len; -+ -+ /* Initialise %g1 with the "rxd" so the trap handler can -+ * complete the envelope processing if we trap while sending the -+ * packet */ -+ asm volatile ("mov %0, %%g1" : /* no outputs */ : "r" (rxd)); -+ -+ /* Generate a packet to start the data transfer */ -+ c_open (EP_VP_DATA (env->NodeId)); -+ c_sendtrans2 (TR_THREADIDENTIFY, rxd->Dmas->dma_destCookieVProc, 0, 0); -+ c_sendmem (TR_SENDACK | TR_REMOTEDMA, 0, rxd->Dmas); -+ ack = c_close(); -+ -+ /* -+ * If we trapped for an output timeout, then the trap handler will have -+ * completed processing this envelope and cleared the spinlock, so we just -+ * need to update the queue descriptor. -+ */ -+ if (ack == EP3_PAckStolen) -+ goto consume_envelope; -+ -+ if (ack != E3_PAckOk) -+ { -+ /* our packet got nacked, so trap into the kernel so that -+ * it can complete processing of this envelope. -+ */ -+ asm volatile ("ta %0" : /* no outputs */ : "i" (EP3_UNIMP_TRAP_PACKET_NACKED)); /* HALT POINT */ -+ goto consume_envelope; -+ } -+ -+ /* remove the RXD from the pending list */ -+ EP3_SPINENTER (&rcvrElan->PendingLock, &rcvrMain->PendingLock); -+ if ((rcvrElan->PendingDescs = rxd->Next) == 0) -+ rcvrMain->PendingDescsTailp = 0; -+ EP3_SPINEXIT (&rcvrElan->PendingLock, &rcvrMain->PendingLock); -+ -+ /* Copy the envelope information - as 5 64 byte chunks. -+ * We force the parameters in g5, g6 so that they aren't -+ * trashed by the loadblk32 into the locals/ins -+ */ -+ if (EP_HAS_PAYLOAD(env->Attr)) -+ { -+ register void *src asm ("g5") = (void *) env; -+ register void *dst asm ("g6") = (void *) &((EP_RXD_MAIN *) rxd->RxdMain)->Envelope; -+ -+ asm volatile ( -+ "and %%sp,63,%%g7 ! Calculate stack alignment\n" -+ "add %%g7,64,%%g7 ! Space to save the registers\n" -+ "sub %%sp,%%g7,%%sp ! align stack\n" -+ "stblock64 %%l0,[%%sp] ! save the locals and ins\n" -+ -+ "ldblock64 [%0 + 0],%%l0 ! load 64-byte block into locals/ins\n" /* copy envelope */ -+ "stblock64 %%l0,[%1 + 0] ! store 64-byte block from local/ins\n" -+ "ldblock64 [%0 + 64],%%l0 ! load 64-byte block into locals/ins\n" -+ "stblock64 %%l0,[%1 + 64] ! store 64-byte block from local/ins\n" -+ -+ "ldblock64 [%0 + 128],%%l0 ! load 64-byte block into locals/ins\n" /* copy payload */ -+ "stblock64 %%l0,[%1 + 128] ! store 64-byte block from local/ins\n" -+ "ldblock64 [%0 + 192],%%l0 ! load 64-byte block into locals/ins\n" -+ "stblock64 %%l0,[%1 + 192] ! store 64-byte block from local/ins\n" -+ -+ "ldblock64 [%%sp],%%l0 ! restore locals and ins\n" -+ "add %%sp,%%g7,%%sp ! restore stack pointer\n" -+ : /* outputs */ -+ : /* inputs */ "r" (src), "r" (dst) -+ : /* clobbered */ "g5", "g6", "g7" ); -+ } -+ else -+ { -+ register void *src asm ("g5") = (void *) env; -+ register void *dst asm ("g6") = (void *) &((EP_RXD_MAIN *) rxd->RxdMain)->Envelope; -+ -+ asm volatile ( -+ "and %%sp,63,%%g7 ! Calculate stack alignment\n" -+ "add %%g7,64,%%g7 ! Space to save the registers\n" -+ "sub %%sp,%%g7,%%sp ! align stack\n" -+ "stblock64 %%l0,[%%sp] ! save the locals and ins\n" -+ -+ "ldblock64 [%0 + 0],%%l0 ! load 64-byte block into locals/ins\n" -+ "stblock64 %%l0,[%1 + 0] ! store 64-byte block from local/ins\n" -+ "ldblock64 [%0 + 64],%%l0 ! load 64-byte block into locals/ins\n" -+ "stblock64 %%l0,[%1 + 64] ! store 64-byte block from local/ins\n" -+ -+ "ldblock64 [%%sp],%%l0 ! restore locals and ins\n" -+ "add %%sp,%%g7,%%sp ! restore stack pointer\n" -+ : /* outputs */ -+ : /* inputs */ "r" (src), "r" (dst) -+ : /* clobbered */ "g5", "g6", "g7" ); -+ } -+ -+ /* Store the message length to indicate that I've finished */ -+ ((EP_RXD_MAIN *) rxd->RxdMain)->Len = rxd->Data.nmd_len; /* PCI write */ -+ -+ EP3_SPINEXIT(&rcvrElan->ThreadLock, &rcvrMain->ThreadLock); -+ -+ consume_envelope: -+ /* Sample the queue full bit *BEFORE* moving the fptr. -+ * Then only clear it if it was full before, otherwise, -+ * as soon as the fptr is moved on the queue could fill -+ * up, and so clearing it could mark a full queue as -+ * empty. -+ * -+ * While the full bit is set, the queue is in a 'steady -+ * state', so it is safe to set the q_state -+ * -+ */ -+ if (((tmp = q->q_state) & E3_QUEUE_FULL) == 0) -+ q->q_fptr = nfptr; /* update queue */ -+ else -+ { -+ q->q_fptr = nfptr; /* update queue */ -+ q->q_state = tmp &~E3_QUEUE_FULL; /* and clear full flag */ -+ } -+ -+ count++; /* bump message count */ -+ if (nfptr == q->q_top) /* queue wrap */ -+ nfptr = q->q_base; -+ else -+ nfptr += q->q_size; -+ -+ c_break_busywait(); /* be nice HALT POINT */ -+ -+ } while (nfptr != q->q_bptr); /* loop until Fptr == Bptr */ -+ } -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan4.c 2005-06-01 23:12:54.640432872 -0400 -@@ -0,0 +1,392 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcomms_elan4.c,v 1.11.2.1 2004/10/28 11:53:28 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_elan4.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "debug.h" -+#include "kcomm_elan4.h" -+#include "epcomms_elan4.h" -+ -+static void -+ep4comms_flush_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ EP4_COMMS_RAIL *commsRail = (EP4_COMMS_RAIL *) arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&commsRail->r_flush_lock, flags); -+ commsRail->r_flush_count = 0; -+ kcondvar_wakeupall (&commsRail->r_flush_sleep, &commsRail->r_flush_lock); -+ spin_unlock_irqrestore (&commsRail->r_flush_lock, flags); -+} -+ -+void -+ep4comms_flush_start (EP4_COMMS_RAIL *commsRail) -+{ -+ kmutex_lock (&commsRail->r_flush_mutex); -+} -+ -+void -+ep4comms_flush_wait (EP4_COMMS_RAIL *commsRail) -+{ -+ unsigned long flags; -+ -+ ep4_wait_event_cmd (commsRail->r_flush_mcq, -+ commsRail->r_elan_addr + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event), -+ E4_EVENT_INIT_VALUE (-32 * commsRail->r_flush_count, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0), -+ commsRail->r_flush_ecq->ecq_addr, -+ INTERRUPT_CMD | (commsRail->r_flush_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ spin_lock_irqsave (&commsRail->r_flush_lock, flags); -+ while (commsRail->r_flush_count != 0) -+ kcondvar_wait (&commsRail->r_flush_sleep, &commsRail->r_flush_lock, &flags); -+ spin_unlock_irqrestore (&commsRail->r_flush_lock, flags); -+ -+ kmutex_unlock (&commsRail->r_flush_mutex); -+} -+ -+void -+ep4comms_flush_setevent (EP4_COMMS_RAIL *commsRail, ELAN4_CQ *cq) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&commsRail->r_flush_lock, flags); -+ -+ elan4_set_event_cmd (cq, commsRail->r_elan_addr + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event)); -+ -+ commsRail->r_flush_count++; -+ -+ spin_unlock_irqrestore (&commsRail->r_flush_lock, flags); -+} -+ -+void -+ep4comms_flush_callback (void *arg, statemap_t *map) -+{ -+ EP4_COMMS_RAIL *commsRail = (EP4_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->r_generic.Subsys; -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->r_generic.Rail; -+ unsigned int rnum = rail->r_generic.Number; -+ struct list_head *el; -+ -+ /* -+ * We stall the retry thread from CB_FLUSH_FILTERING until -+ * we've finished CB_FLUSH_FLUSHING to ensure that sten -+ * packets can not be being retried while we flush them -+ * through. -+ */ -+ switch (rail->r_generic.CallbackStep) -+ { -+ case EP_CB_FLUSH_FILTERING: -+ ep_kthread_stall (&rail->r_retry_thread); -+ -+ ep4comms_flush_start (commsRail); -+ break; -+ -+ case EP_CB_FLUSH_FLUSHING: -+ break; -+ } -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[rnum]) -+ ep4xmtr_flush_callback (xmtr, (EP4_XMTR_RAIL *) xmtr->Rails[rnum]); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[rnum]) -+ ep4rcvr_flush_callback (rcvr, (EP4_RCVR_RAIL *) rcvr->Rails[rnum]); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ switch (rail->r_generic.CallbackStep) -+ { -+ case EP_CB_FLUSH_FILTERING: -+ ep4comms_flush_wait (commsRail); -+ break; -+ -+ case EP_CB_FLUSH_FLUSHING: -+ ep_kthread_resume (&rail->r_retry_thread); -+ break; -+ } -+} -+ -+void -+ep4comms_failover_callback (void *arg, statemap_t *map) -+{ -+ EP_COMMS_RAIL *commsRail = (EP_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->Subsys; -+ unsigned int rnum = commsRail->Rail->Number; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[rnum]) -+ ep4xmtr_failover_callback (xmtr, (EP4_XMTR_RAIL *) xmtr->Rails[rnum]); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[rnum]) -+ ep4rcvr_failover_callback (rcvr, (EP4_RCVR_RAIL *) rcvr->Rails[rnum]); -+ } -+ kmutex_unlock (&subsys->Lock); -+} -+ -+void -+ep4comms_disconnect_callback (void *arg, statemap_t *map) -+{ -+ EP_COMMS_RAIL *commsRail = (EP_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->Subsys; -+ unsigned int rnum = commsRail->Rail->Number; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[rnum]) -+ ep4xmtr_disconnect_callback (xmtr, (EP4_XMTR_RAIL *) xmtr->Rails[rnum]); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[rnum]) -+ ep4rcvr_disconnect_callback (rcvr, (EP4_RCVR_RAIL *) rcvr->Rails[rnum]); -+ } -+ kmutex_unlock (&subsys->Lock); -+} -+ -+void -+ep4comms_neterr_callback (EP4_RAIL *rail, void *arg, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP_COMMS_RAIL *commsRail = (EP_COMMS_RAIL *) arg; -+ EP_COMMS_SUBSYS *subsys = commsRail->Subsys; -+ unsigned int rnum = commsRail->Rail->Number; -+ struct list_head *el; -+ -+ /* First - stall the retry thread, so that it will no longer restart -+ * any sten packets from the retry lists */ -+ ep_kthread_stall (&rail->r_retry_thread); -+ -+ ep4comms_flush_start ((EP4_COMMS_RAIL *) commsRail); -+ -+ /* Second - flush through all command queues for xmtrs and rcvrs */ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[rnum]) -+ ep4xmtr_neterr_flush (xmtr, (EP4_XMTR_RAIL *) xmtr->Rails[rnum], nodeId, cookies); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[rnum]) -+ ep4rcvr_neterr_flush (rcvr, (EP4_RCVR_RAIL *) rcvr->Rails[rnum], nodeId, cookies); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ /* Third - wait for flush to complete */ -+ ep4comms_flush_wait ((EP4_COMMS_RAIL *) commsRail); -+ -+ /* Fourth - flush through all command queues */ -+ ep4_flush_ecqs (rail); -+ -+ /* Fifth - search all the retry lists for the network error cookies */ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Transmitters) { -+ EP_XMTR *xmtr = list_entry (el, EP_XMTR, Link); -+ -+ if (xmtr->Rails[rnum]) -+ ep4xmtr_neterr_check (xmtr, (EP4_XMTR_RAIL *) xmtr->Rails[rnum], nodeId, cookies); -+ } -+ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Rails[rnum]) -+ ep4rcvr_neterr_check (rcvr, (EP4_RCVR_RAIL *) rcvr->Rails[rnum], nodeId, cookies); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ ep_kthread_resume (&rail->r_retry_thread); -+} -+ -+ -+EP_COMMS_RAIL * -+ep4comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *)r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ EP4_COMMS_RAIL *commsRail; -+ E4_InputQueue qdesc; -+ int i; -+ -+ KMEM_ZALLOC (commsRail, EP4_COMMS_RAIL *,sizeof (EP4_COMMS_RAIL), 1); -+ -+ if (commsRail == NULL) -+ return NULL; -+ -+ commsRail->r_generic.Ops.DelRail = ep4comms_del_rail; -+ commsRail->r_generic.Ops.DisplayRail = ep4comms_display_rail; -+ commsRail->r_generic.Ops.Rcvr.AddRail = ep4rcvr_add_rail; -+ commsRail->r_generic.Ops.Rcvr.DelRail = ep4rcvr_del_rail; -+ commsRail->r_generic.Ops.Rcvr.Check = ep4rcvr_check; -+ commsRail->r_generic.Ops.Rcvr.QueueRxd = ep4rcvr_queue_rxd; -+ commsRail->r_generic.Ops.Rcvr.RpcPut = ep4rcvr_rpc_put; -+ commsRail->r_generic.Ops.Rcvr.RpcGet = ep4rcvr_rpc_get; -+ commsRail->r_generic.Ops.Rcvr.RpcComplete = ep4rcvr_rpc_complete; -+ -+ commsRail->r_generic.Ops.Rcvr.StealRxd = ep4rcvr_steal_rxd; -+ -+ commsRail->r_generic.Ops.Rcvr.DisplayRcvr = ep4rcvr_display_rcvr; -+ commsRail->r_generic.Ops.Rcvr.DisplayRxd = ep4rcvr_display_rxd; -+ -+ commsRail->r_generic.Ops.Rcvr.FillOutRailStats = ep4rcvr_fillout_rail_stats; -+ -+ commsRail->r_generic.Ops.Xmtr.AddRail = ep4xmtr_add_rail; -+ commsRail->r_generic.Ops.Xmtr.DelRail = ep4xmtr_del_rail; -+ commsRail->r_generic.Ops.Xmtr.Check = ep4xmtr_check; -+ commsRail->r_generic.Ops.Xmtr.BindTxd = ep4xmtr_bind_txd; -+ commsRail->r_generic.Ops.Xmtr.UnbindTxd = ep4xmtr_unbind_txd; -+ commsRail->r_generic.Ops.Xmtr.PollTxd = ep4xmtr_poll_txd; -+ commsRail->r_generic.Ops.Xmtr.CheckTxdState = ep4xmtr_check_txd_state; -+ -+ commsRail->r_generic.Ops.Xmtr.DisplayXmtr = ep4xmtr_display_xmtr; -+ commsRail->r_generic.Ops.Xmtr.DisplayTxd = ep4xmtr_display_txd; -+ -+ commsRail->r_generic.Ops.Xmtr.FillOutRailStats = ep4xmtr_fillout_rail_stats; -+ -+ /* Allocate command queue space for flushing (1 dword for interrupt + 4 dwords for waitevent) */ -+ if ((commsRail->r_flush_ecq = ep4_get_ecq (rail, EP4_ECQ_EVENT, 1)) == NULL) -+ { -+ KMEM_FREE (commsRail, sizeof (EP4_COMMS_RAIL)); -+ return NULL; -+ } -+ -+ if ((commsRail->r_flush_mcq = ep4_get_ecq (rail, EP4_ECQ_MAIN, 4)) == NULL) -+ { -+ ep4_put_ecq (rail, commsRail->r_flush_ecq, 1); -+ KMEM_FREE (commsRail, sizeof (EP4_COMMS_RAIL)); -+ return NULL; -+ } -+ -+ /* Allocate and initialise the elan memory part */ -+ if ((commsRail->r_elan = ep_alloc_elan (r, EP4_COMMS_RAIL_ELAN_SIZE, 0, &commsRail->r_elan_addr)) == (sdramaddr_t) 0) -+ { -+ ep4_put_ecq (rail, commsRail->r_flush_mcq, 4); -+ ep4_put_ecq (rail, commsRail->r_flush_ecq, 1); -+ KMEM_FREE (commsRail, sizeof (EP4_COMMS_RAIL)); -+ return NULL; -+ } -+ -+ ep4_register_intcookie (rail, &commsRail->r_flush_intcookie, commsRail->r_elan_addr + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event), -+ ep4comms_flush_interrupt, commsRail); -+ -+ elan4_sdram_writeq (dev, commsRail->r_elan + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ -+ -+ /* Allocate and initialise all the queue desriptors as "full" with no event */ -+ if ((commsRail->r_descs = ep_alloc_memory_elan (r, EP_EPCOMMS_QUEUE_BASE, roundup (EP_MSG_NSVC * EP_QUEUE_DESC_SIZE, SDRAM_PAGE_SIZE), EP_PERM_ALL, 0)) == (sdramaddr_t) 0) -+ { -+ ep_free_elan (r, commsRail->r_elan_addr, EP4_COMMS_RAIL_ELAN_SIZE); -+ ep4_put_ecq (rail, commsRail->r_flush_mcq, 4); -+ ep4_put_ecq (rail, commsRail->r_flush_ecq, 1); -+ KMEM_FREE (commsRail, sizeof (EP4_COMMS_RAIL)); -+ return NULL; -+ } -+ -+ qdesc.q_bptr = 0; -+ qdesc.q_fptr = 8; -+ qdesc.q_control = E4_InputQueueControl (qdesc.q_bptr,qdesc.q_fptr, 8); -+ qdesc.q_event = 0; -+ -+ for (i = 0; i < EP_MSG_NSVC; i++) -+ elan4_sdram_copyq_to_sdram (rail->r_ctxt.ctxt_dev, &qdesc, commsRail->r_descs + (i * EP_QUEUE_DESC_SIZE), -+ sizeof (E4_InputQueue)); -+ -+ kmutex_init (&commsRail->r_flush_mutex); -+ spin_lock_init (&commsRail->r_flush_lock); -+ kcondvar_init (&commsRail->r_flush_sleep); -+ -+ ep_register_callback (r, EP_CB_FLUSH_FILTERING, ep4comms_flush_callback, commsRail); -+ ep_register_callback (r, EP_CB_FLUSH_FLUSHING, ep4comms_flush_callback, commsRail); -+ ep_register_callback (r, EP_CB_FAILOVER, ep4comms_failover_callback, commsRail); -+ ep_register_callback (r, EP_CB_DISCONNECTING, ep4comms_disconnect_callback, commsRail); -+ -+ commsRail->r_neterr_ops.op_func = ep4comms_neterr_callback; -+ commsRail->r_neterr_ops.op_arg = commsRail; -+ -+ ep4_add_neterr_ops (rail, &commsRail->r_neterr_ops); -+ -+ return (EP_COMMS_RAIL *) commsRail; -+} -+ -+void -+ep4comms_del_rail (EP_COMMS_RAIL *r) -+{ -+ EP4_COMMS_RAIL *commsRail = (EP4_COMMS_RAIL *) r; -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->r_generic.Rail; -+ -+ ep_remove_callback (&rail->r_generic, EP_CB_FLUSH_FILTERING, ep4comms_flush_callback, commsRail); -+ ep_remove_callback (&rail->r_generic, EP_CB_FLUSH_FLUSHING, ep4comms_flush_callback, commsRail); -+ ep_remove_callback (&rail->r_generic, EP_CB_FAILOVER, ep4comms_failover_callback, commsRail); -+ ep_remove_callback (&rail->r_generic, EP_CB_DISCONNECTING, ep4comms_disconnect_callback, commsRail); -+ -+ kcondvar_destroy (&commsRail->r_flush_sleep); -+ spin_lock_destroy (&commsRail->r_flush_lock); -+ kmutex_destroy (&commsRail->r_flush_mutex); -+ -+ ep_free_memory_elan (&rail->r_generic, EP_EPCOMMS_QUEUE_BASE); -+ ep_free_elan (&rail->r_generic, commsRail->r_elan_addr, EP4_COMMS_RAIL_ELAN_SIZE); -+ -+ ep4_deregister_intcookie (rail, &commsRail->r_flush_intcookie); -+ -+ ep4_put_ecq (rail, commsRail->r_flush_mcq, 4); -+ ep4_put_ecq (rail, commsRail->r_flush_ecq, 1); -+ -+ KMEM_FREE (commsRail, sizeof (EP4_COMMS_RAIL)); -+} -+ -+void -+ep4comms_display_rail (EP_COMMS_RAIL *r) -+{ -+ EP4_COMMS_RAIL *commsRail = (EP4_COMMS_RAIL *) r; -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->r_generic.Rail; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ -+ ep4_display_rail (rail); -+ -+ ep_debugf (DBG_DEBUG, " flush count=%d mcq=%p ecq=%p event %llx.%llx.%llx\n", -+ commsRail->r_flush_count, commsRail->r_flush_mcq, commsRail->r_flush_ecq, -+ elan4_sdram_readq (dev, commsRail->r_elan + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event.ev_CountAndType)), -+ elan4_sdram_readq (dev, commsRail->r_elan + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event.ev_WritePtr)), -+ elan4_sdram_readq (dev, commsRail->r_elan + offsetof (EP4_COMMS_RAIL_ELAN, r_flush_event.ev_WriteValue))); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan4.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_elan4.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan4.h 2005-06-01 23:12:54.641432720 -0400 -@@ -0,0 +1,470 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __EPCOMMS_ELAN4_H -+#define __EPCOMMS_ELAN4_H -+ -+#ident "@(#)$Id: epcomms_elan4.h,v 1.13.2.1 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_elan4.h,v $ */ -+ -+ -+#include -+ -+/* -+ * Elan4 spinlocks are a pair of 64 bit words, one in elan sdram and one in main memory -+ * the sdram word holds the thread sequence number in the bottom 32 bits and the main -+ * lock in the top 32 bits. The main memory word holds the sequence number only in -+ * it's bottom 32 bits */ -+ -+typedef volatile E4_uint64 EP4_SPINLOCK_MAIN; -+typedef volatile E4_uint64 EP4_SPINLOCK_ELAN; -+ -+#define EP4_SPINLOCK_SEQ 0 -+#define EP4_SPINLOCK_MLOCK 4 -+ -+#if defined(__elan4__) -+ -+#define EP4_SPINENTER(CPORT,SLE,SLM) \ -+do { \ -+ register long tmp; \ -+\ -+ asm volatile ("ld4 [%1], %0\n" \ -+ "inc %0\n" \ -+ "st4 %0, [%1]\n" \ -+ "ld4 [%1 + 4], %0\n" \ -+ "srl8,byte %0, 4, %0\n" \ -+ : /* outputs */ "=r" (tmp) \ -+ : /* inputs */ "r" (SLE), "r" (SLM)); \ -+\ -+ if (tmp) \ -+ ep4_spinblock (CPORT,SLE, SLM); \ -+} while (0) -+ -+extern void ep4_spinblock(E4_uint64 *cport, EP4_SPINLOCK_ELAN *sle, EP4_SPINLOCK_MAIN *slm); -+ -+#define EP4_SPINEXIT(CPORT,SLE,SLM) \ -+do { \ -+ register long tmp; \ -+\ -+ asm volatile ("ld4 [%1], %0\n" \ -+ "st4 %0, [%2]\n" \ -+ : /* outputs */ "=r" (tmp) \ -+ : /* inputs */ "r" (SLE), "r" (SLM)); \ -+} while (0) -+ -+#else -+ -+#define EP4_SPINENTER(DEV,SLE,SLM) \ -+do { \ -+ uint32_t seq; \ -+\ -+ mb(); \ -+ elan4_sdram_writel (DEV, (SLE) + EP4_SPINLOCK_MLOCK, 1); \ -+ mb(); \ -+ while ((seq = elan4_sdram_readl (DEV, (SLE) + EP4_SPINLOCK_SEQ)) != *((uint32_t *) (SLM))) \ -+ { \ -+ while (*((uint32_t *) (SLM)) == (seq - 1)) \ -+ { \ -+ mb(); \ -+ DELAY(1); \ -+ } \ -+ } \ -+} while (0) -+ -+#define EP4_SPINEXIT(DEV,SLE,SLM) \ -+do { \ -+ wmb(); \ -+ elan4_sdram_writel (DEV, (SLE) + EP4_SPINLOCK_MLOCK, 0); \ -+} while (0) -+ -+#endif /* !defined(__elan4__) */ -+ -+#define EP4_STEN_RETRYCOUNT 16 -+#define EP4_DMA_RETRYCOUNT 16 -+ -+typedef struct ep4_intr_cmd -+{ -+ E4_uint64 c_write_cmd; -+ E4_uint64 c_write_value; -+ E4_uint64 c_intr_cmd; -+} EP4_INTR_CMD; -+ -+#define EP4_INTR_CMD_NDWORDS (sizeof (EP4_INTR_CMD) / 8) -+ -+typedef struct ep4_rxd_sten_cmd -+{ -+ E4_uint64 c_open; -+ -+ E4_uint64 c_trans; -+ E4_uint64 c_cookie; -+ E4_uint64 c_dma_typeSize; -+ E4_uint64 c_dma_cookie; -+ E4_uint64 c_dma_vproc; -+ E4_uint64 c_dma_srcAddr; -+ E4_uint64 c_dma_dstAddr; -+ E4_uint64 c_dma_srcEvent; -+ E4_uint64 c_dma_dstEvent; -+ -+ E4_uint64 c_ok_guard; -+ E4_uint64 c_ok_write_cmd; -+ E4_uint64 c_ok_write_value; -+ -+ E4_uint64 c_fail_guard; -+ E4_uint64 c_fail_setevent; -+ -+ E4_uint64 c_nop_cmd; -+} EP4_RXD_STEN_CMD; -+ -+#define EP4_RXD_STEN_CMD_NDWORDS (sizeof (EP4_RXD_STEN_CMD) / 8) -+ -+typedef struct ep4_rxd_dma_cmd -+{ -+ E4_uint64 c_dma_typeSize; -+ E4_uint64 c_dma_cookie; -+ E4_uint64 c_dma_vproc; -+ E4_uint64 c_dma_srcAddr; -+ E4_uint64 c_dma_dstAddr; -+ E4_uint64 c_dma_srcEvent; -+ E4_uint64 c_dma_dstEvent; -+ E4_uint64 c_nop_cmd; -+} EP4_RXD_DMA_CMD; -+ -+#define EP4_RXD_DMA_CMD_NDWORDS (sizeof (EP4_RXD_DMA_CMD) / 8) -+#define EP4_RXD_START_CMD_NDWORDS (sizeof (E4_ThreadRegs) / 8) -+ -+typedef struct ep4_rxd_rail_elan -+{ -+ EP4_RXD_STEN_CMD rxd_sten[EP_MAXFRAG+1]; -+ -+ EP4_INTR_CMD rxd_done_cmd; /* command stream issued by done event (aligned to 64 bytes) */ -+ E4_Addr rxd_next; /* linked list when on pending list (pad to 32 bytes)*/ -+ E4_Event32 rxd_failed; /* event set when sten packet fails */ -+ -+ EP4_INTR_CMD rxd_failed_cmd; /* command stream issued by fail event (aligned to 64 bytes) */ -+ E4_uint64 rxd_queued; /* rxd queuing thread has executed (pad to 32 bytes)*/ -+ -+ E4_Event32 rxd_start; /* event to set to fire off and event chain (used as chain[0]) */ -+ E4_Event32 rxd_chain[EP_MAXFRAG]; /* chained events (aligned to 32 bytes) */ -+ E4_Event32 rxd_done; /* event to fire done command stream causing interrupt (used as chain[EP_MAXFRAG]) */ -+ -+ E4_Addr rxd_rxd; /* elan address of EP4_RXD_MAIN */ -+ E4_Addr rxd_main; /* elan address of EP4_RXD_RAIL_MAIN */ -+ E4_uint64 rxd_debug; /* thread debug value */ -+ -+ EP_NMD rxd_buffer; /* Network mapping descriptor for receive data */ -+} EP4_RXD_RAIL_ELAN; -+ -+#define EP4_RXD_RAIL_ELAN_SIZE roundup(sizeof (EP4_RXD_RAIL_ELAN), 64) -+ -+typedef struct ep4_rxd_rail_main -+{ -+ E4_uint64 rxd_sent[EP_MAXFRAG+1]; /* sten packet sent */ -+ E4_uint64 rxd_failed; /* sten packet failed */ -+ E4_uint64 rxd_done; /* operation complete */ -+ -+ E4_Addr rxd_scq; /* command port for scq */ -+} EP4_RXD_RAIL_MAIN; -+ -+#define EP4_RXD_RAIL_MAIN_SIZE roundup(sizeof (EP4_RXD_RAIL_MAIN), 8) -+ -+#if !defined(__elan4__) -+typedef struct ep4_rxd_rail -+{ -+ EP_RXD_RAIL rxd_generic; -+ -+ struct list_head rxd_retry_link; -+ unsigned long rxd_retry_time; -+ -+ EP4_INTCOOKIE rxd_intcookie; -+ -+ sdramaddr_t rxd_elan; -+ EP_ADDR rxd_elan_addr; -+ -+ EP4_RXD_RAIL_MAIN *rxd_main; -+ EP_ADDR rxd_main_addr; -+ -+ EP4_ECQ *rxd_ecq; /* cq with 128 bytes targetted by event */ -+ EP4_ECQ *rxd_scq; /* cq with 8 bytes targetted by main/thread store */ -+} EP4_RXD_RAIL; -+ -+#define EP4_NUM_RXD_PER_BLOCK 16 -+ -+typedef struct ep4_rxd_rail_block -+{ -+ struct list_head blk_link; -+ EP4_RXD_RAIL blk_rxds[EP4_NUM_RXD_PER_BLOCK]; -+} EP4_RXD_RAIL_BLOCK; -+ -+#endif /* !defined(__elan4__) */ -+ -+typedef struct ep4_rcvr_rail_elan -+{ -+ E4_uint64 rcvr_thread_stall[8]; /* place for thread to stall */ -+ E4_Event32 rcvr_qevent; /* Input queue event */ -+ E4_Event32 rcvr_thread_halt; /* place for thread to halt */ -+ -+ volatile E4_Addr rcvr_pending_tailp; /* list of pending rxd's (elan addr) */ -+ volatile E4_Addr rcvr_pending_head; /* -- this pair aligned to 16 bytes */ -+ -+ EP4_SPINLOCK_ELAN rcvr_thread_lock; /* spinlock for thread processing loop */ -+ -+ E4_uint64 rcvr_stall_intcookie; /* interrupt cookie to use when requseted to halt */ -+ -+ E4_uint64 rcvr_qbase; /* base of input queue */ -+ E4_uint64 rcvr_qlast; /* last item in input queue */ -+ -+ E4_uint64 rcvr_debug; /* thread debug value */ -+} EP4_RCVR_RAIL_ELAN; -+ -+typedef struct ep4_rcvr_rail_main -+{ -+ EP4_SPINLOCK_MAIN rcvr_thread_lock; /* spinlock for thread processing loop */ -+} EP4_RCVR_RAIL_MAIN; -+ -+#if !defined(__elan4__) -+ -+typedef struct ep4_rcvr_rail_stats -+{ -+ unsigned long some_stat; -+} EP4_RCVR_RAIL_STATS; -+ -+typedef struct ep4_rcvr_rail -+{ -+ EP_RCVR_RAIL rcvr_generic; /* generic portion */ -+ -+ sdramaddr_t rcvr_elan; -+ EP_ADDR rcvr_elan_addr; -+ -+ EP4_RCVR_RAIL_MAIN *rcvr_main; -+ EP_ADDR rcvr_main_addr; -+ -+ sdramaddr_t rcvr_slots; /* input queue slots */ -+ EP_ADDR rcvr_slots_addr; /* and elan address */ -+ -+ EP_ADDR rcvr_stack; /* stack for thread */ -+ -+ EP4_ECQ *rcvr_ecq; /* command queue space for thread STEN packets */ -+ EP4_ECQ *rcvr_resched; /* command queue space to reschedule the thread */ -+ -+ struct list_head rcvr_freelist; /* freelist of per-rail receive descriptors */ -+ unsigned int rcvr_freecount; /* and number on free list */ -+ unsigned int rcvr_totalcount; /* total number created */ -+ spinlock_t rcvr_freelock; /* and lock for free list */ -+ struct list_head rcvr_blocklist; /* list of receive descriptor blocks */ -+ -+ unsigned int rcvr_freewaiting; /* waiting for descriptors to be freed */ -+ kcondvar_t rcvr_freesleep; /* and sleep here */ -+ -+ EP4_INTCOOKIE rcvr_stall_intcookie; /* interrupt cookie for thread halt */ -+ unsigned char rcvr_thread_halted; /* thread has been halted */ -+ unsigned char rcvr_cleanup_waiting; /* waiting for cleanup */ -+ kcondvar_t rcvr_cleanup_sleep; /* and sleep here */ -+ -+ EP4_RETRY_OPS rcvr_retryops; -+ -+ struct list_head rcvr_retrylist; /* list of txd's to retry envelopes for */ -+ struct list_head rcvr_polllist; /* list of txd's to poll for completion */ -+ spinlock_t rcvr_retrylock; -+ -+ EP4_RCVR_RAIL_STATS rcvr_stats; /* elan4 specific rcvr_rail stats */ -+ -+} EP4_RCVR_RAIL; -+ -+#endif /* !defined(__elan4__) */ -+ -+typedef struct ep4_txd_rail_elan -+{ -+ EP4_INTR_CMD txd_env_cmd; /* command stream for envelope event (64 byte aligned) */ -+ E4_uint64 txd_pad0; /* pad to 32 bytes */ -+ E4_Event32 txd_env; /* event set when STEN packet fails */ -+ -+ EP4_INTR_CMD txd_done_cmd; /* command stream for done event (64 byte aligned) */ -+ E4_uint64 txd_pad1; /* pad to 32 bytes */ -+ E4_Event32 txd_done; /* event set when transmit complete */ -+ -+ E4_Event32 txd_data; /* event set when xmit completes (=> phase becomes passive) */ -+} EP4_TXD_RAIL_ELAN; -+ -+#define EP4_TXD_RAIL_ELAN_SIZE roundup(sizeof(EP4_TXD_RAIL_ELAN), 64) -+ -+typedef struct ep4_txd_rail_main -+{ -+ E4_uint64 txd_env; -+ E4_uint64 txd_data; -+ E4_uint64 txd_done; -+} EP4_TXD_RAIL_MAIN; -+ -+#define EP4_TXD_RAIL_MAIN_SIZE roundup(sizeof(EP4_TXD_RAIL_MAIN), 8) -+ -+#if !defined (__elan4__) -+typedef struct ep4_txd_rail -+{ -+ EP_TXD_RAIL txd_generic; -+ -+ struct list_head txd_retry_link; -+ unsigned long txd_retry_time; -+ -+ EP4_INTCOOKIE txd_intcookie; -+ -+ sdramaddr_t txd_elan; -+ EP_ADDR txd_elan_addr; -+ -+ EP4_TXD_RAIL_MAIN *txd_main; -+ EP_ADDR txd_main_addr; -+ -+ EP4_ECQ *txd_ecq; -+ -+ E4_uint64 txd_cookie; -+} EP4_TXD_RAIL; -+ -+#define EP4_NUM_TXD_PER_BLOCK 21 -+ -+typedef struct ep4_txd_rail_block -+{ -+ struct list_head blk_link; -+ EP4_TXD_RAIL blk_txds[EP4_NUM_TXD_PER_BLOCK]; -+} EP4_TXD_RAIL_BLOCK; -+ -+typedef struct ep4_xmtr_rail_main -+{ -+ E4_int64 xmtr_flowcnt; -+} EP4_XMTR_RAIL_MAIN; -+ -+typedef struct ep4_xmtr_rail_stats -+{ -+ unsigned long some_stat; -+} EP4_XMTR_RAIL_STATS; -+ -+#define EP4_TXD_LIST_POLL 0 -+#define EP4_TXD_LIST_STALLED 1 -+#define EP4_TXD_LIST_RETRY 2 -+#define EP4_TXD_NUM_LISTS 3 -+typedef struct ep4_xmtr_rail -+{ -+ EP_XMTR_RAIL xmtr_generic; -+ -+ EP4_XMTR_RAIL_MAIN *xmtr_main; -+ EP_ADDR xmtr_main_addr; -+ -+ struct list_head xmtr_freelist; -+ unsigned int xmtr_freecount; -+ unsigned int xmtr_totalcount; -+ spinlock_t xmtr_freelock; -+ struct list_head xmtr_blocklist; -+ unsigned int xmtr_freewaiting; -+ kcondvar_t xmtr_freesleep; -+ -+ EP4_INTCOOKIE xmtr_intcookie; /* interrupt cookie for "polled" descriptors */ -+ -+ ELAN4_CQ *xmtr_cq; -+ E4_int64 xmtr_flowcnt; -+ -+ EP4_RETRY_OPS xmtr_retryops; -+ -+ struct list_head xmtr_retrylist[EP4_TXD_NUM_LISTS]; /* list of txd's to retry envelopes for */ -+ struct list_head xmtr_polllist; /* list of txd's to poll for completion */ -+ spinlock_t xmtr_retrylock; -+ -+ EP4_XMTR_RAIL_STATS stats; /* elan4 specific xmtr rail stats */ -+} EP4_XMTR_RAIL; -+ -+#define EP4_XMTR_CQSIZE CQ_Size64K /* size of command queue for xmtr */ -+#define EP4_XMTR_FLOWCNT (CQ_Size(EP4_XMTR_CQSIZE) / 512) /* # of STEN packets which can fit in */ -+ -+typedef struct ep4_comms_rail_elan -+{ -+ E4_Event32 r_flush_event; -+} EP4_COMMS_RAIL_ELAN; -+ -+#define EP4_COMMS_RAIL_ELAN_SIZE roundup(sizeof (EP4_COMMS_RAIL_ELAN), 32) -+ -+typedef struct ep4_comms_rail -+{ -+ EP_COMMS_RAIL r_generic; /* generic comms rail */ -+ sdramaddr_t r_descs; /* input queue descriptors */ -+ -+ sdramaddr_t r_elan; /* elan portion */ -+ EP_ADDR r_elan_addr; -+ -+ kmutex_t r_flush_mutex; /* sequentialise flush usage */ -+ EP4_INTCOOKIE r_flush_intcookie; /* interrupt cookie to generate */ -+ -+ kcondvar_t r_flush_sleep; /* place to sleep waiting */ -+ spinlock_t r_flush_lock; /* and spinlock to use */ -+ -+ unsigned int r_flush_count; /* # setevents issued */ -+ EP4_ECQ *r_flush_ecq; /* command queue for interrupt */ -+ EP4_ECQ *r_flush_mcq; /* command queeu to issue waitevent */ -+ -+ EP4_NETERR_OPS r_neterr_ops; /* network error fixup ops */ -+} EP4_COMMS_RAIL; -+ -+/* epcommsTx_elan4.c */ -+extern void ep4xmtr_flush_callback (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail); -+extern void ep4xmtr_failover_callback (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail); -+extern void ep4xmtr_disconnect_callback (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail); -+ -+extern void ep4xmtr_neterr_flush (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+extern void ep4xmtr_neterr_check (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+ -+/* epcommsRx_elan4.c */ -+extern void ep4rcvr_flush_callback (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail); -+extern void ep4rcvr_failover_callback (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail); -+extern void ep4rcvr_disconnect_callback (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail); -+ -+extern void ep4rcvr_neterr_flush (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+extern void ep4rcvr_neterr_check (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+ -+/* epcomms_elan4.c */ -+extern void ep4comms_flush_start (EP4_COMMS_RAIL *commsRail); -+extern void ep4comms_flush_wait (EP4_COMMS_RAIL *commsRail); -+extern void ep4comms_flush_setevent (EP4_COMMS_RAIL *commsRail, ELAN4_CQ *cq); -+ -+extern EP_COMMS_RAIL *ep4comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *r); -+extern void ep4comms_del_rail (EP_COMMS_RAIL *r); -+extern void ep4comms_display_rail (EP_COMMS_RAIL *r); -+ -+/* epcommsTx_elan4.c */ -+extern int ep4xmtr_bind_txd (EP_TXD *txd, EP_XMTR_RAIL *xmtrRail, unsigned int phase); -+extern void ep4xmtr_unbind_txd (EP_TXD *txd, unsigned int phase); -+extern int ep4xmtr_poll_txd (EP_XMTR_RAIL *xmtrRail, EP_TXD_RAIL *txdRail, int how); -+extern long ep4xmtr_check (EP_XMTR_RAIL *xmtrRail, long nextRunTime); -+extern void ep4xmtr_add_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail); -+extern void ep4xmtr_del_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail); -+extern int ep4xmtr_check_txd_state(EP_TXD *txd); -+ -+extern void ep4xmtr_display_xmtr (DisplayInfo *di, EP_XMTR_RAIL *xmtrRail); -+extern void ep4xmtr_display_txd (DisplayInfo *di, EP_TXD_RAIL *txdRail); -+ -+extern void ep4xmtr_fillout_rail_stats (EP_XMTR_RAIL *xmtr_rail, char *str); -+ -+/* epcommsRx_elan4.c */ -+extern int ep4rcvr_queue_rxd (EP_RXD *rxd, EP_RCVR_RAIL *rcvrRail); -+extern void ep4rcvr_rpc_put (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+extern void ep4rcvr_rpc_get (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+extern void ep4rcvr_rpc_complete (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+ -+extern EP_RXD *ep4rcvr_steal_rxd (EP_RCVR_RAIL *rcvrRail); -+ -+extern long ep4rcvr_check (EP_RCVR_RAIL *rcvrRail, long nextRunTime); -+extern void ep4rcvr_add_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *rail); -+extern void ep4rcvr_del_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *rail); -+ -+extern void ep4rcvr_display_rcvr (DisplayInfo *di, EP_RCVR_RAIL *rcvrRail); -+extern void ep4rcvr_display_rxd (DisplayInfo *di, EP_RXD_RAIL *rxdRail); -+ -+extern void ep4rcvr_fillout_rail_stats (EP_RCVR_RAIL *rcvr_rail, char *str); -+ -+#endif /* !defined(__elan4__) */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __EPCOMMS_ELAN4_H */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan4_thread.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcomms_elan4_thread.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcomms_elan4_thread.c 2005-06-01 23:12:54.642432568 -0400 -@@ -0,0 +1,346 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcomms_elan4_thread.c,v 1.10.8.2 2004/09/28 10:36:51 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms_elan4_thread.c,v $*/ -+ -+//#include -+ -+typedef char int8_t; -+typedef unsigned char uint8_t; -+typedef short int16_t; -+typedef unsigned short uint16_t; -+typedef int int32_t; -+typedef unsigned int uint32_t; -+typedef long int64_t; -+typedef unsigned long uint64_t; -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "epcomms_elan4.h" -+ -+#include -+ -+/* assembler in epcomms_asm_elan4_thread.S */ -+extern void c_waitevent_interrupt (E4_uint64 *cport, E4_Event32 *event, E4_uint64 count, E4_uint64 intcookie); -+extern EP4_RXD_RAIL_ELAN *c_stall_thread (EP4_RCVR_RAIL_ELAN *rcvrRail); -+ -+#define R32_to_R47 "%r32", "%r33", "%r34", "%r35", "%r36", "%r37", "%r38", "%r39", \ -+ "%r40", "%r41", "%r42", "%r43", "%r44", "%r45", "%r46", "%r47" -+#define R48_to_R63 "%r48", "%r49", "%r50", "%r51", "%r52", "%r53", "%r54", "%r55", \ -+ "%r56", "%r57", "%r58", "%r59", "%r60", "%r61", "%r62", "%r63" -+ -+/* proto types for code in asm_elan4_thread.S */ -+extern void c_waitevent (E4_uint64 *commandport, E4_Addr event, E4_uint64 count); -+extern void c_reschedule(E4_uint64 *commandport); -+ -+static inline unsigned long -+c_load_u16(unsigned short *ptr) -+{ -+ unsigned long value; -+ -+ asm volatile ("ld2 [%1], %%r2\n" -+ "srl8,byte %%r2, %1, %0\n" -+ "sll8 %0, 48, %0\n" -+ "srl8 %0, 48, %0\n" -+ : /* outputs */ "=r" (value) -+ : /* inputs */ "r" (ptr) -+ : /* clobbered */ "%r2"); -+ return value; -+} -+ -+static inline unsigned long -+c_load_u32(unsigned int *ptr) -+{ -+ unsigned long value; -+ -+ asm volatile ("ld4 [%1], %%r2\n" -+ "srl8,byte %%r2, %1, %0\n" -+ "sll8 %0, 32, %0\n" -+ "srl8 %0, 32, %0\n" -+ : /* outputs */ "=r" (value) -+ : /* inputs */ "r" (ptr) -+ : /* clobbered */ "%r2"); -+ return value; -+} -+ -+static inline void -+c_store_u32(unsigned int *ptr, unsigned long value) -+{ -+ asm volatile ("sll8,byte %0, %1, %%r2\n" -+ "st4 %%r2, [%1]\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (value), "r" (ptr) -+ : /* clobbered */ "%r2"); -+} -+ -+/* Reschedule the current Elan thread to the back of the run queue -+ * if there is another one ready to run */ -+static inline void -+c_yield (E4_uint64 *commandport) -+{ -+ unsigned long rval; -+ -+ asm volatile ("breaktest %0" : /* outputs */ "=r" (rval) : /* inputs */); -+ -+ if (rval & ICC_SIGNED_BIT) -+ c_reschedule(commandport); -+} -+ -+/* Reschedule the current thread if we're in danger of exceeding the -+ * thread instruction count */ -+static inline void -+c_insn_check(E4_uint64 *commandport) -+{ -+ unsigned long rval; -+ -+ asm volatile ("breaktest %0" : /* outputs */ "=r" (rval) : /* inputs */); -+ -+ if (rval & ICC_ZERO_BIT) -+ c_reschedule(commandport); -+} -+ -+void -+ep4_spinblock (E4_uint64 *cport, EP4_SPINLOCK_ELAN *sle, EP4_SPINLOCK_MAIN *slm) -+{ -+ do { -+ unsigned long val = *sle & 0xfffffffff; -+ -+ *slm = val; /* Release my lock */ -+ -+ while (*sle >> 32) /* Wait until the main */ -+ c_yield(cport); /* releases the lock */ -+ -+ c_store_u32 ((unsigned int *) sle, val + 1); /* and try and relock */ -+ } while (*sle >> 32); -+} -+ -+#define RESCHED_AFTER_PKTS ((CQ_Size(CQ_Size64K) / 128) - 1) -+ -+void -+ep4comms_rcvr (EP4_RAIL_ELAN *rail, EP4_RCVR_RAIL_ELAN *rcvrElan, EP4_RCVR_RAIL_MAIN *rcvrMain, -+ E4_InputQueue *inputq, E4_uint64 *cport, E4_uint64 *resched) -+{ -+ long count = 1; -+ long fptr = inputq->q_fptr; -+ -+ for (;;) -+ { -+ c_waitevent (cport, inputq->q_event, -count << 5); -+ -+ count = 0; -+ -+ while (fptr != inputq->q_bptr) -+ { -+ EP_ENVELOPE *env = (EP_ENVELOPE *) fptr; -+ unsigned long nodeid = c_load_u32 (&env->NodeId); -+ unsigned long opencmd = OPEN_STEN_PKT_CMD | OPEN_PACKET(0, PACK_OK | RESTART_COUNT_ZERO, EP_VP_DATA(nodeid)); -+ unsigned long vproc = EP_VP_DATA(rail->r_nodeid); -+ EP_ATTRIBUTE attr = c_load_u32 (&env->Attr); -+ unsigned long txdRail = c_load_u32 (&env->TxdRail); -+ unsigned long nFrags = c_load_u32 (&env->nFrags); -+ E4_uint64 cookie = rail->r_cookies[nodeid]; -+ unsigned long srcevent = (EP_IS_RPC(attr) ? txdRail + offsetof (EP4_TXD_RAIL_ELAN, txd_data) : -+ txdRail + offsetof (EP4_TXD_RAIL_ELAN, txd_done)); -+ EP4_RXD_RAIL_ELAN *rxdElan; -+ EP4_RXD_RAIL_MAIN *rxdMain; -+ EP_RXD_MAIN *rxd; -+ EP4_RXD_STEN_CMD *sten; -+ E4_Event32 *event; -+ unsigned long first; -+ unsigned long buffer; -+ unsigned long len; -+ unsigned long i; -+ -+ EP4_SPINENTER(resched, &rcvrElan->rcvr_thread_lock, &rcvrMain->rcvr_thread_lock); -+ -+ if ((rxdElan = (EP4_RXD_RAIL_ELAN *) rcvrElan->rcvr_pending_head) == 0) -+ { -+ EP4_SPINEXIT (resched, &rcvrElan->rcvr_thread_lock, &rcvrMain->rcvr_thread_lock); -+ -+ rxdElan = c_stall_thread (rcvrElan); -+ -+ EP4_SPINENTER(resched, &rcvrElan->rcvr_thread_lock, &rcvrMain->rcvr_thread_lock); -+ } -+ -+ if (c_load_u32 (&env->Version) != EP_ENVELOPE_VERSION) /* envelope has been cancelled */ -+ { -+ EP4_SPINEXIT (resched, &rcvrElan->rcvr_thread_lock, &rcvrMain->rcvr_thread_lock); -+ goto consume_envelope; -+ } -+ -+ rxd = (EP_RXD_MAIN *) rxdElan->rxd_rxd; -+ rxdMain = (EP4_RXD_RAIL_MAIN *) rxdElan->rxd_main; -+ first = (EP_MAXFRAG+1) - (( EP_IS_MULTICAST(attr) ? 1 : 0) + (nFrags == 0 ? 1 : nFrags)); -+ sten = &rxdElan->rxd_sten[first]; -+ event = &rxdElan->rxd_chain[first]; -+ -+ if (EP_IS_MULTICAST(attr)) /* need to fetch broadcast bitmap */ -+ { -+ sten->c_open = opencmd; -+ sten->c_trans = SEND_TRANS_CMD | ((TR_REMOTEDMA | TR_WAIT_FOR_EOP) << 16); -+ sten->c_cookie = cookie | EP4_COOKIE_THREAD | EP4_COOKIE_STEN; -+ sten->c_dma_typeSize = E4_DMA_TYPE_SIZE(BT_BITOUL(EP_MAX_NODES) * sizeof (bitmap_t), DMA_DataTypeWord, 0, EP4_DMA_RETRYCOUNT); -+ sten->c_dma_cookie = cookie | EP4_COOKIE_THREAD | EP4_COOKIE_REMOTE | EP4_COOKIE_DMA | EP4_COOKIE_INC; -+ sten->c_dma_vproc = vproc; -+ sten->c_dma_srcAddr = c_load_u32 (&env->TxdMain.nmd_addr) + offsetof(EP_TXD_MAIN, Bitmap); -+ sten->c_dma_dstAddr = (E4_Addr) &rxd->Bitmap; -+ sten->c_dma_srcEvent = srcevent; -+ sten->c_dma_dstEvent = (E4_Addr) event; -+ -+ event->ev_CountAndType = E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_STEN_CMD_NDWORDS); -+ -+ cookie += (EP4_COOKIE_INC << 1); -+ -+ sten++; event++; -+ } -+ -+ if (nFrags == 0) -+ { -+ /* Generate an empty "get" DMA to accept the envelope and fire the rx handler */ -+ sten->c_open = opencmd; -+ sten->c_trans = SEND_TRANS_CMD | ((TR_REMOTEDMA | TR_WAIT_FOR_EOP) << 16); -+ sten->c_cookie = cookie | EP4_COOKIE_THREAD | EP4_COOKIE_STEN; -+ sten->c_dma_typeSize = E4_DMA_TYPE_SIZE(0, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT); -+ sten->c_dma_cookie = cookie | EP4_COOKIE_THREAD | EP4_COOKIE_REMOTE | EP4_COOKIE_DMA | EP4_COOKIE_INC; -+ sten->c_dma_vproc = vproc; -+ sten->c_dma_srcEvent = srcevent; -+ sten->c_dma_dstEvent = (E4_Addr) event; -+ -+ event->ev_CountAndType = E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS); -+ -+ len = 0; -+ -+ cookie += (EP4_COOKIE_INC << 1); -+ } -+ else -+ { -+ /* Generate the DMA chain to fetch the data */ -+ for (i = 0, buffer = c_load_u32 (&rxdElan->rxd_buffer.nmd_addr), len = 0; i < nFrags; i++) -+ { -+ unsigned long fragLen = c_load_u32 (&env->Frags[i].nmd_len); -+ -+ sten->c_open = opencmd; -+ sten->c_trans = SEND_TRANS_CMD | ((TR_REMOTEDMA | TR_WAIT_FOR_EOP) << 16); -+ sten->c_cookie = cookie | EP4_COOKIE_THREAD | EP4_COOKIE_STEN; -+ sten->c_dma_typeSize = E4_DMA_TYPE_SIZE(fragLen, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT); -+ sten->c_dma_cookie = cookie | EP4_COOKIE_THREAD | EP4_COOKIE_REMOTE | EP4_COOKIE_DMA | EP4_COOKIE_INC; -+ sten->c_dma_vproc = vproc; -+ sten->c_dma_srcAddr = c_load_u32 (&env->Frags[i].nmd_addr); -+ sten->c_dma_dstAddr = buffer; -+ sten->c_dma_srcEvent = srcevent; -+ sten->c_dma_dstEvent = (E4_Addr) event; -+ -+ event->ev_CountAndType = E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_STEN_CMD_NDWORDS); -+ -+ buffer += fragLen; -+ len += fragLen; -+ -+ cookie += (EP4_COOKIE_INC << 1); -+ -+ sten++; event++; -+ } -+ -+ (--event)->ev_CountAndType = E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS); -+ -+ if (c_load_u32 (&rxdElan->rxd_buffer.nmd_len) < len) -+ { -+ /* The receive descriptor was too small for the message */ -+ /* complete the message anyway, but don't transfer any */ -+ /* data, we set the length to EP_MSG_TOO_BIG */ -+ for (i = first, sten = &rxdElan->rxd_sten[first]; i <= EP_MAXFRAG; i++, sten++) -+ sten->c_dma_typeSize = E4_DMA_TYPE_SIZE(0, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT); -+ -+ len = EP_MSG_TOO_BIG; -+ } -+ } -+ -+ /* Stuff the first STEN packet into the command queue, there's always enough space, -+ * since we will insert a waitevent at least once for the queue size */ -+ asm volatile ("ld64 [%0], %%r32\n" -+ "ld64 [%0 + 64], %%r48\n" -+ "st64 %%r32, [%1]\n" -+ "st64 %%r48, [%1]\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (&rxdElan->rxd_sten[first]), "r" (cport) -+ : /* clobbered */ R32_to_R47, R48_to_R63); -+ -+ /* remove the RXD from the pending list */ -+ if ((rcvrElan->rcvr_pending_head = rxdElan->rxd_next) == 0) -+ rcvrElan->rcvr_pending_tailp = (E4_Addr)&rcvrElan->rcvr_pending_head; -+ -+ /* mark as not queued */ -+ rxdElan->rxd_queued = 0; -+ -+ /* copy down the envelope */ -+ if (EP_HAS_PAYLOAD(attr)) -+ asm volatile ("ld64 [%0], %%r32\n" -+ "ld64 [%0+64], %%r48\n" -+ "st64 %%r32, [%1]\n" -+ "ld64 [%0+128], %%r32\n" -+ "st64 %%r48, [%1+64]\n" -+ "ld64 [%0+192], %%r48\n" -+ "st64 %%r32, [%1 + 128]\n" -+ "st64 %%r48, [%1 + 192]\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (env), "r" (&rxd->Envelope) -+ : /* clobbered */ R32_to_R47, R48_to_R63); -+ -+ else -+ asm volatile ("ld64 [%0], %%r32\n" -+ "ld64 [%0+64], %%r48\n" -+ "st64 %%r32, [%1]\n" -+ "st64 %%r48, [%1+64]\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (env), "r" (&rxd->Envelope) -+ : /* clobbered */ R32_to_R47, R48_to_R63); -+ -+ /* Store the message length to indicate that I've finished */ -+ c_store_u32 (&rxd->Len, len); -+ -+ /* Finally update the network error cookie */ -+ rail->r_cookies[nodeid] = cookie; -+ -+ EP4_SPINEXIT (resched, &rcvrElan->rcvr_thread_lock, &rcvrMain->rcvr_thread_lock); -+ -+ consume_envelope: -+ if (fptr != rcvrElan->rcvr_qlast) -+ fptr += EP_INPUTQ_SIZE; -+ else -+ fptr = rcvrElan->rcvr_qbase; -+ -+ if (! rcvrElan->rcvr_stall_intcookie) -+ inputq->q_fptr = fptr; -+ -+ if (++count >= RESCHED_AFTER_PKTS) -+ break; -+ -+ c_insn_check (cport); -+ } -+ -+ if (rcvrElan->rcvr_stall_intcookie) -+ { -+ c_waitevent_interrupt (cport, &rcvrElan->rcvr_thread_halt, -(1 << 5), rcvrElan->rcvr_stall_intcookie); -+ inputq->q_fptr = fptr; -+ -+ count++; /* one extra as we were given an extra set to wake us up */ -+ } -+ } -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsFwd.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsFwd.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsFwd.c 2005-06-01 23:12:54.643432416 -0400 -@@ -0,0 +1,310 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsFwd.c,v 1.12 2004/08/16 12:21:15 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsFwd.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "debug.h" -+ -+unsigned int epcomms_forward_limit = 8; -+ -+static void -+GenerateTree (unsigned nodeId, unsigned lowId, unsigned highId, bitmap_t *bitmap, -+ unsigned *parentp, unsigned *childrenp, int *nchildrenp) -+{ -+ int i; -+ int count; -+ int branch; -+ int nSub; -+ int branchIndex; -+ int parent; -+ int nBranch; -+ int rem; -+ int self; -+ int branchRatio; -+ int node; -+ int x, y, z; -+ -+ -+#ifdef DEBUG_PRINTF -+ { -+#define OVERFLOW "...]" -+#define LINESZ 128 -+ char space[LINESZ+1]; -+ -+ if (ep_sprintf_bitmap (space, LINESZ-strlen(OVERFLOW), bitmap, 0, 0, (highId - lowId)+1) != -1) -+ strcat (space, OVERFLOW); -+ -+ EPRINTF3 (DBG_FORWARD, "GenerateTree; elan node low=%d node high=%d bitmap=%s\n", lowId, highId, space); -+#undef OVERFLOW -+#undef LINESZ -+ } -+#endif -+ -+ /* Count the number of nodes in the partition */ -+ /* and work out which one I am */ -+ for (count = 0, self = ELAN_INVALID_NODE, i = lowId; i <= highId; i++) -+ { -+ if (BT_TEST (bitmap, i-lowId)) -+ { -+ if (i == nodeId) -+ self = count; -+ count++; -+ } -+ } -+ -+ EPRINTF2 (DBG_FORWARD, "GenerateTree: count=%d self=%d\n", count, self); -+ -+ if (count == 0 || self == ELAN_INVALID_NODE) -+ { -+ *parentp = ELAN_INVALID_NODE; -+ *nchildrenp = 0; -+ return; -+ } -+ -+ /* search for position in tree */ -+ branchRatio = EP_TREE_ARITY; /* branching ratio */ -+ branch = 0; /* start with process 0 */ -+ nSub = count; /* and whole tree */ -+ branchIndex = -1; /* my branch # in parent */ -+ parent = -1; /* my parent's group index # */ -+ -+ while (branch != self) /* descend process tree */ -+ { /* until I find myself */ -+ parent = branch; -+ branch++; /* parent + 1 = first born */ -+ nSub--; /* set # descendents */ -+ -+ rem = nSub % branchRatio; -+ nSub = nSub / branchRatio + 1; -+ x = rem * nSub; -+ y = self - branch; -+ -+ if (y < x) /* my first 'rem' branches have */ -+ { /* 1 more descendent... */ -+ branchIndex = y / nSub; -+ branch += branchIndex * nSub; -+ } -+ else /* than the rest of my branches */ -+ { -+ nSub--; -+ z = (y - x) / nSub; -+ branchIndex = rem + z; -+ branch += x + z * nSub; -+ } -+ } -+ -+ branch++; /* my first born */ -+ nSub--; /* total # of my descendents */ -+ /* leaves + their parents may have # children < branchRatio */ -+ nBranch = (nSub < branchRatio) ? nSub : branchRatio; -+ -+ EPRINTF2 (DBG_FORWARD, "GenerateTree: parent=%d nBranch=%d\n", parent, nBranch); -+ -+ /* Now calculate the real elan id's of the parent and my children */ -+ if (parent == -1) -+ *parentp = ELAN_INVALID_NODE; -+ else -+ { -+ for (i = lowId, node = 0; i <= highId; i++) -+ { -+ if (BT_TEST(bitmap, i-lowId)) -+ if (node++ == parent) -+ break; -+ } -+ *parentp = i; -+ } -+ -+ for (i = lowId, branchIndex = 0, node = 0; branchIndex < nBranch && i <= highId; i++) -+ { -+ if (BT_TEST(bitmap, i-lowId)) -+ { -+ if (node == branch) -+ { -+ branch = branch + nSub / branchRatio + ((branchIndex < (nSub % branchRatio)) ? 1 : 0); -+ -+ childrenp[branchIndex++] = i; -+ } -+ node++; -+ } -+ } -+ -+ *nchildrenp = branchIndex; -+} -+ -+static void -+ForwardTxDone (EP_TXD *txd, void *arg, EP_STATUS status) -+{ -+ EP_FWD_DESC *desc = (EP_FWD_DESC *) arg; -+ EP_RXD *rxd = desc->Rxd; -+ EP_COMMS_SUBSYS *subsys = rxd->Rcvr->Subsys; -+ unsigned long flags; -+ -+ /* XXXX: if transmit fails, could step to next node in this subtree ? */ -+ -+ spin_lock_irqsave (&subsys->ForwardDescLock, flags); -+ -+ if (--desc->NumChildren > 0) -+ spin_unlock_irqrestore (&subsys->ForwardDescLock, flags); -+ else -+ { -+ rxd->Rcvr->ForwardRxdCount--; -+ -+ spin_unlock_irqrestore (&subsys->ForwardDescLock, flags); -+ -+ KMEM_FREE (desc, sizeof (EP_FWD_DESC)); -+ -+ rxd->Handler (rxd); -+ } -+} -+ -+long -+ep_forward_rxds (EP_COMMS_SUBSYS *subsys, long nextRunTime) -+{ -+ unsigned long flags; -+ int i, res; -+ -+ spin_lock_irqsave (&subsys->ForwardDescLock, flags); -+ while (! list_empty (&subsys->ForwardDescList)) -+ { -+ EP_RXD *rxd = (EP_RXD *) list_entry (subsys->ForwardDescList.next, EP_RXD, Link); -+ EP_RXD_MAIN *rxdMain = rxd->RxdMain; -+ EP_ENVELOPE *env = &rxdMain->Envelope; -+ EP_FWD_DESC *desc; -+ -+ EPRINTF2 (DBG_FORWARD, "ep: forwarding rxd %p to range %x\n", rxd, env->Range); -+ -+ list_del (&rxd->Link); -+ -+ rxd->Rcvr->ForwardRxdCount++; -+ -+ spin_unlock_irqrestore (&subsys->ForwardDescLock, flags); -+ -+ KMEM_ALLOC (desc, EP_FWD_DESC *, sizeof (EP_FWD_DESC), 1); -+ -+ if (desc == NULL) -+ { -+ spin_lock_irqsave (&subsys->ForwardDescLock, flags); -+ rxd->Rcvr->ForwardRxdCount--; -+ spin_unlock_irqrestore (&subsys->ForwardDescLock, flags); -+ -+ rxd->Handler (rxd); -+ } -+ else -+ { -+ /* compute the spanning tree for this message */ -+ unsigned int destLo = EP_RANGE_LOW (env->Range); -+ unsigned int destHi = EP_RANGE_HIGH (env->Range); -+ unsigned int parent; -+ -+ GenerateTree (subsys->Subsys.Sys->Position.pos_nodeid, destLo, destHi, rxdMain->Bitmap, &parent, desc->Children, &desc->NumChildren); -+ -+ if (desc->NumChildren == 0 || (epcomms_forward_limit && (rxd->Rcvr->ForwardRxdCount >= epcomms_forward_limit))) -+ { -+ EPRINTF5 (DBG_FORWARD, "ep; don't forward rxd %p to /%d (%d children/ %d forwarding (%d))\n", -+ rxd, rxd->Rcvr->Service, desc->NumChildren, rxd->Rcvr->ForwardRxdCount, epcomms_forward_limit); -+ -+ spin_lock_irqsave (&subsys->ForwardDescLock, flags); -+ rxd->Rcvr->ForwardRxdCount--; -+ spin_unlock_irqrestore (&subsys->ForwardDescLock, flags); -+ -+ KMEM_FREE (desc, sizeof (EP_FWD_DESC)); -+ -+ rxd->Handler (rxd); -+ } -+ else -+ { -+ ep_nmd_subset (&desc->Data, &rxd->Data, 0, ep_rxd_len (rxd)); -+ desc->Rxd = rxd; -+ -+ /* NOTE - cannot access 'desc' after last call to multicast, since it could complete -+ * and free the desc before we access it again. Hence the reverse loop. */ -+ for (i = desc->NumChildren-1; i >= 0; i--) -+ { -+ ASSERT (desc->Children[i] < subsys->Subsys.Sys->Position.pos_nodes); -+ -+ EPRINTF3 (DBG_FORWARD, "ep: forwarding rxd %p to node %d/%d\n", rxd, desc->Children[i], rxd->Rcvr->Service); -+ -+ if ((res = ep_multicast_forward (subsys->ForwardXmtr, desc->Children[i], rxd->Rcvr->Service, 0, -+ ForwardTxDone, desc, env, EP_HAS_PAYLOAD(env->Attr) ? &rxdMain->Payload : NULL, -+ rxdMain->Bitmap, &desc->Data, 1)) != EP_SUCCESS) -+ { -+ ep_debugf (DBG_FORWARD, "ep: ep_multicast_forward failed\n"); -+ ForwardTxDone (NULL, desc, res); -+ } -+ } -+ -+ } -+ } -+ -+ spin_lock_irqsave (&subsys->ForwardDescLock, flags); -+ } -+ spin_unlock_irqrestore (&subsys->ForwardDescLock, flags); -+ -+ return (nextRunTime); -+} -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+void -+ep_csum_rxds (EP_COMMS_SUBSYS *subsys) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&subsys->CheckSumDescLock, flags); -+ while (! list_empty (&subsys->CheckSumDescList)) -+ { -+ EP_RXD *rxd = (EP_RXD *) list_entry (subsys->CheckSumDescList.next, EP_RXD, CheckSumLink); -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ -+ list_del_init (&rxd->CheckSumLink); -+ spin_unlock_irqrestore (&subsys->CheckSumDescLock, flags); -+ -+ if (env->CheckSum) { -+ EP_NMD nmd; -+ uint32_t csum; -+ -+ ep_nmd_subset ( &nmd, &rxd->Data, 0, ep_rxd_len (rxd)); -+ -+ csum = ep_calc_check_sum(subsys->Subsys.Sys, env, &nmd, 1); -+ if ( env->CheckSum != csum ) { -+ int f; -+ -+ -+ printk("Check Sum Error: env(0x%x,0x%x) data(0x%x,0x%x)\n", ((csum >> 16) & 0x7FFF), ((env->CheckSum >> 16) & 0x7FFF), -+ (csum & 0xFFFF), (env->CheckSum & 0xFFFF)); -+ printk("Check Sum Error: Sent : NodeId %u Range 0x%x Service %u Version 0x%x Attr 0x%x\n", env->NodeId, env->Range, rxd->Rcvr->Service, env->Version, env->Attr); -+ printk("Check Sum Error: Sent : Xid Generation 0x%x Handle 0x%x Unique 0x%llx\n", env->Xid.Generation, env->Xid.Handle, env->Xid.Unique); -+ printk("Check Sum Error: Sent : TxdRail 0x%x TxdMain nmd_addr 0x%x nmd_len %u nmd_attr 0x%x\n", env->TxdRail, env->TxdMain.nmd_addr, env->TxdMain.nmd_len, env->TxdMain.nmd_attr ); -+ printk("Check Sum Error: Sent : nFrags %d \n", env->nFrags); -+ for(f=0;fnFrags;f++) -+ printk("Check Sum Error: Sent (%d): nmd_addr 0x%x nmd_len %u nmd_attr 0x%x\n", f, -+ env->Frags[f].nmd_addr, env->Frags[f].nmd_len, env->Frags[f].nmd_attr); -+ printk("Check Sum Error: Recv : nmd_addr 0x%x nmd_len %u nmd_attr 0x%x\n", -+ nmd.nmd_addr, nmd.nmd_len, nmd.nmd_attr); -+ -+ } -+ } -+ ep_rxd_received_now(rxd); -+ -+ spin_lock_irqsave (&subsys->CheckSumDescLock, flags); -+ } -+ spin_unlock_irqrestore (&subsys->CheckSumDescLock, flags); -+} -+#endif -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsRx.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsRx.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsRx.c 2005-06-01 23:12:54.645432112 -0400 -@@ -0,0 +1,1205 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsRx.c,v 1.27.2.5 2004/11/30 12:02:16 mike Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsRx.c,v $*/ -+ -+#include -+#include -+#include -+#include -+ -+#include "debug.h" -+ -+unsigned int ep_rxd_lowat = 5; -+ -+static int -+AllocateRxdBlock (EP_RCVR *rcvr, EP_ATTRIBUTE attr, EP_RXD **rxdp) -+{ -+ EP_RXD_BLOCK *blk; -+ EP_RXD *rxd; -+ EP_RXD_MAIN *pRxdMain; -+ int i; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (blk, EP_RXD_BLOCK *, sizeof (EP_RXD_BLOCK), ! (attr & EP_NO_SLEEP)); -+ -+ if (blk == NULL) -+ return (ENOMEM); -+ -+ if ((pRxdMain = ep_shared_alloc_main (rcvr->Subsys->Subsys.Sys, EP_RXD_MAIN_SIZE * EP_NUM_RXD_PER_BLOCK, attr, &blk->NmdMain)) == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (blk, sizeof (EP_RXD_BLOCK)); -+ return (ENOMEM); -+ } -+ -+ for (rxd = &blk->Rxd[0], i = 0; i < EP_NUM_RXD_PER_BLOCK; i++, rxd++) -+ { -+ rxd->Rcvr = rcvr; -+ rxd->RxdMain = pRxdMain; -+ -+ ep_nmd_subset (&rxd->NmdMain, &blk->NmdMain, (i * EP_RXD_MAIN_SIZE), EP_RXD_MAIN_SIZE); -+ -+ /* move onto next descriptor */ -+ pRxdMain = (EP_RXD_MAIN *) ((unsigned long) pRxdMain + EP_RXD_MAIN_SIZE); -+ } -+ -+ spin_lock_irqsave (&rcvr->FreeDescLock, flags); -+ -+ list_add (&blk->Link, &rcvr->DescBlockList); -+ -+ rcvr->TotalDescCount += EP_NUM_RXD_PER_BLOCK; -+ -+ for (i = rxdp ? 1 : 0; i < EP_NUM_RXD_PER_BLOCK; i++) -+ { -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ INIT_LIST_HEAD (&blk->Rxd[i].CheckSumLink); -+#endif -+ -+ list_add (&blk->Rxd[i].Link, &rcvr->FreeDescList); -+ -+ rcvr->FreeDescCount++; -+ -+ if (rcvr->FreeDescWanted) -+ { -+ rcvr->FreeDescWanted--; -+ kcondvar_wakeupone (&rcvr->FreeDescSleep, &rcvr->FreeDescLock); -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+ -+ if (rxdp) -+ { -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ INIT_LIST_HEAD (&blk->Rxd[0].CheckSumLink); -+#endif -+ -+ *rxdp = &blk->Rxd[0]; -+ } -+ return (ESUCCESS); -+} -+ -+static void -+FreeRxdBlock (EP_RCVR *rcvr, EP_RXD_BLOCK *blk) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->FreeDescLock, flags); -+ -+ list_del (&blk->Link); -+ -+ rcvr->TotalDescCount -= EP_NUM_RXD_PER_BLOCK; -+ rcvr->FreeDescCount -= EP_NUM_RXD_PER_BLOCK; -+ -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+ -+ ep_shared_free_main (rcvr->Subsys->Subsys.Sys, &blk->NmdMain); -+ KMEM_FREE (blk, sizeof (EP_RXD_BLOCK)); -+} -+ -+static EP_RXD * -+GetRxd (EP_RCVR *rcvr, EP_ATTRIBUTE attr) -+{ -+ EP_RXD *rxd; -+ unsigned long flags; -+ int low_on_rxds; -+ -+ spin_lock_irqsave (&rcvr->FreeDescLock, flags); -+ -+ while (list_empty (&rcvr->FreeDescList)) -+ { -+ if (! (attr & EP_NO_ALLOC)) -+ { -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+ -+ if (AllocateRxdBlock (rcvr, attr, &rxd) == ESUCCESS) -+ return (rxd); -+ -+ spin_lock_irqsave (&rcvr->FreeDescLock, flags); -+ } -+ -+ if (attr & EP_NO_SLEEP) -+ { -+ IncrStat (rcvr->Subsys, NoFreeRxds); -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ return (NULL); -+ } -+ -+ rcvr->FreeDescWanted++; -+ kcondvar_wait (&rcvr->FreeDescSleep, &rcvr->FreeDescLock, &flags); -+ } -+ -+ rxd = list_entry (rcvr->FreeDescList.next, EP_RXD, Link); -+ -+ list_del (&rxd->Link); -+ -+ /* Wakeup the descriptor primer thread if there's not many left */ -+ low_on_rxds = (--rcvr->FreeDescCount < ep_rxd_lowat); -+ -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+ -+ if (low_on_rxds) -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ -+ return (rxd); -+} -+ -+static void -+FreeRxd (EP_RCVR *rcvr, EP_RXD *rxd) -+{ -+ unsigned long flags; -+ -+ ASSERT (EP_XID_INVALID(rxd->MsgXid)); -+ -+ spin_lock_irqsave (&rcvr->FreeDescLock, flags); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ ASSERT(list_empty(&rxd->CheckSumLink)); -+#endif -+ -+ list_add (&rxd->Link, &rcvr->FreeDescList); -+ -+ rcvr->FreeDescCount++; -+ -+ if (rcvr->FreeDescWanted) /* someone waiting for a receive */ -+ { /* descriptor, so wake them up */ -+ rcvr->FreeDescWanted--; -+ kcondvar_wakeupone (&rcvr->FreeDescSleep, &rcvr->FreeDescLock); -+ } -+ -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+} -+ -+int -+ep_queue_receive (EP_RCVR *rcvr, EP_RXH *handler, void *arg, EP_NMD *nmd, EP_ATTRIBUTE attr) -+{ -+ EP_RCVR_RAIL *rcvrRail; -+ EP_RXD *rxd; -+ int rnum; -+ unsigned long flags; -+ -+ if ((rxd = GetRxd (rcvr, attr)) == NULL) -+ return (ENOMEM); -+ -+ rxd->Handler = handler; -+ rxd->Arg = arg; -+ rxd->Data = *nmd; -+ rxd->RxdMain->Len = EP_RXD_PENDING; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ list_add_tail (&rxd->Link, &rcvr->ActiveDescList); -+ -+ if (EP_IS_PREFRAIL_SET(attr)) -+ rnum = EP_ATTR2PREFRAIL(attr); -+ else -+ rnum = ep_rcvr_prefrail (rcvr, EP_NMD_RAILMASK(nmd)); -+ -+ if (rnum < 0 || !(EP_NMD_RAILMASK(nmd) & EP_RAIL2RAILMASK(rnum) & rcvr->RailMask)) -+ rcvrRail = NULL; -+ else -+ rcvrRail = rcvr->Rails[rnum]; -+ -+ EPRINTF7 (DBG_RCVR,"ep_queue_receive: rxd=%p svc %d nmd=%08x,%d,%x rnum=%d rcvrRail=%p\n", -+ rxd, rcvr->Service, nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr, rnum, rcvrRail); -+ -+ rxd->State = EP_RXD_RECEIVE_ACTIVE; -+ -+ if (rcvrRail == NULL || !EP_RCVR_OP (rcvrRail, QueueRxd) (rxd, rcvrRail)) -+ { -+ rxd->State = EP_RXD_RECEIVE_UNBOUND; -+ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return (ESUCCESS); -+} -+ -+void -+ep_requeue_receive (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_NMD *nmd, EP_ATTRIBUTE attr) -+{ -+ EP_RCVR *rcvr = rxd->Rcvr; -+ EP_SYS *sys = rcvr->Subsys->Subsys.Sys; -+ int rnum = ep_pickRail(EP_NMD_RAILMASK(&rxd->Data)); -+ EP_RCVR_RAIL *rcvrRail; -+ unsigned long flags; -+ -+ ASSERT (rxd->RxdRail == NULL); -+ -+ EPRINTF5 (DBG_RCVR,"ep_requeue_receive: rxd=%p svc %d nmd=%08x,%d,%x\n", -+ rxd, rcvr->Service, nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr); -+ -+ rxd->Handler = handler; -+ rxd->Arg = arg; -+ rxd->Data = *nmd; -+ rxd->RxdMain->Len = EP_RXD_PENDING; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ list_add_tail (&rxd->Link, &rcvr->ActiveDescList); -+ -+ /* -+ * Rail selection: if they've asked for a particular rail, then use it, otherwise if -+ * the rail it was last received on is mapped for the nmd and is available -+ * then use that one, otherwise pick one that is mapped by the nmd. -+ */ -+ if (EP_IS_PREFRAIL_SET(attr)) -+ rnum = EP_ATTR2PREFRAIL(attr); -+ -+ if (rnum < 0 || ! (EP_RAIL2RAILMASK (rnum) & EP_NMD_RAILMASK(nmd) & ep_rcvr_availrails (rcvr))) -+ rnum = ep_rcvr_prefrail (rcvr, EP_NMD_RAILMASK(nmd)); -+ -+ if (rnum < 0) -+ rcvrRail = NULL; -+ else -+ { -+ rcvrRail = rcvr->Rails[rnum]; -+ -+ if (! (EP_NMD_RAILMASK(&rxd->Data) & EP_RAIL2RAILMASK(rnum)) && ep_nmd_map_rails (sys, &rxd->Data, EP_RAIL2RAILMASK(rnum)) < 0) -+ rcvrRail = NULL; -+ } -+ -+ rxd->State = EP_RXD_RECEIVE_ACTIVE; -+ -+ if (rcvrRail == NULL || !EP_RCVR_OP(rcvrRail, QueueRxd) (rxd, rcvrRail)) -+ { -+ EPRINTF1 (DBG_RCVR, "ep_requeue_receive: rcvrRail=%p - setting unbound\n", rcvrRail); -+ -+ rxd->State = EP_RXD_RECEIVE_UNBOUND; -+ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+ -+ if (rcvr->CleanupWaiting) -+ kcondvar_wakeupall (&rcvr->CleanupSleep, &rcvr->Lock); -+ rcvr->CleanupWaiting = 0; -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ -+ep_complete_receive (EP_RXD *rxd) -+{ -+ EP_RCVR *rcvr = rxd->Rcvr; -+ unsigned long flags; -+ -+ ASSERT (rxd->RxdRail == NULL && rxd->State == EP_RXD_COMPLETED); -+ -+ FreeRxd (rcvr, rxd); -+ -+ /* if we're waiting for cleanup, then wake them up */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ if (rcvr->CleanupWaiting) -+ kcondvar_wakeupall (&rcvr->CleanupSleep, &rcvr->Lock); -+ rcvr->CleanupWaiting = 0; -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+int -+ep_rpc_put (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_NMD *local, EP_NMD *remote, int nFrags) -+{ -+ EP_RCVR *rcvr = rxd->Rcvr; -+ EP_SYS *sys = rcvr->Subsys->Subsys.Sys; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ if (rxd->State == EP_RXD_BEEN_ABORTED) -+ { -+ EPRINTF2 (DBG_RCVR, "ep_rpc_put: rcvr %p rxd %p completed because no rails available\n", rcvr, rxd); -+ -+ /* rxd no longer on active list - just free it */ -+ /* off and return an error */ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return EP_CONN_RESET; -+ } -+ else -+ { -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ EP_RCVR_RAIL *rcvrRail = rxdRail->RcvrRail; -+ EP_COMMS_RAIL *commsRail = rcvrRail->CommsRail; -+ EP_RAIL *rail = commsRail->Rail; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[env->NodeId]; -+ int i; -+ -+ /* Attempt to ensure that the local nmds are mapped */ -+ for (i = 0; i < nFrags; i++) -+ if (! (EP_NMD_RAILMASK(&local[i]) & EP_RAIL2RAILMASK(rail->Number))) -+ ep_nmd_map_rails (sys, &local[i], EP_RAIL2RAILMASK(rail->Number)); -+ -+ if (nodeRail->State == EP_NODE_CONNECTED && /* rail is connected */ -+ (ep_nmd2railmask (local, nFrags) & ep_nmd2railmask (remote, nFrags) & EP_RAIL2RAILMASK (rail->Number))) /* and NMDs valid for it */ -+ { -+ rxd->State = EP_RXD_PUT_ACTIVE; -+ -+ EP_RCVR_OP(rcvrRail, RpcPut) (rxd, local, remote, nFrags); -+ } -+ else -+ { -+ /* RPC completion cannot progress - either node is no longer connected on this -+ * rail or some of the source/destination NMDs are not mapped on this rail. -+ * Save the NMDs into the RXD and schedule the thread to request mappings */ -+ EPRINTF4 (DBG_RCVR, "%s: ep_rpc_put: rcvr %p rxd %p %s\n", rail->Name, rcvr, rxd, -+ (nodeRail->State == EP_NODE_CONNECTED) ? "NMDs not valid on this rail" : "no longer connected on this rail"); -+ -+ rxd->State = EP_RXD_PUT_STALLED; -+ -+ if (nodeRail->State == EP_NODE_CONNECTED) -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+ -+ /* install the handler */ -+ rxd->Handler = handler; -+ rxd->Arg = arg; -+ -+ /* store the arguements */ -+ rxd->nFrags = nFrags; -+ for (i = 0; i < nFrags; i++) -+ { -+ rxd->Local[i] = local[i]; -+ rxd->Remote[i] = remote[i]; -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return EP_SUCCESS; -+} -+ -+int -+ep_rpc_get (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_NMD *remote, EP_NMD *local, int nFrags) -+{ -+ EP_RCVR *rcvr = rxd->Rcvr; -+ EP_SYS *sys = rcvr->Subsys->Subsys.Sys; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ if (rxd->State == EP_RXD_BEEN_ABORTED) -+ { -+ EPRINTF2 (DBG_RCVR, "ep_rpc_get: rcvr %p rxd %p completed because no rails available\n", rcvr, rxd); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return EP_CONN_RESET; -+ } -+ else -+ { -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ EP_RCVR_RAIL *rcvrRail = rxdRail->RcvrRail; -+ EP_COMMS_RAIL *commsRail = rcvrRail->CommsRail; -+ EP_RAIL *rail = commsRail->Rail; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[env->NodeId]; -+ int i; -+ -+ /* Attempt to ensure that the local nmds are mapped */ -+ for (i = 0; i < nFrags; i++) -+ if (! (EP_NMD_RAILMASK(&local[i]) & EP_RAIL2RAILMASK(rail->Number))) -+ ep_nmd_map_rails (sys, &local[i], EP_RAIL2RAILMASK(rail->Number)); -+ -+ if (nodeRail->State == EP_NODE_CONNECTED && /* rail is connected */ -+ (ep_nmd2railmask (local, nFrags) & ep_nmd2railmask (remote, nFrags) & EP_RAIL2RAILMASK (rail->Number))) /* and NMDs valid for it */ -+ { -+ rxd->State = EP_RXD_GET_ACTIVE; -+ -+ EP_RCVR_OP (rcvrRail, RpcGet) (rxd, local, remote, nFrags); -+ } -+ else -+ { -+ /* RPC completion cannot progress - either node is no longer connected on this -+ * node or some of the source/destination NMDs are not mapped on this rail. -+ * Save the NMDs into the RXD and schedule the thread to request mappings */ -+ EPRINTF4 (DBG_RCVR, "%s: ep_rpc_get: rcvr %p rxd %p %s\n", rail->Name, rcvr, rxd, -+ (nodeRail->State == EP_NODE_CONNECTED) ? "NMDs not valid on this rail" : "no longer connected on this rail"); -+ -+ rxd->State = EP_RXD_GET_STALLED; -+ -+ if (nodeRail->State == EP_NODE_CONNECTED) -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+ -+ /* install the handler */ -+ rxd->Handler = handler; -+ rxd->Arg = arg; -+ -+ /* store the arguements */ -+ rxd->nFrags = nFrags; -+ for (i = 0; i < nFrags; i++) -+ { -+ rxd->Local[i] = local[i]; -+ rxd->Remote[i] = remote[i]; -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return EP_SUCCESS; -+} -+ -+int -+ep_complete_rpc (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_STATUSBLK *blk, EP_NMD *local, EP_NMD *remote, int nFrags) -+{ -+ EP_RCVR *rcvr = rxd->Rcvr; -+ EP_SYS *sys = rcvr->Subsys->Subsys.Sys; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ if (rxd->State == EP_RXD_BEEN_ABORTED) -+ { -+ EPRINTF2 (DBG_RCVR, "ep_complete_rpc: rcvr %p rxd %p completed because no rails available\n", rcvr, rxd); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ return EP_CONN_RESET; -+ } -+ else -+ { -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ EP_RCVR_RAIL *rcvrRail = rxdRail->RcvrRail; -+ EP_COMMS_RAIL *commsRail = rcvrRail->CommsRail; -+ EP_RAIL *rail = commsRail->Rail; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[env->NodeId]; -+ int i; -+ -+ if (blk == NULL) -+ bzero (&rxd->RxdMain->StatusBlk, sizeof (EP_STATUSBLK)); -+ else -+ bcopy (blk, &rxd->RxdMain->StatusBlk, sizeof (EP_STATUSBLK)); -+ -+ /* Attempt to ensure that the local nmds are mapped */ -+ for (i = 0; i < nFrags; i++) -+ if (! (EP_NMD_RAILMASK(&local[i]) & EP_RAIL2RAILMASK(rail->Number))) -+ ep_nmd_map_rails (sys, &local[i], EP_RAIL2RAILMASK(rail->Number)); -+ -+ if (nodeRail->State == EP_NODE_CONNECTED && /* rail is connected */ -+ (ep_nmd2railmask (local, nFrags) & ep_nmd2railmask (remote, nFrags) & EP_RAIL2RAILMASK (rail->Number))) /* and NMDs valid for it */ -+ { -+ rxd->State = EP_RXD_COMPLETE_ACTIVE; -+ -+ EP_RCVR_OP (rcvrRail, RpcComplete) (rxd, local, remote, nFrags); -+ } -+ else -+ { -+ /* RPC completion cannot progress - either node is no longer connected on this -+ * node or some of the source/destination NMDs are not mapped on this rail. -+ * Save the NMDs into the RXD and schedule the thread to request mappings */ -+ EPRINTF4 (DBG_RCVR, "%s: ep_complete_rpc: rcvr %p rxd %p %s\n", rail->Name, rcvr, rxd, -+ (nodeRail->State == EP_NODE_CONNECTED) ? "NMDs not valid on this rail" : "no longer connected on this rail"); -+ -+ rxd->State = EP_RXD_COMPLETE_STALLED; -+ -+ if (nodeRail->State == EP_NODE_CONNECTED) -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+ -+ /* install the handler */ -+ rxd->Handler = handler; -+ rxd->Arg = arg; -+ -+ /* store the arguements */ -+ rxd->nFrags = nFrags; -+ for (i = 0; i < nFrags; i++) -+ { -+ rxd->Local[i] = local[i]; -+ rxd->Remote[i] = remote[i]; -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return (ESUCCESS); -+} -+ -+/* functions for accessing fields of rxds */ -+void *ep_rxd_arg(EP_RXD *rxd) { return (rxd->Arg); } -+int ep_rxd_len(EP_RXD *rxd) { return (rxd->RxdMain->Len); } -+EP_STATUS ep_rxd_status(EP_RXD *rxd) { return (rxd->RxdMain->Len < 0 ? rxd->RxdMain->Len : EP_SUCCESS); } -+int ep_rxd_isrpc(EP_RXD *rxd) { return (EP_IS_RPC(rxd->RxdMain->Envelope.Attr) != 0); } -+EP_ENVELOPE *ep_rxd_envelope(EP_RXD *rxd) { return (&rxd->RxdMain->Envelope); } -+EP_PAYLOAD *ep_rxd_payload(EP_RXD *rxd) { return (EP_HAS_PAYLOAD(rxd->RxdMain->Envelope.Attr) ? &rxd->RxdMain->Payload : NULL); } -+int ep_rxd_node(EP_RXD *rxd) { return (rxd->RxdMain->Envelope.NodeId); } -+EP_STATUSBLK *ep_rxd_statusblk(EP_RXD *rxd) { return (&rxd->RxdMain->StatusBlk); } -+EP_RAILMASK ep_rxd_railmask(EP_RXD *rxd) { return (rxd->Data.nmd_attr); } -+ -+static void -+ProcessNmdMapResponse (EP_RCVR *rcvr, EP_RXD *rxd, EP_MANAGER_MSG *msg) -+{ -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ EP_RCVR_RAIL *rcvrRail = rxdRail->RcvrRail; -+ EP_RAIL *rail = rcvrRail->CommsRail->Rail; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[rxd->RxdMain->Envelope.NodeId]; -+ int i; -+ -+ ASSERT (msg->Body.MapNmd.nFrags == rxd->nFrags); -+ -+ for (i = 0; i < rxd->nFrags; i++) -+ rxd->Remote[i] = msg->Body.MapNmd.Nmd[i]; -+ -+ if (nodeRail->State == EP_NODE_CONNECTED && /* node is still connected on this rail */ -+ (ep_nmd2railmask (rxd->Local, rxd->nFrags) & ep_nmd2railmask (rxd->Remote, rxd->nFrags) & EP_RAIL2RAILMASK (rail->Number))) /* NMDs are now valid for this rail */ -+ { -+ switch (rxd->State) -+ { -+ case EP_RXD_PUT_STALLED: -+ rxd->State = EP_RXD_PUT_ACTIVE; -+ -+ EP_RCVR_OP(rcvrRail, RpcPut) (rxd, rxd->Local, rxd->Remote, rxd->nFrags); -+ break; -+ -+ case EP_RXD_GET_STALLED: -+ rxd->State = EP_RXD_GET_ACTIVE; -+ -+ EP_RCVR_OP(rcvrRail, RpcGet) (rxd, rxd->Local, rxd->Remote, rxd->nFrags); -+ break; -+ -+ case EP_RXD_COMPLETE_STALLED: -+ rxd->State = EP_RXD_COMPLETE_ACTIVE; -+ -+ EP_RCVR_OP(rcvrRail, RpcComplete) (rxd, rxd->Local, rxd->Remote, rxd->nFrags); -+ break; -+ -+ default: -+ panic ("ProcessNmdMapResponse: XID match but rxd in invalid state\n"); -+ break; -+ } -+ -+ rxd->NextRunTime = 0; -+ } -+ else -+ ep_debugf (DBG_MANAGER, "%s: ep_rcvr_xid_msg_handler: rcvr=%p rxd=%p - still cannot proceed\n", rail->Name, rcvr, rxd); -+} -+ -+static void -+ProcessFailoverResponse (EP_RCVR *rcvr, EP_RXD *rxd, EP_MANAGER_MSG *msg) -+{ -+ /* XXXX - TBD */ -+#ifdef NOTYET -+ EP_COMMS_SUBSYS *subsys = rcvr->Subsys; -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ EP_RCVR_RAIL *rcvrRail = rxdRail->RcvrRail; -+ EP_RAIL *rail = rcvrRail->CommsRail->Rail; -+ EP_RCVR_RAIL *nRcvrRail; -+ EP_RXD_RAIL *nRxdRail; -+ -+ ASSERT (rxd->RxdMain->Envelope.Attr & EP_RPC); -+ -+ EPRINTF6 (DBG_RCVR, "ep_rcvr_xid_msg_handler: rcvr=%p rxd=%p Xid=%016llx state %x.%x - txd on rail %d\n", rcvr, rxd, -+ rxd->MsgXid.Unique, rxdRail->RxdMain->DataEvent, rxdRail->RxdMain->DoneEvent, msg->Body.FailoverTxd.Rail); -+ -+ if ((nRcvrRail = rcvr->Rails[msg->Body.FailoverTxd.Rail]) == NULL || -+ (nRcvrRail->Rcvr->RailMask & EP_RAIL2RAILMASK (rail->Number)) == NULL) -+ { -+ ep_debugf (DBG_MANAGER, "%s: ep_rcvr_xid_msg_handler: rcvr=%p rxd=%p - still cannot proceed\n", rail->Name, rcvr,rxd); -+ return; -+ } -+ -+ -+ nRxdRail = EP_RCVR_OP (nrcvrRail, GetRxd) (rcvr, nRcvrRail); -+ -+ -+ /* If the RPC was in progress, then rollback and mark it as flagged, -+ * this will then get treated as though the NMDs were not mapped -+ * for the rail when the user initiated the operation. -+ */ -+ switch (rxdRail->RxdMain->DataEvent) -+ { -+ case EP_EVENT_ACTIVE|EP_RXD_PHASE_PUT: -+ case EP_EVENT_FLAGGED|EP_RXD_PHASE_PUT: -+ ASSERT (rxdRail->RxdMain->DoneEvent == EP_EVENT_PRIVATE || -+ rxdRail->RxdMain->DoneEvent == EP_EVENT_PENDING); -+ -+ nRxdRail->RxdMain->DataEvent = EP_EVENT_FLAGGED|EP_RXD_PHASE_PUT; -+ nRxdRail->RxdMain->DoneEvent = EP_EVENT_PENDING; -+ break; -+ -+ case EP_EVENT_ACTIVE|EP_RXD_PHASE_GET: -+ case EP_EVENT_FLAGGED|EP_RXD_PHASE_GET: -+ ASSERT (rxdRail->RxdMain->DoneEvent == EP_EVENT_PRIVATE || -+ rxdRail->RxdMain->DoneEvent == EP_EVENT_PENDING); -+ -+ nRxdRail->RxdMain->DataEvent = EP_EVENT_FLAGGED|EP_RXD_PHASE_GET; -+ nRxdRail->RxdMain->DoneEvent = EP_EVENT_PENDING; -+ break; -+ -+ case EP_EVENT_PRIVATE: -+ switch (rxdRail->RxdMain->DoneEvent) -+ { -+ case EP_EVENT_ACTIVE|EP_RXD_PHASE_COMPLETE: -+ case EP_EVENT_FLAGGED|EP_RXD_PHASE_COMPLETE: -+ nRxdRail->RxdMain->DataEvent = EP_EVENT_PRIVATE; -+ nRxdRail->RxdMain->DoneEvent = EP_EVENT_FLAGGED|EP_RXD_PHASE_COMPLETE; -+ break; -+ -+ case EP_EVENT_PENDING: -+ break; -+ -+ default: -+ panic ("ep_rcvr_xid_msg_handler: rxd in invalid state\n"); -+ } -+ break; -+ -+ default: -+ panic ("ep_rcvr_xid_msg_handler: rxd in invalid staten"); -+ } -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ -+ /* Mark rxdRail as no longer active */ -+ rxdRail->RxdMain->DataEvent = EP_EVENT_PRIVATE; -+ rxdRail->RxdMain->DoneEvent = EP_EVENT_PRIVATE; -+ -+ sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP_RXD_RAIL_ELAN, DataEvent.ev_Count), 0); -+ sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP_RXD_RAIL_ELAN, DoneEvent.ev_Count), 0); -+ -+ FreeRxdRail (rcvrRail, rxdRail); -+ -+ BindRxdToRail (rxd, nRxdRail); -+ -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+#endif -+} -+ -+void -+ep_rcvr_xid_msg_handler (void *arg, EP_MANAGER_MSG *msg) -+{ -+ EP_RCVR *rcvr = (EP_RCVR *) arg; -+ struct list_head *el; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ list_for_each (el, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el,EP_RXD, Link); -+ -+ if (EP_XIDS_MATCH (msg->Hdr.Xid, rxd->MsgXid)) -+ { -+ EP_INVALIDATE_XID (rxd->MsgXid); -+ -+ switch (msg->Hdr.Type) -+ { -+ case EP_MANAGER_MSG_TYPE_MAP_NMD_RESPONSE: -+ ProcessNmdMapResponse (rcvr, rxd, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_FAILOVER_RESPONSE: -+ ProcessFailoverResponse (rcvr, rxd, msg); -+ break; -+ -+ default: -+ panic ("ep_rcvr_xid_msg_handler: XID match but invalid message type\n"); -+ } -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+ -+EP_RCVR * -+ep_alloc_rcvr (EP_SYS *sys, EP_SERVICE svc, unsigned int nenvs) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ EP_RCVR *rcvr; -+ struct list_head *el; -+ extern int portals_envelopes; -+ -+ if (portals_envelopes && (svc == EP_MSG_SVC_PORTALS_SMALL || svc == EP_MSG_SVC_PORTALS_LARGE)) -+ { -+ printk ("ep: use %d envelopes rather than %d for portals %s message service\n", sys->Position.pos_nodes * 16, nenvs, -+ svc == EP_MSG_SVC_PORTALS_SMALL ? "small" : "large"); -+ -+ nenvs = portals_envelopes; -+ } -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (sys, EPCOMMS_SUBSYS_NAME)) == NULL) -+ return (NULL); -+ -+ KMEM_ZALLOC (rcvr, EP_RCVR *, sizeof (EP_RCVR), 1); -+ -+ if (rcvr == NULL) -+ return (NULL); -+ -+ rcvr->Subsys = subsys; -+ rcvr->Service = svc; -+ rcvr->InputQueueEntries = nenvs; -+ rcvr->FreeDescCount = 0; -+ rcvr->TotalDescCount = 0; -+ rcvr->ForwardRxdCount = 0; -+ -+ spin_lock_init (&rcvr->Lock); -+ INIT_LIST_HEAD (&rcvr->ActiveDescList); -+ -+ kcondvar_init (&rcvr->CleanupSleep); -+ kcondvar_init (&rcvr->FreeDescSleep); -+ spin_lock_init (&rcvr->FreeDescLock); -+ INIT_LIST_HEAD (&rcvr->FreeDescList); -+ INIT_LIST_HEAD (&rcvr->DescBlockList); -+ -+ ep_xid_cache_init (sys, &rcvr->XidCache); -+ -+ rcvr->XidCache.MessageHandler = ep_rcvr_xid_msg_handler; -+ rcvr->XidCache.Arg = rcvr; -+ -+ kmutex_lock (&subsys->Lock); -+ /* See if this service is already in use */ -+ list_for_each (el, &subsys->Receivers) { -+ EP_RCVR *rcvr = list_entry (el, EP_RCVR, Link); -+ -+ if (rcvr->Service == svc) -+ { -+ KMEM_FREE (rcvr, sizeof (EP_RCVR)); -+ kmutex_unlock (&subsys->Lock); -+ return NULL; -+ } -+ } -+ -+ -+ list_add_tail (&rcvr->Link, &subsys->Receivers); -+ -+ ep_procfs_rcvr_add(rcvr); -+ -+ /* Now add all rails which are already started */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ EP_RAIL_OP (commsRail, Rcvr.AddRail) (rcvr, commsRail); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ ep_mod_inc_usecount(); -+ -+ return (rcvr); -+} -+ -+void -+ep_free_rcvr (EP_RCVR *rcvr) -+{ -+ EP_COMMS_SUBSYS *subsys = rcvr->Subsys; -+ EP_SYS *sys = subsys->Subsys.Sys; -+ struct list_head list; -+ struct list_head *el,*nel; -+ unsigned long flags; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ EP_RAIL_OP (commsRail, Rcvr.DelRail) (rcvr, commsRail); -+ } -+ -+ ep_procfs_rcvr_del(rcvr); -+ -+ list_del (&rcvr->Link); -+ kmutex_unlock (&subsys->Lock); -+ -+ INIT_LIST_HEAD (&list); -+ -+ /* abort all rxds - should not be bound to a rail */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ for (;;) -+ { -+ if (! list_empty (&rcvr->ActiveDescList)) -+ { -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ -+ ASSERT (rxd->RxdRail == NULL); -+ ASSERT (rxd->RxdMain->Len == EP_RXD_PENDING); -+ -+ rxd->State = EP_RXD_COMPLETED; -+ rxd->RxdMain->Len = EP_SHUTDOWN; -+ -+ list_del (&rxd->Link); -+ list_add_tail (&rxd->Link, &list); -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ while (! list_empty (&list)) -+ { -+ EP_RXD *rxd = list_entry (list.next, EP_RXD, Link); -+ -+ list_del (&rxd->Link); -+ -+ if (rxd->Handler) -+ rxd->Handler (rxd); -+ } -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ continue; -+ } -+ -+ if (rcvr->FreeDescCount == rcvr->TotalDescCount) -+ break; -+ -+ rcvr->CleanupWaiting++; -+ kcondvar_wait (&rcvr->CleanupSleep, &rcvr->Lock, &flags); -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* must all be in free list */ -+ ASSERT( rcvr->FreeDescCount == rcvr->TotalDescCount); -+ -+ while (! list_empty(& rcvr->DescBlockList) ) -+ FreeRxdBlock (rcvr, list_entry (rcvr->DescBlockList.next, EP_RXD_BLOCK, Link)); -+ -+ /* had better be all gone now */ -+ ASSERT((rcvr->FreeDescCount == 0) && (rcvr->TotalDescCount == 0)); -+ -+ ep_xid_cache_destroy (sys, &rcvr->XidCache); -+ -+ spin_lock_destroy (&rcvr->Lock); -+ KMEM_FREE (rcvr, sizeof (EP_RCVR)); -+ -+ ep_mod_dec_usecount(); -+} -+ -+EP_RXD * -+StealRxdFromOtherRail (EP_RCVR *rcvr) -+{ -+ EP_RXD *rxd; -+ int i; -+ -+ /* looking at the the rcvr railmask to find a rail to try to steal rxd from */ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (rcvr->RailMask & (1 << i) ) -+ if ((rxd = EP_RCVR_OP (rcvr->Rails[i], StealRxd) (rcvr->Rails[i])) != NULL) -+ return rxd; -+ -+ return NULL; -+} -+ -+long -+CheckUnboundRxd (EP_RCVR *rcvr, EP_RXD *rxd, long nextRunTime) -+{ -+ EP_SYS *sys = rcvr->Subsys->Subsys.Sys; -+ EP_RCVR_RAIL *rcvrRail; -+ int rnum; -+ -+ if ((rnum = ep_rcvr_prefrail (rcvr, EP_NMD_RAILMASK(&rxd->Data))) < 0) -+ rnum = ep_rcvr_prefrail (rcvr, ep_rcvr_availrails (rcvr)); -+ -+ if ( rnum < 0 ) { -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ -+ return (nextRunTime); -+ } -+ -+ ASSERT ( rnum >= 0 ); -+ -+ rcvrRail = rcvr->Rails[rnum]; -+ -+ ASSERT ( rcvrRail != NULL); -+ -+ rxd->State = EP_RXD_RECEIVE_ACTIVE; -+ -+ if ((!(EP_NMD_RAILMASK (&rxd->Data) & EP_RAIL2RAILMASK(rnum)) && /* not mapped already and */ -+ ep_nmd_map_rails (sys, &rxd->Data, EP_RAIL2RAILMASK(rnum)) == 0) || /* failed mapping, or */ -+ !EP_RCVR_OP (rcvrRail, QueueRxd) (rxd, rcvrRail)) /* failed to queue */ -+ { -+ ASSERT (rxd->RxdRail == NULL); -+ -+ EPRINTF4 (DBG_RCVR,"CheckUnboundRxd: rcvr=%p rxd=%p -> rnum=%d rcvrRail=%p (failed)\n", rcvr, rxd, rnum, rcvrRail); -+ -+ rxd->State = EP_RXD_RECEIVE_UNBOUND; -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ -+ return (nextRunTime); -+} -+ -+int -+CheckRxdNmdsMapped (EP_RCVR *rcvr, EP_RXD *rxd) -+{ -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ EP_RXD_MAIN *rxdMain = rxd->RxdMain; -+ EP_ENVELOPE *env = &rxdMain->Envelope; -+ EP_SYS *sys = rcvr->Subsys->Subsys.Sys; -+ EP_RAIL *rail = rxdRail->RcvrRail->CommsRail->Rail; -+ int i; -+ -+ /* Try and map the local NMDs before checking to see if we can proceed */ -+ if (! (ep_nmd2railmask (rxd->Local, rxd->nFrags) & EP_RAIL2RAILMASK (rail->Number))) -+ { -+ EPRINTF3 (DBG_MAPNMD, "%s: rcvr=%p rxd=%p RPC Local NMDs not mapped\n", rail->Name, rcvr, rxd); -+ -+ for (i = 0; i < rxd->nFrags; i++) -+ if (! (EP_NMD_RAILMASK(&rxd->Local[i]) & EP_RAIL2RAILMASK(rail->Number))) -+ if (ep_nmd_map_rails (sys, &rxd->Local[i], EP_RAIL2RAILMASK(rail->Number))) -+ rxd->NextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ -+ /* Try and map remote NMDs if they are not valid for this rail */ -+ if (! (ep_nmd2railmask (rxd->Remote, rxd->nFrags) & EP_RAIL2RAILMASK (rail->Number))) -+ { -+ EP_MANAGER_MSG_BODY msgBody; -+ -+ EPRINTF3 (DBG_MAPNMD, "%s: rcvr=%p rxd=%p RPC Remote NMDs not mapped\n", rail->Name, rcvr, rxd); -+ -+ if (EP_XID_INVALID(rxd->MsgXid)) -+ rxd->MsgXid = ep_xid_cache_alloc (sys, &rcvr->XidCache); -+ -+ msgBody.MapNmd.nFrags = rxd->nFrags; -+ msgBody.MapNmd.Railmask = EP_RAIL2RAILMASK (rail->Number); -+ for (i = 0; i < rxd->nFrags; i++) -+ msgBody.MapNmd.Nmd[i] = rxd->Remote[i]; -+ -+ if (ep_send_message (rail, env->NodeId, EP_MANAGER_MSG_TYPE_MAP_NMD_REQUEST, rxd->MsgXid, &msgBody) == 0) -+ rxd->NextRunTime = lbolt + MESSAGE_RETRY_TIME; -+ else -+ rxd->NextRunTime = lbolt + MSGBUSY_RETRY_TIME; -+ -+ return 0; -+ } -+ -+ if ((ep_nmd2railmask (rxd->Local, rxd->nFrags) & ep_nmd2railmask (rxd->Remote, rxd->nFrags) & EP_RAIL2RAILMASK (rail->Number)) != 0) -+ { -+ rxd->NextRunTime = 0; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+long -+ep_check_rcvr (EP_RCVR *rcvr, long nextRunTime) -+{ -+ struct list_head *el, *nel; -+ unsigned long flags; -+ int i; -+ -+ /* Check to see if we're low on rxds */ -+ if (rcvr->FreeDescCount < ep_rxd_lowat) -+ AllocateRxdBlock (rcvr, 0, NULL); -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (rcvr->RailMask & (1 << i) ) -+ nextRunTime = EP_RCVR_OP (rcvr->Rails[i], Check) (rcvr->Rails[i], nextRunTime); -+ -+ /* See if we have any rxd's which need to be handled */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP_RXD_MAIN *rxdMain = rxd->RxdMain; -+ EP_ENVELOPE *env = &rxdMain->Envelope; -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ -+ if (rxdRail == NULL) -+ nextRunTime = CheckUnboundRxd (rcvr, rxd, nextRunTime); -+ else -+ { -+ EP_RCVR_RAIL *rcvrRail = rxdRail->RcvrRail; -+ EP_RAIL *rail = rcvrRail->CommsRail->Rail; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || /* envelope not received yet */ -+ rail->Nodes[env->NodeId].State != EP_NODE_CONNECTED) /* will be failing over */ -+ continue; -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_PUT_STALLED: -+ if (CheckRxdNmdsMapped (rcvr, rxd)) -+ { -+ rxd->State = EP_RXD_PUT_ACTIVE; -+ -+ EP_RCVR_OP (rcvrRail, RpcPut) (rxd, rxd->Local, rxd->Remote, rxd->nFrags); -+ } -+ break; -+ -+ case EP_RXD_GET_STALLED: -+ if (CheckRxdNmdsMapped (rcvr, rxd)) -+ { -+ rxd->State = EP_RXD_GET_ACTIVE; -+ -+ EP_RCVR_OP (rcvrRail, RpcGet) (rxd, rxd->Local, rxd->Remote, rxd->nFrags); -+ } -+ break; -+ -+ case EP_RXD_COMPLETE_STALLED: -+ if (CheckRxdNmdsMapped (rcvr, rxd)) -+ { -+ rxd->State = EP_RXD_COMPLETE_ACTIVE; -+ -+ EP_RCVR_OP (rcvrRail, RpcComplete)(rxd, rxd->Local, rxd->Remote, rxd->nFrags); -+ } -+ break; -+ } -+ -+ if (rxd->NextRunTime && (nextRunTime == 0 || AFTER (nextRunTime, rxd->NextRunTime))) -+ nextRunTime = rxd->NextRunTime; -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return (nextRunTime); -+} -+ -+void -+ep_display_rxd (DisplayInfo *di, EP_RXD *rxd) -+{ -+ EP_RXD_MAIN *rxdMain = rxd->RxdMain; -+ EP_ENVELOPE *env = &rxdMain->Envelope; -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ -+ (di->func)(di->arg, " RXD: %p State=%x RxdMain=%p(%x.%x.%x) Data=%x.%x.%x %s\n", rxd, -+ rxd->State, rxd->RxdMain, rxd->NmdMain.nmd_addr, rxd->NmdMain.nmd_len, -+ rxd->NmdMain.nmd_attr, rxd->Data.nmd_addr, rxd->Data.nmd_len, rxd->Data.nmd_attr, -+ rxd->RxdMain->Len == EP_RXD_PENDING ? "Pending" : "Active"); -+ (di->func)(di->arg, " NodeId=%d Range=%d.%d TxdRail=%x TxdMain=%x.%x.%x nFrags=%d XID=%08x.%08x.%016llx\n", -+ env->NodeId, EP_RANGE_LOW(env->Range), EP_RANGE_HIGH(env->Range), env->TxdRail, env->TxdMain.nmd_addr, -+ env->TxdMain.nmd_len, env->TxdMain.nmd_attr, env->nFrags, env->Xid.Generation, env->Xid.Handle, env->Xid.Unique);; -+ (di->func)(di->arg, " Frag[0] %08x.%08x.%08x\n", env->Frags[0].nmd_addr, env->Frags[0].nmd_len, env->Frags[0].nmd_attr); -+ (di->func)(di->arg, " Frag[1] %08x.%08x.%08x\n", env->Frags[1].nmd_addr, env->Frags[1].nmd_len, env->Frags[1].nmd_attr); -+ (di->func)(di->arg, " Frag[2] %08x.%08x.%08x\n", env->Frags[2].nmd_addr, env->Frags[2].nmd_len, env->Frags[2].nmd_attr); -+ (di->func)(di->arg, " Frag[3] %08x.%08x.%08x\n", env->Frags[3].nmd_addr, env->Frags[3].nmd_len, env->Frags[3].nmd_attr); -+ -+ if (rxdRail) EP_RCVR_OP (rxdRail->RcvrRail, DisplayRxd) (di, rxdRail); -+} -+ -+void -+ep_display_rcvr (DisplayInfo *di, EP_RCVR *rcvr, int full) -+{ -+ int freeCount = 0; -+ int activeCount = 0; -+ int pendingCount = 0; -+ int railCounts[EP_MAX_RAILS]; -+ struct list_head *el; -+ int i; -+ unsigned long flags; -+ -+ for (i = 0; i FreeDescLock, flags); -+ list_for_each (el, &rcvr->FreeDescList) -+ freeCount++; -+ spin_unlock_irqrestore (&rcvr->FreeDescLock, flags); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ list_for_each (el, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP_RXD_RAIL *rxdRail = rxd->RxdRail; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING) -+ pendingCount++; -+ else -+ activeCount++; -+ -+ if (rxdRail) -+ railCounts[rxdRail->RcvrRail->CommsRail->Rail->Number]++; -+ } -+ -+ (di->func)(di->arg, "RCVR: rcvr=%p number=%d\n", rcvr, rcvr->Service); -+ (di->func)(di->arg, " RXDS Free=%d (%d) Pending=%d Active=%d Rails=%d.%d.%d.%d\n", -+ freeCount, rcvr->FreeDescCount, pendingCount, activeCount, railCounts[0], railCounts[1], -+ railCounts[2], railCounts[3]); -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (rcvr->Rails[i] != NULL) -+ EP_RCVR_OP (rcvr->Rails[i], DisplayRcvr) (di, rcvr->Rails[i]); -+ -+ list_for_each (el, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ -+ if (rxd->RxdMain->Len != EP_RXD_PENDING || full) -+ ep_display_rxd (di, rxd); -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ep_rxd_received_now(EP_RXD *rxd) -+{ -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_RCVR *rcvr = rxd->Rcvr; -+ unsigned long flags; -+ -+ INC_STAT(rcvr->stats,rx); -+ ADD_STAT(rcvr->stats,rx_len, rxd->RxdMain->Len); -+ -+ if (rxd->RxdMain->Len < 0 || !EP_IS_MULTICAST(env->Attr)) -+ { -+ rxd->Handler (rxd); -+ } -+ else -+ { -+ EPRINTF5 (DBG_RCVR, "ep_rxd_received: forward rxd=%p Data=%08x.%08x.%08x len=%d\n", rxd, -+ rxd->Data.nmd_addr, rxd->Data.nmd_len, rxd->Data.nmd_attr, ep_rxd_len(rxd)); -+ -+ spin_lock_irqsave (&rcvr->Subsys->ForwardDescLock, flags); -+ list_add_tail (&rxd->Link, &rcvr->Subsys->ForwardDescList); -+ spin_unlock_irqrestore (&rcvr->Subsys->ForwardDescLock, flags); -+ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+} -+ -+#if defined(CONFIG_EP_NO_CHECK_SUM) -+void -+ep_rxd_received(EP_RXD *rxd) -+{ -+ ep_rxd_received_now(rxd); -+} -+ -+#else -+ -+void -+ep_rxd_received(EP_RXD *rxd) -+{ -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ -+ if (env->CheckSum) -+ ep_rxd_queue_csum(rxd); -+ else -+ ep_rxd_received_now(rxd); -+} -+ -+void -+ep_rxd_queue_csum(EP_RXD *rxd) -+{ -+ EP_RCVR *rcvr = rxd->Rcvr; -+ unsigned long flags; -+ -+ EPRINTF5 (DBG_RCVR, "ep_rxd_queue_csum: rxd=%p Data=%08x.%08x.%08x len=%d\n", rxd, -+ rxd->Data.nmd_addr, rxd->Data.nmd_len, rxd->Data.nmd_attr, ep_rxd_len(rxd)); -+ -+ spin_lock_irqsave (&rcvr->Subsys->CheckSumDescLock, flags); -+ list_add_tail (&rxd->CheckSumLink, &rcvr->Subsys->CheckSumDescList); -+ spin_unlock_irqrestore (&rcvr->Subsys->CheckSumDescLock, flags); -+ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+} -+#endif -+ -+void -+ep_rcvr_fillout_stats(EP_RCVR *rcvr, char *str) -+{ -+ sprintf(str+strlen(str),"Rx %lu %lu /sec\n", GET_STAT_TOTAL(rcvr->stats,rx), GET_STAT_PER_SEC(rcvr->stats,rx) ); -+ sprintf(str+strlen(str),"MBytes %lu %lu Mbytes/sec\n", GET_STAT_TOTAL(rcvr->stats,rx_len) / (1024*1024), GET_STAT_PER_SEC(rcvr->stats,rx_len) / (1024*1024)); -+} -+ -+void -+ep_rcvr_rail_fillout_stats(EP_RCVR_RAIL *rcvr_rail, char *str) -+{ -+ sprintf(str+strlen(str),"Rx %lu %lu /sec\n", GET_STAT_TOTAL(rcvr_rail->stats,rx), GET_STAT_PER_SEC(rcvr_rail->stats,rx) ); -+ sprintf(str+strlen(str),"MBytes %lu %lu Mbytes/sec\n", GET_STAT_TOTAL(rcvr_rail->stats,rx_len) / (1024*1024), GET_STAT_PER_SEC(rcvr_rail->stats,rx_len) / (1024*1024)); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsRx_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsRx_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsRx_elan3.c 2005-06-01 23:12:54.649431504 -0400 -@@ -0,0 +1,1776 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsRx_elan3.c,v 1.19.2.3 2004/11/15 11:05:49 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsRx_elan3.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "epcomms_elan3.h" -+#include "debug.h" -+ -+#define RCVR_TO_RAIL(rcvrRail) ((EP3_RAIL *) ((EP_RCVR_RAIL *) rcvrRail)->CommsRail->Rail) -+#define RCVR_TO_DEV(rcvrRail) (RCVR_TO_RAIL(rcvrRail)->Device) -+#define RCVR_TO_SUBSYS(rcvrRail) (((EP_RCVR_RAIL *) rcvrRail)->Rcvr->Subsys) -+ -+static void RxDataEvent (EP3_RAIL *rail, void *arg); -+static void RxDataRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status); -+static void RxDataVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma); -+ -+static EP3_COOKIE_OPS RxDataCookieOps = -+{ -+ RxDataEvent, -+ RxDataRetry, -+ NULL, /* DmaCancelled */ -+ RxDataVerify, -+}; -+ -+static void RxDoneEvent (EP3_RAIL *rail, void *arg); -+static void RxDoneRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status); -+static void RxDoneVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma); -+ -+static EP3_COOKIE_OPS RxDoneCookieOps = -+{ -+ RxDoneEvent, -+ RxDoneRetry, -+ NULL, /* DmaCancelled */ -+ RxDoneVerify, -+}; -+ -+static int -+AllocateRxdRailBlock (EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ EP3_RXD_RAIL_BLOCK *blk; -+ EP3_RXD_RAIL *rxdRail; -+ sdramaddr_t pRxdElan; -+ EP3_RXD_RAIL_MAIN *pRxdMain; -+ E3_Addr pRxdElanAddr; -+ E3_Addr pRxdMainAddr; -+ E3_BlockCopyEvent event; -+ int i, j; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (blk, EP3_RXD_RAIL_BLOCK *, sizeof (EP3_RXD_RAIL_BLOCK), 1); -+ if (blk == NULL) -+ return 0; -+ -+ if ((pRxdElan = ep_alloc_elan (&rail->Generic, EP3_RXD_RAIL_ELAN_SIZE * EP3_NUM_RXD_PER_BLOCK, 0, &pRxdElanAddr)) == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (blk, sizeof (EP3_RXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if ((pRxdMain = ep_alloc_main (&rail->Generic, EP3_RXD_RAIL_MAIN_SIZE * EP3_NUM_RXD_PER_BLOCK, 0, &pRxdMainAddr)) == (sdramaddr_t) 0) -+ { -+ ep_free_elan (&rail->Generic, pRxdElanAddr, EP3_RXD_RAIL_ELAN_SIZE * EP3_NUM_RXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP3_RXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if (ReserveDmaRetries (rail, EP3_NUM_RXD_PER_BLOCK, 0) != ESUCCESS) -+ { -+ ep_free_main (&rail->Generic, pRxdMainAddr, EP3_RXD_RAIL_MAIN_SIZE * EP3_NUM_RXD_PER_BLOCK); -+ ep_free_elan (&rail->Generic, pRxdElanAddr, EP3_RXD_RAIL_ELAN_SIZE * EP3_NUM_RXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP3_RXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ for (rxdRail = &blk->Rxd[0], i = 0; i < EP3_NUM_RXD_PER_BLOCK; i++, rxdRail++) -+ { -+ rxdRail->Generic.RcvrRail = (EP_RCVR_RAIL *) rcvrRail; -+ rxdRail->RxdElan = pRxdElan; -+ rxdRail->RxdElanAddr = pRxdElanAddr; -+ rxdRail->RxdMain = pRxdMain; -+ rxdRail->RxdMainAddr = pRxdMainAddr; -+ -+ elan3_sdram_writel (dev, pRxdElan + offsetof (EP3_RXD_RAIL_ELAN, RxdMain), 0); -+ elan3_sdram_writel (dev, pRxdElan + offsetof (EP3_RXD_RAIL_ELAN, Next), 0); -+ elan3_sdram_writeq (dev, pRxdElan + offsetof (EP3_RXD_RAIL_ELAN, MainAddr), (long) rxdRail); -+ -+ for (j = 0; j < EP_MAXFRAG; j++) -+ { -+ RegisterCookie (&rail->CookieTable, &rxdRail->ChainCookie[j], pRxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[j]), &RxDataCookieOps, (void *) rxdRail); -+ -+ event.ev_Type = EV_TYPE_DMA | (pRxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, Dmas[j+1])); -+ event.ev_Count = 0; -+ -+ elan3_sdram_copyl_to_sdram (dev, &event, pRxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[j]), sizeof (E3_BlockCopyEvent)); -+ } -+ -+ RegisterCookie (&rail->CookieTable, &rxdRail->DataCookie, pRxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, DataEvent), &RxDataCookieOps, (void *) rxdRail); -+ RegisterCookie (&rail->CookieTable, &rxdRail->DoneCookie, pRxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent), &RxDoneCookieOps, (void *) rxdRail); -+ -+ EP3_INIT_COPY_EVENT (event, rxdRail->DataCookie, pRxdMainAddr + offsetof (EP3_RXD_RAIL_MAIN, DataEvent), 1); -+ elan3_sdram_copyl_to_sdram (dev, &event, pRxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent), sizeof (E3_BlockCopyEvent)); -+ -+ EP3_INIT_COPY_EVENT (event, rxdRail->DoneCookie, pRxdMainAddr + offsetof (EP3_RXD_RAIL_MAIN, DoneEvent), 1); -+ elan3_sdram_copyl_to_sdram (dev, &event, pRxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent), sizeof (E3_BlockCopyEvent)); -+ -+ pRxdMain->DataEvent = EP3_EVENT_FREE; -+ pRxdMain->DoneEvent = EP3_EVENT_FREE; -+ -+ /* move onto next descriptor */ -+ pRxdElan += EP3_RXD_RAIL_ELAN_SIZE; -+ pRxdElanAddr += EP3_RXD_RAIL_ELAN_SIZE; -+ pRxdMain = (EP3_RXD_RAIL_MAIN *) ((unsigned long) pRxdMain + EP3_RXD_RAIL_MAIN_SIZE); -+ pRxdMainAddr += EP3_RXD_RAIL_MAIN_SIZE; -+ } -+ -+ spin_lock_irqsave (&rcvrRail->FreeDescLock, flags); -+ -+ list_add (&blk->Link, &rcvrRail->DescBlockList); -+ rcvrRail->TotalDescCount += EP3_NUM_RXD_PER_BLOCK; -+ rcvrRail->FreeDescCount += EP3_NUM_RXD_PER_BLOCK; -+ -+ for (i = 0; i < EP3_NUM_RXD_PER_BLOCK; i++) -+ list_add (&blk->Rxd[i].Generic.Link, &rcvrRail->FreeDescList); -+ -+ spin_unlock_irqrestore (&rcvrRail->FreeDescLock, flags); -+ -+ return 1; -+} -+ -+static void -+FreeRxdRailBlock (EP3_RCVR_RAIL *rcvrRail, EP3_RXD_RAIL_BLOCK *blk) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ EP3_RXD_RAIL *rxdRail; -+ unsigned long flags; -+ int i, j; -+ -+ spin_lock_irqsave (&rcvrRail->FreeDescLock, flags); -+ -+ list_del (&blk->Link); -+ -+ rcvrRail->TotalDescCount -= EP3_NUM_RXD_PER_BLOCK; -+ -+ for (rxdRail = &blk->Rxd[0], i = 0; i < EP3_NUM_RXD_PER_BLOCK; i++, rxdRail++) -+ { -+ -+ rcvrRail->FreeDescCount--; -+ -+ list_del (&rxdRail->Generic.Link); -+ -+ for (j = 0; j < EP_MAXFRAG; j++) -+ DeregisterCookie (&rail->CookieTable, &rxdRail->ChainCookie[j]); -+ -+ DeregisterCookie (&rail->CookieTable, &rxdRail->DataCookie); -+ DeregisterCookie (&rail->CookieTable, &rxdRail->DoneCookie); -+ } -+ -+ spin_unlock_irqrestore (&rcvrRail->FreeDescLock, flags); -+ -+ ReleaseDmaRetries (rail, EP3_NUM_RXD_PER_BLOCK); -+ -+ ep_free_main (&rail->Generic, blk->Rxd[0].RxdMainAddr, EP3_RXD_RAIL_MAIN_SIZE * EP3_NUM_RXD_PER_BLOCK); -+ ep_free_elan (&rail->Generic, blk->Rxd[0].RxdElanAddr, EP3_RXD_RAIL_ELAN_SIZE * EP3_NUM_RXD_PER_BLOCK); -+ -+ KMEM_FREE (blk, sizeof (EP3_RXD_RAIL_BLOCK)); -+} -+ -+static EP3_RXD_RAIL * -+GetRxdRail (EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_RXD_RAIL *rxdRail; -+ unsigned long flags; -+ int low_on_rxds; -+ -+ spin_lock_irqsave (&rcvrRail->FreeDescLock, flags); -+ -+ if (list_empty (&rcvrRail->FreeDescList)) -+ rxdRail = NULL; -+ else -+ { -+ rxdRail = list_entry (rcvrRail->FreeDescList.next, EP3_RXD_RAIL, Generic.Link); -+ -+ list_del (&rxdRail->Generic.Link); -+ -+ rcvrRail->FreeDescCount--; -+ } -+ -+ /* Wakeup the descriptor primer thread if there's not many left */ -+ low_on_rxds = (rcvrRail->FreeDescCount < ep_rxd_lowat); -+ -+ spin_unlock_irqrestore (&rcvrRail->FreeDescLock, flags); -+ -+ if (low_on_rxds) -+ ep_kthread_schedule (&RCVR_TO_SUBSYS(rcvrRail)->Thread, lbolt); -+ -+ return (rxdRail); -+} -+ -+static void -+FreeRxdRail (EP3_RCVR_RAIL *rcvrRail, EP3_RXD_RAIL *rxdRail) -+{ -+ unsigned long flags; -+ -+#if defined(DEBUG_ASSERT) -+ { -+ EP_RAIL *rail = (EP_RAIL *) RCVR_TO_RAIL(rcvrRail); -+ ELAN3_DEV *dev = RCVR_TO_DEV (rcvrRail); -+ -+ EP_ASSERT (rail, rxdRail->Generic.RcvrRail == &rcvrRail->Generic); -+ -+ EP_ASSERT (rail, rxdRail->RxdMain->DataEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (rail, rxdRail->RxdMain->DoneEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (rail, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); -+ EP_ASSERT (rail, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); -+ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_FREE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_FREE; -+ } -+#endif -+ -+ spin_lock_irqsave (&rcvrRail->FreeDescLock, flags); -+ -+ list_add (&rxdRail->Generic.Link, &rcvrRail->FreeDescList); -+ -+ rcvrRail->FreeDescCount++; -+ -+ if (rcvrRail->FreeDescWaiting) -+ { -+ rcvrRail->FreeDescWaiting--; -+ kcondvar_wakeupall (&rcvrRail->FreeDescSleep, &rcvrRail->FreeDescLock); -+ } -+ -+ spin_unlock_irqrestore (&rcvrRail->FreeDescLock, flags); -+} -+ -+static void -+BindRxdToRail (EP_RXD *rxd, EP3_RXD_RAIL *rxdRail) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL (rxdRail->Generic.RcvrRail); -+ -+ ASSERT (SPINLOCK_HELD (&rxd->Rcvr->Lock)); -+ -+ EPRINTF3 (DBG_RCVR, "%s: BindRxdToRail: rxd=%p rxdRail=%p\n", rail->Generic.Name, rxd, rxdRail); -+ -+ elan3_sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, RxdMain), rxd->NmdMain.nmd_addr); /* PCI write */ -+ -+ rxd->RxdRail = &rxdRail->Generic; -+ rxdRail->Generic.Rxd = rxd; -+} -+ -+static void -+UnbindRxdFromRail (EP_RXD *rxd, EP3_RXD_RAIL *rxdRail) -+{ -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ -+ ASSERT (SPINLOCK_HELD (&rxd->Rcvr->Lock)); -+ ASSERT (rxd->RxdRail == &rxdRail->Generic && rxdRail->Generic.Rxd == rxd); -+ -+ EPRINTF3 (DBG_RCVR, "%s: UnbindRxdFromRail: rxd=%p rxdRail=%p\n", RCVR_TO_RAIL(rxdRail->Generic.RcvrRail)->Generic.Name, rxd, rxdRail); -+ -+ rxd->RxdRail = NULL; -+ rxdRail->Generic.Rxd = NULL; -+ -+ if (rcvrRail->CleanupWaiting) -+ kcondvar_wakeupall (&rcvrRail->CleanupSleep, &rxd->Rcvr->Lock); -+ rcvrRail->CleanupWaiting = 0; -+} -+ -+static void -+LockRcvrThread (EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP_COMMS_RAIL *commsRail = rcvrRail->Generic.CommsRail; -+ EP3_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ sdramaddr_t sle = rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadLock); -+ EP3_SPINLOCK_MAIN *sl = &rcvrRail->RcvrMain->ThreadLock; -+ E3_uint32 RestartBits = 0; -+ int delay = 1; -+ E3_uint32 seq; -+ E3_uint32 reg; -+ -+ ASSERT (SPINLOCK_HELD (&rcvrRail->Generic.Rcvr->Lock)); -+ -+ mb(); -+ elan3_sdram_writel (dev, sle + offsetof (EP3_SPINLOCK_ELAN, sl_lock), 1); -+ mb(); -+ seq = elan3_sdram_readl (dev, sle + offsetof (EP3_SPINLOCK_ELAN, sl_seq)); -+ while (seq != sl->sl_seq) -+ { -+ while (sl->sl_seq == (seq - 1)) -+ { -+ mb(); -+ -+ if ((read_reg32 (dev, Exts.InterruptReg) & (INT_TProc | INT_TProcHalted)) != 0 && spin_trylock (&dev->IntrLock)) -+ { -+ reg=read_reg32 (dev, Exts.InterruptReg); -+ ELAN_REG_REC(reg); -+ -+ if ((reg & (INT_TProc | INT_TProcHalted)) != 0&& -+ elan3_sdram_readl (dev, sle + offsetof (EP3_SPINLOCK_ELAN, sl_seq)) != sl->sl_seq) -+ { -+ EPRINTF1 (DBG_RCVR, "%s: LockRcvrThread - thread trapped\n", rail->Generic.Name); -+ -+ /* The thread processor has *really* trapped, and the spinlock is still held. -+ * thus is must have trapped due to a network error - we need to complete the -+ * actions required for this envelope, since we may be spin-locking the receiver -+ * to search the dma retry lists for a particular dma. So must ensure that -+ * if the thread had trapped then the dma has been queued onto the retry list -+ * *before* we inspect them. -+ */ -+ IncrStat (commsRail, LockRcvrTrapped); -+ -+ /* We're going to generate a spurious interrupt here - since we will -+ * handle the thread processor trap directly */ -+ ELAN_REG_REC(reg); -+ if (HandleTProcTrap (dev, &RestartBits)) -+ { -+ /* NOTE - this is not an assert, since the "store" to unlock the lock could -+ * be held up on the PCI interface, whilst the thread processor has -+ * gone on and switched to a new thread, which has then trapped, and -+ * our read of the InterruptReg can overtake the unlock write. -+ * -+ * ASSERT (dev->ThreadTrap->Registers[REG_GLOBALS + (1^WordEndianFlip)] == -+ * elan3_sdram_readl (dev, rcvr->RcvrElan + offsetof (EP_RCVR_ELAN, PendingRxDescsElan))); -+ */ -+ -+ PULSE_SCHED_STATUS (dev, RestartBits); -+ -+ DeliverTProcTrap (dev, dev->ThreadTrap, INT_TProc); -+ } -+ } -+ spin_unlock (&dev->IntrLock); -+ } -+ -+ DELAY (delay); delay++; -+ } -+ seq = elan3_sdram_readl (dev, sle + offsetof (EP3_SPINLOCK_ELAN, sl_seq)); -+ } -+} -+ -+static void -+UnlockRcvrThread (EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ sdramaddr_t sle = rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadLock); -+ -+ mb(); -+ elan3_sdram_writel (rail->Device, sle + offsetof (EP3_SPINLOCK_ELAN, sl_lock), 0); -+ mmiob(); -+} -+ -+void -+CompleteEnvelope (EP3_RAIL *rail, E3_Addr rxdElanAddr, E3_uint32 PAckVal) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ sdramaddr_t rxdElan = ep_elan2sdram (&rail->Generic, rxdElanAddr); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) (unsigned long) elan3_sdram_readq (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, MainAddr)); -+ EP_RXD_MAIN *rxdMain = rxdRail->Generic.Rxd->RxdMain; -+ EP_ENVELOPE *env = &rxdMain->Envelope; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ EP_COMMS_RAIL *commsRail = rcvrRail->Generic.CommsRail; -+ EP_RCVR *rcvr = rcvrRail->Generic.Rcvr; -+ sdramaddr_t queue = ((EP3_COMMS_RAIL *) commsRail)->QueueDescs + rcvr->Service * sizeof (EP3_InputQueue); -+ sdramaddr_t sle = rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadLock); -+ EP3_SPINLOCK_MAIN *sl = &rcvrRail->RcvrMain->ThreadLock; -+ int nodeId; -+ EP_NODE_RAIL *nodeRail; -+ E3_DMA_BE dma; -+ E3_Addr nfptr; -+ E3_Addr next; -+ -+ ASSERT (commsRail->Rail == &rail->Generic); -+ ASSERT (rxdElanAddr == elan3_sdram_readl (dev, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingDescs))); -+ -+ IncrStat (commsRail, CompleteEnvelope); -+ -+ /* We don't need to aquire the NodeLock here (however we might be holding it), -+ * since this can only get called while the node is connected, or disconnecting. -+ * If the node is disconnecting, then we can get called from FlushDisconnecting() -+ * while holding the NodeLock - after we cannot get called again until the node -+ * has reconnected from scratch. -+ */ -+ /* Copy the envelope information */ -+ nfptr = elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_fptr)); -+ -+ if (nfptr == elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_top))) -+ nfptr = elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_base)); -+ else -+ nfptr += elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_size)); -+ -+ /* Copy the envelope and payload (unconditionally) */ -+ elan3_sdram_copyl_from_sdram (dev, rcvrRail->InputQueueBase + (nfptr - rcvrRail->InputQueueAddr), env, EP_ENVELOPE_SIZE + EP_PAYLOAD_SIZE); -+ -+ ASSERT (env->Version == EP_ENVELOPE_VERSION); -+ -+ /* Copy the received message length */ -+ rxdMain->Len = elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Data.nmd_len)); -+ -+ /* Remove the RXD from the pending desc list */ -+ if ((next = elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Next))) == 0) -+ rcvrRail->RcvrMain->PendingDescsTailp = 0; -+ elan3_sdram_writel (dev, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingDescs), next); -+ -+ /* Copy the DMA descriptor to queue on the approriate retry list */ -+ elan3_sdram_copyq_from_sdram (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Dmas[0]), &dma, sizeof (E3_DMA)); /* PCI read block */ -+ -+ EP_ASSERT (&rail->Generic, dma.s.dma_direction == DMA_READ);; -+ -+#if defined(DEBUG_ASSERT) && defined(DEBUG_SDRAM_ASSERT) -+ /* NOTE: not an assertion, since the thread packet could have successfully -+ * transferred the "put" dma to the far side - which could then have -+ * completed - but the far side will see a network error which will -+ * cause the virtual circuit to be dropped by the far side and this -+ * DMA will be removed */ -+ if (rxdRail->RxdMain->DataEvent != EP3_EVENT_ACTIVE || -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) != 1) -+ { -+ printk ("CompleteEnvelope: suspicious dma : Node=%d DataBlock=%d Event=%d\n", -+ env->NodeId, rxdRail->RxdMain->DataEvent, -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count))); -+ } -+#endif -+ -+ EPRINTF6 (DBG_RCVR, "%s: CompleteEnvelope: rxd=%p NodeId=%d Xid=%llx Cookies=%08x,%08x\n", commsRail->Rail->Name, -+ rxdRail, env->NodeId, (long long) env->Xid.Unique, dma.s.dma_srcCookieVProc, dma.s.dma_destCookieVProc); -+ -+ /* we MUST convert this into a DMA_READ_REQUEUE dma as if we don't the DMA descriptor will -+ * be read from the EP_RETRY_DMA rather than the original DMA - this can then get reused -+ * and an incorrect DMA descriptor sent */ -+ dma.s.dma_source = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, Dmas[0]); -+ dma.s.dma_direction = (dma.s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ -+ nodeId = EP_VP_TO_NODE(dma.s.dma_srcVProc); -+ nodeRail = &rail->Generic.Nodes[nodeId]; -+ -+ ASSERT (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ if (PAckVal != E3_PAckOk) -+ { -+ if (nodeRail->State == EP_NODE_CONNECTED) -+ QueueDmaForRetry (rail, &dma, EP_RETRY_LOW_PRI_RETRY); -+ else -+ QueueDmaOnStalledList (rail, &dma); -+ } -+ -+ /* Finaly forcefully drop the spinlock for the thread */ -+ sl->sl_seq = elan3_sdram_readl (dev, sle + offsetof (EP3_SPINLOCK_ELAN, sl_seq)); -+ -+ wmb(); -+} -+ -+void -+StallThreadForNoDescs (EP3_RAIL *rail, E3_Addr rcvrElanAddr, E3_Addr sp) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ sdramaddr_t rcvrElan = ep_elan2sdram (&rail->Generic, rcvrElanAddr); -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) (unsigned long) elan3_sdram_readq (dev, rcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, MainAddr)); -+ EP_RCVR *rcvr = rcvrRail->Generic.Rcvr; -+ EP_COMMS_RAIL *commsRail = rcvrRail->Generic.CommsRail; -+ -+ EPRINTF3 (DBG_RCVR, "%s: StallThreadForNoDescs - rcvrRail=%p sp=%x\n", commsRail->Rail->Name, rcvrRail, sp); -+ -+ IncrStat (commsRail, StallThread); -+ -+ /* NOTE: spin lock not required as thread is trapped */ -+ -+ if (rcvrRail->RcvrMain->PendingDescsTailp != 0) -+ { -+ EPRINTF1 (DBG_RCVR, "%s: StallThreadForNoDescs - pending descriptors, wakeup thread\n", commsRail->Rail->Name); -+ -+ /* -+ * A receive buffer was queued after the thread had decided to go to -+ * sleep, but before the event interrupt occured. Just restart the -+ * thread to consume the envelope. -+ */ -+ IssueRunThread (rail, sp); -+ } -+ else -+ { -+ EPRINTF1 (DBG_RCVR, "%s: StallThreadForNoDescs - set ThreadWaiting\n", commsRail->Rail->Name); -+ -+ IncrStat (commsRail, ThrdWaiting); -+ -+ /* Mark the rcvr as waiting for a rxd, and schedule a call of ep_check_rcvr -+ * to attempt to "steal" a descriptor from a different rail */ -+ rcvrRail->ThreadWaiting = sp; -+ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ } -+} -+ -+void -+StallThreadForHalted (EP3_RAIL *rail, E3_Addr rcvrElanAddr, E3_Addr sp) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ sdramaddr_t rcvrElan = ep_elan2sdram (&rail->Generic, rcvrElanAddr); -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) (unsigned long) elan3_sdram_readq (dev, rcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, MainAddr)); -+ EP_RCVR *rcvr = rcvrRail->Generic.Rcvr; -+ unsigned long flags = 0; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ rcvrRail->ThreadHalted = sp; -+ -+ EPRINTF2 (DBG_EPTRAP, "%s: StallThreadForHalted: sp=%08x\n", rail->Generic.Name, sp); -+ -+ if (rcvrRail->CleanupWaiting) -+ kcondvar_wakeupone (&rcvrRail->CleanupSleep, &rcvr->Lock); -+ rcvrRail->CleanupWaiting = 0; -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+/* -+ * RxDataEvent: arg == EP3_RXD_RAIL -+ * Called on completion of receiving data. -+ */ -+static void -+RxDataEvent (EP3_RAIL *rail, void *arg) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) arg; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_RCVR *rcvr = rxd->Rcvr; -+ ELAN3_DEV *dev = rail->Device; -+ unsigned long flags; -+ int delay = 1; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ for (;;) -+ { -+ if (EP3_EVENT_FIRED (rxdRail->DataCookie, rxdRail->RxdMain->DataEvent)) -+ break; -+ -+ if (EP3_EVENT_FIRING (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent), rxdRail->DataCookie, rxdRail->RxdMain->DataEvent)) -+ { -+ if (delay > EP3_EVENT_FIRING_TLIMIT) -+ panic ("RxDataEvent: events set but block copy not completed\n"); -+ DELAY(delay); -+ delay <<= 1; -+ } -+ else -+ { -+ printk ("%s: RxDataEvent: rxd %p not complete [%x,%x,%x]\n", rail->Generic.Name, rxd, rxdRail->RxdMain->DataEvent, -+ elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)), -+ elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Type))); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ return; -+ } -+ mb(); -+ } -+ -+ /* -+ * Note, since the thread will have sent the "get" dma before copying the -+ * envelope, we must check that it has completed doing this, if not then -+ * it might be that the thread trapped due to a network error, so we must -+ * spinlock against the thread -+ */ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING) -+ { -+ LockRcvrThread (rcvrRail); -+ UnlockRcvrThread (rcvrRail); -+ -+ ASSERT (env->Version == EP_ENVELOPE_VERSION && rxd->RxdMain->Len != EP_RXD_PENDING); -+ } -+ -+ EPRINTF7 (DBG_RCVR, "%s: RxDataEvent: rxd=%p rxdRail=%p completed from elan node %d [XID=%llx] Length %d State %x\n", -+ rail->Generic.Name, rxd, rxdRail, env->NodeId, (long long) env->Xid.Unique, rxd->RxdMain->Len, rxd->State); -+ -+ EP_ASSERT (&rail->Generic, rxd->State == EP_RXD_RECEIVE_ACTIVE || rxd->State == EP_RXD_PUT_ACTIVE || rxd->State == EP_RXD_GET_ACTIVE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, rxdRail->RxdMain->DoneEvent == EP3_EVENT_PRIVATE); -+ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ rxd->Data.nmd_attr = EP_RAIL2RAILMASK (rail->Generic.Number); -+ -+ if (rxd->RxdMain->Len >= 0 && EP_IS_RPC(env->Attr)) -+ rxd->State = EP_RXD_RPC_IN_PROGRESS; -+ else -+ { -+ rxd->State = EP_RXD_COMPLETED; -+ -+ /* remove from active list */ -+ list_del (&rxd->Link); -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ FreeRxdRail (rcvrRail, rxdRail); -+ } -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ ep_rxd_received (rxd); -+ -+} -+ -+/* -+ * RxDataRetry: arg == EP3_RXD_RAIL -+ * Called on retry of "get" dma of large transmit data -+ * and rpc_get/rpc_put and "put" of datavec of rpc completion. -+ */ -+static void -+RxDataRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) arg; -+ EP_COMMS_RAIL *commsRail = rxdRail->Generic.RcvrRail->CommsRail; -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ -+#if defined(DEBUG_ASSERT) -+ RxDataVerify (rail, arg, dma); -+#endif -+ -+ IncrStat (commsRail, RxDataRetry); -+ -+ EPRINTF4 (DBG_RCVR, "%s: RxDataRetry: rcvr %p rxd %p [XID=%llx]\n", rail->Generic.Name, rxd->Rcvr, rxd, (long long) rxd->RxdMain->Envelope.Xid.Unique); -+ -+ QueueDmaForRetry (rail, dma, EP_RETRY_LOW_PRI_RETRY + ep_backoff (&rxdRail->Backoff, EP_BACKOFF_DATA)); -+} -+ -+static void -+RxDataVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma) -+{ -+#if defined(DEBUG_ASSERT) -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) arg; -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ -+ if (dma->s.dma_direction == DMA_WRITE) -+ { -+ EP_ASSERT (&rail->Generic, -+ (rxd->State == EP_RXD_RECEIVE_ACTIVE && rxdRail->RxdMain->DataEvent == EP3_EVENT_ACTIVE && rxdRail->RxdMain->DoneEvent == EP3_EVENT_PRIVATE) || -+ (rxd->State == EP_RXD_PUT_ACTIVE && rxdRail->RxdMain->DataEvent == EP3_EVENT_ACTIVE && rxdRail->RxdMain->DoneEvent == EP3_EVENT_PRIVATE) || -+ (rxd->State == EP_RXD_COMPLETE_ACTIVE && rxdRail->RxdMain->DataEvent == EP3_EVENT_PRIVATE && rxdRail->RxdMain->DoneEvent == EP3_EVENT_ACTIVE)); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (rxd->State == EP_RXD_COMPLETE_ACTIVE ? -+ elan3_sdram_readl (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 1: /* PCI read */ -+ elan3_sdram_readl (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 1)); /* PCI read */ -+ } -+ else -+ { -+ EP_ASSERT (&rail->Generic, dma->s.dma_direction == DMA_READ_REQUEUE); -+ -+#if defined(DEBUG_SDRAM_ASSERT) -+ /* NOTE: not an assertion, since the "get" DMA can still be running if -+ * it's packet got a network error - and then the "put" from the -+ * far side has completed - however the virtual circuit should -+ * then be dropped by the far side and this DMA will be removed */ -+ if (EP_VP_TO_NODE(dma->s.dma_srcVProc) != ep_rxd_node(rxd) || -+ (rxd->State != EP_RXD_RECEIVE_ACTIVE && rxd->State != EP_RXD_GET_ACTIVE) || -+ rxdRail->RxdMain->DataEvent != EP3_EVENT_ACTIVE || -+ elan3_sdram_readl (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) != 1) -+ { -+ EPRINTF6 (DBG_RCVR, "%s: RxDataRetry: suspicious dma : VProc=%d NodeId=%d State=%d DataBlock=%x Event=%d\n", -+ rail->Generic.Name, EP_VP_TO_NODE(dma->s.dma_srcVProc), ep_rxd_node(rxd), rxd->State, rxdRail->RxdMain->DataEvent, -+ elan3_sdram_readl (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count))); -+ } -+#endif /* defined(DEBUG_SDRAM_ASSERT) */ -+ } -+#endif /* DEBUG_ASSERT */ -+} -+ -+/* -+ * RxDoneEvent: arg == EP_RXD -+ * Called on completion of large receive. -+ */ -+static void -+RxDoneEvent (EP3_RAIL *rail, void *arg) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) arg; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ EP_COMMS_RAIL *commsRail = rcvrRail->Generic.CommsRail; -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ EP_RCVR *rcvr = rxd->Rcvr; -+ ELAN3_DEV *dev = rail->Device; -+ int delay = 1; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ for (;;) -+ { -+ if (EP3_EVENT_FIRED (rxdRail->DoneCookie, rxdRail->RxdMain->DoneEvent)) -+ break; -+ -+ if (EP3_EVENT_FIRING (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent), rxdRail->DoneCookie, rxdRail->RxdMain->DoneEvent)) -+ { -+ if (delay > EP3_EVENT_FIRING_TLIMIT) -+ panic ("RxDoneEvent: events set but block copy not completed\n"); -+ DELAY(delay); -+ delay <<= 1; -+ } -+ else -+ { -+ printk ("RxDoneEvent: rxd %p not complete [%x,%x.%x]\n", rxd, rxdRail->RxdMain->DoneEvent, -+ elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)), -+ elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Type))); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ return; -+ } -+ mb(); -+ } -+ -+ EPRINTF4 (DBG_RCVR, "%s: RxDoneEvent: rxd %p completed from elan node %d [XID=%llx]\n", -+ commsRail->Rail->Name, rxd, rxd->RxdMain->Envelope.NodeId, (long long) rxd->RxdMain->Envelope.Xid.Unique); -+ -+ IncrStat (commsRail, RxDoneEvent); -+ -+ EP_ASSERT (&rail->Generic, rxdRail->RxdMain->DataEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (&rail->Generic, EP3_EVENT_FIRED (rxdRail->DoneCookie, rxdRail->RxdMain->DoneEvent)); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); /* PCI read */ -+ -+ /* mark rxd as private */ -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* remove from active list */ -+ list_del (&rxd->Link); -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ FreeRxdRail (rcvrRail, rxdRail); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ rxd->Handler (rxd); -+} -+ -+/* -+ * RxDoneRetry: arg == EP_RXD -+ * Called on retry of "put" of RPC completion status block -+ */ -+static void -+RxDoneRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) arg; -+ EP_COMMS_RAIL *commsRail = rxdRail->Generic.RcvrRail->CommsRail; -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ -+#if defined(DEBUG_ASSERT) -+ RxDoneVerify (rail, arg, dma); -+#endif -+ -+ IncrStat (commsRail, RxDoneRetry); -+ -+ EPRINTF4 (DBG_RCVR, "%s: RxDoneRetry: rcvr %p rxd %p [XID=%llx]\n", commsRail->Rail->Name, rxd->Rcvr, rxd, (long long) rxd->RxdMain->Envelope.Xid.Unique); -+ -+ QueueDmaForRetry (rail, dma, EP_RETRY_LOW_PRI_RETRY + ep_backoff (&rxdRail->Backoff, EP_BACKOFF_DONE)); -+} -+ -+static void -+RxDoneVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma) -+{ -+#if defined(DEBUG_ASSERT) -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) arg; -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ -+ EP_ASSERT (&rail->Generic, dma->s.dma_direction == DMA_WRITE && EP_VP_TO_NODE(dma->s.dma_destVProc) == ep_rxd_node(rxd)); -+ EP_ASSERT (&rail->Generic, rxd->State == EP_RXD_COMPLETE_ACTIVE && rxdRail->RxdMain->DoneEvent == EP3_EVENT_ACTIVE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 1)); /* PCI read */ -+#endif /* defined(DEBUG_ASSERT) */ -+} -+ -+int -+ep3rcvr_queue_rxd (EP_RXD *rxd, EP_RCVR_RAIL *r) -+{ -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) r; -+ EP3_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ EP3_RXD_RAIL *rxdRail; -+ -+ ASSERT ( SPINLOCK_HELD(&rxd->Rcvr->Lock)); -+ -+ if ((rxdRail = GetRxdRail (rcvrRail)) == NULL) -+ return 0; -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->Generic); -+ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, Data.nmd_addr), rxd->Data.nmd_addr); /* PCI write */ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, Data.nmd_len), rxd->Data.nmd_len); /* PCI write */ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, Data.nmd_attr), rxd->Data.nmd_attr); /* PCI write */ -+ -+ /* Bind the rxdRail and rxd together */ -+ BindRxdToRail (rxd, rxdRail); -+ -+ /* Mark as active */ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 1); -+ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_ACTIVE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* Interlock with StallThreadForNoDescs */ -+ spin_lock (&dev->IntrLock); -+ -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_queue_rxd: rcvr %p rxd %p rxdRail %p\n", rail->Generic.Name, rxd->Rcvr, rxd, rxdRail); -+ -+ EP3_SPINENTER (dev, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingLock), &rcvrRail->RcvrMain->PendingLock); -+ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, Next), 0); /* PCI write */ -+ if (rcvrRail->RcvrMain->PendingDescsTailp == 0) -+ elan3_sdram_writel (dev, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingDescs), rxdRail->RxdElanAddr); /* PCI write */ -+ else -+ elan3_sdram_writel (dev, rcvrRail->RcvrMain->PendingDescsTailp, rxdRail->RxdElanAddr); /* PCI write */ -+ rcvrRail->RcvrMain->PendingDescsTailp = rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, Next); -+ -+ EP3_SPINEXIT (dev, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingLock), &rcvrRail->RcvrMain->PendingLock); -+ -+ /* If the thread has paused because it was woken up with no receive buffer */ -+ /* ready, then wake it up to process the one we've just added */ -+ if (rcvrRail->ThreadWaiting) -+ { -+ EPRINTF1 (DBG_RCVR, "%s: DoReceive: ThreadWaiting - restart thread\n", rail->Generic.Name); -+ -+ IssueRunThread (rail, rcvrRail->ThreadWaiting); -+ -+ rcvrRail->ThreadWaiting = (E3_Addr) 0; -+ } -+ -+ spin_unlock (&dev->IntrLock); -+ -+ return 1; -+} -+ -+void -+ep3rcvr_rpc_put (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ -+ EP3_RXD_RAIL_MAIN *rxdMain = rxdRail->RxdMain; -+ sdramaddr_t rxdElan = rxdRail->RxdElan; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ E3_DMA_BE dmabe; -+ int i, len; -+ -+ EP_ASSERT (&rail->Generic, rxd->State == EP_RXD_PUT_ACTIVE); -+ EP_ASSERT (&rail->Generic, rxdMain->DataEvent == EP3_EVENT_PRIVATE && rxdMain->DoneEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); /* PCI read */ -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->Generic); -+ -+ /* Generate the DMA chain to put the data in two loops to burst -+ * the data across the PCI bus */ -+ for (len = 0, i = (nFrags-1), local += (nFrags-1), remote += (nFrags-1); i >= 0; len += local->nmd_len, i--, local--, remote--) -+ { -+ dmabe.s.dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_WRITE, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dmabe.s.dma_size = local->nmd_len; -+ dmabe.s.dma_source = local->nmd_addr; -+ dmabe.s.dma_dest = remote->nmd_addr; -+ dmabe.s.dma_destEvent = (E3_Addr) 0; -+ dmabe.s.dma_destCookieVProc = EP_VP_DATA (env->NodeId); -+ if (i == (nFrags-1)) -+ dmabe.s.dma_srcEvent = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, DataEvent); -+ else -+ dmabe.s.dma_srcEvent = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[i]); -+ dmabe.s.dma_srcCookieVProc = LocalCookie (rail, env->NodeId); -+ -+ EPRINTF9 (DBG_RCVR, "%s: ep3rcvr_rpc_put: rxd %p [XID=%llx] idx=%d Source=%08x Dest=%08x Len=%x Cookies=%x.%x\n", rail->Generic.Name, rxd, -+ (long long) env->Xid.Unique, i, local->nmd_addr, remote->nmd_addr, local->nmd_len, dmabe.s.dma_destCookieVProc, dmabe.s.dma_srcCookieVProc); -+ -+ if (i != 0) -+ elan3_sdram_copyq_to_sdram (dev, &dmabe, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Dmas[i]), sizeof (E3_DMA)); /* PCI write block */ -+ } -+ -+ for (i = 0; i < nFrags; i++) -+ elan3_sdram_writel (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[i].ev_Count), 1); /* PCI write */ -+ -+ /* Initialise the data event */ -+ elan3_sdram_writel (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 1); /* PCI write */ -+ rxdMain->DataEvent = EP3_EVENT_ACTIVE; -+ -+ ASSERT (rail->Generic.Nodes[env->NodeId].State >= EP_NODE_CONNECTED && rail->Generic.Nodes[env->NodeId].State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ if (IssueDma (rail, &dmabe, EP_RETRY_LOW_PRI, FALSE) != ISSUE_COMMAND_OK) -+ { -+ /* Failed to issue the dma command, so copy the dma descriptor and queue it for retry */ -+ EPRINTF2 (DBG_RCVR, "%s: ep3rcvr_rpc_put: queue rxd %p on retry thread\n", rail->Generic.Name, rxd); -+ -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_LOW_PRI); -+ } -+ -+ BucketStat (rxd->Rcvr->Subsys, RPCPut, len); -+} -+ -+void -+ep3rcvr_rpc_get (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ -+ EP3_RXD_RAIL_MAIN *rxdMain = rxdRail->RxdMain; -+ sdramaddr_t rxdElan = rxdRail->RxdElan; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ E3_DMA_BE dmabe; -+ int i, len; -+ -+ EP_ASSERT (&rail->Generic, rxd->State == EP_RXD_GET_ACTIVE); -+ EP_ASSERT (&rail->Generic, rxdMain->DataEvent == EP3_EVENT_PRIVATE && rxdMain->DoneEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); /* PCI read */ -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->Generic); -+ -+ /* Generate the DMA chain to get the data in two loops to burst -+ * the data across the PCI bus */ -+ for (len = 0, i = (nFrags-1), remote += (nFrags-1), local += (nFrags-1); i >= 0; len += remote->nmd_len, i--, remote--, local--) -+ { -+ dmabe.s.dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_READ, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dmabe.s.dma_size = remote->nmd_len; -+ dmabe.s.dma_source = remote->nmd_addr; -+ dmabe.s.dma_dest = local->nmd_addr; -+ if (i == (nFrags-1)) -+ dmabe.s.dma_destEvent = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, DataEvent); -+ else -+ dmabe.s.dma_destEvent = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[i]); -+ dmabe.s.dma_destCookieVProc = LocalCookie (rail, env->NodeId); -+ dmabe.s.dma_srcEvent = (E3_Addr) 0; -+ dmabe.s.dma_srcCookieVProc = RemoteCookie (rail, env->NodeId); -+ -+ EPRINTF9 (DBG_RCVR, "%s: ep3rcvr_rpc_get rxd %p [XID=%llx] idx=%d Source=%08x Dest=%08x Len=%x Cookies=%x.%x\n", rail->Generic.Name, rxd, -+ (long long) env->Xid.Unique, i, remote->nmd_addr, local->nmd_addr, remote->nmd_len, dmabe.s.dma_destCookieVProc, -+ dmabe.s.dma_srcCookieVProc); -+ -+ /* -+ * Always copy down the dma descriptor, since we issue it as a READ_REQUEUE -+ * dma, and the elan will fetch the descriptor to send out of the link from -+ * the rxdElan->Dmas[i] location, before issueing the DMA chain we modify -+ * the dma_source. -+ */ -+ elan3_sdram_copyq_to_sdram (dev, &dmabe, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Dmas[i]), sizeof (E3_DMA)); /* PCI write block */ -+ } -+ -+ for (i = 0; i < nFrags; i++) -+ elan3_sdram_writel (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[i].ev_Count), 1); /* PCI write */ -+ -+ /* Initialise the data event */ -+ elan3_sdram_writel (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 1); /* PCI write */ -+ rxdMain->DataEvent = EP3_EVENT_ACTIVE; -+ -+ ASSERT (rail->Generic.Nodes[env->NodeId].State >= EP_NODE_CONNECTED && rail->Generic.Nodes[env->NodeId].State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ /* we MUST convert this into a DMA_READ_REQUEUE dma as if we don't the DMA descriptor will -+ * be read from the EP_RETRY_DMA rather than the orignal DMA - this can then get reused -+ * and an incorrect DMA descriptor sent */ -+ dmabe.s.dma_source = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, Dmas[0]); -+ dmabe.s.dma_direction = (dmabe.s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ -+ if (IssueDma (rail, &dmabe, EP_RETRY_LOW_PRI, FALSE) != ISSUE_COMMAND_OK) -+ { -+ /* Failed to issue the dma command, so copy the dma descriptor and queue it for retry */ -+ EPRINTF2 (DBG_RCVR, "%s: ep3rcvr_rpc_get: queue rxd %p on retry thread\n", rail->Generic.Name, rxd); -+ -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_LOW_PRI); -+ } -+ -+ BucketStat (rxd->Rcvr->Subsys, RPCGet, len); -+} -+ -+void -+ep3rcvr_rpc_complete (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rxdRail->Generic.RcvrRail; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ -+ EP3_RXD_RAIL_MAIN *rxdMain = rxdRail->RxdMain; -+ sdramaddr_t rxdElan = rxdRail->RxdElan; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ E3_DMA_BE dmabe; -+ int i, len; -+ -+ EP_ASSERT (&rail->Generic, rxd->State == EP_RXD_COMPLETE_ACTIVE); -+ EP_ASSERT (&rail->Generic, rxdMain->DataEvent == EP3_EVENT_PRIVATE && rxdMain->DoneEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); /* PCI read */ -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->Generic); -+ -+ /* Initialise the status block dma */ -+ dmabe.s.dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_WRITE, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dmabe.s.dma_size = sizeof (EP_STATUSBLK); -+ dmabe.s.dma_source = rxd->NmdMain.nmd_addr + offsetof (EP_RXD_MAIN, StatusBlk); -+ dmabe.s.dma_dest = env->TxdMain.nmd_addr + offsetof (EP_TXD_MAIN, StatusBlk); -+ dmabe.s.dma_destEvent = env->TxdRail + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent); -+ dmabe.s.dma_destCookieVProc = EP_VP_DATA(env->NodeId); -+ dmabe.s.dma_srcEvent = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent); -+ dmabe.s.dma_srcCookieVProc = LocalCookie (rail, env->NodeId); -+ -+ EPRINTF8 (DBG_RCVR, "%s: ep3rcvr_rpc_complete: rxd %p [XID=%llx] statusblk source=%08x dest=%08x len=%x Cookies=%x.%x\n", rail->Generic.Name, rxd, -+ (long long) env->Xid.Unique, dmabe.s.dma_source, dmabe.s.dma_dest, dmabe.s.dma_size, dmabe.s.dma_destCookieVProc, -+ dmabe.s.dma_srcCookieVProc); -+ -+ for (len = 0, i = EP_MAXFRAG, remote += (nFrags-1), local += (nFrags-1); i > EP_MAXFRAG-nFrags; len += local->nmd_len, i--, local--, remote--) -+ { -+ /* copy down previous dma */ -+ elan3_sdram_copyq_to_sdram (dev, &dmabe, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Dmas[i]), sizeof (E3_DMA)); /* PCI write block */ -+ -+ dmabe.s.dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_WRITE, DMA_NORMAL, EP3_DMAFAILCOUNT); -+ dmabe.s.dma_size = local->nmd_len; -+ dmabe.s.dma_source = local->nmd_addr; -+ dmabe.s.dma_dest = remote->nmd_addr; -+ dmabe.s.dma_destEvent = (E3_Addr) 0; -+ dmabe.s.dma_destCookieVProc = EP_VP_DATA (env->NodeId); -+ dmabe.s.dma_srcEvent = rxdRail->RxdElanAddr + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[i-1]); -+ dmabe.s.dma_srcCookieVProc = LocalCookie (rail, env->NodeId); -+ -+ EPRINTF9 (DBG_RCVR, "%s: ep3rcvr_rpc_complete: rxd %p [XID=%llx] idx=%d Source=%08x Dest=%08x Len=%x Cookies=%x.%x\n", rail->Generic.Name, rxd, -+ (long long) env->Xid.Unique, i, local->nmd_addr, remote->nmd_addr, local->nmd_len, dmabe.s.dma_destCookieVProc, -+ dmabe.s.dma_srcCookieVProc); -+ } -+ -+ for (i = EP_MAXFRAG-nFrags; i < EP_MAXFRAG; i++) -+ elan3_sdram_writel (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[i].ev_Count), 1); /* PCI write */ -+ -+ /* Initialise the done event */ -+ elan3_sdram_writel (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count), 1); /* PCI write */ -+ rxdMain->DoneEvent = EP3_EVENT_ACTIVE; -+ -+ ASSERT (rail->Generic.Nodes[env->NodeId].State >= EP_NODE_CONNECTED && rail->Generic.Nodes[env->NodeId].State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ if (IssueDma (rail, &dmabe, EP_RETRY_LOW_PRI, FALSE) != ISSUE_COMMAND_OK) -+ { -+ /* Failed to issue the dma command, so copy the dma descriptor and queue it for retry */ -+ EPRINTF2 (DBG_RCVR, "%s: ep3rcvr_rpc_complete: queue rxd %p on retry thread\n", rail->Generic.Name, rxd); -+ -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_LOW_PRI); -+ } -+ -+ BucketStat (rxd->Rcvr->Subsys, CompleteRPC, len); -+} -+ -+void -+ep3rcvr_add_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *commsRail) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) commsRail->Rail; -+ sdramaddr_t qdescs = ((EP3_COMMS_RAIL *) commsRail)->QueueDescs; -+ EP3_RCVR_RAIL *rcvrRail; -+ EP3_InputQueue qdesc; -+ sdramaddr_t stack; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (rcvrRail, EP3_RCVR_RAIL *, sizeof (EP3_RCVR_RAIL), TRUE); -+ -+ kcondvar_init (&rcvrRail->CleanupSleep); -+ spin_lock_init (&rcvrRail->FreeDescLock); -+ INIT_LIST_HEAD (&rcvrRail->FreeDescList); -+ INIT_LIST_HEAD (&rcvrRail->DescBlockList); -+ -+ rcvrRail->Generic.CommsRail = commsRail; -+ rcvrRail->Generic.Rcvr = rcvr; -+ -+ rcvrRail->RcvrMain = ep_alloc_main (&rail->Generic, sizeof (EP3_RCVR_RAIL_MAIN), 0, &rcvrRail->RcvrMainAddr); -+ rcvrRail->RcvrElan = ep_alloc_elan (&rail->Generic, sizeof (EP3_RCVR_RAIL_ELAN), 0, &rcvrRail->RcvrElanAddr); -+ rcvrRail->InputQueueBase = ep_alloc_elan (&rail->Generic, EP_INPUTQ_SIZE * rcvr->InputQueueEntries, 0, &rcvrRail->InputQueueAddr); -+ stack = ep_alloc_elan (&rail->Generic, EP3_STACK_SIZE, 0, &rcvrRail->ThreadStack); -+ -+ rcvrRail->TotalDescCount = 0; -+ rcvrRail->FreeDescCount = 0; -+ -+ /* Initialise the main/elan spin lock */ -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadLock.sl_lock), 0); -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadLock.sl_seq), 0); -+ -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingLock.sl_lock), 0); -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingLock.sl_seq), 0); -+ -+ /* Initialise the receive lists */ -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingDescs), 0); -+ -+ /* Initialise the ThreadShould Halt */ -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadShouldHalt), 0); -+ -+ /* Initialise pointer to the ep_rcvr_rail */ -+ elan3_sdram_writeq (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, MainAddr), (unsigned long) rcvrRail); -+ -+ /* Initialise elan visible main memory */ -+ rcvrRail->RcvrMain->ThreadLock.sl_seq = 0; -+ rcvrRail->RcvrMain->PendingLock.sl_seq = 0; -+ rcvrRail->RcvrMain->PendingDescsTailp = 0; -+ -+ /* initialise and copy down the input queue descriptor */ -+ qdesc.q_state = E3_QUEUE_FULL; -+ qdesc.q_base = rcvrRail->InputQueueAddr; -+ qdesc.q_top = rcvrRail->InputQueueAddr + (rcvr->InputQueueEntries-1) * EP_INPUTQ_SIZE; -+ qdesc.q_fptr = rcvrRail->InputQueueAddr; -+ qdesc.q_bptr = rcvrRail->InputQueueAddr + EP_INPUTQ_SIZE; -+ qdesc.q_size = EP_INPUTQ_SIZE; -+ qdesc.q_event.ev_Count = 0; -+ qdesc.q_event.ev_Type = 0; -+ -+ elan3_sdram_copyl_to_sdram (rail->Device, &qdesc, qdescs + rcvr->Service * sizeof (EP3_InputQueue), sizeof (EP3_InputQueue)); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ rcvr->Rails[rail->Generic.Number] = &rcvrRail->Generic; -+ rcvr->RailMask |= EP_RAIL2RAILMASK (rail->Generic.Number); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* initialise and run the Elan thread to process the queue */ -+ IssueRunThread (rail, ep3_init_thread (rail->Device, ep_symbol (&rail->ThreadCode, "ep3comms_rcvr"), -+ rcvrRail->ThreadStack, stack, EP3_STACK_SIZE, 5, -+ rail->RailElanAddr, rcvrRail->RcvrElanAddr, rcvrRail->RcvrMainAddr, -+ EP_MSGQ_ADDR(rcvr->Service), -+ rail->ElanCookies)); -+} -+ -+void -+ep3rcvr_del_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *commsRail) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) commsRail->Rail; -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) rcvr->Rails[rail->Generic.Number]; -+ unsigned long flags; -+ struct list_head *el, *nel; -+ -+ EPRINTF1 (DBG_RCVR, "%s: ep3rcvr_del_rail: removing rail\n", rail->Generic.Name); -+ -+ /* flag the rail as no longer available */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ rcvr->RailMask &= ~EP_RAIL2RAILMASK (rail->Generic.Number); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* mark the input queue descriptor as full */ -+ SetQueueLocked(rail, ((EP3_COMMS_RAIL *)commsRail)->QueueDescs + rcvr->Service * sizeof (EP3_InputQueue)); -+ -+ /* need to halt the thread first */ -+ /* set ThreadShouldHalt in elan memory */ -+ /* then trigger the event */ -+ /* and wait on haltWait */ -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, ThreadShouldHalt), TRUE); -+ -+ IssueSetevent (rail, EP_MSGQ_ADDR(rcvr->Service) + offsetof(EP3_InputQueue, q_event)); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ while (rcvrRail->ThreadHalted == 0) -+ { -+ rcvrRail->CleanupWaiting++; -+ kcondvar_wait (&rcvrRail->CleanupSleep, &rcvr->Lock, &flags); -+ } -+ -+ /* at this point the thread is halted and it has no envelopes */ -+ -+ /* we need to wait until all the rxd's in the list that are -+ * bound to the rail we are removing are not pending -+ */ -+ for (;;) -+ { -+ int mustWait = 0; -+ -+ list_for_each (el, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el,EP_RXD, Link); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ -+ if (rxdRail && RXD_BOUND2RAIL (rxdRail, rcvrRail) && rxd->RxdMain->Len != EP_RXD_PENDING) -+ { -+ mustWait++; -+ break; -+ } -+ } -+ -+ if (! mustWait) -+ break; -+ -+ EPRINTF1 (DBG_RCVR, "%s: ep3rcvr_del_rail: waiting for active rxd's to be returned\n", rail->Generic.Name); -+ -+ rcvrRail->CleanupWaiting++; -+ kcondvar_wait (&rcvrRail->CleanupSleep, &rcvr->Lock, &flags); -+ } -+ -+ /* at this point all rxd's in the list that are bound to the deleting rail are not pending */ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ -+ if (rxdRail && RXD_BOUND2RAIL (rxdRail, rcvrRail)) -+ { -+ /* here we need to unbind the remaining rxd's */ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ elan3_sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ FreeRxdRail(rcvrRail, rxdRail ); -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* wait for all rxd's for this rail to become free */ -+ spin_lock_irqsave (&rcvrRail->FreeDescLock, flags); -+ while (rcvrRail->FreeDescCount != rcvrRail->TotalDescCount) -+ { -+ rcvrRail->FreeDescWaiting++; -+ kcondvar_wait (&rcvrRail->FreeDescSleep, &rcvrRail->FreeDescLock, &flags); -+ } -+ spin_unlock_irqrestore (&rcvrRail->FreeDescLock, flags); -+ -+ /* can now remove the rail as it can no longer be used */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ rcvr->Rails[rail->Generic.Number] = NULL; -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* all the rxd's accociated with DescBlocks must be in the FreeDescList */ -+ ASSERT (rcvrRail->TotalDescCount == rcvrRail->FreeDescCount); -+ -+ /* run through the DescBlockList deleting them */ -+ while (!list_empty (&rcvrRail->DescBlockList)) -+ FreeRxdRailBlock (rcvrRail, list_entry(rcvrRail->DescBlockList.next, EP3_RXD_RAIL_BLOCK , Link)); -+ -+ /* it had better be empty after that */ -+ ASSERT ((rcvrRail->TotalDescCount == 0) && (rcvrRail->TotalDescCount == rcvrRail->FreeDescCount)); -+ -+ ep_free_elan (&rail->Generic, rcvrRail->ThreadStack, EP3_STACK_SIZE); -+ ep_free_elan (&rail->Generic, rcvrRail->InputQueueAddr, EP_INPUTQ_SIZE * rcvr->InputQueueEntries); -+ ep_free_elan (&rail->Generic, rcvrRail->RcvrElanAddr, sizeof (EP3_RCVR_RAIL_ELAN)); -+ ep_free_main (&rail->Generic, rcvrRail->RcvrMainAddr, sizeof (EP3_RCVR_RAIL_MAIN)); -+ -+ KMEM_FREE (rcvrRail, sizeof (EP3_RCVR_RAIL)); -+} -+ -+EP_RXD * -+ep3rcvr_steal_rxd (EP_RCVR_RAIL *r) -+{ -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) r; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ EP_RCVR *rcvr = rcvrRail->Generic.Rcvr; -+ E3_Addr rxdElanAddr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ LockRcvrThread (rcvrRail); -+ if ((rxdElanAddr = elan3_sdram_readl (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingDescs))) != 0) -+ { -+ sdramaddr_t rxdElan = ep_elan2sdram (&rail->Generic, rxdElanAddr); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) (unsigned long) elan3_sdram_readq (rail->Device, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, MainAddr)); -+ EP_RXD *rxd = rxdRail->Generic.Rxd; -+ sdramaddr_t next; -+ -+ EPRINTF2 (DBG_RCVR, "%s: StealRxdFromOtherRail stealing rxd %p\n", rail->Generic.Name, rail); -+ -+ /* Remove the RXD from the pending desc list */ -+ if ((next = elan3_sdram_readl (rail->Device, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Next))) == 0) -+ rcvrRail->RcvrMain->PendingDescsTailp = 0; -+ elan3_sdram_writel (rail->Device, rcvrRail->RcvrElan + offsetof (EP3_RCVR_RAIL_ELAN, PendingDescs), next); -+ UnlockRcvrThread (rcvrRail); -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* Mark rxdRail as no longer active */ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ elan3_sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 0); -+ elan3_sdram_writel (rail->Device, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count), 0); -+ -+ FreeRxdRail (rcvrRail, rxdRail); -+ -+ return rxd; -+ } -+ -+ UnlockRcvrThread (rcvrRail); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ return NULL; -+} -+ -+long -+ep3rcvr_check (EP_RCVR_RAIL *r, long nextRunTime) -+{ -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) r; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ EP_RCVR *rcvr = rcvrRail->Generic.Rcvr; -+ EP_COMMS_SUBSYS *subsys = rcvr->Subsys; -+ EP_SYS *sys = subsys->Subsys.Sys; -+ EP_RXD *rxd; -+ unsigned long flags; -+ -+ if (rcvrRail->FreeDescCount < ep_rxd_lowat && !AllocateRxdRailBlock (rcvrRail)) -+ { -+ EPRINTF1 (DBG_RCVR,"%s: failed to grow rxd rail pool\n", rail->Generic.Name); -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ -+ if (rcvrRail->ThreadWaiting && (rxd = StealRxdFromOtherRail (rcvr)) != NULL) -+ { -+ /* Map the receive buffer into this rail as well */ -+ EPRINTF4 (DBG_RCVR, "%s: mapping rxd->Data (%08x.%08x.%08x) into this rails\n", -+ rail->Generic.Name, rxd->Data.nmd_addr,rxd->Data.nmd_len, rxd->Data.nmd_attr); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ if ((!(EP_NMD_RAILMASK (&rxd->Data) & EP_RAIL2RAILMASK(rail->Generic.Number)) && /* not already mapped and */ -+ ep_nmd_map_rails (sys, &rxd->Data, EP_RAIL2RAILMASK(rail->Generic.Number)) == 0) || /* failed to map it */ -+ ep3rcvr_queue_rxd (rxd, &rcvrRail->Generic)) /* or failed to queue it */ -+ { -+ EPRINTF5 (DBG_RCVR,"%s: stolen rcvr=%p rxd=%p -> rnum=%d rcvrRail=%p (failed)\n", -+ rail->Generic.Name, rcvr, rxd, rail->Generic.Number, rcvrRail); -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ } -+ -+ return nextRunTime; -+} -+ -+static void -+ep3rcvr_flush_filtering (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_COMMS_RAIL *commsRail = (EP3_COMMS_RAIL *) rcvrRail->Generic.CommsRail; -+ EP3_RAIL *rail = (EP3_RAIL *) commsRail->Generic.Rail; -+ ELAN3_DEV *dev = rail->Device; -+ sdramaddr_t qdesc = commsRail->QueueDescs + rcvr->Service*sizeof (EP3_InputQueue); -+ E3_Addr qTop = elan3_sdram_readl (dev, qdesc + offsetof (EP3_InputQueue, q_top)); -+ E3_Addr qBase = elan3_sdram_readl (dev, qdesc + offsetof (EP3_InputQueue, q_base)); -+ E3_Addr qSize = elan3_sdram_readl (dev,qdesc + offsetof (EP3_InputQueue, q_size)); -+ E3_uint32 nfptr, qbptr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ LockRcvrThread (rcvrRail); /* PCI lock */ -+ -+ nfptr = elan3_sdram_readl (dev, qdesc + offsetof (EP3_InputQueue, q_fptr)); -+ qbptr = elan3_sdram_readl (dev, qdesc + offsetof (EP3_InputQueue, q_bptr)); -+ -+ if (nfptr == qTop) -+ nfptr = qBase; -+ else -+ nfptr += qSize; -+ -+ while (nfptr != qbptr) -+ { -+ unsigned nodeId = elan3_sdram_readl (dev, rcvrRail->InputQueueBase + (nfptr - rcvrRail->InputQueueAddr) + -+ offsetof (EP_ENVELOPE, NodeId)); -+ -+ EPRINTF3 (DBG_DISCON, "%s: ep3rcvr_flush_filtering: nodeId=%d State=%d\n", rail->Generic.Name, nodeId, rail->Generic.Nodes[nodeId].State); -+ -+ if (rail->Generic.Nodes[nodeId].State == EP_NODE_LOCAL_PASSIVATE) -+ elan3_sdram_writel (dev, rcvrRail->InputQueueBase + (nfptr - rcvrRail->InputQueueAddr) + -+ offsetof (EP_ENVELOPE, Version), 0); -+ -+ if (nfptr == qTop) -+ nfptr = qBase; -+ else -+ nfptr += qSize; -+ } -+ -+ UnlockRcvrThread (rcvrRail); /* PCI unlock */ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+static void -+ep3rcvr_flush_flushing (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ LockRcvrThread (rcvrRail); /* PCI lock */ -+ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[env->NodeId]; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL(rxdRail,rcvrRail) || nodeRail->State != EP_NODE_LOCAL_PASSIVATE) -+ continue; -+ -+ EPRINTF6 (DBG_DISCON, "%s: ep3rcvr_flush_flushing: rcvr %p rxd %p state %x.%x elan node %d\n", rail->Generic.Name, -+ rcvr, rxd, rxdRail->RxdMain->DataEvent, rxdRail->RxdMain->DoneEvent, env->NodeId); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_FREE: -+ printk ("ep3rcvr_flush_flushing: rxd state is free but bound to a fail\n"); -+ break; -+ -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxdRail->RxdMain->DataEvent == EP3_EVENT_ACTIVE) /* incomplete message receive */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_flush_flushing: rcvr %p rxd %p nodeId %d - passive\n", -+ rail->Generic.Name, rcvr, rxd, env->NodeId); -+ -+ nodeRail->MessageState |= EP_NODE_PASSIVE_MESSAGES; -+ continue; -+ } -+ break; -+ -+ default: -+ EP_ASSERT (&rail->Generic, EP_IS_RPC(env->Attr)); -+ -+ if (!EP3_EVENT_FIRED (rxdRail->DoneCookie, rxdRail->RxdMain->DoneEvent)) /* incomplete RPC */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_flush_flushing: rcvr %p rxd %p nodeId %d - active\n", -+ rail->Generic.Name, rcvr, rxd, env->NodeId); -+ -+ EP_INVALIDATE_XID (rxd->MsgXid); /* Ignore any previous NMD map responses */ -+ -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ continue; -+ } -+ break; -+ -+ case EP_RXD_BEEN_ABORTED: -+ printk ("ep3rcvr_flush_flushing: rxd state is aborted but bound to a fail\n"); -+ break; -+ } -+ -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_flush_flushing: rcvr %p rxd %p nodeId %d - finished\n", -+ rail->Generic.Name, rcvr, rxd, env->NodeId); -+ } -+ -+ UnlockRcvrThread (rcvrRail); /* PCI unlock */ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ep3rcvr_flush_callback (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ -+ switch (rail->Generic.CallbackStep) -+ { -+ case EP_CB_FLUSH_FILTERING: -+ ep3rcvr_flush_filtering (rcvr, rcvrRail); -+ break; -+ -+ case EP_CB_FLUSH_FLUSHING: -+ ep3rcvr_flush_flushing (rcvr, rcvrRail); -+ break; -+ } -+} -+ -+void -+ep3rcvr_failover_callback (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP_COMMS_SUBSYS *subsys = rcvr->Subsys; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ struct list_head *el, *nel; -+ unsigned long flags; -+#ifdef SUPPORT_RAIL_FAILOVER -+ EP_SYS *sys = subsys->Subsys.Sys; -+#endif -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ LockRcvrThread (rcvrRail); /* PCI lock */ -+ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[env->NodeId]; -+#ifdef SUPPORT_RAIL_FAILOVER -+ EP_MANAGER_MSG_BODY msgBody; -+ EP_NODE *node = &sys->Nodes[env->NodeId]; -+#endif -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL(rxdRail,rcvrRail) || nodeRail->State != EP_NODE_PASSIVATED) -+ continue; -+ -+ EPRINTF6 (DBG_FAILOVER, "%s: ep3rcvr_failover_callback: rcvr %p rxd %p elan node %d state %x.%x\n", rail->Generic.Name, rcvr, rxd, env->NodeId, -+ rxdRail->RxdMain->DataEvent, rxdRail->RxdMain->DoneEvent); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_FREE: -+ printk ("ep4rcvr_failover_callback: rxd state is free but bound to a fail\n"); -+ break; -+ -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxdRail->RxdMain->DataEvent == EP3_EVENT_ACTIVE) /* incomplete message receive */ -+ { -+ EPRINTF4 (DBG_FAILOVER, "%s: ep3rcvr_failover_callback: rcvr %p rxd %p nodeId %d - unbind\n", rail->Generic.Name, rcvr, rxd, env->NodeId); -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* clear the data event - the done event should already be zero */ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeRxdRail (rcvrRail, rxdRail); -+ -+ /* epcomms thread will requeue on different rail */ -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ continue; -+ } -+ break; -+ -+ default: -+ EP_ASSERT (&rail->Generic, EP_IS_RPC(env->Attr)); -+ -+#ifdef SUPPORT_RAIL_FAILOVER -+ if (!EP3_EVENT_FIRED (rxdRail->DoneCookie, rxdRail->RxdMain->DoneEvent) && !(EP_IS_NO_FAILOVER(env->Attr))) /* incomplete RPC, which can be failed over */ -+ { -+ EPRINTF7 (DBG_FAILOVER, "%s: ep3rcvr_failover_callback: rxd %p State %x.%x Xid %llxx MsgXid %llxx nodeId %d - failover\n", -+ rail->Generic.Name, rxd, rxdRail->RxdMain->DataEvent, rxdRail->RxdMain->DoneEvent, -+ (long long) env->Xid.Unique, (long long) rxd->MsgXid.Unique, env->NodeId); -+ -+ if (EP_XID_INVALID(rxd->MsgXid)) -+ rxd->MsgXid = ep_xid_cache_alloc (sys, &rcvr->XidCache); -+ -+ /* XXXX maybe only send the message if the node failover retry is now ? */ -+ msgBody.Failover.Xid = env->Xid; -+ msgBody.Failover.Railmask = node->ConnectedRails; -+ -+ ep_send_message (&rail->Generic, env->NodeId, EP_MANAGER_MSG_TYPE_FAILOVER_REQUEST, rxd->MsgXid, &msgBody); -+ -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ continue; -+ } -+#endif -+ break; -+ -+ case EP_RXD_BEEN_ABORTED: -+ printk ("ep4rcvr_failover_callback: rxd state is aborted but bound to a fail\n"); -+ break; -+ } -+ -+ EPRINTF3 (DBG_FAILOVER, "%s: ep3rcvr_failover_callback: rxd %p nodeId %d - finished\n", rail->Generic.Name, rxd, env->NodeId); -+ } -+ -+ UnlockRcvrThread (rcvrRail); /* PCI unlock */ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ep3rcvr_disconnect_callback (EP_RCVR *rcvr, EP3_RCVR_RAIL *rcvrRail) -+{ -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ struct list_head *el, *nel; -+ struct list_head rxdList; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&rxdList); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ LockRcvrThread (rcvrRail); /* PCI lock */ -+ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[env->NodeId]; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL(rxdRail,rcvrRail) || nodeRail->State != EP_NODE_DISCONNECTING) -+ continue; -+ -+ EPRINTF4 (DBG_DISCON, "%s: ep3rcvr_disconnect_callback: rcvr %p rxd %p elan node %d\n", rail->Generic.Name, rcvr, rxd, env->NodeId); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_FREE: -+ printk ("ep3rcvr_disconnect_callback: rxd state is free but bound to a fail\n"); -+ break; -+ -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxdRail->RxdMain->DataEvent == EP3_EVENT_ACTIVE) /* incomplete message receive */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d - unbind\n", rail->Generic.Name, rcvr, rxd, env->NodeId); -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* clear the data event - the done event should already be zero */ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeRxdRail (rcvrRail, rxdRail); -+ -+ /* remark it as pending if it was partially received */ -+ rxd->RxdMain->Len = EP_RXD_PENDING; -+ -+ /* epcomms thread will requeue on different rail */ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ continue; -+ } -+ break; -+ -+ default: -+ EP_ASSERT (&rail->Generic, EP_IS_RPC(env->Attr)); -+ -+ if (!EP3_EVENT_FIRED (rxdRail->DoneCookie, rxdRail->RxdMain->DoneEvent)) /* incomplete RPC */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d - not able to failover\n", -+ rail->Generic.Name, rcvr, rxd, env->NodeId); -+ -+ /* Mark as no longer active */ -+ rxdRail->RxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ rxdRail->RxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (dev, rxdRail->RxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ UnbindRxdFromRail (rxd, rxdRail); -+ FreeRxdRail (rcvrRail, rxdRail); -+ -+ /* Ignore any previous NMD/failover responses */ -+ EP_INVALIDATE_XID (rxd->MsgXid); -+ -+ /* Remove from active list */ -+ list_del (&rxd->Link); -+ -+ if (rxd->State == EP_RXD_RPC_IN_PROGRESS) /* ownder by user .... */ -+ rxd->State = EP_RXD_BEEN_ABORTED; -+ else /* queue for completion */ -+ { -+ rxd->RxdMain->Len = EP_CONN_RESET; /* ensure ep_rxd_status() fails */ -+ list_add_tail (&rxd->Link, &rxdList); -+ } -+ continue; -+ } -+ break; -+ -+ case EP_RXD_BEEN_ABORTED: -+ printk ("ep4rcvr_failover_callback: rxd state is aborted but bound to a fail\n"); -+ break; -+ } -+ -+ EPRINTF4 (DBG_RCVR, "%s: ep3rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d - finished\n", -+ rail->Generic.Name, rcvr, rxd, env->NodeId); -+ } -+ -+ UnlockRcvrThread (rcvrRail); /* PCI unlock */ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ while (! list_empty (&rxdList)) -+ { -+ EP_RXD *rxd = list_entry (rxdList.next, EP_RXD, Link); -+ -+ list_del (&rxd->Link); -+ -+ rxd->Handler (rxd); -+ } -+} -+ -+void -+ep3rcvr_display_rxd (DisplayInfo *di, EP_RXD_RAIL *r) -+{ -+ EP3_RXD_RAIL *rxdRail = (EP3_RXD_RAIL *) r; -+ sdramaddr_t rxdElan = rxdRail->RxdElan; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rxdRail->Generic.RcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ -+ (di->func)(di->arg, " ChainEvent=%x.%x %x.%x\n", -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[0].ev_Count)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[0].ev_Type)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[1].ev_Count)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[1].ev_Type))); -+ (di->func)(di->arg, " ChainEvent=%x.%x %x.%x\n", -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[2].ev_Count)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[2].ev_Type)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[3].ev_Count)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, ChainEvent[3].ev_Type))); -+ (di->func)(di->arg, " DataEvent=%x.%x DoneEvent=%x.%x\n", -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Count)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DataEvent.ev_Type)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Count)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, DoneEvent.ev_Type))); -+ (di->func)(di->arg, " Data=%x Len=%x\n", -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Data.nmd_addr)), -+ elan3_sdram_readl (dev, rxdElan + offsetof (EP3_RXD_RAIL_ELAN, Data.nmd_len))); -+} -+ -+void -+ep3rcvr_display_rcvr (DisplayInfo *di, EP_RCVR_RAIL *r) -+{ -+ EP3_RCVR_RAIL *rcvrRail = (EP3_RCVR_RAIL *) r; -+ EP3_COMMS_RAIL *commsRail = (EP3_COMMS_RAIL *) rcvrRail->Generic.CommsRail; -+ EP3_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN3_DEV *dev = rail->Device; -+ sdramaddr_t queue = commsRail->QueueDescs + rcvrRail->Generic.Rcvr->Service * sizeof (EP3_InputQueue); -+ E3_Addr qbase = elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_base)); -+ E3_Addr qtop = elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_top)); -+ E3_uint32 qsize = elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_size)); -+ int freeCount = 0; -+ int blockCount = 0; -+ unsigned long flags; -+ struct list_head *el; -+ -+ spin_lock_irqsave (&rcvrRail->FreeDescLock, flags); -+ list_for_each (el, &rcvrRail->FreeDescList) -+ freeCount++; -+ list_for_each (el, &rcvrRail->DescBlockList) -+ blockCount++; -+ spin_unlock_irqrestore (&rcvrRail->FreeDescLock, flags); -+ -+ (di->func)(di->arg, " Rail %d FreeDesc %d (%d) Total %d Blocks %d %s\n", -+ rail->Generic.Number, rcvrRail->FreeDescCount, freeCount, rcvrRail->TotalDescCount, blockCount, -+ rcvrRail->ThreadWaiting ? "ThreadWaiting" : ""); -+ -+ (di->func)(di->arg, " InputQueue state=%x bptr=%x size=%x top=%x base=%x fptr=%x\n", -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_state)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_bptr)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_size)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_top)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_base)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_fptr))); -+ (di->func)(di->arg, " event=%x.%x [%x.%x] wevent=%x.%x\n", -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_event.ev_Type)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_event.ev_Count)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_event.ev_Source)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_event.ev_Dest)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_wevent)), -+ elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_wcount))); -+ -+ LockRcvrThread (rcvrRail); -+ { -+ E3_Addr nfptr = elan3_sdram_readl (dev, queue + offsetof (EP3_InputQueue, q_fptr)); -+ EP_ENVELOPE env; -+ -+ if (nfptr == qtop) -+ nfptr = qbase; -+ else -+ nfptr += qsize; -+ -+ while (nfptr != elan3_sdram_readl (dev, queue + offsetof (E3_Queue, q_bptr))) -+ { -+ elan3_sdram_copyl_from_sdram (dev, rcvrRail->InputQueueBase + (nfptr - rcvrRail->InputQueueAddr), -+ &env, sizeof (EP_ENVELOPE)); -+ -+ (di->func)(di->arg, " ENVELOPE Version=%x Attr=%x Xid=%08x.%08x.%016llx\n", -+ env.Version, env.Attr, env.Xid.Generation, env.Xid.Handle, (long long) env.Xid.Unique); -+ (di->func)(di->arg, " NodeId=%x Range=%x TxdRail=%x TxdMain=%x.%x.%x\n", -+ env.NodeId, env.Range, env.TxdRail, env.TxdMain.nmd_addr, -+ env.TxdMain.nmd_len, env.TxdMain.nmd_attr); -+ -+ -+ if (nfptr == qtop) -+ nfptr = qbase; -+ else -+ nfptr += qsize; -+ } -+ } -+ UnlockRcvrThread (rcvrRail); -+} -+ -+void -+ep3rcvr_fillout_rail_stats(EP_RCVR_RAIL *rcvr_rail, char *str) { -+ /* no stats here yet */ -+ /* EP3_RCVR_RAIL * ep4rcvr_rail = (EP3_RCVR_RAIL *) rcvr_rail; */ -+} -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsRx_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsRx_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsRx_elan4.c 2005-06-01 23:12:54.653430896 -0400 -@@ -0,0 +1,1758 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsRx_elan4.c,v 1.30.2.2 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsRx_elan4.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "debug.h" -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "epcomms_elan4.h" -+ -+#include -+ -+#define RCVR_TO_COMMS(rcvrRail) ((EP4_COMMS_RAIL *) ((EP_RCVR_RAIL *) rcvrRail)->CommsRail) -+#define RCVR_TO_RAIL(rcvrRail) ((EP4_RAIL *) ((EP_RCVR_RAIL *) rcvrRail)->CommsRail->Rail) -+#define RCVR_TO_DEV(rcvrRail) (RCVR_TO_RAIL(rcvrRail)->r_ctxt.ctxt_dev) -+#define RCVR_TO_SUBSYS(rcvrRail) (((EP_RCVR_RAIL *) rcvrRail)->Rcvr->Subsys) -+ -+#define RXD_TO_RCVR(txdRail) ((EP4_RCVR_RAIL *) rxdRail->rxd_generic.RcvrRail) -+#define RXD_TO_RAIL(txdRail) RCVR_TO_RAIL(RXD_TO_RCVR(rxdRail)) -+ -+static void rxd_interrupt (EP4_RAIL *rail, void *arg); -+ -+static __inline__ void -+__ep4_rxd_assert_free (EP4_RXD_RAIL *rxdRail, const char *file, const int line) -+{ -+ EP4_RCVR_RAIL *rcvrRail = RXD_TO_RCVR(rxdRail); -+ ELAN4_DEV *dev = RCVR_TO_DEV(rcvrRail); -+ register int i, failed = 0; -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ if (((rxdRail)->rxd_main->rxd_sent[i] != EP4_STATE_FREE)) -+ failed |= (1 << i); -+ -+ if (((rxdRail)->rxd_main->rxd_failed != EP4_STATE_FREE)) -+ failed |= (1 << 5); -+ if (((rxdRail)->rxd_main->rxd_done != EP4_STATE_FREE)) -+ failed |= (1 << 6); -+ -+ if (sdram_assert) -+ { -+ if (((elan4_sdram_readq (RXD_TO_RAIL(rxdRail)->r_ctxt.ctxt_dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CountAndType)) >> 32) != 0)) -+ failed |= (1 << 7); -+ for (i = 0; i < EP_MAXFRAG; i++) -+ if (((elan4_sdram_readq (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[i].ev_CountAndType)) >> 32) != 0)) -+ failed |= (1 << (8 + i)); -+ if (((elan4_sdram_readq (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType)) >> 32) != 0)) -+ failed |= (1 << 12); -+ if (((int)(elan4_sdram_readq (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType)) >> 32) != -32)) -+ failed |= (1 << 13); -+ } -+ -+ if (failed) -+ { -+ printk ("__ep4_rxd_assert_free: failed=%x rxdRail=%p %s - %d\n", failed, rxdRail, file, line); -+ -+ ep_debugf (DBG_DEBUG, "__ep4_rxd_assert_free: failed=%x rxdRail=%p %s - %d\n", failed, rxdRail, file, line); -+ ep4rcvr_display_rxd (&di_ep_debug, &rxdRail->rxd_generic); -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ (rxdRail)->rxd_main->rxd_sent[i] = EP4_STATE_FREE; -+ -+ (rxdRail)->rxd_main->rxd_failed = EP4_STATE_FREE; -+ (rxdRail)->rxd_main->rxd_done = EP4_STATE_FREE; -+ -+ if (sdram_assert) -+ { -+ elan4_sdram_writew (RXD_TO_RAIL(rxdRail)->r_ctxt.ctxt_dev, -+ (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CountAndType) + 4, 0); -+ -+ for (i = 0; i < EP_MAXFRAG; i++) -+ elan4_sdram_writew (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[i].ev_CountAndType) + 4, 0); -+ elan4_sdram_writew (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType) + 4, 0); -+ elan4_sdram_writew (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType) + 4, -32); -+ } -+ EP_ASSFAIL (RCVR_TO_RAIL(rcvrRail), "__ep4_rxd_assert_free"); -+ } -+} -+ -+static __inline__ void -+__ep4_rxd_assert_pending(EP4_RXD_RAIL *rxdRail, const char *file, const int line) -+{ -+ EP4_RCVR_RAIL *rcvrRail = RXD_TO_RCVR(rcvrRail); -+ register int failed = 0; -+ -+ failed |= ((rxdRail)->rxd_main->rxd_done != EP4_STATE_ACTIVE); -+ -+ if (failed) -+ { -+ printk ("__ep4_rxd_assert_pending: %s - %d\n", file, line); -+ -+ ep_debugf (DBG_DEBUG, "__ep4_rxd_assert_pending: %s - %d\n", file, line); -+ ep4rcvr_display_rxd (&di_ep_debug, &rxdRail->rxd_generic); -+ -+ (rxdRail)->rxd_main->rxd_done = EP4_STATE_ACTIVE; -+ -+ EP_ASSFAIL (RCVR_TO_RAIL(rcvrRail), "__ep4_rxd_assert_pending"); -+ } -+} -+ -+static __inline__ void -+__ep4_rxd_assert_private(EP4_RXD_RAIL *rxdRail, const char *file, const int line) -+{ -+ EP4_RCVR_RAIL *rcvrRail = RXD_TO_RCVR(rxdRail); -+ ELAN4_DEV *dev = RCVR_TO_DEV(rcvrRail); -+ register int failed = 0; -+ -+ if (((rxdRail)->rxd_main->rxd_failed != EP4_STATE_ACTIVE)) failed |= (1 << 0); -+ if (((rxdRail)->rxd_main->rxd_done != EP4_STATE_PRIVATE)) failed |= (1 << 1); -+ -+ if (sdram_assert) -+ { -+ if (((elan4_sdram_readq (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType)) >> 32) != 0)) failed |= (1 << 2); -+ if (((int) (elan4_sdram_readq (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType)) >> 32) != -32)) failed |= (1 << 3); -+ } -+ -+ if (failed) -+ { -+ printk ("__ep4_rxd_assert_private: %s - %d\n", file, line); -+ -+ ep_debugf (DBG_DEBUG, "__ep4_rxd_assert_private: %s - %d\n", file, line); -+ ep4rcvr_display_rxd (&di_ep_debug, &rxdRail->rxd_generic); -+ -+ (rxdRail)->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ (rxdRail)->rxd_main->rxd_done = EP4_STATE_PRIVATE; -+ -+ if (sdram_assert) -+ { -+ elan4_sdram_writew (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType) + 4, 0); -+ elan4_sdram_writew (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType) + 4, -32); -+ } -+ -+ EP_ASSFAIL (RCVR_TO_RAIL(rcvrRail), "__ep4_rxd_assert_private"); -+ } -+} -+ -+static __inline__ void -+__ep4_rxd_private_to_free (EP4_RXD_RAIL *rxdRail) -+{ -+ register int i; -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ rxdRail->rxd_main->rxd_sent[i] = EP4_STATE_FREE; -+ -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_FREE; -+ rxdRail->rxd_main->rxd_done = EP4_STATE_FREE; -+} -+ -+static __inline__ void -+__ep4_rxd_force_private (EP4_RXD_RAIL *rxdRail) -+{ -+ EP4_RAIL *rail = RXD_TO_RAIL(rxdRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ -+ (rxdRail)->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ (rxdRail)->rxd_main->rxd_done = EP4_STATE_PRIVATE; -+ -+ if (sdram_assert) -+ elan4_sdram_writeq (dev, (rxdRail)->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+} -+ -+#define EP4_RXD_ASSERT_FREE(rxdRail) __ep4_rxd_assert_free(rxdRail, __FILE__, __LINE__) -+#define EP4_RXD_ASSERT_PENDING(rxdRail) __ep4_rxd_assert_pending(rxdRail, __FILE__, __LINE__) -+#define EP4_RXD_ASSERT_PRIVATE(rxdRail) __ep4_rxd_assert_private(rxdRail, __FILE__, __LINE__) -+#define EP4_RXD_PRIVATE_TO_FREE(rxdRail) __ep4_rxd_private_to_free(rxdRail) -+#define EP4_RXD_FORCE_PRIVATE(rxdRail) __ep4_rxd_force_private(rxdRail) -+ -+static int -+alloc_rxd_block (EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ EP4_RXD_RAIL_BLOCK *blk; -+ EP4_RXD_RAIL_MAIN *rxdMain; -+ EP_ADDR rxdMainAddr; -+ sdramaddr_t rxdElan; -+ EP_ADDR rxdElanAddr; -+ EP4_RXD_RAIL *rxdRail; -+ unsigned long flags; -+ int i, j; -+ -+ KMEM_ZALLOC (blk, EP4_RXD_RAIL_BLOCK *, sizeof (EP4_RXD_RAIL_BLOCK), 1); -+ -+ if (blk == NULL) -+ return 0; -+ -+ if ((rxdElan = ep_alloc_elan (&rail->r_generic, EP4_RXD_RAIL_ELAN_SIZE * EP4_NUM_RXD_PER_BLOCK, 0, &rxdElanAddr)) == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (blk, sizeof (EP4_RXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if ((rxdMain = ep_alloc_main (&rail->r_generic, EP4_RXD_RAIL_MAIN_SIZE * EP4_NUM_RXD_PER_BLOCK, 0, &rxdMainAddr)) == (EP4_RXD_RAIL_MAIN *) NULL) -+ { -+ ep_free_elan (&rail->r_generic, rxdElanAddr, EP4_RXD_RAIL_ELAN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP4_RXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if (ep4_reserve_dma_retries (rail, EP4_NUM_RXD_PER_BLOCK, 0) != 0) -+ { -+ ep_free_main (&rail->r_generic, blk->blk_rxds[0].rxd_main_addr, EP4_RXD_RAIL_MAIN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ ep_free_elan (&rail->r_generic, rxdElanAddr, EP4_RXD_RAIL_ELAN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP4_RXD_RAIL_BLOCK)); -+ -+ return 0; -+ } -+ -+ for (rxdRail = &blk->blk_rxds[0], i = 0; i < EP4_NUM_RXD_PER_BLOCK; i++, rxdRail++) -+ { -+ rxdRail->rxd_generic.RcvrRail = &rcvrRail->rcvr_generic; -+ rxdRail->rxd_elan = rxdElan; -+ rxdRail->rxd_elan_addr = rxdElanAddr; -+ rxdRail->rxd_main = rxdMain; -+ rxdRail->rxd_main_addr = rxdMainAddr; -+ -+ /* reserve 128 bytes of "event" cq space for the chained STEN packets */ -+ if ((rxdRail->rxd_ecq = ep4_get_ecq (rail, EP4_ECQ_EVENT, EP4_RXD_STEN_CMD_NDWORDS)) == NULL) -+ goto failed; -+ -+ /* allocate a single word of "setevent" command space */ -+ if ((rxdRail->rxd_scq = ep4_get_ecq (rail, EP4_ECQ_SINGLE, 1)) == NULL) -+ { -+ ep4_put_ecq (rail, rxdRail->rxd_ecq, EP4_RXD_STEN_CMD_NDWORDS); -+ goto failed; -+ } -+ -+ /* initialise the completion events */ -+ for (j = 0; j <= EP_MAXFRAG; j++) -+ rxdMain->rxd_sent[i] = EP4_STATE_FREE; -+ -+ rxdMain->rxd_done = EP4_STATE_FREE; -+ rxdMain->rxd_failed = EP4_STATE_FREE; -+ -+ /* initialise the scq for the thread */ -+ rxdMain->rxd_scq = rxdRail->rxd_scq->ecq_addr; -+ -+ /* initialise the "start" event to copy the first STEN packet into the command queue */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_START_CMD_NDWORDS)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CopySource), -+ rxdElanAddr + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[0])); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CopyDest), -+ rxdRail->rxd_ecq->ecq_addr); -+ -+ /* initialise the "chain" events to copy the next STEN packet into the command queue */ -+ for (j = 0; j < EP_MAXFRAG; j++) -+ { -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[j].ev_CountAndType), -+ E4_EVENT_INIT_VALUE(0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_STEN_CMD_NDWORDS)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[j].ev_CopySource), -+ rxdElanAddr + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j+1])); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[j].ev_CopyDest), -+ rxdRail->rxd_ecq->ecq_addr); -+ } -+ -+ /* initialise the portions of the sten packets which don't change */ -+ for (j = 0; j < EP_MAXFRAG+1; j++) -+ { -+ if (j < EP_MAXFRAG) -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_dma_dstEvent), -+ rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[j])); -+ else -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_dma_dstEvent), -+ rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done)); -+ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_ok_guard), -+ GUARD_CMD | GUARD_CHANNEL (1) | GUARD_TEST(0, PACK_OK) | GUARD_RESET (EP4_STEN_RETRYCOUNT)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_ok_write_cmd), -+ WRITE_DWORD_CMD | (rxdMainAddr + offsetof (EP4_RXD_RAIL_MAIN, rxd_sent[j]))); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_ok_write_value), -+ EP4_STATE_FINISHED); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_fail_guard), -+ GUARD_CMD | GUARD_CHANNEL (1) | GUARD_TEST(0, RESTART_COUNT_ZERO) | GUARD_RESET (EP4_STEN_RETRYCOUNT)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_fail_setevent), -+ SET_EVENT_CMD | (rxdElanAddr + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed))); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[j].c_nop_cmd), -+ NOP_CMD); -+ } -+ -+ /* register a main interrupt cookie */ -+ ep4_register_intcookie (rail, &rxdRail->rxd_intcookie, rxdElanAddr + offsetof (EP4_RXD_RAIL_ELAN, rxd_done), -+ rxd_interrupt, rxdRail); -+ -+ /* initialise the command stream for the done event */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done_cmd.c_write_cmd), -+ WRITE_DWORD_CMD | (rxdMainAddr + offsetof (EP4_RXD_RAIL_MAIN, rxd_done))); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done_cmd.c_write_value), -+ EP4_STATE_FINISHED); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done_cmd.c_intr_cmd), -+ INTERRUPT_CMD | (rxdRail->rxd_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ /* initialise the command stream for the fail event */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed_cmd.c_write_cmd), -+ WRITE_DWORD_CMD | (rxdMainAddr + offsetof (EP4_RXD_RAIL_MAIN, rxd_failed))); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed_cmd.c_write_value), -+ EP4_STATE_FAILED); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed_cmd.c_intr_cmd), -+ INTERRUPT_CMD | (rxdRail->rxd_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ /* initialise the done and fail events */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CopySource), -+ rxdElanAddr + offsetof (EP4_RXD_RAIL_ELAN, rxd_done_cmd)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CopyDest), -+ rxdRail->rxd_ecq->ecq_addr); -+ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CopySource), -+ rxdElanAddr + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed_cmd)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CopyDest), -+ rxdRail->rxd_ecq->ecq_addr); -+ -+ /* initialise the pointer to the main memory portion */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_main), -+ rxdMainAddr); -+ -+ /* move onto next descriptor */ -+ rxdElan += EP4_RXD_RAIL_ELAN_SIZE; -+ rxdElanAddr += EP4_RXD_RAIL_ELAN_SIZE; -+ rxdMain = (EP4_RXD_RAIL_MAIN *) ((unsigned long) rxdMain + EP4_RXD_RAIL_MAIN_SIZE); -+ rxdMainAddr += EP4_RXD_RAIL_MAIN_SIZE; -+ } -+ -+ spin_lock_irqsave (&rcvrRail->rcvr_freelock, flags); -+ -+ list_add (&blk->blk_link, &rcvrRail->rcvr_blocklist); -+ -+ rcvrRail->rcvr_totalcount += EP4_NUM_RXD_PER_BLOCK; -+ rcvrRail->rcvr_freecount += EP4_NUM_RXD_PER_BLOCK; -+ -+ for (i = 0; i < EP4_NUM_RXD_PER_BLOCK; i++) -+ list_add (&blk->blk_rxds[i].rxd_generic.Link, &rcvrRail->rcvr_freelist); -+ -+ spin_unlock_irqrestore (&rcvrRail->rcvr_freelock, flags); -+ -+ return 1; -+ -+ failed: -+ while (--i >= 0) -+ { -+ rxdRail--; -+ -+ ep4_put_ecq (rail, rxdRail->rxd_ecq, EP4_RXD_STEN_CMD_NDWORDS); -+ ep4_put_ecq (rail, rxdRail->rxd_scq, 1); -+ -+ ep4_deregister_intcookie (rail, &rxdRail->rxd_intcookie); -+ } -+ -+ ep4_release_dma_retries (rail, EP4_NUM_RXD_PER_BLOCK); -+ -+ ep_free_main (&rail->r_generic, blk->blk_rxds[0].rxd_main_addr, EP4_RXD_RAIL_MAIN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ ep_free_elan (&rail->r_generic, rxdElanAddr, EP4_RXD_RAIL_ELAN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP4_RXD_RAIL_BLOCK)); -+ -+ return 0; -+} -+ -+ -+static void -+free_rxd_block (EP4_RCVR_RAIL *rcvrRail, EP4_RXD_RAIL_BLOCK *blk) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ EP4_RXD_RAIL *rxdRail; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&rcvrRail->rcvr_freelock, flags); -+ -+ list_del (&blk->blk_link); -+ -+ rcvrRail->rcvr_totalcount -= EP4_NUM_RXD_PER_BLOCK; -+ -+ for (rxdRail = &blk->blk_rxds[0], i = 0; i < EP4_NUM_RXD_PER_BLOCK; i++, rxdRail++) -+ { -+ rcvrRail->rcvr_freecount--; -+ -+ ep4_put_ecq (rail, rxdRail->rxd_ecq, EP4_RXD_STEN_CMD_NDWORDS); -+ ep4_put_ecq (rail, rxdRail->rxd_scq, 1); -+ -+ ep4_deregister_intcookie (rail, &rxdRail->rxd_intcookie); -+ -+ list_del (&rxdRail->rxd_generic.Link); -+ } -+ spin_unlock_irqrestore (&rcvrRail->rcvr_freelock, flags); -+ -+ ep4_release_dma_retries (rail, EP4_NUM_RXD_PER_BLOCK); -+ -+ ep_free_main (&rail->r_generic, blk->blk_rxds[0].rxd_main_addr, EP4_RXD_RAIL_MAIN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ ep_free_elan (&rail->r_generic, blk->blk_rxds[0].rxd_elan_addr, EP4_RXD_RAIL_ELAN_SIZE * EP4_NUM_RXD_PER_BLOCK); -+ -+ KMEM_FREE (blk, sizeof (EP4_RXD_RAIL_BLOCK)); -+} -+ -+static EP4_RXD_RAIL * -+get_rxd_rail (EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP_COMMS_SUBSYS *subsys = RCVR_TO_SUBSYS(rcvrRail); -+ EP4_RXD_RAIL *rxdRail; -+ unsigned long flags; -+ int low_on_rxds; -+ -+ spin_lock_irqsave (&rcvrRail->rcvr_freelock, flags); -+ -+ if (list_empty (&rcvrRail->rcvr_freelist)) -+ rxdRail = NULL; -+ else -+ { -+ rxdRail = list_entry (rcvrRail->rcvr_freelist.next, EP4_RXD_RAIL, rxd_generic.Link); -+ -+ EP4_RXD_ASSERT_FREE(rxdRail); -+ -+ list_del (&rxdRail->rxd_generic.Link); -+ -+ rcvrRail->rcvr_freecount--; -+ } -+ /* Wakeup the descriptor primer thread if there's not many left */ -+ low_on_rxds = (rcvrRail->rcvr_freecount < ep_rxd_lowat); -+ -+ spin_unlock_irqrestore (&rcvrRail->rcvr_freelock, flags); -+ -+ if (low_on_rxds) -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ -+ return (rxdRail); -+} -+ -+static void -+free_rxd_rail (EP4_RCVR_RAIL *rcvrRail, EP4_RXD_RAIL *rxdRail) -+{ -+ unsigned long flags; -+ -+ EP4_RXD_ASSERT_FREE(rxdRail); -+ -+ spin_lock_irqsave (&rcvrRail->rcvr_freelock, flags); -+ -+ list_add (&rxdRail->rxd_generic.Link, &rcvrRail->rcvr_freelist); -+ -+ rcvrRail->rcvr_freecount++; -+ -+ if (rcvrRail->rcvr_freewaiting) -+ { -+ rcvrRail->rcvr_freewaiting--; -+ kcondvar_wakeupall (&rcvrRail->rcvr_freesleep, &rcvrRail->rcvr_freelock); -+ } -+ -+ spin_unlock_irqrestore (&rcvrRail->rcvr_freelock, flags); -+} -+ -+static void -+bind_rxd_rail (EP_RXD *rxd, EP4_RXD_RAIL *rxdRail) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL (rxdRail->rxd_generic.RcvrRail); -+ -+ ASSERT (SPINLOCK_HELD (&rxd->Rcvr->Lock)); -+ -+ EPRINTF3 (DBG_RCVR, "%s: bind_rxd_rail: rxd=%p rxdRail=%p\n", rail->r_generic.Name, rxd, rxdRail); -+ -+ elan4_sdram_writeq (rail->r_ctxt.ctxt_dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_rxd), rxd->NmdMain.nmd_addr); /* PCI write */ -+ -+ rxd->RxdRail = &rxdRail->rxd_generic; -+ rxdRail->rxd_generic.Rxd = rxd; -+} -+ -+static void -+unbind_rxd_rail (EP_RXD *rxd, EP4_RXD_RAIL *rxdRail) -+{ -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) rxdRail->rxd_generic.RcvrRail; -+ -+ ASSERT (SPINLOCK_HELD (&rxd->Rcvr->Lock)); -+ ASSERT (rxd->RxdRail == &rxdRail->rxd_generic && rxdRail->rxd_generic.Rxd == rxd); -+ -+ EP4_RXD_ASSERT_PRIVATE (rxdRail); -+ -+ EPRINTF3 (DBG_RCVR, "%s: unbind_rxd_rail: rxd=%p rxdRail=%p\n", RCVR_TO_RAIL(rcvrRail)->r_generic.Name, rxd, rxdRail); -+ -+ rxd->RxdRail = NULL; -+ rxdRail->rxd_generic.Rxd = NULL; -+ -+ if (rcvrRail->rcvr_cleanup_waiting) -+ kcondvar_wakeupall (&rcvrRail->rcvr_cleanup_sleep, &rxd->Rcvr->Lock); -+ rcvrRail->rcvr_cleanup_waiting = 0; -+ -+ EP4_RXD_PRIVATE_TO_FREE (rxdRail); -+} -+ -+ -+static void -+rcvr_stall_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) arg; -+ EP_RCVR *rcvr = rcvrRail->rcvr_generic.Rcvr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ EPRINTF1 (DBG_RCVR, "rcvr_stall_interrupt: rcvrRail %p thread halted\n", rcvrRail); -+ -+ rcvrRail->rcvr_thread_halted = 1; -+ -+ kcondvar_wakeupall (&rcvrRail->rcvr_cleanup_sleep, &rcvr->Lock); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+static void -+rcvr_stall_haltop (ELAN4_DEV *dev, void *arg) -+{ -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) arg; -+ EP4_COMMS_RAIL *commsRail = RCVR_TO_COMMS(rcvrRail); -+ EP_RCVR *rcvr = rcvrRail->rcvr_generic.Rcvr; -+ sdramaddr_t qdesc = ((EP4_COMMS_RAIL *) commsRail)->r_descs + (rcvr->Service * EP_QUEUE_DESC_SIZE); -+ E4_uint64 qbptr = elan4_sdram_readq (dev, qdesc + offsetof (E4_InputQueue, q_bptr)); -+ -+ /* Mark the queue as full by writing the fptr */ -+ if (qbptr == (rcvrRail->rcvr_slots_addr + EP_INPUTQ_SIZE * (rcvr->InputQueueEntries-1))) -+ elan4_sdram_writeq (dev, qdesc + offsetof (E4_InputQueue, q_fptr), rcvrRail->rcvr_slots_addr); -+ else -+ elan4_sdram_writeq (dev, qdesc + offsetof (E4_InputQueue, q_fptr), qbptr + EP_INPUTQ_SIZE); -+ -+ /* Notify the thread that it should stall after processing any outstanding envelopes */ -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_stall_intcookie), -+ rcvrRail->rcvr_stall_intcookie.int_val); -+ -+ /* Issue a swtevent to the queue event to wake the thread up */ -+ ep4_set_event_cmd (rcvrRail->rcvr_resched, rcvrRail->rcvr_elan_addr + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_qevent)); -+} -+ -+static void -+rxd_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) arg; -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) rxdRail->rxd_generic.RcvrRail; -+ EP_RCVR *rcvr = rcvrRail->rcvr_generic.Rcvr; -+ EP4_RXD_RAIL_MAIN *rxdMain = rxdRail->rxd_main; -+ unsigned long delay = 1; -+ EP_RXD *rxd; -+ EP_ENVELOPE *env; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ -+ for (;;) -+ { -+ if (rxdMain->rxd_done == EP4_STATE_FINISHED || rxdMain->rxd_failed == EP4_STATE_FAILED) -+ break; -+ -+ /* The write to rxd_done could be held up in the PCI bridge even though -+ * we've seen the interrupt cookie. Unlike elan3, there is no possibility -+ * of spurious interrupts since we flush the command queues on node -+ * disconnection and the txcallback mechanism */ -+ mb(); -+ -+ if (delay > EP4_EVENT_FIRING_TLIMIT) -+ { -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ EP_ASSFAIL (RCVR_TO_RAIL(rcvrRail), "rxd_interrupt - not finished\n"); -+ return; -+ } -+ DELAY(delay); -+ delay <<= 1; -+ } -+ -+ if (rxdMain->rxd_done != EP4_STATE_FINISHED) -+ { -+ EPRINTF8 (DBG_RETRY, "%s: rxd_interrupt: rxdRail %p retry: done=%d failed=%d NodeId=%d XID=%08x.%08x.%016llx\n", -+ rail->r_generic.Name, rxdRail, (int)rxdMain->rxd_done, (int)rxdMain->rxd_failed, rxdRail->rxd_generic.Rxd->RxdMain->Envelope.NodeId, -+ rxdRail->rxd_generic.Rxd->RxdMain->Envelope.Xid.Generation, rxdRail->rxd_generic.Rxd->RxdMain->Envelope.Xid.Handle, -+ rxdRail->rxd_generic.Rxd->RxdMain->Envelope.Xid.Unique); -+ -+ spin_lock (&rcvrRail->rcvr_retrylock); -+ -+ rxdRail->rxd_retry_time = lbolt + EP_RETRY_LOW_PRI_TIME; /* XXXX backoff ? */ -+ -+ list_add_tail (&rxdRail->rxd_retry_link, &rcvrRail->rcvr_retrylist); -+ -+ ep_kthread_schedule (&rail->r_retry_thread, rxdRail->rxd_retry_time); -+ spin_unlock (&rcvrRail->rcvr_retrylock); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ return; -+ } -+ -+ rxd = rxdRail->rxd_generic.Rxd; -+ env = &rxd->RxdMain->Envelope; -+ -+ /* -+ * Note, since the thread will have sent the remote dma packet before copying -+ * the envelope, we must check that it has completed doing this, we do this -+ * by acquiring the spinlock against the thread which it only drops once it's -+ * completed. -+ */ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING) -+ { -+ EP4_SPINENTER (rail->r_ctxt.ctxt_dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), -+ &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ EP4_SPINEXIT (rail->r_ctxt.ctxt_dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), -+ &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ ASSERT (env->Version == EP_ENVELOPE_VERSION && rxd->RxdMain->Len != EP_RXD_PENDING); -+ } -+ -+ EPRINTF8 (DBG_RCVR, "%s: rxd_interrupt: rxd %p finished from %d XID %08x.%08x.%016llx len %d attr %x\n", rail->r_generic.Name, -+ rxd, rxd->RxdMain->Envelope.NodeId, rxd->RxdMain->Envelope.Xid.Generation, rxd->RxdMain->Envelope.Xid.Handle, -+ rxd->RxdMain->Envelope.Xid.Unique, rxd->RxdMain->Len, rxd->RxdMain->Envelope.Attr); -+ -+ rxdMain->rxd_done = EP4_STATE_PRIVATE; -+ rxd->Data.nmd_attr = EP_RAIL2RAILMASK (rail->r_generic.Number); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxd->RxdMain->Len >= 0 && EP_IS_RPC(env->Attr)) -+ rxd->State = EP_RXD_RPC_IN_PROGRESS; -+ else -+ { -+ rxd->State = EP_RXD_COMPLETED; -+ -+ /* remove from active list */ -+ list_del (&rxd->Link); -+ -+ unbind_rxd_rail (rxd, rxdRail); -+ free_rxd_rail (rcvrRail, rxdRail); -+ } -+ -+ if (rxd->RxdMain->Len >= 0) { -+ INC_STAT(rcvrRail->rcvr_generic.stats,rx); -+ ADD_STAT(rcvrRail->rcvr_generic.stats,rx_len,rxd->RxdMain->Len); -+ INC_STAT(rail->r_generic.Stats,rx); -+ ADD_STAT(rail->r_generic.Stats,rx_len,rxd->RxdMain->Len); -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ ep_rxd_received (rxd); -+ -+ break; -+ -+ case EP_RXD_PUT_ACTIVE: -+ case EP_RXD_GET_ACTIVE: -+ rxd->State = EP_RXD_RPC_IN_PROGRESS; -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ rxd->Handler (rxd); -+ break; -+ -+ case EP_RXD_COMPLETE_ACTIVE: -+ rxd->State = EP_RXD_COMPLETED; -+ -+ /* remove from active list */ -+ list_del (&rxd->Link); -+ -+ unbind_rxd_rail (rxd, rxdRail); -+ free_rxd_rail (rcvrRail, rxdRail); -+ -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ rxd->Handler(rxd); -+ break; -+ -+ default: -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ printk ("%s: rxd_interrupt: rxd %p in invalid state %d\n", rail->r_generic.Name, rxd, rxd->State); -+ /* NOTREACHED */ -+ } -+} -+ -+static void -+ep4rcvr_flush_filtering (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP4_COMMS_RAIL *commsRail = RCVR_TO_COMMS(rcvrRail); -+ EP4_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ sdramaddr_t qdesc = commsRail->r_descs + (rcvr->Service * EP_QUEUE_DESC_SIZE); -+ E4_Addr qbase = rcvrRail->rcvr_slots_addr; -+ E4_Addr qlast = qbase + EP_INPUTQ_SIZE * (rcvr->InputQueueEntries-1); -+ E4_uint64 qfptr, qbptr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ EP4_SPINENTER (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ /* zip down the input queue and invalidate any envelope we find to a node which is locally passivated */ -+ qfptr = elan4_sdram_readq (dev, qdesc + offsetof (E4_InputQueue, q_fptr)); -+ qbptr = elan4_sdram_readq (dev, qdesc + offsetof (E4_InputQueue, q_bptr)); -+ -+ while (qfptr != qbptr) -+ { -+ unsigned int nodeId = elan4_sdram_readl (dev, rcvrRail->rcvr_slots + (qfptr - qbase) + offsetof (EP_ENVELOPE, NodeId)); -+ -+ EPRINTF3 (DBG_DISCON, "%s: ep4rcvr_flush_filtering: nodeId=%d State=%d\n", rail->r_generic.Name, nodeId, rail->r_generic.Nodes[nodeId].State); -+ -+ if (rail->r_generic.Nodes[nodeId].State == EP_NODE_LOCAL_PASSIVATE) -+ elan4_sdram_writel (dev, rcvrRail->rcvr_slots + (qfptr - qbase) + offsetof (EP_ENVELOPE, Version), 0); -+ -+ if (qfptr != qlast) -+ qfptr += EP_INPUTQ_SIZE; -+ else -+ qfptr = qbase; -+ } -+ -+ /* Insert an setevent command into the thread's command queue -+ * to ensure that all sten packets have completed */ -+ elan4_guard (rcvrRail->rcvr_ecq->ecq_cq, GUARD_ALL_CHANNELS); -+ ep4comms_flush_setevent (commsRail, rcvrRail->rcvr_ecq->ecq_cq); -+ -+ EP4_SPINEXIT (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+static void -+ep4rcvr_flush_flushing (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el, *nel; -+ struct list_head rxdList; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&rxdList); -+ -+ /* remove any sten packates which are retrying to nodes which are being passivated */ -+ spin_lock_irqsave (&rcvrRail->rcvr_retrylock, flags); -+ list_for_each_safe (el, nel, &rcvrRail->rcvr_retrylist) { -+ EP4_RXD_RAIL *rxdRail = list_entry (el, EP4_RXD_RAIL, rxd_retry_link); -+ EP_ENVELOPE *env = &rxdRail->rxd_generic.Rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[env->NodeId]; -+ -+ if (nodeRail->State == EP_NODE_LOCAL_PASSIVATE) -+ { -+ EPRINTF2 (DBG_XMTR, "%s; ep4rcvr_flush_flushing: removing rxdRail %p from retry list\n", rail->r_generic.Name, rxdRail); -+ -+ list_del (&rxdRail->rxd_retry_link); -+ } -+ } -+ spin_unlock_irqrestore (&rcvrRail->rcvr_retrylock, flags); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ EP4_SPINENTER (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[env->NodeId]; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL (rxdRail, rcvrRail) || nodeRail->State != EP_NODE_LOCAL_PASSIVATE) -+ continue; -+ -+ EPRINTF5 (DBG_DISCON, "%s: ep4rcvr_flush_flushing: rcvr %p rxd %p state %d elan node %d\n", -+ rail->r_generic.Name, rcvr, rxd, (int)rxdRail->rxd_main->rxd_done, env->NodeId); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_FREE: -+ printk ("ep4rcvr_flush_flushing: rxd state is free but bound to a fail\n"); -+ break; -+ -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxdRail->rxd_main->rxd_done == EP4_STATE_ACTIVE) /* incomplete message receive */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep4rcvr_flush_flushing: rcvr %p rxd %p nodeId %d - passive\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ -+ nodeRail->MessageState |= EP_NODE_PASSIVE_MESSAGES; -+ continue; -+ } -+ break; -+ -+ default: -+ EP4_ASSERT (rail, EP_IS_RPC(env->Attr)); -+ -+ if (rxdRail->rxd_main->rxd_done == EP4_STATE_ACTIVE) /* incomplete RPC */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep4rcvr_flush_flushing: rcvr %p rxd %p nodeId %d - active\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ -+ EP_INVALIDATE_XID (rxd->MsgXid); /* Ignore any previous NMD map responses */ -+ -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ continue; -+ } -+ break; -+ -+ case EP_RXD_BEEN_ABORTED: -+ printk ("ep4rcvr_flush_flushing: rxd state is aborted but bound to a fail\n"); -+ break; -+ } -+ -+ EPRINTF4 (DBG_RCVR, "%s: ep4rcvr_flush_flushing: rcvr %p rxd %p nodeId %d - finished\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ } -+ -+ EP4_SPINEXIT (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ep4rcvr_flush_callback (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL(rcvrRail); -+ -+ switch (rail->r_generic.CallbackStep) -+ { -+ case EP_CB_FLUSH_FILTERING: -+ ep4rcvr_flush_filtering (rcvr, rcvrRail); -+ break; -+ -+ case EP_CB_FLUSH_FLUSHING: -+ ep4rcvr_flush_flushing (rcvr, rcvrRail); -+ break; -+ } -+} -+ -+void -+ep4rcvr_failover_callback (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP_COMMS_SUBSYS *subsys = rcvr->Subsys; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el, *nel; -+ unsigned long flags; -+#if SUPPORT_RAIL_FAILOVER -+ EP_SYS *sys = subsys->Subsys.Sys; -+#endif -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ EP4_SPINENTER (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[env->NodeId]; -+#if SUPPORT_RAIL_FAILOVER -+ EP_NODE *node = &sys->Nodes[env->NodeId]; -+ EP_MANAGER_MSG_BODY msgBody; -+#endif -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL(rxdRail,rcvrRail) || nodeRail->State != EP_NODE_PASSIVATED) -+ continue; -+ -+ EPRINTF5 (DBG_FAILOVER, "%s: ep4rcvr_failover_callback: rcvr %p rxd %p elan node %d state %d\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId, (int)rxdRail->rxd_main->rxd_done); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_FREE: -+ printk ("ep4rcvr_failover_callback: rxd state is free but bound to a fail\n"); -+ break; -+ -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxdRail->rxd_main->rxd_done == EP4_STATE_ACTIVE) /* incomplete message receive */ -+ { -+ EPRINTF4 (DBG_FAILOVER, "%s: ep4rcvr_failover_callback: rcvr %p rxd %p nodeId %d - unbind\n", rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ -+ EP4_RXD_FORCE_PRIVATE(rxdRail); -+ -+ unbind_rxd_rail (rxd, rxdRail); -+ -+ free_rxd_rail (rcvrRail, rxdRail); -+ -+ /* epcomms thread will requeue on different rail */ -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ continue; -+ } -+ break; -+ -+ default: -+ EP4_ASSERT (rail, EP_IS_RPC(env->Attr)); -+ -+#if SUPPORT_RAIL_FAILOVER -+ /* XXXX - no rail failover for now .... */ -+ if (rxdRail->rxd_main->rxd_done == EP4_STATE_ACTIVE && !EP_IS_NO_FAILOVER(env->Attr)) /* incomplete RPC, which can be failed over */ -+ { -+ EPRINTF6 (DBG_FAILOVER, "%s: ep4rcvr_failover_callback: rxd %p State %d Xid %llxx MsgXid %llxx nodeId %d - failover\n", -+ rail->r_generic.Name, rxd, rxd->State, env->Xid.Unique, rxd->MsgXid.Unique, env->NodeId); -+ -+ if (EP_XID_INVALID(rxd->MsgXid)) -+ rxd->MsgXid = ep_xid_cache_alloc (sys, &rcvr->XidCache); -+ -+ /* XXXX maybe only send the message if the node failover retry is now ? */ -+ msgBody.Failover.Xid = env->Xid; -+ msgBody.Failover.Railmask = node->ConnectedRails; -+ -+ ep_send_message (&rail->r_generic, env->NodeId, EP_MANAGER_MSG_TYPE_FAILOVER_REQUEST, rxd->MsgXid, &msgBody); -+ -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ continue; -+ } -+#endif -+ break; -+ -+ case EP_RXD_BEEN_ABORTED: -+ printk ("ep4rcvr_failover_callback: rxd state is aborted but bound to a fail\n"); -+ break; -+ } -+ EPRINTF3 (DBG_FAILOVER, "%s: ep4rcvr_failover_callback: rxd %p nodeId %d - finished\n", rail->r_generic.Name, rxd, env->NodeId); -+ } -+ -+ EP4_SPINEXIT (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ep4rcvr_disconnect_callback (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el, *nel; -+ struct list_head rxdList; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&rxdList); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ EP4_SPINENTER (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[env->NodeId]; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL(rxdRail,rcvrRail) || nodeRail->State != EP_NODE_DISCONNECTING) -+ continue; -+ -+ EPRINTF5 (DBG_DISCON, "%s: ep4rcvr_disconnect_callback: rcvr %p rxd %p elan node %d state %x\n", rail->r_generic.Name, rcvr, rxd, env->NodeId, rxd->State); -+ -+ switch (rxd->State) -+ { -+ case EP_RXD_FREE: -+ printk ("ep4rcvr_disconnect_callback: rxd state is free but bound to a rail\n"); -+ break; -+ -+ case EP_RXD_RECEIVE_ACTIVE: -+ if (rxdRail->rxd_main->rxd_done == EP4_STATE_ACTIVE) /* incomplete message receive */ -+ { -+ EPRINTF4 (DBG_RCVR, "%s: ep4rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d - unbind\n", rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ -+ EP4_RXD_FORCE_PRIVATE (rxdRail); -+ -+ unbind_rxd_rail (rxd, rxdRail); -+ free_rxd_rail (rcvrRail, rxdRail); -+ -+ /* remark it as pending if it was partially received */ -+ rxd->RxdMain->Len = EP_RXD_PENDING; -+ -+ /* epcomms thread will requeue on different rail */ -+ ep_kthread_schedule (&rcvr->Subsys->Thread, lbolt); -+ continue; -+ } -+ break; -+ -+ default: -+ if (rxdRail->rxd_main->rxd_done == EP4_STATE_ACTIVE || rxdRail->rxd_main->rxd_done == EP4_STATE_PRIVATE) /* incomplete RPC */ -+ { -+ EPRINTF5 (DBG_RCVR, "%s: ep4rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d state %x - not able to failover\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId, rxd->State); -+ -+ EP4_RXD_FORCE_PRIVATE (rxdRail); -+ -+ unbind_rxd_rail (rxd, rxdRail); -+ free_rxd_rail (rcvrRail, rxdRail); -+ -+ /* Ignore any previous NMD/failover responses */ -+ EP_INVALIDATE_XID (rxd->MsgXid); -+ -+ /* Remove from active list */ -+ list_del (&rxd->Link); -+ -+ if (rxd->State == EP_RXD_RPC_IN_PROGRESS) /* ownder by user .... */ -+ rxd->State = EP_RXD_BEEN_ABORTED; -+ else /* queue for completion */ -+ { -+ rxd->RxdMain->Len = EP_CONN_RESET; /* ensure ep_rxd_status() fails */ -+ list_add_tail (&rxd->Link, &rxdList); -+ } -+ continue; -+ } -+ break; -+ -+ case EP_RXD_BEEN_ABORTED: -+ printk ("ep4rcvr_disconnect_callback: rxd state is aborted but bound to a rail\n"); -+ break; -+ } -+ -+ printk ("%s: ep4rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d - finished\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ EPRINTF4 (DBG_RCVR, "%s: ep4rcvr_disconnect_callback: rcvr %p rxd %p nodeId %d - finished\n", -+ rail->r_generic.Name, rcvr, rxd, env->NodeId); -+ ep4rcvr_display_rxd (&di_ep_debug, &rxdRail->rxd_generic); -+ } -+ -+ EP4_SPINEXIT (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ while (! list_empty (&rxdList)) -+ { -+ EP_RXD *rxd = list_entry (rxdList.next, EP_RXD, Link); -+ -+ list_del (&rxd->Link); -+ -+ rxd->Handler (rxd); -+ } -+} -+ -+void -+ep4rcvr_neterr_flush (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP4_COMMS_RAIL *commsRail = RCVR_TO_COMMS(rcvrRail); -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ EP4_SPINENTER (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ /* Insert an setevent command into the thread's command queue -+ * to ensure that all sten packets have completed */ -+ elan4_guard (rcvrRail->rcvr_ecq->ecq_cq, GUARD_ALL_CHANNELS); -+ ep4comms_flush_setevent (commsRail, rcvrRail->rcvr_ecq->ecq_cq); -+ -+ EP4_SPINEXIT (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+void -+ep4rcvr_neterr_check (EP_RCVR *rcvr, EP4_RCVR_RAIL *rcvrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ EP4_SPINENTER (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ -+ list_for_each (el, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ -+ if (rxd->RxdMain->Len == EP_RXD_PENDING || !RXD_BOUND2RAIL(rxdRail,rcvrRail) || env->NodeId != nodeId) -+ continue; -+ -+ if (rxd->State == EP_RXD_RECEIVE_ACTIVE || rxd->State == EP_RXD_GET_ACTIVE) -+ { -+ EP_NETERR_COOKIE cookie; -+ unsigned int first, this; -+ -+ if (rxd->State == EP_RXD_RECEIVE_ACTIVE) -+ first = (EP_MAXFRAG+1) - (( EP_IS_MULTICAST(env->Attr) ? 1 : 0) + (env->nFrags == 0 ? 1 : env->nFrags)); -+ else -+ first = (EP_MAXFRAG+1) - rxd->nFrags; -+ -+ for (this = first; this < (EP_MAXFRAG+1); this++) -+ if (rxdRail->rxd_main->rxd_sent[this] == EP4_STATE_ACTIVE) -+ break; -+ -+ if (this > first) -+ { -+ /* Look at the last completed STEN packet and if it's neterr cookie matches, then change -+ * the rxd to look the same as if the sten packet had failed and then schedule it for retry */ -+ cookie = elan4_sdram_readq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[--this].c_cookie)); -+ -+ if (cookie == cookies[0] || cookie == cookies[1]) -+ { -+ EPRINTF5 (DBG_NETWORK_ERROR, "%s: ep4rcvr_neterr_check: cookie <%lld%s%s%s%s> matches rxd %p rxdRail %p this %d\n", -+ rail->r_generic.Name, EP4_COOKIE_STRING(cookie), rxd, rxdRail, this); -+ -+ printk ("%s: ep4rcvr_neterr_check: cookie <%lld%s%s%s%s> matches rxd %p rxdRail %p this %d : time %ld\n", -+ rail->r_generic.Name, EP4_COOKIE_STRING(cookie), rxd, rxdRail, this, rxdRail->rxd_retry_time); -+ -+ rxdRail->rxd_main->rxd_sent[this] = EP4_STATE_ACTIVE; -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_FAILED; -+ -+ spin_lock (&rcvrRail->rcvr_retrylock); -+ -+ ASSERT (rxdRail->rxd_retry_time == 0); -+ -+ rxdRail->rxd_retry_time = lbolt + EP_RETRY_LOW_PRI_TIME; -+ -+ list_add_tail (&rxdRail->rxd_retry_link, &rcvrRail->rcvr_retrylist); -+ -+ ep_kthread_schedule (&rail->r_retry_thread, rxdRail->rxd_retry_time); -+ -+ spin_unlock (&rcvrRail->rcvr_retrylock); -+ } -+ } -+ } -+ } -+ EP4_SPINEXIT (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), &rcvrRail->rcvr_main->rcvr_thread_lock); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+} -+ -+int -+ep4rcvr_queue_rxd (EP_RXD *rxd, EP_RCVR_RAIL *r) -+{ -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) r; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ EP4_RXD_RAIL *rxdRail; -+ register int i; -+ -+ ASSERT (SPINLOCK_HELD(&rxd->Rcvr->Lock)); -+ -+ if ((rxdRail = get_rxd_rail (rcvrRail)) == NULL) -+ return 0; -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->r_generic); -+ -+ EPRINTF6 (DBG_RCVR, "%s: ep4rcvr_queue_rxd: rcvr %p rxd %p rxdRail %p buffer %x len %x\n", -+ rail->r_generic.Name, rxd->Rcvr, rxd, rxdRail, rxd->Data.nmd_addr, rxd->Data.nmd_len); -+ -+ /* bind the rxdRail and rxd together */ -+ bind_rxd_rail (rxd, rxdRail); -+ -+ elan4_sdram_writel (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_buffer.nmd_addr), rxd->Data.nmd_addr); /* PCI write */ -+ elan4_sdram_writel (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_buffer.nmd_len), rxd->Data.nmd_len); /* PCI write */ -+ elan4_sdram_writel (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_buffer.nmd_attr), rxd->Data.nmd_attr); /* PCI write */ -+ -+ /* Mark as active */ -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ rxdRail->rxd_main->rxd_sent[i] = EP4_STATE_ACTIVE; -+ -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ rxdRail->rxd_main->rxd_done = EP4_STATE_ACTIVE; -+ -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[0]) + 0x00, /* %r0 */ -+ ep_symbol (&rail->r_threadcode, "c_queue_rxd")); -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[0]) + 0x10, /* %r2 */ -+ rcvrRail->rcvr_elan_addr); -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[0]) + 0x18, /* %r3 */ -+ rxdRail->rxd_elan_addr); -+ -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_START_CMD_NDWORDS)); -+ -+ ep4_set_event_cmd (rxdRail->rxd_scq, rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_start)); -+ -+ return 1; -+} -+ -+void -+ep4rcvr_rpc_put (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags) -+{ -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) rxdRail->rxd_generic.RcvrRail; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = RCVR_TO_DEV (rcvrRail); -+ sdramaddr_t rxdElan = rxdRail->rxd_elan; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ unsigned long first = (EP_MAXFRAG+1) - nFrags; -+ EP4_RXD_DMA_CMD cmd; -+ register int i, len; -+ -+ EP4_ASSERT (rail, rxd->State == EP_RXD_PUT_ACTIVE); -+ EP4_ASSERT (rail, rxdRail->rxd_main->rxd_done == EP4_STATE_PRIVATE); -+ EP4_SDRAM_ASSERT (rail, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->r_generic); -+ -+ /* Generate the DMA chain to put the data */ -+ for (i = 0, len = 0; i < nFrags; i++, len += local->nmd_len, local++, remote++) -+ { -+ cmd.c_dma_typeSize = RUN_DMA_CMD | E4_DMA_TYPE_SIZE(local->nmd_len, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT); -+ cmd.c_dma_cookie = ep4_neterr_cookie (rail, env->NodeId) | EP4_COOKIE_DMA; -+ cmd.c_dma_vproc = EP_VP_DATA(env->NodeId); -+ cmd.c_dma_srcAddr = local->nmd_addr; -+ cmd.c_dma_dstAddr = remote->nmd_addr; -+ if (i == (nFrags-1)) -+ cmd.c_dma_srcEvent = rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_done); -+ else -+ cmd.c_dma_srcEvent = rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first + i]); -+ cmd.c_dma_dstEvent = 0; -+ cmd.c_nop_cmd = NOP_CMD; -+ -+ EPRINTF7 (DBG_RCVR, "%s: ep4rcvr_rpc_put: rxd %p [XID=%llx] idx=%d Source=%08x Dest=%08x Len=%x\n", -+ rail->r_generic.Name, rxd, env->Xid.Unique, i, local->nmd_addr, remote->nmd_addr, local->nmd_len); -+ -+ elan4_sdram_copyq_to_sdram (dev, &cmd, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i]), sizeof (EP4_RXD_DMA_CMD)); -+ } -+ -+ /* Initialise the event chain */ -+ for (i = 0; i < nFrags-1; i++) -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first + i]), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_DMA_CMD_NDWORDS)); -+ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ rxdRail->rxd_main->rxd_sent[i] = EP4_STATE_ACTIVE; -+ -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ rxdRail->rxd_main->rxd_done = EP4_STATE_ACTIVE; -+ -+ /* Initialise the previous event to start the whole chain off */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1]), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_DMA_CMD_NDWORDS)); -+ -+ ASSERT (rail->r_generic.Nodes[env->NodeId].State >= EP_NODE_CONNECTED && rail->r_generic.Nodes[env->NodeId].State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ /* finally issue the setevent to start the whole chain */ -+ ep4_set_event_cmd (rxdRail->rxd_scq, rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1])); -+ -+ BucketStat (rxd->Rcvr->Subsys, RPCPut, len); -+} -+ -+void -+ep4rcvr_rpc_get (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags) -+{ -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) rxdRail->rxd_generic.RcvrRail; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = RCVR_TO_DEV (rcvrRail); -+ sdramaddr_t rxdElan = rxdRail->rxd_elan; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ unsigned long first = (EP_MAXFRAG+1) - nFrags; -+ register int i, len; -+ -+ EP4_ASSERT (rail, rxd->State == EP_RXD_GET_ACTIVE); -+ EP4_ASSERT (rail, rxdRail->rxd_main->rxd_done == EP4_STATE_PRIVATE); -+ EP4_SDRAM_ASSERT (rail, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->r_generic); -+ -+ /* Generate the DMA chain to put the data */ -+ for (i = 0, len = 0; i < nFrags; i++, len += local->nmd_len, local++, remote++) -+ { -+ EPRINTF7 (DBG_RCVR, "%s: ep4rcvr_rpc_get rxd %p [XID=%llx] idx=%d Source=%08x Dest=%08x Len=%x\n", -+ rail->r_generic.Name, rxd, env->Xid.Unique, i, remote->nmd_addr, local->nmd_addr, remote->nmd_len); -+ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_open), -+ OPEN_STEN_PKT_CMD | OPEN_PACKET(0, PACK_OK | RESTART_COUNT_ZERO, EP_VP_DATA(env->NodeId))); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_trans), -+ SEND_TRANS_CMD | ((TR_REMOTEDMA | TR_WAIT_FOR_EOP) << 16)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_cookie), -+ ep4_neterr_cookie (rail, env->NodeId) | EP4_COOKIE_STEN); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_typeSize), -+ E4_DMA_TYPE_SIZE (local->nmd_len, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_cookie), -+ ep4_neterr_cookie (rail, env->NodeId) | EP4_COOKIE_DMA); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_vproc), -+ EP_VP_DATA (rail->r_generic.Position.pos_nodeid)); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_srcAddr), -+ remote->nmd_addr); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_dstAddr), -+ local->nmd_addr); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_srcEvent), -+ 0); -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i].c_dma_dstEvent), -+ i == (nFrags-1) ? rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_done) : -+ rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first + i])); -+ } -+ -+ /* Initialise the event chain */ -+ for (i = 0; i < nFrags-1; i++) -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first + i]), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_STEN_CMD_NDWORDS)); -+ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ rxdRail->rxd_main->rxd_sent[i] = EP4_STATE_ACTIVE; -+ -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ rxdRail->rxd_main->rxd_done = EP4_STATE_ACTIVE; -+ -+ /* Initialise the previous event to start the whole chain off */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1]), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_STEN_CMD_NDWORDS)); -+ -+ ASSERT (rail->r_generic.Nodes[env->NodeId].State >= EP_NODE_CONNECTED && rail->r_generic.Nodes[env->NodeId].State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ /* finally issue the setevent to start the whole chain */ -+ ep4_set_event_cmd (rxdRail->rxd_scq, rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1])); -+ -+ BucketStat (rxd->Rcvr->Subsys, RPCPut, len); -+} -+ -+void -+ep4rcvr_rpc_complete (EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags) -+{ -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) rxdRail->rxd_generic.RcvrRail; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = RCVR_TO_DEV (rcvrRail); -+ sdramaddr_t rxdElan = rxdRail->rxd_elan; -+ EP_ENVELOPE *env = &rxd->RxdMain->Envelope; -+ unsigned long first = (EP_MAXFRAG+1) - nFrags - 1; -+ EP4_RXD_DMA_CMD cmd; -+ register int i, len; -+ -+ EP4_ASSERT (rail, rxd->State == EP_RXD_COMPLETE_ACTIVE); -+ EP4_ASSERT (rail, rxdRail->rxd_main->rxd_done == EP4_STATE_PRIVATE); -+ EP4_SDRAM_ASSERT (rail, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->r_generic); -+ -+ /* Generate the DMA chain to put the data */ -+ for (i = 0, len = 0; i < nFrags; i++, len += local->nmd_len, local++, remote++) -+ { -+ cmd.c_dma_typeSize = RUN_DMA_CMD | E4_DMA_TYPE_SIZE(local->nmd_len, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT); -+ cmd.c_dma_cookie = ep4_neterr_cookie (rail, env->NodeId) | EP4_COOKIE_DMA; -+ cmd.c_dma_vproc = EP_VP_DATA(env->NodeId); -+ cmd.c_dma_srcAddr = local->nmd_addr; -+ cmd.c_dma_dstAddr = remote->nmd_addr; -+ cmd.c_dma_srcEvent = rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first + i]); -+ cmd.c_dma_dstEvent = 0; -+ cmd.c_nop_cmd = NOP_CMD; -+ -+ EPRINTF7 (DBG_RCVR, "%s: ep4rcvr_rpc_complete: rxd %p [XID=%llx] idx=%d Source=%08x Dest=%08x Len=%x\n", -+ rail->r_generic.Name, rxd, env->Xid.Unique, i, local->nmd_addr, remote->nmd_addr, local->nmd_len); -+ -+ elan4_sdram_copyq_to_sdram (dev, &cmd, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[first + i]), sizeof (EP4_RXD_DMA_CMD)); -+ } -+ -+ /* Initialise the status block dma */ -+ cmd.c_dma_typeSize = RUN_DMA_CMD | E4_DMA_TYPE_SIZE(EP_STATUSBLK_SIZE, DMA_DataTypeByte, 0, EP4_DMA_RETRYCOUNT); -+ cmd.c_dma_cookie = ep4_neterr_cookie (rail, env->NodeId) | EP4_COOKIE_DMA; -+ cmd.c_dma_vproc = EP_VP_DATA(env->NodeId); -+ cmd.c_dma_srcAddr = rxd->NmdMain.nmd_addr + offsetof (EP_RXD_MAIN, StatusBlk); -+ cmd.c_dma_dstAddr = env->TxdMain.nmd_addr + offsetof (EP_TXD_MAIN, StatusBlk); -+ cmd.c_dma_srcEvent = rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_done); -+ cmd.c_dma_dstEvent = env->TxdRail + offsetof (EP4_TXD_RAIL_ELAN, txd_done);; -+ cmd.c_nop_cmd = NOP_CMD; -+ -+ EPRINTF6 (DBG_RCVR, "%s: ep4rcvr_rpc_complete: rxd %p [XID=%llx] statusblk source=%08x dest=%08x len=%x\n", -+ rail->r_generic.Name, rxd, env->Xid.Unique, (int) cmd.c_dma_srcAddr, (int) cmd.c_dma_dstAddr, EP_STATUSBLK_SIZE); -+ -+ elan4_sdram_copyq_to_sdram (dev, &cmd, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[EP_MAXFRAG]), sizeof (EP4_RXD_DMA_CMD)); -+ -+ /* Initialise the event chain */ -+ for (i = 0; i < nFrags; i++) -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first + i]), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_DMA_CMD_NDWORDS)); -+ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ for (i = 0; i <= EP_MAXFRAG; i++) -+ rxdRail->rxd_main->rxd_sent[i] = EP4_STATE_ACTIVE; -+ -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ rxdRail->rxd_main->rxd_done = EP4_STATE_ACTIVE; -+ -+ /* Initialise the previous event to start the whole chain off */ -+ elan4_sdram_writeq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1]), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_DMA_CMD_NDWORDS)); -+ -+ ASSERT (rail->r_generic.Nodes[env->NodeId].State >= EP_NODE_CONNECTED && rail->r_generic.Nodes[env->NodeId].State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ /* finally issue the setevent to start the whole chain */ -+ ep4_set_event_cmd (rxdRail->rxd_scq, rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1])); -+ -+ BucketStat (rxd->Rcvr->Subsys, CompleteRPC, len); -+} -+ -+EP_RXD * -+ep4rcvr_steal_rxd (EP_RCVR_RAIL *r) -+{ -+ /* XXXX - TBD */ -+ return NULL; -+} -+ -+long -+ep4rcvr_check (EP_RCVR_RAIL *r, long nextRunTime) -+{ -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) r; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ -+ if (rcvrRail->rcvr_freecount < ep_rxd_lowat && !alloc_rxd_block (rcvrRail)) -+ { -+ EPRINTF1 (DBG_RCVR,"%s: failed to grow rxd rail pool\n", rail->r_generic.Name); -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ -+ return nextRunTime; -+} -+ -+unsigned long -+ep4rcvr_retry (EP4_RAIL *rail, void *arg, unsigned long nextRunTime) -+{ -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) arg; -+ ELAN4_DEV *dev = RCVR_TO_DEV(rcvrRail); -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvrRail->rcvr_retrylock, flags); -+ while (! list_empty (&rcvrRail->rcvr_retrylist)) -+ { -+ EP4_RXD_RAIL *rxdRail = list_entry (rcvrRail->rcvr_retrylist.next, EP4_RXD_RAIL, rxd_retry_link); -+ EP_ENVELOPE *env = &rxdRail->rxd_generic.Rxd->RxdMain->Envelope; -+ unsigned int first = (EP_MAXFRAG+1) - ((env->Attr & EP_MULTICAST ? 1 : 0) + (env->nFrags == 0 ? 1 : env->nFrags)); -+ -+ if (BEFORE (lbolt, rxdRail->rxd_retry_time)) -+ { -+ if (nextRunTime == 0 || AFTER (nextRunTime, rxdRail->rxd_retry_time)) -+ nextRunTime = rxdRail->rxd_retry_time; -+ -+ break; -+ } -+ -+ list_del (&rxdRail->rxd_retry_link); -+ rxdRail->rxd_retry_time = 0; -+ -+ /* determine which sten packet to resubmit */ -+ for (; first < (EP_MAXFRAG+1); first++) -+ if (rxdRail->rxd_main->rxd_sent[first] == EP4_STATE_ACTIVE) -+ break; -+ -+ EPRINTF3 (DBG_RETRY, "%s: ep4rcvr_retry: rxdRail %p, reissuing sten[%d]\n", rail->r_generic.Name, rxdRail, first); -+ -+ /* re-initialise the fail event */ -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ rxdRail->rxd_main->rxd_failed = EP4_STATE_ACTIVE; -+ -+ /* re-initialise the chain event to resubmit this sten packet */ -+ elan4_sdram_writeq (dev, rxdRail->rxd_elan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first-1].ev_CountAndType), -+ E4_EVENT_INIT_VALUE(-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_RXD_STEN_CMD_NDWORDS)); -+ -+ /* finally issue the setevent to start the chain again */ -+ ep4_set_event_cmd (rxdRail->rxd_scq, rxdRail->rxd_elan_addr + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[first - 1])); -+ } -+ spin_unlock_irqrestore (&rcvrRail->rcvr_retrylock, flags); -+ -+ return nextRunTime; -+} -+ -+void -+ep4rcvr_add_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *commsRail) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->Rail; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ sdramaddr_t qdescs = ((EP4_COMMS_RAIL *) commsRail)->r_descs; -+ EP4_RCVR_RAIL *rcvrRail; -+ E4_InputQueue qdesc; -+ E4_ThreadRegs tregs; -+ sdramaddr_t stack; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (rcvrRail, EP4_RCVR_RAIL *, sizeof (EP4_RCVR_RAIL), 1); -+ -+ spin_lock_init (&rcvrRail->rcvr_freelock); -+ INIT_LIST_HEAD (&rcvrRail->rcvr_freelist); -+ INIT_LIST_HEAD (&rcvrRail->rcvr_blocklist); -+ -+ kcondvar_init (&rcvrRail->rcvr_cleanup_sleep); -+ kcondvar_init (&rcvrRail->rcvr_freesleep); -+ -+ INIT_LIST_HEAD (&rcvrRail->rcvr_retrylist); -+ spin_lock_init (&rcvrRail->rcvr_retrylock); -+ -+ rcvrRail->rcvr_generic.CommsRail = commsRail; -+ rcvrRail->rcvr_generic.Rcvr = rcvr; -+ -+ rcvrRail->rcvr_main = ep_alloc_main (&rail->r_generic, sizeof (EP4_RCVR_RAIL_MAIN), 0, &rcvrRail->rcvr_main_addr); -+ rcvrRail->rcvr_elan = ep_alloc_elan (&rail->r_generic, sizeof (EP4_RCVR_RAIL_ELAN), 0, &rcvrRail->rcvr_elan_addr); -+ rcvrRail->rcvr_slots = ep_alloc_elan (&rail->r_generic, EP_INPUTQ_SIZE * rcvr->InputQueueEntries, 0, &rcvrRail->rcvr_slots_addr); -+ stack = ep_alloc_elan (&rail->r_generic, EP4_STACK_SIZE, 0, &rcvrRail->rcvr_stack); -+ -+ /* allocate a command queue for the thread to use, plus space for it to wait/reschedule */ -+ rcvrRail->rcvr_ecq = ep4_alloc_ecq (rail, CQ_Size64K); -+ rcvrRail->rcvr_resched = ep4_get_ecq (rail, EP4_ECQ_ATOMIC, 8); -+ -+ ep4_register_intcookie (rail, &rcvrRail->rcvr_stall_intcookie, rcvrRail->rcvr_elan_addr + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_stall_intcookie), -+ rcvr_stall_interrupt, rcvrRail); -+ -+ /* Initialise the elan portion */ -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_qevent.ev_CountAndType), 0); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_halt.ev_CountAndType), 0); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock), 0); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_pending_tailp), -+ rcvrRail->rcvr_elan_addr + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_pending_head)); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_pending_head), 0); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_stall_intcookie), 0); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_qbase), rcvrRail->rcvr_slots_addr); -+ elan4_sdram_writeq (dev, rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_qlast), -+ rcvrRail->rcvr_slots_addr + EP_INPUTQ_SIZE * (rcvr->InputQueueEntries-1)); -+ -+ /* Initialise the main memory portion */ -+ rcvrRail->rcvr_main->rcvr_thread_lock = 0; -+ -+ /* Install our retry handler */ -+ rcvrRail->rcvr_retryops.op_func = ep4rcvr_retry; -+ rcvrRail->rcvr_retryops.op_arg = rcvrRail; -+ -+ ep4_add_retry_ops (rail, &rcvrRail->rcvr_retryops); -+ -+ /* Update the queue desriptor */ -+ qdesc.q_bptr = rcvrRail->rcvr_slots_addr; -+ qdesc.q_fptr = rcvrRail->rcvr_slots_addr; -+ qdesc.q_control = E4_InputQueueControl (rcvrRail->rcvr_slots_addr, rcvrRail->rcvr_slots_addr + (EP_INPUTQ_SIZE * (rcvr->InputQueueEntries-1)), EP_INPUTQ_SIZE); -+ qdesc.q_event = rcvrRail->rcvr_elan_addr + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_qevent); -+ -+ ep4_write_qdesc (rail, qdescs + (rcvr->Service * EP_QUEUE_DESC_SIZE), &qdesc); -+ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ rcvr->Rails[rail->r_generic.Number] = &rcvrRail->rcvr_generic; -+ rcvr->RailMask |= EP_RAIL2RAILMASK (rail->r_generic.Number); -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ { -+ sdramaddr_t stackTop = stack + EP4_STACK_SIZE; -+ E4_Addr stackTopAddr = rcvrRail->rcvr_stack + EP4_STACK_SIZE; -+ -+ ep4_init_thread (rail, &tregs, stackTop, stackTopAddr, ep_symbol (&rail->r_threadcode, "ep4comms_rcvr"), 6, -+ (E4_uint64) rail->r_elan_addr, (E4_uint64) rcvrRail->rcvr_elan_addr, (E4_uint64) rcvrRail->rcvr_main_addr, -+ (E4_uint64) EP_MSGQ_ADDR(rcvr->Service), (E4_uint64) rcvrRail->rcvr_ecq->ecq_addr, (E4_uint64) rcvrRail->rcvr_resched->ecq_addr); -+ } -+ -+ /* Issue the command to the threads private command queue */ -+ elan4_run_thread_cmd (rcvrRail->rcvr_ecq->ecq_cq, &tregs); -+ -+ ep_procfs_rcvr_add_rail(&(rcvrRail->rcvr_generic)); -+} -+ -+void -+ep4rcvr_del_rail (EP_RCVR *rcvr, EP_COMMS_RAIL *commsRail) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->Rail; -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) rcvr->Rails[rail->r_generic.Number]; -+ ELAN4_HALTOP haltop; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ ep_procfs_rcvr_del_rail(&(rcvrRail->rcvr_generic)); -+ -+ /* Run a halt operation to mark the input queue as full and -+ * request the thread to halt */ -+ haltop.op_mask = INT_DiscardingHighPri | INT_TProcHalted; -+ haltop.op_function = rcvr_stall_haltop; -+ haltop.op_arg = rcvrRail; -+ -+ elan4_queue_haltop (rail->r_ctxt.ctxt_dev, &haltop); -+ -+ /* Wait for the thread to tell us it's processed the input queue */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ while (! rcvrRail->rcvr_thread_halted) -+ kcondvar_wait (&rcvrRail->rcvr_cleanup_sleep, &rcvr->Lock, &flags); -+ rcvrRail->rcvr_thread_halted = 0; -+ -+ /* flag the rail as no longer available */ -+ rcvr->RailMask &= ~EP_RAIL2RAILMASK (rail->r_generic.Number); -+ -+ /* wait for all active communications to terminate */ -+ for (;;) -+ { -+ int mustWait = 0; -+ -+ list_for_each (el, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ -+ if (rxdRail && RXD_BOUND2RAIL (rxdRail, rcvrRail) && rxd->RxdMain->Len != EP_RXD_PENDING) -+ { -+ mustWait++; -+ break; -+ } -+ } -+ -+ if (! mustWait) -+ break; -+ -+ rcvrRail->rcvr_cleanup_waiting++; -+ kcondvar_wait (&rcvrRail->rcvr_cleanup_sleep, &rcvr->Lock, &flags); -+ } -+ -+ /* at this point all rxd's in the list that are bound to the deleting rail are pending */ -+ list_for_each_safe (el, nel, &rcvr->ActiveDescList) { -+ EP_RXD *rxd = list_entry (el, EP_RXD, Link); -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) rxd->RxdRail; -+ -+ if (rxdRail && RXD_BOUND2RAIL (rxdRail, rcvrRail)) -+ { -+ EP4_RXD_ASSERT_PENDING (rxdRail); -+ EP4_RXD_FORCE_PRIVATE (rxdRail); -+ -+ unbind_rxd_rail (rxd, rxdRail); -+ free_rxd_rail (rcvrRail, rxdRail); -+ } -+ } -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* wait for all rxd's for this rail to become free */ -+ spin_lock_irqsave (&rcvrRail->rcvr_freelock, flags); -+ while (rcvrRail->rcvr_freecount != rcvrRail->rcvr_totalcount) -+ { -+ rcvrRail->rcvr_freewaiting++; -+ kcondvar_wait (&rcvrRail->rcvr_freesleep, &rcvrRail->rcvr_freelock, &flags); -+ } -+ spin_unlock_irqrestore (&rcvrRail->rcvr_freelock, flags); -+ -+ /* can now remove the rail as it can no longer be used */ -+ spin_lock_irqsave (&rcvr->Lock, flags); -+ rcvr->Rails[rail->r_generic.Number] = NULL; -+ spin_unlock_irqrestore (&rcvr->Lock, flags); -+ -+ /* all the rxd's accociated with DescBlocks must be in the FreeDescList */ -+ ASSERT (rcvrRail->rcvr_totalcount == rcvrRail->rcvr_freecount); -+ -+ /* run through the DescBlockList deleting them */ -+ while (!list_empty (&rcvrRail->rcvr_blocklist)) -+ free_rxd_block (rcvrRail, list_entry(rcvrRail->rcvr_blocklist.next, EP4_RXD_RAIL_BLOCK , blk_link)); -+ -+ /* it had better be empty after that */ -+ ASSERT ((rcvrRail->rcvr_totalcount == 0) && (rcvrRail->rcvr_totalcount == rcvrRail->rcvr_freecount)); -+ -+ ep4_remove_retry_ops (rail, &rcvrRail->rcvr_retryops); -+ -+ ep4_deregister_intcookie (rail, &rcvrRail->rcvr_stall_intcookie); -+ -+ ep4_put_ecq (rail, rcvrRail->rcvr_resched, 8); -+ ep4_free_ecq (rail, rcvrRail->rcvr_ecq); -+ -+ ep_free_elan (&rail->r_generic, rcvrRail->rcvr_stack, EP4_STACK_SIZE); -+ ep_free_elan (&rail->r_generic, rcvrRail->rcvr_slots_addr, EP_INPUTQ_SIZE * rcvr->InputQueueEntries); -+ ep_free_elan (&rail->r_generic, rcvrRail->rcvr_elan_addr, sizeof (EP4_RCVR_RAIL_ELAN)); -+ ep_free_main (&rail->r_generic, rcvrRail->rcvr_main_addr, sizeof (EP4_RCVR_RAIL_MAIN)); -+ -+ KMEM_FREE (rcvrRail, sizeof (EP4_RCVR_RAIL)); -+} -+ -+void -+ep4rcvr_display_rxd (DisplayInfo *di, EP_RXD_RAIL *r) -+{ -+ EP4_RXD_RAIL *rxdRail = (EP4_RXD_RAIL *) r; -+ sdramaddr_t rxdElan = rxdRail->rxd_elan; -+ EP4_RAIL *rail = RCVR_TO_RAIL (rxdRail->rxd_generic.RcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ int i; -+ -+ (di->func)(di->arg, " Rail %d rxd %p elan %lx(%x) main %p(%x) ecq %d scq %d debug %llx\n", rail->r_generic.Number, -+ rxdRail, rxdRail->rxd_elan, rxdRail->rxd_elan_addr, rxdRail->rxd_main, rxdRail->rxd_main_addr, -+ elan4_cq2num(rxdRail->rxd_ecq->ecq_cq), elan4_cq2num(rxdRail->rxd_scq->ecq_cq), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_debug))); -+ (di->func)(di->arg, " start %016llx %016llx %016llx [%016llx %016llx]\n", -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_CountAndType)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_Params[0])), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_start.ev_Params[1])), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[0].c_cookie)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[0].c_dma_cookie))); -+ -+ for (i = 0; i < EP_MAXFRAG; i++) -+ (di->func)(di->arg, " chain[%d] %016llx %016llx %016llx [%016llx %016llx]\n", i, -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[i].ev_CountAndType)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[i].ev_Params[0])), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_chain[i].ev_Params[1])), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[i+1].c_cookie)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_sten[i+1].c_dma_cookie))); -+ (di->func)(di->arg, " done %016llx %016llx %016llx -> %016llx\n", -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_CountAndType)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_Params[0])), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_done.ev_Params[1])), -+ rxdRail->rxd_main->rxd_done); -+ (di->func)(di->arg, " fail %016llx %016llx %016llx -> %016llx\n", -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_CountAndType)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_Params[0])), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_failed.ev_Params[1])), -+ rxdRail->rxd_main->rxd_failed); -+ (di->func)(di->arg, " next %016llx queued %016llx main %016llx\n", -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_next)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_queued)), -+ elan4_sdram_readq (dev, rxdElan + offsetof (EP4_RXD_RAIL_ELAN, rxd_main))); -+ (di->func)(di->arg, " sent %016llx %016llx %016llx %016llx %016llx\n", -+ rxdRail->rxd_main->rxd_sent[0], rxdRail->rxd_main->rxd_sent[1], rxdRail->rxd_main->rxd_sent[2], -+ rxdRail->rxd_main->rxd_sent[3], rxdRail->rxd_main->rxd_sent[4]); -+} -+ -+void -+ep4rcvr_display_rcvr (DisplayInfo *di, EP_RCVR_RAIL *r) -+{ -+ EP_RCVR *rcvr = r->Rcvr; -+ EP4_RCVR_RAIL *rcvrRail = (EP4_RCVR_RAIL *) r; -+ EP4_COMMS_RAIL *commsRail = RCVR_TO_COMMS(rcvrRail); -+ EP4_RAIL *rail = RCVR_TO_RAIL (rcvrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ sdramaddr_t rcvrElan = rcvrRail->rcvr_elan; -+ sdramaddr_t qdesc = commsRail->r_descs + (rcvr->Service * EP_QUEUE_DESC_SIZE); -+ sdramaddr_t event = rcvrRail->rcvr_elan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_qevent); -+ unsigned int freeCount = 0; -+ unsigned int blockCount = 0; -+ struct list_head *el; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rcvrRail->rcvr_freelock, flags); -+ list_for_each (el, &rcvrRail->rcvr_freelist) -+ freeCount++; -+ list_for_each (el, &rcvrRail->rcvr_blocklist) -+ blockCount++; -+ spin_unlock_irqrestore(&rcvrRail->rcvr_freelock, flags); -+ -+ (di->func)(di->arg, " Rail %d elan %lx(%x) main %p(%x) ecq %d resched %d debug %llx\n", -+ rail->r_generic.Number, rcvrRail->rcvr_elan, rcvrRail->rcvr_elan_addr, -+ rcvrRail->rcvr_main, rcvrRail->rcvr_main_addr, elan4_cq2num(rcvrRail->rcvr_ecq->ecq_cq), -+ elan4_cq2num (rcvrRail->rcvr_resched->ecq_cq), -+ elan4_sdram_readq (dev, rcvrElan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_debug))); -+ (di->func)(di->arg, " free %d (%d) total %d blocks %d\n", -+ rcvrRail->rcvr_freecount, freeCount, rcvrRail->rcvr_totalcount, blockCount); -+ (di->func)(di->arg, " spinlock %016llx %016llx\n", rcvrRail->rcvr_main->rcvr_thread_lock, -+ elan4_sdram_readq (dev, rcvrElan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_thread_lock))); -+ (di->func)(di->arg, " queue: bptr %016llx fptr %016llx control %016llx (base %lx %x)\n", -+ elan4_sdram_readq (dev, qdesc + offsetof (E4_InputQueue, q_bptr)), -+ elan4_sdram_readq (dev, qdesc + offsetof (E4_InputQueue, q_fptr)), -+ elan4_sdram_readq (dev, qdesc + offsetof (E4_InputQueue, q_control)), -+ rcvrRail->rcvr_slots, rcvrRail->rcvr_slots_addr); -+ (di->func)(di->arg, " event %016llx %016llx %016llx\n", -+ elan4_sdram_readq (dev, event + offsetof (E4_Event32, ev_CountAndType)), -+ elan4_sdram_readq (dev, event + offsetof (E4_Event32, ev_Params[0])), -+ elan4_sdram_readq (dev, event + offsetof (E4_Event32, ev_Params[1]))); -+ (di->func)(di->arg, " pending_tailp %016llx pending_head %016llx\n", -+ elan4_sdram_readq (dev, rcvrElan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_pending_tailp)), -+ elan4_sdram_readq (dev, rcvrElan + offsetof (EP4_RCVR_RAIL_ELAN, rcvr_pending_head))); -+} -+ -+void -+ep4rcvr_fillout_rail_stats(EP_RCVR_RAIL *rcvr_rail, char *str) { -+ /* no stats here yet */ -+ /* EP4_RCVR_RAIL * ep4rcvr_rail = (EP4_RCVR_RAIL *) rcvr_rail; */ -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsTx.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsTx.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsTx.c 2005-06-01 23:12:54.654430744 -0400 -@@ -0,0 +1,919 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsTx.c,v 1.25.2.5 2004/12/09 10:02:42 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsTx.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "cm.h" -+#include "debug.h" -+ -+unsigned int ep_txd_lowat = 5; -+ -+static int -+AllocateTxdBlock (EP_XMTR *xmtr, EP_ATTRIBUTE attr, EP_TXD **txdp) -+{ -+ EP_TXD_BLOCK *blk; -+ EP_TXD *txd; -+ EP_TXD_MAIN *pTxdMain; -+ int i; -+ unsigned long flags; -+ -+ EPRINTF1 (DBG_XMTR, "AllocateTxdBlock: xmtr=%p\n", xmtr); -+ -+ KMEM_ZALLOC (blk, EP_TXD_BLOCK *, sizeof (EP_TXD_BLOCK), ! (attr & EP_NO_SLEEP)); -+ -+ if (blk == NULL) -+ return -ENOMEM; -+ -+ if ((pTxdMain = ep_shared_alloc_main (xmtr->Subsys->Subsys.Sys, EP_TXD_MAIN_SIZE * EP_NUM_TXD_PER_BLOCK, attr, &blk->NmdMain)) == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (blk, sizeof (EP_TXD_BLOCK)); -+ return -ENOMEM; -+ } -+ -+ for (txd = &blk->Txd[0], i = 0; i < EP_NUM_TXD_PER_BLOCK; i++, txd++) -+ { -+ txd->Xmtr = xmtr; -+ txd->TxdMain = pTxdMain; -+ -+ ep_nmd_subset (&txd->NmdMain, &blk->NmdMain, (i * EP_TXD_MAIN_SIZE), EP_TXD_MAIN_SIZE); -+ -+ /* move onto next descriptor */ -+ pTxdMain = (EP_TXD_MAIN *) ((unsigned long) pTxdMain + EP_TXD_MAIN_SIZE); -+ } -+ -+ spin_lock_irqsave (&xmtr->FreeDescLock, flags); -+ -+ list_add (&blk->Link, &xmtr->DescBlockList); -+ xmtr->TotalDescCount += EP_NUM_TXD_PER_BLOCK; -+ -+ for (i = txdp ? 1 : 0; i < EP_NUM_TXD_PER_BLOCK; i++) -+ { -+ list_add (&blk->Txd[i].Link, &xmtr->FreeDescList); -+ -+ xmtr->FreeDescCount++; -+ -+ if (xmtr->FreeDescWanted) -+ { -+ xmtr->FreeDescWanted--; -+ kcondvar_wakeupone (&xmtr->FreeDescSleep, &xmtr->FreeDescLock); -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+ -+ if (txdp) -+ *txdp = &blk->Txd[0]; -+ -+ return 0; -+} -+ -+static void -+FreeTxdBlock (EP_XMTR *xmtr, EP_TXD_BLOCK *blk) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->FreeDescLock, flags); -+ list_del (&blk->Link); -+ -+ xmtr->TotalDescCount -= EP_NUM_RXD_PER_BLOCK; -+ xmtr->FreeDescCount -= EP_NUM_RXD_PER_BLOCK; -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+ -+ ep_shared_free_main (xmtr->Subsys->Subsys.Sys, &blk->NmdMain); -+ KMEM_FREE (blk, sizeof (EP_TXD_BLOCK)); -+} -+ -+static EP_TXD * -+GetTxd (EP_XMTR *xmtr, EP_ATTRIBUTE attr) -+{ -+ EP_COMMS_SUBSYS *subsys = xmtr->Subsys; -+ EP_TXD *txd; -+ int low_on_txds; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->FreeDescLock, flags); -+ -+ while (list_empty (&xmtr->FreeDescList)) -+ { -+ if (! (attr & EP_NO_ALLOC)) -+ { -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+ -+ if (AllocateTxdBlock (xmtr, attr, &txd) == ESUCCESS) -+ return (txd); -+ -+ spin_lock_irqsave (&xmtr->FreeDescLock, flags); -+ } -+ -+ if (attr & EP_NO_SLEEP) -+ { -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+ -+ return (NULL); -+ } -+ -+ xmtr->FreeDescWanted++; -+ kcondvar_wait (&xmtr->FreeDescSleep, &xmtr->FreeDescLock, &flags); -+ } -+ -+ txd = list_entry (xmtr->FreeDescList.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ /* Wakeup the descriptor primer thread if there's not many left */ -+ low_on_txds = (--xmtr->FreeDescCount < ep_txd_lowat); -+ -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+ -+ if (low_on_txds) -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ -+ return (txd); -+} -+ -+void -+FreeTxd (EP_XMTR *xmtr, EP_TXD *txd) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->FreeDescLock, flags); -+ -+ list_add (&txd->Link, &xmtr->FreeDescList); -+ -+ xmtr->FreeDescCount++; -+ -+ if (xmtr->FreeDescWanted) /* someone waiting for a receive */ -+ { /* descriptor, so wake them up */ -+ xmtr->FreeDescWanted--; -+ kcondvar_wakeupone (&xmtr->FreeDescSleep, &xmtr->FreeDescLock); -+ } -+ -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+} -+ -+int -+TxdShouldStabalise (EP_TXD_RAIL *txdRail, EP_RAIL *rail) -+{ -+ EP_TXD *txd = txdRail->Txd; -+ EP_XMTR *xmtr = txd->Xmtr; -+ EP_ATTRIBUTE attr = txd->Envelope.Attr; -+ int stabilise; -+ extern int txd_stabilise; -+ -+ switch (EP_ATTR2TYPE (attr)) -+ { -+ case EP_TYPE_SVC_INDICATOR: /* is the rail in the current service indicator rail mask */ -+ if ((txd_stabilise & 4) == 0) -+ return 0; -+ -+ stabilise = (ep_xmtr_svc_indicator_railmask (xmtr, EP_ATTR2DATA (attr), txd->NodeId) & EP_RAIL2RAILMASK (rail->Number)) == 0; -+ break; -+ -+ case EP_TYPE_TIMEOUT: -+ if ((txd_stabilise & 2) == 0) -+ return 0; -+ -+ stabilise = AFTER(lbolt, txdRail->Txd->TimeStamp + EP_ATTR2DATA(attr)); -+ break; -+ -+ default: -+ if ((txd_stabilise & 1) == 0) -+ return 0; -+ -+ stabilise = AFTER(lbolt, txdRail->Txd->TimeStamp + EP_DEFAULT_TIMEOUT); -+ break; -+ } -+ -+ if (stabilise) -+ { -+ txd->Envelope.Attr = EP_SET_TXD_STABALISING(txd->Envelope.Attr); -+ txd->RetryTime = lbolt; -+ -+ ep_kthread_schedule (&xmtr->Subsys->Thread, lbolt); -+ } -+ -+ return stabilise; -+} -+ -+void ep_xmtr_txd_stat(EP_XMTR *xmtr, EP_TXD *txd) -+{ -+ int f; -+ unsigned long size; -+ EP_TXD_RAIL *txdRail = txd->TxdRail; -+ -+ size = 0; -+ for (f=0; f < txd->Envelope.nFrags; f++) -+ size += txd->Envelope.Frags[f].nmd_len; -+ -+ INC_STAT(xmtr->stats,tx); -+ ADD_STAT(xmtr->stats,tx_len, size); -+ -+ if ((txdRail != NULL) && (txdRail->XmtrRail != NULL)){ -+ INC_STAT(txdRail->XmtrRail->stats,tx); -+ ADD_STAT(txdRail->XmtrRail->stats,tx_len, size); -+ -+ if ((txdRail->XmtrRail->CommsRail != NULL) && ( txdRail->XmtrRail->CommsRail->Rail != NULL)) { -+ INC_STAT(txdRail->XmtrRail->CommsRail->Rail->Stats,tx); -+ ADD_STAT(txdRail->XmtrRail->CommsRail->Rail->Stats,tx_len, size); -+ } -+ } -+} -+ -+static int -+PollActiveTransmitList (EP_XMTR *xmtr, int flag) -+{ -+ struct list_head *el, *nel; -+ struct list_head list; -+ unsigned long flags; -+ int count; -+ -+ INIT_LIST_HEAD (&list); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP_TXD_RAIL *txdRail = txd->TxdRail; -+ -+ if (txdRail == NULL) -+ continue; -+ -+ ASSERT (txdRail->Txd == txd); -+ -+ if (EP_XMTR_OP (txdRail->XmtrRail,PollTxd) (txdRail->XmtrRail, txdRail, flags)) -+ { -+ list_del (&txd->Link); /* remove from active transmit list */ -+ list_add_tail (&txd->Link, &list); /* and add to list to call handlers */ -+ } -+ } -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ for (count = 0; !list_empty (&list); count++) -+ { -+ EP_TXD *txd = list_entry (list.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ txd->Handler (txd, txd->Arg, EP_SUCCESS); -+ -+ FreeTxd (xmtr, txd); -+ } -+ return (count); -+} -+ -+static inline void -+DoTransmit (EP_XMTR *xmtr, EP_TXD *txd) -+{ -+ EP_RAILMASK nmdRailMask = ep_nmd2railmask (txd->Envelope.Frags, txd->Envelope.nFrags); -+ EP_XMTR_RAIL *xmtrRail; -+ unsigned long flags; -+ int rnum; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ if (EP_IS_SVC_INDICATOR(txd->Envelope.Attr)) -+ nmdRailMask = nmdRailMask & ep_xmtr_svc_indicator_railmask(xmtr, EP_ATTR2DATA(txd->Envelope.Attr), txd->NodeId); -+ -+ if (EP_IS_PREFRAIL_SET(txd->Envelope.Attr)) -+ rnum = EP_ATTR2PREFRAIL(txd->Envelope.Attr); -+ else -+ rnum = ep_xmtr_prefrail (xmtr, nmdRailMask, txd->NodeId); -+ -+ if (rnum < 0 || !(nmdRailMask & EP_RAIL2RAILMASK(rnum))) -+ xmtrRail = NULL; -+ else -+ xmtrRail = xmtr->Rails[rnum]; -+ -+ /* Allocate the XID while holding the xmtr->Lock from our XID cache */ -+ txd->Envelope.Xid = ep_xid_cache_alloc (xmtr->Subsys->Subsys.Sys, &xmtr->XidCache); -+ -+ EPRINTF7 (DBG_XMTR, "ep: transmit txd %p to %d/%d: Xid %llx nFrags %d [%08x.%d]\n", -+ txd, txd->NodeId, txd->Service, (long long) txd->Envelope.Xid.Unique, -+ txd->Envelope.nFrags, txd->Envelope.Frags[0].nmd_addr, txd->Envelope.Frags[0].nmd_len); -+ -+ /* Store time transmit started to timeout if not received */ -+ txd->TimeStamp = lbolt; -+ -+ /* Initialise the retry backoff */ -+ txd->Backoff.type = EP_BACKOFF_FREE; -+ -+ list_add_tail (&txd->Link, &xmtr->ActiveDescList); -+ -+ if (xmtrRail == NULL || !EP_XMTR_OP(xmtrRail,BindTxd) (txd, xmtrRail, EP_TXD_PHASE_ACTIVE)) -+ ep_kthread_schedule (&xmtr->Subsys->Thread, lbolt); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ if (EP_IS_NO_INTERRUPT(txd->Envelope.Attr)) -+ PollActiveTransmitList (xmtr, POLL_TX_LIST); -+} -+ -+EP_STATUS -+ep_transmit_message (EP_XMTR *xmtr, unsigned int dest, EP_SERVICE service, EP_ATTRIBUTE attr, -+ EP_TXH *handler, void *arg, EP_PAYLOAD *payload, EP_NMD *nmd, int nFrags) -+{ -+ EP_TXD *txd; -+ int i, len; -+ -+ if (nFrags > EP_MAXFRAG || service > EP_MSG_NSVC) -+ return (EP_EINVAL); -+ -+ if ((txd = GetTxd (xmtr, attr)) == NULL) -+ return (EP_ENOMEM); -+ -+ txd->Handler = handler; -+ txd->Arg = arg; -+ txd->Service = service; -+ txd->NodeId = (unsigned short) dest; -+ -+ /* Initialise the envelope */ -+ txd->Envelope.Version = EP_ENVELOPE_VERSION; -+ txd->Envelope.Attr = EP_CLEAR_LOCAL_ATTR(attr); -+ txd->Envelope.Range = EP_RANGE (dest, dest); -+ txd->Envelope.TxdMain = txd->NmdMain; -+ txd->Envelope.nFrags = nFrags; -+ -+ for (i = len = 0; i < nFrags; len += nmd[i].nmd_len, i++) -+ txd->Envelope.Frags[i] = nmd[i]; -+ -+ if (payload) -+ { -+ txd->Envelope.Attr = EP_SET_HAS_PAYLOAD(txd->Envelope.Attr); -+ -+ bcopy (payload, &txd->Payload, sizeof (EP_PAYLOAD)); -+ } -+ -+ DoTransmit (xmtr, txd); -+ -+ BucketStat (xmtr->Subsys, DataXmit, len); -+ -+ return (EP_SUCCESS); -+} -+ -+EP_STATUS -+ep_multicast_message (EP_XMTR *xmtr, unsigned int destLo, unsigned int destHi, bitmap_t *bitmap, EP_SERVICE service, -+ EP_ATTRIBUTE attr, EP_TXH *handler, void *arg, EP_PAYLOAD *payload, EP_NMD *nmd, int nFrags) -+{ -+ EP_SYS *sys = xmtr->Subsys->Subsys.Sys; -+ EP_TXD *txd; -+ int nnodes; -+ int i, len; -+ unsigned long flags; -+ -+ if (nFrags > EP_MAXFRAG || service > EP_MSG_NSVC) -+ return (EP_EINVAL); -+ -+ if (destLo == -1) -+ destLo = sys->Position.pos_nodeid & ~(EP_MAX_NODES-1); -+ -+ if (destHi == -1 && (destHi = ((sys->Position.pos_nodeid + EP_MAX_NODES) & ~(EP_MAX_NODES-1)) - 1) >= sys->Position.pos_nodes) -+ destHi = sys->Position.pos_nodes-1; -+ -+ nnodes = (destHi-destLo+1); -+ -+ if ((txd = GetTxd (xmtr, attr)) == NULL) -+ return (EP_ENOMEM); -+ -+ txd->Handler = handler; -+ txd->Arg = arg; -+ txd->Service = service; -+ -+ /* Initialise the envelope */ -+ txd->Envelope.Version = EP_ENVELOPE_VERSION; -+ txd->Envelope.Attr = EP_SET_MULTICAST(EP_CLEAR_LOCAL_ATTR(attr)); -+ txd->Envelope.Range = EP_RANGE (destLo, destHi); -+ txd->Envelope.TxdMain = txd->NmdMain; -+ txd->Envelope.nFrags = nFrags; -+ -+ for (i = len = 0; i < nFrags; len += nmd[i].nmd_len, i++) -+ txd->Envelope.Frags[i] = nmd[i]; -+ -+ if (payload) -+ { -+ txd->Envelope.Attr = EP_SET_HAS_PAYLOAD(txd->Envelope.Attr); -+ -+ bcopy (payload, &txd->Payload, sizeof (EP_PAYLOAD)); -+ } -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ if (EP_IS_SVC_INDICATOR(attr)) -+ ep_xmtr_svc_indicator_bitmap(xmtr, EP_ATTR2DATA(attr), txd->TxdMain->Bitmap, destLo, nnodes); -+ else -+ bt_subset (statemap_tobitmap(sys->NodeSet), txd->TxdMain->Bitmap, destLo, nnodes); -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ if (bitmap != NULL) /* bitmap supplied, so intersect it with */ -+ bt_intersect (txd->TxdMain->Bitmap, bitmap, nnodes); /* the current node set map */ -+ -+ if ((attr & EP_NOT_MYSELF) && destLo <= sys->Position.pos_nodeid && sys->Position.pos_nodeid <= destHi) -+ BT_CLEAR (txd->TxdMain->Bitmap, (sys->Position.pos_nodeid-destLo)); /* clear myself if not wanted */ -+ -+ if ((i = bt_lowbit (txd->TxdMain->Bitmap, nnodes)) < 0) -+ { -+ FreeTxd (xmtr, txd); -+ return (EP_NODE_DOWN); -+ } -+ -+ txd->NodeId = (unsigned short) i; -+ -+ DoTransmit (xmtr, txd); -+ -+ BucketStat (xmtr->Subsys, McastXmit, len); -+ -+ return (EP_SUCCESS); -+} -+ -+EP_STATUS -+ep_transmit_rpc (EP_XMTR *xmtr, unsigned int dest, EP_SERVICE service, EP_ATTRIBUTE attr, -+ EP_TXH *handler, void *arg, EP_PAYLOAD *payload, EP_NMD *nmd, int nFrags) -+{ -+ EP_TXD *txd; -+ int i, len; -+ -+ if (nFrags > EP_MAXFRAG || service > EP_MSG_NSVC) -+ return (EP_EINVAL); -+ -+ if ((txd = GetTxd (xmtr, attr)) == NULL) -+ return (EP_ENOMEM); -+ -+ txd->Handler = handler; -+ txd->Arg = arg; -+ txd->Service = service; -+ txd->NodeId = dest; -+ -+ /* Initialise the envelope */ -+ txd->Envelope.Version = EP_ENVELOPE_VERSION; -+ txd->Envelope.Attr = EP_SET_RPC(EP_CLEAR_LOCAL_ATTR(attr)); -+ txd->Envelope.Range = EP_RANGE (dest, dest); -+ txd->Envelope.TxdMain = txd->NmdMain; -+ txd->Envelope.nFrags = nFrags; -+ -+ for (i = len = 0; i < nFrags; len += nmd[i].nmd_len, i++) -+ txd->Envelope.Frags[i] = nmd[i]; -+ -+ if (payload) -+ { -+ txd->Envelope.Attr = EP_SET_HAS_PAYLOAD(txd->Envelope.Attr); -+ -+ bcopy (payload, &txd->Payload, sizeof (EP_PAYLOAD)); -+ } -+ -+ DoTransmit (xmtr, txd); -+ -+ BucketStat (xmtr->Subsys, RPCXmit, len); -+ -+ return (EP_SUCCESS); -+} -+ -+EP_STATUS -+ep_multicast_forward (EP_XMTR *xmtr, unsigned int dest, EP_SERVICE service, EP_ATTRIBUTE attr, EP_TXH *handler, void *arg, -+ EP_ENVELOPE *env, EP_PAYLOAD *payload, bitmap_t *bitmap, EP_NMD *nmd, int nFrags) -+{ -+ EP_TXD *txd; -+ int i, len; -+ -+ if (nFrags > EP_MAXFRAG || service > EP_MSG_NSVC) -+ return (EP_EINVAL); -+ -+ if ((txd = GetTxd (xmtr, attr)) == NULL) -+ return (EP_ENOMEM); -+ -+ txd->Handler = handler; -+ txd->Arg = arg; -+ txd->Service = service; -+ txd->NodeId = (unsigned short) dest; -+ -+ /* Initialise the envelope */ -+ txd->Envelope.Version = EP_ENVELOPE_VERSION; -+ txd->Envelope.Attr = EP_SET_MULTICAST(EP_CLEAR_LOCAL_ATTR(attr)); -+ txd->Envelope.Range = env->Range; -+ txd->Envelope.TxdMain = txd->NmdMain; -+ txd->Envelope.nFrags = nFrags; -+ -+ for (i = len = 0; i < nFrags; len += nmd[i].nmd_len, i++) -+ txd->Envelope.Frags[i] = nmd[i]; -+ -+ bt_copy (bitmap, txd->TxdMain->Bitmap, EP_RANGE_HIGH(env->Range) - EP_RANGE_LOW(env->Range) + 1); -+ -+ if (payload) -+ { -+ txd->Envelope.Attr = EP_SET_HAS_PAYLOAD(txd->Envelope.Attr); -+ -+ bcopy (payload, &txd->Payload, sizeof (EP_PAYLOAD)); -+ } -+ -+ DoTransmit (xmtr, txd); -+ -+ BucketStat (xmtr->Subsys, McastXmit, len); -+ -+ return (EP_SUCCESS); -+} -+ -+int -+ep_poll_transmits (EP_XMTR *xmtr) -+{ -+ return (PollActiveTransmitList (xmtr, POLL_TX_LIST)); -+} -+ -+int -+ep_enable_txcallbacks (EP_XMTR *xmtr) -+{ -+ return (PollActiveTransmitList (xmtr, ENABLE_TX_CALLBACK)); -+} -+ -+int -+ep_disable_txcallbacks (EP_XMTR *xmtr) -+{ -+ return (PollActiveTransmitList (xmtr, DISABLE_TX_CALLBACK)); -+} -+ -+/* functions for accessing fields of txds */ -+int ep_txd_node(EP_TXD *txd) { return (txd->NodeId); } -+EP_STATUSBLK *ep_txd_statusblk(EP_TXD *txd) { return (&txd->TxdMain->StatusBlk); } -+ -+void -+ep_xmtr_xid_msg_handler (void *arg, EP_MANAGER_MSG *msg) -+{ -+ EP_XMTR *xmtr = (EP_XMTR *) arg; -+ EP_SYS *sys = xmtr->Subsys->Subsys.Sys; -+ struct list_head *el,*nel; -+ unsigned long flags; -+ -+ switch (msg->Hdr.Type) -+ { -+ case EP_MANAGER_MSG_TYPE_FAILOVER_REQUEST: -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each (el, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP_TXD_RAIL *txdRail = txd->TxdRail; -+ -+ if (txdRail != NULL && EP_XIDS_MATCH (msg->Body.Failover.Xid, txd->Envelope.Xid)) -+ { -+ EP_XMTR_RAIL *xmtrRail = txdRail->XmtrRail; -+ EP_RAIL *rail = xmtrRail->CommsRail->Rail; -+ EP_MANAGER_MSG_BODY msgBody; -+ int rnum; -+ -+ if (! (msg->Body.Failover.Railmask & EP_RAIL2RAILMASK (rail->Number))) -+ { -+ /* Need to failover this txd to a different rail, select a rail from -+ * the set that she has asked us to use and which is connected to her -+ * on this transmitter. If there are no such rails, then in all probability -+ * we're offline on all common rails and eventually she will see we have no -+ * rails in common and abort the receive. */ -+ if ((rnum = ep_xmtr_prefrail (xmtr, msg->Body.Failover.Railmask, txd->NodeId)) < 0) -+ ep_debugf (DBG_XMTR, "%s: ep_xmtr_xid_msg_handler: FAILOVER_REQUEST but can't determine rail (%04x,%04x,%d,%04x)\n", -+ rail->Name, msg->Body.Failover.Railmask, xmtr->RailMask, txd->NodeId, sys->Nodes[txd->NodeId].ConnectedRails); -+ else -+ { -+ EP_XMTR_RAIL *nXmtrRail = xmtr->Rails[rnum]; -+ -+ EPRINTF4 (DBG_XMTR, "%s: ep_xmtr_xid_msg_handler: FAILOVER_REQUEST txd=%p XID=%llx-> rail %d\n", rail->Name, txd, (long long) txd->Envelope.Xid.Unique, rnum); -+ -+ /* Bind the txd rail onto the new rail - it doesn't matter if we fail -+ * as it will remain bound to the original rail */ -+ (void) EP_XMTR_OP (nXmtrRail, BindTxd) (txd, nXmtrRail, EP_TXD_PHASE_PASSIVE); -+ } -+ } -+ -+ /* Send a failover response including an envelope update */ -+ msgBody.FailoverTxd.Rail = rail->Number; -+ msgBody.FailoverTxd.Xid = txd->Envelope.Xid; -+ msgBody.FailoverTxd.TxdRail = txd->Envelope.TxdRail; -+ -+ ep_send_message (rail, msg->Hdr.NodeId, EP_MANAGER_MSG_TYPE_FAILOVER_RESPONSE, msg->Hdr.Xid, &msgBody); -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_GET_NODE_STATE_RESPONSE: { -+ int txd_has_not_sent_envelope = 0; -+ EP_TXD *txd = NULL; -+ EP_TXD_RAIL *txdRail = NULL; -+ -+ if (msg->Body.NodeState.NetworkErrorState != 0) -+ ep_kthread_schedule (&xmtr->Subsys->Thread, lbolt + MESSAGE_RETRY_TIME); -+ else -+ { -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ -+ txd = list_entry (el, EP_TXD, Link); -+ txdRail = txd->TxdRail; -+ -+ if (txdRail != NULL && EP_XIDS_MATCH (msg->Hdr.Xid, txd->Envelope.Xid)) { -+ txd_has_not_sent_envelope = EP_XMTR_OP(txdRail->XmtrRail,CheckTxdState)(txd); -+ break; -+ } -+ } -+ -+ if (txd_has_not_sent_envelope) { -+ EPRINTF2 (DBG_STABILISE, "ep_xmtr_xid_msg_handler: GET_NODE_STATE_RESPONSE txd=%p XID=%llx not sent envelope\n", -+ txd, (long long) txd->Envelope.Xid.Unique); -+ -+ /* at this point it has finished stabalising */ -+ txd->Envelope.Attr = EP_CLEAR_TXD_STABALISING(txd->Envelope.Attr); -+ -+ /* store railmask into txd if not a service indicator or timeout */ -+ if (EP_IS_NO_TYPE(txd->Envelope.Attr)) -+ txd->Envelope.Attr = EP_SET_DATA(txd->Envelope.Attr, EP_TYPE_RAILMASK, msg->Body.NodeState.Railmask); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ /* TXD is now no longer bound to a rail , so let ep_check_xmtr() handle it */ -+ ep_kthread_schedule (&xmtr->Subsys->Thread, lbolt); -+ } -+ else -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ } -+ break; -+ } -+ default: -+ panic ("ep_xmtr_xid_msg_handler: XID match but invalid message type\n"); -+ } -+} -+ -+EP_XMTR * -+ep_alloc_xmtr (EP_SYS *sys) -+{ -+ EP_COMMS_SUBSYS *subsys; -+ EP_XMTR *xmtr; -+ struct list_head *el; -+ -+ if ((subsys = (EP_COMMS_SUBSYS *) ep_subsys_find (sys, EPCOMMS_SUBSYS_NAME)) == NULL) -+ return (NULL); -+ -+ KMEM_ZALLOC (xmtr, EP_XMTR *, sizeof (EP_XMTR), 1); -+ -+ if (xmtr == NULL) -+ return (NULL); -+ -+ xmtr->Subsys = subsys; -+ -+ spin_lock_init (&xmtr->Lock); -+ INIT_LIST_HEAD (&xmtr->ActiveDescList); -+ -+ kcondvar_init (&xmtr->FreeDescSleep); -+ spin_lock_init (&xmtr->FreeDescLock); -+ INIT_LIST_HEAD (&xmtr->FreeDescList); -+ INIT_LIST_HEAD (&xmtr->DescBlockList); -+ -+ ep_xid_cache_init (sys, &xmtr->XidCache); -+ -+ xmtr->XidCache.MessageHandler = ep_xmtr_xid_msg_handler; -+ xmtr->XidCache.Arg = xmtr; -+ -+ kmutex_lock (&subsys->Lock); -+ list_add_tail (&xmtr->Link, &subsys->Transmitters); -+ -+ ep_procfs_xmtr_add(xmtr); -+ -+ /* Now add all rails which are already started */ -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ EP_RAIL_OP(commsRail, Xmtr.AddRail) (xmtr, commsRail); -+ } -+ kmutex_unlock (&subsys->Lock); -+ -+ ep_mod_inc_usecount(); -+ -+ return (xmtr); -+} -+ -+void -+ep_free_xmtr (EP_XMTR *xmtr) -+{ -+ EP_COMMS_SUBSYS *subsys = xmtr->Subsys; -+ EP_SYS *sys = subsys->Subsys.Sys; -+ struct list_head *el; -+ -+ kmutex_lock (&subsys->Lock); -+ list_for_each (el, &subsys->Rails) { -+ EP_COMMS_RAIL *rail = list_entry (el, EP_COMMS_RAIL, Link); -+ -+ EP_RAIL_OP(rail,Xmtr.DelRail) (xmtr, rail); -+ } -+ -+ list_del (&xmtr->Link); -+ kmutex_unlock (&subsys->Lock); -+ -+ /* all the desc's must be free */ -+ ASSERT(xmtr->FreeDescCount == xmtr->TotalDescCount); -+ -+ /* delete the descs */ -+ while (!list_empty (&xmtr->DescBlockList)) -+ FreeTxdBlock( xmtr, list_entry(xmtr->DescBlockList.next, EP_TXD_BLOCK , Link)); -+ -+ /* they had better all be gone now */ -+ ASSERT((xmtr->FreeDescCount == 0) && (xmtr->TotalDescCount == 0)); -+ -+ ep_procfs_xmtr_del(xmtr); -+ -+ ep_xid_cache_destroy (sys, &xmtr->XidCache); -+ -+ spin_lock_destroy (&xmtr->Lock); -+ KMEM_FREE (xmtr, sizeof (EP_XMTR)); -+ -+ ep_mod_dec_usecount(); -+} -+ -+long -+ep_check_xmtr (EP_XMTR *xmtr, long nextRunTime) -+{ -+ EP_COMMS_SUBSYS *subsys = xmtr->Subsys; -+ EP_SYS *sys = subsys->Subsys.Sys; -+ struct list_head *el, *nel; -+ struct list_head txdList; -+ unsigned long flags; -+ int timed_out=0; -+ int i; -+ EP_MANAGER_MSG_BODY body; -+ -+ INIT_LIST_HEAD (&txdList); -+ -+ /* See if we have any txd's which need to be bound to a rail */ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP_NODE *node = &sys->Nodes[txd->NodeId]; -+ EP_RAILMASK nodeRails = node->ConnectedRails & xmtr->RailMask; -+ EP_ENVELOPE *env = &txd->Envelope; -+ -+ if (EP_IS_TXD_STABALISING(txd->Envelope.Attr)) -+ { -+ ASSERT(txd->TxdRail != NULL); -+ -+ if (AFTER (lbolt, txd->RetryTime)) -+ { -+ EPRINTF6 (DBG_STABILISE, "ep_check_xmtr txd=%p txdRail=%p send get node state to %d Xid=%08x.%08x.%016llx\n", -+ txd, txd->TxdRail, txd->NodeId, env->Xid.Generation, env->Xid.Handle, env->Xid.Unique); -+ -+ body.Service = txd->Service; -+ if (ep_send_message ( txd->TxdRail->XmtrRail->CommsRail->Rail, txd->NodeId, EP_MANAGER_MSG_TYPE_GET_NODE_STATE, env->Xid, &body) == 0) -+ txd->RetryTime = lbolt + (MESSAGE_RETRY_TIME << ep_backoff (&txd->Backoff, EP_BACKOFF_STABILISE)); -+ else -+ txd->RetryTime = lbolt + MSGBUSY_RETRY_TIME; -+ } -+ -+ ep_kthread_schedule (&subsys->Thread, txd->RetryTime); -+ continue; -+ } -+ -+ if (txd->TxdRail != NULL) -+ continue; -+ -+ switch (EP_ATTR2TYPE(txd->Envelope.Attr)) -+ { -+ case EP_TYPE_SVC_INDICATOR: -+ { -+ EP_RAILMASK rmask=0; -+ struct list_head *tmp; -+ -+ list_for_each (tmp, &subsys->Rails) { -+ EP_COMMS_RAIL *commsRail = list_entry (tmp, EP_COMMS_RAIL, Link); -+ if ( cm_svc_indicator_is_set(commsRail->Rail, EP_ATTR2DATA(txd->Envelope.Attr), txd->NodeId)) -+ rmask |= EP_RAIL2RAILMASK(commsRail->Rail->Number); -+ } -+ nodeRails &= rmask; -+ break; -+ } -+ case EP_TYPE_TIMEOUT: -+ timed_out = AFTER(lbolt, txd->TimeStamp + EP_ATTR2DATA(txd->Envelope.Attr)) ? (1) : (0); -+ break; -+ case EP_TYPE_RAILMASK: -+ nodeRails &= EP_ATTR2DATA(txd->Envelope.Attr); -+ break; -+ default: -+ timed_out = AFTER(lbolt, txd->TimeStamp + EP_DEFAULT_TIMEOUT) ? (1) : (0); -+ break; -+ } -+ -+ if (nodeRails == 0 || timed_out || (EP_IS_NO_FAILOVER(env->Attr) && EP_IS_PREFRAIL_SET(env->Attr) && -+ (nodeRails & EP_RAIL2RAILMASK(EP_ATTR2PREFRAIL(env->Attr))) == 0)) -+ { -+ EPRINTF5 (timed_out ? DBG_STABILISE : DBG_XMTR, "ep_check_xmtr: txd=%p XID=%llx to %d no rails connected or cannot failover (nodeRails=0x%x,timed_out=%d\n", -+ txd, (long long) env->Xid.Unique, txd->NodeId, nodeRails, timed_out); -+ -+ list_del (&txd->Link); -+ list_add_tail (&txd->Link, &txdList); -+ } -+ else -+ { -+ EP_XMTR_RAIL *xmtrRail; -+ int i, len, rnum; -+ -+ if (EP_IS_PREFRAIL_SET(env->Attr) && (nodeRails & EP_RAIL2RAILMASK(EP_ATTR2PREFRAIL(env->Attr)))) -+ rnum = EP_ATTR2PREFRAIL(env->Attr); -+ else -+ rnum = ep_pickRail (nodeRails); -+ -+ EPRINTF3 (DBG_XMTR, "ep_check_xmtr: txd=%p XID=%llx mapping NMDs onto rail %d \n", txd, (long long) env->Xid.Unique, rnum); -+ -+ for (i = len = 0; i < env->nFrags; i++, len += env->Frags[i].nmd_len) -+ ep_nmd_map_rails (sys, &env->Frags[i], nodeRails); -+ -+ if ((xmtrRail = xmtr->Rails[rnum]) == NULL || -+ !EP_XMTR_OP(xmtrRail,BindTxd) (txd, xmtrRail, EP_TXD_PHASE_ACTIVE)) -+ ep_kthread_schedule (&subsys->Thread, lbolt + RESOURCE_RETRY_TIME); -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ while (! list_empty (&txdList)) -+ { -+ EP_TXD *txd = list_entry (txdList.next, EP_TXD, Link); -+ list_del (&txd->Link); -+ -+ txd->Handler (txd, txd->Arg, EP_NODE_DOWN); -+ FreeTxd (xmtr, txd); -+ } -+ -+ /* Check to see if we're low on txds */ -+ if (xmtr->FreeDescCount < ep_txd_lowat) -+ AllocateTxdBlock (xmtr, 0, NULL); -+ -+ /* Then check each rail */ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (xmtr->RailMask & (1 << i) ) -+ nextRunTime = EP_XMTR_OP (xmtr->Rails[i],Check) (xmtr->Rails[i], nextRunTime); -+ return (nextRunTime); -+} -+ -+void -+ep_display_txd (DisplayInfo *di, EP_TXD *txd) -+{ -+ EP_ENVELOPE *env = &txd->Envelope; -+ EP_TXD_RAIL *txdRail = txd->TxdRail; -+ -+ (di->func)(di->arg, "TXD: %p Version=%x Attr=%x Xid=%08x.%08x.%016llx\n", txd, -+ env->Version, env->Attr, env->Xid.Generation, env->Xid.Handle, (long long) env->Xid.Unique); -+ (di->func)(di->arg, " NodeId=%d Range=%d.%d TxdRail=%x TxdMain=%x.%x.%x nFrags=%d\n", -+ env->NodeId, EP_RANGE_LOW(env->Range), EP_RANGE_HIGH(env->Range), env->TxdRail, -+ env->TxdMain.nmd_addr, env->TxdMain.nmd_len, env->TxdMain.nmd_attr, env->nFrags); -+ (di->func)(di->arg, " Frag[0] %08x.%08x.%08x\n", env->Frags[0].nmd_addr, env->Frags[0].nmd_len, env->Frags[0].nmd_attr); -+ (di->func)(di->arg, " Frag[1] %08x.%08x.%08x\n", env->Frags[1].nmd_addr, env->Frags[1].nmd_len, env->Frags[1].nmd_attr); -+ (di->func)(di->arg, " Frag[2] %08x.%08x.%08x\n", env->Frags[2].nmd_addr, env->Frags[2].nmd_len, env->Frags[2].nmd_attr); -+ (di->func)(di->arg, " Frag[3] %08x.%08x.%08x\n", env->Frags[3].nmd_addr, env->Frags[3].nmd_len, env->Frags[3].nmd_attr); -+ -+ if (txdRail != NULL) EP_XMTR_OP (txdRail->XmtrRail, DisplayTxd) (di, txdRail); -+} -+ -+void -+ep_display_xmtr (DisplayInfo *di, EP_XMTR *xmtr) -+{ -+ int freeCount = 0; -+ int activeCount = 0; -+ struct list_head *el; -+ int i; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->FreeDescLock, flags); -+ list_for_each (el, &xmtr->FreeDescList) -+ freeCount++; -+ spin_unlock_irqrestore (&xmtr->FreeDescLock, flags); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each (el, &xmtr->ActiveDescList) -+ activeCount++; -+ -+ (di->func)(di->arg, "ep_display_xmtr: xmtr=%p Free=%d Active=%d\n", xmtr, freeCount, activeCount); -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (xmtr->Rails[i]) EP_XMTR_OP (xmtr->Rails[i], DisplayXmtr) (di, xmtr->Rails[i]); -+ -+ list_for_each (el,&xmtr->ActiveDescList) -+ ep_display_txd (di, list_entry (el, EP_TXD, Link)); -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+} -+ -+void -+ep_xmtr_fillout_stats(EP_XMTR *xmtr, char *str) -+{ -+ sprintf(str+strlen(str),"Tx %lu %lu /sec\n", GET_STAT_TOTAL(xmtr->stats,tx), GET_STAT_PER_SEC(xmtr->stats,tx) ); -+ sprintf(str+strlen(str),"MBytes %lu %lu Mbytes/sec\n", GET_STAT_TOTAL(xmtr->stats,tx_len) / (1024*1024), GET_STAT_PER_SEC(xmtr->stats,tx_len) / (1024*1024)); -+} -+ -+void -+ep_xmtr_rail_fillout_stats(EP_XMTR_RAIL *xmtr_rail, char *str) -+{ -+ sprintf(str+strlen(str),"Tx %lu %lu /sec\n", GET_STAT_TOTAL(xmtr_rail->stats,tx), GET_STAT_PER_SEC(xmtr_rail->stats,tx) ); -+ sprintf(str+strlen(str),"MBytes %lu %lu Mbytes/sec\n", GET_STAT_TOTAL(xmtr_rail->stats,tx_len) / (1024*1024), GET_STAT_PER_SEC(xmtr_rail->stats,tx_len) / (1024*1024)); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsTx_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsTx_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsTx_elan3.c 2005-06-01 23:12:54.657430288 -0400 -@@ -0,0 +1,1173 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsTx_elan3.c,v 1.17.2.2 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsTx_elan3.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "epcomms_elan3.h" -+#include "debug.h" -+ -+#define XMTR_TO_RAIL(xmtrRail) ((EP3_RAIL *) ((EP_XMTR_RAIL *) xmtrRail)->CommsRail->Rail) -+#define XMTR_TO_DEV(xmtrRail) (XMTR_TO_RAIL(xmtrRail)->Device) -+#define XMTR_TO_SUBSYS(xmtrRail) (((EP_XMTR_RAIL *) xmtrRail)->Xmtr->Subsys) -+ -+static void TxEnveEvent (EP3_RAIL *rail, void *arg); -+static void TxEnveRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status); -+static void TxEnveVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma); -+ -+static EP3_COOKIE_OPS EnveCookieOps = -+{ -+ TxEnveEvent, -+ TxEnveRetry, -+ NULL, /* DmaCancelled */ -+ TxEnveVerify -+}; -+ -+static void TxDataEvent (EP3_RAIL *rail, void *arg); -+static void TxDataRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status); -+static void TxDataVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma); -+ -+static EP3_COOKIE_OPS DataCookieOps = -+{ -+ TxDataEvent, -+ TxDataRetry, -+ NULL, /* DmaCancelled */ -+ TxDataVerify -+}; -+ -+static void TxDoneEvent (EP3_RAIL *dev, void *arg); -+static void TxDoneRetry (EP3_RAIL *dev, void *arg, E3_DMA_BE *dma, int status); -+static void TxDoneVerify (EP3_RAIL *dev, void *arg, E3_DMA_BE *dma); -+ -+static EP3_COOKIE_OPS DoneCookieOps = -+{ -+ TxDoneEvent, -+ TxDoneRetry, -+ NULL, /* DmaCancelled */ -+ TxDoneVerify, -+} ; -+ -+static int -+AllocateTxdRailBlock (EP3_XMTR_RAIL *xmtrRail) -+{ -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ ELAN3_DEV *dev = rail->Device; -+ EP3_TXD_RAIL_BLOCK *blk; -+ EP3_TXD_RAIL *txdRail; -+ sdramaddr_t pTxdElan; -+ EP3_TXD_RAIL_MAIN *pTxdMain; -+ E3_Addr pTxdElanAddr; -+ E3_Addr pTxdMainAddr; -+ E3_BlockCopyEvent event; -+ int i; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (blk, EP3_TXD_RAIL_BLOCK *, sizeof (EP3_TXD_RAIL_BLOCK), 1); -+ -+ if (blk == NULL) -+ return 0; -+ -+ if ((pTxdElan = ep_alloc_elan (&rail->Generic, EP3_TXD_RAIL_ELAN_SIZE * EP3_NUM_TXD_PER_BLOCK, 0, &pTxdElanAddr)) == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (blk, sizeof (EP3_TXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if ((pTxdMain = ep_alloc_main (&rail->Generic, EP3_TXD_RAIL_MAIN_SIZE * EP3_NUM_TXD_PER_BLOCK, 0, &pTxdMainAddr)) == (EP3_TXD_RAIL_MAIN *) NULL) -+ { -+ ep_free_elan (&rail->Generic, pTxdElanAddr, EP3_TXD_RAIL_ELAN_SIZE * EP3_NUM_TXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP3_TXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if (ReserveDmaRetries (rail, EP3_NUM_TXD_PER_BLOCK, 0) != ESUCCESS) -+ { -+ ep_free_main (&rail->Generic, pTxdMainAddr, EP3_TXD_RAIL_MAIN_SIZE * EP3_NUM_TXD_PER_BLOCK); -+ ep_free_elan (&rail->Generic, pTxdElanAddr, EP3_TXD_RAIL_ELAN_SIZE * EP3_NUM_TXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP3_TXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ for (txdRail = &blk->Txd[0], i = 0; i < EP3_NUM_TXD_PER_BLOCK; i++, txdRail++) -+ { -+ txdRail->Generic.XmtrRail = &xmtrRail->Generic; -+ txdRail->TxdElan = pTxdElan; -+ txdRail->TxdElanAddr = pTxdElanAddr; -+ txdRail->TxdMain = pTxdMain; -+ txdRail->TxdMainAddr = pTxdMainAddr; -+ -+ RegisterCookie (&rail->CookieTable, &txdRail->EnveCookie, pTxdElanAddr + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent), &EnveCookieOps, (void *) txdRail); -+ RegisterCookie (&rail->CookieTable, &txdRail->DataCookie, pTxdElanAddr + offsetof (EP3_TXD_RAIL_ELAN, DataEvent), &DataCookieOps, (void *) txdRail); -+ RegisterCookie (&rail->CookieTable, &txdRail->DoneCookie, pTxdElanAddr + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent), &DoneCookieOps, (void *) txdRail); -+ -+ EP3_INIT_COPY_EVENT (event, txdRail->EnveCookie, pTxdMainAddr + offsetof (EP3_TXD_RAIL_MAIN, EnveEvent), 0); -+ elan3_sdram_copyl_to_sdram (dev, &event, pTxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent), sizeof (E3_BlockCopyEvent)); -+ -+ EP3_INIT_COPY_EVENT (event, txdRail->DataCookie, pTxdMainAddr + offsetof (EP3_TXD_RAIL_MAIN, DataEvent), 0); -+ elan3_sdram_copyl_to_sdram (dev, &event, pTxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent), sizeof (E3_BlockCopyEvent)); -+ -+ EP3_INIT_COPY_EVENT (event, txdRail->DoneCookie, pTxdMainAddr + offsetof (EP3_TXD_RAIL_MAIN, DoneEvent), 0); -+ elan3_sdram_copyl_to_sdram (dev, &event, pTxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent), sizeof (E3_BlockCopyEvent)); -+ -+ pTxdMain->EnveEvent = EP3_EVENT_FREE; -+ pTxdMain->DataEvent = EP3_EVENT_FREE; -+ pTxdMain->DoneEvent = EP3_EVENT_FREE; -+ -+ /* move onto next descriptor */ -+ pTxdElan += EP3_TXD_RAIL_ELAN_SIZE; -+ pTxdElanAddr += EP3_TXD_RAIL_ELAN_SIZE; -+ pTxdMain = (EP3_TXD_RAIL_MAIN *) ((unsigned long) pTxdMain + EP3_TXD_RAIL_MAIN_SIZE); -+ pTxdMainAddr += EP3_TXD_RAIL_MAIN_SIZE; -+ } -+ -+ spin_lock_irqsave (&xmtrRail->FreeDescLock, flags); -+ -+ list_add (&blk->Link, &xmtrRail->DescBlockList); -+ xmtrRail->TotalDescCount += EP3_NUM_TXD_PER_BLOCK; -+ xmtrRail->FreeDescCount += EP3_NUM_TXD_PER_BLOCK; -+ -+ for (i = 0; i < EP3_NUM_TXD_PER_BLOCK; i++) -+ list_add (&blk->Txd[i].Generic.Link, &xmtrRail->FreeDescList); -+ -+ spin_unlock_irqrestore (&xmtrRail->FreeDescLock, flags); -+ -+ return 1; -+} -+ -+static void -+FreeTxdRailBlock (EP3_XMTR_RAIL *xmtrRail, EP3_TXD_RAIL_BLOCK *blk) -+{ -+ EP3_RAIL *rail = XMTR_TO_RAIL(xmtrRail); -+ EP3_TXD_RAIL *txdRail; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&xmtrRail->FreeDescLock, flags); -+ -+ list_del (&blk->Link); -+ -+ xmtrRail->TotalDescCount -= EP3_NUM_TXD_PER_BLOCK; -+ -+ for (txdRail = &blk->Txd[0], i = 0; i < EP3_NUM_TXD_PER_BLOCK; i++, txdRail++) -+ { -+ xmtrRail->FreeDescCount--; -+ -+ list_del (&txdRail->Generic.Link); -+ -+ DeregisterCookie (&rail->CookieTable, &txdRail->EnveCookie); -+ DeregisterCookie (&rail->CookieTable, &txdRail->DataCookie); -+ DeregisterCookie (&rail->CookieTable, &txdRail->DoneCookie); -+ } -+ -+ spin_unlock_irqrestore (&xmtrRail->FreeDescLock, flags); -+ -+ ReleaseDmaRetries (rail, EP3_NUM_TXD_PER_BLOCK); -+ -+ ep_free_main (&rail->Generic, blk->Txd[0].TxdMainAddr, EP3_TXD_RAIL_MAIN_SIZE * EP3_NUM_TXD_PER_BLOCK); -+ ep_free_elan (&rail->Generic, blk->Txd[0].TxdElanAddr, EP3_TXD_RAIL_ELAN_SIZE * EP3_NUM_TXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP3_TXD_RAIL_BLOCK)); -+} -+ -+static EP3_TXD_RAIL * -+GetTxdRail (EP3_XMTR_RAIL *xmtrRail) -+{ -+ EP_COMMS_SUBSYS *subsys = xmtrRail->Generic.Xmtr->Subsys; -+ EP3_TXD_RAIL *txdRail; -+ int low_on_txds; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtrRail->FreeDescLock, flags); -+ -+ if (list_empty (&xmtrRail->FreeDescList)) -+ txdRail = NULL; -+ else -+ { -+ txdRail = list_entry (xmtrRail->FreeDescList.next, EP3_TXD_RAIL, Generic.Link); -+ -+#if defined(DEBUG) -+ { -+ EP_RAIL *rail = xmtrRail->Generic.CommsRail->Rail; -+ ELAN3_DEV *dev = ((EP3_RAIL *) rail)->Device; -+ -+ EP_ASSERT (rail, txdRail->TxdMain->EnveEvent == EP3_EVENT_FREE); -+ EP_ASSERT (rail, txdRail->TxdMain->DataEvent == EP3_EVENT_FREE); -+ EP_ASSERT (rail, txdRail->TxdMain->DoneEvent == EP3_EVENT_FREE); -+ EP_ASSERT (rail, SDRAM_ASSERT(elan3_sdram_readl (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count)) == 0)); -+ EP_ASSERT (rail, SDRAM_ASSERT(elan3_sdram_readl (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); -+ EP_ASSERT (rail, SDRAM_ASSERT(elan3_sdram_readl (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); -+ } -+#endif -+ -+ list_del (&txdRail->Generic.Link); -+ -+ xmtrRail->FreeDescCount--; -+ } -+ /* Wakeup the descriptor primer thread if there's not many left */ -+ low_on_txds = (xmtrRail->FreeDescCount < ep_txd_lowat); -+ -+ spin_unlock_irqrestore (&xmtrRail->FreeDescLock, flags); -+ -+ if (low_on_txds) -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ -+ return (txdRail); -+} -+ -+static void -+FreeTxdRail (EP3_XMTR_RAIL *xmtrRail, EP3_TXD_RAIL *txdRail) -+{ -+ unsigned long flags; -+ -+#if defined(DEBUG_ASSERT) -+ { -+ EP_RAIL *rail = xmtrRail->Generic.CommsRail->Rail; -+ ELAN3_DEV *dev = ((EP3_RAIL *) rail)->Device; -+ -+ EP_ASSERT (rail, txdRail->Generic.XmtrRail == &xmtrRail->Generic); -+ -+ EP_ASSERT (rail, txdRail->TxdMain->EnveEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (rail, txdRail->TxdMain->DataEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (rail, txdRail->TxdMain->DoneEvent == EP3_EVENT_PRIVATE); -+ EP_ASSERT (rail, SDRAM_ASSERT (elan3_sdram_readl (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count)) == 0)); -+ EP_ASSERT (rail, SDRAM_ASSERT (elan3_sdram_readl (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); -+ EP_ASSERT (rail, SDRAM_ASSERT (elan3_sdram_readl (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count)) == 0)); -+ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_FREE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_FREE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_FREE; -+ } -+#endif -+ -+ spin_lock_irqsave (&xmtrRail->FreeDescLock, flags); -+ -+ list_add (&txdRail->Generic.Link, &xmtrRail->FreeDescList); -+ -+ xmtrRail->FreeDescCount++; -+ -+ if (xmtrRail->FreeDescWaiting) -+ { -+ xmtrRail->FreeDescWaiting--; -+ kcondvar_wakeupall (&xmtrRail->FreeDescSleep, &xmtrRail->FreeDescLock); -+ } -+ -+ spin_unlock_irqrestore (&xmtrRail->FreeDescLock, flags); -+} -+ -+static void -+BindTxdToRail (EP_TXD *txd, EP3_TXD_RAIL *txdRail) -+{ -+ ASSERT (SPINLOCK_HELD (&txd->Xmtr->Lock)); -+ -+ EPRINTF6 (DBG_XMTR, "%s: BindTxdToRail: txd=%p txdRail=%p XID=%08x.%08x.%016llx\n", -+ XMTR_TO_RAIL(txdRail->Generic.XmtrRail)->Generic.Name, txd, txdRail, -+ txd->Envelope.Xid.Generation, txd->Envelope.Xid.Handle, (long long) txd->Envelope.Xid.Unique); -+ -+ txd->TxdRail = &txdRail->Generic; -+ txdRail->Generic.Txd = txd; -+} -+ -+static void -+UnbindTxdFromRail (EP_TXD *txd, EP3_TXD_RAIL *txdRail) -+{ -+ ASSERT (SPINLOCK_HELD (&txd->Xmtr->Lock)); -+ ASSERT (txd->TxdRail == &txdRail->Generic && txdRail->Generic.Txd == txd); -+ -+ EPRINTF6 (DBG_XMTR, "%s: UnbindTxdToRail: txd=%p txdRail=%p XID=%08x.%08x.%016llx\n", -+ XMTR_TO_RAIL(txdRail->Generic.XmtrRail)->Generic.Name, txd, txdRail, -+ txd->Envelope.Xid.Generation, txd->Envelope.Xid.Handle, (long long) txd->Envelope.Xid.Unique); -+ txd->TxdRail = NULL; -+ txdRail->Generic.Txd = NULL; -+} -+ -+/* -+ * TxEnveEvent: arg == EP_TXD -+ * Called when envelope delivered -+ */ -+static void -+TxEnveEvent (EP3_RAIL *rail, void *arg) -+{ -+ panic ("TxEnveEvent"); -+} -+ -+/* -+ * TxEnveRetry: arg == EP3_TXD_RAIL -+ * Called on retry of dma of large message envelope. -+ */ -+static void -+TxEnveRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) arg; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ -+ EPRINTF3 (DBG_XMTR, "%s: TxEnveRetry: xmtr %p txd %p\n", rail->Generic.Name, xmtrRail, txdRail); -+ -+ EP_ASSERT (&rail->Generic, txdRail->TxdMain->EnveEvent == EP3_EVENT_ACTIVE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count)) == 1)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, dma->s.dma_direction == DMA_WRITE && EP_VP_TO_NODE(dma->s.dma_destVProc) == txdRail->Generic.Txd->NodeId); -+ -+ if (! TxdShouldStabalise (&txdRail->Generic, &rail->Generic)) -+ QueueDmaForRetry (rail, dma, EP_RETRY_LOW_PRI_RETRY + ep_backoff (&txdRail->Backoff, EP_BACKOFF_ENVELOPE)); -+ else -+ QueueDmaForRetry (rail, dma, EP_RETRY_STABALISING); /* place dma on stabilising list for neterr fixup */ -+} -+ -+static void -+TxEnveVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) arg; -+ -+ EP_ASSERT (&rail->Generic, txdRail->TxdMain->EnveEvent == EP3_EVENT_ACTIVE); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT (elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count)) == 1)); /* PCI read */ -+ EP_ASSERT (&rail->Generic, dma->s.dma_direction == DMA_WRITE && EP_VP_TO_NODE(dma->s.dma_destVProc) == txdRail->Generic.Txd->NodeId); -+} -+ -+/* -+ * TxDataEvent: arg == EP3_TXD -+ * Called on completion of a large transmit. -+ */ -+static void -+TxDataEvent (EP3_RAIL *rail, void *arg) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) arg; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP_XMTR *xmtr = xmtrRail->Generic.Xmtr; -+ EP3_TXD_RAIL_MAIN *txdMain = txdRail->TxdMain; -+ sdramaddr_t txdElan = txdRail->TxdElan; -+ int delay = 1; -+ EP_TXD *txd; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ for (;;) -+ { -+ if (EP3_EVENT_FIRED (txdRail->DataCookie, txdMain->DataEvent)) -+ break; -+ -+ if (EP3_EVENT_FIRING (rail->Device, txdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent), txdRail->DataCookie, txdMain->DataEvent)) /* PCI read */ -+ { -+ if (delay > EP3_EVENT_FIRING_TLIMIT) -+ panic ("TxDataEvent: events set but block copy not completed\n"); -+ DELAY(delay); -+ delay <<= 1; -+ } -+ else -+ { -+ EPRINTF3 (DBG_XMTR, "%s: TxDataEvent: xmtr %p txd %p previously collecting by polling\n", -+ rail->Generic.Name, xmtrRail, txdRail); -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ return; -+ } -+ mb(); -+ } -+ -+ if ((txd = txdRail->Generic.Txd) == NULL || /* If there is no txd, or if the descriptor is marked */ -+ !(EP_IS_INTERRUPT_ENABLED(txd->Envelope.Attr)) || /* as no interrupt, or been reused as an RPC, */ -+ (EP_IS_RPC(txd->Envelope.Attr))) /* then we were either called as a result of a previous */ -+ { /* tx which was completed by polling or as a result */ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); /* of a EnableTxCallBack/DisableTxCallback */ -+ -+ EPRINTF4 (DBG_XMTR, "%s: TxDataEvent: xmtr %p txd %p recyled (%x)\n", -+ rail->Generic.Name, xmtr, txd, txd ? txd->Envelope.Attr : 0); -+ return; -+ } -+ -+ ASSERT (EP3_EVENT_FIRED (txdRail->EnveCookie, txdMain->EnveEvent)); -+ -+ EPRINTF5 (DBG_XMTR, "%s: TxDataEvent : xmtrRail=%p txdRail=%p tx=%p XID=%llx\n", -+ rail->Generic.Name, xmtrRail, txdRail, txd, (long long) txd->Envelope.Xid.Unique); -+ -+ ep_xmtr_txd_stat(xmtr,txd); -+ -+ /* remove from active transmit lists */ -+ list_del (&txd->Link); -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags for next time round */ -+ txdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ txd->Handler (txd, txd->Arg, EP_SUCCESS); -+ -+ FreeTxd (xmtr, txd); -+} -+ -+/* -+ * TxDataRetry: arg == EP3_TXD -+ * Called on retry of remote "put" dma of large transmit data. -+ */ -+static void -+TxDataRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) arg; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP_TXD *txd = txdRail->Generic.Txd; -+ -+ EP_ASSERT (&rail->Generic, ((txdRail->TxdMain->DataEvent == EP3_EVENT_ACTIVE && -+ SDRAM_ASSERT (elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) >= 1)) || /* PCI read */ -+ (EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent) && -+ SDRAM_ASSERT (elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)))); /* PCI read */ -+ EP_ASSERT (&rail->Generic, dma->s.dma_direction == DMA_WRITE && EP_VP_TO_NODE(dma->s.dma_destVProc) == txd->NodeId); -+ -+ EPRINTF5 (DBG_XMTR, "%s: TxDataRetry: xmtrRail=%p txdRail=%p txd=%p XID=%llx\n", -+ rail->Generic.Name, xmtrRail, txdRail, txd, (long long) txd->Envelope.Xid.Unique); -+ -+ QueueDmaForRetry (rail, dma, EP_RETRY_LOW_PRI_RETRY + ep_backoff (&txdRail->Backoff, EP_BACKOFF_DATA)); -+} -+ -+static void -+TxDataVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) arg; -+ EP_TXD *txd = txdRail->Generic.Txd; -+ -+ EP_ASSERT (&rail->Generic, ((txdRail->TxdMain->DataEvent == EP3_EVENT_ACTIVE && -+ SDRAM_ASSERT (elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) >= 1)) || /* PCI read */ -+ (EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent) && -+ SDRAM_ASSERT (elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)))); /* PCI read */ -+ EP_ASSERT (&rail->Generic, dma->s.dma_direction == DMA_WRITE && EP_VP_TO_NODE(dma->s.dma_destVProc) == txd->NodeId); -+} -+ -+/* -+ * TxDoneEvent: arg == EP3_TXD -+ * Called on completion of a RPC. -+ */ -+static void -+TxDoneEvent (EP3_RAIL *rail, void *arg) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) arg; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP_XMTR *xmtr = xmtrRail->Generic.Xmtr; -+ int delay = 1; -+ EP_TXD *txd; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ for (;;) -+ { -+ if (EP3_EVENT_FIRED (txdRail->DoneCookie, txdRail->TxdMain->DoneEvent) && -+ EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent)) -+ break; -+ -+ if (EP3_EVENT_FIRING (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent), txdRail->DoneCookie, txdRail->TxdMain->DoneEvent) && -+ EP3_EVENT_FIRING (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent), txdRail->DataCookie, txdRail->TxdMain->DataEvent)) -+ { -+ if (delay > EP3_EVENT_FIRING_TLIMIT) -+ panic ("TxDoneEvent: events set but block copy not completed\n"); -+ DELAY(delay); -+ delay <<= 1; -+ } -+ else -+ { -+ EPRINTF3 (DBG_XMTR, "%s: TxDoneEvent: xmtr %p txdRail %p previously collecting by polling\n", -+ rail->Generic.Name, xmtr, txdRail); -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ return; -+ } -+ mb(); -+ } -+ -+ if ((txd = txdRail->Generic.Txd) == NULL || /* If there is no txd, or if the descriptor is marked */ -+ !(EP_IS_INTERRUPT_ENABLED(txd->Envelope.Attr) || EP_IS_RPC(txd->Envelope.Attr))) /* marked as no interrupt, or been reused as an transmit, */ -+ { /* then we were either called as a result of a previous */ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); /* tx which was completed by polling or as a result */ -+ /* of a EnableTxCallBack/DisableTxCallback */ -+ -+ EPRINTF4 (DBG_XMTR, "%s: TxDoneEvent: xmtr %p txd %p recyled (%x)\n", -+ rail->Generic.Name, xmtr, txd, txd ? txd->Envelope.Attr : 0); -+ return; -+ } -+ -+ EPRINTF5 (DBG_XMTR, "%s: TxDoneEvent: xmtrRail=%p txdRail=%p txd=%p XID=%llx\n", -+ rail->Generic.Name, xmtrRail, txdRail, txd, (long long) txd->Envelope.Xid.Unique); -+ -+ ep_xmtr_txd_stat(xmtr,txd); -+ -+ /* remove from active transmit list */ -+ list_del (&txd->Link); -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags for next time round */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ if (txd->Handler) -+ txd->Handler (txd, txd->Arg, EP_SUCCESS); -+ -+ FreeTxd (xmtr, txd); -+} -+ -+/* -+ * TxDoneRetry: arg == EP3_TXD -+ */ -+static void -+TxDoneRetry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int status) -+{ -+ panic ("TxDoneRetry"); -+} -+ -+static void -+TxDoneVerify (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma) -+{ -+ panic ("TxDoneVerify"); -+} -+ -+static void -+EnableTransmitCallback (EP_TXD *txd, EP3_TXD_RAIL *txdRail) -+{ -+ ELAN3_DEV *dev = XMTR_TO_RAIL(txdRail->Generic.XmtrRail)->Device; -+ -+ EPRINTF3 (DBG_XMTR, "%s: EnableTransmitCallback: txd %p txdRail %p\n", XMTR_TO_RAIL (txdRail->Generic.XmtrRail)->Generic.Name, txd, txdRail); -+ -+ txd->Envelope.Attr = EP_SET_INTERRUPT_ENABLED(txd->Envelope.Attr); -+ -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Type), EV_TYPE_BCOPY); -+ -+ if (EP_IS_RPC(txd->Envelope.Attr)) -+ { -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Type), EV_TYPE_BCOPY); -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Type), EV_TYPE_BCOPY | EV_TYPE_EVIRQ | txdRail->DoneCookie.Cookie); -+ } -+ else -+ { -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Type), EV_TYPE_BCOPY | EV_TYPE_EVIRQ | txdRail->DataCookie.Cookie); -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Type), EV_TYPE_BCOPY); -+ } -+} -+ -+static void -+DisableTransmitCallback (EP_TXD *txd, EP3_TXD_RAIL *txdRail) -+{ -+ ELAN3_DEV *dev = XMTR_TO_RAIL(txdRail->Generic.XmtrRail)->Device; -+ -+ EPRINTF3 (DBG_XMTR, "%s: DisableTransmitCallback: txd %p txdRail %p\n", XMTR_TO_RAIL (txdRail->Generic.XmtrRail)->Generic.Name, txd, txdRail); -+ -+ txd->Envelope.Attr = EP_CLEAR_INTERRUPT_ENABLED(txd->Envelope.Attr); -+ -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Type), EV_TYPE_BCOPY); -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Type), EV_TYPE_BCOPY); -+ elan3_sdram_writel (dev, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Type), EV_TYPE_BCOPY); -+} -+ -+static void -+InitialiseTxdRail (EP_TXD *txd, EP3_TXD_RAIL *txdRail, int phase) -+{ -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->Generic); -+ -+ /* Initialise the per-rail fields in the envelope */ -+ txd->Envelope.TxdRail = txdRail->TxdElanAddr; -+ txd->Envelope.NodeId = rail->Generic.Position.pos_nodeid; -+ -+ /* Initialise the dma backoff */ -+ txdRail->Backoff.type = EP_BACKOFF_FREE; -+ -+ /* Initialise the per-rail events */ -+ switch (phase) -+ { -+ case EP_TXD_PHASE_ACTIVE: -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 1); -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), -+ (txd->Envelope.nFrags ? txd->Envelope.nFrags : 1) + (EP_IS_MULTICAST(txd->Envelope.Attr) ? 1 : 0)); -+ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_ACTIVE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_ACTIVE; -+ break; -+ -+ case EP_TXD_PHASE_PASSIVE: -+ ASSERT (EP_IS_RPC(txd->Envelope.Attr)); -+ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 0); -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), 0); -+ -+ txdRail->TxdMain->EnveEvent = txdRail->EnveCookie.Cookie; -+ txdRail->TxdMain->DataEvent = txdRail->DataCookie.Cookie; -+ break; -+ } -+ -+ if (! EP_IS_RPC(txd->Envelope.Attr)) -+ txdRail->TxdMain->DoneEvent = txdRail->DoneCookie.Cookie; -+ else -+ { -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 1); -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_ACTIVE; -+ } -+ -+ if (EP_IS_NO_INTERRUPT(txd->Envelope.Attr)) -+ DisableTransmitCallback (txd, txdRail); -+ else -+ EnableTransmitCallback (txd, txdRail); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ if ( epdebug_check_sum ) -+ txd->Envelope.CheckSum = ep_calc_check_sum( txd->Xmtr->Subsys->Subsys.Sys, &txd->Envelope, txd->Envelope.Frags, txd->Envelope.nFrags); -+ else -+#endif -+ txd->Envelope.CheckSum = 0; -+ -+ /* copy the envelope and payload if present down to sdram */ -+ elan3_sdram_copyl_to_sdram (rail->Device, &txd->Envelope, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, Envelope), EP_ENVELOPE_SIZE); -+ -+ if (EP_HAS_PAYLOAD(txd->Envelope.Attr)) -+ elan3_sdram_copyl_to_sdram (rail->Device, &txd->Payload, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, Payload), EP_PAYLOAD_SIZE); -+} -+ -+void -+ep3xmtr_flush_callback (EP_XMTR *xmtr, EP3_XMTR_RAIL *xmtrRail) -+{ -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ struct list_head *el; -+ unsigned long flags; -+ -+ switch (rail->Generic.CallbackStep) -+ { -+ case EP_CB_FLUSH_FILTERING: -+ /* only need to acquire/release the Lock to ensure that -+ * the node state transition has been noticed. */ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ break; -+ -+ case EP_CB_FLUSH_FLUSHING: -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ list_for_each (el, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) txd->TxdRail; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[txd->NodeId]; -+ -+ if (!TXD_BOUND2RAIL(txdRail, xmtrRail) || nodeRail->State != EP_NODE_LOCAL_PASSIVATE) -+ continue; -+ -+ if (EP_IS_RPC(txd->Envelope.Attr)) -+ { -+ if (! EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent)) -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ else if (! EP3_EVENT_FIRED (txdRail->DoneCookie, txdRail->TxdMain->DoneEvent)) -+ nodeRail->MessageState |= EP_NODE_PASSIVE_MESSAGES; -+ } -+ else -+ { -+ if (! EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent)) -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ break; -+ -+ default: -+ panic ("ep3xmtr_flush_callback: invalid callback step\n"); -+ break; -+ } -+} -+ -+void -+ep3xmtr_failover_callback (EP_XMTR *xmtr, EP3_XMTR_RAIL *xmtrRail) -+{ -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ struct list_head txdList; -+ struct list_head *el, *nel; -+ unsigned long flags; -+#ifdef SUPPORT_RAIL_FAILOVER -+ EP_COMMS_SUBSYS *subsys = xmtr->Subsys; -+#endif -+ -+ INIT_LIST_HEAD (&txdList); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) txd->TxdRail; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[txd->NodeId]; -+ -+ /* Only progress relocation of txd's bound to this rail */ -+ if (!TXD_BOUND2RAIL(txdRail, xmtrRail) || nodeRail->State != EP_NODE_PASSIVATED) -+ continue; -+ -+#ifdef SUPPORT_RAIL_FAILOVER -+ /* Transmit data not been sent, so just restart on different rail */ -+ if (! EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent)) -+ { -+ EPRINTF4 (DBG_XMTR, "%s: ep3xmtr_failover_callback - xmtr %p txd %p node %d unbind an retry\n", rail->Generic.Name, xmtr, txd, txd->NodeId); -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* reset all events, since non of them could have been set */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ /* epcomms thread will restart on different rail */ -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ continue; -+ } -+ -+ if (EP_IS_RPC(txd->Envelope.Attr) && !EP3_EVENT_FIRED (txdRail->DoneCookie, txdRail->TxdMain->DoneEvent)) -+ { -+ if (EP_IS_NO_FAILOVER(txd->Envelope.Attr)) -+ { -+ EPRINTF4 (DBG_XMTR, "%s: ep3xmtr_failover_callback - xmtr %p txd %p node %d - not able to failover\n", -+ rail->Generic.Name, xmtr, txd, txd->NodeId); -+ -+ list_del (&txd->Link); -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* envelope and data events must have been set, so only clear the done event */ -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT(elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count)) == 0)); -+ EP_ASSERT (&rail->Generic, SDRAM_ASSERT(elan3_sdram_readl (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)) == 0)); -+ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ list_add_tail (&txd->Link, &txdList); -+ continue; -+ } -+ EPRINTF4 (DBG_XMTR, "%s: ep3xmtr_failover_callback - xmtr %p txd %p node %d passive\n", rail->Generic.Name, xmtr, txd, txd->NodeId); -+ -+ nodeRail->MessageState |= EP_NODE_PASSIVE_MESSAGES; -+ continue; -+ } -+ -+ EPRINTF4 (DBG_XMTR, "%s: ep3xmtr_failover_callback - xmtr %p txd %p node %d completed\n", rail->Generic.Name, xmtr, txd, txd->NodeId); -+#endif -+ -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ while (! list_empty (&txdList)) -+ { -+ EP_TXD *txd = list_entry (txdList.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ txd->Handler (txd, txd->Arg, EP_CONN_RESET); -+ -+ FreeTxd (xmtr, txd); -+ } -+} -+ -+ -+void -+ep3xmtr_disconnect_callback (EP_XMTR *xmtr, EP3_XMTR_RAIL *xmtrRail) -+{ -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ struct list_head *el, *nel; -+ struct list_head txdList; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&txdList); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) txd->TxdRail; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[txd->NodeId]; -+ -+ if (!TXD_BOUND2RAIL(txdRail, xmtrRail) || nodeRail->State != EP_NODE_DISCONNECTING) -+ continue; -+ -+ if (EP3_EVENT_FIRED (txdRail->EnveCookie, txdRail->TxdMain->EnveEvent) && -+ EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent) && -+ EP3_EVENT_FIRED (txdRail->DoneCookie, txdRail->TxdMain->DoneEvent)) -+ { -+ EPRINTF4 (DBG_XMTR, "%s: ep3xmtr_disconnect_callback - xmtr %p txd %p completed to node %d\n", rail->Generic.Name, xmtr, txd, txd->NodeId); -+ continue; -+ } -+ -+ /* Remove from active list */ -+ list_del (&txd->Link); -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* reset the envelope and data events, since only they could have been set */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ EPRINTF4 (DBG_XMTR, "%s: ep3xmtr_disconnect_callback - xmtr %p txd %p node %d not conected\n", rail->Generic.Name, xmtr, txd, txd->NodeId); -+ -+ /* add to the list of txd's which are to be completed */ -+ list_add_tail (&txd->Link, &txdList); -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ while (! list_empty (&txdList)) -+ { -+ EP_TXD *txd = list_entry (txdList.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ txd->Handler (txd, txd->Arg, EP_CONN_RESET); -+ -+ FreeTxd (xmtr, txd); -+ } -+} -+ -+int -+ep3xmtr_poll_txd (EP_XMTR_RAIL *x, EP_TXD_RAIL *t, int how) -+{ -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) x; -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) t; -+ EP_TXD *txd = txdRail->Generic.Txd; -+ -+ switch (how) -+ { -+ case ENABLE_TX_CALLBACK: -+ if (EP_IS_NO_INTERRUPT(txd->Envelope.Attr)) -+ EnableTransmitCallback (txd, txdRail); -+ break; -+ -+ case DISABLE_TX_CALLBACK: -+ if (EP_IS_NO_INTERRUPT(txd->Envelope.Attr)) -+ DisableTransmitCallback (txd, txdRail); -+ break; -+ } -+ -+ if (EP3_EVENT_FIRED (txdRail->EnveCookie, txdRail->TxdMain->EnveEvent) && -+ EP3_EVENT_FIRED (txdRail->DataCookie, txdRail->TxdMain->DataEvent) && -+ EP3_EVENT_FIRED (txdRail->DoneCookie, txdRail->TxdMain->DoneEvent)) -+ { -+ EPRINTF3 (DBG_XMTR, "%s: ep3xmtr_poll_txd: txd=%p XID=%llx completed\n", -+ XMTR_TO_RAIL (xmtrRail)->Generic.Name, txd, (long long) txd->Envelope.Xid.Unique); -+ -+ ep_xmtr_txd_stat(xmtrRail->Generic.Xmtr,txd); -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+ep3xmtr_bind_txd (EP_TXD *txd, EP_XMTR_RAIL *x, unsigned int phase) -+{ -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) x; -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ EP3_TXD_RAIL *txdRail; -+ E3_DMA_BE dmabe; -+ -+ if ((txdRail = GetTxdRail (xmtrRail)) == NULL) -+ return 0; -+ -+ switch (phase) -+ { -+ case EP_TXD_PHASE_ACTIVE: -+ if (rail->Generic.Nodes[txd->NodeId].State != EP_NODE_CONNECTED) -+ { -+ EPRINTF2 (DBG_XMTR, "%s: TransmitTxdOnRail: node %u not connected on this rail\n", rail->Generic.Name, txd->NodeId); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* reset all events, since non of them could have been set */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ return 0; -+ } -+ -+ InitialiseTxdRail (txd, txdRail, phase); -+ -+ /* Initialise the dma descriptor */ -+ dmabe.s.dma_type = E3_DMA_TYPE (DMA_BYTE, DMA_WRITE, DMA_QUEUED, EP3_DMAFAILCOUNT); -+ dmabe.s.dma_size = (EP_HAS_PAYLOAD(txd->Envelope.Attr) ? EP_INPUTQ_SIZE : EP_ENVELOPE_SIZE); -+ dmabe.s.dma_source = txdRail->TxdElanAddr + offsetof (EP3_TXD_RAIL_ELAN, Envelope); -+ dmabe.s.dma_dest = (E3_Addr) 0; -+ dmabe.s.dma_destEvent = EP_MSGQ_ADDR(txd->Service); -+ dmabe.s.dma_destCookieVProc = EP_VP_DATA (txd->NodeId); -+ dmabe.s.dma_srcEvent = txdRail->TxdElanAddr + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent); -+ dmabe.s.dma_srcCookieVProc = LocalCookie (rail, txd->NodeId); -+ -+ EPRINTF8 (DBG_XMTR, "%s: TransmitTxdOnRail: txd=%p txdRail=%p @ %x XID=%llx dest=%u srcEvent=%x srcCookie=%x\n", rail->Generic.Name, -+ txd, txdRail, txdRail->TxdElanAddr, (long long) txd->Envelope.Xid.Unique, txd->NodeId, dmabe.s.dma_srcEvent, dmabe.s.dma_srcCookieVProc); -+ -+ BindTxdToRail (txd, txdRail); -+ -+ if (IssueDma (rail, &dmabe, EP_RETRY_LOW_PRI, FALSE) != ISSUE_COMMAND_OK) -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_LOW_PRI); -+ break; -+ -+ case EP_TXD_PHASE_PASSIVE: -+ InitialiseTxdRail (txd, txdRail, EP_TXD_PHASE_PASSIVE); /* initialise as passive (updated envelope) */ -+ -+ EP_XMTR_OP (txd->TxdRail->XmtrRail, UnbindTxd) (txd, EP_TXD_PHASE_PASSIVE); /* unbind from existing rail */ -+ -+ BindTxdToRail (txd, txdRail); /* and bind it to our new rail */ -+ break; -+ } -+ -+ return 1; -+} -+ -+void -+ep3xmtr_unbind_txd (EP_TXD *txd, unsigned int phase) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) txd->TxdRail; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ -+ /* XXXX - TBD assertions on phase */ -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* reset the envelope and data events, since only they could have been set */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeTxdRail (xmtrRail, txdRail); -+} -+ -+long -+ep3xmtr_check (EP_XMTR_RAIL *x, long nextRunTime) -+{ -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) x; -+ -+ if (xmtrRail->FreeDescCount < ep_txd_lowat && !AllocateTxdRailBlock(xmtrRail)) -+ { -+ EPRINTF1 (DBG_RCVR,"%s: failed to grow txd rail pool\n", XMTR_TO_RAIL(xmtrRail)->Generic.Name); -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ -+ return nextRunTime; -+} -+ -+void -+ep3xmtr_add_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail) -+{ -+ EP3_XMTR_RAIL *xmtrRail; -+ unsigned long flags; -+ -+ KMEM_ZALLOC (xmtrRail, EP3_XMTR_RAIL *, sizeof (EP3_XMTR_RAIL), 1); -+ -+ spin_lock_init (&xmtrRail->FreeDescLock); -+ kcondvar_init (&xmtrRail->FreeDescSleep); -+ INIT_LIST_HEAD (&xmtrRail->FreeDescList); -+ INIT_LIST_HEAD (&xmtrRail->DescBlockList); -+ -+ xmtrRail->Generic.CommsRail = commsRail; -+ xmtrRail->Generic.Xmtr = xmtr; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ xmtr->Rails[commsRail->Rail->Number] = &xmtrRail->Generic; -+ xmtr->RailMask |= EP_RAIL2RAILMASK(commsRail->Rail->Number); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+} -+ -+void -+ep3xmtr_del_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) commsRail->Rail; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) xmtr->Rails[commsRail->Rail->Number]; -+ unsigned long flags; -+ -+ /* rail mask set as not usable */ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ xmtr->RailMask &= ~EP_RAIL2RAILMASK (rail->Generic.Number); -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ /* wait for all txd's for this rail to become free */ -+ spin_lock_irqsave (&xmtrRail->FreeDescLock, flags); -+ while (xmtrRail->FreeDescCount != xmtrRail->TotalDescCount) -+ { -+ xmtrRail->FreeDescWaiting++; -+ kcondvar_wait (&xmtrRail->FreeDescSleep, &xmtrRail->FreeDescLock, &flags); -+ } -+ spin_unlock_irqrestore (&xmtrRail->FreeDescLock, flags); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ xmtr->Rails[commsRail->Rail->Number] = NULL; -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ /* need to free up the txd's and blocks */ -+ /* all the txd's accociated with DescBlocks must be in the FreeDescList */ -+ ASSERT (xmtrRail->TotalDescCount == xmtrRail->FreeDescCount); -+ -+ /* run through the DescBlockList deleting them */ -+ while (!list_empty (&xmtrRail->DescBlockList)) -+ FreeTxdRailBlock (xmtrRail, list_entry(xmtrRail->DescBlockList.next, EP3_TXD_RAIL_BLOCK , Link)); -+ -+ /* it had better be empty after that */ -+ ASSERT ((xmtrRail->FreeDescCount == 0) && (xmtrRail->TotalDescCount == 0)); -+ -+ spin_lock_destroy (&xmtrRail->FreeDescLock); -+ kcondvar_destroy (&xmtrRail->FreeDescSleep); -+ -+ KMEM_FREE (xmtrRail, sizeof (EP3_XMTR_RAIL)); -+} -+ -+void -+ep3xmtr_display_xmtr (DisplayInfo *di, EP_XMTR_RAIL *x) -+{ -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) x; -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ struct list_head *el; -+ unsigned long flags; -+ int freeCount = 0; -+ -+ spin_lock_irqsave (&xmtrRail->FreeDescLock, flags); -+ list_for_each (el, &xmtrRail->FreeDescList) -+ freeCount++; -+ spin_unlock_irqrestore (&xmtrRail->FreeDescLock, flags); -+ -+ (di->func)(di->arg, " Rail=%d Free=%d Total=%d (%d)\n", -+ rail->Generic.Number, xmtrRail->FreeDescCount, xmtrRail->TotalDescCount, freeCount); -+} -+ -+void -+ep3xmtr_display_txd (DisplayInfo *di, EP_TXD_RAIL *t) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) t; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP3_TXD_RAIL_MAIN *txdMain = txdRail->TxdMain; -+ sdramaddr_t txdElan = txdRail->TxdElan; -+ EP3_RAIL *rail = (EP3_RAIL *) xmtrRail->Generic.CommsRail->Rail; -+ ELAN3_DEV *dev = rail->Device; -+ -+ (di->func)(di->arg, " EnveEvent=%x DataEvent=%x DoneEvent=%x Rail=%s\n", -+ txdMain->EnveEvent, txdMain->DataEvent, txdMain->DoneEvent, rail->Generic.Name); -+ (di->func)(di->arg, " EnveEvent=%x.%x DataEvent=%x.%x DoneEvent=%x.%x\n", -+ elan3_sdram_readl (dev, txdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count)), -+ elan3_sdram_readl (dev, txdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Type)), -+ elan3_sdram_readl (dev, txdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count)), -+ elan3_sdram_readl (dev, txdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Type)), -+ elan3_sdram_readl (dev, txdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count)), -+ elan3_sdram_readl (dev, txdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Type))); -+} -+ -+int -+ep3xmtr_check_txd_state (EP_TXD *txd) -+{ -+ EP3_TXD_RAIL *txdRail = (EP3_TXD_RAIL *) txd->TxdRail; -+ EP3_XMTR_RAIL *xmtrRail = (EP3_XMTR_RAIL *) txdRail->Generic.XmtrRail; -+ EP3_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ E3_Addr enveEvent = txdRail->TxdElanAddr + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent); -+ EP3_RETRY_DMA *retry = NULL; -+ -+ struct list_head *el; -+ struct list_head *nel; -+ unsigned long flags; -+ -+ /* is enevelope event is really not set */ -+ if (EP3_EVENT_FIRED (txdRail->EnveCookie, txdRail->TxdMain->EnveEvent )) -+ return (0); -+ -+ /* remove matching dma from stalled list */ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ list_for_each_safe(el, nel, &rail->DmaRetries[EP_RETRY_STABALISING]) { -+ retry = list_entry (el, EP3_RETRY_DMA, Link); -+ -+ if ( retry->Dma.s.dma_srcEvent == enveEvent ) { -+ /* remove from retry list */ -+ list_del (&retry->Link); -+ break; /* there can only be one */ -+ } -+ } -+ ASSERT ( retry != NULL); /* must find one in list */ -+ ASSERT ( retry->Dma.s.dma_srcEvent == enveEvent ); /* better still be the right type then */ -+ -+ /* add to free list */ -+ list_add (&retry->Link, &rail->DmaRetryFreeList); -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ -+ UnbindTxdFromRail (txd, txdRail); -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->TxdMain->EnveEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DataEvent = EP3_EVENT_PRIVATE; -+ txdRail->TxdMain->DoneEvent = EP3_EVENT_PRIVATE; -+ -+ /* reset the envelope and data events, since only they could have been set */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, EnveEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DataEvent.ev_Count), 0); /* PCI write */ -+ elan3_sdram_writel (rail->Device, txdRail->TxdElan + offsetof (EP3_TXD_RAIL_ELAN, DoneEvent.ev_Count), 0); /* PCI write */ -+ -+ FreeTxdRail (xmtrRail, txdRail); -+ -+ return (1); -+} -+ -+void -+ep3xmtr_fillout_rail_stats(EP_XMTR_RAIL *xmtr_rail, char *str) { -+ /* no stats here yet */ -+ /* EP3_XMTR_RAIL * ep3xmtr_rail = (EP3_XMTR_RAIL *) xmtr_rail; */ -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/epcommsTx_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/epcommsTx_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/epcommsTx_elan4.c 2005-06-01 23:12:54.659429984 -0400 -@@ -0,0 +1,1389 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: epcommsTx_elan4.c,v 1.26.2.4 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcommsTx_elan4.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "debug.h" -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "epcomms_elan4.h" -+ -+#include -+ -+#define XMTR_TO_COMMS(xmtrRail) ((EP4_COMMS_RAIL *) ((EP_XMTR_RAIL *) xmtrRail)->CommsRail) -+#define XMTR_TO_RAIL(xmtrRail) ((EP4_RAIL *) ((EP_XMTR_RAIL *) xmtrRail)->CommsRail->Rail) -+#define XMTR_TO_DEV(xmtrRail) (XMTR_TO_RAIL(xmtrRail)->r_ctxt.ctxt_dev) -+#define XMTR_TO_SUBSYS(xmtrRail) (((EP_XMTR_RAIL *) xmtrRail)->Xmtr->Subsys) -+ -+#define TXD_TO_XMTR(txdRail) ((EP4_XMTR_RAIL *) txdRail->txd_generic.XmtrRail) -+#define TXD_TO_RAIL(txdRail) XMTR_TO_RAIL(TXD_TO_XMTR(txdRail)) -+ -+static void txd_interrupt (EP4_RAIL *rail, void *arg); -+static void poll_interrupt (EP4_RAIL *rail, void *arg); -+ -+static __inline__ int -+on_list (struct list_head *ent, struct list_head *list) -+{ -+ struct list_head *el; -+ unsigned int count = 0; -+ list_for_each (el, list) { -+ if (el == ent) -+ count++; -+ } -+ return count; -+} -+ -+static __inline__ void -+__ep4_txd_assert_free (EP4_TXD_RAIL *txdRail, const char *file, const int line) -+{ -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR (txdRail); -+ ELAN4_DEV *dev = XMTR_TO_DEV (xmtrRail); -+ register int failed = 0; -+ -+ if ((txdRail)->txd_retry_time != 0) failed |= (1 << 0); -+ if ((txdRail)->txd_main->txd_env != EP4_STATE_FREE) failed |= (1 << 1); -+ if ((txdRail)->txd_main->txd_data != EP4_STATE_FREE) failed |= (1 << 2); -+ if ((txdRail)->txd_main->txd_done != EP4_STATE_FREE) failed |= (1 << 3); -+ -+ if (sdram_assert) -+ { -+ if ((int)(elan4_sdram_readq (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType)) >> 32) != -32) failed |= (1 << 4); -+ if ((int)(elan4_sdram_readq (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType)) >> 32) != 0) failed |= (1 << 5); -+ if ((int)(elan4_sdram_readq (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType)) >> 32) != 0) failed |= (1 << 6); -+ } -+ -+ if (failed) -+ { -+ printk ("__ep4_txd_assert_free: failed=%x txdRail=%p at %s:%d\n", failed, txdRail, file, line); -+ -+ ep_debugf (DBG_DEBUG, "__ep4_txd_assert_free: failed=%x txdRail=%p at %s:%d\n", failed, txdRail, file, line); -+ ep4xmtr_display_txd (&di_ep_debug, &txdRail->txd_generic); -+ -+ (txdRail)->txd_retry_time = 0; -+ (txdRail)->txd_main->txd_env = EP4_STATE_FREE; -+ (txdRail)->txd_main->txd_data = EP4_STATE_FREE; -+ (txdRail)->txd_main->txd_done = EP4_STATE_FREE; -+ -+ if (sdram_assert) -+ { -+ elan4_sdram_writel (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType) + 4, -32); -+ elan4_sdram_writel (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType) + 4, 0); -+ elan4_sdram_writel (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType) + 4, 0); -+ } -+ EP_ASSFAIL (XMTR_TO_RAIL(xmtrRail), "__ep4_txd_assert_free"); -+ } -+} -+ -+static __inline__ void -+__ep4_txd_assert_finished (EP4_TXD_RAIL *txdRail, const char *file, const int line) -+{ -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR (txdRail); -+ ELAN4_DEV *dev = XMTR_TO_DEV (xmtrRail); -+ register int failed = 0; -+ -+ if ((txdRail)->txd_retry_time != 0) failed |= (1 << 0); -+ if ((txdRail)->txd_main->txd_env != EP4_STATE_FINISHED) failed |= (1 << 1); -+ if ((txdRail)->txd_main->txd_data != EP4_STATE_FINISHED) failed |= (1 << 2); -+ if ((txdRail)->txd_main->txd_done != EP4_STATE_FINISHED) failed |= (1 << 3); -+ -+ if (sdram_assert) -+ { -+ if ((int)(elan4_sdram_readq (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType)) >> 32) != -32) failed |= (1 << 4); -+ if ((int)(elan4_sdram_readq (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType)) >> 32) != 0) failed |= (1 << 5); -+ if ((int)(elan4_sdram_readq (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType)) >> 32) != 0) failed |= (1 << 6); -+ } -+ -+ if (failed) -+ { -+ printk ("__ep4_txd_assert_finished: failed=%x txdRail=%p at %s:%d\n", failed, txdRail, file, line); -+ -+ ep_debugf (DBG_DEBUG, "__ep4_txd_assert_finished: failed=%x txdRail=%p at %s:%d\n", failed, txdRail, file, line); -+ ep4xmtr_display_txd (&di_ep_debug, &txdRail->txd_generic); -+ -+ (txdRail)->txd_retry_time = 0; -+ (txdRail)->txd_main->txd_env = EP4_STATE_FINISHED; -+ (txdRail)->txd_main->txd_data = EP4_STATE_FINISHED; -+ (txdRail)->txd_main->txd_done = EP4_STATE_FINISHED; -+ -+ if (sdram_assert) -+ { -+ elan4_sdram_writel (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType) + 4, -32); -+ elan4_sdram_writel (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType) + 4, 0); -+ elan4_sdram_writel (dev, (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType) + 4, 0); -+ } -+ EP_ASSFAIL (XMTR_TO_RAIL(xmtrRail), "__ep4_txd_assert_finished"); -+ } -+} -+ -+static __inline__ int -+__ep4_txd_assfail (EP4_TXD_RAIL *txdRail, const char *expr, const char *file, const int line) -+{ -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR (txdRail); -+ -+ printk ("__ep4_txd_assfail: %s:%d '%s'\n", file, line, expr); -+ -+ ep_debugf (DBG_DEBUG, "__ep4_txd_assfail: %s:%d '%s'\n", file, line, expr); -+ ep4xmtr_display_txd (&di_ep_debug, &txdRail->txd_generic); -+ -+ EP_ASSFAIL (XMTR_TO_RAIL (xmtrRail), "__ep4_txd_assfail"); -+ -+ return 0; -+} -+ -+#define EP4_TXD_ASSERT(txdRail, EX) ((void) ((EX) || (__ep4_txd_assfail(txdRail, #EX, __FILE__, __LINE__)))) -+#define EP4_TXD_ASSERT_FREE(txdRail) __ep4_txd_assert_free(txdRail, __FILE__, __LINE__) -+#define EP4_TXD_ASSERT_FINISHED(txdRail) __ep4_txd_assert_finished(txdRail, __FILE__, __LINE__) -+ -+static int -+alloc_txd_block (EP4_XMTR_RAIL *xmtrRail) -+{ -+ EP4_RAIL *rail = XMTR_TO_RAIL(xmtrRail); -+ ELAN4_DEV *dev = XMTR_TO_DEV(xmtrRail); -+ EP4_TXD_RAIL_BLOCK *blk; -+ EP4_TXD_RAIL_MAIN *txdMain; -+ EP_ADDR txdMainAddr; -+ sdramaddr_t txdElan; -+ EP_ADDR txdElanAddr; -+ EP4_TXD_RAIL *txdRail; -+ unsigned long flags; -+ int i; -+ -+ KMEM_ZALLOC (blk, EP4_TXD_RAIL_BLOCK *, sizeof (EP4_TXD_RAIL_BLOCK), 1); -+ -+ if (blk == NULL) -+ return 0; -+ -+ if ((txdElan = ep_alloc_elan (&rail->r_generic, EP4_TXD_RAIL_ELAN_SIZE * EP4_NUM_TXD_PER_BLOCK, 0, &txdElanAddr)) == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (blk, sizeof (EP4_TXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if ((txdMain = ep_alloc_main (&rail->r_generic, EP4_TXD_RAIL_MAIN_SIZE * EP4_NUM_TXD_PER_BLOCK, 0, &txdMainAddr)) == (EP4_TXD_RAIL_MAIN *) NULL) -+ { -+ ep_free_elan (&rail->r_generic, txdElanAddr, EP4_TXD_RAIL_ELAN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP4_TXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ if (ep4_reserve_dma_retries (rail, EP4_NUM_TXD_PER_BLOCK, 0) != 0) -+ { -+ ep_free_main (&rail->r_generic, blk->blk_txds[0].txd_main_addr, EP4_TXD_RAIL_MAIN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ ep_free_elan (&rail->r_generic, txdElanAddr, EP4_TXD_RAIL_ELAN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ KMEM_FREE (blk, sizeof (EP4_TXD_RAIL_BLOCK)); -+ return 0; -+ } -+ -+ for (txdRail = &blk->blk_txds[0], i = 0; i < EP4_NUM_TXD_PER_BLOCK; i++, txdRail++) -+ { -+ txdRail->txd_generic.XmtrRail = &xmtrRail->xmtr_generic; -+ txdRail->txd_elan = txdElan; -+ txdRail->txd_elan_addr = txdElanAddr; -+ txdRail->txd_main = txdMain; -+ txdRail->txd_main_addr = txdMainAddr; -+ -+ /* We only need to reserve space for one command stream, since the sten packet -+ * can only be retrying *before* the dma source event is set. -+ * reserve bytes of "event" cq space for the completion write + interrupt */ -+ if ((txdRail->txd_ecq = ep4_get_ecq (rail, EP4_ECQ_EVENT, EP4_INTR_CMD_NDWORDS)) == NULL) -+ goto failed; -+ -+ /* register the main interrupt cookies */ -+ ep4_register_intcookie (rail, &txdRail->txd_intcookie, txdElanAddr + offsetof (EP4_TXD_RAIL_ELAN, txd_done), txd_interrupt, txdRail); -+ -+ /* initialise the events */ -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CopySource), -+ txdElanAddr + offsetof (EP4_TXD_RAIL_ELAN, txd_env_cmd)); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CopyDest), -+ txdRail->txd_ecq->ecq_addr); -+ -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_WritePtr), -+ txdMainAddr + offsetof (EP4_TXD_RAIL_MAIN, txd_data)); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_WriteValue), -+ EP4_STATE_FINISHED); -+ -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CopySource), -+ txdElanAddr + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd)); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CopyDest), -+ txdRail->txd_ecq->ecq_addr); -+ -+ /* Initialise the command streams */ -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env_cmd.c_write_cmd), -+ WRITE_DWORD_CMD | (txdMainAddr + offsetof (EP4_TXD_RAIL_MAIN, txd_env))); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env_cmd.c_write_value), -+ EP4_STATE_FAILED); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env_cmd.c_intr_cmd), -+ INTERRUPT_CMD | (txdRail->txd_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_write_cmd), -+ WRITE_DWORD_CMD | (txdMainAddr + offsetof (EP4_TXD_RAIL_MAIN, txd_done))); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_write_value), -+ EP4_STATE_FINISHED); -+ elan4_sdram_writeq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_intr_cmd), -+ INTERRUPT_CMD | (txdRail->txd_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ txdMain->txd_env = EP4_STATE_FREE; -+ txdMain->txd_data = EP4_STATE_FREE; -+ txdMain->txd_done = EP4_STATE_FREE; -+ -+ /* move onto next descriptor */ -+ txdElan += EP4_TXD_RAIL_ELAN_SIZE; -+ txdElanAddr += EP4_TXD_RAIL_ELAN_SIZE; -+ txdMain = (EP4_TXD_RAIL_MAIN *) ((unsigned long) txdMain + EP4_TXD_RAIL_MAIN_SIZE); -+ txdMainAddr += EP4_TXD_RAIL_MAIN_SIZE; -+ } -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_freelock, flags); -+ -+ list_add (&blk->blk_link, &xmtrRail->xmtr_blocklist); -+ -+ xmtrRail->xmtr_totalcount += EP4_NUM_TXD_PER_BLOCK; -+ xmtrRail->xmtr_freecount += EP4_NUM_TXD_PER_BLOCK; -+ -+ for (i = 0; i < EP4_NUM_TXD_PER_BLOCK; i++) -+ list_add (&blk->blk_txds[i].txd_generic.Link, &xmtrRail->xmtr_freelist); -+ -+ spin_unlock_irqrestore (&xmtrRail->xmtr_freelock, flags); -+ -+ return 1; -+ -+ failed: -+ while (--i >= 0) -+ { -+ ep4_put_ecq (rail, txdRail->txd_ecq, EP4_INTR_CMD_NDWORDS); -+ ep4_deregister_intcookie (rail, &txdRail->txd_intcookie); -+ } -+ ep4_release_dma_retries (rail, EP4_NUM_TXD_PER_BLOCK); -+ -+ ep_free_main (&rail->r_generic, blk->blk_txds[0].txd_main_addr, EP4_TXD_RAIL_MAIN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ ep_free_elan (&rail->r_generic, blk->blk_txds[0].txd_elan_addr, EP4_TXD_RAIL_ELAN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ -+ KMEM_FREE (blk, sizeof (EP4_TXD_RAIL_BLOCK)); -+ -+ return 0; -+} -+ -+static void -+free_txd_block (EP4_XMTR_RAIL *xmtrRail, EP4_TXD_RAIL_BLOCK *blk) -+{ -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ EP4_TXD_RAIL *txdRail; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_freelock, flags); -+ -+ list_del (&blk->blk_link); -+ -+ xmtrRail->xmtr_totalcount -= EP4_NUM_TXD_PER_BLOCK; -+ -+ for (txdRail = &blk->blk_txds[0], i = 0; i < EP4_NUM_TXD_PER_BLOCK; i++, txdRail++) -+ { -+ xmtrRail->xmtr_freecount--; -+ -+ ep4_put_ecq (rail, txdRail->txd_ecq, EP4_INTR_CMD_NDWORDS); -+ -+ ep4_deregister_intcookie (rail, &txdRail->txd_intcookie); -+ -+ list_del (&txdRail->txd_generic.Link); -+ } -+ spin_unlock_irqrestore (&xmtrRail->xmtr_freelock, flags); -+ -+ ep4_release_dma_retries (rail, EP4_NUM_TXD_PER_BLOCK); -+ -+ ep_free_main (&rail->r_generic, blk->blk_txds[0].txd_main_addr, EP4_TXD_RAIL_MAIN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ ep_free_elan (&rail->r_generic, blk->blk_txds[0].txd_elan_addr, EP4_TXD_RAIL_ELAN_SIZE * EP4_NUM_TXD_PER_BLOCK); -+ -+ KMEM_FREE (blk, sizeof (EP4_TXD_RAIL_BLOCK)); -+} -+ -+static EP4_TXD_RAIL * -+get_txd_rail (EP4_XMTR_RAIL *xmtrRail) -+{ -+ EP_COMMS_SUBSYS *subsys = XMTR_TO_SUBSYS(xmtrRail); -+ EP4_TXD_RAIL *txdRail; -+ unsigned long flags; -+ int low_on_txds; -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_freelock, flags); -+ -+ if (list_empty (&xmtrRail->xmtr_freelist)) -+ txdRail = NULL; -+ else -+ { -+ txdRail = list_entry (xmtrRail->xmtr_freelist.next, EP4_TXD_RAIL, txd_generic.Link); -+ -+ EP4_TXD_ASSERT_FREE(txdRail); -+ -+ list_del (&txdRail->txd_generic.Link); -+ -+ xmtrRail->xmtr_freecount--; -+ } -+ /* Wakeup the descriptor primer thread if there's not many left */ -+ low_on_txds = (xmtrRail->xmtr_freecount < ep_txd_lowat); -+ -+ spin_unlock_irqrestore (&xmtrRail->xmtr_freelock, flags); -+ -+ if (low_on_txds) -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ -+ -+ return (txdRail); -+} -+ -+static void -+free_txd_rail (EP4_XMTR_RAIL *xmtrRail, EP4_TXD_RAIL *txdRail) -+{ -+ unsigned long flags; -+ -+ EP4_TXD_ASSERT_FREE(txdRail); -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_freelock, flags); -+ -+ list_add (&txdRail->txd_generic.Link, &xmtrRail->xmtr_freelist); -+ -+ xmtrRail->xmtr_freecount++; -+ -+ if (xmtrRail->xmtr_freewaiting) -+ { -+ xmtrRail->xmtr_freewaiting--; -+ kcondvar_wakeupall (&xmtrRail->xmtr_freesleep, &xmtrRail->xmtr_freelock); -+ } -+ -+ spin_unlock_irqrestore (&xmtrRail->xmtr_freelock, flags); -+} -+ -+static void -+bind_txd_rail (EP_TXD *txd, EP4_TXD_RAIL *txdRail) -+{ -+ EPRINTF6 (DBG_XMTR, "%s: bind_txd_rail: txd=%p txdRail=%p XID=%08x.%08x.%016llx\n", -+ XMTR_TO_RAIL(txdRail->txd_generic.XmtrRail)->r_generic.Name, txd, txdRail, -+ txd->Envelope.Xid.Generation, txd->Envelope.Xid.Handle, txd->Envelope.Xid.Unique); -+ -+ txd->TxdRail = &txdRail->txd_generic; -+ txdRail->txd_generic.Txd = txd; -+} -+ -+static void -+unbind_txd_rail (EP_TXD *txd, EP4_TXD_RAIL *txdRail) -+{ -+ EP4_TXD_ASSERT (txdRail, txd->TxdRail == &txdRail->txd_generic && txdRail->txd_generic.Txd == txd); -+ -+ EPRINTF6 (DBG_XMTR, "%s: unbind_txd_rail: txd=%p txdRail=%p XID=%08x.%08x.%016llx\n", -+ XMTR_TO_RAIL(txdRail->txd_generic.XmtrRail)->r_generic.Name, txd, txdRail, -+ txd->Envelope.Xid.Generation, txd->Envelope.Xid.Handle, txd->Envelope.Xid.Unique); -+ -+ -+ txdRail->txd_generic.Txd = NULL; -+ txd->TxdRail = NULL; -+} -+ -+static void -+initialise_txd (EP_TXD *txd, EP4_TXD_RAIL *txdRail, unsigned int phase) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) txdRail->txd_generic.XmtrRail; -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ -+ /* Flush the Elan TLB if mappings have changed */ -+ ep_perrail_dvma_sync (&rail->r_generic); -+ -+ /* Initialise the per-rail fields in the envelope */ -+ txd->Envelope.TxdRail = txdRail->txd_elan_addr; -+ txd->Envelope.NodeId = rail->r_generic.Position.pos_nodeid; -+ -+ /* Allocate a network error fixup cookie */ -+ txdRail->txd_cookie = ep4_neterr_cookie (rail, txd->NodeId) | EP4_COOKIE_STEN; -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ if ( epdebug_check_sum ) -+ txd->Envelope.CheckSum = ep_calc_check_sum( txd->Xmtr->Subsys->Subsys.Sys, &txd->Envelope, txd->Envelope.Frags, txd->Envelope.nFrags); -+ else -+#endif -+ txd->Envelope.CheckSum = 0; -+ -+ /* Initialise the per-rail events */ -+ switch (phase) -+ { -+ case EP_TXD_PHASE_ACTIVE: -+ { -+ unsigned int nsets = (txd->Envelope.nFrags ? txd->Envelope.nFrags : 1) + ( EP_IS_MULTICAST(txd->Envelope.Attr) ? 1 : 0); -+ -+ if (! EP_IS_RPC(txd->Envelope.Attr)) -+ { -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32 * nsets, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ txdRail->txd_main->txd_data = EP4_STATE_FINISHED; -+ } -+ else -+ { -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType), -+ E4_EVENT_INIT_VALUE(-32 * nsets , E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ txdRail->txd_main->txd_data = EP4_STATE_ACTIVE; -+ } -+ -+ txdRail->txd_main->txd_env = EP4_STATE_ACTIVE; -+ txdRail->txd_main->txd_done = EP4_STATE_ACTIVE; -+ break; -+ } -+ -+ case EP_TXD_PHASE_PASSIVE: -+ EP4_TXD_ASSERT (txdRail, EP_IS_RPC(txd->Envelope.Attr)); -+ -+ txdRail->txd_main->txd_env = EP4_STATE_FINISHED; -+ txdRail->txd_main->txd_data = EP4_STATE_FINISHED; -+ txdRail->txd_main->txd_done = EP4_STATE_ACTIVE; -+ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ break; -+ } -+ -+ if (EP_IS_NO_INTERRUPT(txd->Envelope.Attr)) -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_intr_cmd), NOP_CMD); -+} -+ -+static void -+terminate_txd_rail (EP4_XMTR_RAIL *xmtrRail, EP4_TXD_RAIL *txdRail) -+{ -+ EP4_SDRAM_ASSERT (TXD_TO_RAIL(txdRail),\ -+ (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType),\ -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS));\ -+ -+ /* clear the done flags - so that it will be ignored if an event interrupt is generated */ -+ txdRail->txd_main->txd_env = EP4_STATE_FREE; -+ txdRail->txd_main->txd_data = EP4_STATE_FREE; -+ txdRail->txd_main->txd_done = EP4_STATE_FREE; -+ -+#if defined(DEBUG_ASSERT) -+ if (sdram_assert) -+ { -+ ELAN4_DEV *dev = XMTR_TO_RAIL (xmtrRail)->r_ctxt.ctxt_dev; -+ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ } -+#endif -+} -+ -+static void -+defer_txd_rail (EP4_TXD_RAIL *txdRail) -+{ -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR(txdRail); -+ EP4_RAIL *rail = XMTR_TO_RAIL(xmtrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ EP_COMMS_SUBSYS *subsys = XMTR_TO_SUBSYS(xmtrRail); -+ -+ EPRINTF5 (DBG_XMTR, "%s: defer_txd_rail: xmtrRail=%p txdRail=%p env/data (%d,%d) not finished\n", -+ rail->r_generic.Name, xmtrRail, txdRail, (int)txdRail->txd_main->txd_env, (int)txdRail->txd_main->txd_data); -+ -+ /* transmit has completed, but the data dma has not completed -+ * (because of network error fixup), we queue the txdRail onto a list -+ * to be polled for completion later. -+ */ -+ if (txdRail->txd_retry_time) -+ { -+ EP4_TXD_ASSERT (txdRail, (on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY]) == 1 || -+ on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]) == 1)); -+ -+ list_del (&txdRail->txd_retry_link); -+ -+ txdRail->txd_main->txd_env = EP4_STATE_FINISHED; -+ -+ /* re-initialise the envelope event */ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ } -+ -+ txdRail->txd_retry_time = lbolt; -+ -+ list_add_tail (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_POLL]); -+ -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+} -+ -+static void -+finalise_txd (EP_TXD *txd, EP4_TXD_RAIL *txdRail) -+{ -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR(txdRail); -+ -+ EP4_TXD_ASSERT_FINISHED (txdRail); -+ -+ unbind_txd_rail (txd, txdRail); -+ -+ terminate_txd_rail (xmtrRail, txdRail); -+ free_txd_rail (xmtrRail, txdRail); -+} -+ -+static void -+txd_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) arg; -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR(txdRail); -+ EP_XMTR *xmtr = xmtrRail->xmtr_generic.Xmtr; -+ int delay = 1; -+ EP_TXD *txd; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ for (;;) -+ { -+ if (txdRail->txd_main->txd_done == EP4_STATE_FINISHED || txdRail->txd_main->txd_env == EP4_STATE_FAILED) -+ break; -+ -+ /* The write to txd_done could be held up in the PCI bridge even though -+ * we've seen the interrupt cookie. Unlike elan3, there is no possibility -+ * of spurious interrupts since we flush the command queues on node -+ * disconnection and the txcallback mechanism */ -+ mb(); -+ -+ if (delay > EP4_EVENT_FIRING_TLIMIT) -+ { -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ EP_ASSFAIL (XMTR_TO_RAIL(xmtrRail), "txd_interrupt - not finished\n"); -+ return; -+ } -+ DELAY (delay); -+ delay <<= 1; -+ } -+ -+ txd = txdRail->txd_generic.Txd; -+ -+ if (txdRail->txd_main->txd_env == EP4_STATE_FAILED) -+ { -+ spin_lock (&xmtrRail->xmtr_retrylock); -+ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_retry_time == 0); /* cannot be on retry/poll list */ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_main->txd_done != EP4_STATE_FINISHED); /* data xfer cannot have finished */ -+ -+ if (TxdShouldStabalise (&txdRail->txd_generic, &rail->r_generic)) -+ { -+ EPRINTF6 (DBG_STABILISE, "%s: txd_interrupt: stablise xmtrRail=%p txdRail=%p txd=%p XID=%llx dest=%u\n", rail->r_generic.Name, -+ xmtrRail, txdRail, txd, txd->Envelope.Xid.Unique, txd->NodeId); -+ -+ txdRail->txd_retry_time = lbolt; /* indicate on retry list */ -+ -+ list_add_tail (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]); -+ } -+ else -+ { -+ EPRINTF6 (DBG_RETRY, "%s: txd_interrupt: retry xmtrRail=%p txdRail=%p txd=%p XID=%llx dest=%u\n", rail->r_generic.Name, -+ xmtrRail, txdRail, txd, txd->Envelope.Xid.Unique, txd->NodeId); -+ -+ txdRail->txd_retry_time = lbolt + EP_RETRY_LOW_PRI_TIME; /* XXXX: backoff ? */ -+ -+ list_add_tail (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY]); -+ -+ ep_kthread_schedule (&rail->r_retry_thread, txdRail->txd_retry_time); -+ } -+ spin_unlock (&xmtrRail->xmtr_retrylock); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ return; -+ } -+ -+ EP4_TXD_ASSERT (txdRail, txd != NULL && !(EP_IS_NO_INTERRUPT(txd->Envelope.Attr))); -+ -+ EPRINTF6 (DBG_XMTR, "%s: txd_interrupt: xmtrRail=%p txdRail=%p txd=%p XID=%llx dest=%u\n", rail->r_generic.Name, -+ xmtrRail, txdRail, txd, txd->Envelope.Xid.Unique, txd->NodeId); -+ -+ if (txdRail->txd_main->txd_env != EP4_STATE_FINISHED || txdRail->txd_main->txd_data != EP4_STATE_FINISHED) -+ { -+ defer_txd_rail (txdRail); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ } -+ else -+ { -+ /* remove from active transmit list */ -+ list_del (&txd->Link); -+ -+ ep_xmtr_txd_stat(xmtr,txd); -+ -+ finalise_txd (txd, txdRail); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ txd->Handler (txd, txd->Arg, EP_SUCCESS); -+ -+ FreeTxd (xmtr, txd); -+ } -+} -+ -+static void -+poll_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) arg; -+ -+ ep_poll_transmits (xmtrRail->xmtr_generic.Xmtr); -+} -+ -+void -+issue_envelope_packet (EP4_XMTR_RAIL *xmtrRail, EP4_TXD_RAIL *txdRail) -+{ -+ EP_TXD *txd = txdRail->txd_generic.Txd; -+ ELAN4_CQ *cq = xmtrRail->xmtr_cq; -+ E4_uint64 *blk0 = (E4_uint64 *) &txd->Envelope; -+ E4_uint64 *blk1 = EP_HAS_PAYLOAD(txd->Envelope.Attr) ? (E4_uint64 *) &txd->Payload : NULL; -+ E4_Addr qaddr = EP_MSGQ_ADDR(txd->Service); -+ -+ EP4_SDRAM_ASSERT (TXD_TO_RAIL(txdRail),\ -+ (txdRail)->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType),\ -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS));\ -+ -+ elan4_open_packet (cq, OPEN_PACKET (0, PACK_OK | RESTART_COUNT_ZERO, EP_VP_DATA(txd->NodeId))); -+ elan4_sendtrans0 (cq, TR_INPUT_Q_GETINDEX, EP_MSGQ_ADDR(txd->Service)); -+ -+ /* send the payload if present */ -+ if (blk0) elan4_sendtransp (cq, TR_WRITE(128 >> 3, 0, TR_DATATYPE_BYTE), 0, blk0); -+ if (blk1) elan4_sendtransp (cq, TR_WRITE(128 >> 3, 0, TR_DATATYPE_BYTE), 128, blk1); -+ -+ elan4_sendtrans1 (cq, TR_INPUT_Q_COMMIT, qaddr, txdRail->txd_cookie); -+ -+ elan4_guard (cq, GUARD_CHANNEL (1) | GUARD_TEST(0, PACK_OK) | GUARD_RESET (EP4_STEN_RETRYCOUNT)); -+ elan4_write_dword_cmd (cq, txdRail->txd_main_addr + offsetof (EP4_TXD_RAIL_MAIN, txd_env), EP4_STATE_FINISHED); -+ -+ elan4_guard (cq, GUARD_CHANNEL (1) | GUARD_TEST(0, RESTART_COUNT_ZERO) | GUARD_RESET (EP4_STEN_RETRYCOUNT)); -+ elan4_set_event_cmd (cq, txdRail->txd_elan_addr + offsetof (EP4_TXD_RAIL_ELAN, txd_env)); -+ -+ elan4_write_dword_cmd (cq, xmtrRail->xmtr_main_addr + offsetof (EP4_XMTR_RAIL_MAIN, xmtr_flowcnt), ++xmtrRail->xmtr_flowcnt); -+} -+ -+void -+ep4xmtr_flush_callback (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail) -+{ -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ EP4_COMMS_RAIL *commsRail = XMTR_TO_COMMS (xmtrRail); -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ switch (rail->r_generic.CallbackStep) -+ { -+ case EP_CB_FLUSH_FILTERING: -+ /* need to acquire/release the Lock to ensure that the node state -+ * transition has been noticed and no new envelopes are queued to -+ * nodes which are passivating. */ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ /* Then we insert a "setevent" into the command queue to flush -+ * through the envelopes which have already been submitted */ -+ ep4comms_flush_setevent (commsRail, xmtrRail->xmtr_cq); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ break; -+ -+ case EP_CB_FLUSH_FLUSHING: -+ /* remove any envelopes which are retrying to nodes which are going down */ -+ spin_lock_irqsave (&xmtrRail->xmtr_retrylock, flags); -+ list_for_each_safe (el, nel, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY]) { -+ EP4_TXD_RAIL *txdRail = list_entry (el, EP4_TXD_RAIL, txd_retry_link); -+ EP_TXD *txd = txdRail->txd_generic.Txd; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[txd->NodeId]; -+ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_main->txd_env == EP4_STATE_FAILED); -+ -+ if (nodeRail->State == EP_NODE_LOCAL_PASSIVATE) -+ { -+ EPRINTF2 (DBG_XMTR, "%s; ep4xmtr_flush_callback: removing txdRail %p from retry list\n", rail->r_generic.Name, txdRail); -+ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_retry_time != 0); -+ -+ list_del (&txdRail->txd_retry_link); -+ list_add_tail (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]); -+ } -+ } -+ spin_unlock_irqrestore (&xmtrRail->xmtr_retrylock, flags); -+ -+ /* Determine whether we have active or passive messages to -+ * any node which is passivating */ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each (el, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) txd->TxdRail; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[txd->NodeId]; -+ -+ if (txdRail == NULL || txdRail->txd_generic.XmtrRail != &xmtrRail->xmtr_generic || nodeRail->State != EP_NODE_LOCAL_PASSIVATE) -+ continue; -+ -+ EPRINTF5 (DBG_XMTR, "%s: flush txd=%p txdRail=%p data=%llx done=%llx\n", rail->r_generic.Name, -+ txd, txdRail, txdRail->txd_main->txd_data, txdRail->txd_main->txd_done); -+ -+ if (EP_IS_RPC(txd->Envelope.Attr)) -+ { -+ if (txdRail->txd_main->txd_data == EP4_STATE_ACTIVE) -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ else if (txdRail->txd_main->txd_data == EP4_STATE_ACTIVE) -+ nodeRail->MessageState |= EP_NODE_PASSIVE_MESSAGES; -+ } -+ else -+ { -+ if (txdRail->txd_main->txd_data == EP4_STATE_ACTIVE) -+ nodeRail->MessageState |= EP_NODE_ACTIVE_MESSAGES; -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ break; -+ -+ default: -+ panic ("ep4xmtr_flush_callback: invalid callback step\n"); -+ break; -+ } -+} -+ -+void -+ep4xmtr_failover_callback (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail) -+{ -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ struct list_head txdList; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&txdList); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) txd->TxdRail; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[txd->NodeId]; -+ -+ /* Only progress relocation of txd's bound to this rail */ -+ if (! TXD_BOUND2RAIL (txdRail, xmtrRail) || nodeRail->State != EP_NODE_PASSIVATED) -+ continue; -+ -+ /* XXXX - no rail failover for now ....*/ -+ -+ EPRINTF4 (DBG_XMTR, "%s: ep4xmtr_failover_callback - xmtr %p txd %p node %d completed\n", rail->r_generic.Name, xmtr, txd, txd->NodeId); -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ while (! list_empty (&txdList)) -+ { -+ EP_TXD *txd = list_entry (txdList.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ txd->Handler (txd, txd->Arg, EP_CONN_RESET); -+ -+ FreeTxd (xmtr, txd); -+ } -+} -+ -+ -+void -+ep4xmtr_disconnect_callback (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail) -+{ -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el, *nel; -+ struct list_head txdList; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&txdList); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ list_for_each_safe (el, nel, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) txd->TxdRail; -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[txd->NodeId]; -+ -+ if ( ! TXD_BOUND2RAIL (txdRail, xmtrRail) || nodeRail->State != EP_NODE_DISCONNECTING) -+ continue; -+ -+ if (txdRail->txd_main->txd_done == EP4_STATE_ACTIVE) -+ { -+ -+ EPRINTF8 (DBG_DISCON, "ep4xmtr_disconnect_callback: txdRail=%p : events %llx,%llx,%llx done %llx,%llx,%llx retry %lx\n",txdRail, -+ elan4_sdram_readq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType)), -+ elan4_sdram_readq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType)), -+ elan4_sdram_readq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType)), -+ txdRail->txd_main->txd_env, txdRail->txd_main->txd_data, txdRail->txd_main->txd_done, -+ txdRail->txd_retry_time); -+ -+ if (txdRail->txd_retry_time) -+ { -+ /* re-initialise the envelope event */ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ EP4_TXD_ASSERT (txdRail, on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]) == 1); -+ -+ txdRail->txd_retry_time = 0; -+ -+ list_del (&txdRail->txd_retry_link); -+ } -+ -+ /* Remove from active list */ -+ list_del (&txd->Link); -+ -+ unbind_txd_rail (txd, txdRail); -+ -+ terminate_txd_rail (xmtrRail, txdRail); -+ free_txd_rail (xmtrRail, txdRail); -+ -+ EPRINTF4 (DBG_XMTR, "%s: ep4xmtr_disconnect_callback - xmtr %p txd %p node %d not conected\n", rail->r_generic.Name, xmtr, txd, txd->NodeId); -+ -+ /* add to the list of txd's which are to be completed */ -+ list_add_tail (&txd->Link, &txdList); -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ while (! list_empty (&txdList)) -+ { -+ EP_TXD *txd = list_entry (txdList.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ txd->Handler (txd, txd->Arg, EP_CONN_RESET); -+ -+ FreeTxd (xmtr, txd); -+ } -+} -+ -+void -+ep4xmtr_neterr_flush (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP4_COMMS_RAIL *commsRail = XMTR_TO_COMMS (xmtrRail); -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ /* insert a "setevent" into the command queue to flush -+ * through the envelopes which have already been submitted */ -+ ep4comms_flush_setevent (commsRail, xmtrRail->xmtr_cq); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+} -+ -+void -+ep4xmtr_neterr_check (EP_XMTR *xmtr, EP4_XMTR_RAIL *xmtrRail, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each (el, &xmtr->ActiveDescList) { -+ EP_TXD *txd = list_entry (el, EP_TXD, Link); -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) txd->TxdRail; -+ -+ if ( ! TXD_BOUND2RAIL (txdRail, xmtrRail) || txd->NodeId != nodeId) -+ continue; -+ -+ /* The only non-dma associated with a txd is the initial sten packet, if it has been acked -+ * and the neterr cookie matches, then change it to look like it's been acked since the -+ * INPUT_Q_COMMIT transaction has already been executed */ -+ if (txdRail->txd_main->txd_env == EP4_STATE_FAILED && (txdRail->txd_cookie == cookies[0] || txdRail->txd_cookie == cookies[1])) -+ { -+ EPRINTF4 (DBG_NETWORK_ERROR, "%s: ep4xmtr_neterr_callback: cookie <%lld%s%s%s%s> matches txd %p txdRail %p\n", -+ rail->r_generic.Name, EP4_COOKIE_STRING(txdRail->txd_cookie), txd, txdRail); -+ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_retry_time != 0); -+ -+ txdRail->txd_main->txd_env = EP4_STATE_FINISHED; -+ -+ /* re-initialise the envelope event */ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ spin_lock (&xmtrRail->xmtr_retrylock); -+ -+ EP4_TXD_ASSERT (txdRail, (on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY]) == 1 || -+ on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]) == 1)); -+ -+ txdRail->txd_retry_time = 0; -+ -+ list_del (&txdRail->txd_retry_link); -+ -+ spin_unlock (&xmtrRail->xmtr_retrylock); -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+} -+ -+int -+ep4xmtr_poll_txd (EP_XMTR_RAIL *x, EP_TXD_RAIL *t, int how) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) x; -+ ELAN4_DEV *dev = XMTR_TO_DEV (xmtrRail); -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) t; -+ EP_TXD *txd = txdRail->txd_generic.Txd; -+ -+ if (! EP_IS_NO_INTERRUPT(txd->Envelope.Attr)) -+ return 0; -+ -+ switch (how) -+ { -+ case ENABLE_TX_CALLBACK: -+ if (!EP_IS_INTERRUPT_ENABLED(txd->Envelope.Attr)) -+ { -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_intr_cmd), -+ INTERRUPT_CMD | (xmtrRail->xmtr_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ txd->Envelope.Attr |= EP_INTERRUPT_ENABLED; -+ } -+ break; -+ -+ case DISABLE_TX_CALLBACK: -+ if (EP_IS_INTERRUPT_ENABLED(txd->Envelope.Attr & EP_INTERRUPT_ENABLED)) -+ { -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_intr_cmd), NOP_CMD); -+ -+ txd->Envelope.Attr &= ~EP_INTERRUPT_ENABLED; -+ } -+ } -+ -+ if (txdRail->txd_main->txd_env == EP4_STATE_FINISHED && txdRail->txd_main->txd_data == EP4_STATE_FINISHED && txdRail->txd_main->txd_done == EP4_STATE_FINISHED) -+ { -+ EPRINTF3 (DBG_XMTR, "%s: ep4xmtr_poll_txd: txd=%p XID=%llx completed\n", -+ XMTR_TO_RAIL (xmtrRail)->r_generic.Name, txd, txd->Envelope.Xid.Unique); -+ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_done_cmd.c_intr_cmd), -+ INTERRUPT_CMD | (txdRail->txd_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ -+ ep_xmtr_txd_stat(xmtrRail->xmtr_generic.Xmtr,txd); -+ -+ finalise_txd (txd, txdRail); -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+ep4xmtr_bind_txd (EP_TXD *txd, EP_XMTR_RAIL *x, unsigned int phase) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) x; -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ EP4_TXD_RAIL *txdRail; -+ unsigned long flags; -+ -+ if ((txdRail = get_txd_rail (xmtrRail)) == NULL) -+ return 0; -+ -+ switch (phase) -+ { -+ case EP_TXD_PHASE_ACTIVE: -+ if (rail->r_generic.Nodes[txd->NodeId].State != EP_NODE_CONNECTED) -+ { -+ EPRINTF2 (DBG_XMTR, "%s: ep4xmtr_bind_txd: node %u not connected on this rail\n", rail->r_generic.Name, txd->NodeId); -+ -+ free_txd_rail (xmtrRail, txdRail); -+ return 0; -+ } -+ -+ initialise_txd (txd, txdRail, EP_TXD_PHASE_ACTIVE); -+ -+ bind_txd_rail (txd, txdRail); -+ -+ /* generate the STEN packet to transfer the envelope */ -+ spin_lock_irqsave (&xmtrRail->xmtr_retrylock, flags); -+ if (((int) (xmtrRail->xmtr_flowcnt - xmtrRail->xmtr_main->xmtr_flowcnt)) < EP4_XMTR_FLOWCNT) -+ issue_envelope_packet (xmtrRail, txdRail); -+ else -+ { -+ txdRail->txd_retry_time = lbolt; -+ -+ list_add_tail (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY]); -+ -+ ep_kthread_schedule (&rail->r_retry_thread, txdRail->txd_retry_time); -+ } -+ spin_unlock_irqrestore (&xmtrRail->xmtr_retrylock, flags); -+ break; -+ -+ case EP_TXD_PHASE_PASSIVE: -+ initialise_txd (txd, txdRail, EP_TXD_PHASE_PASSIVE); -+ -+ EP_XMTR_OP (txd->TxdRail->XmtrRail, UnbindTxd) (txd, EP_TXD_PHASE_PASSIVE); /* unbind from existing rail */ -+ -+ bind_txd_rail (txd, txdRail); /* and bind it to our new rail */ -+ break; -+ } -+ -+ return 1; -+} -+ -+void -+ep4xmtr_unbind_txd (EP_TXD *txd, unsigned int phase) -+{ -+ /* XXXX - TBD */ -+} -+ -+long -+ep4xmtr_check (EP_XMTR_RAIL *x, long nextRunTime) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) x; -+ EP_XMTR *xmtr = xmtrRail->xmtr_generic.Xmtr; -+ struct list_head txdList; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&txdList); -+ -+ if (xmtrRail->xmtr_freecount < ep_txd_lowat && !alloc_txd_block (xmtrRail)) -+ { -+ EPRINTF1 (DBG_RCVR,"%s: failed to grow txd rail pool\n", XMTR_TO_RAIL(xmtrRail)->r_generic.Name); -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + RESOURCE_RETRY_TIME)) -+ nextRunTime = lbolt + RESOURCE_RETRY_TIME; -+ } -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ list_for_each_safe (el, nel, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_POLL]) { -+ EP4_TXD_RAIL *txdRail = list_entry (el, EP4_TXD_RAIL, txd_retry_link); -+ -+ if (txdRail->txd_main->txd_env != EP4_STATE_FINISHED || txdRail->txd_main->txd_data != EP4_STATE_FINISHED) -+ { -+ ep_debugf (DBG_XMTR, "%s: ep4xmtr_check: xmtrRail=%p txdRail=%p env/data (%d,%d) not finished\n", -+ XMTR_TO_RAIL(xmtrRail)->r_generic.Name, xmtrRail, txdRail, (int)txdRail->txd_main->txd_env, (int)txdRail->txd_main->txd_data); -+ -+ nextRunTime = lbolt + HZ; -+ } -+ else -+ { -+ EP_TXD *txd = txdRail->txd_generic.Txd; -+ -+ ep_debugf (DBG_XMTR, "%s: ep4xmtr_check: xmtrRail=%p txdRail=%p env/data (%d,%d) finished\n", -+ XMTR_TO_RAIL(xmtrRail)->r_generic.Name, xmtrRail, txdRail, (int)txdRail->txd_main->txd_env, (int)txdRail->txd_main->txd_data); -+ -+ EPRINTF5 (DBG_XMTR, "%s: ep4xmtr_check: xmtrRail=%p txdRail=%p env/data (%d,%d) finished\n", -+ XMTR_TO_RAIL(xmtrRail)->r_generic.Name, xmtrRail, txdRail, (int)txdRail->txd_main->txd_env, (int)txdRail->txd_main->txd_data); -+ EPRINTF3 (DBG_XMTR, "%s: done %x data %x\n", XMTR_TO_RAIL(xmtrRail)->r_generic.Name, -+ txdRail->txd_elan_addr + offsetof (EP4_TXD_RAIL_ELAN, txd_done), -+ txdRail->txd_elan_addr + offsetof (EP4_TXD_RAIL_ELAN, txd_data)); -+ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_retry_time != 0); -+ -+ /* remove txd from active list and add to list to call handlers */ -+ list_del (&txd->Link); -+ list_add_tail (&txd->Link, &txdList); -+ -+ /* remove and free of txdRail */ -+ txdRail->txd_retry_time = 0; -+ list_del (&txdRail->txd_retry_link); -+ -+ finalise_txd (txd, txdRail); -+ -+ } -+ } -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ while (! list_empty (&txdList)) -+ { -+ EP_TXD *txd = list_entry (txdList.next, EP_TXD, Link); -+ -+ list_del (&txd->Link); -+ -+ ep_xmtr_txd_stat (xmtr,txd); -+ -+ txd->Handler (txd, txd->Arg, EP_SUCCESS); -+ -+ FreeTxd (xmtr, txd); -+ } -+ -+ return nextRunTime; -+} -+ -+unsigned long -+ep4xmtr_retry (EP4_RAIL *rail, void *arg, unsigned long nextRunTime) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) arg; -+ ELAN4_DEV *dev = XMTR_TO_DEV(xmtrRail); -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_retrylock, flags); -+ while (! list_empty (&xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY])) -+ { -+ EP4_TXD_RAIL *txdRail = list_entry (xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY].next, EP4_TXD_RAIL, txd_retry_link); -+ -+ if (BEFORE (lbolt, txdRail->txd_retry_time)) -+ { -+ if (nextRunTime == 0 || AFTER (nextRunTime, txdRail->txd_retry_time)) -+ nextRunTime = txdRail->txd_retry_time; -+ -+ break; -+ } -+ -+ if (((int) (xmtrRail->xmtr_flowcnt - xmtrRail->xmtr_main->xmtr_flowcnt)) < EP4_XMTR_FLOWCNT) -+ { -+ txdRail->txd_retry_time = 0; -+ -+ list_del (&txdRail->txd_retry_link); -+ -+ /* re-initialise the envelope event */ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ EPRINTF3 (DBG_RETRY, "%s: ep4xmtr_retry: re-issue envelope packet to %d for txdRail=%p\n", -+ rail->r_generic.Name, txdRail->txd_generic.Txd->Envelope.NodeId, txdRail); -+ -+ txdRail->txd_main->txd_env = EP4_STATE_ACTIVE; -+ -+ issue_envelope_packet (xmtrRail, txdRail); -+ } -+ else -+ { -+ EPRINTF2 (DBG_RETRY, "%s: ep4xmtr_retry: cannot re-issue envelope packet to %d\n", rail->r_generic.Name, txdRail->txd_generic.Txd->Envelope.NodeId); -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, txdRail->txd_retry_time)) -+ nextRunTime = txdRail->txd_retry_time; -+ -+ break; -+ } -+ } -+ spin_unlock_irqrestore (&xmtrRail->xmtr_retrylock, flags); -+ -+ return nextRunTime; -+} -+ -+void -+ep4xmtr_add_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->Rail; -+ EP_COMMS_SUBSYS *subsys = xmtr->Subsys; -+ EP4_XMTR_RAIL *xmtrRail; -+ unsigned long flags; -+ int i; -+ -+ KMEM_ZALLOC (xmtrRail, EP4_XMTR_RAIL *, sizeof (EP4_XMTR_RAIL), 1); -+ -+ spin_lock_init (&xmtrRail->xmtr_freelock); -+ kcondvar_init (&xmtrRail->xmtr_freesleep); -+ INIT_LIST_HEAD (&xmtrRail->xmtr_freelist); -+ INIT_LIST_HEAD (&xmtrRail->xmtr_blocklist); -+ -+ for (i = 0; i < EP4_TXD_NUM_LISTS; i++) -+ INIT_LIST_HEAD (&xmtrRail->xmtr_retrylist[i]); -+ spin_lock_init (&xmtrRail->xmtr_retrylock); -+ -+ xmtrRail->xmtr_generic.CommsRail = commsRail; -+ xmtrRail->xmtr_generic.Xmtr = xmtr; -+ -+ xmtrRail->xmtr_main = ep_alloc_main (&rail->r_generic, sizeof (EP4_XMTR_RAIL_MAIN), 0, &xmtrRail->xmtr_main_addr); -+ xmtrRail->xmtr_cq = elan4_alloccq (&rail->r_ctxt, EP4_XMTR_CQSIZE, CQ_EnableAllBits, CQ_Priority); -+ -+ xmtrRail->xmtr_retryops.op_func = ep4xmtr_retry; -+ xmtrRail->xmtr_retryops.op_arg = xmtrRail; -+ -+ ep4_add_retry_ops (rail, &xmtrRail->xmtr_retryops); -+ -+ ep4_register_intcookie (rail, &xmtrRail->xmtr_intcookie, xmtrRail->xmtr_main_addr, -+ poll_interrupt, xmtrRail); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ -+ xmtr->Rails[commsRail->Rail->Number] = &xmtrRail->xmtr_generic; -+ xmtr->RailMask |= EP_RAIL2RAILMASK(commsRail->Rail->Number); -+ -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ ep_kthread_schedule (&subsys->Thread, lbolt); -+ -+ ep_procfs_xmtr_add_rail(&(xmtrRail->xmtr_generic)); -+} -+ -+void -+ep4xmtr_del_rail (EP_XMTR *xmtr, EP_COMMS_RAIL *commsRail) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) commsRail->Rail; -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) xmtr->Rails[commsRail->Rail->Number]; -+ unsigned long flags; -+ -+ /* rail mask set as not usable */ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ xmtr->RailMask &= ~EP_RAIL2RAILMASK (rail->r_generic.Number); -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ ep_procfs_xmtr_del_rail(&(xmtrRail->xmtr_generic)); -+ -+ /* wait for all txd's for this rail to become free */ -+ spin_lock_irqsave (&xmtrRail->xmtr_freelock, flags); -+ while (xmtrRail->xmtr_freecount != xmtrRail->xmtr_totalcount) -+ { -+ xmtrRail->xmtr_freewaiting++; -+ kcondvar_wait (&xmtrRail->xmtr_freesleep, &xmtrRail->xmtr_freelock, &flags); -+ } -+ spin_unlock_irqrestore (&xmtrRail->xmtr_freelock, flags); -+ -+ spin_lock_irqsave (&xmtr->Lock, flags); -+ xmtr->Rails[commsRail->Rail->Number] = NULL; -+ spin_unlock_irqrestore (&xmtr->Lock, flags); -+ -+ /* all the txd's accociated with DescBlocks must be in the freelist */ -+ ASSERT (xmtrRail->xmtr_totalcount == xmtrRail->xmtr_freecount); -+ -+ /* run through the DescBlockList deleting them */ -+ while (!list_empty (&xmtrRail->xmtr_blocklist)) -+ free_txd_block (xmtrRail, list_entry(xmtrRail->xmtr_blocklist.next, EP4_TXD_RAIL_BLOCK , blk_link)); -+ -+ /* it had better be empty after that */ -+ ASSERT ((xmtrRail->xmtr_freecount == 0) && (xmtrRail->xmtr_totalcount == 0)); -+ -+ ep4_deregister_intcookie (rail, &xmtrRail->xmtr_intcookie); -+ -+ ep4_remove_retry_ops (rail, &xmtrRail->xmtr_retryops); -+ -+ elan4_freecq (&rail->r_ctxt, xmtrRail->xmtr_cq); -+ ep_free_main (&rail->r_generic, xmtrRail->xmtr_main_addr, sizeof (EP4_XMTR_RAIL_MAIN)); -+ -+ spin_lock_destroy (&xmtrRail->xmtr_retrylock); -+ -+ spin_lock_destroy (&xmtrRail->xmtr_freelock); -+ kcondvar_destroy (&xmtrRail->xmtr_freesleep); -+ -+ KMEM_FREE (xmtrRail, sizeof (EP4_XMTR_RAIL)); -+} -+ -+void -+ep4xmtr_display_xmtr (DisplayInfo *di, EP_XMTR_RAIL *x) -+{ -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) x; -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ unsigned int freeCount = 0; -+ unsigned int pollCount = 0; -+ unsigned int stalledCount = 0; -+ unsigned int retryCount = 0; -+ struct list_head *el; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_freelock, flags); -+ list_for_each (el, &xmtrRail->xmtr_freelist) -+ freeCount++; -+ spin_unlock_irqrestore (&xmtrRail->xmtr_freelock, flags); -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_retrylock, flags); -+ list_for_each (el, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_POLL]) -+ pollCount++; -+ list_for_each (el, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]) -+ stalledCount++; -+ list_for_each (el, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY]) -+ retryCount++; -+ spin_unlock_irqrestore (&xmtrRail->xmtr_retrylock, flags); -+ -+ (di->func)(di->arg, " rail=%d free=%d total=%d (%d) (retry %d,%d,%d)\n", -+ rail->r_generic.Number, xmtrRail->xmtr_freecount, xmtrRail->xmtr_totalcount, -+ freeCount, pollCount, stalledCount, retryCount); -+ (di->func)(di->arg, " cq %d flowcnt %lld,%lld\n", elan4_cq2num (xmtrRail->xmtr_cq), xmtrRail->xmtr_flowcnt, xmtrRail->xmtr_main->xmtr_flowcnt); -+} -+ -+void -+ep4xmtr_display_txd (DisplayInfo *di, EP_TXD_RAIL *t) -+{ -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) t; -+ EP4_XMTR_RAIL *xmtrRail = TXD_TO_XMTR(txdRail); -+ EP4_TXD_RAIL_MAIN *txdMain = txdRail->txd_main; -+ sdramaddr_t txdElan = txdRail->txd_elan; -+ EP4_RAIL *rail = XMTR_TO_RAIL (xmtrRail); -+ ELAN4_DEV *dev = XMTR_TO_DEV (xmtrRail); -+ char *list = ""; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_retrylock, flags); -+ if (txdRail->txd_retry_time) -+ { -+ if (on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_POLL])) -+ list = " poll"; -+ else if (on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED])) -+ list = " stalled"; -+ else if (on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_RETRY])) -+ list = " retry"; -+ else -+ list = " ERROR"; -+ } -+ spin_unlock_irqrestore (&xmtrRail->xmtr_retrylock, flags); -+ -+ (di->func)(di->arg, " Rail %d txd %p elan %lx (%x) main %p (%x) cookie <%lld%s%s%s%s> ecq %d %s\n", rail->r_generic.Number, -+ txdRail, txdRail->txd_elan, txdRail->txd_elan_addr, txdRail->txd_main, txdRail->txd_main_addr, -+ EP4_COOKIE_STRING(txdRail->txd_cookie), elan4_cq2num (txdRail->txd_ecq->ecq_cq), list); -+ -+ (di->func)(di->arg, " env %016llx %016llx %016llx -> %016llx\n", -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType)), -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_Params[0])), -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_Params[1])), -+ txdMain->txd_env); -+ (di->func)(di->arg, " data %016llx %016llx %016llx -> %016llx\n", -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_CountAndType)), -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_Params[0])), -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_data.ev_Params[1])), -+ txdMain->txd_data); -+ (di->func)(di->arg, " done %016llx %016llx %016llx -> %016llx\n", -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_CountAndType)), -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_Params[0])), -+ elan4_sdram_readq (dev, txdElan + offsetof (EP4_TXD_RAIL_ELAN, txd_done.ev_Params[1])), -+ txdMain->txd_done); -+} -+ -+int -+ep4xmtr_check_txd_state (EP_TXD *txd) -+{ -+ EP4_TXD_RAIL *txdRail = (EP4_TXD_RAIL *) txd->TxdRail; -+ EP4_XMTR_RAIL *xmtrRail = (EP4_XMTR_RAIL *) txdRail->txd_generic.XmtrRail; -+ ELAN4_DEV *dev = XMTR_TO_DEV (xmtrRail); -+ unsigned long flags; -+ -+ if (txdRail->txd_main->txd_env == EP4_STATE_FINISHED) -+ return 0; -+ -+ EP4_TXD_ASSERT (txdRail, txdRail->txd_retry_time != 0); -+ -+ spin_lock_irqsave (&xmtrRail->xmtr_retrylock, flags); -+ EP4_TXD_ASSERT (txdRail, on_list (&txdRail->txd_retry_link, &xmtrRail->xmtr_retrylist[EP4_TXD_LIST_STALLED]) == 1); -+ -+ list_del (&txdRail->txd_retry_link); -+ txdRail->txd_retry_time = 0; -+ spin_unlock_irqrestore (&xmtrRail->xmtr_retrylock, flags); -+ -+ /* re-initialise the envelope event */ -+ elan4_sdram_writeq (dev, txdRail->txd_elan + offsetof (EP4_TXD_RAIL_ELAN, txd_env.ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_INTR_CMD_NDWORDS)); -+ -+ unbind_txd_rail (txd, txdRail); -+ -+ terminate_txd_rail (xmtrRail, txdRail); -+ free_txd_rail (xmtrRail, txdRail); -+ -+ return 1; -+} -+ -+void -+ep4xmtr_fillout_rail_stats(EP_XMTR_RAIL *xmtr_rail, char *str) { -+ /* no stats here yet */ -+ /* EP4_XMTR_RAIL * ep4xmtr_rail = (EP4_XMTR_RAIL *) xmtr_rail; */ -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/ep_procfs.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/ep_procfs.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/ep_procfs.c 2005-06-01 23:12:54.660429832 -0400 -@@ -0,0 +1,331 @@ -+ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: ep_procfs.c,v 1.5.6.3 2004/11/30 10:10:57 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/ep_procfs.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "cm.h" -+#include "debug.h" -+#include "conf_linux.h" -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "epcomms_elan4.h" -+ -+#include -+ -+struct proc_dir_entry *ep_procfs_xmtr_root; -+struct proc_dir_entry *ep_procfs_rcvr_root; -+ -+static int -+ep_proc_open (struct inode *inode, struct file *file) -+{ -+ PROC_PRIVATE *pr; -+ int pages = 4; -+ -+ if ((pr = kmalloc (sizeof (PROC_PRIVATE), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ do { -+ pr->pr_data_len = PAGESIZE * pages; -+ -+ KMEM_ZALLOC (pr->pr_data, char *, pr->pr_data_len, 1); -+ if (pr->pr_data == NULL) -+ { -+ pr->pr_len = sprintf (pr->pr_data, "Out of Memory\n"); -+ break; -+ } -+ -+ pr->pr_off = 0; -+ pr->pr_len = 0; -+ pr->pr_data[0] = 0; -+ -+ pr->pr_di.func = proc_character_fill; -+ pr->pr_di.arg = (long)pr; -+ -+ if (!strcmp("debug_xmtr", file->f_dentry->d_iname)) -+ { -+ EP_XMTR *xmtr = (EP_XMTR *)(PDE(inode)->data); -+ ep_display_xmtr (&pr->pr_di, xmtr); -+ } -+ -+ if (!strcmp("debug_rcvr", file->f_dentry->d_iname)) -+ { -+ EP_RCVR *rcvr = (EP_RCVR *)(PDE(inode)->data); -+ ep_display_rcvr (&pr->pr_di, rcvr, 0); -+ } -+ -+ if (!strcmp("debug_full", file->f_dentry->d_iname)) -+ { -+ EP_RCVR *rcvr = (EP_RCVR *)(PDE(inode)->data); -+ ep_display_rcvr (&pr->pr_di, rcvr, 1); -+ } -+ -+ if ( pr->pr_len < pr->pr_data_len) -+ break; /* we managed to get all the output into the buffer */ -+ -+ pages++; -+ KMEM_FREE ( pr->pr_data, pr->pr_data_len); -+ } while (1); -+ -+ -+ file->private_data = (void *) pr; -+ -+ MOD_INC_USE_COUNT; -+ return (0); -+} -+ -+struct file_operations ep_proc_operations = -+{ -+ read: proc_read, -+ open: ep_proc_open, -+ release: proc_release, -+}; -+ -+static int -+proc_read_rcvr_stats(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_RCVR *rcvr = (EP_RCVR *)data; -+ -+ if (rcvr == NULL) -+ sprintf(page,"proc_read_rcvr_stats rcvr=NULL\n"); -+ else { -+ page[0] = 0; -+ ep_rcvr_fillout_stats(rcvr,page); -+ } -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+static int -+proc_read_rcvr_rail_stats(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_RCVR_RAIL *rcvr_rail = (EP_RCVR_RAIL *)data; -+ -+ if (rcvr_rail == NULL) { -+ strcpy(page,"proc_read_rcvr_rail_stats rcvr_rail=NULL"); -+ } else { -+ page[0] = 0; -+ ep_rcvr_rail_fillout_stats(rcvr_rail, page); -+ EP_RCVR_OP(rcvr_rail,FillOutRailStats)(rcvr_rail,page); -+ } -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+void -+ep_procfs_rcvr_add(EP_RCVR *rcvr) -+{ -+ /* ep/rcvr/service_number/stats */ -+ /* ep/rcvr/service_number/debug_rcvr */ -+ /* ep/rcvr/service_number/debug_full */ -+ struct proc_dir_entry *p; -+ char str[32]; -+ -+ sprintf(str,"%d", rcvr->Service); -+ -+ rcvr->procfs_root = proc_mkdir (str, ep_procfs_rcvr_root); -+ -+ if ((p = create_proc_entry ("stats", 0, rcvr->procfs_root)) != NULL) -+ { -+ p->write_proc = NULL; -+ p->read_proc = proc_read_rcvr_stats; -+ p->data = rcvr; -+ p->owner = THIS_MODULE; -+ } -+ -+ if ((p = create_proc_entry ("debug_rcrv", 0, rcvr->procfs_root)) != NULL) -+ { -+ p->proc_fops = &ep_proc_operations; -+ p->owner = THIS_MODULE; -+ p->data = rcvr; -+ } -+ -+ if ((p = create_proc_entry ("debug_full", 0, rcvr->procfs_root)) != NULL) -+ { -+ p->proc_fops = &ep_proc_operations; -+ p->owner = THIS_MODULE; -+ p->data = rcvr; -+ } -+} -+ -+void -+ep_procfs_rcvr_del(EP_RCVR *rcvr) -+{ -+ char str[32]; -+ sprintf(str,"%d", rcvr->Service); -+ -+ remove_proc_entry ("stats", rcvr->procfs_root); -+ remove_proc_entry ("debug_rcvr", rcvr->procfs_root); -+ remove_proc_entry ("debug_full", rcvr->procfs_root); -+ -+ remove_proc_entry (str, ep_procfs_rcvr_root); -+} -+ -+void -+ep_procfs_rcvr_add_rail(EP_RCVR_RAIL *rcvrRail) -+{ -+ /* ep/rcvr/service_number/railN/stats */ -+ -+ struct proc_dir_entry *p; -+ char str[32]; -+ sprintf(str,"rail%d",rcvrRail->CommsRail->Rail->Number); -+ -+ rcvrRail->procfs_root = proc_mkdir (str, rcvrRail->Rcvr->procfs_root); -+ -+ if ((p = create_proc_entry ("stats", 0, rcvrRail->procfs_root)) != NULL) -+ { -+ p->write_proc = NULL; -+ p->read_proc = proc_read_rcvr_rail_stats; -+ p->data = rcvrRail; -+ p->owner = THIS_MODULE; -+ } -+} -+ -+void -+ep_procfs_rcvr_del_rail(EP_RCVR_RAIL *rcvrRail) -+{ -+ char str[32]; -+ sprintf(str,"rail%d",rcvrRail->CommsRail->Rail->Number); -+ -+ remove_proc_entry ("stats", rcvrRail->procfs_root); -+ -+ remove_proc_entry (str, rcvrRail->Rcvr->procfs_root); -+} -+ -+ -+ -+ -+static int -+proc_read_xmtr_stats(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_XMTR *xmtr = (EP_XMTR *)data; -+ -+ if (xmtr == NULL) -+ strcpy(page,"proc_read_xmtr_stats xmtr=NULL\n"); -+ else { -+ page[0] = 0; -+ ep_xmtr_fillout_stats(xmtr, page); -+ } -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+static int -+proc_read_xmtr_rail_stats(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_XMTR_RAIL *xmtr_rail = (EP_XMTR_RAIL *)data; -+ -+ if (xmtr_rail == NULL) -+ strcpy(page,"proc_read_xmtr_rail_stats xmtr_rail=NULL\n"); -+ else { -+ page[0] = 0; -+ ep_xmtr_rail_fillout_stats(xmtr_rail, page); -+ EP_XMTR_OP(xmtr_rail,FillOutRailStats)(xmtr_rail,page); -+ } -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+void -+ep_procfs_xmtr_add(EP_XMTR *xmtr) -+{ -+ /* ep/xmtr/service_number/stats */ -+ /* ep/xmtr/service_number/debug_xmtr */ -+ struct proc_dir_entry *p; -+ char str[32]; -+ -+ sprintf(str,"%llx", (unsigned long long) (unsigned long)xmtr); -+ -+ xmtr->procfs_root = proc_mkdir (str, ep_procfs_xmtr_root); -+ -+ if ((p = create_proc_entry ("stats", 0, xmtr->procfs_root)) != NULL) -+ { -+ p->write_proc = NULL; -+ p->read_proc = proc_read_xmtr_stats; -+ p->data = xmtr; -+ p->owner = THIS_MODULE; -+ } -+ -+ if ((p = create_proc_entry ("debug_xmtr", 0, xmtr->procfs_root)) != NULL) -+ { -+ p->proc_fops = &ep_proc_operations; -+ p->owner = THIS_MODULE; -+ p->data = xmtr; -+ } -+} -+ -+void -+ep_procfs_xmtr_del(EP_XMTR *xmtr) -+{ -+ char str[32]; -+ sprintf(str,"%llx", (unsigned long long) (unsigned long)xmtr); -+ -+ remove_proc_entry ("stats", xmtr->procfs_root); -+ remove_proc_entry ("debug_xmtr", xmtr->procfs_root); -+ -+ remove_proc_entry (str, ep_procfs_xmtr_root); -+} -+ -+void -+ep_procfs_xmtr_add_rail(EP_XMTR_RAIL *xmtrRail) -+{ -+ /* ep/xmtr/service_number/railN/stats */ -+ -+ struct proc_dir_entry *p; -+ char str[32]; -+ sprintf(str,"rail%d",xmtrRail->CommsRail->Rail->Number); -+ -+ xmtrRail->procfs_root = proc_mkdir (str, xmtrRail->Xmtr->procfs_root); -+ -+ if ((p = create_proc_entry ("stats", 0, xmtrRail->procfs_root)) != NULL) -+ { -+ p->write_proc = NULL; -+ p->read_proc = proc_read_xmtr_rail_stats; -+ p->data = xmtrRail; -+ p->owner = THIS_MODULE; -+ } -+} -+ -+void -+ep_procfs_xmtr_del_rail(EP_XMTR_RAIL *xmtrRail) -+{ -+ char str[32]; -+ sprintf(str,"rail%d",xmtrRail->CommsRail->Rail->Number); -+ -+ remove_proc_entry ("stats", xmtrRail->procfs_root); -+ -+ remove_proc_entry (str, xmtrRail->Xmtr->procfs_root); -+} -+ -+void -+ep_procfs_rcvr_xmtr_init(void) -+{ -+ ep_procfs_rcvr_root = proc_mkdir ("rcvr", ep_procfs_root); -+ ep_procfs_xmtr_root = proc_mkdir ("xmtr", ep_procfs_root); -+} -+ -+void -+ep_procfs_rcvr_xmtr_fini(void) -+{ -+ remove_proc_entry ("rcvr", ep_procfs_root); -+ remove_proc_entry ("xmtr", ep_procfs_root); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kalloc.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kalloc.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kalloc.c 2005-06-01 23:12:54.661429680 -0400 -@@ -0,0 +1,677 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kalloc.c,v 1.17.8.2 2004/12/14 10:19:14 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kalloc.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "debug.h" -+ -+static void -+HashInPool (EP_ALLOC *alloc, EP_POOL *pool) -+{ -+ int idx0 = HASH (pool->Handle.nmh_nmd.nmd_addr); -+ int idx1 = HASH (pool->Handle.nmh_nmd.nmd_addr + pool->Handle.nmh_nmd.nmd_len); -+ -+ list_add (&pool->HashBase, &alloc->HashBase[idx0]); -+ list_add (&pool->HashTop, &alloc->HashTop[idx1]); -+} -+ -+static void -+HashOutPool (EP_ALLOC *alloc, EP_POOL *pool) -+{ -+ list_del (&pool->HashBase); -+ list_del (&pool->HashTop); -+} -+ -+static EP_POOL * -+LookupPool (EP_ALLOC *alloc, EP_ADDR addr) -+{ -+ struct list_head *el; -+ -+ list_for_each (el, &alloc->HashBase[HASH(addr)]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, HashBase); -+ -+ if (pool->Handle.nmh_nmd.nmd_addr <= addr && addr < (pool->Handle.nmh_nmd.nmd_addr + pool->Handle.nmh_nmd.nmd_len)) -+ return (pool); -+ } -+ -+ list_for_each (el, &alloc->HashTop[HASH(addr)]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, HashTop); -+ -+ if (pool->Handle.nmh_nmd.nmd_addr <= addr && addr < (pool->Handle.nmh_nmd.nmd_addr + pool->Handle.nmh_nmd.nmd_len)) -+ return (pool); -+ } -+ -+ return (NULL); -+} -+ -+static EP_POOL * -+AllocatePool (EP_ALLOC *alloc, EP_ADDR addr, unsigned size, unsigned int perm, EP_ATTRIBUTE attr) -+{ -+ EP_ADDR base = 0; -+ EP_POOL *pool; -+ EP_RAIL *rail; -+ int i, railmask = 0; -+ struct list_head *el; -+ -+ KMEM_ZALLOC (pool, EP_POOL *, sizeof (EP_POOL), !(attr & EP_NO_SLEEP)); -+ -+ if (pool == NULL) -+ return (NULL); -+ -+ if (addr != 0) -+ base = addr; -+ else -+ { -+ for (i = LN2_MIN_SIZE; i <= LN2_MAX_SIZE; i ++) -+ { -+ KMEM_ZALLOC (pool->Bitmaps[i - LN2_MIN_SIZE], bitmap_t *, BT_BITOUL(1 << (LN2_MAX_SIZE-i)) * sizeof (bitmap_t), !(attr & EP_NO_SLEEP)); -+ if (pool->Bitmaps[i - LN2_MIN_SIZE] == NULL) -+ goto failed; -+ } -+ -+ if ((base = ep_rmalloc (alloc->ResourceMap, size, !(attr & EP_NO_SLEEP))) == 0) -+ goto failed; -+ } -+ -+ switch (alloc->Type) -+ { -+ case EP_ALLOC_TYPE_PRIVATE_SDRAM: -+ rail = alloc->Data.Private.Rail; -+ -+ if ((pool->Buffer.Sdram = rail->Operations.SdramAlloc (rail, base, size)) == 0) -+ goto failed; -+ -+ ep_perrail_sdram_map (rail, base, pool->Buffer.Sdram, size, perm, attr); -+ -+ pool->Handle.nmh_nmd.nmd_addr = base; -+ pool->Handle.nmh_nmd.nmd_len = size; -+ break; -+ -+ case EP_ALLOC_TYPE_PRIVATE_MAIN: -+ KMEM_GETPAGES(pool->Buffer.Ptr, unsigned long, btop (size), !(attr & EP_NO_SLEEP)); -+ if (pool->Buffer.Ptr == 0) -+ goto failed; -+ -+ ep_perrail_kaddr_map (alloc->Data.Private.Rail, base, pool->Buffer.Ptr, size, perm, attr); -+ -+ pool->Handle.nmh_nmd.nmd_addr = base; -+ pool->Handle.nmh_nmd.nmd_len = size; -+ break; -+ -+ case EP_ALLOC_TYPE_SHARED_MAIN: -+ KMEM_GETPAGES(pool->Buffer.Ptr, unsigned long, btop (size), !(attr & EP_NO_SLEEP)); -+ if (pool->Buffer.Ptr == 0) -+ goto failed; -+ -+ list_for_each (el, &alloc->Data.Shared.Rails) { -+ EP_RAIL *rail = list_entry (el, EP_RAIL_ENTRY, Link)->Rail; -+ -+ ep_perrail_kaddr_map (rail, base, pool->Buffer.Ptr, size, perm, attr); -+ -+ railmask |= (1 << rail->Number); -+ } -+ pool->Handle.nmh_nmd.nmd_addr = base; -+ pool->Handle.nmh_nmd.nmd_len = size; -+ pool->Handle.nmh_nmd.nmd_attr = EP_NMD_ATTR (alloc->Data.Shared.System->Position.pos_nodeid, railmask); -+ -+ ep_nmh_insert (&alloc->Data.Shared.System->MappingTable, &pool->Handle); -+ break; -+ -+ default: -+ goto failed; -+ } -+ -+ return (pool); -+ -+ failed: -+ if (addr == 0 && base) -+ ep_rmfree (alloc->ResourceMap, size, base); -+ -+ for (i = LN2_MIN_SIZE; i <= LN2_MAX_SIZE; i ++) -+ if (pool->Bitmaps[i - LN2_MIN_SIZE] != NULL) -+ KMEM_FREE (pool->Bitmaps[i - LN2_MIN_SIZE], BT_BITOUL(1 << (LN2_MAX_SIZE - i)) * sizeof (bitmap_t)); -+ -+ KMEM_FREE (pool, sizeof (EP_POOL)); -+ return (NULL); -+} -+ -+static void -+FreePool (EP_ALLOC *alloc, EP_POOL *pool) -+{ -+ struct list_head *el; -+ int i; -+ -+ switch (alloc->Type) -+ { -+ case EP_ALLOC_TYPE_PRIVATE_SDRAM: -+ ep_perrail_unmap (alloc->Data.Private.Rail, pool->Handle.nmh_nmd.nmd_addr, pool->Handle.nmh_nmd.nmd_len); -+ -+ alloc->Data.Private.Rail->Operations.SdramFree (alloc->Data.Private.Rail, pool->Buffer.Sdram, pool->Handle.nmh_nmd.nmd_len); -+ break; -+ -+ case EP_ALLOC_TYPE_PRIVATE_MAIN: -+ ep_perrail_unmap (alloc->Data.Private.Rail, pool->Handle.nmh_nmd.nmd_addr, pool->Handle.nmh_nmd.nmd_len); -+ -+ KMEM_FREEPAGES (pool->Buffer.Ptr, btop (pool->Handle.nmh_nmd.nmd_len)); -+ break; -+ -+ case EP_ALLOC_TYPE_SHARED_MAIN: -+ ep_nmh_remove (&alloc->Data.Shared.System->MappingTable, &pool->Handle); -+ -+ list_for_each (el, &alloc->Data.Shared.Rails) { -+ EP_RAIL *rail = list_entry (el, EP_RAIL_ENTRY, Link)->Rail; -+ -+ ep_perrail_unmap (rail, pool->Handle.nmh_nmd.nmd_addr, pool->Handle.nmh_nmd.nmd_len); -+ } -+ -+ KMEM_FREEPAGES (pool->Buffer.Ptr, btop (pool->Handle.nmh_nmd.nmd_len)); -+ break; -+ } -+ -+ if (pool->Bitmaps[0]) -+ { -+ ep_rmfree (alloc->ResourceMap, pool->Handle.nmh_nmd.nmd_len, pool->Handle.nmh_nmd.nmd_addr); -+ -+ for (i = LN2_MIN_SIZE; i <= LN2_MAX_SIZE; i ++) -+ KMEM_FREE (pool->Bitmaps[i - LN2_MIN_SIZE], BT_BITOUL(1 << (LN2_MAX_SIZE - i)) * sizeof (bitmap_t)); -+ } -+ -+ KMEM_FREE (pool, sizeof (EP_POOL)); -+} -+ -+static int -+AddRail (EP_ALLOC *alloc, EP_RAIL *rail) -+{ -+ struct list_head *el; -+ EP_RAIL_ENTRY *l; -+ unsigned long flags; -+ int i; -+ -+ ASSERT (alloc->Type == EP_ALLOC_TYPE_SHARED_MAIN); -+ -+ KMEM_ZALLOC (l, EP_RAIL_ENTRY *, sizeof (EP_RAIL_ENTRY), 1); -+ -+ if (l == NULL) -+ return (ENOMEM); -+ -+ l->Rail = rail; -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ for (i = 0; i < NHASH; i++) -+ { -+ list_for_each (el, &alloc->HashBase[i]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, HashBase); -+ -+ ep_perrail_kaddr_map (rail, pool->Handle.nmh_nmd.nmd_addr, pool->Buffer.Ptr, -+ pool->Handle.nmh_nmd.nmd_len, EP_PERM_WRITE, EP_NO_SLEEP); -+ -+ pool->Handle.nmh_nmd.nmd_attr |= EP_NMD_ATTR (0, 1 << rail->Number); -+ } -+ } -+ -+ list_add (&l->Link, &alloc->Data.Shared.Rails); -+ -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+ return (0); -+} -+ -+static void -+RemoveRail (EP_ALLOC *alloc, EP_RAIL *rail) -+{ -+ struct list_head *el; -+ unsigned long flags; -+ int i; -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ for (i = 0; i < NHASH; i++) -+ { -+ list_for_each (el, &alloc->HashBase[i]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, HashBase); -+ -+ ep_perrail_unmap (rail, pool->Handle.nmh_nmd.nmd_addr, pool->Handle.nmh_nmd.nmd_len); -+ -+ pool->Handle.nmh_nmd.nmd_attr &= ~EP_NMD_ATTR (0, 1 << rail->Number); -+ } -+ } -+ -+ list_for_each (el, &alloc->Data.Shared.Rails) { -+ EP_RAIL_ENTRY *tmp = list_entry (el, EP_RAIL_ENTRY, Link); -+ if (tmp->Rail == rail) -+ { -+ list_del (el); -+ KMEM_FREE(tmp, sizeof (EP_RAIL_ENTRY)); -+ break; -+ } -+ } -+ -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+} -+ -+static EP_POOL * -+AllocateBlock (EP_ALLOC *alloc, unsigned size, EP_ATTRIBUTE attr, int *offset) -+{ -+ int block, j, k; -+ unsigned long flags; -+ EP_POOL *pool; -+ -+ -+ if (size > MAX_SIZE) -+ { -+ if ((attr & EP_NO_ALLOC) || (pool = AllocatePool (alloc, 0, size, alloc->Perm, attr)) == NULL) -+ return (NULL); -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ HashInPool (alloc, pool); -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+ -+ *offset = 0; -+ -+ return pool; -+ } -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ -+ /* Round up size to next power of 2 */ -+ for (k = LN2_MIN_SIZE; (1 << k) < size; k++) -+ ; -+ -+ /* k now has ln2 of the size to allocate. */ -+ /* find the free list with the smallest block we can use*/ -+ for (j = k; j <= LN2_MAX_SIZE && list_empty (&alloc->Freelists[j - LN2_MIN_SIZE]); j++) -+ ; -+ -+ /* j has ln2 of the smallest size block we can use */ -+ if (j < LN2_MAX_SIZE) -+ { -+ int nbits = 1 << (LN2_MAX_SIZE-j); -+ -+ pool = list_entry (alloc->Freelists[j - LN2_MIN_SIZE].next, EP_POOL, Link[j - LN2_MIN_SIZE]); -+ block = (bt_lowbit (pool->Bitmaps[j - LN2_MIN_SIZE], nbits) << j); -+ -+ BT_CLEAR (pool->Bitmaps[j - LN2_MIN_SIZE], block >> j); -+ -+ if (bt_lowbit (pool->Bitmaps[j - LN2_MIN_SIZE], nbits) == -1) -+ list_del (&pool->Link[j - LN2_MIN_SIZE]); -+ } -+ else -+ { -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+ -+ if ((attr & EP_NO_ALLOC) || (pool = AllocatePool (alloc, 0, MAX_SIZE, alloc->Perm, attr)) == NULL) -+ return (NULL); -+ -+ block = 0; -+ j = LN2_MAX_SIZE; -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ -+ HashInPool (alloc, pool); -+ } -+ -+ /* Split it until the buddies are the correct size, putting one -+ * buddy back on the free list and continuing to split the other */ -+ while (--j >= k) -+ { -+ list_add (&pool->Link[j - LN2_MIN_SIZE], &alloc->Freelists[j - LN2_MIN_SIZE]); -+ -+ BT_SET (pool->Bitmaps[j - LN2_MIN_SIZE], block >> j); -+ -+ block += (1 << j); -+ } -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+ -+ *offset = block; -+ -+ return (pool); -+} -+ -+static void -+FreeBlock (EP_ALLOC *alloc, EP_ADDR addr, unsigned size) -+{ -+ EP_POOL *pool; -+ int k, block = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ /* Round up size to next power of 2 */ -+ for (k = LN2_MIN_SIZE; (1 << k) < size; k++) -+ ; -+ -+ /* Find the pool containing this block */ -+ pool = LookupPool (alloc, addr); -+ -+ /* It must exist */ -+ ASSERT (pool != NULL); -+ -+ /* If we're freeing a subset of it, then update the bitmaps */ -+ if (size <= MAX_SIZE) -+ { -+ ASSERT (BT_TEST (pool->Bitmaps[k - LN2_MIN_SIZE], (addr - pool->Handle.nmh_nmd.nmd_addr) >> k) == 0); -+ -+ block = addr - pool->Handle.nmh_nmd.nmd_addr; -+ -+ while (k < LN2_MAX_SIZE && BT_TEST (pool->Bitmaps[k - LN2_MIN_SIZE], (block >> k) ^ 1)) -+ { -+ BT_CLEAR (pool->Bitmaps[k - LN2_MIN_SIZE], (block >> k) ^ 1); -+ -+ if (bt_lowbit (pool->Bitmaps[k - LN2_MIN_SIZE], (1 << (LN2_MAX_SIZE - k))) == -1) -+ list_del (&pool->Link[k - LN2_MIN_SIZE]); -+ -+ k++; -+ } -+ } -+ -+ if (k >= LN2_MAX_SIZE) -+ { -+ HashOutPool (alloc, pool); -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+ -+ FreePool (alloc, pool); -+ } -+ else -+ { -+ if (bt_lowbit (pool->Bitmaps[k - LN2_MIN_SIZE], (1 << (LN2_MAX_SIZE - k))) == -1) -+ list_add (&pool->Link[k - LN2_MIN_SIZE], &alloc->Freelists[k - LN2_MIN_SIZE]); -+ -+ BT_SET (pool->Bitmaps[k - LN2_MIN_SIZE], block >> k); -+ -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+ } -+} -+ -+static void -+InitialiseAllocator (EP_ALLOC *alloc, EP_ALLOC_TYPE type, unsigned int perm, EP_RMAP *rmap) -+{ -+ int i; -+ -+ spin_lock_init (&alloc->Lock); -+ -+ alloc->Type = type; -+ alloc->ResourceMap = rmap; -+ alloc->Perm = perm; -+ -+ for (i = 0; i < NHASH; i++) -+ { -+ (&alloc->HashBase[i])->next = &alloc->HashBase[i]; -+ -+ INIT_LIST_HEAD (&alloc->HashBase[i]); -+ INIT_LIST_HEAD (&alloc->HashTop[i]); -+ } -+ -+ for (i = 0; i < NUM_FREELISTS; i++) -+ INIT_LIST_HEAD (&alloc->Freelists[i]); -+} -+ -+static void -+DestroyAllocator (EP_ALLOC *alloc) -+{ -+ struct list_head *el, *next; -+ int i; -+ -+ for (i = 0; i < NHASH; i++) -+ { -+ list_for_each_safe (el, next, &alloc->HashBase[i]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, HashBase); -+ -+ printk ("!!DestroyAllocator: pool=%p type=%d addr=%x len=%x\n", pool, alloc->Type, -+ pool->Handle.nmh_nmd.nmd_addr, pool->Handle.nmh_nmd.nmd_len); -+ -+ list_del (&pool->HashBase); -+ list_del (&pool->HashTop); -+ -+ // XXXX: FreePool (alloc, pool); -+ } -+ } -+ -+ spin_lock_destroy (&alloc->Lock); -+} -+ -+void -+ep_display_alloc (EP_ALLOC *alloc) -+{ -+ struct list_head *el; -+ int i; -+ int npools = 0; -+ int nbytes = 0; -+ int nfree = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&alloc->Lock, flags); -+ -+ ep_debugf (DBG_DEBUG, "Kernel comms memory allocator %p type %d\n", alloc, alloc->Type); -+ for (i = 0; i < NHASH; i++) -+ { -+ list_for_each (el, &alloc->HashBase[i]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, HashBase); -+ -+ ep_debugf (DBG_DEBUG, " POOL %4x: %p -> %x.%x\n", i, pool, pool->Handle.nmh_nmd.nmd_addr, -+ pool->Handle.nmh_nmd.nmd_addr + pool->Handle.nmh_nmd.nmd_len); -+ -+ npools++; -+ nbytes += pool->Handle.nmh_nmd.nmd_len; -+ } -+ } -+ -+ for (i = LN2_MIN_SIZE; i <= LN2_MAX_SIZE; i++) -+ { -+ int n = 0; -+ -+ list_for_each (el, &alloc->Freelists[i - LN2_MIN_SIZE]) { -+ EP_POOL *pool = list_entry (el, EP_POOL, Link[i - LN2_MIN_SIZE]); -+ int nbits = bt_nbits (pool->Bitmaps[i - LN2_MIN_SIZE], 1 << (LN2_MAX_SIZE - i)); -+ -+ n += nbits; -+ nfree += (nbits << i); -+ } -+ -+ if (n != 0) -+ ep_debugf (DBG_DEBUG, " SIZE %5d : num %d\n", (1 << i), n); -+ } -+ ep_debugf (DBG_DEBUG, "%d pools with %d bytes and %d bytes free\n", npools, nbytes, nfree); -+ -+ spin_unlock_irqrestore (&alloc->Lock, flags); -+} -+ -+/* per-rail allocators */ -+void -+ep_alloc_init (EP_RAIL *rail) -+{ -+ EP_RMAP *rmap = ep_rmallocmap (EP_PRIVATE_RMAP_SIZE, "PrivateMap", 1); -+ -+ ep_rmfree (rmap, EP_PRIVATE_TOP-EP_PRIVATE_BASE, EP_PRIVATE_BASE); -+ -+ InitialiseAllocator (&rail->ElanAllocator, EP_ALLOC_TYPE_PRIVATE_SDRAM, EP_PERM_ALL, rmap); -+ InitialiseAllocator (&rail->MainAllocator, EP_ALLOC_TYPE_PRIVATE_MAIN, EP_PERM_WRITE, rmap); -+ -+ rail->ElanAllocator.Data.Private.Rail = rail; -+ rail->MainAllocator.Data.Private.Rail = rail; -+} -+ -+void -+ep_alloc_fini (EP_RAIL *rail) -+{ -+ EP_RMAP *rmap = rail->ElanAllocator.ResourceMap; -+ -+ DestroyAllocator (&rail->ElanAllocator); -+ DestroyAllocator (&rail->MainAllocator); -+ -+ ep_rmfreemap (rmap); -+} -+ -+sdramaddr_t -+ep_alloc_memory_elan (EP_RAIL *rail, EP_ADDR addr, unsigned size, unsigned int perm, EP_ATTRIBUTE attr) -+{ -+ EP_POOL *pool = AllocatePool (&rail->ElanAllocator, addr, size, perm, attr); -+ unsigned long flags; -+ -+ if (pool == NULL) -+ return (0); -+ -+ spin_lock_irqsave (&rail->ElanAllocator.Lock, flags); -+ HashInPool (&rail->ElanAllocator, pool); -+ spin_unlock_irqrestore (&rail->ElanAllocator.Lock, flags); -+ -+ return (pool->Buffer.Sdram); -+} -+ -+void -+ep_free_memory_elan (EP_RAIL *rail, EP_ADDR addr) -+{ -+ EP_POOL *pool; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->ElanAllocator.Lock, flags); -+ pool = LookupPool (&rail->ElanAllocator, addr); -+ -+ HashOutPool (&rail->ElanAllocator, pool); -+ spin_unlock_irqrestore (&rail->ElanAllocator.Lock, flags); -+ -+ FreePool (&rail->ElanAllocator, pool); -+} -+ -+sdramaddr_t -+ep_alloc_elan (EP_RAIL *rail, unsigned size, EP_ATTRIBUTE attr, EP_ADDR *addrp) -+{ -+ int offset; -+ EP_POOL *pool; -+ -+ if ((pool = AllocateBlock (&rail->ElanAllocator, size, attr, &offset)) == NULL) -+ return (0); -+ -+ *addrp = pool->Handle.nmh_nmd.nmd_addr + offset; -+ -+ return (pool->Buffer.Sdram + offset); -+} -+ -+void -+ep_free_elan (EP_RAIL *rail, EP_ADDR addr, unsigned size) -+{ -+ FreeBlock (&rail->ElanAllocator, addr, size); -+} -+ -+void * -+ep_alloc_main (EP_RAIL *rail, unsigned size, EP_ATTRIBUTE attr, EP_ADDR *addrp) -+{ -+ int offset; -+ EP_POOL *pool; -+ -+ if ((pool = AllocateBlock (&rail->MainAllocator, size, attr, &offset)) == NULL) -+ return (NULL); -+ -+ *addrp = pool->Handle.nmh_nmd.nmd_addr + offset; -+ -+ return ((void *) ((unsigned long) pool->Buffer.Ptr + offset)); -+} -+ -+void -+ep_free_main (EP_RAIL *rail, EP_ADDR addr, unsigned size) -+{ -+ FreeBlock (&rail->MainAllocator, addr, size); -+} -+ -+sdramaddr_t -+ep_elan2sdram (EP_RAIL *rail, EP_ADDR addr) -+{ -+ EP_POOL *pool; -+ sdramaddr_t res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->ElanAllocator.Lock, flags); -+ if ((pool = LookupPool (&rail->ElanAllocator, addr)) == NULL) -+ res = 0; -+ else -+ res = pool->Buffer.Sdram + (addr - pool->Handle.nmh_nmd.nmd_addr); -+ spin_unlock_irqrestore (&rail->ElanAllocator.Lock, flags); -+ -+ return (res); -+} -+ -+void * -+ep_elan2main (EP_RAIL *rail, EP_ADDR addr) -+{ -+ EP_POOL *pool; -+ void *res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->MainAllocator.Lock, flags); -+ if ((pool = LookupPool (&rail->MainAllocator, addr)) == NULL) -+ res = NULL; -+ else -+ res = (void *) ((unsigned long) pool->Buffer.Ptr + (addr - pool->Handle.nmh_nmd.nmd_addr)); -+ spin_unlock_irqrestore (&rail->MainAllocator.Lock, flags); -+ -+ return (res); -+} -+ -+/* shared allocators */ -+int -+ep_shared_alloc_add_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ return (AddRail (&sys->Allocator, rail)); -+} -+ -+void -+ep_shared_alloc_remove_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ RemoveRail (&sys->Allocator, rail); -+} -+ -+void -+ep_shared_alloc_init (EP_SYS *sys) -+{ -+ EP_RMAP *rmap = ep_rmallocmap (EP_SHARED_RMAP_SIZE, "shared_alloc_map", 1); -+ -+ ep_rmfree (rmap, EP_SHARED_TOP - EP_SHARED_BASE, EP_SHARED_BASE); -+ -+ InitialiseAllocator (&sys->Allocator, EP_ALLOC_TYPE_SHARED_MAIN, EP_PERM_WRITE, rmap); -+ -+ INIT_LIST_HEAD (&sys->Allocator.Data.Shared.Rails); -+ -+ sys->Allocator.Data.Shared.System = sys; -+} -+ -+void -+ep_shared_alloc_fini (EP_SYS *sys) -+{ -+ EP_RMAP *rmap = sys->Allocator.ResourceMap; -+ -+ DestroyAllocator (&sys->Allocator); -+ -+ ep_rmfreemap (rmap); -+} -+ -+void * -+ep_shared_alloc_main (EP_SYS *sys, unsigned size, EP_ATTRIBUTE attr, EP_NMD *nmd) -+{ -+ int offset; -+ EP_POOL *pool; -+ -+ if ((pool = AllocateBlock (&sys->Allocator, size, attr, &offset)) == NULL) -+ return (NULL); -+ -+ ep_nmd_subset (nmd, &pool->Handle.nmh_nmd, offset, size); -+ -+ return ((void *) ((unsigned long) pool->Buffer.Ptr + offset)); -+} -+ -+void -+ep_shared_free_main (EP_SYS *sys, EP_NMD *nmd) -+{ -+ FreeBlock (&sys->Allocator, nmd->nmd_addr, nmd->nmd_len); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kcomm.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kcomm.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kcomm.c 2005-06-01 23:12:54.664429224 -0400 -@@ -0,0 +1,1448 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kcomm.c,v 1.50.2.9 2004/12/09 10:02:42 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm.c,v $ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "cm.h" -+#include "debug.h" -+ -+int MaxSwitchLevels = 5; /* Max 1024 sized machine */ -+ -+static char *NodeStateNames[EP_NODE_NUM_STATES] = -+{ -+ "Disconnected", -+ "Connecting", -+ "Connnected", -+ "LeavingConnected", -+ "LocalPassivate", -+ "RemotePassivate", -+ "Passivated", -+ "Disconnecting", -+}; -+ -+static void -+ep_xid_cache_fill (EP_SYS *sys, EP_XID_CACHE *cache) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->XidLock, flags); -+ -+ cache->Current = sys->XidNext; -+ cache->Last = cache->Current + EP_XID_CACHE_CHUNKS-1; -+ -+ sys->XidNext += EP_XID_CACHE_CHUNKS; -+ -+ spin_unlock_irqrestore (&sys->XidLock, flags); -+} -+ -+EP_XID -+ep_xid_cache_alloc (EP_SYS *sys, EP_XID_CACHE *cache) -+{ -+ EP_XID xid; -+ -+ if (cache->Current == cache->Last) -+ ep_xid_cache_fill (sys, cache); -+ -+ xid.Generation = sys->XidGeneration; -+ xid.Handle = cache->Handle; -+ xid.Unique = cache->Current++; -+ -+ return (xid); -+} -+ -+void -+ep_xid_cache_init (EP_SYS *sys, EP_XID_CACHE *cache) -+{ -+ /* Stall manager thread - it doesn't lock the XidCacheList */ -+ ep_kthread_stall (&sys->ManagerThread); -+ -+ cache->Handle = ++sys->XidHandle; -+ -+ list_add_tail (&cache->Link, &sys->XidCacheList); -+ -+ ep_kthread_resume (&sys->ManagerThread); -+} -+ -+void -+ep_xid_cache_destroy (EP_SYS *sys, EP_XID_CACHE *cache) -+{ -+ /* Stall manager thread - it doesn't lock the XidCacheList */ -+ ep_kthread_stall (&sys->ManagerThread); -+ -+ list_del (&cache->Link); -+ -+ ep_kthread_resume (&sys->ManagerThread); -+} -+ -+EP_XID_CACHE * -+ep_xid_cache_find (EP_SYS *sys, EP_XID xid) -+{ -+ struct list_head *el; -+ -+ list_for_each (el, &sys->XidCacheList) { -+ EP_XID_CACHE *cache = list_entry (el, EP_XID_CACHE, Link); -+ -+ if (sys->XidGeneration == xid.Generation && cache->Handle == xid.Handle) -+ return (cache); -+ } -+ -+ return (NULL); -+} -+ -+static int -+MsgBusy (EP_RAIL *rail, EP_OUTPUTQ *outputq, int slotNum) -+{ -+ switch (rail->Operations.OutputQState (rail, outputq, slotNum)) -+ { -+ case EP_OUTPUTQ_BUSY: /* still busy */ -+ return 1; -+ -+ case EP_OUTPUTQ_FAILED: /* NACKed */ -+ { -+#if defined(DEBUG_PRINTF) -+ EP_MANAGER_MSG *msg = rail->Operations.OutputQMsg (rail, outputq, slotNum); -+ -+ EPRINTF4 (DBG_MANAGER, "%s: kcomm msg %d type %d to %d failed\n", rail->Name, slotNum, msg->Hdr.Type, msg->Hdr.DestId); -+#endif -+ break; -+ } -+ -+ case EP_OUTPUTQ_FINISHED: /* anything else is finished */ -+ break; -+ } -+ -+ return 0; -+} -+ -+int -+ep_send_message (EP_RAIL *rail, int nodeId, int type, EP_XID xid, EP_MANAGER_MSG_BODY *body) -+{ -+ EP_SYS *sys = rail->System; -+ EP_NODE *node = &sys->Nodes[nodeId]; -+ int n = EP_MANAGER_OUTPUTQ_SLOTS; -+ int slotNum; -+ int rnum; -+ EP_RAIL *msgRail; -+ EP_MANAGER_MSG *msg; -+ unsigned long flags; -+ -+ ASSERT (! EP_XID_INVALID (xid)); -+ -+ if ((rnum = ep_pickRail (node->ConnectedRails)) >= 0) -+ msgRail = sys->Rails[rnum]; -+ else -+ { -+ if (EP_MANAGER_MSG_TYPE_CONNECTED(type)) -+ { -+ ep_debugf (DBG_MANAGER, "%s: no rails available, trying to send type %d to %d\n", rail->Name, type, nodeId); -+ return -EHOSTDOWN; -+ } -+ -+ ep_debugf (DBG_MANAGER, "%s: no rails connected to %d - using receiving rail\n", rail->Name, nodeId); -+ -+ msgRail = rail; -+ } -+ -+ -+ spin_lock_irqsave (&msgRail->ManagerOutputQLock, flags); -+ -+ slotNum = msgRail->ManagerOutputQNextSlot; -+ -+ while (n-- > 0 && MsgBusy (msgRail, msgRail->ManagerOutputQ, slotNum)) /* search for idle message buffer */ -+ { -+ if (++(msgRail->ManagerOutputQNextSlot) == EP_MANAGER_OUTPUTQ_SLOTS) -+ msgRail->ManagerOutputQNextSlot = 0; -+ -+ slotNum = msgRail->ManagerOutputQNextSlot; -+ } -+ -+ if (n == 0) /* all message buffers busy */ -+ { -+ spin_unlock_irqrestore (&msgRail->ManagerOutputQLock, flags); -+ -+ ep_debugf (DBG_MANAGER, "%s: all message buffers busy: trying to send type %d to %d\n", msgRail->Name, type, nodeId); -+ return -EBUSY; -+ } -+ -+ msg = msgRail->Operations.OutputQMsg (msgRail, msgRail->ManagerOutputQ, slotNum); -+ -+ EPRINTF7 (DBG_MANAGER, "%s: ep_send_message: type=%d nodeId=%d rail=%d xid=%08x.%08x.%016llx\n", -+ msgRail->Name, type, nodeId, rail->Number, xid.Generation, xid.Handle, (long long) xid.Unique); -+ -+ msg->Hdr.Version = EP_MANAGER_MSG_VERSION; -+ msg->Hdr.Type = type; -+ msg->Hdr.Rail = rail->Number; -+ msg->Hdr.NodeId = msgRail->Position.pos_nodeid; -+ msg->Hdr.DestId = nodeId; -+ msg->Hdr.Xid = xid; -+ msg->Hdr.Checksum = 0; -+ -+ if (body) bcopy (body, &msg->Body, sizeof (EP_MANAGER_MSG_BODY)); -+ -+ msg->Hdr.Checksum = CheckSum ((char *) msg, EP_MANAGER_MSG_SIZE); -+ -+ if (rail->Operations.OutputQSend (msgRail, msgRail->ManagerOutputQ, slotNum, EP_MANAGER_MSG_SIZE, -+ nodeId, EP_SYSTEMQ_MANAGER, EP_MANAGER_OUTPUTQ_RETRIES) < 0) -+ IncrStat (msgRail, SendMessageFailed); -+ -+ if (++(msgRail->ManagerOutputQNextSlot) == EP_MANAGER_OUTPUTQ_SLOTS) /* check this one last next time */ -+ msgRail->ManagerOutputQNextSlot = 0; -+ -+ spin_unlock_irqrestore (&msgRail->ManagerOutputQLock, flags); -+ -+ return 0; -+} -+ -+void -+ep_panic_node (EP_SYS *sys, int nodeId, unsigned char *reason) -+{ -+ EP_NODE *node = &sys->Nodes[nodeId]; -+ EP_MANAGER_MSG_BODY body; -+ EP_XID xid; -+ kcondvar_t sleep; -+ int rnum; -+ unsigned long flags; -+ -+ if (nodeId > sys->Position.pos_nodes) -+ return; -+ -+ strncpy (body.PanicReason, reason, sizeof (body.PanicReason)); -+ -+ kcondvar_init (&sleep); -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ for (;;) -+ { -+ if (node->ConnectedRails == 0) -+ break; -+ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ if (node->ConnectedRails & (1 << rnum)) -+ break; -+ -+ xid = ep_xid_cache_alloc(sys, &sys->Rails[rnum]->XidCache); -+ -+ if (ep_send_message (sys->Rails[rnum], nodeId, EP_MANAGER_MSG_TYPE_REMOTE_PANIC, xid, &body) == 0) -+ break; -+ -+ if (kcondvar_timedwaitsig (&sleep, &sys->NodeLock, &flags, lbolt + hz) == CV_RET_SIGPENDING) -+ break; -+ } -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ kcondvar_destroy (&sleep); -+} -+ -+static void -+ProcessNeterrRequest (EP_RAIL *msgRail, EP_RAIL *rail, EP_MANAGER_MSG *msg) -+{ -+ EPRINTF4 (DBG_NETWORK_ERROR, "%s: process neterr request - node %d cookies %llx %llx\n", rail->Name, msg->Hdr.NodeId, msg->Body.Cookies[0], msg->Body.Cookies[1]); -+ -+ rail->Operations.NeterrFixup (rail, msg->Hdr.NodeId, msg->Body.Cookies); -+ -+ ep_send_message (rail, msg->Hdr.NodeId, EP_MANAGER_MSG_TYPE_NETERR_RESPONSE, msg->Hdr.Xid, &msg->Body); -+} -+ -+ -+static void -+ProcessNeterrResponse (EP_RAIL *msgRail, EP_RAIL *rail, EP_MANAGER_MSG *msg) -+{ -+ EP_SYS *sys = rail->System; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[msg->Hdr.NodeId]; -+ unsigned long flags; -+ -+ EPRINTF4 (DBG_NETWORK_ERROR, "%s: process neterr response - node %d cookies %llx %llx\n", rail->Name, msg->Hdr.NodeId, msg->Body.Cookies[0], msg->Body.Cookies[1]); -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ if (EP_XIDS_MATCH (nodeRail->MsgXid, msg->Hdr.Xid)) -+ { -+ EP_INVALIDATE_XID (nodeRail->MsgXid); -+ -+ if (nodeRail->NetworkErrorCookies[0] != 0 && nodeRail->NetworkErrorCookies[0] == msg->Body.Cookies[0]) -+ nodeRail->NetworkErrorCookies[0] = 0; -+ -+ if (nodeRail->NetworkErrorCookies[1] != 0 && nodeRail->NetworkErrorCookies[1] == msg->Body.Cookies[1]) -+ nodeRail->NetworkErrorCookies[1] = 0; -+ -+ if (nodeRail->NetworkErrorCookies[0] == 0 && nodeRail->NetworkErrorCookies[1] == 0) -+ nodeRail->NetworkErrorState &= ~EP_NODE_NETERR_ATOMIC_PACKET; -+ } -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+} -+ -+ -+static void -+ProcessGetNodeState (EP_RAIL *msgRail, EP_RAIL *rail, EP_MANAGER_MSG *msg) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[msg->Hdr.NodeId]; -+ unsigned int service = msg->Body.Service; -+ -+ EPRINTF5 (DBG_MANAGER, "%s: ProcessGetNodeState: %s - %d %s%s\n", msgRail->Name, rail->Name, msg->Hdr.NodeId, -+ NodeStateNames[nodeRail->State], nodeRail->NetworkErrorState ? " (NetworkError)" : ""); -+ -+ msg->Body.NodeState.State = nodeRail->State; -+ msg->Body.NodeState.NetworkErrorState = nodeRail->NetworkErrorState; -+ msg->Body.NodeState.Railmask = ep_rcvr_railmask (rail->System, service); -+ -+ if (ep_send_message (rail, msg->Hdr.NodeId, EP_MANAGER_MSG_TYPE_GET_NODE_STATE_RESPONSE, msg->Hdr.Xid, &msg->Body) < 0) -+ printk ("%s: get node state for %s[%d] - failed to send response\n", msgRail->Name, rail->Name, msg->Hdr.NodeId); -+} -+ -+static void -+ProcessFlushRequest (EP_RAIL *msgRail, EP_RAIL *rail, EP_MANAGER_MSG *msg) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[msg->Hdr.NodeId]; -+ -+ EPRINTF5 (DBG_MANAGER, "%s: ProcessFlushRequest: %s - %d %s%s\n", msgRail->Name, rail->Name, msg->Hdr.NodeId, -+ NodeStateNames[nodeRail->State], nodeRail->NetworkErrorState ? " (NetworkError)" : ""); -+ -+ switch (nodeRail->State) -+ { -+ case EP_NODE_REMOTE_PASSIVATE: -+ nodeRail->NextRunTime = lbolt + MSGBUSY_RETRY_TIME; /* retransmit our flush request quickly */ -+ EPRINTF3 (DBG_MANAGER, "%s: ProcessFlushRequest: NextRunTime -> %lx (%lx)\n", rail->Name, nodeRail->NextRunTime, lbolt); -+ /* DROPTHROUGH */ -+ -+ case EP_NODE_PASSIVATED: -+ case EP_NODE_DISCONNECTED: -+ if (nodeRail->NetworkErrorState != 0) -+ break; -+ -+ if (ep_send_message (rail, msg->Hdr.NodeId, EP_MANAGER_MSG_TYPE_FLUSH_RESPONSE, msg->Hdr.Xid, NULL) < 0) -+ printk ("%s: flush request for %s[%d] - failed to send response\n", msgRail->Name, rail->Name, msg->Hdr.NodeId); -+ break; -+ -+ default: -+ EPRINTF4 (DBG_MANAGER, "%s: flush request for %s[%d] - node not in approriate state - %s\n", msgRail->Name, rail->Name, msg->Hdr.NodeId, NodeStateNames[nodeRail->State]); -+ break; -+ } -+} -+ -+static void -+ProcessFlushResponse (EP_RAIL *msgRail, EP_RAIL *rail, EP_MANAGER_MSG *msg) -+{ -+ EP_NODE_RAIL *nodeRail= &rail->Nodes[msg->Hdr.NodeId]; -+ -+ EPRINTF5 (DBG_MANAGER, "%s: ProcessFlushResponse: %s - %d %s%s\n", msgRail->Name, rail->Name, msg->Hdr.NodeId, -+ NodeStateNames[nodeRail->State], EP_XIDS_MATCH (nodeRail->MsgXid, msg->Hdr.Xid) ? " (XIDS match)" : ""); -+ -+ if (nodeRail->State == EP_NODE_REMOTE_PASSIVATE && EP_XIDS_MATCH(nodeRail->MsgXid, msg->Hdr.Xid)) -+ { -+ EP_INVALIDATE_XID (nodeRail->MsgXid); -+ -+ printk ("%s: flush response from %d - move to passivated list\n", rail->Name, msg->Hdr.NodeId); -+ list_del (&nodeRail->Link); -+ -+ /* Node is now passivated - attempt to failover messages */ -+ list_add_tail (&nodeRail->Link, &rail->PassivatedList); -+ nodeRail->State = EP_NODE_PASSIVATED; -+ } -+ else -+ { -+ printk ("%s: flush response from %d - not passivating (%s) or XIDs mismatch (%llx %llx)\n", rail->Name, -+ msg->Hdr.NodeId, NodeStateNames[nodeRail->State], (long long) nodeRail->MsgXid.Unique, (long long) msg->Hdr.Xid.Unique); -+ } -+} -+ -+static void -+ProcessMapNmdRequest (EP_RAIL *msgRail, EP_RAIL *rail, EP_MANAGER_MSG *msg) -+{ -+ EP_SYS *sys = rail->System; -+ EP_MAP_NMD_BODY *msgBody = &msg->Body.MapNmd; -+ int i; -+ -+ EPRINTF4 (DBG_MANAGER, "%s: Map NMD request from %d for %d NMDs to railmask %x\n", rail->Name, msg->Hdr.NodeId, msgBody->nFrags, msgBody->Railmask); -+ -+ for (i = 0; i < msgBody->nFrags; i++) -+ ep_nmd_map_rails (sys, &msgBody->Nmd[i], msgBody->Railmask); -+ -+ /* Must flush TLBs before responding */ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (sys->Rails[i] && sys->Rails[i]->TlbFlushRequired) -+ ep_perrail_dvma_sync (sys->Rails[i]); -+ -+ if (ep_send_message (rail, msg->Hdr.NodeId, EP_MANAGER_MSG_TYPE_MAP_NMD_RESPONSE, msg->Hdr.Xid, &msg->Body) < 0) -+ printk ("%s: map nmd request for %s[%d] - failed to send response\n", msgRail->Name, rail->Name, msg->Hdr.NodeId); -+} -+ -+static void -+ProcessXidMessage (EP_RAIL *msgRail, EP_MANAGER_MSG *msg, EP_XID xid) -+{ -+ EP_XID_CACHE *xidCache = ep_xid_cache_find (msgRail->System, xid); -+ -+ EPRINTF6 (DBG_MANAGER, "%s: ProcessXidMessage: XID=%08x.%0x8.%016llx -> %p(%p)\n", -+ msgRail->Name, xid.Generation, xid.Handle, (long long) xid.Unique, -+ xidCache ? xidCache->MessageHandler : 0, xidCache ? xidCache->Arg : 0); -+ -+ if (xidCache != NULL) -+ xidCache->MessageHandler (xidCache->Arg, msg); -+} -+ -+static void -+ProcessMessage (EP_RAIL *msgRail, void *arg, void *msgbuf) -+{ -+ EP_SYS *sys = msgRail->System; -+ EP_MANAGER_MSG *msg = (EP_MANAGER_MSG *) msgbuf; -+ uint16_t csum = msg->Hdr.Checksum; -+ EP_RAIL *rail; -+ -+ if (msg->Hdr.Version != EP_MANAGER_MSG_VERSION) -+ return; -+ -+ msg->Hdr.Checksum= 0; -+ if (CheckSum ((char *) msg, EP_MANAGER_MSG_SIZE) != csum) -+ { -+ printk ("%s: checksum failed on msg from %d (%d) (%x != %x) ?\n", msgRail->Name, msg->Hdr.NodeId, msg->Hdr.Type, csum, CheckSum ((char *) msg, EP_MANAGER_MSG_SIZE)); -+ return; -+ } -+ -+ if ((rail = sys->Rails[msg->Hdr.Rail]) == NULL) -+ { -+ printk ("%s: rail no longer exists for msg from %d?\n", msgRail->Name, msg->Hdr.NodeId); -+ return; -+ } -+ -+ EPRINTF7 (DBG_MANAGER, "%s: ProcessMessage (%s) type=%d node=%d XID=%08x.%0x8.%016llx\n", -+ msgRail->Name, rail->Name, msg->Hdr.Type, msg->Hdr.NodeId, -+ msg->Hdr.Xid.Generation, msg->Hdr.Xid.Handle, msg->Hdr.Xid.Unique); -+ -+ switch (msg->Hdr.Type) -+ { -+ case EP_MANAGER_MSG_TYPE_REMOTE_PANIC: -+ msg->Body.PanicReason[EP_PANIC_STRLEN] = '\0'; /* ensure string terminated */ -+ -+ printk ("%s: remote panic call from elan node %d - %s\n", msgRail->Name, msg->Hdr.NodeId, msg->Body.PanicReason); -+ panic ("ep: remote panic request\n"); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_NETERR_REQUEST: -+ ProcessNeterrRequest (msgRail, rail, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_NETERR_RESPONSE: -+ ProcessNeterrResponse (msgRail, rail, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_FLUSH_REQUEST: -+ ProcessFlushRequest (msgRail, rail, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_FLUSH_RESPONSE: -+ ProcessFlushResponse (msgRail, rail, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_MAP_NMD_REQUEST: -+ ProcessMapNmdRequest (msgRail, rail, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_MAP_NMD_RESPONSE: -+ ProcessXidMessage (msgRail, msg, msg->Hdr.Xid); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_FAILOVER_REQUEST: -+ ProcessXidMessage (msgRail, msg, msg->Body.Failover.Xid); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_FAILOVER_RESPONSE: -+ ProcessXidMessage (msgRail, msg, msg->Hdr.Xid); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_GET_NODE_STATE: -+ ProcessGetNodeState (msgRail, rail, msg); -+ break; -+ -+ case EP_MANAGER_MSG_TYPE_GET_NODE_STATE_RESPONSE: -+ ProcessXidMessage (msgRail, msg, msg->Hdr.Xid); -+ break; -+ -+ default: -+ printk ("%s: Unknown message type %d from %d\n", msgRail->Name, msg->Hdr.Type, msg->Hdr.NodeId); -+ break; -+ } -+} -+ -+ -+static void -+ManagerQueueEvent (EP_RAIL *rail, void *arg) -+{ -+ ep_kthread_schedule ((EP_KTHREAD *) arg, lbolt); -+} -+ -+void -+UpdateConnectionState (EP_RAIL *rail, statemap_t *map) -+{ -+ EP_SYS *sys = rail->System; -+ bitmap_t seg; -+ int offset, nodeId; -+ unsigned long flags; -+ -+ while ((offset = statemap_findchange (map, &seg, 1)) >= 0) -+ { -+ for (nodeId = offset; nodeId < (offset + BT_NBIPUL) && nodeId < rail->Position.pos_nodes; nodeId++) -+ { -+ EP_NODE *node = &sys->Nodes[nodeId]; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[nodeId]; -+ -+ if (statemap_getbits (map, nodeId, 1)) -+ { -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ -+ switch (nodeRail->State) -+ { -+ case EP_NODE_DISCONNECTED: -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d -> Disconnected \n", rail->Name, nodeId); -+ break; -+ -+ case EP_NODE_CONNECTING: -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d -> Connect\n", rail->Name, nodeId); -+ -+ /* load the route table entry *before* setting the state -+ * to connected, since DMA's can be initiated as soon as -+ * the node is marked as connected */ -+ rail->Operations.LoadNodeRoute (rail, nodeId); -+ -+ nodeRail->State = EP_NODE_CONNECTED; -+ -+ statemap_setbits (rail->NodeSet, nodeId, 1, 1); -+ if (statemap_getbits (sys->NodeSet, nodeId, 1) == 0) -+ statemap_setbits (sys->NodeSet, nodeId, 1, 1); -+ -+ /* Add to rails connected to this node */ -+ node->ConnectedRails |= (1 << rail->Number); -+ -+ /* Finally lower the per-node context filter */ -+ rail->Operations.LowerFilter (rail, nodeId); -+ break; -+ -+ case EP_NODE_LEAVING_CONNECTED: -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d -> Local Passivate\n", rail->Name, nodeId); -+ -+ /* Raise the per-node context filter */ -+ rail->Operations.RaiseFilter (rail, nodeId); -+ -+ /* If it's resolving network errors it will be on the NodeNeterrList, -+ * remove if from this list before placing it on the LocalPassivateList -+ * as we'll resolve the network error later in RemotePassivate */ -+ if (nodeRail->NetworkErrorState) -+ list_del (&nodeRail->Link); -+ -+ list_add_tail (&nodeRail->Link, &rail->LocalPassivateList); -+ nodeRail->State = EP_NODE_LOCAL_PASSIVATE; -+ -+ /* Remove from rails connected to this node */ -+ node->ConnectedRails &= ~(1 << rail->Number); -+ break; -+ -+ default: -+ printk ("%s: Node %d - in NodeChangeMap with state %d\n", rail->Name, nodeId, nodeRail->State); -+ panic ("Node in NodeChangeMap with invalid state\n"); -+ break; -+ } -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ } -+ } -+ } -+} -+ -+void -+ProgressNetworkError (EP_RAIL *rail, EP_NODE_RAIL *nodeRail) -+{ -+ EP_SYS *sys = rail->System; -+ int nodeId = nodeRail - rail->Nodes; -+ EP_MANAGER_MSG_BODY msg; -+ -+ ASSERT (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_REMOTE_PASSIVATE); -+ -+ if (BEFORE (lbolt, nodeRail->NextRunTime)) -+ return; -+ -+ if (nodeRail->NetworkErrorState & EP_NODE_NETERR_DMA_PACKET) -+ nodeRail->NetworkErrorState &= ~EP_NODE_NETERR_DMA_PACKET; -+ -+ if (nodeRail->NetworkErrorState & EP_NODE_NETERR_ATOMIC_PACKET) -+ { -+ if (EP_XID_INVALID (nodeRail->MsgXid)) -+ nodeRail->MsgXid = ep_xid_cache_alloc (sys, &rail->XidCache); -+ -+ msg.Cookies[0] = nodeRail->NetworkErrorCookies[0]; -+ msg.Cookies[1] = nodeRail->NetworkErrorCookies[1]; -+ -+ EPRINTF4 (DBG_NETWORK_ERROR, "%s: progress neterr - node %d cookies %llx %llx\n", rail->Name, nodeId, msg.Cookies[0], msg.Cookies[1]); -+ -+ if (ep_send_message (rail, nodeId, EP_MANAGER_MSG_TYPE_NETERR_REQUEST, nodeRail->MsgXid, &msg) == 0) -+ nodeRail->NextRunTime = lbolt + MESSAGE_RETRY_TIME; -+ else -+ nodeRail->NextRunTime = lbolt + MSGBUSY_RETRY_TIME; -+ } -+} -+ -+long -+ProgressNodeLists (EP_RAIL *rail, long nextRunTime) -+{ -+ EP_SYS *sys = rail->System; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ list_for_each_safe (el, nel, &rail->NetworkErrorList) { -+ EP_NODE_RAIL *nodeRail = list_entry (el, EP_NODE_RAIL, Link); -+ int nodeId = nodeRail - rail->Nodes; -+ -+ ProgressNetworkError (rail, nodeRail); -+ -+ if (nodeRail->NetworkErrorState == 0) -+ { -+ EPRINTF2 (DBG_NETWORK_ERROR, "%s: lower context filter for node %d due to network error\n", rail->Name, nodeId); -+ printk ("%s: lower context filter for node %d due to network error\n", rail->Name, nodeId); -+ -+ rail->Operations.LowerFilter (rail, nodeId); -+ -+ list_del (&nodeRail->Link); -+ continue; -+ } -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, nodeRail->NextRunTime)) -+ nextRunTime = nodeRail->NextRunTime; -+ } -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ if (! list_empty (&rail->LocalPassivateList)) -+ { -+ EPRINTF1 (DBG_MANAGER, "%s: Locally Passivating Nodes\n", rail->Name); -+ -+ /* We have disconnected from some nodes or have left ourselves -+ * flush through all communications and determine whether we -+ * need to perform rail failover */ -+ rail->Operations.FlushFilters (rail); -+ -+ ep_call_callbacks (rail, EP_CB_FLUSH_FILTERING, rail->NodeSet); -+ -+ rail->Operations.FlushQueues (rail); -+ -+ ep_call_callbacks (rail, EP_CB_FLUSH_FLUSHING, rail->NodeSet); -+ -+ while (! list_empty (&rail->LocalPassivateList)) -+ { -+ EP_NODE_RAIL *nodeRail = list_entry (rail->LocalPassivateList.next, EP_NODE_RAIL, Link); -+ int nodeId = nodeRail - rail->Nodes; -+ -+ list_del (&nodeRail->Link); -+ -+ rail->Operations.UnloadNodeRoute (rail, nodeId); -+ -+ if (nodeRail->NetworkErrorState == 0 && nodeRail->MessageState == 0) -+ { -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d -> Disconnecting\n", rail->Name, nodeId); -+ -+ list_add_tail (&nodeRail->Link, &rail->DisconnectingList); -+ nodeRail->State = EP_NODE_DISCONNECTING; -+ } -+ else -+ { -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d -> Remote Passivate\n", rail->Name, nodeId); -+ -+ list_add_tail (&nodeRail->Link, &rail->RemotePassivateList); -+ nodeRail->State = EP_NODE_REMOTE_PASSIVATE; -+ -+ if (nodeRail->NetworkErrorState == 0) -+ nodeRail->NextRunTime = lbolt; -+ } -+ } -+ -+ ep_call_callbacks (rail, EP_CB_PASSIVATED, rail->NodeSet); -+ } -+ -+ list_for_each_safe (el, nel, &rail->RemotePassivateList) { -+ EP_NODE_RAIL *nodeRail = list_entry (el, EP_NODE_RAIL, Link); -+ int nodeId = nodeRail - rail->Nodes; -+ EP_NODE *node = &sys->Nodes[nodeId]; -+ -+ if (node->ConnectedRails == 0) /* no rails connected to this node (anymore) */ -+ { -+ /* Remove from this list */ -+ list_del (&nodeRail->Link); -+ -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d, no rails, Remote Passivate -> Disconnecting\n", rail->Name, nodeId); -+ -+ /* transition towards disconnected */ -+ list_add_tail (&nodeRail->Link, &rail->DisconnectingList); -+ nodeRail->State = EP_NODE_DISCONNECTING; -+ continue; -+ } -+ -+ EPRINTF6 (DBG_MANAGER, "%s: Node %d - %s NetworkErrorState=%x NextRunTime=%lx (%lx)\n", -+ rail->Name, nodeId, NodeStateNames[nodeRail->State], nodeRail->NetworkErrorState, -+ nodeRail->NextRunTime, nextRunTime); -+ -+ if (nodeRail->NetworkErrorState) -+ { -+ ProgressNetworkError (rail, nodeRail); -+ } -+ else if (! BEFORE (lbolt, nodeRail->NextRunTime)) -+ { -+ if (EP_XID_INVALID (nodeRail->MsgXid)) -+ nodeRail->MsgXid = ep_xid_cache_alloc (sys, &rail->XidCache); -+ -+ if (ep_send_message (rail, nodeId, EP_MANAGER_MSG_TYPE_FLUSH_REQUEST, nodeRail->MsgXid, NULL) == 0) -+ nodeRail->NextRunTime = lbolt + MESSAGE_RETRY_TIME; -+ else -+ nodeRail->NextRunTime = lbolt + MSGBUSY_RETRY_TIME; -+ } -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, nodeRail->NextRunTime)) -+ nextRunTime = nodeRail->NextRunTime; -+ } -+ -+ if (! list_empty (&rail->PassivatedList)) -+ { -+ ep_call_callbacks (rail, EP_CB_FAILOVER, rail->NodeSet); -+ -+ list_for_each_safe (el, nel, &rail->PassivatedList) { -+ EP_NODE_RAIL *nodeRail = list_entry (rail->PassivatedList.next, EP_NODE_RAIL, Link); -+ int nodeId = nodeRail - rail->Nodes; -+ EP_NODE *node = &sys->Nodes[nodeId]; -+ -+ ASSERT (nodeRail->NetworkErrorState == 0); -+ -+ if (node->ConnectedRails == 0) -+ { -+ /* Remove from this list */ -+ list_del (&nodeRail->Link); -+ -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d, no rails, Passivated -> Disconnecting\n", rail->Name, nodeId); -+ -+ /* transition towards disconnected */ -+ list_add_tail (&nodeRail->Link, &rail->DisconnectingList); -+ nodeRail->State = EP_NODE_DISCONNECTING; -+ continue; -+ } -+ -+ EPRINTF6 (DBG_MANAGER, "%s: Node %d - %s NetworkErrorState=%x NextRunTime=%lx (%lx)\n", -+ rail->Name, nodeId, NodeStateNames[nodeRail->State], nodeRail->NetworkErrorState, -+ nodeRail->NextRunTime, nextRunTime); -+ -+ if (nodeRail->MessageState == 0) -+ { -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d, no messages, Passivated -> Disconnecting\n", rail->Name,nodeId); -+ -+ list_del (&nodeRail->Link); -+ list_add_tail (&nodeRail->Link, &rail->DisconnectingList); -+ nodeRail->State = EP_NODE_DISCONNECTING; -+ continue; -+ } -+ -+ nodeRail->MessageState = 0; -+ nodeRail->NextRunTime = lbolt + FAILOVER_RETRY_TIME; -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, nodeRail->NextRunTime)) -+ nextRunTime = nodeRail->NextRunTime; -+ } -+ } -+ -+ if (! list_empty (&rail->DisconnectingList)) -+ { -+ ep_call_callbacks (rail, EP_CB_DISCONNECTING, rail->NodeSet); -+ -+ while (! list_empty (&rail->DisconnectingList)) -+ { -+ EP_NODE_RAIL *nodeRail = list_entry (rail->DisconnectingList.next, EP_NODE_RAIL, Link); -+ int nodeId = nodeRail - rail->Nodes; -+ EP_NODE *node = &sys->Nodes[nodeId]; -+ -+ EPRINTF2 (DBG_MANAGER, "%s: Node %d, Disconnecting -> Disconnected\n", rail->Name, nodeId); -+ -+ list_del (&nodeRail->Link); -+ -+ rail->Operations.NodeDisconnected (rail, nodeId); -+ -+ /* Clear the network error state */ -+ nodeRail->NextRunTime = 0; -+ nodeRail->NetworkErrorState = 0; -+ nodeRail->NetworkErrorCookies[0] = 0; -+ nodeRail->NetworkErrorCookies[1] = 0; -+ -+ /* Clear the message state */ -+ nodeRail->MessageState = 0; -+ -+ cm_node_disconnected (rail, nodeId); -+ -+ nodeRail->State = EP_NODE_DISCONNECTED; -+ -+ statemap_setbits (rail->NodeSet, nodeId, 0, 1); -+ -+ if (node->ConnectedRails == 0) -+ statemap_setbits (sys->NodeSet, nodeId, 0, 1); -+ } -+ -+ ep_call_callbacks (rail, EP_CB_DISCONNECTED, rail->NodeSet); -+ } -+ -+ return (nextRunTime); -+} -+ -+void -+DisplayNodes (EP_RAIL *rail) -+{ -+ EP_SYS *sys = rail->System; -+ int i, state, count; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ -+ for (state = 0; state < EP_NODE_NUM_STATES; state++) -+ { -+ for (count = i = 0; i < rail->Position.pos_nodes; i++) -+ { -+ ASSERT (rail->Nodes[i].State < EP_NODE_NUM_STATES); -+ -+ if (rail->Nodes[i].State == state) -+ if (state != EP_NODE_DISCONNECTED) -+ printk ("%s %d", !count++ ? NodeStateNames[state] : "", i); -+ } -+ if (count) -+ printk ("%s (%d total)\n", state == EP_NODE_DISCONNECTED ? NodeStateNames[state] : "", count); -+ } -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+} -+ -+static void -+PositionFound (EP_RAIL *rail, ELAN_POSITION *pos) -+{ -+ EP_SYS *sys = rail->System; -+ struct list_head *el; -+ int i; -+ -+ /* only called from the ep_managage whilst rail->State == EP_RAIL_STATE_STARTED */ -+ ASSERT ( rail->State == EP_RAIL_STATE_STARTED ); -+ -+#if defined(PER_CPU_TIMEOUT) -+ /* -+ * On Tru64 - if we're running in a "funnelled" thread, then we will be -+ * unable to start the per-cpu timeouts, so if we return then eventually -+ * the ep_manager() thread will find the network position and we're -+ * in control of our own destiny. -+ */ -+ if (THREAD_IS_FUNNELED(current_thread())) -+ { -+ ep_kthread_schedule (&sys->ManagerThread, lbolt); -+ return; -+ } -+#endif -+ -+ sprintf (rail->Name, "ep%d[%d]", rail->Number, pos->pos_nodeid); -+ -+ if (pos->pos_levels > MaxSwitchLevels) -+ { -+ for (i = 0; i < (pos->pos_levels - MaxSwitchLevels); i++) -+ pos->pos_nodes /= pos->pos_arity[i]; -+ -+ for (i = 0; i < MaxSwitchLevels; i++) -+ pos->pos_arity[i] = pos->pos_arity[i + (pos->pos_levels - MaxSwitchLevels)]; -+ -+ pos->pos_levels = MaxSwitchLevels; -+ pos->pos_nodeid = pos->pos_nodeid % pos->pos_nodes; -+ -+ printk ("%s: limiting switch levels to %d\n", rail->Name, MaxSwitchLevels); -+ printk ("%s: nodeid=%d level=%d numnodes=%d\n", rail->Name, pos->pos_nodeid, pos->pos_levels, pos->pos_nodes); -+ -+ sprintf (rail->Name, "ep%d[%d]", rail->Number, pos->pos_nodeid); -+ } -+ -+ if (rail->Position.pos_mode != ELAN_POS_UNKNOWN && rail->Position.pos_nodeid != pos->pos_nodeid) -+ { -+ printk ("%s: NodeId has changed from %d to %d\n", rail->Name, rail->Position.pos_nodeid, pos->pos_nodeid); -+ panic ("ep: PositionFound: NodeId has changed\n"); -+ } -+ -+ if (sys->Position.pos_mode != ELAN_POS_UNKNOWN && (sys->Position.pos_nodeid != pos->pos_nodeid || sys->Position.pos_nodes != pos->pos_nodes)) -+ { -+ printk ("%s: position incompatible - disabling rail\n", rail->Name); -+ rail->State = EP_RAIL_STATE_INCOMPATIBLE; -+ return; -+ } -+ -+ if (sys->Position.pos_mode == ELAN_POS_UNKNOWN) -+ { -+ sys->Position = *pos; -+ sys->NodeSet = statemap_create (pos->pos_nodes); -+ KMEM_ZALLOC (sys->Nodes, EP_NODE *, pos->pos_nodes * sizeof (EP_NODE), 1); -+ } -+ -+ rail->Position = *pos; -+ rail->SwitchBroadcastLevel = pos->pos_levels - 1; -+ rail->State = EP_RAIL_STATE_RUNNING; -+ -+ for (i = 0; i < pos->pos_levels; i++) -+ { -+ rail->SwitchProbeTick[i] = lbolt; -+ rail->SwitchLast[i].uplink = 4; -+ } -+ -+ rail->Operations.PositionFound (rail, pos); -+ -+ INIT_LIST_HEAD (&rail->NetworkErrorList); -+ INIT_LIST_HEAD (&rail->LocalPassivateList); -+ INIT_LIST_HEAD (&rail->RemotePassivateList); -+ INIT_LIST_HEAD (&rail->PassivatedList); -+ INIT_LIST_HEAD (&rail->DisconnectingList); -+ -+ rail->NodeSet = statemap_create (rail->Position.pos_nodes); -+ rail->NodeChangeMap = statemap_create (rail->Position.pos_nodes); -+ rail->NodeChangeTmp = statemap_create (rail->Position.pos_nodes); -+ -+ KMEM_ZALLOC (rail->Nodes, EP_NODE_RAIL *, rail->Position.pos_nodes * sizeof (EP_NODE_RAIL), 1); -+ -+ for (i = 0; i < rail->Position.pos_nodes; i++) -+ { -+ spin_lock_init (&rail->Nodes[i].CookieLock); -+ -+ INIT_LIST_HEAD (&rail->Nodes[i].StalledDmas); -+ -+ rail->Nodes[i].State = EP_NODE_DISCONNECTED; -+ } -+ -+ /* Notify all subsystems that a new rail has been enabled */ -+ kmutex_lock (&sys->SubsysLock); -+ list_for_each (el, &sys->Subsystems) { -+ EP_SUBSYS *subsys = list_entry (el, EP_SUBSYS, Link); -+ -+ if (subsys->AddRail) -+ subsys->AddRail (subsys, sys, rail); -+ -+ /* XXXX: what to do if the subsystem refused to add the rail ? */ -+ } -+ kmutex_unlock (&sys->SubsysLock); -+ -+ /* Now enable the manager input queue */ -+ ep_enable_inputq (rail, rail->ManagerInputQ); -+} -+ -+static void -+ep_manager (void *arg) -+{ -+ EP_SYS *sys = (EP_SYS *) arg; -+ struct list_head *el; -+ ELAN_POSITION pos; -+ unsigned long flags; -+ -+ kernel_thread_init ("ep_manager"); -+ kernel_thread_become_highpri(); -+ -+ for (;;) -+ { -+ long nextRunTime = lbolt + MSEC2TICKS(CM_THREAD_SCHEDULE_TIMEOUT); -+ -+ list_for_each (el, &sys->ManagedRails) { -+ EP_RAIL *rail = list_entry (el, EP_RAIL, ManagerLink); -+ -+ switch (rail->State) -+ { -+ case EP_RAIL_STATE_STARTED: -+ if (ProbeNetwork (rail, &pos) == 0) -+ { -+ PositionFound (rail, &pos); -+ break; -+ } -+ -+ if (nextRunTime == 0 || AFTER (nextRunTime, lbolt + HZ)) -+ nextRunTime = lbolt + HZ; -+ break; -+ -+ case EP_RAIL_STATE_RUNNING: -+ if (ep_poll_inputq (rail, rail->ManagerInputQ, 100, ProcessMessage, rail) >= 100) -+ nextRunTime = lbolt; -+ -+ /* Handle any nodes which the cluster membership subsystem -+ * has indicated are to begin connecting or disconnecting */ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ if (! statemap_changed (rail->NodeChangeMap)) -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ else -+ { -+ /* -+ * Take a copy of the statemap, and zero all entries so -+ * we only see new requests next time -+ */ -+ statemap_copy (rail->NodeChangeTmp, rail->NodeChangeMap); -+ statemap_zero (rail->NodeChangeMap); -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ UpdateConnectionState (rail, rail->NodeChangeTmp); -+ } -+ -+ nextRunTime = ProgressNodeLists (rail, nextRunTime); -+ -+ if (statemap_changed (rail->NodeSet)) -+ { -+ ep_call_callbacks (rail, EP_CB_NODESET, rail->NodeSet); -+ -+ statemap_clearchanges (rail->NodeSet); -+ } -+ break; -+ -+ case EP_RAIL_STATE_INCOMPATIBLE: -+ break; -+ } -+ } -+ -+ -+ EPRINTF5 (DBG_MANAGER, "ep_manager: sleep now=%lx nextRunTime=%lx (%ld) [%lx (%ld)]\n", -+ lbolt, nextRunTime, nextRunTime ? nextRunTime - lbolt : 0, sys->ManagerThread.next_run, -+ sys->ManagerThread.next_run ? sys->ManagerThread.next_run - lbolt : 0); -+ -+ if (ep_kthread_sleep (&sys->ManagerThread, nextRunTime) < 0) -+ break; -+ } -+ -+ ep_kthread_stopped (&sys->ManagerThread); -+ kernel_thread_exit(); -+} -+ -+void -+ep_connect_node (EP_RAIL *rail, int nodeId) -+{ -+ EP_SYS *sys = rail->System; -+ EP_NODE_RAIL *node = &rail->Nodes[nodeId]; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ -+ EPRINTF2 (DBG_MANAGER, "%s: ep_connect_node: nodeId %d\n", rail->Name, nodeId); -+ -+ ASSERT (node->State == EP_NODE_DISCONNECTED && statemap_getbits (rail->NodeChangeMap, nodeId, 1) == 0); -+ -+ node->State = EP_NODE_CONNECTING; -+ -+ statemap_setbits (rail->NodeChangeMap, nodeId, 1, 1); -+ -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ ep_kthread_schedule (&sys->ManagerThread, lbolt); -+} -+ -+int -+ep_disconnect_node (EP_RAIL *rail, int nodeId) -+{ -+ EP_SYS *sys = rail->System; -+ EP_NODE_RAIL *node = &rail->Nodes[nodeId]; -+ int state; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ -+ EPRINTF3 (DBG_MANAGER, "%s: ep_disconnect_node: nodeId %d - %s\n", rail->Name, nodeId, NodeStateNames[node->State]); -+ -+ switch (state = node->State) -+ { -+ case EP_NODE_CONNECTING: -+ statemap_setbits (rail->NodeChangeMap, nodeId, 0, 1); -+ -+ node->State = EP_NODE_DISCONNECTED; -+ break; -+ -+ case EP_NODE_CONNECTED: -+ statemap_setbits (rail->NodeChangeMap, nodeId, 1, 1); -+ -+ node->State = EP_NODE_LEAVING_CONNECTED; -+ break; -+ -+ case EP_NODE_LEAVING_CONNECTED: -+ /* no assert on NodeChangeMap as the map could have been taken but not acted on */ -+ break; -+ -+ default: -+ ASSERT (statemap_getbits (rail->NodeChangeMap, nodeId, 1) == 0); -+ break; -+ } -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ if (state == EP_NODE_CONNECTED) -+ ep_kthread_schedule (&sys->ManagerThread, lbolt); -+ -+ return state; -+} -+ -+int -+ep_manager_add_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ if ((rail->ManagerOutputQ = ep_alloc_outputq (rail, EP_MANAGER_MSG_SIZE, EP_MANAGER_OUTPUTQ_SLOTS)) == NULL) -+ return -ENOMEM; -+ -+ if ((rail->ManagerInputQ = ep_alloc_inputq (rail, EP_SYSTEMQ_MANAGER, EP_MANAGER_MSG_SIZE, EP_MANAGER_INPUTQ_SLOTS, -+ ManagerQueueEvent, &sys->ManagerThread)) == NULL) -+ { -+ ep_free_outputq (rail, rail->ManagerOutputQ); -+ return -ENOMEM; -+ } -+ -+ spin_lock_init (&rail->ManagerOutputQLock); -+ -+ ep_xid_cache_init (sys, &rail->XidCache); -+ -+ ep_kthread_stall (&sys->ManagerThread); -+ list_add_tail (&rail->ManagerLink, &sys->ManagedRails); -+ ep_kthread_resume (&sys->ManagerThread); -+ -+ return (0); -+} -+ -+void -+ep_manager_remove_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ if (rail->ManagerInputQ != NULL) -+ { -+ ep_kthread_stall (&sys->ManagerThread); -+ list_del (&rail->ManagerLink); -+ ep_kthread_resume (&sys->ManagerThread); -+ -+ ep_xid_cache_destroy (sys, &rail->XidCache); -+ -+ spin_lock_destroy (&rail->ManagerOutputQLock); -+ -+ ep_disable_inputq (rail, rail->ManagerInputQ); -+ ep_free_inputq (rail, rail->ManagerInputQ); -+ ep_free_outputq (rail, rail->ManagerOutputQ); -+ } -+} -+ -+int -+ep_manager_init (EP_SYS *sys) -+{ -+ INIT_LIST_HEAD (&sys->ManagedRails); -+ -+ ep_kthread_init (&sys->ManagerThread); -+ -+ if (kernel_thread_create (ep_manager, (void *) sys) == 0) -+ return (ENOMEM); -+ -+ ep_kthread_started (&sys->ManagerThread); -+ -+ return (0); -+} -+ -+void -+ep_manager_fini (EP_SYS *sys) -+{ -+ ep_kthread_stop (&sys->ManagerThread); -+ ep_kthread_destroy (&sys->ManagerThread); -+} -+ -+int -+ep_sys_init (EP_SYS *sys) -+{ -+ kmutex_init (&sys->SubsysLock); -+ kmutex_init (&sys->StartStopLock); -+ spin_lock_init (&sys->NodeLock); -+ -+ INIT_LIST_HEAD (&sys->Subsystems); -+ -+ /* initialise the xid allocators */ -+ spin_lock_init (&sys->XidLock); -+ INIT_LIST_HEAD (&sys->XidCacheList); -+ -+ /* initially don't know where we are in the network */ -+ sys->Position.pos_mode = ELAN_POS_UNKNOWN; -+ -+ /* initialise the network mapping descriptor hash tables */ -+ ep_nmh_init (&sys->MappingTable); -+ -+ /* intialise the shared allocators */ -+ ep_shared_alloc_init (sys); -+ -+ /* initialise the dvma space */ -+ ep_dvma_init (sys); -+ -+ /* intiialise the rail manager */ -+ ep_manager_init (sys); -+ -+ /* initialise all subsystems */ -+ cm_init (sys); -+ ep_comms_init (sys); -+ //ep_msgsys_init (sys); -+ -+ return (0); -+} -+ -+void -+ep_sys_fini (EP_SYS *sys) -+{ -+ /* Destroy the subsystems in the reverse order to their creation */ -+ while (! list_empty (&sys->Subsystems)) -+ { -+ EP_SUBSYS *subsys = list_entry (sys->Subsystems.prev, EP_SUBSYS, Link); -+ -+ list_del (&subsys->Link); -+ -+ subsys->Destroy (subsys, sys); -+ } -+ -+ ep_manager_fini(sys); -+ ep_dvma_fini (sys); -+ ep_shared_alloc_fini (sys); -+ -+ ep_nmh_fini (&sys->MappingTable); -+ -+ if (sys->Position.pos_mode != ELAN_POS_UNKNOWN) { -+ statemap_destroy (sys->NodeSet); -+ KMEM_FREE(sys->Nodes, sys->Position.pos_nodes * sizeof (EP_NODE)); -+ } -+ -+ spin_lock_destroy (&sys->XidLock); -+ -+ spin_lock_destroy (&sys->NodeLock); -+ kmutex_destroy (&sys->SubsysLock); -+ kmutex_destroy (&sys->StartStopLock); -+} -+ -+void -+ep_shutdown (EP_SYS *sys) -+{ -+ sys->Shutdown = 1; -+} -+ -+int -+ep_init_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ static int rnum; -+ -+ rail->System = sys; -+ rail->State = EP_RAIL_STATE_UNINITIALISED; -+ rail->Number = rnum++; -+ rail->Position.pos_mode = ELAN_POS_UNKNOWN; -+ rail->Position.pos_nodeid = ELAN_INVALID_NODE; -+ -+ rail->CallbackRegistered = 0; -+ -+ sprintf (rail->Name, "ep%d", rail->Number); -+ -+ /* Initialise externally visible locks */ -+ kmutex_init (&rail->CallbackLock); -+ -+ ep_alloc_init (rail); -+ -+ sys->Rails[rail->Number] = rail; -+ -+ return 0; -+} -+ -+void -+ep_destroy_rail (EP_RAIL *rail) -+{ -+ ASSERT (rail->State == EP_RAIL_STATE_UNINITIALISED); -+ -+ ep_alloc_fini (rail); -+ -+ kmutex_destroy (&rail->CallbackLock); -+ -+ rail->System->Rails[rail->Number] = NULL; -+ -+ rail->Operations.DestroyRail (rail); -+} -+ -+/* We need to traverse the Subsystems lists backwards -+ * but it's not defined in */ -+#define list_for_each_backwards(pos,list) \ -+ for (pos = (list)->prev; pos != (list); \ -+ pos = (pos)->prev) -+ -+void -+__ep_stop_rail (EP_RAIL *rail) -+{ -+ /* called holding the sys->Lock */ -+ EP_SYS *sys = rail->System; -+ struct list_head *el; -+ -+ rail->Operations.StallRail (rail); -+ -+ /* Notify all subsystems that this rail is being stopped */ -+ if (rail->State == EP_RAIL_STATE_RUNNING) -+ { -+ kmutex_lock (&sys->SubsysLock); -+ list_for_each_backwards (el, &sys->Subsystems) { -+ EP_SUBSYS *subsys = list_entry (el, EP_SUBSYS, Link); -+ -+ if (subsys->RemoveRail) -+ subsys->RemoveRail (subsys, sys, rail); -+ } -+ kmutex_unlock (&sys->SubsysLock); -+ -+ ep_manager_remove_rail (sys, rail); -+ -+ KMEM_FREE (rail->Nodes, rail->Position.pos_nodes * sizeof (EP_NODE_RAIL)); -+ -+ statemap_destroy (rail->NodeChangeTmp); -+ statemap_destroy (rail->NodeChangeMap); -+ statemap_destroy (rail->NodeSet); -+ } -+ -+ ep_dvma_remove_rail (sys, rail); -+ ep_shared_alloc_remove_rail (sys, rail); -+ -+ rail->Operations.StopRail (rail); -+ -+ rail->State = EP_RAIL_STATE_UNINITIALISED; -+} -+ -+void -+ep_stop_rail (EP_RAIL *rail) -+{ -+ EP_SYS *sys = rail->System; -+ -+ /* stall ep_manager */ -+ /* and remove the rail from the manaager */ -+ -+ ep_kthread_stall (&sys->ManagerThread); -+ if ( rail->State == EP_RAIL_STATE_STARTED ) -+ ep_manager_remove_rail (sys, rail); -+ ep_kthread_resume (&sys->ManagerThread); -+ -+ __ep_stop_rail (rail); -+} -+ -+int -+ep_start_rail (EP_RAIL *rail) -+{ -+ EP_SYS *sys = rail->System; -+ -+ ASSERT (rail->State == EP_RAIL_STATE_UNINITIALISED); -+ -+ if (rail->Operations.StartRail (rail) < 0) -+ return -ENXIO; -+ -+ kmutex_lock (&sys->StartStopLock); -+ /* Add this rail to the shared allocator */ -+ if (ep_shared_alloc_add_rail (rail->System, rail)) -+ goto failed; -+ -+ /* Add this rail to dvma kmap */ -+ if (ep_dvma_add_rail (rail->System, rail)) -+ goto failed; -+ -+ /* rail is now started */ -+ rail->State = EP_RAIL_STATE_STARTED; -+ -+ /* notify the rail manager of the new rail */ -+ if (ep_manager_add_rail (rail->System, rail)) -+ goto failed; -+ -+ kmutex_unlock (&sys->StartStopLock); -+ return (ESUCCESS); -+ -+ failed: -+ printk ("%s: start failed\n", rail->Name); -+ kmutex_unlock (&sys->StartStopLock); -+ __ep_stop_rail (rail); -+ -+ return (ENOMEM); -+} -+ -+void -+ep_subsys_add (EP_SYS *sys, EP_SUBSYS *subsys) -+{ -+ kmutex_lock (&sys->SubsysLock); -+ list_add_tail (&subsys->Link, &sys->Subsystems); -+ kmutex_unlock (&sys->SubsysLock); -+} -+ -+void -+ep_subsys_del (EP_SYS *sys, EP_SUBSYS *subsys) -+{ -+ kmutex_lock (&sys->SubsysLock); -+ list_del (&subsys->Link); -+ kmutex_unlock (&sys->SubsysLock); -+} -+ -+EP_SUBSYS * -+ep_subsys_find (EP_SYS *sys, char *name) -+{ -+ struct list_head *el; -+ -+ ASSERT ( !in_interrupt()); -+ -+ kmutex_lock (&sys->SubsysLock); -+ list_for_each (el, &sys->Subsystems) { -+ EP_SUBSYS *subsys = list_entry (el, EP_SUBSYS, Link); -+ -+ if (! strcmp (subsys->Name, name)) -+ { -+ kmutex_unlock (&sys->SubsysLock); -+ return (subsys); -+ } -+ } -+ -+ kmutex_unlock (&sys->SubsysLock); -+ return (NULL); -+} -+ -+int -+ep_waitfor_nodeid (EP_SYS *sys) -+{ -+ int i, printed = 0; -+ kcondvar_t Sleep; -+ spinlock_t Lock; -+ -+ kcondvar_init (&Sleep); -+ spin_lock_init (&Lock); -+ -+#define TICKS_TO_WAIT (10*hz) -+#define TICKS_PER_LOOP (hz/10) -+ for (i = 0; sys->Position.pos_mode == ELAN_POS_UNKNOWN && i < TICKS_TO_WAIT; i += TICKS_PER_LOOP) -+ { -+ if (! printed++) -+ printk ("ep: waiting for network position to be found\n"); -+ -+ spin_lock (&Lock); -+ kcondvar_timedwait (&Sleep, &Lock, NULL, lbolt + TICKS_PER_LOOP); -+ spin_unlock (&Lock); -+ } -+ -+ if (sys->Position.pos_mode == ELAN_POS_UNKNOWN) -+ printk ("ep: network position not found after waiting\n"); -+ else if (printed) -+ printk ("ep: network position found at nodeid %d\n", sys->Position.pos_nodeid); -+ -+ spin_lock_destroy (&Lock); -+ kcondvar_destroy (&Sleep); -+ -+ return (sys->Position.pos_mode == ELAN_POS_UNKNOWN ? ELAN_INVALID_NODE : sys->Position.pos_nodeid); -+} -+ -+int -+ep_nodeid (EP_SYS *sys) -+{ -+ return (sys->Position.pos_mode == ELAN_POS_UNKNOWN ? ELAN_INVALID_NODE : sys->Position.pos_nodeid); -+} -+ -+int -+ep_numnodes (EP_SYS *sys) -+{ -+ return (sys->Position.pos_nodes); -+} -+ -+void -+ep_fillout_stats(EP_RAIL *r, char *str) -+{ -+ sprintf(str+strlen(str),"SendMessageFailed %lu NeterrAtomicPacket %lu NeterrDmaPacket %lu \n", r->Stats.SendMessageFailed, r->Stats.NeterrAtomicPacket, r->Stats.NeterrDmaPacket); -+ sprintf(str+strlen(str),"Rx %lu %lu /sec\n", GET_STAT_TOTAL(r->Stats,rx), GET_STAT_PER_SEC(r->Stats,rx) ); -+ sprintf(str+strlen(str),"MBytes %lu %lu MB/sec\n", GET_STAT_TOTAL(r->Stats,rx_len)/ (1024*1024), GET_STAT_PER_SEC(r->Stats,rx_len) / (1024*1024)); -+ sprintf(str+strlen(str),"Tx %lu %lu /sec\n", GET_STAT_TOTAL(r->Stats,tx), GET_STAT_PER_SEC(r->Stats,tx) ); -+ sprintf(str+strlen(str),"MBytes %lu %lu MB/sec\n", GET_STAT_TOTAL(r->Stats,tx_len)/ (1024*1024), GET_STAT_PER_SEC(r->Stats,tx_len) / (1024*1024)); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kcomm_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan3.c 2005-06-01 23:12:54.665429072 -0400 -@@ -0,0 +1,504 @@ -+ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kcomm_elan3.c,v 1.31.8.3 2004/11/30 12:02:17 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm_elan3.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "conf_linux.h" -+ -+extern EP_CODE threadcode_elan3; -+ -+unsigned int -+ep3_create_rails (EP_SYS *sys, unsigned int disabled) -+{ -+ unsigned int rmask = 0; -+ ELAN3_DEV *dev; -+ EP_RAIL *rail; -+ int i; -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ { -+ if ((dev = elan3_device (i)) != NULL) -+ { -+ if ((rail = ep3_create_rail (sys, dev)) != NULL) -+ { -+ if (disabled & (1 << rail->Number)) -+ printk ("%s: auto-start of device disabled by configuration\n", rail->Name); -+ else -+ ep_start_rail (rail); -+ -+ ep_procfs_rail_init(rail); -+ -+ rmask |= (1 << rail->Number); -+ } -+ } -+ } -+ -+ return rmask; -+} -+ -+EP_RAIL * -+ep3_create_rail (EP_SYS *sys, ELAN3_DEV *dev) -+{ -+ EP3_RAIL *rail; -+ int res; -+ -+ KMEM_ZALLOC (rail, EP3_RAIL *, sizeof (EP3_RAIL), TRUE); -+ -+ if (rail == NULL) -+ return (EP_RAIL *) NULL; -+ -+ if ((res = ep_init_rail (sys, &rail->Generic)) != 0) -+ { -+ KMEM_FREE (rail, sizeof (EP3_RAIL)); -+ return (EP_RAIL *) NULL; -+ } -+ -+ rail->Device = dev; -+ -+ /* Install our rail operations */ -+ rail->Generic.Operations.DestroyRail = ep3_destroy_rail; -+ rail->Generic.Operations.StartRail = ep3_start_rail; -+ rail->Generic.Operations.StallRail = ep3_stall_rail; -+ rail->Generic.Operations.StopRail = ep3_stop_rail; -+ -+ rail->Generic.Operations.SdramAlloc = ep3_sdram_alloc; -+ rail->Generic.Operations.SdramFree = ep3_sdram_free; -+ rail->Generic.Operations.SdramWriteb = ep3_sdram_writeb; -+ -+ rail->Generic.Operations.KaddrMap = ep3_kaddr_map; -+ rail->Generic.Operations.SdramMap = ep3_sdram_map; -+ rail->Generic.Operations.Unmap = ep3_unmap; -+ -+ rail->Generic.Operations.DvmaReserve = ep3_dvma_reserve; -+ rail->Generic.Operations.DvmaRelease = ep3_dvma_release; -+ rail->Generic.Operations.DvmaSetPte = ep3_dvma_set_pte; -+ rail->Generic.Operations.DvmaReadPte = ep3_dvma_read_pte; -+ rail->Generic.Operations.DvmaUnload = ep3_dvma_unload; -+ rail->Generic.Operations.FlushTlb = ep3_flush_tlb; -+ -+ rail->Generic.Operations.ProbeRoute = ep3_probe_route; -+ rail->Generic.Operations.PositionFound = ep3_position_found; -+ rail->Generic.Operations.CheckPosition = ep3_check_position; -+ rail->Generic.Operations.NeterrFixup = ep3_neterr_fixup; -+ -+ rail->Generic.Operations.LoadSystemRoute = ep3_load_system_route; -+ -+ rail->Generic.Operations.LoadNodeRoute = ep3_load_node_route; -+ rail->Generic.Operations.UnloadNodeRoute = ep3_unload_node_route; -+ rail->Generic.Operations.LowerFilter = ep3_lower_filter; -+ rail->Generic.Operations.RaiseFilter = ep3_raise_filter; -+ rail->Generic.Operations.NodeDisconnected = ep3_node_disconnected; -+ -+ rail->Generic.Operations.FlushFilters = ep3_flush_filters; -+ rail->Generic.Operations.FlushQueues = ep3_flush_queues; -+ -+ rail->Generic.Operations.AllocInputQ = ep3_alloc_inputq; -+ rail->Generic.Operations.FreeInputQ = ep3_free_inputq; -+ rail->Generic.Operations.EnableInputQ = ep3_enable_inputq; -+ rail->Generic.Operations.DisableInputQ = ep3_disable_inputq; -+ rail->Generic.Operations.PollInputQ = ep3_poll_inputq; -+ -+ rail->Generic.Operations.AllocOutputQ = ep3_alloc_outputq; -+ rail->Generic.Operations.FreeOutputQ = ep3_free_outputq; -+ rail->Generic.Operations.OutputQMsg = ep3_outputq_msg; -+ rail->Generic.Operations.OutputQState = ep3_outputq_state; -+ rail->Generic.Operations.OutputQSend = ep3_outputq_send; -+ -+ rail->Generic.Operations.FillOutStats = ep3_fillout_stats; -+ -+ rail->Generic.Devinfo = dev->Devinfo; -+ -+ printk ("%s: connected via elan3 rev%c device %d\n", rail->Generic.Name, -+ 'a' + dev->Devinfo.dev_revision_id, dev->Instance); -+ -+ return (EP_RAIL *) rail; -+} -+ -+void -+ep3_destroy_rail (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ -+ KMEM_FREE (rail, sizeof (EP3_RAIL)); -+} -+ -+static int -+ep3_attach_rail (EP3_RAIL *rail) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ ELAN3_CTXT *ctxt; -+ ELAN_CAPABILITY *cap; -+ int ctx; -+ unsigned long flags; -+ -+ if ((ctxt = elan3_alloc (dev, TRUE)) == (ELAN3_CTXT *) NULL) -+ { -+ printk ("%s: cannot allocate elan context\n", rail->Generic.Name); -+ return -ENXIO; -+ } -+ -+ ctxt->Operations = &ep3_elan3_ops; -+ ctxt->Private = (void *) rail; -+ -+ /* Initialise a capability and attach to the elan*/ -+ KMEM_ALLOC (cap, ELAN_CAPABILITY *, sizeof (ELAN_CAPABILITY), TRUE); -+ -+ elan_nullcap (cap); -+ -+ cap->cap_type = ELAN_CAP_TYPE_KERNEL; -+ cap->cap_version = ELAN_CAP_VERSION_NUMBER; -+ cap->cap_mycontext = ELAN3_MRF_CONTEXT_NUM | SYS_CONTEXT_BIT; -+ cap->cap_lowcontext = ELAN3_MRF_CONTEXT_NUM | SYS_CONTEXT_BIT; -+ cap->cap_highcontext = ELAN3_MRF_CONTEXT_NUM | SYS_CONTEXT_BIT; -+ cap->cap_railmask = 1 << dev->Devinfo.dev_rail; -+ -+ /* Ensure the context filter is raised while we initialise */ -+ elan3_block_inputter (ctxt, TRUE); -+ -+ if (elan3_doattach (ctxt, cap) != 0) -+ { -+ printk ("%s: cannot attach to kernel context\n", rail->Generic.Name); -+ -+ KMEM_FREE (cap, sizeof (ELAN_CAPABILITY)); -+ elan3_free (ctxt); -+ return -ENXIO; -+ } -+ KMEM_FREE (cap, sizeof (ELAN_CAPABILITY)); -+ -+ /* now attach to all the kernel comms input/dmaring/data contexts */ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ for (ctx = ELAN3_DMARING_BASE_CONTEXT_NUM; ctx <= ELAN3_DMARING_TOP_CONTEXT_NUM; ctx++) -+ { -+ /* place it in the info table. NOTE: don't call elan3mmu_set_info, as this */ -+ /* will queue the info again on the devices info list */ -+ dev->CtxtTable[ctx] = ctxt; -+ -+ elan3mmu_set_context_filter (dev, ctx|SYS_CONTEXT_BIT, TRUE, 0, NULL); -+ elan3mmu_attach (dev, ctx, ctxt->Elan3mmu, ctxt->RouteTable->Table, ctxt->RouteTable->Size-1); -+ } -+ -+ for (ctx = ELAN3_KCOMM_BASE_CONTEXT_NUM; ctx <= ELAN3_KCOMM_TOP_CONTEXT_NUM; ctx++) -+ { -+ /* place it in the info table. NOTE: don't call elan3mmu_set_info, as this */ -+ /* will queue the info again on the devices info list */ -+ dev->CtxtTable[ctx] = ctxt; -+ -+ elan3mmu_set_context_filter (dev, ctx|SYS_CONTEXT_BIT, TRUE, 0, NULL); -+ elan3mmu_attach (dev, ctx, ctxt->Elan3mmu, ctxt->RouteTable->Table, ctxt->RouteTable->Size-1); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ /* Stash the ctxt,commandport, mmu and route table */ -+ rail->Ctxt = ctxt; -+ rail->CommandPort = ctxt->CommandPort; -+ rail->Elan3mmu = ctxt->Elan3mmu; -+ rail->RouteTable = ctxt->RouteTable; -+ -+ return 0; -+} -+ -+static void -+ep3_detach_rail (EP3_RAIL *rail) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ unsigned long flags; -+ int ctx; -+ -+ /* detach from the elan */ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ for (ctx = ELAN3_KCOMM_BASE_CONTEXT_NUM; ctx <= ELAN3_KCOMM_TOP_CONTEXT_NUM; ctx++) -+ { -+ dev->CtxtTable[ctx] = NULL; -+ elan3mmu_detach (dev, ctx); -+ } -+ -+ for (ctx = ELAN3_DMARING_BASE_CONTEXT_NUM; ctx <= ELAN3_DMARING_TOP_CONTEXT_NUM; ctx++) -+ { -+ dev->CtxtTable[ctx] = NULL; -+ elan3mmu_detach (dev, ctx); -+ } -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ elan3_dodetach(rail->Ctxt); -+ elan3_free (rail->Ctxt); -+ -+ rail->Ctxt = NULL; -+ rail->CommandPort = 0; -+ rail->Elan3mmu = NULL; -+ rail->RouteTable = NULL; -+} -+ -+int -+ep3_start_rail (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ int i, res; -+ unsigned long flags; -+ -+ if ((res = ep3_attach_rail (rail)) != 0) -+ return res; -+ -+ spin_lock_init (&rail->CookieLock); -+ kmutex_init (&rail->HaltOpMutex); -+ kcondvar_init (&rail->HaltOpSleep); -+ -+ /* Initialise event interrupt cookie table */ -+ InitialiseCookieTable (&rail->CookieTable); -+ -+ /* Load and map the thread code */ -+ rail->ThreadCode = threadcode_elan3; -+ if (ep_loadcode (&rail->Generic, &rail->ThreadCode) != ESUCCESS) -+ goto failed; -+ -+ /* Map the command port to be visible to the Elan */ -+ ep3_ioaddr_map (&rail->Generic, EP3_COMMANDPORT_ADDR, rail->Ctxt->CommandPage, PAGESIZE, EP_PERM_WRITE); -+ rail->CommandPortAddr = EP3_COMMANDPORT_ADDR + (rail->Ctxt->CommandPort - rail->Ctxt->CommandPage); -+ -+ /* Allocate the elan visible sdram/main memory */ -+ if ((rail->RailElan = ep_alloc_elan (&rail->Generic, sizeof (EP3_RAIL_ELAN), 0, &rail->RailElanAddr)) == 0 || -+ (rail->RailMain = ep_alloc_main (&rail->Generic, sizeof (EP3_RAIL_MAIN), 0, &rail->RailMainAddr)) == 0) -+ { -+ goto failed; -+ } -+ -+ /* Allocate the system input queues at their fixed elan address */ -+ if (! (rail->QueueDescs = ep_alloc_memory_elan (&rail->Generic, EP_SYSTEM_QUEUE_BASE, PAGESIZE, EP_PERM_ALL, 0))) -+ goto failed; -+ -+ /* Initialise all queue entries to be full */ -+ for (i = 0; i < EP_NUM_SYSTEMQ; i++) -+ elan3_sdram_writel (rail->Device, EP_SYSTEMQ_DESC(rail->QueueDescs, i) + offsetof (EP3_InputQueue, q_state), E3_QUEUE_FULL); -+ -+ /* initialise the dma rings */ -+ if (DmaRingsCreate (rail)) -+ goto failed; -+ -+ if (InitialiseDmaRetries (rail)) -+ goto failed; -+ -+ if (ep3_init_probenetwork (rail)) -+ goto failed; -+ -+ /* can now drop the context filter for the system context */ -+ spin_lock_irqsave (&rail->Device->IntrLock, flags); -+ elan3mmu_set_context_filter (rail->Device, ELAN3_MRF_CONTEXT_NUM|SYS_CONTEXT_BIT, FALSE, 0, NULL); -+ spin_unlock_irqrestore (&rail->Device->IntrLock, flags); -+ -+ return 0; -+ -+ failed: -+ printk ("ep3_start_rail: failed for rail %d\n", rail->Generic.Number); -+ ep3_stop_rail (&rail->Generic); -+ -+ return -ENOMEM; -+} -+ -+void -+ep3_stall_rail (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ int ctx; -+ unsigned long flags; -+ -+ /* raise all the context filters */ -+ spin_lock_irqsave (&rail->Device->IntrLock, flags); -+ -+ for (ctx = ELAN3_KCOMM_BASE_CONTEXT_NUM; ctx <= ELAN3_KCOMM_TOP_CONTEXT_NUM; ctx++) -+ elan3mmu_set_context_filter (rail->Device, ctx|SYS_CONTEXT_BIT, TRUE, 0, NULL); -+ -+ for (ctx = ELAN3_DMARING_BASE_CONTEXT_NUM; ctx <= ELAN3_DMARING_TOP_CONTEXT_NUM; ctx++) -+ elan3mmu_set_context_filter (rail->Device, ctx|SYS_CONTEXT_BIT, TRUE, 0, NULL); -+ -+ elan3mmu_set_context_filter (rail->Device, ELAN3_MRF_CONTEXT_NUM|SYS_CONTEXT_BIT, TRUE, 0, NULL); -+ -+ spin_unlock_irqrestore (&rail->Device->IntrLock, flags); -+} -+ -+void -+ep3_stop_rail (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ -+ ep3_destroy_probenetwork (rail); -+ -+ if (rail->DmaRetryInitialised) -+ DestroyDmaRetries (rail); -+ -+ DmaRingsRelease(rail); -+ -+ if (rail->Generic.State == EP_RAIL_STATE_RUNNING) -+ { -+ KMEM_FREE (rail->MainCookies, rail->Generic.Position.pos_nodes * sizeof (E3_uint32)); -+ -+ ep_free_elan (&rail->Generic, rail->ElanCookies, rail->Generic.Position.pos_nodes * sizeof (E3_uint32)); -+ } -+ -+ if (rail->QueueDescs) -+ ep_free_memory_elan (&rail->Generic, EP_SYSTEM_QUEUE_BASE); -+ rail->QueueDescs = 0; -+ -+ if (rail->RailMain) -+ ep_free_main (&rail->Generic, rail->RailMainAddr, sizeof (EP3_RAIL_MAIN)); -+ rail->RailMain = 0; -+ -+ if (rail->RailElan) -+ ep_free_elan (&rail->Generic, rail->RailElanAddr, sizeof (EP3_RAIL_ELAN)); -+ rail->RailElan = 0; -+ -+ ep_unloadcode (&rail->Generic, &rail->ThreadCode); -+ -+ DestroyCookieTable (&rail->CookieTable); -+ -+ ep_perrail_unmap (&rail->Generic, rail->Ctxt->CommandPage, PAGESIZE); -+ -+ kcondvar_destroy (&rail->HaltOpSleep); -+ kmutex_destroy (&rail->HaltOpMutex); -+ spin_lock_destroy (&rail->CookieLock); -+ -+ ep3_detach_rail (rail); -+} -+ -+void -+ep3_position_found (EP_RAIL *r, ELAN_POSITION *pos) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ sdramaddr_t addr; -+ -+ rail->SwitchBroadcastLevelTick = lbolt; -+ -+ elan3_sdram_writel (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, NodeId), pos->pos_nodeid); -+ -+ /* Allocate Network Identify cookie state */ -+ KMEM_ZALLOC (rail->MainCookies, E3_uint32 *, pos->pos_nodes * sizeof (E3_uint32), 1); -+ -+ if (! (addr = ep_alloc_elan (&rail->Generic, pos->pos_nodes * sizeof (E3_uint32), 0, &rail->ElanCookies))) -+ panic ("ep: PositionFound: cannot allocate elan cookies array\n"); -+ -+ elan3_sdram_zeroq_sdram (rail->Device, addr, pos->pos_nodes * sizeof (E3_uint32)); -+ -+ ep3_probe_position_found (rail, pos); -+} -+ -+sdramaddr_t -+ep3_sdram_alloc (EP_RAIL *r, EP_ADDR addr, unsigned size) -+{ -+ return elan3_sdram_alloc (((EP3_RAIL *) r)->Device, size); -+} -+ -+void -+ep3_sdram_free (EP_RAIL *r, sdramaddr_t addr, unsigned size) -+{ -+ elan3_sdram_free (((EP3_RAIL *) r)->Device, addr, size); -+} -+ -+void -+ep3_sdram_writeb (EP_RAIL *r, sdramaddr_t addr, unsigned char val) -+{ -+ elan3_sdram_writeb (((EP3_RAIL *) r)->Device, addr, val); -+} -+ -+void -+ep3_flush_tlb (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ ELAN3_DEV *dev = rail->Device; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->TlbLock, flags); -+ -+ IncrStat (dev, TlbFlushes); -+ -+ write_reg32 (dev, Cache_Control_Reg.ContReg, dev->Cache_Control_Reg | MMU_FLUSH); -+ mmiob (); -+ spin_unlock_irqrestore (&dev->TlbLock, flags); -+ -+ while (! (read_reg32 (dev, Cache_Control_Reg.ContReg) & MMU_FLUSHED)) -+ mb(); -+} -+ -+void -+ep3_load_system_route (EP_RAIL *r, unsigned vp, unsigned lowNode, unsigned highNode) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ E3_uint16 flits[MAX_FLITS]; -+ int nflits; -+ -+ nflits = GenerateRoute (&rail->Generic.Position, flits, lowNode, highNode, DEFAULT_ROUTE_TIMEOUT, HIGH_ROUTE_PRIORITY); -+ -+ if (LoadRoute (rail->Device, rail->RouteTable, vp, ELAN3_MRF_CONTEXT_NUM|SYS_CONTEXT_BIT, nflits, flits) != 0) -+ { -+ /* XXXX: whilst LoadRoute() can fail - it is not likely. */ -+ panic ("ep3_load_system_route: cannot load p2p route entry\n"); -+ } -+} -+ -+void -+ep3_load_node_route (EP_RAIL *r, unsigned nodeId) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ E3_uint16 flits[MAX_FLITS]; -+ int nflits; -+ -+ nflits = GenerateRoute (&rail->Generic.Position, flits, nodeId, nodeId, DEFAULT_ROUTE_TIMEOUT, DEFAULT_ROUTE_PRIORITY); -+ -+ if (LoadRoute (rail->Device, rail->RouteTable, EP_VP_DATA(nodeId), EP3_CONTEXT_NUM(rail->Generic.Position.pos_nodeid), nflits, flits) != 0) -+ panic ("ep3_load_node_route: cannot load p2p data route entry\n"); -+} -+ -+void -+ep3_unload_node_route (EP_RAIL *r, unsigned nodeId) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ -+ ClearRoute (rail->Device, rail->RouteTable, EP_VP_DATA(nodeId)); -+} -+ -+void -+ep3_lower_filter (EP_RAIL *r, unsigned nodeId) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->Device->IntrLock, flags); -+ elan3mmu_set_context_filter (rail->Device, EP3_CONTEXT_NUM(nodeId), 0, 0, NULL); -+ spin_unlock_irqrestore (&rail->Device->IntrLock, flags); -+} -+ -+void -+ep3_raise_filter (EP_RAIL *r, unsigned nodeId) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->Device->IntrLock, flags); -+ elan3mmu_set_context_filter (rail->Device, EP3_CONTEXT_NUM(nodeId), 1, 0, NULL); -+ spin_unlock_irqrestore (&rail->Device->IntrLock, flags); -+} -+ -+void -+ep3_node_disconnected (EP_RAIL *r, unsigned nodeId) -+{ -+ FreeStalledDmas ((EP3_RAIL *) r, nodeId); -+} -+ -+void -+ep3_fillout_stats(EP_RAIL *r, char *str) -+{ -+ /* no stats here yet */ -+ /* EP3_RAIL *ep3rail = (EP3_RAIL *)r; */ -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan3.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kcomm_elan3.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan3.h 2005-06-01 23:12:54.666428920 -0400 -@@ -0,0 +1,431 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __EP_KCOMM_ELAN3_H -+#define __EP_KCOMM_ELAN3_H -+ -+#ident "@(#)$Id: kcomm_elan3.h,v 1.50.8.3 2004/12/14 10:19:14 mike Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm_elan3.h,v $*/ -+ -+#if !defined(__ELAN3__) -+#include -+#include -+#include -+#include -+#include -+#include -+#endif /* !defined(__ELAN3__) */ -+ -+#include -+ -+/* private address allocation */ -+#define EP3_TEXT_BASE 0xFF000000 /* base address for thread code (defined in makerules.elan3) */ -+#define EP3_COMMANDPORT_ADDR 0xFFF00000 /* mapping address for elan command port */ -+ -+#define EP3_STACK_SIZE 1024 /* default thread code stack size */ -+ -+#define EP3_PACEMAKER_EVENTADDR 0xfeedbeef /* mis-aligned address used by heartbeat pacemaker */ -+ -+/* context number allocation */ -+#define EP3_CONTEXT_NUM(nodeId) ((ELAN3_KCOMM_BASE_CONTEXT_NUM + (nodeId)) | SYS_CONTEXT_BIT) -+#define EP3_CONTEXT_ISDATA(ctx) (((ctx) & MAX_ROOT_CONTEXT_MASK) >= ELAN3_KCOMM_BASE_CONTEXT_NUM && \ -+ ((ctx) & MAX_ROOT_CONTEXT_MASK) <= ELAN3_KCOMM_TOP_CONTEXT_NUM) -+#define EP3_CONTEXT_TO_NODE(ctx) (((ctx) & MAX_ROOT_CONTEXT_MASK) - ELAN3_KCOMM_BASE_CONTEXT_NUM) -+ -+/* DMA issueing rings */ -+#define EP3_RING_CRITICAL 0 -+#define EP3_RING_CRITICAL_LEN 128 -+#define EP3_RING_HIGH_PRI 1 -+#define EP3_RING_HIGH_PRI_LEN 64 -+#define EP3_RING_LOW_PRI 2 -+#define EP3_RING_LOW_PRI_LEN 32 -+#define EP3_NUM_RINGS 3 -+ -+/* Value to "return" from c_close() when envelope handled by the trap handler */ -+#define EP3_PAckStolen 4 -+ -+/* unimplemented instruction trap types for thread code */ -+#define EP3_UNIMP_TRAP_NO_DESCS 0 -+#define EP3_UNIMP_TRAP_PACKET_NACKED 1 -+#define EP3_UNIMP_THREAD_HALTED 2 -+#define EP3_NUM_UNIMP_TRAPS 3 -+ -+/* forward declarations */ -+typedef struct ep3_rail EP3_RAIL; -+ -+/* block copy elan3 inputter queue - with waitvent0 */ -+typedef struct ep3_inputqueue -+{ -+ volatile E3_uint32 q_state; /* queue is full=bit0, queue is locked=bit8 */ -+ volatile E3_Addr q_bptr; /* block aligned ptr to current back item */ -+ E3_uint32 q_size; /* size of queue item; 0x1 <= size <= (0x40 * 5) */ -+ E3_Addr q_top; /* block aligned ptr to last queue item */ -+ E3_Addr q_base; /* block aligned ptr to first queue item */ -+ volatile E3_Addr q_fptr; /* block aligned ptr to current front item */ -+ E3_BlockCopyEvent q_event; /* queue block copy event */ -+ E3_uint32 q_pad[4]; /* pad to 64 bytes */ -+ E3_Addr q_wevent; /* WaitEvent0 struct */ -+ E3_int32 q_wcount; -+} EP3_InputQueue; -+ -+ -+#if !defined(__ELAN3__) -+ -+/* dma retries types and retry times */ -+typedef struct ep3_retry_dma -+{ -+ struct list_head Link; /* chained on free/retry list */ -+ long RetryTime; /* "lbolt" to retry at */ -+ E3_DMA_BE Dma; /* DMA (in main memory) */ -+} EP3_RETRY_DMA; -+ -+typedef struct ep3_dma_ring -+{ -+ sdramaddr_t pEvent; -+ E3_Addr epEvent; -+ -+ sdramaddr_t pDma; -+ E3_Addr epDma; -+ -+ E3_uint32 *pDoneBlk; -+ E3_Addr epDoneBlk; -+ -+ int Entries; /* number of slots in array */ -+ int Position; /* current position in array */ -+ -+ ioaddr_t CommandPort; -+ ioaddr_t CommandPage; -+ DeviceMappingHandle CommandPageHandle; -+} EP3_DMA_RING; -+ -+#define DMA_RING_EVENT(ring,n) ((ring)->pEvent + (n)*sizeof (E3_BlockCopyEvent)) -+#define DMA_RING_EVENT_ELAN(ring,n) ((ring)->epEvent + (n)*sizeof (E3_BlockCopyEvent)) -+ -+#define DMA_RING_DMA(ring,n) ((ring)->pDma + (n)*sizeof (E3_DMA)) -+#define DMA_RING_DMA_ELAN(ring,n) ((ring)->epDma + (n)*sizeof (E3_DMA)) -+ -+#define DMA_RING_DONE_ELAN(ring,n) ((ring)->epDoneBlk + (n)*sizeof (E3_uint32)) -+ -+/* Event interrupt cookie operations and lookup table */ -+typedef struct ep3_cookie_ops -+{ -+ void (*Event) (EP3_RAIL *rail, void *arg); /* called from the interrupt handler when an event is "set" */ -+ void (*DmaRetry) (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int error); /* called from the interrupt handler when a DMA is "nacked" */ -+ void (*DmaCancelled)(EP3_RAIL *rail, void *arg, E3_DMA_BE *dma); /* called from the interrupt handler/flush disconnecting when cancelled. */ -+ void (*DmaVerify) (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma); /* called from multiple places, to check dma is consistent with state. */ -+} EP3_COOKIE_OPS; -+ -+typedef struct ep3_cookie -+{ -+ struct ep3_cookie *Next; /* Cookies are chained in hash table. */ -+ E3_uint32 Cookie; /* Cooke store in ev_Type */ -+ EP3_COOKIE_OPS *Operations; /* Cookie operations */ -+ void *Arg; /* Users arguement. */ -+} EP3_COOKIE; -+ -+#define EP3_COOKIE_HASH_SIZE (256) -+#define EP3_HASH_COOKIE(a) ((((a) >> 3) ^ ((a) >> 7) ^ ((a) >> 11)) & (EP3_COOKIE_HASH_SIZE-1)) -+ -+typedef struct ep3_cookie_table -+{ -+ spinlock_t Lock; -+ EP3_COOKIE *Entries[EP3_COOKIE_HASH_SIZE]; -+} EP3_COOKIE_TABLE; -+ -+#endif /* !defined(__ELAN3__) */ -+ -+#define EP3_EVENT_FREE ((1 << 4) | EV_WCOPY) -+#define EP3_EVENT_ACTIVE ((2 << 4) | EV_WCOPY) -+/* DONE == Cookie */ -+#define EP3_EVENT_FAILED ((3 << 4) | EV_WCOPY) -+#define EP3_EVENT_PRIVATE ((4 << 4) | EV_WCOPY) -+ -+/* The event cookie can get posted (and seen) before the write has */ -+/* hit main memory - in this case the event count is <= 0 and the block */ -+/* will be marked as ACTIVE - but could transition to DONE at any time */ -+/* Also for a word copy event, the value written into the "done" word */ -+/* can be the event interrupt cookie rather than the "source" value */ -+/* this happens since the uCode does not wait for the write to have */ -+/* occured before overwriting TMP_0 with the cookie */ -+#define EP3_EVENT_FIRING(edev, event, cookie, done) \ -+ (((((done) & ~(EV_TYPE_BCOPY | EV_TYPE_MASK_EVIRQ)) == (cookie).Cookie) || (done) == EP3_EVENT_ACTIVE) && \ -+ (int) elan3_sdram_readl (edev, (event) + offsetof (E3_BlockCopyEvent, ev_Count)) <= 0) -+#define EP3_EVENT_FIRED(cookie, done) \ -+ (((done) & ~(EV_TYPE_BCOPY | EV_TYPE_MASK_EVIRQ)) == (cookie).Cookie) -+ -+ -+/* Time limit to wait while event is firing and block write has not occured */ -+#define EP3_EVENT_FIRING_TLIMIT 16384 /* 1023 uS */ -+ -+#define EP3_INIT_COPY_EVENT(event, cookie, dest, intr) \ -+{ \ -+ (event).ev_Count = 0; \ -+ (event).ev_Type = (intr) ? EV_TYPE_BCOPY | EV_TYPE_EVIRQ | (cookie).Cookie : EV_TYPE_BCOPY; \ -+ (event).ev_Source = (cookie).Cookie | EV_WCOPY; \ -+ (event).ev_Dest = (dest) | EV_TYPE_BCOPY_WORD; \ -+} -+ -+#if !defined(__ELAN3__) -+ -+/* Generic input queues which can be polled */ -+typedef struct ep3_inputq -+{ -+ EP3_COOKIE q_cookie; -+ unsigned int q_slotSize; -+ unsigned int q_slotCount; -+ -+ void *q_slots; -+ EP_ADDR q_slotsAddr; -+ -+ EP_INPUTQ_CALLBACK *q_callback; -+ void *q_arg; -+ -+ sdramaddr_t q_desc; -+ E3_Addr q_descAddr; -+ -+ E3_Addr q_base; -+ E3_Addr q_top; -+ E3_Addr q_fptr; -+ -+ E3_uint32 q_waitCount; -+} EP3_INPUTQ; -+ -+typedef struct ep3_outputq -+{ -+ EP3_COOKIE q_cookie; -+ -+ unsigned int q_slotCount; /* # slots allocated */ -+ unsigned int q_slotSize; /* size of each slot (rounded up) */ -+ -+ sdramaddr_t q_elan; -+ E3_Addr q_elanAddr; -+ -+ void *q_main; -+ E3_Addr q_mainAddr; -+} EP3_OUTPUTQ; -+ -+#endif /* !defined(__ELAN3__) */ -+ -+/* per-rail elan memory portion of device */ -+typedef struct ep3_rail_elan -+{ -+ E3_uint16 ProbeSource0[TR_TRACEROUTE_ENTRIES]; /* 32 byte aligned */ -+ E3_uint16 ProbeSource1[TR_TRACEROUTE_ENTRIES]; -+ -+ E3_BlockCopyEvent ProbeDone; /* 16 byte aligned */ -+ E3_Event ProbeStart; /* 8 byte aligned */ -+ -+ E3_uint32 ProbeType; /* 4 byte aligned */ -+ E3_uint32 ProbeLevel; -+ -+ E3_uint32 NodeId; -+} EP3_RAIL_ELAN; -+ -+/* values for ProbeType */ -+#define PROBE_SINGLE 0 -+#define PROBE_MULTIPLE 1 -+/* number of attempts for each type */ -+#define PROBE_SINGLE_ATTEMPTS 10 -+#define PROBE_SINGLE_TIMEOUTS 5 -+#define PROBE_MULTIPLE_ATTEMPTS 20 -+#define PROBE_MULTIPLE_TIMEOUTS 10 -+ -+/* per-rail elan memory portsion of device */ -+typedef struct ep3_rail_main -+{ -+ E3_uint16 ProbeDest0[TR_TRACEROUTE_ENTRIES]; /* 32 byte aligned */ -+ E3_uint16 ProbeDest1[TR_TRACEROUTE_ENTRIES]; -+ -+ E3_uint32 ProbeDone; /* 4 byte aligned */ -+ E3_uint32 ProbeResult; -+ E3_uint32 ProbeLevel; -+} EP3_RAIL_MAIN; -+ -+#if !defined(__ELAN3__) -+ -+struct ep3_rail -+{ -+ EP_RAIL Generic; /* Generic rail */ -+ -+ ELAN3_DEV *Device; /* Elan device we're using */ -+ ELAN3_CTXT *Ctxt; /* Elan context struct */ -+ ioaddr_t CommandPort; /* commandport from context */ -+ E3_Addr CommandPortAddr; /* and address mapped into elan */ -+ -+ ELAN3_ROUTE_TABLE *RouteTable; /* routetable from context */ -+ ELAN3MMU *Elan3mmu; /* elanmmu from context */ -+ -+ EP3_COOKIE_TABLE CookieTable; /* Event cookie table */ -+ -+ EP_CODE ThreadCode; /* copy of thread code */ -+ unsigned int CommandPortEventTrap; /* flag to indicate command port eventint queue overflow trap */ -+ -+ sdramaddr_t RailElan; /* Elan visible main/sdram portions of */ -+ E3_Addr RailElanAddr; /* device structure */ -+ EP3_RAIL_MAIN *RailMain; -+ E3_Addr RailMainAddr; -+ -+ /* small system message queues */ -+ sdramaddr_t QueueDescs; /* Input Queue descriptors */ -+ -+ /* Network position prober */ -+ E3_Addr ProbeStack; /* Network position thread command structure */ -+ EP3_COOKIE ProbeCookie; /* event cookie for Done event */ -+ kcondvar_t ProbeWait; /* place to wait on probe thread */ -+ spinlock_t ProbeLock; /* and lock */ -+ volatile int ProbeDone; /* and flag to indicate it's done */ -+ -+ E3_uint16 ProbeDest0[TR_TRACEROUTE_ENTRIES]; /* last result of CheckNetworkPosition */ -+ E3_uint16 ProbeDest1[TR_TRACEROUTE_ENTRIES]; -+ E3_uint32 ProbeResult; -+ -+ long ProbeLevelTick[ELAN_MAX_LEVELS]; -+ long SwitchBroadcastLevelTick; -+ -+ /* rings for issueing dmas */ -+ EP3_DMA_RING DmaRings[EP3_NUM_RINGS]; -+ -+ /* retry lists for dmas */ -+ struct list_head DmaRetries[EP_NUM_RETRIES]; /* Dma retry lists */ -+ struct list_head DmaRetryFreeList; /* and free list */ -+ u_int DmaRetryCount; /* and total retry count */ -+ u_int DmaRetryReserved; /* and number reserved */ -+ u_int DmaRetryThreadShouldStall; /* count of reasons to stall retries */ -+ u_int DmaRetryThreadStarted:1; /* dma retry thread running */ -+ u_int DmaRetryThreadShouldStop:1; /* but should stop */ -+ u_int DmaRetryThreadStopped:1; /* and now it's stopped */ -+ u_int DmaRetryInitialised:1; /* have initialise dma retries */ -+ -+ spinlock_t DmaRetryLock; /* spinlock protecting lists */ -+ kcondvar_t DmaRetryWait; /* place retry thread sleeps */ -+ long DmaRetryTime; /* and when it will next wakeup */ -+ unsigned int DmaRetrySleeping; /* and it's sleeping there */ -+ -+ /* Network Identify Cookies */ -+ E3_uint32 *MainCookies; /* One cookie allocator per-node for main*/ -+ E3_Addr ElanCookies; /* and one for elan */ -+ spinlock_t CookieLock; /* spinlock to protect main cookies */ -+ -+ /* Halt operation flags for flushing. */ -+ kmutex_t HaltOpMutex; /* serialize access to halt operations */ -+ unsigned int HaltOpCompleted; /* flag to indicate halt operation completed */ -+ kcondvar_t HaltOpSleep; /* place to wait for it to complete */ -+ -+ /* Network error state */ -+ kcondvar_t NetworkErrorSleep; /* place to sleep for network error halt operation */ -+ u_int NetworkErrorFlushed; /* and flag to indicate flushed */ -+ -+ -+ EP3_RAIL_STATS Stats; /* statistics */ -+}; -+ -+/* support.c */ -+ -+extern ELAN3_OPS ep3_elan3_ops; -+ -+extern E3_uint32 LocalCookie (EP3_RAIL *rail, unsigned int remoteNode); -+extern E3_uint32 RemoteCookie (EP3_RAIL *rail, unsigned int remoteNode); -+ -+extern void InitialiseCookieTable (EP3_COOKIE_TABLE *table); -+extern void DestroyCookieTable (EP3_COOKIE_TABLE *table); -+extern void RegisterCookie (EP3_COOKIE_TABLE *table, EP3_COOKIE *cookie, -+ E3_Addr event, EP3_COOKIE_OPS *ops, void *arg); -+extern void DeregisterCookie (EP3_COOKIE_TABLE *table, EP3_COOKIE *cookie); -+extern EP3_COOKIE *LookupCookie (EP3_COOKIE_TABLE *table, uint32_t cookie); -+extern EP3_COOKIE *LookupEventCookie (EP3_RAIL *rail, EP3_COOKIE_TABLE *table, E3_Addr); -+ -+extern int DmaRingsCreate (EP3_RAIL *rail); -+extern void DmaRingsRelease (EP3_RAIL *rail); -+extern int IssueDma (EP3_RAIL *rail, E3_DMA_BE *dma, int type, int retryThread); -+ -+extern int IssueWaitevent (EP3_RAIL *rail, E3_Addr value); -+extern void IssueSetevent (EP3_RAIL *rail, E3_Addr value); -+extern void IssueRunThread (EP3_RAIL *rail, E3_Addr value); -+extern long DmaRetryTime (int type); -+extern int InitialiseDmaRetries (EP3_RAIL *rail); -+extern void DestroyDmaRetries (EP3_RAIL *rail); -+extern int ReserveDmaRetries (EP3_RAIL *rail, int count, EP_ATTRIBUTE attr); -+extern void ReleaseDmaRetries (EP3_RAIL *rail, int count); -+extern void StallDmaRetryThread (EP3_RAIL *rail); -+extern void ResumeDmaRetryThread (EP3_RAIL *rail); -+extern void QueueDmaForRetry (EP3_RAIL *rail, E3_DMA_BE *dma, int interval); -+extern void QueueDmaOnStalledList (EP3_RAIL *rail, E3_DMA_BE *dma); -+extern void FreeStalledDmas (EP3_RAIL *rail, unsigned int nodeId); -+ -+extern void SetQueueLocked(EP3_RAIL *rail, sdramaddr_t qaddr); -+ -+/* threadcode_elan3.c */ -+extern E3_Addr ep3_init_thread (ELAN3_DEV *dev, E3_Addr fn, E3_Addr addr, sdramaddr_t stack, -+ int stackSize, int nargs, ...); -+ -+/* probenetwork.c */ -+extern int ep3_init_probenetwork (EP3_RAIL *rail); -+extern void ep3_destroy_probenetwork (EP3_RAIL *rail); -+extern void ep3_probe_position_found (EP3_RAIL *rail, ELAN_POSITION *pos); -+extern int ep3_probe_route (EP_RAIL *r, int level, int sw, int nodeid, int *linkup, int *linkdown, int attempts, EP_SWITCH *lsw); -+extern int ep3_check_position (EP_RAIL *rail); -+ -+/* neterr_elan3.c */ -+extern void ep3_neterr_fixup (EP_RAIL *r, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+ -+/* kcomm_elan3.c */ -+extern EP_RAIL *ep3_create_rail (EP_SYS *sys, ELAN3_DEV *dev); -+extern void ep3_destroy_rail (EP_RAIL *rail); -+ -+extern int ep3_start_rail (EP_RAIL *rail); -+extern void ep3_stall_rail (EP_RAIL *rail); -+extern void ep3_stop_rail (EP_RAIL *rail); -+ -+extern void ep3_position_found (EP_RAIL *rail, ELAN_POSITION *pos); -+ -+extern sdramaddr_t ep3_sdram_alloc (EP_RAIL *rail, EP_ADDR addr, unsigned int size); -+extern void ep3_sdram_free (EP_RAIL *rail, sdramaddr_t addr, unsigned int size); -+extern void ep3_sdram_writeb (EP_RAIL *rail, sdramaddr_t addr, unsigned char val); -+ -+extern void ep3_flush_tlb (EP_RAIL *r); -+extern void ep3_load_system_route (EP_RAIL *r, unsigned int vp, unsigned int lowNode, unsigned int highNode); -+extern void ep3_load_node_route (EP_RAIL *r, unsigned int nodeId); -+extern void ep3_unload_node_route (EP_RAIL *r, unsigned int nodeId); -+extern void ep3_lower_filter (EP_RAIL *r, unsigned int nodeId); -+extern void ep3_raise_filter (EP_RAIL *rail, unsigned int nodeId); -+extern void ep3_node_disconnected (EP_RAIL *r, unsigned int nodeId); -+ -+extern void ep3_fillout_stats(EP_RAIL *rail, char *str); -+ -+/* kmap_elan3.c */ -+extern void ep3_kaddr_map (EP_RAIL *r, EP_ADDR eaddr, virtaddr_t kaddr, unsigned int len, unsigned int perm, int ep_attr); -+extern void ep3_sdram_map (EP_RAIL *r, EP_ADDR eaddr, sdramaddr_t saddr, unsigned int len, unsigned int perm, int ep_attr); -+extern void ep3_ioaddr_map (EP_RAIL *r, EP_ADDR eaddr, ioaddr_t ioaddr, unsigned int len, unsigned int perm); -+extern void ep3_unmap (EP_RAIL *r, EP_ADDR eaddr, unsigned int len); -+extern void *ep3_dvma_reserve (EP_RAIL *r, EP_ADDR eaddr, unsigned int npages); -+extern void ep3_dvma_release (EP_RAIL *r, EP_ADDR eaddr, unsigned int npages, void *private); -+extern void ep3_dvma_set_pte (EP_RAIL *r, void *private, unsigned int index, physaddr_t paddr, unsigned int perm); -+extern physaddr_t ep3_dvma_read_pte (EP_RAIL *r, void *private, unsigned int index); -+extern void ep3_dvma_unload (EP_RAIL *r, void *private, unsigned int index, unsigned int npages); -+ -+/* kmsg_elan3.c */ -+extern EP_INPUTQ *ep3_alloc_inputq (EP_RAIL *r, unsigned int qnum, unsigned int slotSize, unsigned int slotCount, -+ EP_INPUTQ_CALLBACK *callback, void *arg); -+extern void ep3_free_inputq (EP_RAIL *r, EP_INPUTQ *q); -+extern void ep3_enable_inputq (EP_RAIL *r, EP_INPUTQ *q); -+extern void ep3_disable_inputq (EP_RAIL *r, EP_INPUTQ *q); -+extern int ep3_poll_inputq (EP_RAIL *r, EP_INPUTQ *q, int maxCount, EP_INPUTQ_HANDLER *handler, void *arg); -+extern EP_OUTPUTQ *ep3_alloc_outputq (EP_RAIL *r, unsigned int slotSize, unsigned int slotCount); -+extern void ep3_free_outputq (EP_RAIL *r, EP_OUTPUTQ *q); -+extern void *ep3_outputq_msg (EP_RAIL *r, EP_OUTPUTQ *q, unsigned int slotNum); -+extern int ep3_outputq_state (EP_RAIL *r, EP_OUTPUTQ *q, unsigned int slotNum); -+extern int ep3_outputq_send (EP_RAIL *r, EP_OUTPUTQ *q, unsigned int slotNum, unsigned int size, -+ unsigned int nodeId, unsigned int qnum, unsigned int retries); -+ -+/* support_elan3.c */ -+extern void ep3_flush_filters (EP_RAIL *r); -+extern void ep3_flush_queues (EP_RAIL *r); -+ -+#endif /* !defined(__ELAN3__) */ -+ -+#endif /* __EP_KCOMM_ELAN3_H */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kcomm_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan4.c 2005-06-01 23:12:54.667428768 -0400 -@@ -0,0 +1,526 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kcomm_elan4.c,v 1.16.2.3 2004/11/30 12:02:17 mike Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm_elan4.c,v $*/ -+ -+#include -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "conf_linux.h" -+ -+extern EP_CODE threadcode_elan4; -+ -+unsigned int -+ep4_create_rails (EP_SYS *sys, unsigned int disabled) -+{ -+ unsigned int rmask = 0; -+ ELAN4_DEV *dev; -+ EP_RAIL *rail; -+ int i; -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ { -+ if ((dev = elan4_reference_device (i, ELAN4_STATE_STARTED)) != NULL) -+ { -+ if ((rail = ep4_create_rail (sys, dev)) == NULL) -+ elan4_dereference_device (dev); -+ else -+ { -+ if (disabled & (1 << rail->Number)) -+ printk ("%s: auto-start of device disabled by configuration\n", rail->Name); -+ else -+ ep_start_rail (rail); -+ -+ ep_procfs_rail_init(rail); -+ -+ rmask |= (1 << rail->Number); -+ } -+ } -+ } -+ -+ if (rmask) -+ qsnet_debug_alloc(); -+ -+ return rmask; -+} -+ -+EP_RAIL * -+ep4_create_rail (EP_SYS *sys, ELAN4_DEV *dev) -+{ -+ EP4_RAIL *rail; -+ int res; -+ -+ KMEM_ZALLOC (rail, EP4_RAIL *, sizeof (EP4_RAIL), 1); -+ -+ if (rail == NULL) -+ return (EP_RAIL *) NULL; -+ -+ if ((res = ep_init_rail (sys, &rail->r_generic)) != 0) -+ { -+ KMEM_FREE (rail, sizeof (EP4_RAIL)); -+ return (EP_RAIL *) NULL; -+ } -+ -+ rail->r_ctxt.ctxt_dev = dev; -+ -+ /* install our rail operations */ -+ rail->r_generic.Operations.DestroyRail = ep4_destroy_rail; -+ rail->r_generic.Operations.StartRail = ep4_start_rail; -+ rail->r_generic.Operations.StallRail = ep4_stall_rail; -+ rail->r_generic.Operations.StopRail = ep4_stop_rail; -+ -+ rail->r_generic.Operations.SdramAlloc = ep4_sdram_alloc; -+ rail->r_generic.Operations.SdramFree = ep4_sdram_free; -+ rail->r_generic.Operations.SdramWriteb = ep4_sdram_writeb; -+ -+ rail->r_generic.Operations.KaddrMap = ep4_kaddr_map; -+ rail->r_generic.Operations.SdramMap = ep4_sdram_map; -+ rail->r_generic.Operations.Unmap = ep4_unmap; -+ -+ rail->r_generic.Operations.DvmaReserve = ep4_dvma_reserve; -+ rail->r_generic.Operations.DvmaRelease = ep4_dvma_release; -+ rail->r_generic.Operations.DvmaSetPte = ep4_dvma_set_pte; -+ rail->r_generic.Operations.DvmaReadPte = ep4_dvma_read_pte; -+ rail->r_generic.Operations.DvmaUnload = ep4_dvma_unload; -+ rail->r_generic.Operations.FlushTlb = ep4_flush_tlb; -+ -+ rail->r_generic.Operations.ProbeRoute = ep4_probe_route; -+ -+ rail->r_generic.Operations.PositionFound = ep4_position_found; -+ rail->r_generic.Operations.CheckPosition = ep4_check_position; -+ rail->r_generic.Operations.NeterrFixup = ep4_neterr_fixup; -+ -+ rail->r_generic.Operations.LoadSystemRoute = ep4_load_system_route; -+ -+ rail->r_generic.Operations.LoadNodeRoute = ep4_load_node_route; -+ rail->r_generic.Operations.UnloadNodeRoute = ep4_unload_node_route; -+ rail->r_generic.Operations.LowerFilter = ep4_lower_filter; -+ rail->r_generic.Operations.RaiseFilter = ep4_raise_filter; -+ rail->r_generic.Operations.NodeDisconnected = ep4_node_disconnected; -+ -+ rail->r_generic.Operations.FlushFilters = ep4_flush_filters; -+ rail->r_generic.Operations.FlushQueues = ep4_flush_queues; -+ -+ rail->r_generic.Operations.AllocInputQ = ep4_alloc_inputq; -+ rail->r_generic.Operations.FreeInputQ = ep4_free_inputq; -+ rail->r_generic.Operations.EnableInputQ = ep4_enable_inputq; -+ rail->r_generic.Operations.DisableInputQ = ep4_disable_inputq; -+ rail->r_generic.Operations.PollInputQ = ep4_poll_inputq; -+ -+ rail->r_generic.Operations.AllocOutputQ = ep4_alloc_outputq; -+ rail->r_generic.Operations.FreeOutputQ = ep4_free_outputq; -+ rail->r_generic.Operations.OutputQMsg = ep4_outputq_msg; -+ rail->r_generic.Operations.OutputQState = ep4_outputq_state; -+ rail->r_generic.Operations.OutputQSend = ep4_outputq_send; -+ -+ rail->r_generic.Operations.FillOutStats = ep4_fillout_stats; -+ rail->r_generic.Operations.Debug = ep4_debug_rail; -+ -+ rail->r_generic.Devinfo = dev->dev_devinfo; -+ -+ printk ("%s: connected via elan4 rev%c device %d\n", rail->r_generic.Name, -+ 'a' + dev->dev_devinfo.dev_revision_id, dev->dev_instance); -+ -+ return (EP_RAIL *) rail; -+} -+ -+void -+ep4_destroy_rail (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ elan4_dereference_device (rail->r_ctxt.ctxt_dev); -+ -+ KMEM_FREE (rail, sizeof (EP4_RAIL)); -+} -+ -+static int -+ep4_attach_rail (EP4_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned ctx; -+ -+ if (elan4_insertctxt (dev, &rail->r_ctxt, &ep4_trap_ops) != 0) -+ return -ENOMEM; -+ -+ if ((rail->r_routetable = elan4_alloc_routetable (dev, 4)) == NULL) /* 512 << 4 == 8192 entries */ -+ { -+ elan4_removectxt (dev, &rail->r_ctxt); -+ return -ENOMEM; -+ } -+ elan4_set_routetable (&rail->r_ctxt, rail->r_routetable); -+ -+ /* Attach to the kernel comms nextwork context */ -+ if (elan4_attach_filter (&rail->r_ctxt, ELAN4_KCOMM_CONTEXT_NUM) < 0) -+ { -+ elan4_free_routetable (dev, rail->r_routetable); -+ elan4_removectxt (dev, &rail->r_ctxt); -+ -+ return -EBUSY; -+ } -+ -+ for (ctx = ELAN4_KCOMM_BASE_CONTEXT_NUM; ctx <= ELAN4_KCOMM_TOP_CONTEXT_NUM; ctx++) -+ elan4_attach_filter (&rail->r_ctxt, ctx); -+ -+ return 0; -+} -+ -+static void -+ep4_detach_rail (EP4_RAIL *rail) -+{ -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned ctx; -+ -+ elan4_detach_filter (&rail->r_ctxt, ELAN4_KCOMM_CONTEXT_NUM); -+ -+ for (ctx = ELAN4_KCOMM_BASE_CONTEXT_NUM; ctx <= ELAN4_KCOMM_TOP_CONTEXT_NUM; ctx++) -+ elan4_detach_filter (&rail->r_ctxt, ctx); -+ -+ if (rail->r_routetable) -+ { -+ elan4_set_routetable (&rail->r_ctxt, NULL); -+ elan4_free_routetable (dev, rail->r_routetable); -+ } -+ -+ elan4_removectxt (dev, &rail->r_ctxt); -+} -+ -+int -+ep4_start_rail (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ E4_InputQueue qdesc; -+ int i, res; -+ -+ if ((res = ep4_attach_rail (rail)) < 0) -+ return res; -+ -+ /* Initialise main interrupt cookie table */ -+ spin_lock_init (&rail->r_intcookie_lock); -+ for (i = 0; i < EP4_INTCOOKIE_HASH_SIZE; i++) -+ INIT_LIST_HEAD (&rail->r_intcookie_hash[i]); -+ -+ kmutex_init (&rail->r_haltop_mutex); -+ kcondvar_init (&rail->r_haltop_sleep); -+ spin_lock_init (&rail->r_haltop_lock); -+ -+ spin_lock_init (&rail->r_cookie_lock); -+ -+ INIT_LIST_HEAD (&rail->r_ecq_list[EP4_ECQ_EVENT]); -+ INIT_LIST_HEAD (&rail->r_ecq_list[EP4_ECQ_ATOMIC]); -+ INIT_LIST_HEAD (&rail->r_ecq_list[EP4_ECQ_SINGLE]); -+ INIT_LIST_HEAD (&rail->r_ecq_list[EP4_ECQ_MAIN]); -+ spin_lock_init (&rail->r_ecq_lock); -+ -+ ep_kthread_init (&rail->r_retry_thread); -+ INIT_LIST_HEAD (&rail->r_retry_ops); -+ -+ INIT_LIST_HEAD (&rail->r_neterr_ops); -+ -+ kmutex_init (&rail->r_flush_mutex); -+ kcondvar_init (&rail->r_flush_sleep); -+ -+ /* Allocate the elan visible sdram/main memory */ -+ if ((rail->r_elan = ep_alloc_elan (&rail->r_generic, sizeof (EP4_RAIL_ELAN), 0, &rail->r_elan_addr)) == 0 || -+ (rail->r_main = ep_alloc_main (&rail->r_generic, sizeof (EP4_RAIL_MAIN), 0, &rail->r_main_addr)) == 0) -+ { -+ goto failed; -+ } -+ -+ for (i = 0; i < EP_NUM_SYSTEMQ; i++) -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_qevents[i].ev_CountAndType), 0); -+ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_flush_event.ev_CountAndType), E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ -+ /* Allocate the system input queues at their fixed elan address */ -+ /* avoid sdram address aliasing by allocating the min sdram pagesize */ -+ if (! (rail->r_queuedescs= ep_alloc_memory_elan (&rail->r_generic, EP_SYSTEM_QUEUE_BASE, SDRAM_PAGE_SIZE, EP_PERM_ALL, 0))) -+ goto failed; -+ -+ /* Initialise the input queue descriptor as "full" with no event */ -+ qdesc.q_bptr = 0; -+ qdesc.q_fptr = 8; -+ qdesc.q_control = E4_InputQueueControl(qdesc.q_bptr, qdesc.q_fptr, 8); -+ qdesc.q_event = 0; -+ -+ for (i = 0; i < EP_NUM_SYSTEMQ; i++) -+ elan4_sdram_copyq_to_sdram (dev, &qdesc, EP_SYSTEMQ_DESC (rail->r_queuedescs, i), sizeof (E4_InputQueue)); -+ -+ /* Allocate the resource map for command queue mappings */ -+ if ((rail->r_ecq_rmap = ep_rmallocmap (EP4_ECQ_RMAPSIZE, "r_ecq_rmap", 1)) == NULL) -+ goto failed; -+ -+ ep_rmfree (rail->r_ecq_rmap, EP4_ECQ_TOP - EP4_ECQ_BASE, EP4_ECQ_BASE); -+ -+ /* register an interrupt cookie & allocate command queues for command queue flushing */ -+ rail->r_flush_mcq = ep4_get_ecq (rail, EP4_ECQ_MAIN, 4); -+ rail->r_flush_ecq = ep4_get_ecq (rail, EP4_ECQ_EVENT, 1); -+ -+ if (rail->r_flush_mcq == NULL || rail->r_flush_ecq == NULL) -+ goto failed; -+ -+ ep4_register_intcookie (rail, &rail->r_flush_intcookie, rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_flush_event), ep4_flush_interrupt, rail); -+ -+ /* startup the retry thread */ -+ if (kernel_thread_create (ep4_retry_thread, (void *) rail) == 0) -+ goto failed; -+ ep_kthread_started (&rail->r_retry_thread); -+ -+ ep4_initialise_dma_retries (rail); -+ -+ if ((rail->r_event_ecq = ep4_alloc_ecq (rail, CQ_Size1K)) == NULL) -+ goto failed; -+ -+ rail->r_threadcode = threadcode_elan4; -+ if (ep_loadcode (&rail->r_generic, &rail->r_threadcode)) -+ goto failed; -+ -+ elan4_flush_icache (&rail->r_ctxt); -+ -+ if (ep4_probe_init (rail)) -+ goto failed; -+ -+ /* can now drop the context filter for the system context */ -+ elan4_set_filter (&rail->r_ctxt, ELAN4_KCOMM_CONTEXT_NUM, E4_FILTER_HIGH_PRI); -+ -+ return 0; -+ -+ failed: -+ printk ("ep4_start_rail: failed for rail '%s'\n", rail->r_generic.Name); -+ ep4_stop_rail (&rail->r_generic); -+ -+ return -ENOMEM; -+} -+ -+void -+ep4_stall_rail (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ unsigned ctx; -+ -+ /* Raise all the context filters */ -+ elan4_set_filter (&rail->r_ctxt, ELAN4_KCOMM_CONTEXT_NUM, E4_FILTER_DISCARD_ALL); -+ -+ for (ctx = ELAN4_KCOMM_BASE_CONTEXT_NUM; ctx <= ELAN4_KCOMM_TOP_CONTEXT_NUM; ctx++) -+ elan4_set_filter (&rail->r_ctxt, ctx, E4_FILTER_DISCARD_ALL); -+} -+ -+void -+ep4_stop_rail (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ if (rail->r_generic.State == EP_RAIL_STATE_RUNNING) /* undo ep4_position_found() */ -+ { -+ ELAN_POSITION *pos = &rail->r_generic.Position; -+ EP_ADDR addr = elan4_sdram_readq (rail->r_ctxt.ctxt_dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_cookies)); -+ -+ ep_free_elan (&rail->r_generic, addr, pos->pos_nodes * sizeof (E4_uint64)); -+ -+ KMEM_FREE (rail->r_cookies, pos->pos_nodes * sizeof (E4_uint64)); -+ } -+ -+ ep4_probe_destroy (rail); -+ -+ ep_unloadcode (&rail->r_generic, &rail->r_threadcode); -+ -+ if (rail->r_event_ecq) -+ ep4_free_ecq (rail, rail->r_event_ecq); -+ rail->r_event_ecq = NULL; -+ -+ ep4_finalise_dma_retries (rail); -+ -+ ep_kthread_stop (&rail->r_retry_thread); -+ ep_kthread_destroy (&rail->r_retry_thread); -+ -+ if (rail->r_flush_intcookie.int_arg) -+ ep4_deregister_intcookie (rail, &rail->r_flush_intcookie); -+ rail->r_flush_intcookie.int_arg = NULL; -+ -+ if (rail->r_flush_mcq) -+ ep4_put_ecq (rail, rail->r_flush_mcq, 4); -+ rail->r_flush_mcq = NULL; -+ -+ if (rail->r_flush_ecq) -+ ep4_put_ecq (rail, rail->r_flush_ecq, 1); -+ rail->r_flush_ecq = NULL; -+ -+ if (rail->r_ecq_rmap) -+ ep_rmfreemap (rail->r_ecq_rmap); -+ -+ if (rail->r_queuedescs) -+ ep_free_memory_elan (&rail->r_generic, EP_SYSTEM_QUEUE_BASE); -+ rail->r_queuedescs = 0; -+ -+ if (rail->r_elan) -+ ep_free_elan (&rail->r_generic, rail->r_elan_addr, sizeof (EP4_RAIL_ELAN)); -+ rail->r_elan = 0; -+ -+ if (rail->r_main) -+ ep_free_main (&rail->r_generic, rail->r_main_addr, sizeof (EP4_RAIL_MAIN)); -+ rail->r_main = NULL; -+ -+ kcondvar_destroy (&rail->r_flush_sleep); -+ kmutex_destroy (&rail->r_flush_mutex); -+ -+ spin_lock_destroy (&rail->r_ecq_lock); -+ spin_lock_destroy (&rail->r_cookie_lock); -+ -+ spin_lock_destroy (&rail->r_haltop_lock); -+ kcondvar_destroy(&rail->r_haltop_sleep); -+ kmutex_destroy (&rail->r_haltop_mutex); -+ spin_lock_destroy (&rail->r_intcookie_lock); -+ -+ ep4_detach_rail (rail); -+} -+ -+void -+ep4_position_found (EP_RAIL *r, ELAN_POSITION *pos) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ sdramaddr_t cookies; -+ EP_ADDR addr; -+ int i; -+ -+ KMEM_ZALLOC (rail->r_cookies, E4_uint64 *, pos->pos_nodes * sizeof (E4_uint64), 1); -+ -+ if (! (cookies = ep_alloc_elan (&rail->r_generic, pos->pos_nodes * sizeof (E4_uint64), 0, &addr))) -+ panic ("ep4_position_found: cannot allocate elan cookies array\n"); -+ -+ for (i = 0; i < pos->pos_nodes; i++) -+ elan4_sdram_writeq (rail->r_ctxt.ctxt_dev, cookies + (i * sizeof (E4_uint64)), 0); -+ -+ for (i = 0; i < pos->pos_nodes; i++) -+ rail->r_cookies[i] = 0; -+ -+ elan4_sdram_writeq (rail->r_ctxt.ctxt_dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_nodeid), pos->pos_nodeid); -+ elan4_sdram_writeq (rail->r_ctxt.ctxt_dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_cookies), addr); -+ -+ ep4_probe_position_found (rail, pos); -+} -+ -+sdramaddr_t -+ep4_sdram_alloc (EP_RAIL *r, EP_ADDR addr, unsigned size) -+{ -+ ELAN4_DEV *dev = ((EP4_RAIL *) r)->r_ctxt.ctxt_dev; -+ -+ if (size >= SDRAM_PAGE_SIZE) -+ return elan4_sdram_alloc (dev, size); -+ else -+ { -+ sdramaddr_t block = elan4_sdram_alloc (dev, SDRAM_PAGE_SIZE); -+ sdramaddr_t sdram = block + (addr & (SDRAM_PAGE_SIZE-1)); -+ -+ /* free of the portion before sdram */ -+ if (sdram > block) -+ elan4_sdram_free (dev, block, sdram - block); -+ -+ /* free of the portion after sdram */ -+ if ((block + SDRAM_PAGE_SIZE) > (sdram + size)) -+ elan4_sdram_free (dev, sdram + size, block + SDRAM_PAGE_SIZE - (sdram + size)); -+ -+ return sdram; -+ } -+} -+ -+void -+ep4_sdram_free (EP_RAIL *r, sdramaddr_t addr, unsigned size) -+{ -+ elan4_sdram_free (((EP4_RAIL *) r)->r_ctxt.ctxt_dev, addr, size); -+} -+ -+void -+ep4_sdram_writeb (EP_RAIL *r, sdramaddr_t addr, unsigned char val) -+{ -+ elan4_sdram_writeb (((EP4_RAIL *) r)->r_ctxt.ctxt_dev, addr, val); -+} -+ -+void -+ep4_flush_tlb (EP_RAIL *r) -+{ -+ elan4mmu_flush_tlb (((EP4_RAIL *) r)->r_ctxt.ctxt_dev); -+} -+ -+void -+ep4_load_system_route (EP_RAIL *r, unsigned vp, unsigned lowNode, unsigned highNode) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ E4_VirtualProcessEntry route; -+ -+ if (elan4_generate_route (&rail->r_generic.Position, &route, ELAN4_KCOMM_CONTEXT_NUM, -+ lowNode, highNode, FIRST_SYSTEM_PACKET | FIRST_HIGH_PRI | FIRST_TIMEOUT(3)) < 0) -+ { -+ panic ("ep4_load_system_route: generate route failed\n"); -+ /* NOTREACHED */ -+ } -+ -+ elan4_write_route (dev, rail->r_routetable, vp, &route); -+} -+ -+void -+ep4_load_node_route (EP_RAIL *r, unsigned nodeId) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ E4_VirtualProcessEntry route; -+ -+ if (elan4_generate_route (&rail->r_generic.Position, &route, EP4_CONTEXT_NUM(rail->r_generic.Position.pos_nodeid), -+ nodeId, nodeId, FIRST_SYSTEM_PACKET | FIRST_TIMEOUT(3)) < 0) -+ { -+ panic ("ep4_load_node_route: generate route failed\n"); -+ /* NOTREACHED */ -+ } -+ -+ elan4_write_route (dev, rail->r_routetable, EP_VP_DATA(nodeId), &route); -+} -+ -+void -+ep4_unload_node_route (EP_RAIL *r, unsigned nodeId) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ -+ elan4_invalidate_route (dev, rail->r_routetable, EP_VP_DATA(nodeId)); -+} -+ -+void -+ep4_lower_filter (EP_RAIL *r, unsigned nodeId) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ elan4_set_filter (&rail->r_ctxt, EP4_CONTEXT_NUM(nodeId), E4_FILTER_HIGH_PRI); -+} -+ -+void -+ep4_raise_filter (EP_RAIL *r, unsigned nodeId) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ elan4_set_filter (&rail->r_ctxt, EP4_CONTEXT_NUM(nodeId), E4_FILTER_DISCARD_ALL); -+} -+ -+void -+ep4_node_disconnected (EP_RAIL *r, unsigned nodeId) -+{ -+ ep4_free_stalled_dmas ((EP4_RAIL *) r, nodeId); -+} -+ -+void -+ep4_fillout_stats(EP_RAIL *r, char *str) -+{ -+ /* no stats here yet */ -+ /* EP4_RAIL *ep4rail = (EP4_RAIL *)r; */ -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan4.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kcomm_elan4.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kcomm_elan4.h 2005-06-01 23:12:54.668428616 -0400 -@@ -0,0 +1,443 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __EP_KCOMM_ELAN4_H -+#define __EP_KCOMM_ELAN4_H -+ -+#ident "@(#)$Id: kcomm_elan4.h,v 1.16.2.2 2004/12/14 10:19:14 mike Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm_elan4.h,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#if !defined(__elan4__) -+#include -+#endif /* ! defined(__elan4__) */ -+ -+/* private address allocation */ -+#define EP4_TEXT_BASE 0xF8000000 /* base address for thread code (defined in makerules.elan4) */ -+#define EP4_ECQ_BASE 0xFF000000 /* address space for mapping command queues */ -+#define EP4_ECQ_TOP 0xFF800000 -+ -+#define EP4_ECQ_RMAPSIZE 128 -+#define EP4_STACK_SIZE 1024 /* default thread code stack size */ -+#define EP4_MAX_LEVELS 8 /* same as ELAN_MAX_LEVELS */ -+ -+/* context number allocation */ -+#define EP4_CONTEXT_NUM(nodeId) (ELAN4_KCOMM_BASE_CONTEXT_NUM + (nodeId)) -+#define EP4_CONTEXT_ISDATA(ctx) ((ctx) >= ELAN4_KCOMM_BASE_CONTEXT_NUM && \ -+ (ctx) <= ELAN4_KCOMM_TOP_CONTEXT_NUM) -+#define EP4_CONTEXT_TO_NODE(ctx) ((ctx) - ELAN4_KCOMM_BASE_CONTEXT_NUM) -+ -+/* -+ * network error cookie format: -+ * ------------------------------------------------- -+ * | unique cookie value | Remote | DMA | Location | -+ * ------------------------------------------------- -+ * [63:4] Cookie - unique cookie number -+ * [3] Thread - cookie generated by thread code -+ * [2] Remote - cookie generated by remote end -+ * [1] STEN - cookie is for a STEN packet -+ * [0] DMA - cookie is for a DMA -+ */ -+#define EP4_COOKIE_DMA (1 << 0) -+#define EP4_COOKIE_STEN (1 << 1) -+#define EP4_COOKIE_REMOTE (1 << 2) -+#define EP4_COOKIE_THREAD (1 << 3) -+#define EP4_COOKIE_INC (1ull << 4) -+ -+#define EP4_COOKIE_STRING(val) ((val) & ~(EP4_COOKIE_INC-1)) >> 4, \ -+ ((val) & EP4_COOKIE_DMA) ? ",dma" : "", \ -+ ((val) & EP4_COOKIE_REMOTE) ? ",remote" : "", \ -+ ((val) & EP4_COOKIE_THREAD) ? ",thread" : "", \ -+ ((val) & EP4_COOKIE_STEN) ? ",sten" : "" -+/* -+ * Done "word" values -+ */ -+#define EP4_STATE_FREE 0 -+#define EP4_STATE_ACTIVE 1 -+#define EP4_STATE_FINISHED 2 -+#define EP4_STATE_FAILED 3 -+#define EP4_STATE_PRIVATE 4 -+ -+#define EP4_EVENT_FIRING_TLIMIT 16384 /* 1023 uS */ -+ -+/* forward declarations */ -+typedef struct ep4_rail EP4_RAIL; -+ -+#if !defined(__elan4__) -+ -+typedef struct ep4_intcookie -+{ -+ struct list_head int_link; -+ E4_uint64 int_val; -+ void (*int_callback)(EP4_RAIL *rail, void *arg); -+ void *int_arg; -+} EP4_INTCOOKIE; -+ -+#define EP4_INTCOOKIE_HASH_SIZE 256 -+#define EP4_INTCOOKIE_HASH(a) ((((a) >> 3) ^ ((a) >> 7) ^ ((a) >> 11)) & (EP4_INTCOOKIE_HASH_SIZE-1)) -+ -+typedef struct ep4_ecq -+{ -+ struct list_head ecq_link; /* linked on r_ecq_list */ -+ ELAN4_INTOP ecq_intop; /* main interrupt op space */ -+ ELAN4_CQ *ecq_cq; /* command queue */ -+ E4_Addr ecq_addr; /* address mapped into elan */ -+ unsigned int ecq_avail; /* # dwords still available */ -+ -+ spinlock_t ecq_lock; /* spinlock for main accesses */ -+ sdramaddr_t ecq_event; /* event for flushing "event" queues */ -+ EP_ADDR ecq_event_addr; -+ struct ep4_ecq *ecq_flushcq; /* and command port to issue setevent to */ -+} EP4_ECQ; -+ -+#define EP4_ECQ_EVENT 0 /* command queues targetted by multi-blocks events */ -+#define EP4_ECQ_ATOMIC 1 /* command queues targetted by atomic store operations */ -+#define EP4_ECQ_SINGLE 2 /* command queues targetted by single word commands from main */ -+#define EP4_ECQ_MAIN 3 /* command queues targetted by multi word commands from main */ -+#define EP4_NUM_ECQ 4 -+ -+#define EP4_ECQ_Size(which) ((which) == EP4_ECQ_EVENT ? CQ_Size64K : \ -+ (which) == EP4_ECQ_ATOMIC ? CQ_Size8K : \ -+ (which) == EP4_ECQ_SINGLE ? CQ_Size1K : \ -+ (which) == EP4_ECQ_MAIN ? CQ_Size8K : \ -+ CQ_Size1K) -+ -+typedef struct ep4_dma_retry -+{ -+ struct list_head retry_link; /* chained on free/retry list */ -+ unsigned long retry_time; /* "lbolt" to retry at */ -+ E4_DMA retry_dma; /* DMA (in main memory) */ -+} EP4_DMA_RETRY; -+ -+#define EP4_DMA_RETRY_CQSIZE CQ_Size8K /* size of command queue for dma retry */ -+#define EP4_DMA_RETRY_FLOWCNT (CQ_Size(EP4_DMA_RETRY_CQSIZE)/72) /* # of reissued DMA's which can fit in */ -+ -+typedef struct ep4_inputq -+{ -+ EP4_INTCOOKIE q_intcookie; -+ unsigned int q_slotSize; -+ unsigned int q_slotCount; -+ -+ void *q_slots; -+ EP_ADDR q_slotsAddr; -+ -+ EP_INPUTQ_CALLBACK *q_callback; -+ void *q_arg; -+ -+ sdramaddr_t q_desc; -+ EP_ADDR q_descAddr; -+ EP_ADDR q_eventAddr; -+ EP4_ECQ *q_wcq; /* command queue to issue waitevent to */ -+ EP4_ECQ *q_ecq; /* command queue targetted by event to generate interrupt */ -+ -+ EP_ADDR q_fptr; /* cached current front pointer */ -+ EP_ADDR q_last; /* elan addr for last queue slot */ -+ -+ atomic_t q_fired; /* atomic flag that interrupt received */ -+ unsigned int q_count; /* count of slots consumed */ -+} EP4_INPUTQ; -+ -+typedef struct ep4_outputq -+{ -+ spinlock_t q_lock; -+ unsigned int q_slotCount; -+ unsigned int q_slotSize; -+ unsigned int q_dwords; -+ ELAN4_CQ *q_cq; -+ void *q_main; -+ EP_ADDR q_mainAddr; -+ unsigned int q_retries; -+} EP4_OUTPUTQ; -+ -+#endif /* ! defined(__elan4__) */ -+ -+typedef struct ep4_check_sten -+{ -+ E4_uint64 c_reset_event_cmd; /* WRITEDWORD to reset start event */ -+ E4_uint64 c_reset_event_value; -+ -+ E4_uint64 c_open; /* OPEN VP_PROBE(lvl) */ -+ E4_uint64 c_trans_traceroute0; /* SENDTRANS TR_TRACEROUTE 0s */ -+ E4_uint64 c_addr_traceroute0; -+ E4_uint64 c_data_traceroute0[8]; -+ E4_uint64 c_trans_traceroute1; /* SENDTRANS TR_TRACEROUTE 1s */ -+ E4_uint64 c_addr_traceroute1; -+ E4_uint64 c_data_traceroute1[8]; -+ E4_uint64 c_trans_sendack; /* SENDTRANS SENDACK */ -+ E4_uint64 c_addr_sendack; -+ -+ E4_uint64 c_guard_ok; /* GUARD OK - write level */ -+ E4_uint64 c_writedword_ok; -+ E4_uint64 c_value_ok; -+ -+ E4_uint64 c_guard_fail; /* GUARD FAIL - chain setevent/write fail */ -+ E4_uint64 c_setevent_fail; -+ E4_uint64 c_setevent_nop; -+ E4_uint64 c_nop_pad; -+} EP4_CHECK_STEN; -+ -+#define EP4_CHECK_STEN_NDWORDS (sizeof (EP4_CHECK_STEN) >> 3) -+ -+typedef struct ep4_rail_elan -+{ -+ EP4_CHECK_STEN r_check_sten[EP4_MAX_LEVELS]; -+ E4_Event32 r_check_fail; /* Check failed (== r_check_start[-1]) */ -+ E4_Event32 r_check_start[EP4_MAX_LEVELS]; -+ -+ E4_Event32 r_qevents[EP_NUM_SYSTEMQ]; -+ E4_Event32 r_flush_event; -+ -+ E4_uint64 r_nodeid; -+#ifdef __elan4__ -+ E4_uint64 *r_cookies; -+#else -+ E4_Addr r_cookies; -+#endif -+} EP4_RAIL_ELAN; -+ -+#define TRACEROUTE_ENTRIES 16 /* 2 * ELAN_MAX_LEVELS */ -+#define TRACEROUTE_NDWORDS (TRACEROUTE_ENTRIES/2) -+ -+typedef struct ep4_rail_main -+{ -+ E4_uint32 r_probe_dest0[TRACEROUTE_ENTRIES]; -+ E4_uint32 r_probe_dest1[TRACEROUTE_ENTRIES]; -+ E4_uint64 r_probe_result; -+ E4_uint64 r_probe_level; -+ -+ E4_uint64 r_dma_flowcnt; /* count of dma's queued */ -+} EP4_RAIL_MAIN; -+ -+#define EP4_PROBE_ACTIVE (0xffff) -+#define EP4_PROBE_FAILED (0xfffe) -+ -+#if !defined(__elan4__) -+ -+typedef struct ep4_retry_ops -+{ -+ struct list_head op_link; -+ unsigned long (*op_func)(EP4_RAIL *rail, void *arg, unsigned long nextRunTime); -+ void *op_arg; -+} EP4_RETRY_OPS; -+ -+typedef struct ep4_neterr_ops -+{ -+ struct list_head op_link; -+ void (*op_func) (EP4_RAIL *rail, void *arg, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+ void *op_arg; -+} EP4_NETERR_OPS; -+ -+struct ep4_rail -+{ -+ EP_RAIL r_generic; -+ ELAN4_CTXT r_ctxt; -+ ELAN4_ROUTE_TABLE *r_routetable; -+ -+ spinlock_t r_intcookie_lock; -+ struct list_head r_intcookie_hash[EP4_INTCOOKIE_HASH_SIZE]; -+ -+ sdramaddr_t r_elan; -+ EP_ADDR r_elan_addr; -+ EP4_RAIL_MAIN *r_main; -+ EP_ADDR r_main_addr; -+ -+ EP_CODE r_threadcode; /* copy of thread code */ -+ -+ sdramaddr_t r_queuedescs; /* systemq queue descriptors */ -+ -+ E4_uint64 *r_cookies; /* network error cookies */ -+ spinlock_t r_cookie_lock; /* and spin lock */ -+ -+ kcondvar_t r_probe_wait; /* network position probing */ -+ spinlock_t r_probe_lock; -+ volatile int r_probe_done; -+ EP4_INTCOOKIE r_probe_intcookie; -+ EP4_ECQ *r_probe_cq; -+ E4_uint32 r_probe_source0[TRACEROUTE_ENTRIES]; -+ E4_uint32 r_probe_source1[TRACEROUTE_ENTRIES]; -+ -+ kmutex_t r_haltop_mutex; /* halt/flush operations */ -+ ELAN4_HALTOP r_haltop; -+ ELAN4_DMA_FLUSHOP r_flushop; -+ kcondvar_t r_haltop_sleep; -+ spinlock_t r_haltop_lock; -+ -+ struct list_head r_ecq_list[EP4_NUM_ECQ]; /* list of statically allocated command queues */ -+ EP_RMAP *r_ecq_rmap; /* resource map for command queue mappings */ -+ spinlock_t r_ecq_lock; /* spinlock for list/space management */ -+ -+ kmutex_t r_flush_mutex; /* serialize command queue flushing */ -+ unsigned long r_flush_count; /* # setevents issued for flushing */ -+ EP4_ECQ *r_flush_mcq; /* and command queue for waitevent */ -+ EP4_ECQ *r_flush_ecq; /* and command queue for interrupt */ -+ EP4_INTCOOKIE r_flush_intcookie; /* and interrupt cookie */ -+ kcondvar_t r_flush_sleep; /* and place to sleep ... */ -+ -+ EP_KTHREAD r_retry_thread; /* retry thread */ -+ struct list_head r_retry_ops; /* list of retry operations */ -+ -+ EP4_RETRY_OPS r_dma_ops; /* dma retry operations */ -+ EP4_ECQ *r_dma_ecq; /* command queue to reissue DMAs */ -+ E4_uint64 r_dma_flowcnt; /* count of dma's reissued */ -+ struct list_head r_dma_retrylist[EP_NUM_RETRIES]; /* retry lists */ -+ struct list_head r_dma_freelist; /* and free list */ -+ spinlock_t r_dma_lock; /* and spinlock to protect lists */ -+ unsigned long r_dma_allocated; /* # retries allocated*/ -+ unsigned long r_dma_reserved; /* # retries reserved */ -+ -+ EP4_ECQ *r_event_ecq; /* command queue for occasional setevents */ -+ -+ struct list_head r_neterr_ops; /* list of neterr fixup operations */ -+ -+ ELAN4_IPROC_TRAP r_iproc_trap; -+ ELAN4_TPROC_TRAP r_tproc_trap; -+} ; -+ -+#define EP4_CTXT_TO_RAIL(ctxt) ((EP4_RAIL *) (((unsigned long) (ctxt)) - offsetof (EP4_RAIL, r_ctxt))) -+ -+#if defined(DEBUG_ASSERT) -+#define EP4_ASSERT(rail,EXPR) EP_ASSERT(&((rail)->r_generic), EXPR) -+#define EP4_SDRAM_ASSERT(rail,off,value) EP4_ASSERT(rail, (sdram_assert ? elan4_sdram_readq ((rail)->r_ctxt.ctxt_dev, (off)) == (value) : 1)) -+#else -+#define EP4_ASSERT(rail,EXPR) -+#define EP4_SDRAM_ASSERT(rail,off,value) -+#endif -+ -+/* kcomm_elan4.c */ -+extern EP_RAIL *ep4_create_rail (EP_SYS *sys, ELAN4_DEV *dev); -+extern void ep4_destroy_rail (EP_RAIL *rail); -+ -+extern int ep4_start_rail (EP_RAIL *rail); -+extern void ep4_stall_rail (EP_RAIL *rail); -+extern void ep4_stop_rail (EP_RAIL *rail); -+ -+extern void ep4_debug_rail (EP_RAIL *rail); -+ -+extern void ep4_position_found (EP_RAIL *rail, ELAN_POSITION *pos); -+ -+extern sdramaddr_t ep4_sdram_alloc (EP_RAIL *rail, EP_ADDR addr, unsigned int size); -+extern void ep4_sdram_free (EP_RAIL *rail, sdramaddr_t addr, unsigned int size); -+extern void ep4_sdram_writeb (EP_RAIL *rail, sdramaddr_t addr, unsigned char val); -+ -+extern void ep4_flush_tlb (EP_RAIL *r); -+extern void ep4_load_system_route (EP_RAIL *r, unsigned int vp, unsigned int lowNode, unsigned int highNode); -+extern void ep4_load_node_route (EP_RAIL *r, unsigned int nodeId); -+extern void ep4_unload_node_route (EP_RAIL *r, unsigned int nodeId); -+extern void ep4_lower_filter (EP_RAIL *r, unsigned int nodeId); -+extern void ep4_raise_filter (EP_RAIL *rail, unsigned int nodeId); -+extern void ep4_node_disconnected (EP_RAIL *r, unsigned int nodeId); -+ -+/* kmap_elan4.c */ -+extern void ep4_kaddr_map (EP_RAIL *r, EP_ADDR eaddr, virtaddr_t kaddr, unsigned int len, unsigned int perm, int ep_attr); -+extern void ep4_sdram_map (EP_RAIL *r, EP_ADDR eaddr, sdramaddr_t saddr, unsigned int len, unsigned int perm, int ep_attr); -+extern void ep4_ioaddr_map (EP_RAIL *r, EP_ADDR eaddr, ioaddr_t ioaddr, unsigned int len, unsigned int perm); -+extern void ep4_unmap (EP_RAIL *r, EP_ADDR eaddr, unsigned int len); -+extern void *ep4_dvma_reserve (EP_RAIL *r, EP_ADDR eaddr, unsigned int npages); -+extern void ep4_dvma_release (EP_RAIL *r, EP_ADDR eaddr, unsigned int npages, void *private); -+extern void ep4_dvma_set_pte (EP_RAIL *r, void *private, unsigned int index, physaddr_t paddr, unsigned int perm); -+extern physaddr_t ep4_dvma_read_pte (EP_RAIL *r, void *private, unsigned int index); -+extern void ep4_dvma_unload (EP_RAIL *r, void *private, unsigned int index, unsigned int npages); -+ -+/* kmsg_elan4.c */ -+extern EP_INPUTQ *ep4_alloc_inputq (EP_RAIL *r, unsigned int qnum, unsigned int slotSize, unsigned int slotCount, -+ EP_INPUTQ_CALLBACK *callback, void *arg); -+extern void ep4_free_inputq (EP_RAIL *r, EP_INPUTQ *q); -+extern void ep4_enable_inputq (EP_RAIL *r, EP_INPUTQ *q); -+extern void ep4_disable_inputq (EP_RAIL *r, EP_INPUTQ *q); -+extern int ep4_poll_inputq (EP_RAIL *r, EP_INPUTQ *q, int maxCount, EP_INPUTQ_HANDLER *handler, void *arg); -+extern EP_OUTPUTQ *ep4_alloc_outputq (EP_RAIL *r, unsigned int slotSize, unsigned int slotCount); -+extern void ep4_free_outputq (EP_RAIL *r, EP_OUTPUTQ *q); -+extern void *ep4_outputq_msg (EP_RAIL *r, EP_OUTPUTQ *q, unsigned int slotNum); -+extern int ep4_outputq_state (EP_RAIL *r, EP_OUTPUTQ *q, unsigned int slotNum); -+extern int ep4_outputq_send (EP_RAIL *r, EP_OUTPUTQ *q, unsigned int slotNum, unsigned int size, -+ unsigned int nodeId, unsigned int qnum, unsigned int retries); -+ -+/* probenetwork_elan4.c */ -+extern int ep4_probe_init (EP4_RAIL *r); -+extern void ep4_probe_destroy (EP4_RAIL *r); -+extern void ep4_probe_position_found (EP4_RAIL *rail, ELAN_POSITION *pos); -+extern int ep4_probe_route (EP_RAIL *r, int level, int sw, int nodeid, int *linkup, int *linkdown, int attempts, EP_SWITCH *lsw); -+extern int ep4_check_position (EP_RAIL *rail); -+ -+/* support_elan4.c */ -+extern ELAN4_TRAP_OPS ep4_trap_ops; -+extern void ep4_register_intcookie (EP4_RAIL *rail, EP4_INTCOOKIE *cp, E4_uint64 cookie, void (*callback)(EP4_RAIL *r, void *arg), void *arg); -+extern void ep4_deregister_intcookie (EP4_RAIL *rail, EP4_INTCOOKIE *cp); -+extern EP4_INTCOOKIE *ep4_lookup_intcookie (EP4_RAIL *rail, E4_uint64 cookie); -+extern E4_uint64 ep4_neterr_cookie (EP4_RAIL *rail, unsigned int node); -+ -+extern void ep4_flush_filters (EP_RAIL *r); -+extern void ep4_flush_queues (EP_RAIL *r); -+extern void ep4_write_qdesc (EP4_RAIL *rail, sdramaddr_t qaddr, E4_InputQueue *qdesc); -+ -+extern EP4_ECQ *ep4_alloc_ecq (EP4_RAIL *rail, unsigned int cqsize); -+extern void ep4_free_ecq (EP4_RAIL *rail, EP4_ECQ *ecq); -+extern EP4_ECQ *ep4_get_ecq (EP4_RAIL *rail, unsigned int which, unsigned int ndwords); -+extern void ep4_put_ecq (EP4_RAIL *rail, EP4_ECQ *ecq, unsigned int ndwords); -+ -+extern void ep4_nop_cmd (EP4_ECQ *ecq, E4_uint64 tag); -+extern void ep4_set_event_cmd (EP4_ECQ *ecq, E4_Addr event); -+extern void ep4_wait_event_cmd (EP4_ECQ *ecq, E4_Addr event, E4_uint64 candt, E4_uint64 param0, E4_uint64 param1); -+ -+extern void ep4_flush_interrupt (EP4_RAIL *rail, void *arg); -+extern void ep4_flush_ecqs (EP4_RAIL *rail); -+ -+extern void ep4_init_thread (EP4_RAIL *rail, E4_ThreadRegs *regs, sdramaddr_t stackTop, -+ EP_ADDR stackAddr, E4_Addr startpc, int nargs,...); -+ -+extern void ep4_initialise_dma_retries (EP4_RAIL *rail); -+extern void ep4_finalise_dma_retries (EP4_RAIL *rail); -+extern int ep4_reserve_dma_retries (EP4_RAIL *rail, unsigned int count, unsigned int attr); -+extern void ep4_release_dma_retries(EP4_RAIL *rail, unsigned int count); -+extern void ep4_queue_dma_retry (EP4_RAIL *rail, E4_DMA *dma, int interval); -+extern void ep4_queue_dma_stalled (EP4_RAIL *rail, E4_DMA *dma); -+extern void ep4_free_stalled_dmas (EP4_RAIL *rail, unsigned int nodeId); -+extern void ep4_display_rail (EP4_RAIL *rail); -+ -+extern void ep4_add_retry_ops (EP4_RAIL *rail, EP4_RETRY_OPS *ops); -+extern void ep4_remove_retry_ops (EP4_RAIL *rail, EP4_RETRY_OPS *ops); -+extern void ep4_retry_thread (EP4_RAIL *rail); -+ -+/* neterr_elan4.c */ -+extern void ep4_add_neterr_ops (EP4_RAIL *rail, EP4_NETERR_OPS *ops); -+extern void ep4_remove_neterr_ops (EP4_RAIL *rail, EP4_NETERR_OPS *ops); -+extern void ep4_neterr_fixup (EP_RAIL *r, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+ -+/* commands_elan4.c */ -+extern void elan4_nop_cmd (ELAN4_CQ *cq, E4_uint64 tag); -+extern void elan4_write_dword_cmd (ELAN4_CQ *cq, E4_Addr addr, E4_uint64 data); -+extern void elan4_add_dword_cmd (ELAN4_CQ *cq, E4_Addr addr, E4_uint64 data); -+extern void elan4_copy64_cmd (ELAN4_CQ *cq, E4_Addr from, E4_Addr to, E4_uint32 datatype); -+extern void elan4_interrupt_cmd (ELAN4_CQ *cq, E4_uint64 cookie); -+extern void elan4_run_thread_cmd (ELAN4_CQ *cq, E4_ThreadRegs *regs); -+extern void elan4_run_dma_cmd (ELAN4_CQ *cq, E4_DMA *dma); -+extern void elan4_set_event_cmd (ELAN4_CQ *cq, E4_Addr event); -+extern void elan4_set_eventn_cmd (ELAN4_CQ *cq, E4_Addr event, E4_uint32 count); -+extern void elan4_wait_event_cmd (ELAN4_CQ *cq, E4_Addr event, E4_uint64 candt, E4_uint64 param0, E4_uint64 param1); -+extern void elan4_open_packet (ELAN4_CQ *cq, E4_uint64 command); -+extern void elan4_guard (ELAN4_CQ *cq, E4_uint64 command); -+extern void elan4_sendtrans0 (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr); -+extern void elan4_sendtrans1 (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, E4_uint64 p0); -+extern void elan4_sendtrans2 (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, E4_uint64 p0, E4_uint64 p1); -+extern void elan4_sendtransn (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, ...); -+extern void elan4_sendtransp (ELAN4_CQ *cq, E4_uint16 trtype, E4_uint64 addr, E4_uint64 *ptr); -+ -+extern void ep4_add_retry_ops (EP4_RAIL *rail, EP4_RETRY_OPS *ops); -+extern void ep4_remove_retry_ops (EP4_RAIL *rail, EP4_RETRY_OPS *ops); -+extern void ep4_retry_thread (EP4_RAIL *rail); -+ -+extern void ep4_fillout_stats(EP_RAIL *rail, char *str); -+ -+#endif /* ! defined(__elan4__) */ -+ -+#endif /* __EP_KCOMM_ELAN4_H */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kcomm_vp.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kcomm_vp.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kcomm_vp.h 2005-06-01 23:12:54.668428616 -0400 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __EP_KCOMM_VP_H -+#define __EP_KCOMM_VP_H -+ -+#ident "@(#)$Id: kcomm_vp.h,v 1.2 2004/03/24 11:32:56 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm_vp.h,v $*/ -+ -+#define EP_MAX_NODES 2048 /* Max nodes we support */ -+ -+/* virtual process allocation */ -+#define EP_VP_NODE_BASE (0) -+#define EP_VP_DATA_BASE (EP_VP_NODE_BASE + EP_MAX_NODES) -+#define EP_VP_PROBE_BASE (EP_VP_DATA_BASE + EP_MAX_NODES) -+#define EP_VP_PROBE_COUNT ELAN_MAX_LEVELS -+ -+#define EP_VP_BCAST_BASE (EP_VP_PROBE_BASE + EP_VP_PROBE_COUNT) -+#define EP_VP_BCAST_COUNT (CM_SGMTS_PER_LEVEL * (CM_MAX_LEVELS - 1) + 1) -+ -+#define EP_VP_NODE(nodeId) (EP_VP_NODE_BASE + (nodeId)) -+#define EP_VP_DATA(nodeId) (EP_VP_DATA_BASE + (nodeId)) -+#define EP_VP_PROBE(lvl) (EP_VP_PROBE_BASE + (lvl)) -+#define EP_VP_BCAST(lvl,sgmt) (EP_VP_BCAST_BASE + ((lvl) - 1)*CM_SGMTS_PER_LEVEL + (sgmt)) -+ -+#define EP_VP_TO_NODE(vp) ((vp) & (EP_MAX_NODES-1)) -+#define EP_VP_ISDATA(vp) ((vp) >= EP_VP_DATA_BASE && (vp) < (EP_VP_DATA_BASE + EP_MAX_NODES)) -+ -+#endif /* __EP_KCOMM_VP_H */ -+ -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/kmap.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kmap.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kmap.c 2005-06-01 23:12:54.669428464 -0400 -@@ -0,0 +1,561 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kmap.c,v 1.10.6.2 2004/12/14 10:19:14 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmap.c,v $*/ -+ -+#include -+#include -+ -+#include -+ -+#include "debug.h" -+ -+#if defined(DIGITAL_UNIX) -+# define kernel_map (first_task->map) -+# define vaddr_to_phys(map, addr) (pmap_extract (vm_map_pmap ((vm_map_t) map), (unsigned long) addr)) -+#elif defined(LINUX) -+# define kernel_map get_kern_mm() -+# define vaddr_to_phys(map, addr) (kmem_to_phys(addr)) -+#elif defined(SOLARIS) -+# define kernel_map &kas -+# define vaddr_to_phys(map,addr) ptob(hat_getpfnum (((struct as *) map)->a_hat, (caddr_t) addr)) -+#endif -+ -+void -+ep_perrail_kaddr_map (EP_RAIL *rail, EP_ADDR eaddr, virtaddr_t kaddr, unsigned long len, unsigned int perm, int ep_attr) -+{ -+ rail->Operations.KaddrMap (rail, eaddr, kaddr, len, perm, ep_attr); -+} -+ -+void -+ep_perrail_sdram_map (EP_RAIL *rail, EP_ADDR eaddr, sdramaddr_t saddr, unsigned long len, unsigned int perm, int ep_attr) -+{ -+ rail->Operations.SdramMap (rail, eaddr, saddr, len, perm, ep_attr); -+} -+ -+void -+ep_perrail_unmap (EP_RAIL *rail, EP_ADDR eaddr, unsigned long len) -+{ -+ rail->Operations.Unmap (rail, eaddr, len); -+} -+ -+void -+ep_perrail_dvma_sync (EP_RAIL *rail) -+{ -+ if (rail->TlbFlushRequired) -+ { -+ rail->TlbFlushRequired = 0; -+ -+ rail->Operations.FlushTlb (rail); -+ } -+} -+ -+ -+static int ep_dvma_map_rails (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd, EP_RAILMASK mask); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+static uint16_t ep_dvma_calc_check_sum (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd, uint16_t check_sum); -+#endif -+ -+EP_NMH_OPS ep_dvma_nmh_ops = -+{ -+ ep_dvma_map_rails, -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ ep_dvma_calc_check_sum -+#endif -+}; -+ -+extern void -+ep_dvma_init (EP_SYS *sys) -+{ -+ EP_DVMA_STATE *d = &sys->DvmaState; -+ -+ kmutex_init (&d->dvma_lock); -+ -+ INIT_LIST_HEAD (&d->dvma_handles); -+ INIT_LIST_HEAD (&d->dvma_rails); -+ -+ d->dvma_rmap = ep_rmallocmap (EP_DVMA_RMAP_SIZE, "dvma_rmap", 1); -+ -+ ep_rmfree (d->dvma_rmap, EP_DVMA_TOP - EP_DVMA_BASE, EP_DVMA_BASE); -+} -+ -+extern void -+ep_dvma_fini (EP_SYS *sys) -+{ -+ EP_DVMA_STATE *d = &sys->DvmaState; -+ -+ ep_rmfreemap (d->dvma_rmap); -+ -+ kmutex_destroy (&d->dvma_lock); -+} -+ -+extern int -+ep_dvma_add_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ EP_DVMA_STATE *d = &sys->DvmaState; -+ EP_RAIL_ENTRY *l; -+ struct list_head *el; -+ -+ KMEM_ZALLOC (l, EP_RAIL_ENTRY *, sizeof (EP_RAIL_ENTRY), 1); -+ -+ if (l == NULL) -+ return (ENOMEM); -+ -+ kmutex_lock (&d->dvma_lock); -+ -+ l->Rail = rail; -+ -+ list_add_tail (&l->Link, &d->dvma_rails); -+ -+ list_for_each (el, &d->dvma_handles) { -+ EP_DVMA_NMH *desc = list_entry (el, EP_DVMA_NMH, dvma_link); -+ int npages = desc->dvma_nmh.nmh_nmd.nmd_len >> PAGESHIFT; -+ -+ desc->dvma_rails[rail->Number] = rail; -+ desc->dvma_railmask |= ( 1 << rail->Number); -+ -+ desc->dvma_private[rail->Number] = rail->Operations.DvmaReserve (rail, desc->dvma_nmh.nmh_nmd.nmd_addr, npages); -+ } -+ -+ kmutex_unlock (&d->dvma_lock); -+ return (0); -+} -+ -+extern void -+ep_dvma_remove_rail (EP_SYS *sys, EP_RAIL *rail) -+{ -+ EP_DVMA_STATE *d = &sys->DvmaState; -+ struct list_head *el; -+ -+ kmutex_lock (&d->dvma_lock); -+ -+ list_for_each (el, &d->dvma_handles) { -+ EP_DVMA_NMH *desc = list_entry (el, EP_DVMA_NMH, dvma_link); -+ int npages = desc->dvma_nmh.nmh_nmd.nmd_len >> PAGESHIFT; -+ -+ desc->dvma_rails[rail->Number] = NULL; -+ desc->dvma_railmask &= ~(1 << rail->Number); -+ -+ rail->Operations.DvmaRelease (rail, desc->dvma_nmh.nmh_nmd.nmd_addr, npages, desc->dvma_private[rail->Number]); -+ } -+ -+ list_for_each (el, &d->dvma_rails) { -+ EP_RAIL_ENTRY *tmp = list_entry (el, EP_RAIL_ENTRY, Link); -+ -+ if (tmp->Rail == rail) -+ { -+ list_del (el); -+ -+ KMEM_FREE (tmp, sizeof (EP_RAIL_ENTRY)); -+ break; -+ } -+ } -+ kmutex_unlock (&d->dvma_lock); -+} -+ -+EP_NMH * -+ep_dvma_reserve (EP_SYS *sys, unsigned npages, unsigned perm) -+{ -+ EP_DVMA_STATE *d = &sys->DvmaState; -+ EP_DVMA_NMH *desc; -+ EP_ADDR addr; -+ struct list_head *el; -+ int i; -+ -+ KMEM_ZALLOC (desc, EP_DVMA_NMH *, offsetof (EP_DVMA_NMH, dvma_attrs[npages]), 1); -+ -+ if (desc == NULL) -+ return (NULL); -+ -+ if ((addr = ep_rmalloc (d->dvma_rmap, npages << PAGESHIFT, 0)) == 0) -+ { -+ -+ KMEM_FREE (desc, sizeof (EP_DVMA_NMH)); -+ return (NULL); -+ } -+ -+ spin_lock_init (&desc->dvma_lock); -+ -+ desc->dvma_perm = perm; -+ -+ kmutex_lock (&d->dvma_lock); -+ /* reserve the mapping resource */ -+ list_for_each (el, &d->dvma_rails) { -+ EP_RAIL *rail = list_entry (el, EP_RAIL_ENTRY, Link)->Rail; -+ -+ EPRINTF4 (DBG_KMAP, "%s: ep_dvma_reserve desc=%p npages=%d rail=%p\n", rail->Name, desc, npages, rail); -+ -+ if ((desc->dvma_private[rail->Number] = rail->Operations.DvmaReserve (rail, addr, npages)) == NULL) -+ { -+ printk ("%s: !!ep_dvma_reserve - rail->DvmaReserve failed\n", rail->Name); -+ goto failed; -+ } -+ -+ desc->dvma_rails[rail->Number] = rail; -+ desc->dvma_railmask |= (1 << rail->Number); -+ } -+ -+ /* insert into the network mapping handle table */ -+ desc->dvma_nmh.nmh_nmd.nmd_addr = addr; -+ desc->dvma_nmh.nmh_nmd.nmd_len = npages << PAGESHIFT; -+ desc->dvma_nmh.nmh_nmd.nmd_attr = EP_NMD_ATTR (sys->Position.pos_nodeid, 0); -+ desc->dvma_nmh.nmh_ops = &ep_dvma_nmh_ops; -+ -+ ep_nmh_insert (&sys->MappingTable, &desc->dvma_nmh); -+ -+ list_add (&desc->dvma_link, &d->dvma_handles); -+ -+ kmutex_unlock (&d->dvma_lock); -+ -+ return (&desc->dvma_nmh); -+ -+ failed: -+ -+ kmutex_unlock (&d->dvma_lock); -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (desc->dvma_rails[i] != NULL) -+ desc->dvma_rails[i]->Operations.DvmaRelease (desc->dvma_rails[i], addr, npages, desc->dvma_private[i]); -+ -+ ep_rmfree (d->dvma_rmap, npages << PAGESHIFT, addr); -+ -+ KMEM_FREE (desc, sizeof (EP_DVMA_NMH)); -+ return (NULL); -+} -+ -+void -+ep_dvma_release (EP_SYS *sys, EP_NMH *nmh) -+{ -+ EP_DVMA_STATE *d = &sys->DvmaState; -+ EP_DVMA_NMH *desc = (EP_DVMA_NMH *) nmh; -+ EP_ADDR addr = nmh->nmh_nmd.nmd_addr; -+ int npages = nmh->nmh_nmd.nmd_len >> PAGESHIFT; -+ EP_RAIL *rail; -+ int i; -+ -+ kmutex_lock (&d->dvma_lock); -+ -+ list_del (&desc->dvma_link); -+ -+ ep_nmh_remove (&sys->MappingTable, nmh); -+ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if ((rail = desc->dvma_rails[i]) != NULL) -+ rail->Operations.DvmaRelease (rail, addr, npages, desc->dvma_private[i]); -+ -+ ep_rmfree (d->dvma_rmap, npages << PAGESHIFT, addr); -+ -+ KMEM_FREE (desc, offsetof (EP_DVMA_NMH, dvma_attrs[npages])); -+ -+ kmutex_unlock (&d->dvma_lock); -+} -+ -+void -+ep_dvma_load (EP_SYS *sys, void *map, caddr_t vaddr, unsigned len, EP_NMH *nmh, unsigned index, EP_RAILMASK *hints, EP_NMD *subset) -+{ -+ EP_DVMA_NMH *desc = (EP_DVMA_NMH *) nmh; -+ unsigned offset = (unsigned long) vaddr & PAGEOFFSET; -+ unsigned npages = btopr (len + offset); -+ EP_ADDR addr = nmh->nmh_nmd.nmd_addr + (index << PAGESHIFT); -+ int rmask = *hints; -+ EP_RAIL *rail; -+ register int i, rnum; -+ unsigned long flags; -+ -+ EPRINTF7 (DBG_KMAP, "ep_dvma_load: map=%p vaddr=%p len=%x nmh=%p(%x,%x) index=%d\n", -+ map, vaddr, len, nmh, nmh->nmh_nmd.nmd_addr, nmh->nmh_nmd.nmd_len, index); -+ -+ /* If no rail specified, then map into all rails */ -+ if (rmask == 0) -+ rmask = desc->dvma_railmask; -+ -+ ASSERT ((index + npages) <= (nmh->nmh_nmd.nmd_len >> PAGESHIFT)); -+ -+ /* If not map specified then use the kernel map */ -+ if (map == NULL) -+ map = kernel_map; -+ -+ spin_lock_irqsave (&desc->dvma_lock, flags); -+ /* Now map each of the specified pages (backwards) */ -+ -+ vaddr = (vaddr - offset) + (npages-1)*PAGESIZE; -+ for (i = npages-1; i >= 0; i--, vaddr -= PAGESIZE) -+ { -+ physaddr_t paddr = vaddr_to_phys (map, vaddr); -+ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ { -+ if (! (rmask & (1 << rnum)) || (rail = desc->dvma_rails[rnum]) == NULL) -+ rmask &= ~(1 << rnum); -+ else -+ { -+ rail->Operations.DvmaSetPte (rail, desc->dvma_private[rnum], index + i, paddr, desc->dvma_perm); -+ -+ desc->dvma_attrs[index + i] |= (1 << rnum); -+ } -+ } -+ } -+ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ if ((rmask & (1 << rnum)) && (rail = desc->dvma_rails[rnum]) != NULL) -+ rail->TlbFlushRequired = 1; -+ -+ spin_unlock_irqrestore (&desc->dvma_lock, flags); -+ -+ /* Construct the network mapping handle to be returned. */ -+ subset->nmd_addr = addr + offset; -+ subset->nmd_len = len; -+ subset->nmd_attr = EP_NMD_ATTR(sys->Position.pos_nodeid, rmask); -+} -+ -+void -+ep_dvma_unload (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd) -+{ -+ EP_DVMA_NMH *desc = (EP_DVMA_NMH *) nmh; -+ unsigned offset = nmd->nmd_addr & PAGEOFFSET; -+ unsigned npages = btopr (nmd->nmd_len + offset); -+ unsigned index = (nmd->nmd_addr - nmh->nmh_nmd.nmd_addr) >> PAGESHIFT; -+ EP_RAIL *rail; -+ int rnum; -+ int rmask; -+ register int i; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&desc->dvma_lock, flags); -+ -+ /* compute which rails we need to unload on */ -+ for (rmask = 0, i = 0; i < npages; i++) -+ { -+ rmask |= desc->dvma_attrs[index + i]; -+ -+ desc->dvma_attrs[index + i] = 0; -+ } -+ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ if ((rmask & (1 << rnum)) && (rail = desc->dvma_rails[rnum]) != NULL) -+ rail->Operations.DvmaUnload (rail, desc->dvma_private[rnum], index, npages); -+ -+ spin_unlock_irqrestore (&desc->dvma_lock, flags); -+} -+ -+int -+ep_dvma_map_rails (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd, EP_RAILMASK mask) -+{ -+ EP_DVMA_NMH *desc = (EP_DVMA_NMH *) nmh; -+ unsigned offset = nmd->nmd_addr & PAGEOFFSET; -+ unsigned npages = btopr (nmd->nmd_len + offset); -+ unsigned index = (nmd->nmd_addr - nmh->nmh_nmd.nmd_addr) >> PAGESHIFT; -+ int r, rnum; -+ register int i; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&desc->dvma_lock, flags); -+ -+ EPRINTF4 (DBG_KMAP, "ep_dvma_map_rails: nmd=%08x.%08x.%08x mask=%04x\n", nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr, mask); -+ -+ if ((mask &= desc->dvma_railmask) == 0) -+ { -+ printk ("ep_dvma_map_rails: no intersecting rails %04x.%04x\n", mask, desc->dvma_railmask); -+ spin_unlock_irqrestore (&desc->dvma_lock, flags); -+ return (-1); -+ } -+ -+ for (i = npages-1; i >= 0; i--) -+ { -+ int pgidx = (index + i); -+ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ if (desc->dvma_attrs[pgidx] & (1 << rnum)) -+ break; -+ -+ if (rnum == EP_MAX_RAILS) -+ { -+ EPRINTF3 (DBG_KMAP, "ep_dvma_map_rails: nmh=%p idx=%x [%08x] not ptes valid\n", nmh, pgidx, -+ nmh->nmh_nmd.nmd_addr + ((pgidx) << PAGESHIFT)); -+ mask = 0; -+ } -+ else -+ { -+ EP_RAIL *rail = desc->dvma_rails[rnum]; -+ physaddr_t paddr = rail->Operations.DvmaReadPte (rail, desc->dvma_private[rnum], pgidx); -+ -+ EPRINTF5 (DBG_KMAP, "%s: ep_dvma_map_rails: nmh=%p idx=%x [%08x] paddr %llx\n", rail->Name, nmh, pgidx, -+ nmh->nmh_nmd.nmd_addr + (pgidx << PAGESHIFT), (long long) paddr); -+ -+ for (r = 0; r < EP_MAX_RAILS; r++) -+ { -+ if ((mask & (1 << r)) == 0) -+ continue; -+ -+ if ((desc->dvma_attrs[pgidx] & (1 << r)) == 0) -+ { -+ EPRINTF5 (DBG_KMAP, "%s: ep_dvma_map_rails: nmh=%p idx=%x [%08x] paddr=%llx\n", -+ desc->dvma_rails[rnum]->Name, nmh, pgidx, nmh->nmh_nmd.nmd_addr + (pgidx << PAGESHIFT), -+ (long long) paddr); -+ -+ rail->Operations.DvmaSetPte (rail, desc->dvma_private[rnum], pgidx, paddr, desc->dvma_perm); -+ -+ desc->dvma_attrs[pgidx] |= (1 << r); -+ } -+ } -+ } -+ } -+ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ if ((mask & (1 << rnum)) != 0) -+ desc->dvma_rails[rnum]->TlbFlushRequired = 1; -+ -+ EPRINTF4 (DBG_KMAP, "ep_dvma_map_rails: nmd=%08x.%08x.%08x|%04x\n", nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr, mask); -+ -+ /* Finally update the network memory descriptor */ -+ nmd->nmd_attr |= mask; -+ -+ spin_unlock_irqrestore (&desc->dvma_lock, flags); -+ -+ return (0); -+} -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+#include -+ -+/* Generic rolling checksum algorithm */ -+uint16_t -+rolling_check_sum (char *msg, int nob, uint16_t sum) -+{ -+ while (nob-- > 0) -+ sum = sum * 13 + *msg++; -+ -+ return (sum); -+} -+ -+#if ! defined(NO_RMAP) -+void -+unmap_phys_address(unsigned long phys_addr) -+{ -+ unsigned long pfn = (phys_addr >> PAGE_SHIFT); -+ -+ if (pfn_valid(pfn)) -+ kunmap(pfn_to_page(pfn)); -+} -+ -+void * -+map_phys_address(unsigned long phys_addr) -+{ -+ unsigned long pfn = (phys_addr >> PAGE_SHIFT); -+ -+ if (pfn_valid(pfn)) -+ return kmap(pfn_to_page(pfn)); -+ -+ return NULL; -+} -+#else -+void -+unmap_phys_address(unsigned long phys_addr) -+{ -+ struct page *p = virt_to_page(__va(phys_addr)); -+ -+ if (VALID_PAGE(p)) -+ kunmap(p); -+} -+ -+void * -+map_phys_address(unsigned long phys_addr) -+{ -+ struct page *p = virt_to_page(__va(phys_addr)); -+ -+ if (VALID_PAGE(p)) -+ return kmap(p); -+ -+ return NULL; -+} -+#endif -+ -+uint16_t -+ep_dvma_calc_check_sum (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd, uint16_t check_sum) -+{ -+ /* cant be called from an interupt */ -+ -+ EP_DVMA_NMH *desc = (EP_DVMA_NMH *) nmh; -+ unsigned offset = nmd->nmd_addr & PAGEOFFSET; -+ unsigned npages = btopr (nmd->nmd_len + offset); -+ unsigned index = (nmd->nmd_addr - nmh->nmh_nmd.nmd_addr) >> PAGESHIFT; -+ unsigned start, len; -+ int rnum; -+ register int i; -+ unsigned long flags; -+ EP_RAIL *rail; -+ -+ -+ spin_lock_irqsave (&desc->dvma_lock, flags); -+ -+ EPRINTF3 (DBG_KMAP, "ep_dvma_calc_check_sum: nmd=%08x.%08x.%08x \n", nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr); -+ -+ /* find a rail */ -+ for (rnum = 0; rnum < EP_MAX_RAILS; rnum++) -+ if (desc->dvma_attrs[index] & (1 << rnum)) -+ break; -+ -+ ASSERT (rnum != EP_MAX_RAILS); -+ -+ rail = desc->dvma_rails[rnum]; -+ -+ for (i = 0; i <= (npages-1); i++) -+ { -+ int pgidx = (index + i); -+ physaddr_t paddr = rail->Operations.DvmaReadPte (rail, desc->dvma_private[rnum], pgidx); -+ void * virt; -+ -+ spin_unlock_irqrestore (&desc->dvma_lock, flags); /* unlock for check sum calc */ -+ -+ virt = map_phys_address(paddr); -+ -+ if (!virt) -+ printk("ep_dvma_calc_check_sum: virt = NULL ! \n"); -+ else { -+ if ( i == 0 ) { -+ /* last bit of the first page */ -+ start = (nmd->nmd_addr & (PAGESIZE - 1)) ; -+ len = PAGESIZE - start; -+ if ( len > nmd->nmd_len) /* less than the remaining page */ -+ len = nmd->nmd_len; -+ } else { -+ if ( i != (npages-1)) { -+ /* all of the middle pages */ -+ start = 0; -+ len = PAGESIZE; -+ } else { -+ /* first bit of the last page */ -+ start = 0; -+ len = ((nmd->nmd_addr + nmd->nmd_len -1) & (PAGESIZE -1)) +1; -+ } -+ } -+ -+ check_sum = rolling_check_sum (((char *)virt)+start, len, check_sum); -+ unmap_phys_address(paddr); -+ -+ /* re aquire the lock */ -+ spin_lock_irqsave (&desc->dvma_lock, flags); -+ } -+ -+ EPRINTF5 (DBG_KMAP, "%s: ep_dvma_calc_check_sum: nmh=%p idx=%x [%08x] paddr %llx\n", rail->Name, nmh, pgidx, -+ nmh->nmh_nmd.nmd_addr + (pgidx << PAGESHIFT), (long long) paddr); -+ } -+ -+ EPRINTF4 (DBG_KMAP, "ep_dvma_calc_check_sum: nmd=%08x.%08x.%08x = %d\n", nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr, check_sum); -+ -+ spin_unlock_irqrestore (&desc->dvma_lock, flags); -+ -+ return (check_sum); -+} -+#endif -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kmap_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kmap_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kmap_elan3.c 2005-06-01 23:12:54.670428312 -0400 -@@ -0,0 +1,209 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kmap_elan3.c,v 1.3.8.1 2004/12/14 10:19:14 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmap_elan3.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "kcomm_elan3.h" -+ -+#if defined(DIGITAL_UNIX) -+# define kernel_map (first_task->map) -+# define vaddr_to_phys(map, addr) (pmap_extract (vm_map_pmap ((vm_map_t) map), (unsigned long) addr)) -+#elif defined(LINUX) -+# define kernel_map get_kern_mm() -+# define vaddr_to_phys(map, addr) (kmem_to_phys(addr)) -+#elif defined(SOLARIS) -+# define kernel_map &kas -+# define vaddr_to_phys(map,addr) ptob(hat_getpfnum (((struct as *) map)->a_hat, (caddr_t) addr)) -+#endif -+ -+#define ELAN3_PTES_PER_PAGE (PAGESIZE/ELAN3_PAGE_SIZE) -+ -+#if defined(__LITTLE_ENDIAN__) -+#define PERM_ENDIAN 0 -+#else -+#define PERM_ENDIAN ELAN3_PTE_BIG_ENDIAN -+#endif -+ -+static unsigned int main_permtable[] = -+{ -+ ELAN3_PERM_REMOTEALL, /* EP_PERM_EXECUTE */ -+ ELAN3_PERM_REMOTEREAD, /* EP_PERM_READ */ -+ ELAN3_PERM_REMOTEWRITE, /* EP_PERM_WRITE */ -+ ELAN3_PERM_REMOTEWRITE, /* EP_PERM_ALL */ -+}; -+ -+static unsigned int sdram_permtable[] = -+{ -+ ELAN3_PERM_REMOTEREAD, /* EP_PERM_EXECUTE */ -+ ELAN3_PERM_REMOTEREAD, /* EP_PERM_READ */ -+ ELAN3_PERM_REMOTEWRITE, /* EP_PERM_WRITE */ -+ ELAN3_PERM_REMOTEALL, /* EP_PERM_ALL */ -+}; -+ -+static unsigned int io_permtable[] = -+{ -+ ELAN3_PERM_LOCAL_READ, /* EP_PERM_EXECUTE */ -+ ELAN3_PERM_REMOTEREAD, /* EP_PERM_READ */ -+ ELAN3_PERM_REMOTEWRITE, /* EP_PERM_WRITE */ -+ ELAN3_PERM_REMOTEWRITE, /* EP_PERM_ALL */ -+}; -+ -+void -+ep3_kaddr_map (EP_RAIL *r, EP_ADDR eaddr, virtaddr_t kaddr, unsigned len, unsigned int perm, int ep_attr) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ unsigned npages = len >> PAGESHIFT; -+ int i; -+ unsigned int off; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (kaddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ for (i = 0; i < npages; i++) -+ { -+ physaddr_t paddr = vaddr_to_phys (kernel_map, (void *) kaddr); -+ -+ for (off = 0; off < PAGESIZE; off += ELAN3_PAGE_SIZE) -+ elan3mmu_pteload (rail->Elan3mmu, PTBL_LEVEL_3, eaddr + off, paddr + off, -+ main_permtable[perm], PTE_LOAD_LOCK | PTE_LOAD_NOSYNC | ((ep_attr & EP_NO_SLEEP) ? PTE_NO_SLEEP : 0)); -+ -+ eaddr += PAGESIZE; -+ kaddr += PAGESIZE; -+ } -+} -+ -+void -+ep3_sdram_map (EP_RAIL *r, EP_ADDR eaddr, sdramaddr_t saddr, unsigned len, unsigned int perm, int ep_attr) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ unsigned npages = len >> PAGESHIFT; -+ int i; -+ unsigned int off; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (saddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ for (i = 0; i < npages; i++) -+ { -+ physaddr_t paddr = elan3_sdram_to_phys (rail->Device, saddr); -+ -+ for (off = 0; off < PAGESIZE; off += ELAN3_PAGE_SIZE) -+ elan3mmu_pteload (rail->Elan3mmu, PTBL_LEVEL_3, eaddr+off, paddr+off, -+ sdram_permtable[perm], PTE_LOAD_LOCK | PTE_LOAD_NOSYNC | ((ep_attr & EP_NO_SLEEP) ? PTE_NO_SLEEP : 0) ); -+ -+ eaddr += PAGESIZE; -+ saddr += PAGESIZE; -+ } -+} -+ -+void -+ep3_ioaddr_map (EP_RAIL *r, EP_ADDR eaddr, ioaddr_t ioaddr, unsigned len, unsigned int perm) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ unsigned npages = len >> PAGESHIFT; -+ int i; -+ unsigned int off; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (ioaddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ for (i = 0; i < npages; i++) -+ { -+ physaddr_t paddr = vaddr_to_phys (kernel_map, (void *) ioaddr); -+ -+ for (off = 0; off < PAGESIZE; off += ELAN3_PAGE_SIZE) -+ elan3mmu_pteload (rail->Elan3mmu, PTBL_LEVEL_3, eaddr + off, paddr + off, -+ io_permtable[perm], PTE_LOAD_LOCK | PTE_LOAD_NOSYNC); -+ -+ eaddr += PAGESIZE; -+ ioaddr += PAGESIZE; -+ } -+} -+void -+ep3_unmap (EP_RAIL *r, EP_ADDR eaddr, unsigned len) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ elan3mmu_unload (rail->Elan3mmu, eaddr, len, PTE_UNLOAD_UNLOCK | PTE_UNLOAD_NOSYNC); -+} -+ -+void * -+ep3_dvma_reserve (EP_RAIL *r, EP_ADDR eaddr, unsigned npages) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ void *private; -+ -+ KMEM_ALLOC (private, void *, npages * ELAN3_PTES_PER_PAGE * sizeof (sdramaddr_t), 1); -+ -+ if (private == NULL) -+ return NULL; -+ -+ elan3mmu_reserve (rail->Elan3mmu, eaddr, npages * ELAN3_PTES_PER_PAGE, (sdramaddr_t *) private); -+ -+ return private; -+} -+ -+void -+ep3_dvma_release (EP_RAIL *r, EP_ADDR eaddr, unsigned npages, void *private) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ -+ elan3mmu_release (rail->Elan3mmu, eaddr, npages * ELAN3_PTES_PER_PAGE, (sdramaddr_t *) private); -+ -+ KMEM_FREE (private, npages * ELAN3_PTES_PER_PAGE * sizeof (sdramaddr_t)); -+} -+ -+void -+ep3_dvma_set_pte (EP_RAIL *r, void *private, unsigned index, physaddr_t paddr, unsigned int perm) -+{ -+ ELAN3_DEV *dev = ((EP3_RAIL *) r)->Device; -+ sdramaddr_t *ptep = &((sdramaddr_t *) private)[index * ELAN3_PTES_PER_PAGE]; -+ int off; -+ -+ for (off =0 ; off < PAGESIZE; off += ELAN3_PAGE_SIZE) -+ { -+ ELAN3_PTE newpte = elan3mmu_phys_to_pte (dev, paddr + off, main_permtable[perm]) | ELAN3_PTE_REF | ELAN3_PTE_MOD; -+ -+ elan3_writepte (dev, *ptep, newpte); -+ -+ ptep++; -+ } -+} -+ -+physaddr_t -+ep3_dvma_read_pte (EP_RAIL *r, void *private, unsigned index) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ sdramaddr_t *ptep = &((sdramaddr_t *) private)[index * ELAN3_PTES_PER_PAGE]; -+ ELAN3_PTE pte = elan3_readpte (rail->Device, *ptep); -+ -+ return pte & ELAN3_PTE_PFN_MASK; -+} -+ -+void -+ep3_dvma_unload (EP_RAIL *r, void *private, unsigned index, unsigned npages) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ sdramaddr_t *ptep = &((sdramaddr_t *) private)[index * ELAN3_PTES_PER_PAGE]; -+ ELAN3_PTE tpte = elan3mmu_kernel_invalid_pte (rail->Elan3mmu); -+ int i; -+ -+ for (i = (npages * ELAN3_PTES_PER_PAGE) - 1; i >= 0; i--) -+ elan3_writepte (rail->Device, ptep[i], tpte); -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/kmap_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kmap_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kmap_elan4.c 2005-06-01 23:12:54.670428312 -0400 -@@ -0,0 +1,226 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kmap_elan4.c,v 1.7.8.2 2004/12/14 10:19:14 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmap_elan4.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "debug.h" -+#include "kcomm_elan4.h" -+ -+#if defined(DIGITAL_UNIX) -+# define kernel_map (first_task->map) -+# define vaddr_to_phys(map, addr) (pmap_extract (vm_map_pmap ((vm_map_t) map), (unsigned long) addr)) -+#elif defined(LINUX) -+# define kernel_map get_kern_mm() -+# define vaddr_to_phys(map, addr) (kmem_to_phys(addr)) -+#elif defined(SOLARIS) -+# define kernel_map &kas -+# define vaddr_to_phys(map,addr) ptob(hat_getpfnum (((struct as *) map)->a_hat, (caddr_t) addr)) -+#endif -+ -+static unsigned int main_permtable[] = -+{ -+ PERM_Unused, /* EP_PERM_EXECUTE */ -+ PERM_RemoteReadOnly, /* EP_PERM_READ */ -+ PERM_DataReadWrite, /* EP_PERM_WRITE */ -+ PERM_DataReadWrite, /* EP_PERM_ALL */ -+}; -+ -+static unsigned int sdram_permtable[] = -+{ -+ PERM_LocExecute, /* EP_PERM_EXECUTE */ -+ PERM_RemoteReadOnly, /* EP_PERM_READ */ -+ PERM_DataReadWrite, /* EP_PERM_WRITE */ -+ PERM_RemoteAll, /* EP_PERM_ALL */ -+}; -+ -+static unsigned int io_permtable[] = -+{ -+ PERM_Unused, /* EP_PERM_EXECUTE */ -+ PERM_RemoteReadOnly, /* EP_PERM_READ */ -+ PERM_DataReadWrite, /* EP_PERM_WRITE */ -+ PERM_Unused, /* EP_PERM_ALL */ -+}; -+ -+void -+ep4_kaddr_map (EP_RAIL *r, EP_ADDR eaddr, virtaddr_t kaddr, unsigned int len, unsigned int perm, int ep_attr) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned int npages = len >> PAGESHIFT; -+ int i; -+ unsigned int off; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (kaddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ for (i = 0; i < npages; i++) -+ { -+ physaddr_t paddr = vaddr_to_phys (kernel_map, (void *) kaddr); -+ -+ for (off = 0; off < PAGESIZE; off += (1 << dev->dev_pageshift[0])) -+ { -+ E4_uint64 newpte = elan4mmu_phys2pte (dev, paddr + off, main_permtable[perm]); -+ -+ elan4mmu_pteload (&rail->r_ctxt, 0, eaddr + off, newpte); -+ } -+ -+ eaddr += PAGESIZE; -+ kaddr += PAGESIZE; -+ } -+} -+ -+void -+ep4_sdram_map (EP_RAIL *r, EP_ADDR eaddr, sdramaddr_t saddr, unsigned int len, unsigned int perm, int ep_attr) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned int npages = len >> PAGESHIFT; -+ int i; -+ unsigned int off; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (saddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ if ((eaddr & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT)) != (saddr & (SDRAM_PGOFF_OFFSET << PAGE_SHIFT))) -+ printk ("ep4_sdram_map: eaddr=%x saddr=%lx - incorrectly alised\n", eaddr, saddr); -+ -+ for (i = 0; i < npages; i++) -+ { -+ for (off = 0; off < PAGESIZE; off += (1 << dev->dev_pageshift[0])) -+ { -+ E4_uint64 newpte = ((saddr + off) >> PTE_PADDR_SHIFT) | PTE_SetPerm (sdram_permtable[perm]); -+ -+ elan4mmu_pteload (&rail->r_ctxt, 0, eaddr + off, newpte); -+ } -+ -+ eaddr += PAGESIZE; -+ saddr += PAGESIZE; -+ } -+} -+ -+void -+ep4_ioaddr_map (EP_RAIL *r, EP_ADDR eaddr, ioaddr_t ioaddr, unsigned int len, unsigned int perm) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned int npages = len >> PAGESHIFT; -+ int i; -+ unsigned int off; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (ioaddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ for (i = 0; i < npages; i++) -+ { -+ physaddr_t paddr = vaddr_to_phys (kernel_map, (void *) ioaddr); -+ -+ for (off = 0; off < PAGESIZE; off += (1 << dev->dev_pageshift[0])) -+ { -+ E4_uint64 newpte = elan4mmu_phys2pte (dev, paddr + off, io_permtable[perm]); -+ -+ elan4mmu_pteload (&rail->r_ctxt, 0, eaddr + off, newpte); -+ } -+ -+ eaddr += PAGESIZE; -+ ioaddr += PAGESIZE; -+ } -+} -+void -+ep4_unmap (EP_RAIL *r, EP_ADDR eaddr, unsigned int len) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ ASSERT ((eaddr & PAGEOFFSET) == 0 && (len & PAGEOFFSET) == 0); -+ -+ elan4mmu_unload_range (&rail->r_ctxt, 0, eaddr, len); -+} -+ -+void * -+ep4_dvma_reserve (EP_RAIL *r, EP_ADDR eaddr, unsigned int npages) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ -+ EPRINTF3 (DBG_KMAP, "ep4_dvma_reserve: eaddr=%x npages=%d (=> %d)\n", eaddr, npages, (npages << (PAGE_SHIFT - dev->dev_pageshift[0]))); -+ -+ return elan4mmu_reserve (&rail->r_ctxt, 0, (E4_Addr) eaddr, (npages << (PAGE_SHIFT - dev->dev_pageshift[0])), 0); -+} -+ -+void -+ep4_dvma_release (EP_RAIL *r, EP_ADDR eaddr, unsigned int npages, void *private) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ EPRINTF3 (DBG_KMAP, "ep4_dvma_release: eaddr=%x npages=%d private=%p\n", eaddr, npages, private); -+ -+ elan4mmu_release (&rail->r_ctxt, (ELAN4_HASH_CACHE *) private); -+} -+ -+void -+ep4_dvma_set_pte (EP_RAIL *r, void *private, unsigned int index, physaddr_t paddr, unsigned int perm) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ unsigned int off; -+ unsigned long flags; -+ -+ EPRINTF3 (DBG_KMAP, "ep4_dvma_set_pte: index %x -> eaddr %llx paddr %llx\n", -+ index, ((ELAN4_HASH_CACHE *) private)->hc_start + (index * PAGE_SIZE), (long long) paddr); -+ -+ local_irq_save (flags); -+ for (off = 0; off < PAGESIZE; off += (1 << dev->dev_pageshift[0])) -+ { -+ E4_uint64 newpte = elan4mmu_phys2pte (dev, paddr + off, main_permtable[perm]); -+ -+ elan4mmu_set_pte (&rail->r_ctxt, (ELAN4_HASH_CACHE *) private, (index << (PAGE_SHIFT - dev->dev_pageshift[0])) + -+ (off >> dev->dev_pageshift[0]), newpte); -+ } -+ local_irq_restore (flags); -+} -+ -+physaddr_t -+ep4_dvma_read_pte (EP_RAIL *r, void *private, unsigned int index) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ E4_uint64 pte; -+ unsigned long flags; -+ -+ local_irq_save (flags); -+ pte = elan4mmu_get_pte (&rail->r_ctxt, (ELAN4_HASH_CACHE *) private, index << (PAGE_SHIFT - dev->dev_pageshift[0])); -+ local_irq_restore (flags); -+ -+ return elan4mmu_pte2phys (dev, pte); -+} -+ -+void -+ep4_dvma_unload (EP_RAIL *r, void *private, unsigned int index, unsigned int npages) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ EP_ADDR eaddr = ((ELAN4_HASH_CACHE *) private)->hc_start + (index * PAGE_SIZE); -+ unsigned long idx = (index << (PAGE_SHIFT - dev->dev_pageshift[0])); -+ unsigned long lim = idx + (npages << (PAGE_SHIFT - dev->dev_pageshift[0])); -+ unsigned long flags; -+ -+ EPRINTF5 (DBG_KMAP, "ep4_dvma_unload: eaddr %x -> %lx : index=%d idx=%ld lim=%ld\n", -+ eaddr, (unsigned long)(eaddr + (npages * PAGE_SIZE)), index, idx, lim); -+ -+ local_irq_save (flags); -+ for (; idx < lim; idx++) -+ elan4mmu_clear_pte (&rail->r_ctxt, (ELAN4_HASH_CACHE *) private, idx); -+ local_irq_restore (flags); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kmsg_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kmsg_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kmsg_elan3.c 2005-06-01 23:12:54.671428160 -0400 -@@ -0,0 +1,345 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kmsg_elan3.c,v 1.3.8.1 2004/09/30 09:52:37 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmsg_elan3.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "debug.h" -+ -+static void -+ep3_inputq_event (EP3_RAIL *rail, void *arg) -+{ -+ EP3_INPUTQ *inputq = (EP3_INPUTQ *) arg; -+ -+ (*inputq->q_callback)((EP_RAIL *)rail, inputq->q_arg); -+} -+ -+static EP3_COOKIE_OPS ep3_inputq_cookie_ops = -+{ -+ ep3_inputq_event, -+}; -+ -+EP_INPUTQ * -+ep3_alloc_inputq (EP_RAIL *r, unsigned qnum, unsigned slotSize, unsigned slotCount, -+ EP_INPUTQ_CALLBACK *callback, void *arg) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_INPUTQ *inputq; -+ EP3_InputQueue qdesc; -+ void *slots; -+ int i; -+ -+ ASSERT ((slotSize & (EP_SYSTEMQ_MSG_ALIGN-1)) == 0); -+ -+ KMEM_ALLOC (inputq, EP3_INPUTQ *, sizeof (EP3_INPUTQ), TRUE); -+ -+ if (inputq == NULL) -+ return (EP_INPUTQ *) NULL; -+ -+ if ((slots = ep_alloc_main (&rail->Generic, slotSize * slotCount, 0, &inputq->q_slotsAddr)) == NULL) -+ { -+ KMEM_FREE (inputq, sizeof (EP3_INPUTQ)); -+ return (EP_INPUTQ *) NULL; -+ } -+ -+ inputq->q_slotSize = slotSize; -+ inputq->q_slotCount = slotCount; -+ inputq->q_callback = callback; -+ inputq->q_arg = arg; -+ inputq->q_slots = slots; -+ -+ /* Initialise all the slots to be "unreceived" */ -+ for (i = 0; i < slotCount; i++) -+ ((uint32_t *) ((unsigned long) slots + (i+1) * slotSize))[-1] = EP_SYSTEMQ_UNRECEIVED; -+ -+ inputq->q_base = inputq->q_slotsAddr; -+ inputq->q_top = inputq->q_base + (slotCount-1) * slotSize; -+ inputq->q_fptr = inputq->q_base; -+ inputq->q_desc = EP_SYSTEMQ_DESC(rail->QueueDescs, qnum); -+ inputq->q_descAddr = EP_SYSTEMQ_ADDR (qnum); -+ -+ if (callback) -+ RegisterCookie (&rail->CookieTable, &inputq->q_cookie, inputq->q_descAddr, &ep3_inputq_cookie_ops, inputq); -+ -+ /* Initialise the input queue descriptor */ -+ qdesc.q_state = E3_QUEUE_FULL; -+ qdesc.q_bptr = inputq->q_base + slotSize; -+ qdesc.q_fptr = inputq->q_fptr; -+ qdesc.q_base = inputq->q_base; -+ qdesc.q_top = inputq->q_top; -+ qdesc.q_size = slotSize; -+ qdesc.q_event.ev_Count = 1; -+ qdesc.q_event.ev_Type = callback ? EV_TYPE_EVIRQ | inputq->q_cookie.Cookie : 0; -+ qdesc.q_wevent = inputq->q_descAddr + offsetof (EP3_InputQueue, q_event); -+ qdesc.q_wcount = 0; -+ -+ /* copy the queue descriptor down to sdram */ -+ elan3_sdram_copyl_to_sdram (rail->Device, &qdesc, inputq->q_desc, sizeof (EP3_InputQueue)); -+ -+ return (EP_INPUTQ *) inputq; -+} -+ -+void -+ep3_free_inputq (EP_RAIL *r, EP_INPUTQ *q) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_INPUTQ *inputq = (EP3_INPUTQ *) q; -+ -+ ep_free_main (&rail->Generic, inputq->q_slotsAddr, inputq->q_slotSize * inputq->q_slotCount); -+ -+ if (inputq->q_callback) -+ DeregisterCookie (&rail->CookieTable, &inputq->q_cookie); -+ -+ KMEM_FREE (inputq, sizeof (EP3_INPUTQ)); -+} -+ -+void -+ep3_enable_inputq (EP_RAIL *r, EP_INPUTQ *q) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_INPUTQ *inputq = (EP3_INPUTQ *) q; -+ -+ elan3_sdram_writel (rail->Device, inputq->q_desc + offsetof (EP3_InputQueue, q_state), 0); -+} -+ -+void -+ep3_disable_inputq (EP_RAIL *r, EP_INPUTQ *q) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_INPUTQ *inputq = (EP3_INPUTQ *) q; -+ EP3_InputQueue qdesc; -+ -+ /* mark the queue as locked */ -+ SetQueueLocked (rail, inputq->q_desc); -+ -+ /* re-initialise the queue as empty */ -+ qdesc.q_state = E3_QUEUE_FULL; -+ qdesc.q_bptr = (E3_Addr) inputq->q_base + inputq->q_slotSize; -+ qdesc.q_fptr = inputq->q_fptr; -+ qdesc.q_base = inputq->q_base; -+ qdesc.q_top = inputq->q_top; -+ qdesc.q_size = inputq->q_slotSize; -+ qdesc.q_event.ev_Count = 1; -+ qdesc.q_event.ev_Type = inputq->q_callback ? EV_TYPE_EVIRQ | inputq->q_cookie.Cookie : 0; -+ qdesc.q_wevent = inputq->q_descAddr + offsetof (EP3_InputQueue, q_event); -+ qdesc.q_wcount = 0; -+ -+ /* copy the queue descriptor down to sdram */ -+ elan3_sdram_copyl_to_sdram (rail->Device, &qdesc, inputq->q_desc, sizeof (EP3_InputQueue)); -+} -+ -+int -+ep3_poll_inputq (EP_RAIL *r, EP_INPUTQ *q, int maxCount, EP_INPUTQ_HANDLER *handler, void *arg) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_INPUTQ *inputq = (EP3_INPUTQ *) q; -+ sdramaddr_t qdesc = inputq->q_desc; -+ E3_Addr nfptr; -+ int count = 0; -+ E3_uint32 state; -+ int delay; -+ -+ run_again_because_of_eventqueue_overflow: -+ nfptr = inputq->q_fptr + inputq->q_slotSize; -+ if (nfptr > inputq->q_top) -+ nfptr = inputq->q_base; -+ -+ while (nfptr != elan3_sdram_readl (rail->Device, qdesc + offsetof (EP3_InputQueue, q_bptr))) /* PCI read */ -+ { -+ unsigned long slot = (unsigned long) inputq->q_slots + (nfptr - inputq->q_base); -+ -+ /* Poll the final word of the message until the message has completely -+ * arrived in main memory. */ -+ for (delay = 1; ((uint32_t *) (slot + inputq->q_slotSize))[-1] == EP_SYSTEMQ_UNRECEIVED && delay < EP_SYSTEMQ_UNRECEIVED_TLIMIT; delay <<= 1) -+ DELAY (delay); -+ -+ /* Call the message handler */ -+ (*handler) (r, arg, (void *) slot); -+ -+ state = elan3_sdram_readl (rail->Device, qdesc + offsetof (EP3_InputQueue, q_state)); /* PCI read */ -+ if ((state & E3_QUEUE_FULL) == 0) -+ elan3_sdram_writel (rail->Device, qdesc + offsetof (EP3_InputQueue, q_fptr), nfptr); /* PCI write */ -+ else -+ { -+ elan3_sdram_writel (rail->Device, qdesc + offsetof (EP3_InputQueue, q_fptr), nfptr); /* PCI write */ -+ elan3_sdram_writel (rail->Device, qdesc + offsetof (EP3_InputQueue, q_state), (state & ~E3_QUEUE_FULL)); /* PCI write */ -+ } -+ inputq->q_fptr = nfptr; -+ -+ nfptr += roundup (inputq->q_slotSize, E3_BLK_ALIGN); -+ if (nfptr > inputq->q_top) -+ nfptr = inputq->q_base; -+ -+ if (++count >= maxCount && maxCount) -+ break; -+ } -+ -+ if (inputq->q_callback && count != 0) -+ { -+ if (count != inputq->q_waitCount) -+ elan3_sdram_writel (rail->Device, qdesc + offsetof (EP3_InputQueue, q_wcount), inputq->q_waitCount = count); -+ -+ if (IssueWaitevent (rail, inputq->q_descAddr + offsetof (EP3_InputQueue, q_wevent)) == ISSUE_COMMAND_TRAPPED) -+ goto run_again_because_of_eventqueue_overflow; -+ } -+ -+ return count; -+} -+ -+#define Q_EVENT(q,slotNum) ((q)->q_elan + (slotNum) * sizeof (E3_BlockCopyEvent)) -+#define Q_EVENT_ADDR(q,slotNum) ((q)->q_elanAddr + (slotNum) * sizeof (E3_BlockCopyEvent)) -+#define Q_MSG(q,slotNum) (void *)((q)->q_main + (slotNum) * (q)->q_slotSize) -+#define Q_MSG_ADDR(q,slotNum) ((q)->q_mainAddr + (slotNum) * (q)->q_slotSize) -+#define Q_DONE(q,slotNum) (*((int *)((q)->q_main + (q)->q_slotCount * (q)->q_slotSize + (slotNum) * sizeof (E3_uint32)))) -+#define Q_DONE_ADDR(q,slotNum) ((q)->q_mainAddr + (q)->q_slotCount * (q)->q_slotSize + (slotNum) * sizeof (E3_uint32)) -+ -+#define Q_ELAN_SIZE(q) ((q)->q_slotCount * sizeof (E3_BlockCopyEvent)) -+#define Q_MAIN_SIZE(q) ((q)->q_slotCount * ((q)->q_slotSize + sizeof (E3_uint32))) -+ -+static void -+ep3_outputq_retry (EP3_RAIL *rail, void *arg, E3_DMA_BE *dma, int error) -+{ -+ E3_DMA_BE *dmabe = (E3_DMA_BE *) dma; -+ sdramaddr_t event = ep_elan2sdram (&rail->Generic, dmabe->s.dma_srcEvent); -+ E3_Addr done = elan3_sdram_readl (rail->Device, event + offsetof (E3_BlockCopyEvent, ev_Dest)); -+ E3_uint32 *donep = ep_elan2main (&rail->Generic, done & ~EV_BCOPY_DTYPE_MASK); -+ -+ EPRINTF1 (DBG_KMSG, "ep3_ouputq_retry: donep at %p -> FAILED\n", donep); -+ -+ *donep = EP3_EVENT_FAILED; -+} -+ -+static EP3_COOKIE_OPS ep3_outputq_cookie_ops = -+{ -+ NULL, /* Event */ -+ ep3_outputq_retry, -+ NULL, /* DmaCancelled */ -+ NULL, /* DmaVerify */ -+}; -+ -+EP_OUTPUTQ * -+ep3_alloc_outputq (EP_RAIL *r, unsigned slotSize, unsigned slotCount) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_OUTPUTQ *outputq; -+ int i; -+ E3_BlockCopyEvent event; -+ -+ ASSERT ((slotSize & (EP_SYSTEMQ_MSG_ALIGN-1)) == 0); -+ -+ KMEM_ALLOC (outputq, EP3_OUTPUTQ *, sizeof (EP3_OUTPUTQ), 1); -+ -+ if (outputq == NULL) -+ return NULL; -+ -+ outputq->q_slotCount = slotCount; -+ outputq->q_slotSize = slotSize; -+ -+ outputq->q_elan = ep_alloc_elan (r, Q_ELAN_SIZE(outputq), 0, &outputq->q_elanAddr); -+ -+ if (outputq->q_elan == (sdramaddr_t) 0) -+ { -+ KMEM_FREE (outputq, sizeof (EP3_OUTPUTQ)); -+ return NULL; -+ } -+ -+ outputq->q_main = ep_alloc_main (r, Q_MAIN_SIZE(outputq), 0, &outputq->q_mainAddr); -+ -+ if (outputq->q_main == (void *) NULL) -+ { -+ ep_free_elan (r, outputq->q_elanAddr, Q_ELAN_SIZE(outputq)); -+ KMEM_FREE (outputq, sizeof (EP3_OUTPUTQ)); -+ return NULL; -+ } -+ -+ RegisterCookie (&rail->CookieTable, &outputq->q_cookie, outputq->q_elanAddr, &ep3_outputq_cookie_ops, outputq); -+ -+ for (i = 0; i < slotCount; i++) -+ { -+ EP3_INIT_COPY_EVENT (event, outputq->q_cookie, Q_DONE_ADDR(outputq, i), 0); -+ -+ Q_DONE(outputq, i) = outputq->q_cookie.Cookie; -+ -+ elan3_sdram_copyl_to_sdram (rail->Device, &event, Q_EVENT(outputq, i), sizeof (E3_BlockCopyEvent)); -+ } -+ -+ return (EP_OUTPUTQ *) outputq; -+} -+ -+void -+ep3_free_outputq (EP_RAIL *r, EP_OUTPUTQ *q) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_OUTPUTQ *outputq = (EP3_OUTPUTQ *) q; -+ -+ DeregisterCookie (&rail->CookieTable, &outputq->q_cookie); -+ -+ ep_free_main (r, outputq->q_mainAddr, Q_MAIN_SIZE(outputq)); -+ ep_free_elan (r, outputq->q_elanAddr, Q_ELAN_SIZE(outputq)); -+ -+ KMEM_FREE (outputq, sizeof (EP3_OUTPUTQ)); -+} -+ -+void * -+ep3_outputq_msg (EP_RAIL *r, EP_OUTPUTQ *q, unsigned slotNum) -+{ -+ return Q_MSG ((EP3_OUTPUTQ *) q, slotNum); -+} -+ -+int -+ep3_outputq_state (EP_RAIL *r, EP_OUTPUTQ *q, unsigned slotNum) -+{ -+ switch (Q_DONE((EP3_OUTPUTQ *) q, slotNum)) -+ { -+ case EP3_EVENT_ACTIVE: -+ return EP_OUTPUTQ_BUSY; -+ -+ case EP3_EVENT_FAILED: -+ return EP_OUTPUTQ_FAILED; -+ -+ default: -+ return EP_OUTPUTQ_FINISHED; -+ } -+} -+ -+int -+ep3_outputq_send (EP_RAIL *r, EP_OUTPUTQ *q, unsigned slotNum, unsigned size, -+ unsigned vp, unsigned qnum, unsigned retries) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_OUTPUTQ *outputq = (EP3_OUTPUTQ *) q; -+ unsigned base = outputq->q_slotSize - roundup (size, E3_BLK_ALIGN); -+ E3_DMA_BE dmabe; -+ -+ dmabe.s.dma_type = E3_DMA_TYPE(DMA_BYTE, DMA_WRITE, DMA_QUEUED, retries); -+ dmabe.s.dma_size = roundup (size, E3_BLK_ALIGN); -+ dmabe.s.dma_source = Q_MSG_ADDR(outputq, slotNum) + base; -+ dmabe.s.dma_dest = base; -+ dmabe.s.dma_destEvent = EP_SYSTEMQ_ADDR(qnum); -+ dmabe.s.dma_destCookieVProc = vp; -+ dmabe.s.dma_srcEvent = Q_EVENT_ADDR(outputq, slotNum); -+ dmabe.s.dma_srcCookieVProc = 0; -+ -+ Q_DONE(outputq, slotNum) = EP3_EVENT_ACTIVE; -+ -+ elan3_sdram_writel (rail->Device, Q_EVENT(outputq, slotNum), 1); -+ -+ if (IssueDma (rail, &dmabe, EP_RETRY_CRITICAL, FALSE) != ISSUE_COMMAND_OK) -+ { -+ Q_DONE(outputq, slotNum) = EP3_EVENT_FAILED; -+ return FALSE; -+ } -+ -+ return TRUE; -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/kmsg_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kmsg_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kmsg_elan4.c 2005-06-01 23:12:54.672428008 -0400 -@@ -0,0 +1,416 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kmsg_elan4.c,v 1.8.6.1 2004/09/30 09:52:37 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmsg_elan4.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "debug.h" -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+ -+#include -+ -+static void -+ep4_inputq_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ EP4_INPUTQ *inputq = (EP4_INPUTQ *) arg; -+ -+ /* mark the queue as "fired" to cause a single waitevent -+ * to be issued next time the queue is polled */ -+ atomic_inc (&inputq->q_fired); -+ -+ (*inputq->q_callback)(&rail->r_generic, inputq->q_arg); -+} -+ -+EP_INPUTQ * -+ep4_alloc_inputq (EP_RAIL *r, unsigned qnum, unsigned slotSize, unsigned slotCount, -+ EP_INPUTQ_CALLBACK *callback, void *arg) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_INPUTQ *inputq; -+ E4_Event32 qevent; -+ void *slots; -+ int i; -+ -+ ASSERT ((slotSize & (EP_SYSTEMQ_MSG_ALIGN-1)) == 0); -+ -+ KMEM_ALLOC (inputq, EP4_INPUTQ *, sizeof (EP4_INPUTQ), 1); -+ -+ if (inputq == NULL) -+ return (EP_INPUTQ *) NULL; -+ -+ if ((slots = ep_alloc_main (&rail->r_generic, slotSize * slotCount, 0, &inputq->q_slotsAddr)) == NULL) -+ { -+ KMEM_FREE (inputq, sizeof (EP4_INPUTQ)); -+ return (EP_INPUTQ *) NULL; -+ } -+ -+ inputq->q_slotSize = slotSize; -+ inputq->q_slotCount = slotCount; -+ inputq->q_callback = callback; -+ inputq->q_arg = arg; -+ inputq->q_slots = slots; -+ -+ /* Initialise all the slots to be "unreceived" */ -+ for (i = 0; i < slotCount; i++) -+ ((uint32_t *) ((unsigned long) slots + (i+1) * slotSize))[-1] = EP_SYSTEMQ_UNRECEIVED; -+ -+ inputq->q_last = inputq->q_slotsAddr + (slotCount-1) * slotSize; -+ inputq->q_fptr = inputq->q_slotsAddr; -+ inputq->q_desc = EP_SYSTEMQ_DESC (rail->r_queuedescs, qnum); -+ inputq->q_descAddr = EP_SYSTEMQ_ADDR (qnum); -+ inputq->q_eventAddr = rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_qevents[qnum]); -+ -+ if (callback) -+ { -+ if ((inputq->q_ecq = ep4_get_ecq (rail, EP4_ECQ_EVENT, 1)) == 0) -+ { -+ ep_free_main (&rail->r_generic, inputq->q_slotsAddr, inputq->q_slotSize * inputq->q_slotCount); -+ -+ KMEM_FREE (inputq, sizeof (EP4_INPUTQ)); -+ return (EP_INPUTQ *) NULL; -+ } -+ -+ if ((inputq->q_wcq = ep4_get_ecq (rail, EP4_ECQ_MAIN, 4)) == 0) -+ { -+ ep4_put_ecq (rail, inputq->q_ecq, 1); -+ ep_free_main (&rail->r_generic, inputq->q_slotsAddr, inputq->q_slotSize * inputq->q_slotCount); -+ -+ KMEM_FREE (inputq, sizeof (EP4_INPUTQ)); -+ return (EP_INPUTQ *) NULL; -+ } -+ -+ ep4_register_intcookie (rail, &inputq->q_intcookie, inputq->q_descAddr, ep4_inputq_interrupt, inputq); -+ -+ inputq->q_count = 0; -+ -+ atomic_set (&inputq->q_fired, 0); -+ -+ /* Initialise the queue event */ -+ qevent.ev_CountAndType = E4_EVENT_INIT_VALUE (callback ? -32 : 0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0); -+ qevent.ev_WritePtr = inputq->q_ecq->ecq_addr; -+ qevent.ev_WriteValue = (inputq->q_intcookie.int_val << E4_MAIN_INT_SHIFT) | INTERRUPT_CMD; -+ } -+ -+ /* copy the event down to sdram */ -+ elan4_sdram_copyq_to_sdram (rail->r_ctxt.ctxt_dev, &qevent, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_qevents[qnum]), sizeof (E4_Event32)); -+ -+ return (EP_INPUTQ *) inputq; -+} -+ -+void -+ep4_free_inputq (EP_RAIL *r, EP_INPUTQ *q) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_INPUTQ *inputq = (EP4_INPUTQ *) q; -+ -+ ep_free_main (&rail->r_generic, inputq->q_slotsAddr, inputq->q_slotSize * inputq->q_slotCount); -+ -+ if (inputq->q_callback) -+ { -+ ep4_deregister_intcookie (rail, &inputq->q_intcookie); -+ ep4_put_ecq (rail, inputq->q_ecq, 1); -+ ep4_put_ecq (rail, inputq->q_wcq, 4); -+ } -+ -+ KMEM_FREE (inputq, sizeof (EP4_INPUTQ)); -+} -+ -+void -+ep4_enable_inputq (EP_RAIL *r, EP_INPUTQ *q) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_INPUTQ *inputq = (EP4_INPUTQ *) q; -+ EP_ADDR lastSlot = inputq->q_slotsAddr + (inputq->q_slotCount-1) * inputq->q_slotSize; -+ E4_InputQueue qdesc; -+ -+ qdesc.q_bptr = inputq->q_slotsAddr; -+ qdesc.q_fptr = inputq->q_slotsAddr; -+ qdesc.q_control = E4_InputQueueControl (inputq->q_slotsAddr, lastSlot, inputq->q_slotSize); -+ qdesc.q_event = inputq->q_callback ? inputq->q_eventAddr : 0; -+ -+ /* copy the queue descriptor down to sdram */ -+ ep4_write_qdesc (rail, inputq->q_desc, &qdesc); -+ -+ EPRINTF5 (DBG_KMSG, "ep_enable_inputq: %x - %016llx %016llx %016llx %016llx\n", (int) inputq->q_descAddr, -+ elan4_sdram_readq (rail->r_ctxt.ctxt_dev, inputq->q_desc + 0), -+ elan4_sdram_readq (rail->r_ctxt.ctxt_dev, inputq->q_desc + 8), -+ elan4_sdram_readq (rail->r_ctxt.ctxt_dev, inputq->q_desc + 16), -+ elan4_sdram_readq (rail->r_ctxt.ctxt_dev, inputq->q_desc + 24)); -+} -+ -+void -+ep4_disable_inputq (EP_RAIL *r, EP_INPUTQ *q) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_INPUTQ *inputq = (EP4_INPUTQ *) q; -+ E4_InputQueue qdesc; -+ -+ /* Initialise the input queue descriptor as "full" with no event */ -+ qdesc.q_bptr = 0; -+ qdesc.q_fptr = 8; -+ qdesc.q_control = E4_InputQueueControl(qdesc.q_bptr, qdesc.q_fptr, 8); -+ qdesc.q_event = 0; -+ -+ /* copy the queue descriptor down to sdram */ -+ ep4_write_qdesc (rail, inputq->q_desc, &qdesc); -+} -+ -+int -+ep4_poll_inputq (EP_RAIL *r, EP_INPUTQ *q, int maxCount, EP_INPUTQ_HANDLER *handler, void *arg) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ EP4_INPUTQ *inputq = (EP4_INPUTQ *) q; -+ sdramaddr_t qdesc = inputq->q_desc; -+ E4_Addr fptr = inputq->q_fptr; -+ E4_Addr bptr = elan4_sdram_readl (dev, qdesc + offsetof (E4_InputQueue, q_bptr)); -+ int count = 0; -+ int delay; -+ -+ while (bptr != 0 && fptr != bptr) -+ { -+ while (fptr != bptr) -+ { -+ unsigned long slot = (unsigned long) inputq->q_slots + (fptr - inputq->q_slotsAddr); -+ -+ /* Poll the final word of the message until the message has completely -+ * arrived in main memory. */ -+ for (delay = 1; ((uint32_t *) (slot + inputq->q_slotSize))[-1] == EP_SYSTEMQ_UNRECEIVED && delay < EP_SYSTEMQ_UNRECEIVED_TLIMIT; delay <<= 1) -+ DELAY (delay); -+ -+ EPRINTF4(DBG_KMSG, "ep4_poll_inputq: %x slot %d of %d [%08x]\n", (int)inputq->q_descAddr, -+ ((int)(fptr - inputq->q_slotsAddr))/inputq->q_slotSize, -+ inputq->q_slotCount, ((uint32_t *) (slot + inputq->q_slotSize))[-1]); -+ -+ /* Call the message handler */ -+ (*handler) (r, arg, (void *) slot); -+ -+ /* reset the last word of the slot to "unreceived" */ -+ ((uint32_t *) (slot + inputq->q_slotSize))[-1] = EP_SYSTEMQ_UNRECEIVED; -+ -+ /* move on the front pointer */ -+ fptr = (fptr == inputq->q_last) ? inputq->q_slotsAddr : fptr + inputq->q_slotSize; -+ -+ elan4_sdram_writel (dev, qdesc + offsetof (E4_InputQueue, q_fptr), fptr); -+ -+ inputq->q_count++; -+ -+ if (++count >= maxCount && maxCount) -+ { -+ inputq->q_fptr = fptr; -+ -+ return count; -+ } -+ } -+ -+ bptr = elan4_sdram_readl (dev, qdesc + offsetof (E4_InputQueue, q_bptr)); -+ } -+ -+ inputq->q_fptr = fptr; -+ -+ /* Only insert a single wait event command if the callback has -+ * occured, otherwise just acrue the count as we've just periodically -+ * polled it. -+ */ -+ if (inputq->q_callback && atomic_read (&inputq->q_fired)) -+ { -+ atomic_dec (&inputq->q_fired); -+ -+ ep4_wait_event_cmd (inputq->q_wcq, inputq->q_eventAddr, -+ E4_EVENT_INIT_VALUE (-inputq->q_count << 5, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0), -+ inputq->q_ecq->ecq_addr, -+ (inputq->q_intcookie.int_val << E4_MAIN_INT_SHIFT) | INTERRUPT_CMD); -+ -+ inputq->q_count = 0; -+ } -+ -+ return count; -+} -+ -+#define Q_MSG(q,slotNum) (unsigned long)((q)->q_main + (slotNum) * (q)->q_slotSize) -+#define Q_MSG_ADDR(q,slotNum) ((q)->q_mainAddr + (slotNum) * (q)->q_slotSize) -+#define Q_DONE(q,slotNum) *((E4_uint64 *)((q)->q_main + (q)->q_slotCount * (q)->q_slotSize + (slotNum) * sizeof (E4_uint64))) -+#define Q_DONE_ADDR(q,slotNum) ((q)->q_mainAddr + (q)->q_slotCount * (q)->q_slotSize + (slotNum) * sizeof (E4_uint64)) -+ -+#define Q_MAIN_SIZE(q) ((q)->q_slotCount * ((q)->q_slotSize + sizeof (E4_uint64))) -+ -+#define Q_DONE_VAL(val,cnt) ((cnt) << 16 | (val)) -+#define Q_DONE_RET(done) ((int) ((done) & 0xffff)) -+#define Q_DONE_CNT(done) ((int) ((done) >> 16)) -+ -+EP_OUTPUTQ * -+ep4_alloc_outputq (EP_RAIL *r, unsigned slotSize, unsigned slotCount) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_OUTPUTQ *outputq; -+ int i; -+ -+ ASSERT ((slotSize & (EP_SYSTEMQ_MSG_ALIGN-1)) == 0); -+ -+ KMEM_ALLOC (outputq, EP4_OUTPUTQ *, sizeof (EP4_OUTPUTQ), 1); -+ -+ if (outputq == NULL) -+ return NULL; -+ -+ spin_lock_init (&outputq->q_lock); -+ -+ outputq->q_slotCount = slotCount; -+ outputq->q_slotSize = slotSize; -+ outputq->q_main = ep_alloc_main (r, Q_MAIN_SIZE(outputq), 0, &outputq->q_mainAddr); -+ -+ if (outputq->q_main == (E4_uint64 *) NULL) -+ { -+ KMEM_FREE (outputq, sizeof (EP_OUTPUTQ)); -+ return NULL; -+ } -+ -+ outputq->q_cq = elan4_alloccq (&rail->r_ctxt, CQ_Size64K, CQ_STENEnableBit | CQ_WriteEnableBit, CQ_Priority); -+ -+ if (outputq->q_cq == (ELAN4_CQ *) NULL) -+ { -+ ep_free_main (&rail->r_generic, outputq->q_mainAddr, Q_MAIN_SIZE(outputq)); -+ -+ KMEM_FREE (outputq, sizeof (EP_OUTPUTQ)); -+ } -+ -+ outputq->q_dwords = CQ_Size (outputq->q_cq->cq_size) >> 3; -+ -+ /* mark all the queue slots as finished */ -+ for (i = 0; i < slotCount; i++) -+ Q_DONE(outputq, i) = Q_DONE_VAL (EP_OUTPUTQ_FINISHED, 0); -+ -+ return (EP_OUTPUTQ *) outputq; -+} -+ -+void -+ep4_free_outputq (EP_RAIL *r, EP_OUTPUTQ *q) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_OUTPUTQ *outputq = (EP4_OUTPUTQ *) q; -+ -+ elan4_freecq (&rail->r_ctxt, outputq->q_cq); -+ -+ ep_free_main (&rail->r_generic, outputq->q_mainAddr, Q_MAIN_SIZE(outputq)); -+ -+ spin_lock_destroy (&outputq->q_lock); -+ -+ KMEM_FREE (outputq, sizeof (EP4_OUTPUTQ)); -+} -+ -+void * -+ep4_outputq_msg (EP_RAIL *r, EP_OUTPUTQ *q, unsigned slotNum) -+{ -+ return (void *) Q_MSG ((EP4_OUTPUTQ *) q, slotNum); -+} -+ -+int -+ep4_outputq_state (EP_RAIL *r, EP_OUTPUTQ *q, unsigned slotNum) -+{ -+ EPRINTF2 (DBG_KMSG, "ep4_outputq_state: slotNum %d state %x\n", slotNum, (int)Q_DONE((EP4_OUTPUTQ *) q, slotNum)); -+ -+ return Q_DONE_RET(Q_DONE((EP4_OUTPUTQ *)q, slotNum)); -+} -+ -+int -+ep4_outputq_send (EP_RAIL *r, EP_OUTPUTQ *q, unsigned slotNum, unsigned size, -+ unsigned vp, unsigned qnum, unsigned retries) -+{ -+ EP4_OUTPUTQ *outputq = (EP4_OUTPUTQ *) q; -+ unsigned int nbytes = roundup (size, 32); -+ unsigned int base = outputq->q_slotSize - nbytes; -+ unsigned int i, dwords; -+ unsigned long flags; -+ E4_uint64 val; -+ -+ spin_lock_irqsave (&outputq->q_lock, flags); -+ -+ EPRINTF4 (DBG_KMSG, "ep4_outputq_send: slotNum=%d size=%d vp=%d qnum=%d\n", slotNum, size, vp, qnum); -+ -+ /* compute command queue size as follows - each slot uses -+ * overhead: 14 dwords + -+ * data > 128 ? 36 dwords -+ * data > 64 ? 18 dwords -+ * data > 32 ? 10 dwords -+ * else 6 dwords -+ */ -+ dwords = 14 + (size > 128 ? 36 : -+ size > 64 ? 18 : -+ size ? 10 : 6); -+ -+ outputq->q_dwords += Q_DONE_CNT (Q_DONE(outputq, slotNum)); -+ -+ if (dwords > outputq->q_dwords) -+ { -+ /* attempt to reclaim command queue space from other slots */ -+ i = slotNum; -+ do { -+ if (++i == outputq->q_slotCount) -+ i = 0; -+ -+ val = Q_DONE(outputq, i); -+ -+ if ((Q_DONE_RET (val) == EP_OUTPUTQ_FINISHED || Q_DONE_RET (val) == EP_OUTPUTQ_FAILED) && Q_DONE_CNT(val) > 0) -+ { -+ outputq->q_dwords += Q_DONE_CNT (val); -+ -+ Q_DONE(outputq, i) = Q_DONE_VAL(Q_DONE_RET(val), 0); -+ } -+ } while (i != slotNum && dwords > outputq->q_dwords); -+ } -+ -+ if (dwords > outputq->q_dwords) -+ { -+ spin_unlock_irqrestore (&outputq->q_lock, flags); -+ -+ EPRINTF0 (DBG_KMSG, "ep4_outputq_state: no command queue space\n"); -+ return 0; -+ } -+ -+ outputq->q_dwords -= dwords; -+ -+ Q_DONE(outputq, slotNum) = Q_DONE_VAL (EP_OUTPUTQ_BUSY, dwords); -+ -+ if (outputq->q_retries != retries) -+ { -+ elan4_guard (outputq->q_cq, GUARD_CHANNEL(1) | GUARD_RESET(outputq->q_retries = retries)); -+ elan4_nop_cmd (outputq->q_cq, 0); -+ } -+ -+ /* transfer the top "size" bytes from message buffer to top of input queue */ -+ elan4_open_packet (outputq->q_cq, OPEN_PACKET (0, PACK_OK | RESTART_COUNT_ZERO, vp)); -+ elan4_sendtrans0 (outputq->q_cq, TR_INPUT_Q_GETINDEX, EP_SYSTEMQ_ADDR(qnum)); -+ -+ /* send upto EP_SYSTEMQ_MSG_MAX (256) bytes of message to the top of the slot */ -+ if (size > 128) -+ { -+ elan4_sendtransp (outputq->q_cq, TR_WRITE (128 >> 3, 0, TR_DATATYPE_DWORD), base + 0, (void *) (Q_MSG(outputq, slotNum) + base + 0)); -+ elan4_sendtransp (outputq->q_cq, TR_WRITE (128 >> 3, 0, TR_DATATYPE_DWORD), base + 128, (void *) (Q_MSG(outputq, slotNum) + base + 128)); -+ } -+ else if (size > 64) -+ elan4_sendtransp (outputq->q_cq, TR_WRITE (128 >> 3, 0, TR_DATATYPE_DWORD), base, (void *) (Q_MSG(outputq, slotNum) + base)); -+ else if (size > 32) -+ elan4_sendtransp (outputq->q_cq, TR_WRITE (64 >> 3, 0, TR_DATATYPE_DWORD), base, (void *) (Q_MSG(outputq, slotNum) + base)); -+ else -+ elan4_sendtransp (outputq->q_cq, TR_WRITE (32 >> 3, 0, TR_DATATYPE_DWORD), base, (void *) (Q_MSG(outputq, slotNum) + base)); -+ elan4_sendtrans1 (outputq->q_cq, TR_INPUT_Q_COMMIT, EP_SYSTEMQ_ADDR(qnum), 0 /* no cookie */); -+ -+ elan4_guard (outputq->q_cq, GUARD_CHANNEL (1) | GUARD_TEST(0, PACK_OK) | GUARD_RESET (outputq->q_retries)); -+ elan4_write_dword_cmd (outputq->q_cq, Q_DONE_ADDR(outputq, slotNum), Q_DONE_VAL (EP_OUTPUTQ_FINISHED, dwords)); -+ -+ elan4_guard (outputq->q_cq, GUARD_CHANNEL (1) | GUARD_TEST(0, RESTART_COUNT_ZERO) | GUARD_RESET (outputq->q_retries)); -+ elan4_write_dword_cmd (outputq->q_cq, Q_DONE_ADDR(outputq, slotNum), Q_DONE_VAL (EP_OUTPUTQ_FAILED, dwords)); -+ -+ spin_unlock_irqrestore (&outputq->q_lock, flags); -+ -+ return 1; -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/kthread.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kthread.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kthread.c 2005-06-01 23:12:54.672428008 -0400 -@@ -0,0 +1,186 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kthread.c,v 1.5 2004/05/19 08:54:57 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kthread.c,v $*/ -+ -+#include -+ -+#include -+ -+void -+ep_kthread_init (EP_KTHREAD *kt) -+{ -+ spin_lock_init (&kt->lock); -+ kcondvar_init (&kt->wait); -+ -+ kt->next_run = 0; -+ kt->should_stall = 0; -+ kt->started = 0; -+ kt->should_stop = 0; -+ kt->stopped = 0; -+ kt->state = KT_STATE_RUNNING; -+} -+ -+void -+ep_kthread_destroy (EP_KTHREAD *kt) -+{ -+ spin_lock_destroy (&kt->lock); -+ kcondvar_destroy (&kt->wait); -+} -+ -+void -+ep_kthread_started (EP_KTHREAD *kt) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ kt->started = 1; -+ spin_unlock_irqrestore(&kt->lock, flags); -+} -+ -+void -+ep_kthread_stopped (EP_KTHREAD *kt) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ kt->stopped = 1; -+ kcondvar_wakeupall (&kt->wait, &kt->lock); -+ spin_unlock_irqrestore(&kt->lock, flags); -+} -+ -+int -+ep_kthread_should_stall (EP_KTHREAD *kth) -+{ -+ return (kth->should_stall); -+} -+ -+int -+ep_kthread_sleep (EP_KTHREAD *kt, long next_run) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ if (next_run && (kt->next_run == 0 || BEFORE (next_run, kt->next_run))) -+ kt->next_run = next_run; -+ -+ if (kt->should_stop) -+ { -+ spin_unlock_irqrestore (&kt->lock, flags); -+ return (-1); -+ } -+ -+ do { -+ if (kt->should_stall) -+ kcondvar_wakeupall (&kt->wait, &kt->lock); -+ -+ kt->state = KT_STATE_SLEEPING; -+ kt->running = 0; -+ if (kt->should_stall || kt->next_run == 0) -+ kcondvar_wait (&kt->wait, &kt->lock, &flags); -+ else -+ kcondvar_timedwait (&kt->wait,&kt->lock, &flags, kt->next_run); -+ kt->state = KT_STATE_RUNNING; -+ kt->running = lbolt; -+ } while (kt->should_stall); -+ kt->next_run = 0; -+ spin_unlock_irqrestore (&kt->lock, flags); -+ -+ return (0); -+} -+ -+void -+ep_kthread_schedule (EP_KTHREAD *kt, long tick) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ if (kt->next_run == 0 || BEFORE (tick, kt->next_run)) -+ { -+ kt->next_run = tick; -+ if (!kt->should_stall && kt->state == KT_STATE_SLEEPING) -+ { -+ kt->state = KT_STATE_SCHEDULED; -+ kcondvar_wakeupone (&kt->wait, &kt->lock); -+ } -+ } -+ spin_unlock_irqrestore (&kt->lock, flags); -+} -+ -+void -+ep_kthread_stall (EP_KTHREAD *kt) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ if (kt->should_stall++ == 0) -+ kcondvar_wakeupall (&kt->wait, &kt->lock); -+ -+ while (kt->state != KT_STATE_SLEEPING) -+ kcondvar_wait (&kt->wait, &kt->lock, &flags); -+ spin_unlock_irqrestore (&kt->lock, flags); -+} -+ -+void -+ep_kthread_resume (EP_KTHREAD *kt) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ if (--kt->should_stall == 0) -+ { -+ kt->state = KT_STATE_SCHEDULED; -+ kcondvar_wakeupone (&kt->wait, &kt->lock); -+ } -+ spin_unlock_irqrestore (&kt->lock, flags); -+} -+ -+void -+ep_kthread_stop (EP_KTHREAD *kt) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ kt->should_stop = 1; -+ while (kt->started && !kt->stopped) -+ { -+ kcondvar_wakeupall (&kt->wait, &kt->lock); -+ kcondvar_wait (&kt->wait, &kt->lock, &flags); -+ } -+ spin_unlock_irqrestore (&kt->lock, flags); -+} -+ -+int -+ep_kthread_state (EP_KTHREAD *kt, long *time) -+{ -+ unsigned long flags; -+ int res = KT_STATE_SLEEPING; -+ -+ spin_lock_irqsave (&kt->lock, flags); -+ -+ if (kt->next_run) { -+ *time = kt->next_run; -+ res = kt->should_stall ? KT_STATE_STALLED : KT_STATE_SCHEDULED; -+ } -+ -+ if (kt->running) { -+ *time = kt->running; -+ res = KT_STATE_RUNNING; -+ } -+ -+ spin_unlock_irqrestore (&kt->lock, flags); -+ -+ return res; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/kthread.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/kthread.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/kthread.h 2005-06-01 23:12:54.673427856 -0400 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_KTHREAD_H -+#define __ELAN3_KTHREAD_H -+ -+#ident "@(#)$Id: kthread.h,v 1.4 2004/05/06 14:24:08 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kthread.h,v $*/ -+ -+typedef struct ep_kthread -+{ -+ kcondvar_t wait; /* place to sleep */ -+ spinlock_t lock; /* and lock */ -+ long next_run; /* tick when thread should next run */ -+ long running; /* tick when thread started to run */ -+ unsigned short should_stall; -+ unsigned char state; -+ unsigned int started:1; -+ unsigned int should_stop:1; -+ unsigned int stopped:1; -+} EP_KTHREAD; -+ -+#define KT_STATE_SLEEPING 0 -+#define KT_STATE_SCHEDULED 1 -+#define KT_STATE_RUNNING 2 -+#define KT_STATE_STALLED 3 -+ -+#define AFTER(a, b) ((((long)(a)) - ((long)(b))) > 0) -+#define BEFORE(a,b) ((((long)(a)) - ((long)(b))) < 0) -+ -+extern void ep_kthread_init (EP_KTHREAD *kt); -+extern void ep_kthread_destroy (EP_KTHREAD *kt); -+extern void ep_kthread_started (EP_KTHREAD *kt); -+extern void ep_kthread_stopped (EP_KTHREAD *kt); -+extern int ep_kthread_should_stall (EP_KTHREAD *kth); -+extern int ep_kthread_sleep (EP_KTHREAD *kth, long next_run); -+extern void ep_kthread_schedule (EP_KTHREAD *kt, long when); -+extern void ep_kthread_stall (EP_KTHREAD *kth); -+extern void ep_kthread_resume (EP_KTHREAD *kt); -+extern void ep_kthread_stop (EP_KTHREAD *kt); -+extern int ep_kthread_state (EP_KTHREAD *kt, long *time); -+#endif /* __ELAN3_KTHREAD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/Makefile 2005-06-01 23:12:54.673427856 -0400 -@@ -0,0 +1,33 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/ep/Makefile -+# -+ -+ -+ep3-$(CONFIG_ELAN3) := kcomm_elan3.o kmsg_elan3.o kmap_elan3.o neterr_elan3.o probenetwork_elan3.o support_elan3.o threadcode_elan3.o threadcode_elan3_Linux.o epcomms_elan3.o epcommsTx_elan3.o epcommsRx_elan3.o -+ep4-$(CONFIG_ELAN4) := kcomm_elan4.o kmsg_elan4.o kmap_elan4.o neterr_elan4.o probenetwork_elan4.o commands_elan4.o debug_elan4.o support_elan4.o threadcode_elan4_Linux.o epcomms_elan4.o epcommsTx_elan4.o epcommsRx_elan4.o -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/ep/Makefile -+# -+ -+list-multi := ep.o -+ep-objs := cm.o debug.o kalloc.o kcomm.o kmap.o kthread.o neterr.o nmh.o probenetwork.o railhints.o rmap.o statemap.o support.o threadcode.o epcomms.o epcommsRx.o epcommsTx.o epcommsFwd.o conf_linux.o procfs_linux.o ep_procfs.o cm_procfs.o $(ep3-$(CONFIG_EP)) $(ep4-$(CONFIG_EP)) -+export-objs := conf_linux.o -+obj-$(CONFIG_EP) := ep.o -+ -+ep.o : $(ep-objs) -+ $(LD) -r -o $@ $(ep-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/Makefile.conf 2005-06-01 23:12:54.673427856 -0400 -@@ -0,0 +1,12 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = ep.o -+MODULENAME = ep -+KOBJFILES = cm.o debug.o kalloc.o kcomm.o kmap.o kthread.o neterr.o nmh.o probenetwork.o railhints.o rmap.o statemap.o support.o threadcode.o epcomms.o epcommsRx.o epcommsTx.o epcommsFwd.o conf_linux.o procfs_linux.o ep_procfs.o cm_procfs.o \$\(ep3-\$\(CONFIG_EP\)\) \$\(ep4-\$\(CONFIG_EP\)\) -+EXPORT_KOBJS = conf_linux.o -+CONFIG_NAME = CONFIG_EP -+SGALFC = -+# EXTRALINES START -+ -+ep3-$(CONFIG_ELAN3) := kcomm_elan3.o kmsg_elan3.o kmap_elan3.o neterr_elan3.o probenetwork_elan3.o support_elan3.o threadcode_elan3.o threadcode_elan3_Linux.o epcomms_elan3.o epcommsTx_elan3.o epcommsRx_elan3.o -+ep4-$(CONFIG_ELAN4) := kcomm_elan4.o kmsg_elan4.o kmap_elan4.o neterr_elan4.o probenetwork_elan4.o commands_elan4.o debug_elan4.o support_elan4.o threadcode_elan4_Linux.o epcomms_elan4.o epcommsTx_elan4.o epcommsRx_elan4.o -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/ep/neterr.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/neterr.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/neterr.c 2005-06-01 23:12:54.674427704 -0400 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: neterr.c,v 1.25.8.1 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/neterr.c,v $ */ -+ -+#include -+#include -+ -+#include "debug.h" -+ -+void -+ep_queue_network_error (EP_RAIL *rail, int nodeId, int what, int channel, EP_NETERR_COOKIE cookie) -+{ -+ EP_SYS *sys = rail->System; -+ EP_NODE_RAIL *nodeRail = &rail->Nodes[nodeId]; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ -+ ASSERT (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ if (nodeRail->NetworkErrorState == 0) -+ { -+ EPRINTF2 (DBG_NETWORK_ERROR, "%s: raise context filter for node %d due to network error\n", rail->Name, nodeId); -+ printk ("%s: raise context filter for node %d due to network error\n", rail->Name, nodeId); -+ -+ rail->Operations.RaiseFilter (rail, nodeId); -+ -+ if (nodeRail->State == EP_NODE_LOCAL_PASSIVATE) -+ printk ("%s: node %d is flushing - deferring network error fixup\n", rail->Name, nodeId); -+ else -+ list_add_tail (&nodeRail->Link, &rail->NetworkErrorList); -+ } -+ -+ switch (what) -+ { -+ case EP_NODE_NETERR_ATOMIC_PACKET: -+ ASSERT (nodeRail->NetworkErrorCookies[channel] == 0); -+ -+ /* Need to raise the approriate context filter for this node, -+ * and periodically send a neterr fixup message to it until -+ * we receive an ack from it -+ */ -+ IncrStat (rail, NeterrAtomicPacket); -+ -+ nodeRail->NetworkErrorCookies[channel] = cookie; -+ -+ nodeRail->NetworkErrorState |= EP_NODE_NETERR_ATOMIC_PACKET; -+ nodeRail->MsgXid = ep_xid_cache_alloc (sys, &rail->XidCache); -+ -+ EPRINTF3 (DBG_NETWORK_ERROR, "%s: atomic packet destroyed - node %d cookie %llx\n", rail->Name, nodeId, cookie); -+ -+ printk ("%s: atomic packet destroyed - node %d cookie %llx\n", rail->Name, nodeId, cookie); -+ break; -+ -+ case EP_NODE_NETERR_DMA_PACKET: -+ /* Must be an overlapped dma packet, raise the context filter, -+ * and hold it up for a NETWORK_ERROR_TIMEOUT */ -+ IncrStat (rail, NeterrDmaPacket); -+ -+ nodeRail->NetworkErrorState |= EP_NODE_NETERR_DMA_PACKET; -+ break; -+ } -+ -+ nodeRail->NextRunTime = lbolt + NETWORK_ERROR_TIMEOUT; -+ -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ ep_kthread_schedule (&sys->ManagerThread, nodeRail->NextRunTime); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/neterr_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/neterr_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/neterr_elan3.c 2005-06-01 23:12:54.674427704 -0400 -@@ -0,0 +1,326 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: neterr_elan3.c,v 1.24 2003/11/17 13:26:45 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/neterr_elan3.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "debug.h" -+ -+typedef struct neterr_halt_args -+{ -+ EP3_RAIL *Rail; -+ unsigned int NodeId; -+ EP_NETERR_COOKIE *Cookies; -+} NETERR_HALT_ARGS; -+ -+static int -+DmaMatchesCookie (EP3_RAIL *rail, E3_DMA_BE *dma, int nodeId, EP_NETERR_COOKIE *cookies, char *where) -+{ -+ E3_uint32 cvproc; -+ E3_uint32 cookie; -+ -+ if (dma->s.dma_direction == DMA_WRITE) -+ { -+ cvproc = dma->s.dma_destCookieVProc; -+ cookie = dma->s.dma_srcCookieVProc; -+ } -+ else -+ { -+ cvproc = dma->s.dma_srcCookieVProc; -+ cookie = dma->s.dma_destCookieVProc; -+ } -+ -+ EPRINTF6 (DBG_NETWORK_ERROR, "%s: Neterr - %s: DMA %08x %08x %08x %08x\n", rail->Generic.Name, where, -+ dma->s.dma_type, dma->s.dma_size, dma->s.dma_source, dma->s.dma_dest); -+ EPRINTF5 (DBG_NETWORK_ERROR, "%s: %08x %08x %08x %08x\n", rail->Generic.Name, -+ dma->s.dma_destEvent, dma->s.dma_destCookieVProc, dma->s.dma_srcEvent, dma->s.dma_srcCookieVProc); -+ -+ if (EP_VP_ISDATA((cvproc & DMA_PROCESS_MASK)) && EP_VP_TO_NODE(cvproc & DMA_PROCESS_MASK) == nodeId) -+ { -+ /* -+ * This is a DMA going to the node which has a network fixup -+ * request pending, so check if the cookie matches. -+ */ -+ if ((cookie == cookies[0] || cookie == cookies[1]) /* && !WaitForEop */) -+ { -+ EPRINTF3 (DBG_NETWORK_ERROR, "%s: match cookie %08x on %s\n", rail->Generic.Name, cookie, where); -+ -+ return (TRUE); -+ } -+ } -+ -+ return (FALSE); -+} -+ -+ -+static void -+NetworkErrorHaltOperation (ELAN3_DEV *dev, void *arg) -+{ -+ NETERR_HALT_ARGS *args = (NETERR_HALT_ARGS *) arg; -+ EP3_RAIL *rail = args->Rail; -+ EP_SYS *sys = rail->Generic.System; -+ sdramaddr_t FPtr, BPtr; -+ sdramaddr_t Base, Top; -+ E3_DMA_BE dma; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc.s.FSR)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData1.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData2.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData3.s.FSR.Status)) == 0); -+ -+ FPtr = read_reg32 (dev, DProc_SysCntx_FPtr); -+ BPtr = read_reg32 (dev, DProc_SysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[E3_SysCntxQueueSize-1]); -+ -+ while (FPtr != BPtr) -+ { -+ elan3_sdram_copyq_from_sdram (dev, FPtr, &dma, sizeof (E3_DMA_BE)); -+ -+ if (DmaMatchesCookie (rail, &dma, args->NodeId, args->Cookies, "runq ")) -+ { -+ /* -+ * Transfer the DMA to the node, it's source event will -+ * get executed later. -+ */ -+ QueueDmaOnStalledList (rail, &dma); -+ -+ /* -+ * Remove the DMA from the queue by replacing it with one with -+ * zero size and no events. -+ * -+ * NOTE: we must preserve the SYS_CONTEXT_BIT since the Elan uses this -+ * to mark the approriate run queue as empty. -+ */ -+ dma.s.dma_type = (SYS_CONTEXT_BIT << 16); -+ dma.s.dma_size = 0; -+ dma.s.dma_source = (E3_Addr) 0; -+ dma.s.dma_dest = (E3_Addr) 0; -+ dma.s.dma_destEvent = (E3_Addr) 0; -+ dma.s.dma_destCookieVProc = 0; -+ dma.s.dma_srcEvent = (E3_Addr) 0; -+ dma.s.dma_srcCookieVProc = 0; -+ -+ elan3_sdram_copyq_to_sdram (dev, &dma, FPtr, sizeof (E3_DMA_BE)); -+ } -+ -+ FPtr = (FPtr == Top) ? Base : FPtr + sizeof (E3_DMA); -+ } -+ -+ rail->NetworkErrorFlushed = TRUE; -+ kcondvar_wakeupall (&rail->NetworkErrorSleep, &sys->NodeLock); -+ -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+} -+ -+void -+ep3_neterr_fixup (EP_RAIL *r, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP_SYS *sys = rail->Generic.System; -+ ELAN3_DEV *dev = rail->Device; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[nodeId]; -+ E3_DMA_BE dmabe; -+ EP3_COOKIE *cp; -+ E3_uint32 vp; -+ NETERR_HALT_ARGS args; -+ struct list_head *el, *nel, matchedList; -+ int i; -+ unsigned long flags; -+ -+ INIT_LIST_HEAD (&matchedList); -+ -+ StallDmaRetryThread (rail); -+ -+ args.Rail = rail; -+ args.NodeId = nodeId; -+ args.Cookies = cookies; -+ -+ spin_lock_irqsave (&rail->Device->IntrLock, flags); -+ QueueHaltOperation (rail->Device, 0, NULL, INT_TProcHalted | INT_DProcHalted, NetworkErrorHaltOperation, &args); -+ spin_unlock_irqrestore (&rail->Device->IntrLock, flags); -+ -+ spin_lock_irqsave (&sys->NodeLock, flags); -+ while (! rail->NetworkErrorFlushed) -+ kcondvar_wait (&rail->NetworkErrorSleep, &sys->NodeLock, &flags); -+ rail->NetworkErrorFlushed = FALSE; -+ -+ spin_lock (&rail->DmaRetryLock); -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ list_for_each_safe (el, nel, &rail->DmaRetries[i]) { -+ EP3_RETRY_DMA *retry = list_entry (el, EP3_RETRY_DMA, Link); -+ -+ if (DmaMatchesCookie (rail, &retry->Dma, nodeId, cookies, "retry")) -+ { -+ /* remove from retry list */ -+ list_del (&retry->Link); -+ -+ /* add to list of dmas which matched */ -+ list_add_tail (&retry->Link, &matchedList); -+ } -+ } -+ } -+ -+ list_for_each_safe (el, nel, &nodeRail->StalledDmas) { -+ EP3_RETRY_DMA *retry = list_entry (el, EP3_RETRY_DMA, Link); -+ -+ if (DmaMatchesCookie (rail, &retry->Dma, nodeId, cookies, "stalled")) -+ { -+ /* remove from retry list */ -+ list_del (&retry->Link); -+ -+ /* add to list of dmas which matched */ -+ list_add_tail (&retry->Link, &matchedList); -+ } -+ } -+ -+ spin_unlock (&rail->DmaRetryLock); -+ spin_unlock_irqrestore (&sys->NodeLock, flags); -+ -+ ResumeDmaRetryThread (rail); -+ -+ /* Now "set" the source event of any write DMA's */ -+ while (! list_empty (&matchedList)) -+ { -+ EP3_RETRY_DMA *retry = list_entry (matchedList.next, EP3_RETRY_DMA, Link); -+ -+ list_del (&retry->Link); -+ -+ if (retry->Dma.s.dma_direction == DMA_WRITE && retry->Dma.s.dma_srcEvent) -+ { -+ sdramaddr_t event = ep_elan2sdram (&rail->Generic, retry->Dma.s.dma_srcEvent); -+ -+ /* Block local interrupts, since we need to atomically -+ * decrement the event count and perform the word write -+ */ -+ local_irq_save (flags); -+ { -+ E3_uint32 type = elan3_sdram_readl (dev, event + offsetof (E3_Event, ev_Type)); -+ E3_uint32 count = elan3_sdram_readl (dev, event + offsetof (E3_Event, ev_Count)); -+ -+ elan3_sdram_writel (dev, event + offsetof (E3_Event, ev_Count), count - 1); -+ -+ if (count == 1) -+ { -+ if (type & EV_TYPE_MASK_BCOPY) -+ { -+ E3_Addr srcVal = elan3_sdram_readl (dev, event + offsetof (E3_BlockCopyEvent, ev_Source)); -+ E3_Addr dstAddr = elan3_sdram_readl (dev, event + offsetof (E3_BlockCopyEvent, ev_Dest)) & ~EV_BCOPY_DTYPE_MASK; -+ -+ ASSERT ((srcVal & EV_WCOPY) != 0); -+ -+ EPRINTF3 (DBG_NETWORK_ERROR, "%s: neterr perform event word write at %08x with %08x\n", rail->Generic.Name, dstAddr, srcVal); -+ -+ ELAN3_OP_STORE32 (rail->Ctxt, dstAddr, srcVal); -+ } -+ -+ if ((type & ~EV_TYPE_MASK_BCOPY) != 0) -+ { -+ if ((type & EV_TYPE_MASK_CHAIN) == EV_TYPE_CHAIN) -+ { -+ printk ("%s: event at %08x - chained event %x is invalid\n", rail->Generic.Name, retry->Dma.s.dma_srcEvent, type); -+ panic ("ep: neterr invalid event type\n"); -+ } -+ else if ((type & EV_TYPE_MASK_EVIRQ) == EV_TYPE_EVIRQ) -+ { -+ EPRINTF2 (DBG_NETWORK_ERROR, "%s: neterr event interrupt - cookie %08x\n", rail->Generic.Name, (type & ~(EV_TYPE_MASK_EVIRQ|EV_TYPE_MASK_BCOPY))); -+ -+ cp = LookupCookie (&rail->CookieTable, (type & ~(EV_TYPE_MASK_EVIRQ|EV_TYPE_MASK_BCOPY))); -+ -+ if (cp->Operations->Event) -+ cp->Operations->Event(rail, cp->Arg); -+ } -+ else if ((type & EV_TYPE_MASK_DMA) == EV_TYPE_DMA) -+ { -+ sdramaddr_t dma = ep_elan2sdram (&rail->Generic, (type & ~EV_TYPE_MASK2)); -+ -+ EPRINTF2 (DBG_NETWORK_ERROR, "%s: neterr chained dma - %08x\n", rail->Generic.Name, (type & ~EV_TYPE_MASK2)); -+ -+ elan3_sdram_copyq_from_sdram (dev, dma, &dmabe, sizeof (E3_DMA)); -+ -+ if (dmabe.s.dma_direction == DMA_WRITE) -+ { -+ vp = dmabe.s.dma_destVProc; -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_srcEvent); -+ } -+ else -+ { -+ vp = dmabe.s.dma_srcVProc; -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_destEvent); -+ -+ /* we MUST convert this into a DMA_READ_REQUEUE dma as if we don't the -+ * DMA descriptor will be read from the EP_RETRY_DMA rather than the -+ * original DMA - this can then get reused and an incorrect DMA -+ * descriptor sent -+ * eventp->ev_Type contains the dma address with type in the lower bits -+ */ -+ -+ dmabe.s.dma_source = (type & ~EV_TYPE_MASK2); -+ dmabe.s.dma_direction = (dmabe.s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ } -+ -+ ASSERT (EP_VP_ISDATA(vp)); -+ -+ nodeRail = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ switch (nodeRail->State) -+ { -+ case EP_NODE_CONNECTED: -+ case EP_NODE_LEAVING_CONNECTED: -+ if (cp != NULL) -+ cp->Operations->DmaRetry (rail, cp->Arg, &dmabe, EAGAIN); -+ else -+ { -+ ASSERT (dmabe.s.dma_direction == DMA_WRITE && dmabe.s.dma_srcEvent == 0 && dmabe.s.dma_isRemote); -+ -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_ANONYMOUS); -+ } -+ break; -+ -+ case EP_NODE_LOCAL_PASSIVATE: -+ QueueDmaOnStalledList (rail, &dmabe); -+ break; -+ -+ default: -+ panic ("ep: neterr incorrect state for node\n"); -+ } -+ } -+ else if ((type & EV_TYPE_MASK_THREAD) == EV_TYPE_THREAD) -+ { -+ printk ("%s: event at %08x - thread waiting %x is invalid\n", rail->Generic.Name, retry->Dma.s.dma_srcEvent, type); -+ panic ("ep: neterr invalid event type\n"); -+ } -+ } -+ } -+ } -+ local_irq_restore(flags); -+ } -+ -+ /* add to free list */ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ list_add (&retry->Link, &rail->DmaRetryFreeList); -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ } -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/neterr_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/neterr_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/neterr_elan4.c 2005-06-01 23:12:54.675427552 -0400 -@@ -0,0 +1,251 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: neterr_elan4.c,v 1.2 2003/11/24 17:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/neterr_elan4.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "debug.h" -+ -+struct neterr_desc -+{ -+ EP4_RAIL *rail; -+ unsigned int nodeid; -+ EP_NETERR_COOKIE *cookies; -+ int done; -+} ; -+ -+static int -+dma_matches_cookie (EP4_RAIL *rail, E4_uint64 vproc, E4_uint64 cookie, unsigned int nodeId, EP_NETERR_COOKIE *cookies, const char *where) -+{ -+ if ((EP_VP_ISDATA (vproc) && EP_VP_TO_NODE (vproc) == nodeId) && (cookie == cookies[0] || cookie == cookies[1])) -+ { -+ EPRINTF3 (DBG_NETWORK_ERROR, "%s: match cookie %016llx on %s\n", rail->r_generic.Name, cookie, where); -+ -+ return 1; -+ } -+ return 0; -+} -+ -+static void -+ep4_neterr_dma_flushop (ELAN4_DEV *dev, void *arg, int qfull) -+{ -+ struct neterr_desc *desc = (struct neterr_desc *) arg; -+ EP4_RAIL *rail = desc->rail; -+ E4_uint64 qptrs = read_reg64 (dev, DProcHighPriPtrs); -+ E4_uint32 qsize = E4_QueueSize (E4_QueueSizeValue (qptrs)); -+ E4_uint32 qfptr = E4_QueueFrontPointer (qptrs); -+ E4_uint32 qbptr = E4_QueueBackPointer (qptrs); -+ E4_DProcQueueEntry qentry; -+ unsigned long flags; -+ -+ while ((qfptr != qbptr) || qfull) -+ { -+ E4_uint64 cookie = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_cookie)); -+ E4_uint64 vproc = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_vproc)); -+ -+ if (dma_matches_cookie (rail, vproc, cookie, desc->nodeid, desc->cookies, "runq ")) -+ { -+ elan4_sdram_copyq_from_sdram (dev, qfptr, &qentry, sizeof (E4_DProcQueueEntry)); -+ -+ ep4_queue_dma_stalled (rail, &qentry.Desc); -+ -+ /* Replace the dma with one which will "disappear" */ -+ qentry.Desc.dma_typeSize = DMA_ShMemWrite | dev->dev_ctxt.ctxt_num; -+ qentry.Desc.dma_cookie = 0; -+ qentry.Desc.dma_vproc = 0; -+ qentry.Desc.dma_srcAddr = 0; -+ qentry.Desc.dma_dstAddr = 0; -+ qentry.Desc.dma_srcEvent = 0; -+ qentry.Desc.dma_dstEvent = 0; -+ -+ elan4_sdram_copyq_to_sdram (dev, &qentry, qfptr, sizeof (E4_DProcQueueEntry)); -+ } -+ -+ qfptr = (qfptr & ~(qsize-1)) | ((qfptr + sizeof (E4_DProcQueueEntry)) & (qsize-1)); -+ qfull = 0; -+ } -+ -+ spin_lock_irqsave (&rail->r_haltop_lock, flags); -+ desc->done = 1; -+ kcondvar_wakeupall (&rail->r_haltop_sleep, &rail->r_haltop_lock); -+ spin_unlock_irqrestore (&rail->r_haltop_lock, flags); -+} -+ -+static void -+ep4_neterr_dma_haltop (ELAN4_DEV *dev, void *arg) -+{ -+ struct neterr_desc *desc = (struct neterr_desc *) arg; -+ -+ elan4_queue_dma_flushop (dev, &desc->rail->r_flushop, 1); -+} -+ -+void -+ep4_neterr_fixup_dmas (EP4_RAIL *rail, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[nodeId]; -+ struct neterr_desc desc; -+ struct list_head matchedList; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ register int i; -+ -+ desc.rail = rail; -+ desc.nodeid = nodeId; -+ desc.cookies = cookies; -+ desc.done = 0; -+ -+ INIT_LIST_HEAD (&matchedList); -+ -+ /* First - stall the retry thread, so that it will no longer restart -+ * any dma's from the retry list */ -+ ep_kthread_stall (&rail->r_retry_thread); -+ -+ /* Second - flush through all command queues targetted by events, thread etc */ -+ ep4_flush_ecqs (rail); -+ -+ /* Third - queue a halt operation to flush through all DMA's which are executing -+ * or on the run queues */ -+ kmutex_lock (&rail->r_haltop_mutex); -+ -+ rail->r_haltop.op_mask = INT_DProcHalted; -+ rail->r_haltop.op_function = ep4_neterr_dma_haltop; -+ rail->r_haltop.op_arg = &desc; -+ -+ rail->r_flushop.op_function = ep4_neterr_dma_flushop; -+ rail->r_flushop.op_arg = &desc; -+ -+ elan4_queue_haltop (rail->r_ctxt.ctxt_dev, &rail->r_haltop); -+ -+ spin_lock_irqsave (&rail->r_haltop_lock, flags); -+ while (! desc.done) -+ kcondvar_wait (&rail->r_haltop_sleep, &rail->r_haltop_lock, &flags); -+ spin_unlock_irqrestore (&rail->r_haltop_lock, flags); -+ kmutex_unlock (&rail->r_haltop_mutex); -+ -+ /* Fourth - run down the dma retry lists and move all entries to the cancelled -+ * list. Any dma's which were on the run queues have already been -+ * moved there */ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ list_for_each_safe (el,nel, &rail->r_dma_retrylist[i]) { -+ EP4_DMA_RETRY *retry = list_entry (el, EP4_DMA_RETRY, retry_link); -+ -+ if (dma_matches_cookie (rail, retry->retry_dma.dma_vproc, retry->retry_dma.dma_cookie, nodeId, cookies, "retry")) -+ { -+ /* remove from retry list */ -+ list_del (&retry->retry_link); -+ -+ /* add to list of dmas which matched */ -+ list_add_tail (&retry->retry_link, &matchedList); -+ } -+ } -+ } -+ -+ list_for_each_safe (el, nel, &nodeRail->StalledDmas) { -+ EP4_DMA_RETRY *retry = list_entry (el, EP4_DMA_RETRY, retry_link); -+ -+ if (dma_matches_cookie (rail, retry->retry_dma.dma_vproc, retry->retry_dma.dma_cookie, nodeId, cookies, "stalled")) -+ { -+ /* remove from retry list */ -+ list_del (&retry->retry_link); -+ -+ /* add to list of dmas which matched */ -+ list_add_tail (&retry->retry_link, &matchedList); -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ -+ /* Now "set" the source event of any put DMA#'s we can use the dma -+ * retry command queue as the retry thread is stalled */ -+ while (! list_empty (&matchedList)) -+ { -+ EP4_DMA_RETRY *retry = list_entry (matchedList.next, EP4_DMA_RETRY, retry_link); -+ -+ list_del (&retry->retry_link); -+ -+ elan4_set_event_cmd (rail->r_dma_ecq->ecq_cq, retry->retry_dma.dma_srcEvent); -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ list_add (&retry->retry_link, &rail->r_dma_freelist); -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ } -+ -+ /* Flush through the command queues to ensure that all the setevents have executed */ -+ ep4_flush_ecqs (rail); -+ -+ /* Finally - allow the retry thread to run again */ -+ ep_kthread_resume (&rail->r_retry_thread); -+} -+ -+void -+ep4_add_neterr_ops (EP4_RAIL *rail, EP4_NETERR_OPS *ops) -+{ -+ /* we're called from the ManagerThread, so no need to stall it */ -+ list_add_tail (&ops->op_link, &rail->r_neterr_ops); -+} -+void -+ep4_remove_neterr_ops (EP4_RAIL *rail, EP4_NETERR_OPS *ops) -+{ -+ EP_SYS *sys = rail->r_generic.System; -+ -+ ep_kthread_stall (&sys->ManagerThread); -+ list_del (&ops->op_link); -+ ep_kthread_resume (&sys->ManagerThread); -+} -+ -+void -+ep4_neterr_fixup_sten (EP4_RAIL *rail, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ struct list_head *el; -+ -+ list_for_each (el, &rail->r_neterr_ops) { -+ EP4_NETERR_OPS *op = list_entry (el, EP4_NETERR_OPS, op_link); -+ -+ (op->op_func) (rail, op->op_arg, nodeId, cookies); -+ } -+} -+ -+void -+ep4_neterr_fixup (EP_RAIL *r, unsigned int nodeId, EP_NETERR_COOKIE *cookies) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ -+ /* network error cookies can come from the following : -+ * -+ * DMA engine -+ * if a DMA matches a network error cookie, then we just need to -+ * execute the local setevent *before* returning. -+ * -+ * STEN packet -+ * if the STEN packet was generated with as a WAIT_FOR_EOP -+ * and it's not present on the retry lists, then re-create -+ * it. -+ * -+ */ -+ EPRINTF4 (DBG_NETWORK_ERROR, "%s: ep4_neterr_fixup: node %d cookies <%lld%s%s%s%s> <%lld%s%s%s%s>\n", -+ rail->r_generic.Name, nodeId, EP4_COOKIE_STRING(cookies[0]), EP4_COOKIE_STRING(cookies[1])); -+ -+ if ((cookies[0] & EP4_COOKIE_DMA) || (cookies[1] & EP4_COOKIE_DMA)) -+ ep4_neterr_fixup_dmas (rail, nodeId, cookies); -+ -+ if ((cookies[0] & EP4_COOKIE_STEN) || (cookies[1] & EP4_COOKIE_STEN)) -+ ep4_neterr_fixup_sten (rail, nodeId, cookies); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/nmh.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/nmh.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/nmh.c 2005-06-01 23:12:54.676427400 -0400 -@@ -0,0 +1,181 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+#ident "@(#)$Id: nmh.c,v 1.6 2004/01/05 13:48:08 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/nmh.c,v $*/ -+ -+#include -+ -+#include -+ -+#define EP_NMD_SPANS(nmd, base, top) ((nmd)->nmd_addr <= (base) && \ -+ ((nmd)->nmd_addr + (nmd)->nmd_len - 1) >= (top)) -+ -+#define EP_NMD_OVERLAPS(nmd, addr, len) ((nmd)->nmd_addr <= ((addr) + (len)) && \ -+ ((nmd)->nmd_addr + (nmd)->nmd_len - 1) >= (addr)) -+ -+#define EP_NMH_HASH(tbl,idx,addr) ((addr) % (tbl)->tbl_size[idx]) -+ -+int -+ep_nmh_init (EP_NMH_TABLE *tbl) -+{ -+ int i, idx, hsize = 1; -+ -+ for (idx = EP_NMH_NUMHASH-1; idx >= 0; idx--, hsize <<= 1) -+ { -+ tbl->tbl_size[idx] = (hsize < EP_NMH_HASHSIZE) ? hsize : EP_NMH_HASHSIZE; -+ -+ KMEM_ZALLOC (tbl->tbl_hash[idx], struct list_head *, sizeof (struct list_head) * tbl->tbl_size[idx], 1); -+ -+ if (tbl->tbl_hash == NULL) -+ { -+ while (++idx < EP_NMH_NUMHASH) -+ KMEM_FREE (tbl->tbl_hash[idx], sizeof (struct list_head) * tbl->tbl_size[idx]); -+ return (ENOMEM); -+ } -+ -+ for (i = 0; i < tbl->tbl_size[idx]; i++) -+ INIT_LIST_HEAD (&tbl->tbl_hash[idx][i]); -+ } -+ -+ return (0); -+} -+ -+void -+ep_nmh_fini (EP_NMH_TABLE *tbl) -+{ -+ int idx; -+ -+ for (idx = 0; idx < EP_NMH_NUMHASH; idx++) -+ if (tbl->tbl_hash[idx]) -+ KMEM_FREE (tbl->tbl_hash[idx], sizeof (struct list_head) * tbl->tbl_size[idx]); -+ -+ bzero (tbl, sizeof (EP_NMH_TABLE)); -+} -+ -+void -+ep_nmh_insert (EP_NMH_TABLE *tbl, EP_NMH *nmh) -+{ -+ EP_ADDR base = nmh->nmh_nmd.nmd_addr; -+ EP_ADDR top = base + nmh->nmh_nmd.nmd_len - 1; -+ int idx; -+ -+ for (idx = 0, base >>= 12, top >>= 12; base != top && idx < EP_NMH_NUMHASH; idx++, base >>= 1, top >>= 1) -+ ; -+ -+ list_add_tail (&nmh->nmh_link, &tbl->tbl_hash[idx][EP_NMH_HASH(tbl, idx, base)]); -+} -+ -+void -+ep_nmh_remove (EP_NMH_TABLE *tbl, EP_NMH *nmh) -+{ -+ list_del (&nmh->nmh_link); -+} -+ -+EP_NMH * -+ep_nmh_find (EP_NMH_TABLE *tbl, EP_NMD *nmd) -+{ -+ EP_ADDR base = nmd->nmd_addr; -+ EP_ADDR top = base + nmd->nmd_len - 1; -+ int idx; -+ struct list_head *le; -+ -+ for (idx = 0, base >>= 12, top >>= 12; base != top && idx < EP_NMH_NUMHASH; idx++, base >>= 1, top >>= 1) -+ ; -+ -+ for (; idx < EP_NMH_NUMHASH; idx++, base >>= 1, top >>= 1) { -+ -+ list_for_each (le, &tbl->tbl_hash[idx][EP_NMH_HASH(tbl, idx, base)]) { -+ EP_NMH *nmh = list_entry (le, EP_NMH, nmh_link); -+ -+ if (EP_NMD_SPANS (&nmh->nmh_nmd, nmd->nmd_addr, nmd->nmd_addr + nmd->nmd_len - 1)) -+ return (nmh); -+ } -+ } -+ -+ return (0); -+} -+ -+void -+ep_nmd_subset (EP_NMD *subset, EP_NMD *nmd, unsigned off, unsigned len) -+{ -+ ASSERT ((off + len - 1) <= nmd->nmd_len); -+ -+ subset->nmd_addr = nmd->nmd_addr + off; -+ subset->nmd_len = len; -+ subset->nmd_attr = nmd->nmd_attr; -+} -+ -+int -+ep_nmd_merge (EP_NMD *merged, EP_NMD *a, EP_NMD *b) -+{ -+ if (EP_NMD_NODEID (a) != EP_NMD_NODEID (b)) /* not generated on the same node */ -+ return 0; -+ -+ if ((EP_NMD_RAILMASK (a) & EP_NMD_RAILMASK (b)) == 0) /* no common rails */ -+ return 0; -+ -+ if (b->nmd_addr == (a->nmd_addr + a->nmd_len)) -+ { -+ if (merged != NULL) -+ { -+ merged->nmd_addr = a->nmd_addr; -+ merged->nmd_len = a->nmd_len + b->nmd_len; -+ merged->nmd_attr = EP_NMD_ATTR(EP_NMD_NODEID(a), EP_NMD_RAILMASK(a) & EP_NMD_RAILMASK(b)); -+ } -+ return 1; -+ } -+ -+ if (a->nmd_addr == (b->nmd_addr + b->nmd_len)) -+ { -+ if (merged != NULL) -+ { -+ merged->nmd_addr = b->nmd_addr; -+ merged->nmd_len = b->nmd_len + a->nmd_len; -+ merged->nmd_attr = EP_NMD_ATTR(EP_NMD_NODEID(b), EP_NMD_RAILMASK(a) & EP_NMD_RAILMASK(b)); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+ep_nmd_map_rails (EP_SYS *sys, EP_NMD *nmd, unsigned railmask) -+{ -+ EP_NMH *nmh = ep_nmh_find (&sys->MappingTable, nmd); -+ -+ if (nmh == NULL) -+ { -+ printk ("ep_nmd_map_rails: nmd=%08x.%08x.%08x cannot be found\n", -+ nmd->nmd_addr, nmd->nmd_len, nmd->nmd_attr); -+ return (-1); -+ } -+ -+ return (nmh->nmh_ops->op_map_rails (sys, nmh, nmd, railmask)); -+} -+ -+EP_RAILMASK -+ep_nmd2railmask (EP_NMD *frags, int nFrags) -+{ -+ EP_RAILMASK mask; -+ -+ if (nFrags == 0) -+ return ((EP_RAILMASK)-1); -+ -+ for (mask = EP_NMD_RAILMASK(frags); --nFrags; ) -+ mask &= EP_NMD_RAILMASK(++frags); -+ -+ return (mask); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/probenetwork.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/probenetwork.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/probenetwork.c 2005-06-01 23:12:54.677427248 -0400 -@@ -0,0 +1,446 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: probenetwork.c,v 1.43 2004/04/19 15:43:15 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/probenetwork.c,v $ */ -+ -+#include -+ -+#include -+#include "debug.h" -+ -+int PositionCheck = 1; -+ -+#define NUM_DOWN_FROM_VAL(NumDownLinksVal, level) (((NumDownLinksVal) >> ((level) << 2)) & 0xF) -+ -+int -+ProbeNetwork (EP_RAIL *rail, ELAN_POSITION *pos) -+{ -+ int lvl, i; -+ int level; -+ int nodeid; -+ int numnodes; -+ int randomRoutingDisabled; -+ int sw; -+ int nacks; -+ int nowayup; -+ int nalias; -+ int upmask; -+ int partial; -+ int link; -+ int invalid; -+ int linkdown[ELAN_MAX_LEVELS]; -+ int linkup[ELAN_MAX_LEVELS]; -+ EP_SWITCH *switches[ELAN_MAX_LEVELS]; -+ int switchCount[ELAN_MAX_LEVELS+1]; -+ int lowestBcast; -+ int numUpLinks[ELAN_MAX_LEVELS]; -+ int routedown [ELAN_MAX_LEVELS]; -+ -+ EPRINTF1 (DBG_PROBE, "%s: ProbeNetwork started\n", rail->Name); -+ -+ switchCount[0] = 1; -+ numUpLinks [0] = 4; -+ -+ for (level = 0; level < ELAN_MAX_LEVELS; level++) -+ { -+ int ndown = NUM_DOWN_FROM_VAL (rail->Devinfo.dev_num_down_links_value, level); -+ -+ KMEM_ZALLOC (switches[level], EP_SWITCH *, sizeof (EP_SWITCH) * switchCount[level], 1); -+ -+ for (sw = 0, nacks = 0, nowayup = 0, lowestBcast=7; sw < switchCount[level]; sw++) -+ { -+ EP_SWITCH *lsw = &switches[level][sw]; -+ int good = 1; -+ int tsw; -+ -+ for (nodeid = 0,tsw = sw, lvl = level-1 ; lvl >= 0 ; lvl--) -+ { -+ EP_SWITCH *lsw; -+ int link = (8-numUpLinks[lvl]) + (tsw % numUpLinks[lvl]); -+ -+ tsw = tsw / numUpLinks[lvl]; -+ lsw = &switches[lvl][tsw]; -+ -+ if (lsw->present == 0 || (lsw->lnr & (1 << link))) -+ { -+ EPRINTF4 (DBG_PROBE, "lvl %d sw %d present=%d lnr=%x\n", lvl, sw, lsw->present, lsw->lnr); -+ good = 0; -+ } -+ -+ linkup[lvl] = link; -+ linkdown[lvl] = lsw->link; -+ -+ if ( lvl ) nodeid = ((nodeid + linkdown[lvl]) * (8-numUpLinks[lvl-1])); -+ else nodeid += linkdown[0]; -+ -+ } -+ -+ /* -+ * don't bother probing routes which we we've already seen are unreachable -+ * because a link upwards was in reset or the switch previously nacked us. -+ */ -+ if (! good) -+ { -+ lsw->present = 0; -+ -+ nacks++; -+ nowayup++; -+ -+ continue; -+ } -+ -+ lsw->present = rail->Operations.ProbeRoute (rail, level, sw, nodeid, linkup, linkdown, 5, lsw); -+ -+ if (! lsw->present) -+ { -+ EPRINTF3 (DBG_PROBE, "%s: level %d switch %d - unexpected nack\n", rail->Name, level, sw); -+ -+ nacks++; -+ nowayup++; -+ } -+ else -+ { -+ EPRINTF5 (DBG_PROBE, "%s: level %d switch %d - link %d bcast %d\n", rail->Name, level, sw, lsw->link, lsw->bcast); -+ -+ if (level == 2 && rail->Devinfo.dev_device_id == PCI_DEVICE_ID_ELAN3) -+ { -+ /* If we see broadcast top as 7, and we came in on a low link, then we can't -+ * determine whether we're in a 128 way or a un-configured 64u64d switch, so -+ * we treat it as a 64u64d and detect the 128 way case by "going over the top" -+ * below. Unless we've been told what it really is by NumDownLinksVal. -+ */ -+ if (lsw->bcast == 7 && lsw->link < 4) -+ lsw->bcast = ndown ? (ndown - 1) : 3; -+ } -+ -+ if ( lowestBcast > lsw->bcast ) -+ lowestBcast = lsw->bcast; -+ -+ if (lsw->link > (ndown ? (ndown-1) : (lowestBcast == 7 ? 3 : lowestBcast))) -+ { -+ /* We've arrived on a "up-link" - this could be either -+ * we're in the top half of a x8 top-switch - or we're -+ * in the bottom half and have gone "over the top". We -+ * differentiate these cases since the switches below -+ * a x8 top-switch will have broadcast top set to 3, -+ * and the x8 topswitch have broadcast top set to 7. -+ */ -+ if (lsw->bcast == 7) -+ nowayup++; -+ else -+ { -+ EPRINTF2 (DBG_PROBE, "%s: level %d - gone over the top\n", -+ rail->Name, level); -+ -+ if (level > 0) -+ { -+ KMEM_FREE (switches[level], sizeof (EP_SWITCH) * switchCount[level] ); -+ level--; -+ } -+ -+ numUpLinks[level] = 0; -+ goto finished; -+ } -+ } -+ -+ } -+ } -+ -+ numUpLinks[level] = ndown ? (8 - ndown) : (7 - lowestBcast); -+ switchCount[level+1] = switchCount[level] * numUpLinks[level]; -+ -+ /* Now we know which links are uplinks, we can see whether there is -+ * any possible ways up */ -+ upmask = (ndown ? (0xFF << ndown) & 0xFF : (0xFF << (8 - numUpLinks[level])) & 0xFF); -+ -+ for (sw = 0; sw < switchCount[level]; sw++) -+ { -+ EP_SWITCH *lsw = &switches[level][sw]; -+ -+ if (lsw->present && lsw->link <= (ndown ? (ndown-1) : (lowestBcast == 7 ? 3 : lowestBcast)) && (switches[level][sw].lnr & upmask) == upmask) -+ nowayup++; -+ } -+ -+ EPRINTF7 (DBG_PROBE, "%s: level %d - sw=%d nacks=%d nowayup=%d bcast=%d numup=%d\n", -+ rail->Name, level, sw, nacks, nowayup, lowestBcast, numUpLinks[level]); -+ -+ if (nacks == sw) -+ { -+ static bitmap_t printed[BT_BITOUL(EP_MAX_RAILS)]; -+ -+ if (! BT_TEST (printed, rail->Number)) -+ printk ("%s: cannot determine network position\n", rail->Name); -+ BT_SET (printed, rail->Number); -+ goto failed; -+ } -+ -+ if (nowayup == sw) -+ goto finished; -+ } -+ -+ printk ("%s: exceeded number of levels\n", rail->Name); -+ level = ELAN_MAX_LEVELS - 1; -+ -+ failed: -+ -+ for (lvl = 0; lvl <= level; lvl++) -+ KMEM_FREE (switches[lvl], sizeof (EP_SWITCH) * switchCount[lvl] ); -+ -+ return -EAGAIN; -+ -+ finished: -+ /* we've successfully probed the network - now calculate our node -+ * positon and what level of random routing is possible */ -+ nalias = 1; -+ for (lvl = 0, invalid = 0, partial = 0, randomRoutingDisabled = 0; lvl <= level; lvl++) -+ { -+ int ndown = NUM_DOWN_FROM_VAL (rail->Devinfo.dev_num_down_links_value, lvl); -+ int upmask = ndown ? (0xFF << ndown) & 0xFF : 0xF0; -+ -+ for (sw = 0, nalias = 0; sw < switchCount[lvl]; sw++) -+ { -+ EP_SWITCH *lsw = &switches[lvl][sw]; -+ -+ /* You can only use adaptive routing if links 4-7 are uplinks, and at least one of them is -+ * not in reset. Otherwise you can randomly select an "uplink" if all the uplinks are not -+ * in reset. */ -+ if (lsw->present && ((upmask == 0xF0) ? (lsw->lnr & upmask) == upmask : (lsw->lnr & upmask) != 0)) -+ randomRoutingDisabled |= (1 << lvl); -+ -+ if (!lsw->present) -+ partial++; -+ else -+ { -+ if (lsw->invalid) -+ { -+ printk ("%s: invalid switch detected (level %d switch %d)\n", rail->Name, lvl, sw); -+ invalid++; -+ } -+ -+ for (i = 0; i < nalias; i++) -+ if (linkdown[i] == lsw->link) -+ break; -+ if (i == nalias) -+ linkdown[nalias++] = lsw->link; -+ } -+ } -+ -+ link = linkdown[0]; -+ for (i = 1; i < nalias; i++) -+ if (linkdown[i] < link) -+ link = linkdown[i]; -+ -+ if (nalias > 1 && lvl != level) -+ { -+ printk ("%s: switch aliased below top level (level %d)\n", rail->Name, lvl); -+ invalid++; -+ } -+ -+ routedown[lvl] = link; -+ } -+ -+ for (lvl = 0; lvl <= level; lvl++) -+ KMEM_FREE (switches[lvl], sizeof (EP_SWITCH) * switchCount[lvl] ); -+ -+ if (invalid) -+ { -+ printk ("%s: invalid switch configuration\n", rail->Name); -+ return (EINVAL); -+ } -+ -+ /* Handle the aliasing case where a 16 way is used as multiple smaller switches */ -+ if (nalias == 1) -+ level++; -+ else if (nalias == 2) /* a 16 way as 2x8 ways */ -+ numUpLinks[level++] = 6; /* only 2 down links */ -+ else if (nalias > 4) /* a 16 way as 8x2 ways */ -+ numUpLinks[level-1] = 6; -+ -+ /* -+ * Compute my nodeid and number of nodes in the machine -+ * from the routedown and the number of downlinks at each level. -+ */ -+ for(nodeid=0, lvl = level - 1; lvl >= 0; lvl--) -+ { -+ if (lvl) nodeid = ((nodeid + routedown[lvl]) * (8-numUpLinks[lvl-1])); -+ else nodeid += routedown[0]; -+ } -+ -+ for (numnodes = 1, lvl = 0; lvl < level; lvl++) -+ numnodes *= (8 - numUpLinks[lvl]); -+ -+ sprintf (rail->Name, "ep%d[%d]", rail->Number, nodeid); -+ -+ if (randomRoutingDisabled & ((1 << (level-1))-1)) -+ printk ("%s: nodeid=%d level=%d numnodes=%d (random routing disabled 0x%x)\n", -+ rail->Name, nodeid, level, numnodes, randomRoutingDisabled); -+ else if (partial) -+ printk ("%s: nodeid=%d level=%d numnodes=%d (random routing ok)\n", -+ rail->Name, nodeid, level, numnodes); -+ else -+ printk ("%s: nodeid=%d level=%d numnodes=%d\n", -+ rail->Name, nodeid, level, numnodes); -+ -+ pos->pos_mode = ELAN_POS_MODE_SWITCHED; -+ pos->pos_nodeid = nodeid; -+ pos->pos_levels = level; -+ pos->pos_nodes = numnodes; -+ pos->pos_random_disabled = randomRoutingDisabled; -+ -+ for(lvl = 0; lvl < level; lvl++) -+ pos->pos_arity[level -lvl - 1] = (8-numUpLinks[lvl]); -+ pos->pos_arity[level] = 1; /* XXXX why does this need to be 1 ? */ -+ -+ return 0; -+} -+ -+/* -+ * broadcast top is invalid if it is not set to the number of downlinks-1, -+ * or at the topmost level it is less than ndown-1. -+ */ -+#define BCAST_TOP_INVALID(lvl, bcast, ndown) ((lvl) == 0 ? (bcast) < ((ndown)-1) : (bcast) != ((ndown) - 1)) -+ -+void -+CheckPosition (EP_RAIL *rail) -+{ -+ ELAN_POSITION *pos = &rail->Position; -+ unsigned int nodeid = pos->pos_nodeid; -+ unsigned int invalid = 0; -+ unsigned int changed = 0; -+ int lvl, slvl; -+ -+ if (! PositionCheck) -+ return; -+ -+ if (rail->Operations.CheckPosition(rail)) /* is update ready for this rail */ -+ { -+ EPRINTF2 (DBG_ROUTETABLE, "%s: check position: SwitchProbeLevel=%d\n", rail->Name, rail->SwitchProbeLevel); -+ -+ for (lvl = 0, slvl = pos->pos_levels-1; lvl <= rail->SwitchProbeLevel; lvl++, slvl--) -+ { -+ EP_SWITCHSTATE *state = &rail->SwitchState[lvl]; -+ EP_SWITCHSTATE *lstate = &rail->SwitchLast[lvl]; -+ unsigned int ndown = pos->pos_arity[slvl]; -+ unsigned int upmask = (0xFF << ndown) & 0xFF; -+ unsigned int mylink = nodeid % ndown; -+ unsigned int error = 0; -+ unsigned int binval = 0; -+ -+ nodeid /= ndown; -+ -+ /* -+ * broadcast top is invalid if it is not set to the number of downlinks-1, -+ * or at the topmost level it is less than ndown-1. -+ */ -+ if (BCAST_TOP_INVALID(lvl, state->bcast, ndown) || (state->LNR & upmask) == upmask) -+ { -+ /* no way up from here - we'd better be at the top */ -+ if (lvl != (pos->pos_levels-1)) -+ { -+ if (state->bcast != (ndown-1)) -+ printk ("%s: invalid broadcast top %d at level %d\n", rail->Name, state->bcast, lvl); -+ else if ((state->LNR & upmask) == upmask && (lstate->LNR & upmask) == upmask) -+ printk ("%s: no way up to switch at level %d (turned off ?)\n", rail->Name, lvl+1); -+ } -+ else -+ { -+ if (state->linkid != mylink) -+ printk ("%s: moved at top level was connected to link %d now connected to %d\n", rail->Name, mylink, state->linkid); -+ } -+ -+ if (state->linkid != mylink) -+ error++; -+ -+ if (BCAST_TOP_INVALID (lvl, state->bcast, ndown)) -+ binval++; -+ } -+ else -+ { -+ if (state->linkid != mylink) -+ { -+ if (state->linkid != rail->SwitchLast[lvl].linkid) -+ printk ("%s: moved at lvl %d was connected to link %d now connected to %d\n", rail->Name, lvl, mylink, state->linkid); -+ -+ error++; -+ } -+ } -+ -+ if (error == 0 && invalid == 0) -+ rail->SwitchProbeTick[lvl] = lbolt; -+ -+ EPRINTF10 (DBG_ROUTETABLE, "%s: lvl=%d (slvl=%d) linkid=%d bcast=%d lnr=%02x uplink=%d : error=%d binval=%d invalid=%d\n", -+ rail->Name, lvl, slvl, state->linkid, state->bcast, state->LNR, state->uplink, error, binval, invalid); -+ -+ invalid |= (error | binval); -+ } -+ -+ for (lvl = 0; lvl < rail->SwitchProbeLevel; lvl++) -+ if (rail->SwitchState[lvl].uplink != rail->SwitchLast[lvl].uplink) -+ changed++; -+ -+ if (changed) -+ { -+ printk ("%s: broadcast tree has changed from", rail->Name); -+ for (lvl = 0; lvl < rail->SwitchProbeLevel; lvl++) -+ printk ("%c%d", lvl == 0 ? ' ' : ',', rail->SwitchLast[lvl].uplink); -+ -+ for (lvl = 0; lvl < rail->SwitchProbeLevel; lvl++) -+ printk ("%s%d", lvl == 0 ? " to " : ",", rail->SwitchState[lvl].uplink); -+ printk ("\n"); -+ } -+ -+ if (rail->SwitchProbeLevel > 0) -+ bcopy (rail->SwitchState, rail->SwitchLast, rail->SwitchProbeLevel * sizeof (EP_SWITCHSTATE)); -+ } -+ -+ for (lvl = 0; lvl < pos->pos_levels; lvl++) -+ { -+ EPRINTF4 (DBG_ROUTETABLE, "%s: level %d lbolt=%lx ProbeLevelTick=%lx\n", -+ rail->Name, lvl, lbolt, rail->SwitchProbeTick[lvl]); -+ -+ if (AFTER (lbolt, rail->SwitchProbeTick[lvl] + EP_POSITION_TIMEOUT)) -+ { -+ if (lvl < rail->SwitchBroadcastLevel+1) -+ { -+ if (lvl == 0) -+ printk ("%s: cable disconnected\n", rail->Name); -+ else -+ printk ("%s: broadcast level has dropped to %d (should be %d)\n", -+ rail->Name, lvl, rail->Position.pos_levels); -+ } -+ break; -+ } -+ } -+ -+ if (lvl > rail->SwitchBroadcastLevel+1) -+ { -+ if (rail->SwitchBroadcastLevel < 0) -+ printk ("%s: cable reconnected\n", rail->Name); -+ if (lvl == rail->Position.pos_levels) -+ printk ("%s: broadcast level has recovered\n", rail->Name); -+ else -+ printk ("%s: broadcast level has recovered to %d (should be %d)\n", -+ rail->Name, lvl, rail->Position.pos_levels); -+ } -+ -+ if (rail->SwitchBroadcastLevel != (lvl - 1)) -+ { -+ EPRINTF2 (DBG_ROUTETABLE, "%s: setting SwitchBroadcastLevel to %d\n", rail->Name, lvl-1); -+ -+ rail->SwitchBroadcastLevel = lvl - 1; -+ rail->SwitchBroadcastLevelTick = lbolt; -+ } -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/probenetwork_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/probenetwork_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/probenetwork_elan3.c 2005-06-01 23:12:54.677427248 -0400 -@@ -0,0 +1,298 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: probenetwork_elan3.c,v 1.40 2004/04/15 12:30:08 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/probenetwork_elan3.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "debug.h" -+ -+#include -+ -+static void ep3_probe_event (EP3_RAIL *rail, void *arg); -+static EP3_COOKIE_OPS ep3_probe_ops = -+{ -+ ep3_probe_event -+} ; -+ -+int -+ep3_init_probenetwork (EP3_RAIL *rail) -+{ -+ sdramaddr_t stack; -+ E3_Addr sp; -+ E3_BlockCopyEvent event; -+ int i; -+ -+ if (! (stack = ep_alloc_elan (&rail->Generic, EP3_STACK_SIZE, 0, &rail->ProbeStack))) -+ return -ENOMEM; -+ -+ spin_lock_init (&rail->ProbeLock); -+ kcondvar_init (&rail->ProbeWait); -+ -+ /* Initialise the probe command structure */ -+ for (i = 0; i < TR_TRACEROUTE_ENTRIES; i++) -+ elan3_sdram_writew (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeSource0[i]), 0); -+ for (i = 0; i < TR_TRACEROUTE_ENTRIES; i++) -+ elan3_sdram_writew (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeSource1[i]), 1); -+ -+ RegisterCookie (&rail->CookieTable, &rail->ProbeCookie, rail->RailElanAddr + offsetof (EP3_RAIL_ELAN, ProbeDone), &ep3_probe_ops, rail); -+ -+ elan3_sdram_writel (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeStart.ev_Type), 0); -+ elan3_sdram_writel (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeStart.ev_Count), 0); -+ -+ EP3_INIT_COPY_EVENT (event, rail->ProbeCookie, rail->RailMainAddr + offsetof (EP3_RAIL_MAIN, ProbeDone), 1); -+ elan3_sdram_copyl_to_sdram (rail->Device, &event, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeDone), sizeof (E3_BlockCopyEvent)); -+ -+ rail->RailMain->ProbeDone = EP3_EVENT_FREE; -+ -+ sp = ep3_init_thread (rail->Device, ep_symbol (&rail->ThreadCode, "kcomm_probe"), -+ rail->ProbeStack, stack, EP3_STACK_SIZE, -+ 3, rail->CommandPortAddr, rail->RailElanAddr, rail->RailMainAddr); -+ -+ IssueRunThread (rail, sp); -+ -+ return 0; -+} -+ -+void -+ep3_destroy_probenetwork (EP3_RAIL *rail) -+{ -+ if (rail->ProbeStack == (sdramaddr_t) 0) -+ return; -+ -+ /* XXXX: ensure that the network probe thread is stopped */ -+ -+ DeregisterCookie (&rail->CookieTable, &rail->ProbeCookie); -+ -+ kcondvar_destroy (&rail->ProbeWait); -+ spin_lock_destroy (&rail->ProbeLock); -+ -+ ep_free_elan (&rail->Generic, rail->ProbeStack, EP3_STACK_SIZE); -+} -+ -+static void -+ep3_probe_event (EP3_RAIL *rail, void *arg) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->ProbeLock, flags); -+ rail->ProbeDone = 1; -+ kcondvar_wakeupone (&rail->ProbeWait, &rail->ProbeLock); -+ spin_unlock_irqrestore (&rail->ProbeLock, flags); -+} -+ -+int -+ep3_probe_route (EP_RAIL *r, int level, int sw, int nodeid, int *linkup, int *linkdown, int attempts, EP_SWITCH *lsw) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_RAIL_MAIN *railMain = rail->RailMain; -+ sdramaddr_t railElan = rail->RailElan; -+ E3_uint16 flits[MAX_FLITS]; -+ E3_uint32 result; -+ int nflits; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->ProbeLock, flags); -+ -+ nflits = GenerateProbeRoute ( flits, nodeid, level, linkup, linkdown, 0); -+ -+ if (LoadRoute (rail->Device, rail->RouteTable, EP_VP_PROBE(level), ELAN3_MRF_CONTEXT_NUM|SYS_CONTEXT_BIT, nflits, flits) != 0) -+ { -+ EPRINTF0 (DBG_ROUTETABLE, "ProbeRoute: cannot load route entry\n"); -+ spin_unlock_irqrestore (&rail->ProbeLock, flags); -+ return (EINVAL); -+ } -+ -+ do { -+ /* Initialise the probe source to include our partially computed nodeid */ -+ elan3_sdram_writew (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeSource0[TR_TRACEROUTE_ENTRIES-1]), nodeid); -+ elan3_sdram_writew (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeSource1[TR_TRACEROUTE_ENTRIES-1]), nodeid); -+ -+ /* Initialise the count result etc */ -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeType), PROBE_SINGLE); -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeLevel), level); -+ -+ railMain->ProbeResult = -1; -+ -+ /* Clear the receive area */ -+ bzero (railMain->ProbeDest0, sizeof (railMain->ProbeDest0)); -+ bzero (railMain->ProbeDest1, sizeof (railMain->ProbeDest1)); -+ -+ /* Re-arm the completion event */ -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeDone.ev_Count), 1); -+ railMain->ProbeDone = EP3_EVENT_ACTIVE; -+ rail->ProbeDone = 0; -+ -+ /* And wakeup the thread to do the probe */ -+ IssueSetevent (rail, rail->RailElanAddr + offsetof (EP3_RAIL_ELAN, ProbeStart)); -+ -+ /* Now wait for it to complete */ -+ while (! rail->ProbeDone) -+ kcondvar_wait (&rail->ProbeWait, &rail->ProbeLock, &flags); -+ -+ /* wait for block copy event to flush write buffers */ -+ while (! EP3_EVENT_FIRED (rail->ProbeCookie, railMain->ProbeDone)) -+ if (! EP3_EVENT_FIRING(rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeDone), rail->ProbeCookie, railMain->ProbeDone)) -+ panic ("ProbeRoute: network probe event failure\n"); -+ -+ result = railMain->ProbeResult; -+ -+ if (result == C_ACK_ERROR) -+ kcondvar_timedwait (&rail->ProbeWait, &rail->ProbeLock, &flags, lbolt + (hz/8)); -+ -+ railMain->ProbeDone = EP3_EVENT_FREE; -+ -+ } while (result != C_ACK_OK && --attempts); -+ -+ if (result == C_ACK_OK) -+ { -+ if (railMain->ProbeDest0[TR_TRACEROUTE_ENTRIES - ((2*level)+1) - 1] != nodeid || -+ railMain->ProbeDest1[TR_TRACEROUTE_ENTRIES - ((2*level)+1) - 1] != nodeid) -+ { -+ printk ("%s: lost nodeid at level %d switch %d - %d != %d\n", rail->Generic.Name, level, sw, -+ railMain->ProbeDest0[TR_TRACEROUTE_ENTRIES - ((2*level)+1) - 1], nodeid); -+ -+ result = C_ACK_ERROR; -+ } -+ else -+ { -+ E3_uint16 val0 = railMain->ProbeDest0[TR_TRACEROUTE_ENTRIES - level - 1]; -+ E3_uint16 val1 = railMain->ProbeDest1[TR_TRACEROUTE_ENTRIES - level - 1]; -+ -+ EPRINTF7 (DBG_PROBE, "%s: level %d switch %d - linkid=%d bcast=%d LNR=%02x%s\n", -+ rail->Generic.Name, level, sw, TR_TRACEROUTE0_LINKID(val0), -+ TR_TRACEROUTE1_BCAST_TOP(val1), TR_TRACEROUTE0_LNR(val0), -+ TR_TRACEROUTE0_REVID(val0) ? "" : " RevA Part"); -+ -+ lsw->lnr = TR_TRACEROUTE0_LNR(val0); -+ lsw->link = TR_TRACEROUTE0_LINKID(val0); -+ lsw->bcast = TR_TRACEROUTE1_BCAST_TOP(val1); -+ lsw->invalid = (TR_TRACEROUTE0_REVID(val0) == 0); -+ } -+ } -+ spin_unlock_irqrestore (&rail->ProbeLock, flags); -+ -+ return (result == C_ACK_OK); -+} -+ -+void -+ep3_probe_position_found (EP3_RAIL *rail, ELAN_POSITION *pos) -+{ -+ E3_uint16 flits[MAX_FLITS]; -+ int lvl, nflits; -+ -+ for (lvl = 0; lvl < pos->pos_levels; lvl++) -+ { -+ nflits = GenerateCheckRoute (pos, flits, pos->pos_levels - lvl - 1, 0); -+ -+ if (LoadRoute (rail->Device, rail->Ctxt->RouteTable, EP_VP_PROBE(lvl), ELAN3_MRF_CONTEXT_NUM|SYS_CONTEXT_BIT, nflits, flits) != 0) -+ panic ("ep3_probe_position_found: cannot load probe route entry\n"); -+ } -+ -+ /* Initialise the traceroute source data with our nodeid */ -+ elan3_sdram_writew (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeSource0[TR_TRACEROUTE_ENTRIES-1]), pos->pos_nodeid); -+ elan3_sdram_writew (rail->Device, rail->RailElan + offsetof (EP3_RAIL_ELAN, ProbeSource1[TR_TRACEROUTE_ENTRIES-1]), pos->pos_nodeid); -+} -+ -+int -+ep3_check_position (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ EP3_RAIL_MAIN *railMain = rail->RailMain; -+ sdramaddr_t railElan = rail->RailElan; -+ ELAN_POSITION *pos = &rail->Generic.Position; -+ unsigned int level = rail->RailMain->ProbeLevel; -+ unsigned int updated = EP3_EVENT_FIRED (rail->ProbeCookie, railMain->ProbeDone); -+ unsigned int lvl; -+ -+ if (updated) -+ { -+ if (railMain->ProbeResult != C_ACK_OK) -+ { -+ EPRINTF2 (DBG_PROBE, "%s: CheckNetworkPosition: packet nacked result=%d\n", rail->Generic.Name, railMain->ProbeResult); -+ -+ rail->Generic.SwitchProbeLevel = -1; -+ } -+ else -+ { -+ E3_uint16 val0 = railMain->ProbeDest0[TR_TRACEROUTE_ENTRIES - 2*(level+1)]; -+ E3_uint16 val1 = railMain->ProbeDest1[TR_TRACEROUTE_ENTRIES - 2*(level+1)]; -+ -+ if (val0 != pos->pos_nodeid || val1 != pos->pos_nodeid) -+ { -+ static unsigned long printed = 0; -+ -+ /* We've received a packet from another node - this probably means -+ * that we've moved */ -+ if ((lbolt - printed) > (HZ*10)) -+ { -+ printk ("%s: ep3_check_position - level %d lost nodeid\n", rail->Generic.Name, level); -+ printed = lbolt; -+ } -+ -+ rail->Generic.SwitchProbeLevel = -1; -+ } -+ else -+ { -+ for (lvl = 0; lvl <= level; lvl++) -+ { -+ E3_uint16 val0 = railMain->ProbeDest0[TR_TRACEROUTE_ENTRIES - ((2*level) - lvl + 1)]; -+ E3_uint16 val1 = railMain->ProbeDest1[TR_TRACEROUTE_ENTRIES - ((2*level) - lvl + 1)]; -+ -+ rail->Generic.SwitchState[lvl].linkid = TR_TRACEROUTE0_LINKID(val0); -+ rail->Generic.SwitchState[lvl].LNR = TR_TRACEROUTE0_LNR(val0); -+ rail->Generic.SwitchState[lvl].bcast = TR_TRACEROUTE1_BCAST_TOP(val1); -+ rail->Generic.SwitchState[lvl].uplink = 4; -+ -+ EPRINTF5 (DBG_PROBE, " --- lvl %d: linkid=%d LNR=%x bcast=%d uplink=%d\n", lvl, rail->Generic.SwitchState[lvl].linkid, -+ rail->Generic.SwitchState[lvl].LNR, rail->Generic.SwitchState[lvl].bcast ,rail->Generic.SwitchState[lvl].uplink); -+ } -+ rail->Generic.SwitchProbeLevel = level; -+ } -+ } -+ -+ railMain->ProbeDone = EP3_EVENT_FREE; -+ } -+ -+ if (railMain->ProbeDone == EP3_EVENT_FREE) -+ { -+ if (rail->Generic.SwitchBroadcastLevel == rail->Generic.Position.pos_levels-1) -+ level = rail->Generic.Position.pos_levels - 1; -+ else -+ level = rail->Generic.SwitchBroadcastLevel + 1; -+ -+ EPRINTF2 (DBG_PROBE, "%s: ep3_check_postiion: level %d\n", rail->Generic.Name, level); -+ -+ /* Initialise the count result etc */ -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeType), PROBE_MULTIPLE); -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeLevel), level); -+ -+ railMain->ProbeResult = -1; -+ railMain->ProbeLevel = -1; -+ -+ /* Clear the receive area */ -+ bzero (railMain->ProbeDest0, sizeof (railMain->ProbeDest0)); -+ bzero (railMain->ProbeDest1, sizeof (railMain->ProbeDest1)); -+ -+ /* Re-arm the completion event */ -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeDone.ev_Type), EV_TYPE_BCOPY); -+ elan3_sdram_writel (rail->Device, railElan + offsetof (EP3_RAIL_ELAN, ProbeDone.ev_Count), 1); -+ -+ railMain->ProbeDone = EP3_EVENT_ACTIVE; -+ -+ IssueSetevent (rail, rail->RailElanAddr + offsetof (EP3_RAIL_ELAN, ProbeStart)); -+ } -+ -+ return updated; -+} -+ -Index: linux-2.4.21/drivers/net/qsnet/ep/probenetwork_elan3_thread.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/probenetwork_elan3_thread.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/probenetwork_elan3_thread.c 2005-06-01 23:12:54.678427096 -0400 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: probenetwork_elan3_thread.c,v 1.19 2004/03/24 11:32:56 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/probenetwork_elan3_thread.c,v $*/ -+ -+#include -+#include -+#include -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+ -+static int -+kcomm_probe_vp (EP3_RAIL_ELAN *railElan, EP3_RAIL_MAIN *railMain, int vp, int attempts, int timeouts) -+{ -+ int rc; -+ -+ /* Since we use %g1 to hold the "rxd" so the trap handler can -+ * complete the envelope processing - we pass zero to indicate we're -+ * not a receiver thread */ -+ asm volatile ("mov %g0, %g1"); -+ -+ while (attempts && timeouts) -+ { -+ c_open (vp); -+ c_sendmem (TR_TRACEROUTE, &railMain->ProbeDest0, &railElan->ProbeSource0); -+ c_sendmem (TR_TRACEROUTE, &railMain->ProbeDest1, &railElan->ProbeSource1); -+ c_sendtrans0 (TR_SENDACK | TR_SETEVENT, (E3_Addr) 0); -+ -+ switch (rc = c_close()) -+ { -+ case C_ACK_OK: -+ return (C_ACK_OK); -+ -+ case C_ACK_DISCARD: -+ attempts--; -+ break; -+ -+ default: /* output timeout */ -+ timeouts--; -+ } -+ -+ c_break_busywait(); -+ } -+ -+ return (timeouts == 0 ? C_ACK_ERROR : C_ACK_DISCARD); -+} -+ -+void -+kcomm_probe (E3_CommandPort *cport, EP3_RAIL_ELAN *railElan, EP3_RAIL_MAIN *railMain) -+{ -+ int level; -+ -+ for (;;) -+ { -+ c_waitevent (&railElan->ProbeStart, 1); -+ -+ switch (railElan->ProbeType) -+ { -+ case PROBE_SINGLE: -+ railMain->ProbeResult = kcomm_probe_vp (railElan, railMain, EP_VP_PROBE(railElan->ProbeLevel), -+ PROBE_SINGLE_ATTEMPTS, PROBE_SINGLE_TIMEOUTS); -+ -+ cport->SetEvent = (E3_Addr) &railElan->ProbeDone; -+ break; -+ -+ case PROBE_MULTIPLE: -+ for (level = railElan->ProbeLevel; level >= 0; level--) -+ { -+ if (kcomm_probe_vp (railElan, railMain, EP_VP_PROBE(level), -+ PROBE_MULTIPLE_ATTEMPTS, PROBE_MULTIPLE_TIMEOUTS) == C_ACK_OK) -+ { -+ railMain->ProbeLevel = level; -+ railMain->ProbeResult = C_ACK_OK; -+ break; -+ } -+ -+ c_break_busywait(); -+ } -+ cport->SetEvent = (E3_Addr) &railElan->ProbeDone; -+ break; -+ } -+ -+ } -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/probenetwork_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/probenetwork_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/probenetwork_elan4.c 2005-06-01 23:12:54.679426944 -0400 -@@ -0,0 +1,396 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: probenetwork_elan4.c,v 1.9 2004/08/19 11:05:03 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/probenetwork_elan4.c,v $*/ -+ -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "debug.h" -+ -+#include -+#include -+ -+static void -+probe_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_probe_lock, flags); -+ rail->r_probe_done = 1; -+ kcondvar_wakeupone (&rail->r_probe_wait, &rail->r_probe_lock); -+ spin_unlock_irqrestore (&rail->r_probe_lock, flags); -+} -+ -+int -+ep4_probe_init (EP4_RAIL *rail) -+{ -+ spin_lock_init (&rail->r_probe_lock); -+ kcondvar_init (&rail->r_probe_wait); -+ -+ rail->r_probe_cq = ep4_alloc_ecq (rail, CQ_Size1K); -+ -+ if (rail->r_probe_cq == NULL) -+ return -ENOMEM; -+ -+ ep4_register_intcookie (rail, &rail->r_probe_intcookie, rail->r_elan_addr, probe_interrupt, rail); -+ -+ return 0; -+} -+ -+void -+ep4_probe_destroy (EP4_RAIL *rail) -+{ -+ if (rail->r_probe_cq) -+ ep4_free_ecq (rail, rail->r_probe_cq); -+ -+ if (rail->r_probe_intcookie.int_arg == NULL) -+ return; -+ ep4_deregister_intcookie (rail, &rail->r_probe_intcookie); -+ -+ kcondvar_destroy (&rail->r_probe_wait); -+ spin_lock_destroy (&rail->r_probe_lock); -+} -+ -+#define LINKDOWN(nodeid, level) ((nodeid >> (level << 1)) & 3) -+#define PROBE_PATTERN0(nodeid) (0xaddebabe ^ nodeid) -+#define PROBE_PATTERN1(nodeid) (0xfeedbeef ^ nodeid) -+ -+#define EP4_PROBE_RETRIES 4 -+ -+int -+ep4_probe_route (EP_RAIL *r, int level, int sw, int nodeid, int *linkup, int *linkdown, int attempts, EP_SWITCH *lsw) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ EP4_RAIL_MAIN *rmain = rail->r_main; -+ E4_uint16 first = 0; -+ int rb = 0; -+ -+ E4_uint8 packed[ROUTE_NUM_PACKED]; -+ E4_VirtualProcessEntry route; -+ unsigned long flags; -+ int i; -+ -+ for (i = 0; i < ROUTE_NUM_PACKED; i++) -+ packed[i] = 0; -+ -+ /* Generate "up" routes */ -+ for (i = 0; i < level; i++) -+ if (first == 0) -+ first = linkup ? FIRST_ROUTE(linkup[i]) : FIRST_ADAPTIVE; -+ else -+ packed[rb++] = linkup ? PACKED_ROUTE(linkup[i]) : PACKED_ADAPTIVE; -+ -+ /* Generate a "to-me" route down */ -+ if (first == 0) -+ first = FIRST_MYLINK; -+ else -+ packed[rb++] = PACKED_MYLINK; -+ -+ /* Generate the "down" routes */ -+ for (i = level-1; i >= 0; i--) -+ packed[rb++] = linkdown ? PACKED_ROUTE(linkdown[i]) : PACKED_ROUTE(LINKDOWN(nodeid, i)); -+ -+ /* Pack up the routes into the virtual process entry */ -+ route.Values[0] = first | FIRST_HIGH_PRI | FIRST_SYSTEM_PACKET | FIRST_TIMEOUT(3); -+ route.Values[1] = ROUTE_CTXT_VALUE(ELAN4_KCOMM_CONTEXT_NUM); -+ -+ for (i = 0; i < (ROUTE_NUM_PACKED >> 1); i++) -+ { -+ route.Values[0] |= ((E4_uint64) packed[i]) << ((i << 2) + ROUTE_PACKED_OFFSET); -+ route.Values[1] |= ((E4_uint64) packed[i+(ROUTE_NUM_PACKED >> 1)]) << ((i << 2)); -+ } -+ -+ elan4_write_route (rail->r_ctxt.ctxt_dev, rail->r_routetable, EP_VP_PROBE(level), &route); -+ -+ while (attempts--) -+ { -+ rail->r_probe_done = 0; -+ -+ /* generate the STEN packet - note we use a datatype of dword as we're copying to elan in dwords -+ * NB - no flow control is required, since the max packet size is less than the command queue -+ * size and it's dedicated for network probing. -+ */ -+ -+ elan4_guard (rail->r_probe_cq->ecq_cq, GUARD_CHANNEL(1) | GUARD_RESET(EP4_PROBE_RETRIES)); -+ elan4_nop_cmd (rail->r_probe_cq->ecq_cq, 0); -+ -+ elan4_open_packet (rail->r_probe_cq->ecq_cq, OPEN_STEN_PKT_CMD | OPEN_PACKET(0, PACK_OK | RESTART_COUNT_ZERO, EP_VP_PROBE(level))); -+ elan4_sendtransn (rail->r_probe_cq->ecq_cq, TR_TRACEROUTE(TRACEROUTE_NDWORDS), -+ rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_dest0), -+ 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, -+ 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull, 0x0000000000000000ull | ((E4_uint64)PROBE_PATTERN0(nodeid) << 32)); -+ elan4_sendtransn (rail->r_probe_cq->ecq_cq, TR_TRACEROUTE(TRACEROUTE_NDWORDS), -+ rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_dest1), -+ 0x0000000100000001ull, 0x0000000100000001ull, 0x0000000100000001ull, 0x0000000100000001ull, -+ 0x0000000100000001ull, 0x0000000100000001ull, 0x0000000100000001ull, 0x0000000000000001ull | ((E4_uint64)PROBE_PATTERN1(nodeid) << 32)); -+ elan4_sendtrans0 (rail->r_probe_cq->ecq_cq, TR_NOP_TRANS | TR_LAST_AND_SEND_ACK, 0); -+ -+ elan4_guard (rail->r_probe_cq->ecq_cq, GUARD_CHANNEL(1) | GUARD_TEST(0, PACK_OK) | GUARD_RESET(EP4_PROBE_RETRIES)); -+ elan4_write_dword_cmd (rail->r_probe_cq->ecq_cq, rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_result), EP4_STATE_FINISHED); -+ -+ elan4_guard (rail->r_probe_cq->ecq_cq, GUARD_CHANNEL(1) | GUARD_TEST(0, RESTART_COUNT_ZERO) | GUARD_RESET(EP4_PROBE_RETRIES)); -+ elan4_write_dword_cmd (rail->r_probe_cq->ecq_cq, rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_result), EP4_STATE_FAILED); -+ -+ elan4_interrupt_cmd (rail->r_probe_cq->ecq_cq, rail->r_probe_intcookie.int_val); -+ -+ spin_lock_irqsave (&rail->r_probe_lock, flags); -+ while (! rail->r_probe_done) -+ kcondvar_wait (&rail->r_probe_wait, &rail->r_probe_lock, &flags); -+ spin_unlock_irqrestore (&rail->r_probe_lock, flags); -+ -+ if (rmain->r_probe_result == EP4_STATE_FINISHED) -+ { -+ if (rmain->r_probe_dest0[TRACEROUTE_ENTRIES - ((2*level)+1) - 1] != PROBE_PATTERN0(nodeid) || -+ rmain->r_probe_dest1[TRACEROUTE_ENTRIES - ((2*level)+1) - 1] != PROBE_PATTERN1(nodeid)) -+ { -+ printk ("%s: lost nodeid at level %d switch %d - %d != %d\n", rail->r_generic.Name, level, sw, -+ rmain->r_probe_dest0[TRACEROUTE_ENTRIES - ((2*level)+1) - 1], PROBE_PATTERN0(nodeid)); -+ } -+ else -+ { -+ E4_uint32 val0 = rmain->r_probe_dest0[TRACEROUTE_ENTRIES - level - 1]; -+ E4_uint32 val1 = rmain->r_probe_dest1[TRACEROUTE_ENTRIES - level - 1]; -+ -+ lsw->lnr = TR_TRACEROUTE0_LNR(val0); -+ lsw->link = TR_TRACEROUTE0_LINKID(val0); -+ lsw->bcast = TR_TRACEROUTE1_BCAST_TOP(val1); -+ lsw->invalid = 0; -+ -+ return 1; -+ } -+ } -+ -+ rmain->r_probe_result = EP4_STATE_FREE; -+ } -+ -+ return 0; -+} -+ -+ -+void -+ep4_probe_position_found (EP4_RAIL *rail, ELAN_POSITION *pos) -+{ -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ int lvl; -+ -+ for (lvl = 0; lvl < pos->pos_levels; lvl++) -+ { -+ /* Initialise the "probe" route to use the broadcast tree */ -+ ELAN_POSITION *pos = &rail->r_generic.Position; -+ unsigned char *arityp = &pos->pos_arity[pos->pos_levels - 1]; -+ unsigned int spanned = *arityp; -+ E4_uint16 first = 0; -+ int rb = 0; -+ -+ E4_uint8 packed[ROUTE_NUM_PACKED]; -+ E4_VirtualProcessEntry route; -+ int i; -+ -+ for (i = 0; i < ROUTE_NUM_PACKED; i++) -+ packed[i] = 0; -+ -+ /* Generate "up" routes */ -+ for (i = 0; i < lvl; i++, spanned *= *(--arityp)) -+ { -+ if (first == 0) -+ first = FIRST_BCAST_TREE; -+ else -+ packed[rb++] = PACKED_BCAST_TREE; -+ } -+ -+ /* Generate a "to-me" route down */ -+ if (first == 0) -+ first = FIRST_MYLINK; -+ else -+ packed[rb++] = PACKED_MYLINK; -+ -+ spanned /= *arityp++; -+ -+ /* Generate the "down" routes */ -+ for (i = lvl-1; i >= 0; i--) -+ { -+ spanned /= *arityp; -+ packed[rb++] = PACKED_ROUTE((pos->pos_nodeid / spanned) % *arityp); -+ arityp++; -+ } -+ -+ -+ /* Pack up the routes into the virtual process entry */ -+ route.Values[0] = first | FIRST_HIGH_PRI | FIRST_SYSTEM_PACKET | FIRST_TIMEOUT(3); -+ route.Values[1] = ROUTE_CTXT_VALUE(ELAN4_KCOMM_CONTEXT_NUM); -+ -+ for (i = 0; i < (ROUTE_NUM_PACKED >> 1); i++) -+ { -+ route.Values[0] |= ((E4_uint64) packed[i]) << ((i << 2) + ROUTE_PACKED_OFFSET); -+ route.Values[1] |= ((E4_uint64) packed[i+(ROUTE_NUM_PACKED >> 1)]) << ((i << 2)); -+ } -+ -+ elan4_write_route (rail->r_ctxt.ctxt_dev, rail->r_routetable, EP_VP_PROBE(lvl), &route); -+ -+ /* Initialise "start" event for this level */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_start[lvl].ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_CHECK_STEN_NDWORDS)); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_start[lvl].ev_CopySource), -+ rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl])); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_start[lvl].ev_CopyDest), -+ rail->r_probe_cq->ecq_addr); -+ -+ /* Initiailise command stream - reset the start event */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_reset_event_cmd), -+ WRITE_DWORD_CMD | (rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_check_start[lvl]))); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_reset_event_value), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, EP4_CHECK_STEN_NDWORDS)); -+ -+ /* Initiailise command stream - sten traceroute packet */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_open), -+ OPEN_STEN_PKT_CMD | OPEN_PACKET (0, PACK_OK | RESTART_COUNT_ZERO, EP_VP_PROBE(lvl))); -+ -+ /* Initiailise command stream - traceroute 0 */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_trans_traceroute0), -+ SEND_TRANS_CMD | (TR_TRACEROUTE(TRACEROUTE_NDWORDS) << 16)); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_addr_traceroute0), -+ rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_dest0)); -+ for (i = 0; i < (TRACEROUTE_NDWORDS-1); i++) -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_data_traceroute0[i]), -+ 0x0000000000000000ull); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_data_traceroute0[i]), -+ 0x0000000000000000ull | ((E4_uint64) PROBE_PATTERN0(pos->pos_nodeid) << 32)); -+ -+ /* Initiailise command stream - traceroute 1 */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_trans_traceroute1), -+ SEND_TRANS_CMD | (TR_TRACEROUTE(TRACEROUTE_NDWORDS) << 16)); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_addr_traceroute1), -+ rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_dest1)); -+ for (i = 0; i < (TRACEROUTE_NDWORDS-1); i++) -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_data_traceroute1[i]), -+ 0x0000000100000001ull); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_data_traceroute1[i]), -+ 0x0000000000000001ull | ((E4_uint64) PROBE_PATTERN1(pos->pos_nodeid) << 32)); -+ -+ /* Initiailise command stream - null sendack */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_trans_sendack), -+ SEND_TRANS_CMD | ((TR_NOP_TRANS | TR_LAST_AND_SEND_ACK) << 16)); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_addr_sendack), -+ 0); -+ -+ /* Initiailise command stream - guard ok, write done */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_guard_ok), -+ GUARD_CMD | GUARD_CHANNEL(1) | GUARD_TEST(0, PACK_OK) | GUARD_RESET(EP4_PROBE_RETRIES)); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_writedword_ok), -+ WRITE_DWORD_CMD | (rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_level))); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_value_ok), -+ lvl); -+ -+ /* Initiailise command stream - guard fail, chain to next or write done */ -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_guard_fail), -+ GUARD_CMD | GUARD_CHANNEL(1) | GUARD_TEST(0, RESTART_COUNT_ZERO) | GUARD_RESET(EP4_PROBE_RETRIES)); -+ -+ if (lvl > 0) -+ { -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_setevent_fail), -+ SET_EVENT_CMD | (rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_check_start[lvl-1]))); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_setevent_nop), -+ NOP_CMD); -+ } -+ else -+ { -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_setevent_fail), -+ WRITE_DWORD_CMD | (rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_probe_level))); -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_setevent_nop), -+ EP4_PROBE_FAILED); -+ } -+ elan4_sdram_writeq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_check_sten[lvl].c_nop_pad), -+ NOP_CMD); -+ } -+ -+ -+ rail->r_main->r_probe_level = EP4_PROBE_ACTIVE; -+ -+ mb(); -+ ep4_set_event_cmd (rail->r_probe_cq, rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_check_start[pos->pos_levels-1])); -+} -+ -+int -+ep4_check_position (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ ELAN_POSITION *pos = &rail->r_generic.Position; -+ unsigned int level = rail->r_main->r_probe_level; -+ unsigned int lvl; -+ -+ EPRINTF2 (DBG_PROBE, "%s: ep4_check_position: level=%lld\n", rail->r_generic.Name, rail->r_main->r_probe_level); -+ -+ if (rail->r_main->r_probe_level != EP4_PROBE_ACTIVE) -+ { -+ if (rail->r_main->r_probe_level == EP4_PROBE_FAILED) -+ { -+ EPRINTF1 (DBG_PROBE, "%s: ep4_check_position: packets all nacked\n", rail->r_generic.Name); -+ -+ rail->r_generic.SwitchProbeLevel = -1; -+ } -+ else -+ { -+ E4_uint32 val0 = rail->r_main->r_probe_dest0[TRACEROUTE_ENTRIES - 2*(level+1)]; -+ E4_uint32 val1 = rail->r_main->r_probe_dest1[TRACEROUTE_ENTRIES - 2*(level+1)]; -+ -+ if (val0 != PROBE_PATTERN0 (pos->pos_nodeid) || val1 != PROBE_PATTERN1 (pos->pos_nodeid)) -+ { -+ static unsigned long printed = 0; -+ -+ /* We've received a packet from another node - this probably means -+ * that we've moved */ -+ if ((lbolt - printed) > (HZ*10)) -+ { -+ printk ("%s: ep4_check_position - level %d lost nodeid\n", rail->r_generic.Name, level); -+ printed = lbolt; -+ } -+ -+ rail->r_generic.SwitchProbeLevel = -1; -+ } -+ else -+ { -+ for (lvl = 0 ; lvl <= level; lvl++) -+ { -+ E4_uint32 uval0 = rail->r_main->r_probe_dest0[TRACEROUTE_ENTRIES - lvl - 1]; -+ E4_uint32 dval0 = rail->r_main->r_probe_dest0[TRACEROUTE_ENTRIES - ((2*level) - lvl + 1)]; -+ E4_uint32 dval1 = rail->r_main->r_probe_dest1[TRACEROUTE_ENTRIES - ((2*level) - lvl + 1)]; -+ -+ rail->r_generic.SwitchState[lvl].linkid = TR_TRACEROUTE0_LINKID (dval0); -+ rail->r_generic.SwitchState[lvl].LNR = TR_TRACEROUTE0_LNR(dval0); -+ rail->r_generic.SwitchState[lvl].bcast = TR_TRACEROUTE1_BCAST_TOP (dval1); -+ rail->r_generic.SwitchState[lvl].uplink = TR_TRACEROUTE0_LINKID (uval0); -+ -+ EPRINTF5 (DBG_PROBE, " --- lvl %d: linkid=%d LNR=%x bcast=%d uplink=%d\n", lvl, rail->r_generic.SwitchState[lvl].linkid, -+ rail->r_generic.SwitchState[lvl].LNR, rail->r_generic.SwitchState[lvl].bcast ,rail->r_generic.SwitchState[lvl].uplink); -+ -+ } -+ -+ rail->r_generic.SwitchProbeLevel = level; -+ } -+ } -+ -+ rail->r_main->r_probe_level = EP4_PROBE_ACTIVE; -+ mb(); -+ -+ if (rail->r_generic.SwitchBroadcastLevel == rail->r_generic.Position.pos_levels-1) -+ level = rail->r_generic.Position.pos_levels - 1; -+ else -+ level = rail->r_generic.SwitchBroadcastLevel + 1; -+ -+ ep4_set_event_cmd (rail->r_probe_cq, rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_check_start[level])); -+ -+ return 1; -+ } -+ -+ return 0; -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/procfs_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/procfs_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/procfs_linux.c 2005-06-01 23:12:54.680426792 -0400 -@@ -0,0 +1,693 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: procfs_linux.c,v 1.53.2.4 2005/01/18 14:18:42 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/procfs_linux.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "cm.h" -+#include "debug.h" -+#include "conf_linux.h" -+#include -+#include -+#include -+ -+#include -+ -+struct proc_dir_entry *ep_procfs_root; -+struct proc_dir_entry *ep_config_root; -+ -+/* -+ * We provide a slightly "special" interface for /proc/elan/device%d/nodeset, -+ * so that it can be included in a "poll" system call. On each "read" on the -+ * file, we generate a new nodeset if a) the previous one has been completely -+ * read and b) if it has changed since it was generated. -+ * -+ * Unfortunately ... this doesn't allow "tail -f" to work, since this uses -+ * fstat() on the fd, as we only hold the last nodeset string, we could not -+ * handle the case where two processes were reading a different rates. -+ * We could maybe have implemented this as a "sliding window", so that we -+ * add a new nodeset string, when it has changed and someone reads past -+ * end of the last one. Then if someone read from before out "window" -+ * we would produce "padding" data. The problem with this, is that a -+ * simple "cat" on /proc/elan/device%d/nodeset will read the whole "file" -+ * which will be mostly padding ! -+ * -+ * Just to not that the purpose of this interface is: -+ * 1) to allow cat /proc/elan/device%d/nodeset to show the current -+ * nodeset. -+ * 2) to allow rms (or similar) to poll() on the file, and when the -+ * nodeset changes read a new one. -+ * -+ * so ... we don't bother solving the troublesome "tail -f" problem. -+ */ -+ -+typedef struct nodeset_private -+{ -+ struct nodeset_private *pr_next; -+ EP_RAIL *pr_rail; -+ unsigned pr_changed; -+ char *pr_page; -+ unsigned pr_off; -+ unsigned pr_len; -+} NODESET_PRIVATE; -+ -+NODESET_PRIVATE *ep_nodeset_list; -+wait_queue_head_t ep_nodeset_wait; -+spinlock_t ep_nodeset_lock; -+ -+static int -+proc_write_state(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ EP_RAIL *rail = (EP_RAIL *) data; -+ char tmpbuf[128]; -+ int res; -+ -+ if (count > sizeof (tmpbuf)-1) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ -+ if (copy_from_user (tmpbuf, buffer, count)) -+ res = -EFAULT; -+ else -+ { -+ tmpbuf[count] = '\0'; -+ -+ if (tmpbuf[count-1] == '\n') -+ tmpbuf[count-1] = '\0'; -+ -+ if (! strcmp (tmpbuf, "start") && rail->State == EP_RAIL_STATE_UNINITIALISED) -+ ep_start_rail (rail); -+ -+ if (! strcmp (tmpbuf, "stop") && rail->State > EP_RAIL_STATE_UNINITIALISED) -+ ep_stop_rail (rail); -+ -+ if (! strcmp (tmpbuf, "offline") && rail->State > EP_RAIL_STATE_UNINITIALISED) -+ cm_force_offline (rail, 1, CM_OFFLINE_PROCFS); -+ -+ if (! strcmp (tmpbuf, "online") && rail->State > EP_RAIL_STATE_UNINITIALISED) -+ cm_force_offline (rail, 0, CM_OFFLINE_PROCFS); -+ -+ if (! strncmp (tmpbuf, "restart=", 8) && rail->State == EP_RAIL_STATE_RUNNING) -+ cm_restart_node (rail, simple_strtol (tmpbuf + 8, NULL, 0)); -+ -+ if (! strncmp (tmpbuf, "panic=", 6)) -+ ep_panic_node (rail->System, simple_strtol(tmpbuf + 6, NULL, 0), -+ strchr (tmpbuf, ',') ? strchr(tmpbuf, ',') + 1 : "remote panic request"); -+ -+ if (! strncmp (tmpbuf, "raise=", 6) && rail->State > EP_RAIL_STATE_UNINITIALISED) -+ rail->Operations.RaiseFilter (rail, simple_strtol (tmpbuf + 6, NULL, 0)); -+ -+ if (! strncmp (tmpbuf, "lower=", 6) && rail->State > EP_RAIL_STATE_UNINITIALISED) -+ rail->Operations.LowerFilter (rail, simple_strtol (tmpbuf + 6, NULL, 0)); -+ -+ res = count; -+ } -+ -+ MOD_DEC_USE_COUNT; -+ -+ return (res); -+} -+ -+static int -+proc_read_state(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_RAIL *rail = (EP_RAIL *) data; -+ int len; -+ -+ switch (rail->State) -+ { -+ case EP_RAIL_STATE_UNINITIALISED: -+ len = sprintf (page, "uninitialised\n"); -+ break; -+ case EP_RAIL_STATE_STARTED: -+ len = sprintf (page, "started\n"); -+ break; -+ case EP_RAIL_STATE_RUNNING: -+ len = sprintf (page, "running NodeId=%d NumNodes=%d\n", rail->Position.pos_nodeid, rail->Position.pos_nodes); -+ break; -+ case EP_RAIL_STATE_INCOMPATIBLE: -+ len = sprintf (page, "incompatible NodeId=%d NumNodes=%d\n", rail->Position.pos_nodeid, rail->Position.pos_nodes); -+ break; -+ default: -+ len = sprintf (page, "\n"); -+ break; -+ } -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+static int -+proc_write_display(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ EP_RAIL *rail = (EP_RAIL *) data; -+ char tmpbuf[128]; -+ int res; -+ -+ if (count > sizeof (tmpbuf)-1) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ -+ if (copy_from_user (tmpbuf, buffer, count)) -+ res = -EFAULT; -+ else -+ { -+ tmpbuf[count] = '\0'; -+ -+ if (tmpbuf[count-1] == '\n') -+ tmpbuf[count-1] = '\0'; -+ -+ if (! strcmp (tmpbuf, "rail")) -+ DisplayRail (rail); -+ if (! strcmp (tmpbuf, "segs")) -+ DisplaySegs (rail); -+ if (! strcmp (tmpbuf, "nodes")) -+ DisplayNodes (rail); -+ if (! strcmp (tmpbuf, "status")) -+ DisplayStatus (rail); -+ if (! strcmp (tmpbuf, "debug") && rail->Operations.Debug) -+ rail->Operations.Debug (rail); -+ if (! strncmp (tmpbuf, "epcomms", 7)) -+ ep_comms_display (rail->System, tmpbuf[7] == '=' ? tmpbuf + 8 : NULL); -+ res = count; -+ } -+ -+ MOD_DEC_USE_COUNT; -+ -+ return (res); -+} -+ -+static int -+proc_read_display(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = sprintf (page, "\n"); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+ -+static int -+proc_read_stats(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_RAIL *rail = (EP_RAIL *) data; -+ -+ if ( rail == NULL ) { -+ strcpy(page,"proc_read_stats rail=NULL\n"); -+ } else { -+ page[0] = 0; -+ ep_fillout_stats(rail, page); -+ rail->Operations.FillOutStats (rail, page); -+ } -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, strlen(page))); -+} -+ -+static int -+proc_read_devinfo(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ EP_RAIL *rail = (EP_RAIL *) data; -+ ELAN_DEVINFO *devinfo = &rail->Devinfo; -+ ELAN_POSITION *pos = &rail->Position; -+ char *p = page; -+ -+ switch (devinfo->dev_device_id) -+ { -+ case PCI_DEVICE_ID_ELAN3: -+ p += sprintf (p, "ep%d is elan3 %d rev %c\n", rail->Number, -+ devinfo->dev_instance, 'a' + devinfo->dev_revision_id); -+ break; -+ -+ case PCI_DEVICE_ID_ELAN4: -+ p += sprintf (p, "ep%d is elan4 %d rev %c\n", rail->Number, -+ devinfo->dev_instance, 'a' + devinfo->dev_revision_id); -+ break; -+ default: -+ p += sprintf (p, "ep%d is unkown %x/%x\n", rail->Number, devinfo->dev_vendor_id, devinfo->dev_device_id); -+ break; -+ } -+ -+ if (rail->State == EP_RAIL_STATE_RUNNING) -+ p += sprintf (p, "ep%d nodeid %d numnodes %d\n", rail->Number, pos->pos_nodeid, pos->pos_nodes); -+ -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, p - page)); -+} -+ -+static struct rail_info -+{ -+ char *name; -+ int (*read_func) (char *page, char **start, off_t off, int count, int *eof, void *data); -+ int (*write_func) (struct file *file, const char *buf, unsigned long count, void *data); -+} rail_info[] = { -+ {"state", proc_read_state, proc_write_state}, -+ {"display", proc_read_display, proc_write_display}, -+ {"stats", proc_read_stats, NULL}, -+ {"devinfo", proc_read_devinfo, NULL}, -+}; -+ -+static int -+nodeset_open (struct inode *inode, struct file *file) -+{ -+ NODESET_PRIVATE *pr; -+ -+ if ((pr = kmalloc (sizeof (NODESET_PRIVATE), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ pr->pr_changed = 1; -+ pr->pr_off = 0; -+ pr->pr_len = 0; -+ pr->pr_page = NULL; -+ pr->pr_rail = (EP_RAIL *)( PDE(inode)->data ); -+ -+ spin_lock (&ep_nodeset_lock); -+ pr->pr_next = ep_nodeset_list; -+ ep_nodeset_list = pr; -+ spin_unlock (&ep_nodeset_lock); -+ -+ file->private_data = (void *) pr; -+ -+ MOD_INC_USE_COUNT; -+ return (0); -+} -+ -+static int -+nodeset_release (struct inode *inode, struct file *file) -+{ -+ NODESET_PRIVATE *pr = (NODESET_PRIVATE *) file->private_data; -+ NODESET_PRIVATE **ppr; -+ -+ spin_lock (&ep_nodeset_lock); -+ for (ppr = &ep_nodeset_list; (*ppr) != pr; ppr = &(*ppr)->pr_next) -+ ; -+ (*ppr) = pr->pr_next; -+ spin_unlock (&ep_nodeset_lock); -+ -+ if (pr->pr_page) -+ free_page ((unsigned long) pr->pr_page); -+ kfree (pr); -+ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static ssize_t -+nodeset_read (struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ NODESET_PRIVATE *pr = (NODESET_PRIVATE *) file->private_data; -+ EP_RAIL *rail = pr->pr_rail; -+ int error; -+ unsigned long flags; -+ -+ if (!pr->pr_changed && pr->pr_off >= pr->pr_len) -+ return (0); -+ -+ if ((error = verify_area (VERIFY_WRITE, buf, count)) != 0) -+ return (error); -+ -+ if (pr->pr_page == NULL && (pr->pr_page = (char *) __get_free_page (GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ if (pr->pr_off >= pr->pr_len) -+ { -+ kmutex_lock (&rail->CallbackLock); -+ if (rail->State == EP_RAIL_STATE_RUNNING) -+ { -+ spin_lock_irqsave (&rail->System->NodeLock, flags); -+ ep_sprintf_bitmap (pr->pr_page, PAGESIZE, statemap_tobitmap(rail->NodeSet), 0, 0, rail->Position.pos_nodes); -+ spin_unlock_irqrestore (&rail->System->NodeLock, flags); -+ -+ if (rail->SwitchBroadcastLevel == -1) -+ strcat (pr->pr_page, ""); -+ else if (rail->SwitchBroadcastLevel < (rail->Position.pos_levels-1)) -+ sprintf (pr->pr_page + strlen (pr->pr_page), "<%d>", rail->SwitchBroadcastLevel); -+ strcat (pr->pr_page, "\n"); -+ } -+ else -+ strcpy (pr->pr_page, "\n"); -+ kmutex_unlock (&rail->CallbackLock); -+ -+ pr->pr_len = strlen (pr->pr_page); -+ pr->pr_off = 0; -+ pr->pr_changed = 0; -+ } -+ -+ if (count >= (pr->pr_len - pr->pr_off)) -+ count = pr->pr_len - pr->pr_off; -+ -+ copy_to_user (buf, pr->pr_page + pr->pr_off, count); -+ -+ pr->pr_off += count; -+ *ppos += count; -+ -+ if (pr->pr_off >= pr->pr_len) -+ { -+ free_page ((unsigned long) pr->pr_page); -+ pr->pr_page = NULL; -+ } -+ -+ return (count); -+} -+ -+static unsigned int -+nodeset_poll (struct file *file, poll_table *wait) -+{ -+ NODESET_PRIVATE *pr = (NODESET_PRIVATE *) file->private_data; -+ -+ poll_wait (file, &ep_nodeset_wait, wait); -+ if (pr->pr_changed || pr->pr_off < pr->pr_len) -+ return (POLLIN | POLLRDNORM); -+ return (0); -+} -+ -+static void -+nodeset_callback (void *arg, statemap_t *map) -+{ -+ EP_RAIL *rail = (EP_RAIL *) arg; -+ NODESET_PRIVATE *pr; -+ -+ ep_display_bitmap (rail->Name, "Nodeset", statemap_tobitmap(map), 0, ep_numnodes(rail->System)); -+ -+ spin_lock (&ep_nodeset_lock); -+ for (pr = ep_nodeset_list; pr; pr = pr->pr_next) -+ if (pr->pr_rail == rail) -+ pr->pr_changed = 1; -+ spin_unlock (&ep_nodeset_lock); -+ -+ wake_up_interruptible (&ep_nodeset_wait); -+} -+ -+void -+proc_character_fill (long mode, char *fmt, ...) -+{ -+ int len; -+ va_list ap; -+ PROC_PRIVATE *private = (PROC_PRIVATE *)mode; -+ -+ /* is the buffer already full */ -+ if (private->pr_len >= private->pr_data_len) -+ return; -+ -+ /* attempt to fill up to the remaining space */ -+ va_start (ap, fmt); -+ len = vsnprintf ( & private->pr_data[private->pr_len], (private->pr_data_len - private->pr_len), fmt, ap); -+ va_end (ap); -+ -+ if (len < 0 ) -+ { -+ /* we have reached the end of buffer and need to fail all future writes -+ * the caller can check (pr_len >= pr_data_len) and recall with more space -+ */ -+ private->pr_len = private->pr_data_len; -+ return; -+ } -+ -+ /* move the length along */ -+ private->pr_len += len; -+} -+ -+int -+proc_release (struct inode *inode, struct file *file) -+{ -+ PROC_PRIVATE *pr = (PROC_PRIVATE *) file->private_data; -+ -+ if (pr->pr_data) -+ KMEM_FREE (pr->pr_data, pr->pr_data_len); -+ kfree (pr); -+ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+ssize_t -+proc_read (struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ PROC_PRIVATE *pr = (PROC_PRIVATE *) file->private_data; -+ int error; -+ -+ if (pr->pr_off >= pr->pr_len) -+ return (0); -+ -+ if ((error = verify_area (VERIFY_WRITE, buf, count)) != 0) -+ return (error); -+ -+ if (count >= (pr->pr_len - pr->pr_off)) -+ count = pr->pr_len - pr->pr_off; -+ -+ copy_to_user (buf, pr->pr_data + pr->pr_off, count); -+ -+ pr->pr_off += count; -+ *ppos += count; -+ -+ return (count); -+} -+ -+static int -+proc_open (struct inode *inode, struct file *file) -+{ -+ PROC_PRIVATE *pr; -+ CM_RAIL *cmRail; -+ int pages = 4; -+ unsigned long flags; -+ -+ if ((pr = kmalloc (sizeof (PROC_PRIVATE), GFP_KERNEL)) == NULL) -+ return (-ENOMEM); -+ -+ pr->pr_rail = (EP_RAIL *)(PDE(inode)->data); -+ -+ do { -+ pr->pr_data_len = PAGESIZE * pages; -+ -+ KMEM_ZALLOC (pr->pr_data, char *, pr->pr_data_len, 1); -+ if (pr->pr_data == NULL) -+ { -+ pr->pr_len = sprintf (pr->pr_data, "Out of Memory\n"); -+ break; -+ } -+ -+ pr->pr_off = 0; -+ pr->pr_len = 0; -+ pr->pr_data[0] = 0; -+ -+ if (pr->pr_rail->State != EP_RAIL_STATE_RUNNING) -+ { -+ pr->pr_len = sprintf (pr->pr_data, "Rail not Running\n"); -+ break; -+ } -+ else -+ { -+ pr->pr_di.func = proc_character_fill; -+ pr->pr_di.arg = (long)pr; -+ -+ if (!strcmp("maps", file->f_dentry->d_iname)) -+ { -+ cmRail = pr->pr_rail->ClusterRail; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ DisplayNodeMaps (&pr->pr_di, cmRail); -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ } -+ -+ if (!strcmp("segs", file->f_dentry->d_iname)) -+ { -+ cmRail = pr->pr_rail->ClusterRail; -+ -+ spin_lock_irqsave (&cmRail->Lock, flags); -+ DisplayNodeSgmts (&pr->pr_di, cmRail); -+ spin_unlock_irqrestore (&cmRail->Lock, flags); -+ } -+ -+ if (!strcmp("tree", file->f_dentry->d_iname)) -+ DisplayRailDo (&pr->pr_di, pr->pr_rail); -+ } -+ -+ if ( pr->pr_len < pr->pr_data_len) -+ break; /* we managed to get all the output into the buffer */ -+ -+ pages++; -+ KMEM_FREE ( pr->pr_data, pr->pr_data_len); -+ } while (1); -+ -+ -+ file->private_data = (void *) pr; -+ -+ MOD_INC_USE_COUNT; -+ return (0); -+} -+ -+struct file_operations proc_nodeset_operations = -+{ -+ read: nodeset_read, -+ poll: nodeset_poll, -+ open: nodeset_open, -+ release: nodeset_release, -+}; -+ -+struct file_operations proc_operations = -+{ -+ read: proc_read, -+ open: proc_open, -+ release: proc_release, -+}; -+ -+void -+ep_procfs_rail_init (EP_RAIL *rail) -+{ -+ struct proc_dir_entry *dir; -+ struct proc_dir_entry *p; -+ char name[10]; -+ int i; -+ -+ sprintf (name, "rail%d", rail->Number); -+ -+ if ((dir = rail->ProcDir = proc_mkdir (name, ep_procfs_root)) == NULL) -+ return; -+ -+ for (i = 0; i < sizeof (rail_info)/sizeof (rail_info[0]); i++) -+ { -+ if ((p = create_proc_entry (rail_info[i].name, 0, dir)) != NULL) -+ { -+ p->read_proc = rail_info[i].read_func; -+ p->write_proc = rail_info[i].write_func; -+ p->data = rail; -+ p->owner = THIS_MODULE; -+ } -+ } -+ -+ if ((p = create_proc_entry ("nodeset", 0, dir)) != NULL) -+ { -+ p->proc_fops = &proc_nodeset_operations; -+ p->owner = THIS_MODULE; -+ p->data = rail; -+ -+ rail->CallbackRegistered = 1; -+ ep_register_callback (rail, EP_CB_NODESET, nodeset_callback, rail); -+ } -+ -+ if ((p = create_proc_entry ("maps", 0, dir)) != NULL) -+ { -+ p->proc_fops = &proc_operations; -+ p->owner = THIS_MODULE; -+ p->data = rail; -+ } -+ -+ if ((p = create_proc_entry ("segs", 0, dir)) != NULL) -+ { -+ p->proc_fops = &proc_operations; -+ p->owner = THIS_MODULE; -+ p->data = rail; -+ } -+ -+ if ((p = create_proc_entry ("tree", 0, dir)) != NULL) -+ { -+ p->proc_fops = &proc_operations; -+ p->owner = THIS_MODULE; -+ p->data = rail; -+ } -+ -+} -+ -+void -+ep_procfs_rail_fini (EP_RAIL *rail) -+{ -+ struct proc_dir_entry *dir = rail->ProcDir; -+ char name[10]; -+ int i; -+ -+ if (dir == NULL) -+ return; -+ -+ if (rail->CallbackRegistered) -+ { -+ ep_remove_callback (rail, EP_CB_NODESET, nodeset_callback, rail); -+ -+ remove_proc_entry ("nodeset", dir); -+ } -+ -+ remove_proc_entry ("maps", dir); -+ remove_proc_entry ("segs", dir); -+ remove_proc_entry ("tree", dir); -+ -+ for (i = 0; i < sizeof (rail_info)/sizeof (rail_info[0]); i++) -+ remove_proc_entry (rail_info[i].name, dir); -+ -+ sprintf (name, "rail%d", rail->Number); -+ remove_proc_entry (name, ep_procfs_root); -+} -+ -+#include "quadrics_version.h" -+static char quadrics_version[] = QUADRICS_VERSION; -+ -+void -+ep_procfs_init() -+{ -+ extern int txd_stabilise; -+ extern int MaxSwitchLevels; -+ -+ spin_lock_init (&ep_nodeset_lock); -+ init_waitqueue_head (&ep_nodeset_wait); -+ -+ ep_procfs_root = proc_mkdir ("ep", qsnet_procfs_root); -+ ep_config_root = proc_mkdir ("config", ep_procfs_root); -+ -+ qsnet_proc_register_str (ep_procfs_root, "version", quadrics_version, 1); -+ -+ qsnet_proc_register_hex (ep_config_root, "epdebug", &epdebug, 0); -+ qsnet_proc_register_hex (ep_config_root, "epdebug_console", &epdebug_console, 0); -+ qsnet_proc_register_hex (ep_config_root, "epdebug_cmlevel", &epdebug_cmlevel, 0); -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ qsnet_proc_register_hex (ep_config_root, "epdebug_check_sum", &epdebug_check_sum, 0); -+#endif -+ qsnet_proc_register_hex (ep_config_root, "epcomms_forward_limit", &epcomms_forward_limit, 0); -+ qsnet_proc_register_int (ep_config_root, "txd_stabilise", &txd_stabilise, 0); -+ qsnet_proc_register_int (ep_config_root, "assfail_mode", &assfail_mode, 0); -+ qsnet_proc_register_int (ep_config_root, "max_switch_levels", &MaxSwitchLevels, 1); -+ -+ ep_procfs_rcvr_xmtr_init(); -+} -+ -+void -+ep_procfs_fini(void) -+{ -+ ep_procfs_rcvr_xmtr_fini(); -+ -+ remove_proc_entry ("max_switch_levels", ep_config_root); -+ remove_proc_entry ("assfail_mode", ep_config_root); -+ remove_proc_entry ("txd_stabilise", ep_config_root); -+ remove_proc_entry ("epcomms_forward_limit", ep_config_root); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ remove_proc_entry ("epdebug_check_sum", ep_config_root); -+#endif -+ remove_proc_entry ("epdebug_cmlevel", ep_config_root); -+ remove_proc_entry ("epdebug_console", ep_config_root); -+ remove_proc_entry ("epdebug", ep_config_root); -+ -+ remove_proc_entry ("version", ep_procfs_root); -+ -+ remove_proc_entry ("config", ep_procfs_root); -+ remove_proc_entry ("ep", qsnet_procfs_root); -+ -+ spin_lock_destroy (&ep_nodeset_lock); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/quadrics_version.h 2005-06-01 23:12:54.680426792 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/ep/railhints.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/railhints.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/railhints.c 2005-06-01 23:12:54.680426792 -0400 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: railhints.c,v 1.5 2004/02/06 22:37:06 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/railhints.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "debug.h" -+ -+int -+ep_pickRail(EP_RAILMASK railmask) -+{ -+ static volatile int lastGlobal; -+ int i, rnum, last = lastGlobal; -+ -+ /* Pick a single rail out of the railmask */ -+ for (i = 0; i < EP_MAX_RAILS; i++) -+ if (railmask & (1 << ((last + i) % EP_MAX_RAILS))) -+ break; -+ -+ if (i == EP_MAX_RAILS) -+ return (-1); -+ -+ rnum = (last + i) % EP_MAX_RAILS; -+ -+ lastGlobal = (rnum + 1) % EP_MAX_RAILS; -+ -+ ASSERT (railmask & (1 << rnum)); -+ -+ return (rnum); -+} -+ -+int -+ep_xmtr_bcastrail (EP_XMTR *xmtr, EP_RAILMASK allowedRails) -+{ -+ /* Retrun a single rail out of allowed mask with the best connectivity for broadcast. */ -+ return (ep_pickRail (allowedRails & xmtr->RailMask)); -+} -+ -+int -+ep_xmtr_prefrail (EP_XMTR *xmtr, EP_RAILMASK allowedRails, unsigned nodeId) -+{ -+ EP_NODE *node = &xmtr->Subsys->Subsys.Sys->Nodes[nodeId]; -+ -+ EPRINTF5 (DBG_XMTR, "ep_xmtr_prefrail: xmtr=%p allowedRails=%x nodeId=%d xmtr->RailMaks=%x Connected=%x\n", -+ xmtr, allowedRails, nodeId, xmtr->RailMask, node->ConnectedRails); -+ -+ /* Return a single rail which is currently connected to nodeId (limited to rails -+ * in allowedmask) - if more than one rail is possible, then round-robin between -+ * them */ -+ return (ep_pickRail (allowedRails & xmtr->RailMask & node->ConnectedRails)); -+} -+ -+EP_RAILMASK -+ep_xmtr_availrails (EP_XMTR *xmtr) -+{ -+ /* Return which rails can be used to transmit one. */ -+ -+ return (xmtr->RailMask); -+} -+ -+EP_RAILMASK -+ep_xmtr_noderails (EP_XMTR *xmtr, unsigned nodeId) -+{ -+ EP_NODE *node = &xmtr->Subsys->Subsys.Sys->Nodes[nodeId]; -+ -+ /* Return which rails can be used to transmit to this node. */ -+ -+ return (xmtr->RailMask & node->ConnectedRails); -+} -+ -+int -+ep_rcvr_prefrail (EP_RCVR *rcvr, EP_RAILMASK allowedRails) -+{ -+ /* Return the "best" rail for queueing a receive buffer out on - this will be a -+ * rail with ThreadWaiting set or the rail with the least descriptors queued -+ * on it. */ -+ -+ return (ep_pickRail (allowedRails & rcvr->RailMask)); -+} -+ -+EP_RAILMASK -+ep_rcvr_availrails (EP_RCVR *rcvr) -+{ -+ /* Return which rails can be used to queue receive buffers. */ -+ return (rcvr->RailMask); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/rmap.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/rmap.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/rmap.c 2005-06-01 23:12:54.681426640 -0400 -@@ -0,0 +1,365 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: rmap.c,v 1.15 2004/05/19 10:24:38 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/rmap.c,v $ */ -+ -+#include -+#include -+ -+#include "debug.h" -+ -+void -+ep_display_rmap (EP_RMAP *mp) -+{ -+ EP_RMAP_ENTRY *bp; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&mp->m_lock, flags); -+ ep_debugf (DBG_DEBUG, "map: %s size %d free %d\n", mp->m_name, mp->m_size, mp->m_free); -+ for (bp = &mp->m_map[0]; bp->m_size; bp++) -+ ep_debugf (DBG_DEBUG, " [%lx - %lx]\n", bp->m_addr, bp->m_addr+bp->m_size-1); -+ spin_unlock_irqrestore (&mp->m_lock, flags); -+} -+ -+void -+ep_mapinit (EP_RMAP *mp, char *name, u_int mapsize) -+{ -+ spin_lock_init (&mp->m_lock); -+ kcondvar_init (&mp->m_wait); -+ -+ /* The final segment in the array has size 0 and acts as a delimiter -+ * we insure that we never use segments past the end of the array by -+ * maintaining a free segment count in m_free. When excess segments -+ * occur we discard some resources */ -+ -+ mp->m_size = mapsize; -+ mp->m_free = mapsize; -+ mp->m_name = name; -+ -+ bzero (mp->m_map, sizeof (EP_RMAP_ENTRY) * (mapsize+1)); -+} -+ -+EP_RMAP * -+ep_rmallocmap (size_t mapsize, char *name, int cansleep) -+{ -+ EP_RMAP *mp; -+ -+ KMEM_ZALLOC (mp, EP_RMAP *, sizeof (EP_RMAP) + mapsize*sizeof (EP_RMAP_ENTRY), cansleep); -+ -+ if (mp != NULL) -+ ep_mapinit (mp, name, mapsize); -+ -+ return (mp); -+} -+ -+void -+ep_rmfreemap (EP_RMAP *mp) -+{ -+ spin_lock_destroy (&mp->m_lock); -+ kcondvar_destroy (&mp->m_wait); -+ -+ KMEM_FREE (mp, sizeof (EP_RMAP) + mp->m_size * sizeof (EP_RMAP_ENTRY)); -+} -+ -+static u_long -+ep_rmalloc_locked (EP_RMAP *mp, size_t size) -+{ -+ EP_RMAP_ENTRY *bp; -+ u_long addr; -+ -+ ASSERT (size > 0); -+ ASSERT (SPINLOCK_HELD (&mp->m_lock)); -+ -+ for (bp = &mp->m_map[0]; bp->m_size; bp++) -+ { -+ if (bp->m_size >= size) -+ { -+ addr = bp->m_addr; -+ bp->m_addr += size; -+ -+ if ((bp->m_size -= size) == 0) -+ { -+ /* taken all of this slot - so shift the map down */ -+ do { -+ bp++; -+ (bp-1)->m_addr = bp->m_addr; -+ } while (((bp-1)->m_size = bp->m_size) != 0); -+ -+ mp->m_free++; -+ } -+ return (addr); -+ } -+ } -+ -+ return (0); -+} -+ -+u_long -+ep_rmalloc (EP_RMAP *mp, size_t size, int cansleep) -+{ -+ unsigned long addr; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&mp->m_lock, flags); -+ while ((addr = ep_rmalloc_locked (mp, size)) == 0 && cansleep) -+ { -+ mp->m_want = 1; -+ kcondvar_wait (&mp->m_wait, &mp->m_lock, &flags); -+ } -+ -+ spin_unlock_irqrestore (&mp->m_lock, flags); -+ -+ return (addr); -+} -+ -+ -+ -+u_long -+ep_rmalloc_constrained (EP_RMAP *mp, size_t size, u_long alo, u_long ahi, u_long align, int cansleep) -+{ -+ EP_RMAP_ENTRY *bp, *bp2, *lbp; -+ unsigned long addr=0; -+ size_t delta; -+ int ok; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&mp->m_lock, flags); -+ again: -+ for (bp = &mp->m_map[0]; bp->m_size; bp++) -+ { -+ delta = 0; -+ -+ if (alo < bp->m_addr) -+ { -+ addr = bp->m_addr; -+ -+ if (addr & (align-1)) -+ addr = (addr + (align-1)) & ~(align-1); -+ -+ delta = addr - bp->m_addr; -+ -+ if (ahi >= bp->m_addr + bp->m_size) -+ ok = (bp->m_size >= (size + delta)); -+ else -+ ok = ((bp->m_addr + size + delta) <= ahi); -+ } -+ else -+ { -+ addr = alo; -+ if (addr & (align-1)) -+ addr = (addr + (align-1)) & ~(align-1); -+ delta = addr - bp->m_addr; -+ -+ if (ahi >= bp->m_addr + bp->m_size) -+ ok = ((alo + size + delta) <= (bp->m_addr + bp->m_size)); -+ else -+ ok = ((alo + size + delta) <= ahi); -+ } -+ -+ if (ok) -+ break; -+ } -+ -+ if (bp->m_size == 0) -+ { -+ if (cansleep) -+ { -+ mp->m_want = 1; -+ kcondvar_wait (&mp->m_wait, &mp->m_lock, &flags); -+ goto again; -+ } -+ spin_unlock_irqrestore (&mp->m_lock, flags); -+ return (0); -+ } -+ -+ /* found an approriate map entry - so take the bit out which we want */ -+ if (bp->m_addr == addr) -+ { -+ if (bp->m_size == size) -+ { -+ /* allocate entire segment and compress map */ -+ bp2 = bp; -+ while (bp2->m_size) -+ { -+ bp2++; -+ (bp2-1)->m_addr = bp2->m_addr; -+ (bp2-1)->m_size = bp2->m_size; -+ } -+ mp->m_free++; -+ } -+ else -+ { -+ /* take from start of segment */ -+ bp->m_addr += size; -+ bp->m_size -= size; -+ } -+ } -+ else -+ { -+ if (bp->m_addr + bp->m_size == addr + size) -+ { -+ /* take from end of segment */ -+ bp->m_size -= size; -+ } -+ else -+ { -+ /* split the segment loosing the last entry if there's no space */ -+ if (mp->m_free == 0) -+ { -+ /* find last map entry */ -+ for (lbp = bp; lbp->m_size != 0; lbp++) -+ ; -+ lbp--; -+ -+ if (lbp->m_size > (lbp-1)->m_size) -+ lbp--; -+ -+ printk ("%s: lost resource map entry [%lx, %lx]\n", -+ mp->m_name, lbp->m_addr, lbp->m_addr + lbp->m_size); -+ -+ *lbp = *(lbp+1); -+ (lbp+1)->m_size = 0; -+ -+ mp->m_free++; -+ } -+ -+ for (bp2 = bp; bp2->m_size != 0; bp2++) -+ continue; -+ -+ for (bp2--; bp2 > bp; bp2--) -+ { -+ (bp2+1)->m_addr = bp2->m_addr; -+ (bp2+1)->m_size = bp2->m_size; -+ } -+ -+ mp->m_free--; -+ -+ (bp+1)->m_addr = addr + size; -+ (bp+1)->m_size = bp->m_addr + bp->m_size - (addr + size); -+ bp->m_size = addr - bp->m_addr; -+ } -+ } -+ -+ spin_unlock_irqrestore (&mp->m_lock, flags); -+ return (addr); -+} -+ -+void -+ep_rmfree (EP_RMAP *mp, size_t size, u_long addr) -+{ -+ EP_RMAP_ENTRY *bp; -+ unsigned long t; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&mp->m_lock, flags); -+ -+ ASSERT (addr != 0 && size > 0); -+ -+again: -+ /* find the piece of the map which starts after the returned space -+ * or the end of the map */ -+ for (bp = &mp->m_map[0]; bp->m_addr <= addr && bp->m_size != 0; bp++) -+ ; -+ -+ /* bp points to the piece to the right of where we want to go */ -+ -+ if (bp > &mp->m_map[0] && (bp-1)->m_addr + (bp-1)->m_size >= addr) -+ { -+ /* merge with piece on the left */ -+ -+ ASSERT ((bp-1)->m_addr + (bp-1)->m_size <= addr); -+ -+ (bp-1)->m_size += size; -+ -+ ASSERT (bp->m_size == 0 || addr+size <= bp->m_addr); -+ -+ if (bp->m_size && (addr + size) == bp->m_addr) -+ { -+ /* merge witht he piece on the right by -+ * growing the piece on the left and shifting -+ * the map down */ -+ -+ ASSERT ((addr + size) <= bp->m_addr); -+ -+ (bp-1)->m_size += bp->m_size; -+ while (bp->m_size) -+ { -+ bp++; -+ (bp-1)->m_addr = bp->m_addr; -+ (bp-1)->m_size = bp->m_size; -+ } -+ -+ mp->m_free++; -+ } -+ } -+ else if (addr + size >= bp->m_addr && bp->m_size) -+ { -+ /* merge with piece to the right */ -+ -+ ASSERT ((addr + size) <= bp->m_addr); -+ -+ bp->m_addr -= size; -+ bp->m_size += size; -+ } -+ else -+ { -+ /* doesn't join with left or right - check for map -+ overflow and discard the smallest of the last or -+ next to last entries */ -+ -+ if (mp->m_free == 0) -+ { -+ EP_RMAP_ENTRY *lbp; -+ -+ /* find last map entry */ -+ for (lbp = bp; lbp->m_size != 0; lbp++) -+ ; -+ lbp--; -+ -+ if (lbp->m_size > (lbp-1)->m_size) -+ lbp--; -+ -+ printk ("%s: lost resource map entry [%lx, %lx]\n", -+ mp->m_name, lbp->m_addr, lbp->m_addr + lbp->m_size); -+ -+ *lbp = *(lbp+1); -+ (lbp+1)->m_size = 0; -+ -+ mp->m_free++; -+ goto again; -+ } -+ -+ /* make a new entry and push the remaining ones up */ -+ do { -+ t = bp->m_addr; -+ bp->m_addr = addr; -+ addr = t; -+ t = bp->m_size; -+ bp->m_size = size; -+ bp++; -+ } while ((size = t) != 0); -+ -+ mp->m_free--; -+ } -+ -+ /* if anyone blocked on rmalloc failure, wake 'em up */ -+ if (mp->m_want) -+ { -+ mp->m_want = 0; -+ kcondvar_wakeupall (&mp->m_wait, &mp->m_lock); -+ } -+ -+ spin_unlock_irqrestore (&mp->m_lock, flags); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/spinlock_elan3_thread.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/spinlock_elan3_thread.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/spinlock_elan3_thread.c 2005-06-01 23:12:54.681426640 -0400 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: spinlock_elan3_thread.c,v 1.9 2003/10/07 13:22:38 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/spinlock_elan3_thread.c,v $ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "kcomm_elan3.h" -+#include "epcomms_elan3.h" -+ -+void -+ep3_spinblock (EP3_SPINLOCK_ELAN *sle, EP3_SPINLOCK_MAIN *sl) -+{ -+ do { -+ sl->sl_seq = sle->sl_seq; /* Release my lock */ -+ -+ while (sle->sl_lock) /* Wait until the main */ -+ c_break(); /* releases the lock */ -+ -+ sle->sl_seq++; /* and try and relock */ -+ } while (sle->sl_lock); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/statemap.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/statemap.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/statemap.c 2005-06-01 23:12:54.682426488 -0400 -@@ -0,0 +1,385 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: statemap.c,v 1.11.8.1 2004/11/18 12:05:00 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/statemap.c,v $ */ -+ -+#include -+#include -+ -+/******************************** global state bitmap stuff **********************************/ -+static int -+statemap_setmapbit (bitmap_t *map, int offset, int bit) -+{ -+ bitmap_t *e = &map[offset >> BT_ULSHIFT]; -+ bitmap_t mask = ((bitmap_t)1) << (offset & BT_ULMASK); -+ int rc = ((*e) & mask) != 0; -+ -+ if (bit) -+ { -+ *e |= mask; -+ return (!rc); -+ } -+ -+ *e &= ~mask; -+ return (rc); -+} -+ -+static int -+statemap_firstsegbit (bitmap_t seg) -+{ -+ int bit = 0; -+ -+ if (seg == 0) -+ return (-1); -+ -+#if (BT_ULSHIFT == 6) -+ if ((seg & 0xffffffffL) == 0) -+ { -+ seg >>= 32; -+ bit += 32; -+ } -+#elif (BT_ULSHIFT != 5) -+# error "Unexpected value of BT_ULSHIFT" -+#endif -+ -+ if ((seg & 0xffff) == 0) -+ { -+ seg >>= 16; -+ bit += 16; -+ } -+ -+ if ((seg & 0xff) == 0) -+ { -+ seg >>= 8; -+ bit += 8; -+ } -+ -+ if ((seg & 0xf) == 0) -+ { -+ seg >>= 4; -+ bit += 4; -+ } -+ -+ if ((seg & 0x3) == 0) -+ { -+ seg >>= 2; -+ bit += 2; -+ } -+ -+ return (((seg & 0x1) == 0) ? bit + 1 : bit); -+} -+ -+bitmap_t -+statemap_getseg (statemap_t *map, unsigned int offset) -+{ -+ ASSERT (offset < map->size); -+ ASSERT ((offset & BT_ULMASK) == 0); -+ -+ return (map->bitmap[offset >> BT_ULSHIFT]); -+} -+ -+void -+statemap_setseg (statemap_t *map, unsigned int offset, bitmap_t seg) -+{ -+ ASSERT (offset < map->size); -+ ASSERT ((offset & BT_ULMASK) == 0); -+ -+ offset >>= BT_ULSHIFT; -+ if (map->bitmap[offset] == seg) -+ return; -+ -+ map->bitmap[offset] = seg; -+ -+ if (statemap_setmapbit (map->changemap2, offset, 1) && -+ statemap_setmapbit (map->changemap1, offset >>= BT_ULSHIFT, 1)) -+ statemap_setmapbit (map->changemap0, offset >>= BT_ULSHIFT, 1); -+} -+ -+bitmap_t -+statemap_getbits (statemap_t *map, unsigned int offset, int nbits) -+{ -+ int index = offset >> BT_ULSHIFT; -+ bitmap_t mask = (nbits == BT_NBIPUL) ? (bitmap_t) -1 : (((bitmap_t)1) << nbits) - 1; -+ -+ ASSERT (nbits <= BT_NBIPUL); -+ ASSERT (offset + nbits <= map->size); -+ -+ offset &= BT_ULMASK; -+ if (offset + nbits <= BT_NBIPUL) -+ return ((map->bitmap[index] >> offset) & mask); -+ -+ return (((map->bitmap[index] >> offset) | -+ (map->bitmap[index + 1] << (BT_NBIPUL - offset))) & mask); -+} -+ -+void -+statemap_setbits (statemap_t *map, unsigned int offset, bitmap_t bits, int nbits) -+{ -+ int index = offset >> BT_ULSHIFT; -+ bitmap_t mask; -+ bitmap_t seg; -+ bitmap_t newseg; -+ -+ ASSERT (nbits <= BT_NBIPUL); -+ ASSERT (offset + nbits <= map->size); -+ -+ offset &= BT_ULMASK; -+ if (offset + nbits <= BT_NBIPUL) -+ { -+ mask = ((nbits == BT_NBIPUL) ? -1 : ((((bitmap_t)1) << nbits) - 1)) << offset; -+ seg = map->bitmap[index]; -+ newseg = ((bits << offset) & mask) | (seg & ~mask); -+ -+ if (seg == newseg) -+ return; -+ -+ map->bitmap[index] = newseg; -+ -+ if (statemap_setmapbit (map->changemap2, index, 1) && -+ statemap_setmapbit (map->changemap1, index >>= BT_ULSHIFT, 1)) -+ statemap_setmapbit (map->changemap0, index >>= BT_ULSHIFT, 1); -+ return; -+ } -+ -+ mask = ((bitmap_t)-1) << offset; -+ seg = map->bitmap[index]; -+ newseg = ((bits << offset) & mask) | (seg & ~mask); -+ -+ if (seg != newseg) -+ { -+ map->bitmap[index] = newseg; -+ -+ if (statemap_setmapbit (map->changemap2, index, 1) && -+ statemap_setmapbit (map->changemap1, index >> BT_ULSHIFT, 1)) -+ statemap_setmapbit (map->changemap0, index >> (2 * BT_ULSHIFT), 1); -+ } -+ -+ index++; -+ offset = BT_NBIPUL - offset; -+ mask = (((bitmap_t)1) << (nbits - offset)) - 1; -+ seg = map->bitmap[index]; -+ newseg = ((bits >> offset) & mask) | (seg & ~mask); -+ -+ if (seg == newseg) -+ return; -+ -+ map->bitmap[index] = newseg; -+ -+ if (statemap_setmapbit (map->changemap2, index, 1) && -+ statemap_setmapbit (map->changemap1, index >>= BT_ULSHIFT, 1)) -+ statemap_setmapbit (map->changemap0, index >>= BT_ULSHIFT, 1); -+} -+ -+void -+statemap_zero (statemap_t *dst) -+{ -+ int size = dst->size; -+ int offset = 0; -+ bitmap_t *changemap0 = dst->changemap0; -+ bitmap_t *changemap1 = dst->changemap1; -+ bitmap_t *changemap2 = dst->changemap2; -+ bitmap_t *dstmap = dst->bitmap; -+ bitmap_t bit0; -+ bitmap_t bit1; -+ bitmap_t bit2; -+ -+ for (bit0 = 1; offset < size; bit0 <<= 1, changemap1++) -+ { -+ for (bit1 = 1; bit1 != 0 && offset < size; bit1 <<= 1, changemap2++) -+ { -+ for (bit2 = 1; bit2 != 0 && offset < size; bit2 <<= 1, dstmap++, offset += BT_NBIPUL) -+ { -+ *dstmap = 0; -+ *changemap2 |= bit2; -+ } -+ *changemap1 |= bit1; -+ } -+ *changemap0 |= bit0; -+ } -+} -+ -+void -+statemap_setmap (statemap_t *dst, statemap_t *src) -+{ -+ int size = dst->size; -+ int offset = 0; -+ bitmap_t *changemap0 = dst->changemap0; -+ bitmap_t *changemap1 = dst->changemap1; -+ bitmap_t *changemap2 = dst->changemap2; -+ bitmap_t *dstmap = dst->bitmap; -+ bitmap_t *srcmap = src->bitmap; -+ bitmap_t bit0; -+ bitmap_t bit1; -+ bitmap_t bit2; -+ -+ ASSERT (src->size == size); -+ -+ for (bit0 = 1; offset < size; bit0 <<= 1, changemap1++) -+ { -+ for (bit1 = 1; bit1 != 0 && offset < size; bit1 <<= 1, changemap2++) -+ { -+ for (bit2 = 1; bit2 != 0 && offset < size; bit2 <<= 1, dstmap++, srcmap++, offset += BT_NBIPUL) -+ if (*dstmap != *srcmap) -+ { -+ *dstmap = *srcmap; -+ *changemap2 |= bit2; -+ } -+ if (*changemap2 != 0) -+ *changemap1 |= bit1; -+ } -+ if (*changemap1 != 0) -+ *changemap0 |= bit0; -+ } -+} -+ -+void -+statemap_ormap (statemap_t *dst, statemap_t *src) -+{ -+ int size = dst->size; -+ int offset = 0; -+ bitmap_t *changemap0 = dst->changemap0; -+ bitmap_t *changemap1 = dst->changemap1; -+ bitmap_t *changemap2 = dst->changemap2; -+ bitmap_t *dstmap = dst->bitmap; -+ bitmap_t *srcmap = src->bitmap; -+ bitmap_t bit0; -+ bitmap_t bit1; -+ bitmap_t bit2; -+ bitmap_t seg; -+ -+ ASSERT (src->size == size); -+ -+ for (bit0 = 1; offset < size; bit0 <<= 1, changemap1++) -+ { -+ for (bit1 = 1; bit1 != 0 && offset < size; bit1 <<= 1, changemap2++) -+ { -+ for (bit2 = 1; bit2 != 0 && offset < size; bit2 <<= 1, dstmap++, srcmap++, offset += BT_NBIPUL) -+ { -+ seg = *dstmap | *srcmap; -+ if (*dstmap != seg) -+ { -+ *dstmap = seg; -+ *changemap2 |= bit2; -+ } -+ } -+ if (*changemap2 != 0) -+ *changemap1 |= bit1; -+ } -+ if (*changemap1 != 0) -+ *changemap0 |= bit0; -+ } -+} -+ -+int -+statemap_findchange (statemap_t *map, bitmap_t *newseg, int clearchange) -+{ -+ int bit0; -+ bitmap_t *cm1; -+ int bit1; -+ bitmap_t *cm2; -+ int bit2; -+ unsigned int offset; -+ -+ bit0 = statemap_firstsegbit (*(map->changemap0)); -+ if (bit0 < 0) -+ return (-1); -+ -+ offset = bit0; -+ cm1 = map->changemap1 + offset; -+ bit1 = statemap_firstsegbit (*cm1); -+ ASSERT (bit1 >= 0); -+ -+ offset = (offset << BT_ULSHIFT) + bit1; -+ cm2 = map->changemap2 + offset; -+ bit2 = statemap_firstsegbit (*cm2); -+ ASSERT (bit2 >= 0); -+ -+ offset = (offset << BT_ULSHIFT) + bit2; -+ *newseg = map->bitmap[offset]; -+ -+ if (clearchange && -+ (*cm2 &= ~(((bitmap_t)1) << bit2)) == 0 && -+ (*cm1 &= ~(((bitmap_t)1) << bit1)) == 0) -+ map->changemap0[0] &= ~(((bitmap_t)1) << bit0); -+ -+ return (offset << BT_ULSHIFT); -+} -+ -+int -+statemap_changed (statemap_t *map) -+{ -+ return ((*(map->changemap0) != 0)); -+} -+ -+void -+statemap_reset (statemap_t *map) -+{ -+ bzero (map->changemap0, map->changemap_nob + map->bitmap_nob); -+} -+ -+void -+statemap_copy (statemap_t *dst, statemap_t *src) -+{ -+ ASSERT (dst->size == src->size); -+ bcopy (src->changemap0, dst->changemap0, src->changemap_nob + src->bitmap_nob); -+} -+ -+void -+statemap_clearchanges (statemap_t *map) -+{ -+ if (statemap_changed (map)) -+ bzero (map->changemap0, map->changemap_nob); -+} -+ -+bitmap_t * -+statemap_tobitmap (statemap_t *map) -+{ -+ return (map->bitmap); -+} -+ -+statemap_t * -+statemap_create (int size) -+{ -+ int struct_entries = (sizeof (statemap_t) * 8 + (BT_NBIPUL-1)) >> BT_ULSHIFT; -+ int bitmap_entries = (size + (BT_NBIPUL-1)) >> BT_ULSHIFT; -+ int changemap2_entries = (bitmap_entries + (BT_NBIPUL-1)) >> BT_ULSHIFT; -+ int changemap1_entries = (changemap2_entries + (BT_NBIPUL-1)) >> BT_ULSHIFT; -+ int changemap0_entries = (changemap1_entries + (BT_NBIPUL-1)) >> BT_ULSHIFT; -+ int changemap_entries = changemap0_entries + changemap1_entries + changemap2_entries; -+ int nob = (struct_entries + bitmap_entries + changemap_entries) * sizeof (bitmap_t); -+ statemap_t *map; -+ -+ ASSERT ((1 << BT_ULSHIFT) == BT_NBIPUL); -+ ASSERT (changemap0_entries == 1); -+ -+ KMEM_ZALLOC (map, statemap_t *, nob, 1); -+ -+ map->size = size; -+ map->nob = nob; -+ map->changemap_nob = changemap_entries * sizeof (bitmap_t); -+ map->bitmap_nob = bitmap_entries * sizeof (bitmap_t); -+ map->changemap0 = ((bitmap_t *)map) + struct_entries; -+ map->changemap1 = map->changemap0 + changemap0_entries; -+ map->changemap2 = map->changemap1 + changemap1_entries; -+ map->bitmap = map->changemap2 + changemap2_entries; -+ -+ return (map); -+} -+ -+void -+statemap_destroy (statemap_t *map) -+{ -+ KMEM_FREE (map, map->nob); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/statusmon.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/statusmon.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/statusmon.h 2005-06-01 23:12:54.682426488 -0400 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: statusmon.h,v 1.6 2003/10/07 13:22:38 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/statusmon.h,v $*/ -+ -+#ifndef __ELAN3_STATUSMON_H -+#define __ELAN3_STATUSMON_H -+ -+typedef struct statusmon_node -+{ -+ u_int NodeId; -+ u_int State; -+} STATUSMON_SGMT; -+ -+typedef struct statusmon_level -+{ -+ unsigned Width; -+ STATUSMON_SGMT Nodes[CM_SGMTS_PER_LEVEL]; -+} STATUSMON_LEVEL; -+ -+typedef struct statusmon_msg -+{ -+ unsigned Type; -+ unsigned NodeId; -+ unsigned NumLevels; -+ unsigned TopLevel; -+ unsigned Role; -+ STATUSMON_LEVEL Levels[CM_MAX_LEVELS]; -+} STATUSMON_MSG; -+ -+ -+#endif /* __ELAN3_STATUSMON_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/support.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/support.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/support.c 2005-06-01 23:12:54.683426336 -0400 -@@ -0,0 +1,109 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: support.c,v 1.37.8.1 2004/09/30 15:01:53 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/support.c,v $ */ -+ -+#include -+#include -+ -+/****************************************************************************************/ -+/* -+ * Nodeset/flush callbacks. -+ */ -+int -+ep_register_callback (EP_RAIL *rail, unsigned idx, void (*routine)(void *, statemap_t *), void *arg) -+{ -+ EP_CALLBACK *cb; -+ -+ KMEM_ALLOC (cb, EP_CALLBACK *, sizeof (EP_CALLBACK), 1); -+ -+ cb->Routine = routine; -+ cb->Arg = arg; -+ -+ kmutex_lock (&rail->CallbackLock); -+ cb->Next = rail->CallbackList[idx]; -+ rail->CallbackList[idx] = cb; -+ kmutex_unlock (&rail->CallbackLock); -+ -+ return (ESUCCESS); -+} -+ -+void -+ep_remove_callback (EP_RAIL *rail, unsigned idx, void (*routine)(void *, statemap_t *), void *arg) -+{ -+ EP_CALLBACK *cb; -+ EP_CALLBACK **predp; -+ -+ kmutex_lock (&rail->CallbackLock); -+ for (predp = &rail->CallbackList[idx]; (cb = *predp); predp = &cb->Next) -+ if (cb->Routine == routine && cb->Arg == arg) -+ break; -+ -+ if (cb == NULL) -+ panic ("ep_remove_member_callback"); -+ -+ *predp = cb->Next; -+ kmutex_unlock (&rail->CallbackLock); -+ -+ KMEM_FREE (cb, sizeof (EP_CALLBACK)); -+} -+ -+void -+ep_call_callbacks (EP_RAIL *rail, unsigned idx, statemap_t *map) -+{ -+ EP_CALLBACK *cb; -+ -+ kmutex_lock (&rail->CallbackLock); -+ -+ rail->CallbackStep = idx; -+ -+ for (cb = rail->CallbackList[idx]; cb; cb = cb->Next) { -+ (cb->Routine) (cb->Arg, map); -+ } -+ kmutex_unlock (&rail->CallbackLock); -+} -+ -+unsigned int -+ep_backoff (EP_BACKOFF *backoff, int type) -+{ -+ static int bcount[EP_NUM_BACKOFF] = {1, 16, 32, 64, 128, 256, 512, 1024}; -+ -+ if (backoff->type != type) -+ { -+ backoff->type = type; -+ backoff->indx = 0; -+ backoff->count = 0; -+ } -+ -+ if (++backoff->count > bcount[backoff->indx] && backoff->indx < (EP_NUM_BACKOFF-1)) -+ { -+ backoff->indx++; -+ backoff->count = 0; -+ } -+ -+ return (backoff->indx); -+} -+ -+/* Generic checksum algorithm */ -+uint16_t -+CheckSum (char *msg, int nob) -+{ -+ uint16_t sum = 0; -+ -+ while (nob-- > 0) -+ sum = sum * 13 + *msg++; -+ -+ return (sum); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/support_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/support_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/support_elan3.c 2005-06-01 23:12:54.687425728 -0400 -@@ -0,0 +1,2111 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: support_elan3.c,v 1.42.8.3 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/support_elan3.c,v $ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan3.h" -+#include "epcomms_elan3.h" -+#include "debug.h" -+ -+#include -+#include -+ -+/****************************************************************************************/ -+#define DMA_RING_NEXT_POS(ring) ((ring)->Position+1 == ring->Entries ? 0 : ((ring)->Position+1)) -+#define DMA_RING_PREV_POS(ring,pos) ((pos) == 0 ? (ring)->Entries-1 : (pos) - 1) -+ -+static int -+DmaRingCreate (EP3_RAIL *rail, EP3_DMA_RING *ring, int ctxnum, int entries) -+{ -+ unsigned long pgnum = (ctxnum * sizeof (E3_CommandPort)) / PAGE_SIZE; -+ unsigned long pgoff = (ctxnum * sizeof (E3_CommandPort)) & (PAGE_SIZE-1); -+ int s; -+ -+ /* set up the initial position */ -+ ring->Entries = entries; -+ ring->Position = 0; -+ -+ if (! (ring->pEvent = ep_alloc_elan (&rail->Generic, entries * sizeof (E3_BlockCopyEvent), 0, &ring->epEvent))) -+ { -+ ring->CommandPort = (ioaddr_t) NULL; -+ return (ENOMEM); -+ } -+ -+ if (! (ring->pDma = ep_alloc_elan (&rail->Generic, entries * sizeof (E3_DMA), 0, &ring->epDma))) -+ { -+ ep_free_elan (&rail->Generic, ring->epEvent, entries * sizeof (E3_BlockCopyEvent)); -+ -+ ring->CommandPort = (ioaddr_t) NULL; -+ return (ENOMEM); -+ } -+ -+ if (! (ring->pDoneBlk = ep_alloc_main (&rail->Generic, entries * sizeof (E3_uint32), 0, &ring->epDoneBlk))) -+ { -+ ep_free_elan (&rail->Generic, ring->epEvent, entries * sizeof (E3_BlockCopyEvent)); -+ ep_free_elan (&rail->Generic, ring->epDma, entries * sizeof (E3_DMA)); -+ -+ ring->CommandPort = (ioaddr_t) NULL; -+ return (ENOMEM); -+ } -+ -+ if (MapDeviceRegister (rail->Device, ELAN3_BAR_COMMAND_PORT, &ring->CommandPage, pgnum * PAGE_SIZE, PAGE_SIZE, &ring->CommandPageHandle) != ESUCCESS) -+ { -+ ep_free_elan (&rail->Generic, ring->epEvent, entries * sizeof (E3_BlockCopyEvent)); -+ ep_free_elan (&rail->Generic, ring->epDma, entries * sizeof (E3_DMA)); -+ ep_free_main (&rail->Generic, ring->epDoneBlk, entries * sizeof (E3_uint32)); -+ -+ ring->CommandPort = (ioaddr_t) NULL; -+ return (ENOMEM); -+ } -+ ring->CommandPort = ring->CommandPage + pgoff; -+ -+ for (s = 0; s < entries; s++) -+ { -+ /* setup the event */ -+ elan3_sdram_writel(rail->Device, DMA_RING_EVENT(ring,s) + offsetof(E3_BlockCopyEvent,ev_Type), -+ EV_TYPE_BCOPY | EV_TYPE_DMA | DMA_RING_DMA_ELAN(ring, s)); -+ elan3_sdram_writel(rail->Device, DMA_RING_EVENT(ring,s) + offsetof(E3_BlockCopyEvent,ev_Source), DMA_RING_DMA_ELAN(ring,s) | EV_WCOPY); -+ elan3_sdram_writel(rail->Device, DMA_RING_EVENT(ring,s) + offsetof(E3_BlockCopyEvent,ev_Dest), DMA_RING_DONE_ELAN(ring,s) | EV_TYPE_BCOPY_WORD ); -+ -+ /* need to set all the doneBlks to appear that they have completed */ -+ ring->pDoneBlk[s] = DMA_RING_DMA_ELAN(ring,s) | EV_WCOPY; -+ } -+ -+ return 0; /* success */ -+} -+ -+static void -+DmaRingRelease(EP3_RAIL *rail, EP3_DMA_RING *ring) -+{ -+ if (ring->CommandPage != (ioaddr_t) 0) -+ { -+ UnmapDeviceRegister(rail->Device, &ring->CommandPageHandle); -+ -+ ep_free_elan (&rail->Generic, ring->epEvent, ring->Entries * sizeof (E3_BlockCopyEvent)); -+ ep_free_elan (&rail->Generic, ring->epDma, ring->Entries * sizeof (E3_DMA)); -+ ep_free_main (&rail->Generic, ring->epDoneBlk, ring->Entries * sizeof (E3_uint32)); -+ } -+ ring->CommandPage = (ioaddr_t) 0; -+} -+ -+void -+DmaRingsRelease (EP3_RAIL *rail) -+{ -+ DmaRingRelease (rail, &rail->DmaRings[EP3_RING_CRITICAL]); -+ DmaRingRelease (rail, &rail->DmaRings[EP3_RING_HIGH_PRI]); -+ DmaRingRelease (rail, &rail->DmaRings[EP3_RING_LOW_PRI]); -+} -+ -+int -+DmaRingsCreate (EP3_RAIL *rail) -+{ -+ if (DmaRingCreate (rail, &rail->DmaRings[EP3_RING_CRITICAL], ELAN3_DMARING_BASE_CONTEXT_NUM + EP3_RING_CRITICAL, EP3_RING_CRITICAL_LEN) || -+ DmaRingCreate (rail, &rail->DmaRings[EP3_RING_HIGH_PRI], ELAN3_DMARING_BASE_CONTEXT_NUM + EP3_RING_HIGH_PRI, EP3_RING_HIGH_PRI_LEN) || -+ DmaRingCreate (rail, &rail->DmaRings[EP3_RING_LOW_PRI], ELAN3_DMARING_BASE_CONTEXT_NUM + EP3_RING_LOW_PRI, EP3_RING_LOW_PRI_LEN)) -+ { -+ DmaRingsRelease (rail); -+ return (ENOMEM); -+ } -+ -+ return 0; -+} -+ -+static int -+DmaRingNextSlot (EP3_DMA_RING *ring) -+{ -+ int pos = ring->Position; -+ int npos = DMA_RING_NEXT_POS(ring); -+ -+ if (ring->pDoneBlk[npos] == EP3_EVENT_ACTIVE) -+ return (-1); -+ -+ ring->pDoneBlk[pos] = EP3_EVENT_ACTIVE; -+ -+ ring->Position = npos; /* move on one */ -+ -+ return (pos); -+} -+ -+ -+/****************************************************************************************/ -+/* -+ * Dma/event command issueing - these handle cproc queue overflow traps. -+ */ -+static int -+DmaRunQueueSizeCheck (EP3_RAIL *rail, E3_uint32 len) -+{ -+ E3_uint64 FandBPtr = read_reg64 (rail->Device, DProc_SysCntx_FPtr); -+ E3_uint32 FPtr, BPtr; -+ E3_uint32 qlen; -+ -+#if (BYTE_ORDER == LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) -+ FPtr = (FandBPtr & 0xFFFFFFFFull); -+ BPtr = (FandBPtr >> 32); -+#else -+ FPtr = (FandBPtr >> 32); -+ BPtr = (FandBPtr & 0xFFFFFFFFull); -+#endif -+ -+ qlen = (((BPtr - FPtr)/sizeof (E3_DMA)) & (E3_SysCntxQueueSize-1)); -+ -+ if (qlen < 4) IncrStat (rail, DmaQueueLength[0]); -+ else if (qlen < 8) IncrStat (rail, DmaQueueLength[1]); -+ else if (qlen < 16) IncrStat (rail, DmaQueueLength[2]); -+ else if (qlen < 32) IncrStat (rail, DmaQueueLength[3]); -+ else if (qlen < 64) IncrStat (rail, DmaQueueLength[4]); -+ else if (qlen < 128) IncrStat (rail, DmaQueueLength[5]); -+ else if (qlen < 240) IncrStat (rail, DmaQueueLength[6]); -+ else IncrStat (rail, DmaQueueLength[7]); -+ -+ return (qlen < len); -+} -+ -+int -+IssueDma (EP3_RAIL *rail, E3_DMA_BE * dmabe, int type, int retryThread) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ EP3_RETRY_DMA *retry; -+ EP3_DMA_RING *ring; -+ int slot; -+ int i, res; -+ unsigned long flags; -+ -+ ASSERT (dmabe->s.dma_direction == DMA_WRITE || dmabe->s.dma_direction == DMA_READ_REQUEUE); -+ -+ ASSERT (! EP_VP_ISDATA(dmabe->s.dma_destVProc) || -+ (dmabe->s.dma_direction == DMA_WRITE ? -+ EP_VP_TO_NODE(dmabe->s.dma_srcVProc) == rail->Generic.Position.pos_nodeid : -+ EP_VP_TO_NODE(dmabe->s.dma_destVProc) == rail->Generic.Position.pos_nodeid)); -+ -+ /* -+ * If we're not the retry thread - then don't issue this DMA -+ * if there are any already queued on the retry lists with -+ * higher or equal priority than this one that are ready to -+ * retry. -+ */ -+ if (! retryThread) -+ { -+ for (i = EP_RETRY_BASE; i < type; i++) -+ { -+ if (list_empty (&rail->DmaRetries[i])) -+ continue; -+ -+ retry = list_entry (rail->DmaRetries[i].next, EP3_RETRY_DMA, Link); -+ -+ if (AFTER (lbolt, retry->RetryTime)) -+ { -+ IncrStat (rail, IssueDmaFail[type]); -+ return (ISSUE_COMMAND_RETRY); -+ } -+ } -+ } -+ -+ /* -+ * Depending on the type of DMA we're issuing - throttle back -+ * issueing of it if the DMA run queue is too full. This then -+ * prioritises the "special" messages and completing data -+ * transfers which have matched a receive buffer. -+ */ -+ -+ if (type >= EP_RETRY_LOW_PRI_RETRY) -+ { -+ if (! DmaRunQueueSizeCheck (rail, E3_SysCntxQueueSize / 2)) -+ { -+ IncrStat (rail, IssueDmaFail[type]); -+ return (ISSUE_COMMAND_RETRY); -+ } -+ ring = &rail->DmaRings[EP3_RING_LOW_PRI]; -+ } -+ else if (type == EP_RETRY_LOW_PRI) -+ { -+ if (! DmaRunQueueSizeCheck (rail, E3_SysCntxQueueSize / 3)) -+ { -+ IncrStat (rail, IssueDmaFail[type]); -+ return (ISSUE_COMMAND_RETRY); -+ } -+ ring = &rail->DmaRings[EP3_RING_LOW_PRI]; -+ } -+ else if (type >= EP_RETRY_HIGH_PRI) -+ ring = &rail->DmaRings[EP3_RING_HIGH_PRI]; -+ else -+ ring = &rail->DmaRings[EP3_RING_CRITICAL]; -+ -+ local_irq_save (flags); -+ if (! spin_trylock (&dev->CProcLock)) -+ { -+ IncrStat (rail, IssueDmaFail[type]); -+ -+ res = ISSUE_COMMAND_RETRY; -+ } -+ else -+ { -+ if ((slot = DmaRingNextSlot (ring)) == -1) -+ { -+ IncrStat (rail, IssueDmaFail[type]); -+ -+ res = ISSUE_COMMAND_RETRY; -+ } -+ else -+ { -+ EPRINTF4 (DBG_COMMAND, "IssueDma: type %08x size %08x Elan source %08x Elan dest %08x\n", -+ dmabe->s.dma_type, dmabe->s.dma_size, dmabe->s.dma_source, dmabe->s.dma_dest); -+ EPRINTF2 (DBG_COMMAND, " dst event %08x cookie/proc %08x\n", -+ dmabe->s.dma_destEvent, dmabe->s.dma_destCookieVProc); -+ EPRINTF2 (DBG_COMMAND, " src event %08x cookie/proc %08x\n", -+ dmabe->s.dma_srcEvent, dmabe->s.dma_srcCookieVProc); -+ -+ elan3_sdram_copyq_to_sdram (dev, dmabe, DMA_RING_DMA(ring, slot), sizeof (E3_DMA)); /* PCI write block */ -+ elan3_sdram_writel (dev, DMA_RING_EVENT(ring, slot) + offsetof (E3_BlockCopyEvent, ev_Count), 1); /* PCI write */ -+ -+ mb(); /* ensure writes to main memory completed */ -+ writel (DMA_RING_EVENT_ELAN(ring,slot), ring->CommandPort + offsetof (E3_CommandPort, SetEvent)); -+ mmiob(); /* and flush through IO writes */ -+ -+ res = ISSUE_COMMAND_OK; -+ } -+ spin_unlock (&dev->CProcLock); -+ } -+ local_irq_restore (flags); -+ -+ return (res); -+} -+ -+int -+IssueWaitevent (EP3_RAIL *rail, E3_Addr value) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ int res; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ ASSERT (rail->CommandPortEventTrap == FALSE); -+ -+ /* -+ * Disable the command processor interrupts, so that we don't see -+ * spurious interrupts appearing. -+ */ -+ DISABLE_INT_MASK (dev, INT_CProc | INT_ComQueue); -+ -+ EPRINTF1 (DBG_COMMAND, "IssueWaitevent: %08x\n", value); -+ -+ mb(); /* ensure writes to main memory completed */ -+ writel (value, rail->CommandPort + offsetof (E3_CommandPort, WaitEvent0)); -+ mmiob(); /* and flush through IO writes */ -+ -+ do { -+ res = CheckCommandQueueFlushed (rail->Ctxt, EventComQueueNotEmpty, ISSUE_COMMAND_CANT_WAIT, &flags); -+ -+ EPRINTF1 (DBG_COMMAND, "IssueWaitevent: CheckCommandQueueFlushed -> %d\n", res); -+ -+ if (res == ISSUE_COMMAND_WAIT) -+ HandleCProcTrap (dev, 0, NULL); -+ } while (res != ISSUE_COMMAND_OK); -+ -+ if (! rail->CommandPortEventTrap) -+ res = ISSUE_COMMAND_OK; -+ else -+ { -+ rail->CommandPortEventTrap = FALSE; -+ res = ISSUE_COMMAND_TRAPPED; -+ } -+ -+ EPRINTF1 (DBG_COMMAND, "IssueWaitevent: -> %d\n", res); -+ -+ /* -+ * Re-enable the command processor interrupt as we've finished -+ * polling it. -+ */ -+ ENABLE_INT_MASK (dev, INT_CProc | INT_ComQueue); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ -+ return (res); -+} -+ -+void -+IssueSetevent (EP3_RAIL *rail, E3_Addr value) -+{ -+ EPRINTF1 (DBG_COMMAND, "IssueSetevent: %08x\n", value); -+ -+ mb(); /* ensure writes to main memory completed */ -+ writel (value, rail->CommandPort + offsetof (E3_CommandPort, SetEvent)); -+ mmiob(); /* and flush through IO writes */ -+} -+ -+void -+IssueRunThread (EP3_RAIL *rail, E3_Addr value) -+{ -+ EPRINTF1 (DBG_COMMAND, "IssueRunThread: %08x\n", value); -+ -+ mb(); /* ensure writes to main memory completed */ -+ writel (value, rail->CommandPort + offsetof (E3_CommandPort, RunThread)); -+ mmiob(); /* and flush through IO writes */ -+} -+ -+/****************************************************************************************/ -+/* -+ * DMA retry list management -+ */ -+static unsigned DmaRetryTimes[EP_NUM_RETRIES]; -+ -+static void -+ep3_dma_retry (EP3_RAIL *rail) -+{ -+ EP3_COOKIE *cp; -+ int res; -+ int vp; -+ unsigned long flags; -+ int i; -+ -+ kernel_thread_init("ep3_dma_retry"); -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ for (;;) -+ { -+ long yieldAt = lbolt + (hz/10); -+ long retryTime = 0; -+ -+ if (rail->DmaRetryThreadShouldStop) -+ break; -+ -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ while (! list_empty (&rail->DmaRetries[i])) -+ { -+ EP3_RETRY_DMA *retry = list_entry (rail->DmaRetries[i].next, EP3_RETRY_DMA, Link); -+ -+ if (! AFTER (lbolt, retry->RetryTime)) -+ break; -+ -+ if (rail->DmaRetryThreadShouldStall || AFTER (lbolt, yieldAt)) -+ goto cant_do_more; -+ -+ EPRINTF2 (DBG_RETRY, "%s: DmaRetryThread: retry %p\n", rail->Generic.Name, retry); -+ EPRINTF5 (DBG_RETRY, "%s: %08x %08x %08x %08x\n", -+ rail->Generic.Name, retry->Dma.s.dma_type, retry->Dma.s.dma_size, retry->Dma.s.dma_source, retry->Dma.s.dma_dest); -+ EPRINTF5 (DBG_RETRY, "%s: %08x %08x %08x %08x\n", -+ rail->Generic.Name, retry->Dma.s.dma_destEvent, retry->Dma.s.dma_destCookieVProc, -+ retry->Dma.s.dma_srcEvent, retry->Dma.s.dma_srcCookieVProc); -+#if defined(DEBUG) -+ if (retry->Dma.s.dma_direction == DMA_WRITE) -+ cp = LookupEventCookie (rail, &rail->CookieTable, retry->Dma.s.dma_srcEvent); -+ else -+ cp = LookupEventCookie (rail, &rail->CookieTable, retry->Dma.s.dma_destEvent); -+ -+ ASSERT (cp != NULL || (retry->Dma.s.dma_srcEvent == 0 && retry->Dma.s.dma_direction == DMA_WRITE && retry->Dma.s.dma_isRemote)); -+ -+ if (cp && cp->Operations->DmaVerify) -+ cp->Operations->DmaVerify (rail, cp->Arg, &retry->Dma); -+#endif -+ -+#if defined(DEBUG_ASSERT) -+ if (retry->Dma.s.dma_direction == DMA_WRITE) -+ vp = retry->Dma.s.dma_destVProc; -+ else -+ vp = retry->Dma.s.dma_srcVProc; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || -+ (rail->Generic.Nodes[EP_VP_TO_NODE(vp)].State >= EP_NODE_CONNECTED && -+ rail->Generic.Nodes[EP_VP_TO_NODE(vp)].State <= EP_NODE_LOCAL_PASSIVATE)); -+#endif -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ res = IssueDma (rail, &(retry->Dma), i, TRUE); -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ if (res != ISSUE_COMMAND_OK) -+ goto cant_do_more; -+ -+ /* Command issued, so remove from list, and add to free list */ -+ list_del (&retry->Link); -+ list_add (&retry->Link, &rail->DmaRetryFreeList); -+ } -+ } -+ cant_do_more: -+ -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ if (!list_empty (&rail->DmaRetries[i])) -+ { -+ EP3_RETRY_DMA *retry = list_entry (rail->DmaRetries[i].next, EP3_RETRY_DMA, Link); -+ -+ retryTime = retryTime ? MIN(retryTime, retry->RetryTime) : retry->RetryTime; -+ } -+ } -+ -+ if (retryTime && !AFTER (retryTime, lbolt)) -+ retryTime = lbolt + 1; -+ -+ do { -+ EPRINTF3 (DBG_RETRY, "%s: ep_cm_retry: %s %lx\n", rail->Generic.Name, rail->DmaRetryThreadShouldStall ? "stalled" : "sleeping", retryTime); -+ -+ if (rail->DmaRetryTime == 0 || (retryTime != 0 && retryTime < rail->DmaRetryTime)) -+ rail->DmaRetryTime = retryTime; -+ -+ rail->DmaRetrySleeping = TRUE; -+ -+ if (rail->DmaRetryThreadShouldStall) /* wakeup threads waiting in StallDmaRetryThread */ -+ kcondvar_wakeupall (&rail->DmaRetryWait, &rail->DmaRetryLock); /* for us to really go to sleep for good. */ -+ -+ if (rail->DmaRetryTime == 0 || rail->DmaRetryThreadShouldStall) -+ kcondvar_wait (&rail->DmaRetryWait, &rail->DmaRetryLock, &flags); -+ else -+ kcondvar_timedwait (&rail->DmaRetryWait, &rail->DmaRetryLock, &flags, rail->DmaRetryTime); -+ -+ rail->DmaRetrySleeping = FALSE; -+ -+ } while (rail->DmaRetryThreadShouldStall); -+ -+ rail->DmaRetryTime = 0; -+ } -+ -+ rail->DmaRetryThreadStopped = 1; -+ kcondvar_wakeupall (&rail->DmaRetryWait, &rail->DmaRetryLock); -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ -+ kernel_thread_exit(); -+} -+ -+void -+StallDmaRetryThread (EP3_RAIL *rail) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ rail->DmaRetryThreadShouldStall++; -+ -+ while (! rail->DmaRetrySleeping) -+ kcondvar_wait (&rail->DmaRetryWait, &rail->DmaRetryLock, &flags); -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+} -+ -+void -+ResumeDmaRetryThread (EP3_RAIL *rail) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ ASSERT (rail->DmaRetrySleeping); -+ -+ if (--rail->DmaRetryThreadShouldStall == 0) -+ { -+ rail->DmaRetrySleeping = 0; -+ kcondvar_wakeupone (&rail->DmaRetryWait, &rail->DmaRetryLock); -+ } -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+} -+ -+int -+InitialiseDmaRetries (EP3_RAIL *rail) -+{ -+ int i; -+ -+ spin_lock_init (&rail->DmaRetryLock); -+ kcondvar_init (&rail->DmaRetryWait); -+ -+ for (i = 0; i < EP_NUM_RETRIES; i++) -+ INIT_LIST_HEAD (&rail->DmaRetries[i]); -+ -+ INIT_LIST_HEAD (&rail->DmaRetryFreeList); -+ -+ DmaRetryTimes[EP_RETRY_HIGH_PRI] = EP_RETRY_HIGH_PRI_TIME; -+ -+ for (i =0 ; i < EP_NUM_BACKOFF; i++) -+ DmaRetryTimes[EP_RETRY_HIGH_PRI_RETRY+i] = EP_RETRY_HIGH_PRI_TIME << i; -+ -+ DmaRetryTimes[EP_RETRY_LOW_PRI] = EP_RETRY_LOW_PRI_TIME; -+ -+ for (i =0 ; i < EP_NUM_BACKOFF; i++) -+ DmaRetryTimes[EP_RETRY_LOW_PRI_RETRY+i] = EP_RETRY_LOW_PRI_TIME << i; -+ -+ DmaRetryTimes[EP_RETRY_ANONYMOUS] = EP_RETRY_ANONYMOUS_TIME; -+ DmaRetryTimes[EP_RETRY_NETERR] = EP_RETRY_NETERR_TIME; -+ -+ rail->DmaRetryInitialised = 1; -+ -+ if (kernel_thread_create (ep3_dma_retry, (void *) rail) == 0) -+ { -+ spin_lock_destroy (&rail->DmaRetryLock); -+ return (ENOMEM); -+ } -+ -+ rail->DmaRetryThreadStarted = 1; -+ -+ return (ESUCCESS); -+} -+ -+void -+DestroyDmaRetries (EP3_RAIL *rail) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ rail->DmaRetryThreadShouldStop = 1; -+ while (rail->DmaRetryThreadStarted && !rail->DmaRetryThreadStopped) -+ { -+ kcondvar_wakeupall (&rail->DmaRetryWait, &rail->DmaRetryLock); -+ kcondvar_wait (&rail->DmaRetryWait, &rail->DmaRetryLock, &flags); -+ } -+ rail->DmaRetryThreadStarted = 0; -+ rail->DmaRetryThreadStopped = 0; -+ rail->DmaRetryThreadShouldStop = 0; -+ rail->DmaRetryInitialised = 0; -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ -+ /* Everyone should have given back their retry dma's by now */ -+ ASSERT (rail->DmaRetryReserved == 0); -+ -+ while (! list_empty (&rail->DmaRetryFreeList)) -+ { -+ EP3_RETRY_DMA *retry = list_entry (rail->DmaRetryFreeList.next, EP3_RETRY_DMA, Link); -+ -+ list_del (&retry->Link); -+ -+ KMEM_FREE (retry, sizeof (EP3_RETRY_DMA)); -+ } -+ -+ kcondvar_destroy (&rail->DmaRetryWait); -+ spin_lock_destroy (&rail->DmaRetryLock); -+} -+ -+int -+ReserveDmaRetries (EP3_RAIL *rail, int count, EP_ATTRIBUTE attr) -+{ -+ EP3_RETRY_DMA *retry; -+ int remaining = count; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ if (remaining <= (rail->DmaRetryCount - rail->DmaRetryReserved)) -+ { -+ rail->DmaRetryReserved += remaining; -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ return (ESUCCESS); -+ } -+ -+ remaining -= (rail->DmaRetryCount - rail->DmaRetryReserved); -+ -+ rail->DmaRetryReserved = rail->DmaRetryCount; -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ -+ while (remaining) -+ { -+ KMEM_ALLOC (retry, EP3_RETRY_DMA *, sizeof (EP3_RETRY_DMA), !(attr & EP_NO_SLEEP)); -+ -+ if (retry == NULL) -+ goto failed; -+ -+ /* clear E3_DMA */ -+ bzero((char *)(&(retry->Dma.s)), sizeof(E3_DMA)); -+ -+ remaining--; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ list_add (&retry->Link, &rail->DmaRetryFreeList); -+ -+ rail->DmaRetryCount++; -+ rail->DmaRetryReserved++; -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ } -+ return (ESUCCESS); -+ -+ failed: -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ rail->DmaRetryReserved -= (count - remaining); -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ return (ENOMEM); -+} -+ -+void -+ReleaseDmaRetries (EP3_RAIL *rail, int count) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ rail->DmaRetryReserved -= count; -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+} -+ -+void -+QueueDmaForRetry (EP3_RAIL *rail, E3_DMA_BE *dma, int interval) -+{ -+ EP3_RETRY_DMA *retry; -+ unsigned long flags; -+ -+ /* -+ * When requeueing DMAs they must never be "READ" dma's since -+ * these would fetch the DMA descriptor from the retryn descriptor -+ */ -+ ASSERT (dma->s.dma_direction == DMA_WRITE || dma->s.dma_direction == DMA_READ_REQUEUE); -+ ASSERT (dma->s.dma_direction == DMA_WRITE ? -+ EP_VP_TO_NODE(dma->s.dma_srcVProc) == rail->Generic.Position.pos_nodeid : -+ EP_VP_TO_NODE(dma->s.dma_destVProc) == rail->Generic.Position.pos_nodeid); -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ EP_ASSERT (&rail->Generic, !list_empty (&rail->DmaRetryFreeList)); -+ -+ /* take an item of the free list */ -+ retry = list_entry (rail->DmaRetryFreeList.next, EP3_RETRY_DMA, Link); -+ -+ list_del (&retry->Link); -+ -+ EPRINTF5 (DBG_RETRY, "%s: QueueDmaForRetry: %08x %08x %08x %08x\n", rail->Generic.Name, -+ dma->s.dma_type, dma->s.dma_size, dma->s.dma_source, dma->s.dma_dest); -+ EPRINTF5 (DBG_RETRY, "%s: %08x %08x %08x %08x\n",rail->Generic.Name, -+ dma->s.dma_destEvent, dma->s.dma_destCookieVProc, -+ dma->s.dma_srcEvent, dma->s.dma_srcCookieVProc); -+ -+ /* copy the DMA into the retry descriptor */ -+ retry->Dma.s.dma_type = dma->s.dma_type; -+ retry->Dma.s.dma_size = dma->s.dma_size; -+ retry->Dma.s.dma_source = dma->s.dma_source; -+ retry->Dma.s.dma_dest = dma->s.dma_dest; -+ retry->Dma.s.dma_destEvent = dma->s.dma_destEvent; -+ retry->Dma.s.dma_destCookieVProc = dma->s.dma_destCookieVProc; -+ retry->Dma.s.dma_srcEvent = dma->s.dma_srcEvent; -+ retry->Dma.s.dma_srcCookieVProc = dma->s.dma_srcCookieVProc; -+ -+ retry->RetryTime = lbolt + DmaRetryTimes[interval]; -+ -+ /* chain onto the end of the approriate retry list */ -+ list_add_tail (&retry->Link, &rail->DmaRetries[interval]); -+ -+ /* now wakeup the retry thread */ -+ if (rail->DmaRetryTime == 0 || retry->RetryTime < rail->DmaRetryTime) -+ rail->DmaRetryTime = retry->RetryTime; -+ -+ if (rail->DmaRetrySleeping && !rail->DmaRetryThreadShouldStall) -+ { -+ rail->DmaRetrySleeping = 0; -+ kcondvar_wakeupone (&rail->DmaRetryWait, &rail->DmaRetryLock); -+ } -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+} -+ -+void -+QueueDmaOnStalledList (EP3_RAIL *rail, E3_DMA_BE *dma) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[dma->s.dma_direction == DMA_WRITE ? -+ EP_VP_TO_NODE(dma->s.dma_srcVProc) : -+ EP_VP_TO_NODE(dma->s.dma_destVProc)]; -+ EP3_RETRY_DMA *retry; -+ unsigned long flags; -+ -+ /* -+ * When requeueing DMAs they must never be "READ" dma's since -+ * these would fetch the DMA descriptor from the retryn descriptor -+ */ -+ ASSERT (dma->s.dma_direction == DMA_WRITE || dma->s.dma_direction == DMA_READ_REQUEUE); -+ ASSERT (dma->s.dma_direction == DMA_WRITE ? -+ EP_VP_TO_NODE(dma->s.dma_srcVProc) == rail->Generic.Position.pos_nodeid : -+ EP_VP_TO_NODE(dma->s.dma_destVProc) == rail->Generic.Position.pos_nodeid); -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ -+ EP_ASSERT (&rail->Generic, !list_empty (&rail->DmaRetryFreeList)); -+ -+ /* take an item of the free list */ -+ retry = list_entry (rail->DmaRetryFreeList.next, EP3_RETRY_DMA, Link); -+ -+ list_del (&retry->Link); -+ -+ EPRINTF5 (DBG_RETRY, "%s: QueueDmaOnStalledList: %08x %08x %08x %08x\n", rail->Generic.Name, -+ dma->s.dma_type, dma->s.dma_size, dma->s.dma_source, dma->s.dma_dest); -+ EPRINTF5 (DBG_RETRY, "%s: %08x %08x %08x %08x\n", rail->Generic.Name, -+ dma->s.dma_destEvent, dma->s.dma_destCookieVProc, -+ dma->s.dma_srcEvent, dma->s.dma_srcCookieVProc); -+ -+ /* copy the DMA into the retry descriptor */ -+ retry->Dma.s.dma_type = dma->s.dma_type; -+ retry->Dma.s.dma_size = dma->s.dma_size; -+ retry->Dma.s.dma_source = dma->s.dma_source; -+ retry->Dma.s.dma_dest = dma->s.dma_dest; -+ retry->Dma.s.dma_destEvent = dma->s.dma_destEvent; -+ retry->Dma.s.dma_destCookieVProc = dma->s.dma_destCookieVProc; -+ retry->Dma.s.dma_srcEvent = dma->s.dma_srcEvent; -+ retry->Dma.s.dma_srcCookieVProc = dma->s.dma_srcCookieVProc; -+ -+ /* chain onto the node cancelled dma list */ -+ list_add_tail (&retry->Link, &nodeRail->StalledDmas); -+ -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+} -+ -+void -+FreeStalledDmas (EP3_RAIL *rail, unsigned int nodeId) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[nodeId]; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ list_for_each_safe (el, nel, &nodeRail->StalledDmas) { -+ list_del (el); -+ list_add (el, &rail->DmaRetryFreeList); -+ } -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+} -+ -+/****************************************************************************************/ -+/* -+ * Connection management. -+ */ -+static void -+DiscardingHaltOperation (ELAN3_DEV *dev, void *arg) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ rail->HaltOpCompleted = 1; -+ kcondvar_wakeupall (&rail->HaltOpSleep, &dev->IntrLock); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+typedef struct { -+ EP3_RAIL *rail; -+ sdramaddr_t qaddr; -+} SetQueueFullData; -+ -+static void -+SetQueueLockedOperation (ELAN3_DEV *dev, void *arg) -+{ -+ SetQueueFullData *data = (SetQueueFullData *) arg; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ -+ elan3_sdram_writel (dev, data->qaddr, E3_QUEUE_LOCKED | elan3_sdram_readl(dev, data->qaddr)); -+ -+ data->rail->HaltOpCompleted = 1; -+ kcondvar_wakeupall (&data->rail->HaltOpSleep, &dev->IntrLock); -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+static void -+FlushDmaQueuesHaltOperation (ELAN3_DEV *dev, void *arg) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) arg; -+ sdramaddr_t FPtr, BPtr; -+ sdramaddr_t Base, Top; -+ E3_DMA_BE dma; -+ EP_NODE_RAIL *node; -+ int vp; -+ unsigned long flags; -+ -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProc.s.FSR)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData0.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData1.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData2.s.FSR.Status)) == 0); -+ ASSERT (elan3_sdram_readl (dev, dev->TAndQBase + offsetof (E3_TrapAndQueue, DProcData3.s.FSR.Status)) == 0); -+ -+ FPtr = read_reg32 (dev, DProc_SysCntx_FPtr); -+ BPtr = read_reg32 (dev, DProc_SysCntx_BPtr); -+ Base = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[0]); -+ Top = dev->TAndQBase + offsetof (E3_TrapAndQueue, SysCntxDmaQueue[E3_SysCntxQueueSize-1]); -+ -+ while (FPtr != BPtr) -+ { -+ elan3_sdram_copyq_from_sdram (dev, FPtr, &dma, sizeof (E3_DMA_BE)); -+ -+ EPRINTF5 (DBG_DISCON, "%s: FlushDmaQueuesHaltOperation: %08x %08x %08x %08x\n", rail->Generic.Name, -+ dma.s.dma_type, dma.s.dma_size, dma.s.dma_source, dma.s.dma_dest); -+ EPRINTF5 (DBG_DISCON, "%s: %08x %08x %08x %08x\n", rail->Generic.Name, -+ dma.s.dma_destEvent, dma.s.dma_destCookieVProc, -+ dma.s.dma_srcEvent, dma.s.dma_srcCookieVProc); -+ -+ ASSERT ((dma.s.dma_u.s.Context & SYS_CONTEXT_BIT) != 0); -+ -+ if (dma.s.dma_direction == DMA_WRITE) -+ vp = dma.s.dma_destVProc; -+ else -+ vp = dma.s.dma_srcVProc; -+ -+ node = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || (node->State >= EP_NODE_CONNECTED && node->State <= EP_NODE_LOCAL_PASSIVATE)); -+ -+ if (EP_VP_ISDATA(vp) && node->State == EP_NODE_LOCAL_PASSIVATE) -+ { -+ /* -+ * This is a DMA going to the node which is being removed, -+ * so move it onto the node dma list where it will get -+ * handled later. -+ */ -+ EPRINTF1 (DBG_DISCON, "%s: FlushDmaQueuesHaltOperation: move dma to cancelled list\n", rail->Generic.Name); -+ -+ if (dma.s.dma_direction != DMA_WRITE) -+ { -+ /* for read dma's set the DMA_READ_REQUEUE bits as the dma_source has been -+ * modified by the elan to point at the dma in the rxd where it was issued -+ * from */ -+ dma.s.dma_direction = (dma.s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ } -+ -+ QueueDmaOnStalledList (rail, &dma); -+ -+ /* -+ * Remove the DMA from the queue by replacing it with one with -+ * zero size and no events. -+ * -+ * NOTE: we must preserve the SYS_CONTEXT_BIT since the Elan uses this -+ * to mark the approriate run queue as empty. -+ */ -+ dma.s.dma_type = (SYS_CONTEXT_BIT << 16); -+ dma.s.dma_size = 0; -+ dma.s.dma_source = (E3_Addr) 0; -+ dma.s.dma_dest = (E3_Addr) 0; -+ dma.s.dma_destEvent = (E3_Addr) 0; -+ dma.s.dma_destCookieVProc = 0; -+ dma.s.dma_srcEvent = (E3_Addr) 0; -+ dma.s.dma_srcCookieVProc = 0; -+ -+ elan3_sdram_copyq_to_sdram (dev, &dma, FPtr, sizeof (E3_DMA_BE)); -+ } -+ -+ FPtr = (FPtr == Top) ? Base : FPtr + sizeof (E3_DMA); -+ } -+ -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ rail->HaltOpCompleted = 1; -+ kcondvar_wakeupall (&rail->HaltOpSleep, &dev->IntrLock); -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+} -+ -+void -+SetQueueLocked (EP3_RAIL *rail, sdramaddr_t qaddr) -+{ -+ ELAN3_DEV *dev = rail->Device; -+ SetQueueFullData data; -+ unsigned long flags; -+ -+ /* Ensure that the context filter changes have been seen by halting -+ * then restarting the inputters - this also ensures that any setevent -+ * commands used to issue dma's have completed and any trap has been -+ * handled. */ -+ data.rail = rail; -+ data.qaddr = qaddr; -+ -+ kmutex_lock (&rail->HaltOpMutex); -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ QueueHaltOperation (dev, 0, NULL, INT_DiscardingSysCntx | INT_TProcHalted, SetQueueLockedOperation, &data); -+ -+ while (! rail->HaltOpCompleted) -+ kcondvar_wait (&rail->HaltOpSleep, &dev->IntrLock, &flags); -+ rail->HaltOpCompleted = 0; -+ -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ kmutex_unlock (&rail->HaltOpMutex); -+} -+ -+void -+ep3_flush_filters (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ ELAN3_DEV *dev = rail->Device; -+ unsigned long flags; -+ -+ /* Ensure that the context filter changes have been seen by halting -+ * then restarting the inputters - this also ensures that any setevent -+ * commands used to issue dma's have completed and any trap has been -+ * handled. */ -+ kmutex_lock (&rail->HaltOpMutex); -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ QueueHaltOperation (dev, 0, NULL, INT_DiscardingSysCntx, DiscardingHaltOperation, rail); -+ -+ while (! rail->HaltOpCompleted) -+ kcondvar_wait (&rail->HaltOpSleep, &dev->IntrLock, &flags); -+ rail->HaltOpCompleted = 0; -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ kmutex_unlock (&rail->HaltOpMutex); -+} -+ -+void -+ep3_flush_queues (EP_RAIL *r) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) r; -+ ELAN3_DEV *dev = rail->Device; -+ struct list_head *el; -+ struct list_head *nel; -+ EP_NODE_RAIL *node; -+ unsigned long flags; -+ int vp, i; -+ -+ ASSERT (NO_LOCKS_HELD); -+ -+ /* First - stall the dma retry thread, so that it will no longer -+ * restart any dma's from the rety lists. */ -+ StallDmaRetryThread (rail); -+ -+ /* Second - queue a halt operation to flush through all DMA's which are executing -+ * or on the run queue. */ -+ kmutex_lock (&rail->HaltOpMutex); -+ spin_lock_irqsave (&dev->IntrLock, flags); -+ QueueHaltOperation (dev, 0, NULL, INT_DProcHalted | INT_TProcHalted, FlushDmaQueuesHaltOperation, rail); -+ while (! rail->HaltOpCompleted) -+ kcondvar_wait (&rail->HaltOpSleep, &dev->IntrLock, &flags); -+ rail->HaltOpCompleted = 0; -+ spin_unlock_irqrestore (&dev->IntrLock, flags); -+ kmutex_unlock (&rail->HaltOpMutex); -+ -+ /* Third - run down the dma retry lists and move all entries to the cancelled -+ * list. Any dma's which were on the run queues have already been -+ * moved there */ -+ spin_lock_irqsave (&rail->DmaRetryLock, flags); -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ list_for_each_safe (el, nel, &rail->DmaRetries[i]) { -+ EP3_RETRY_DMA *retry = list_entry (el, EP3_RETRY_DMA, Link); -+ -+ if (retry->Dma.s.dma_direction == DMA_WRITE) -+ vp = retry->Dma.s.dma_destVProc; -+ else -+ vp = retry->Dma.s.dma_srcVProc; -+ -+ node = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || (node->State >= EP_NODE_CONNECTED && node->State <= EP_NODE_LOCAL_PASSIVATE)); -+ -+ if (EP_VP_ISDATA(vp) && node->State == EP_NODE_LOCAL_PASSIVATE) -+ { -+ EPRINTF5 (DBG_DISCON, "%s: FlushDmaQueues: %08x %08x %08x %08x\n",rail->Generic.Name, -+ retry->Dma.s.dma_type, retry->Dma.s.dma_size, retry->Dma.s.dma_source, retry->Dma.s.dma_dest); -+ EPRINTF5 (DBG_DISCON, "%s: %08x %08x %08x %08x\n", rail->Generic.Name, -+ retry->Dma.s.dma_destEvent, retry->Dma.s.dma_destCookieVProc, -+ retry->Dma.s.dma_srcEvent, retry->Dma.s.dma_srcCookieVProc); -+ -+ list_del (&retry->Link); -+ -+ list_add_tail (&retry->Link, &node->StalledDmas); -+ } -+ } -+ } -+ spin_unlock_irqrestore (&rail->DmaRetryLock, flags); -+ -+ /* Finally - allow the dma retry thread to run again */ -+ ResumeDmaRetryThread (rail); -+} -+ -+/****************************************************************************************/ -+/* NOTE - we require that all cookies are non-zero, which is -+ * achieved because EP_VP_DATA() is non-zero for all -+ * nodes */ -+E3_uint32 -+LocalCookie (EP3_RAIL *rail, unsigned remoteNode) -+{ -+ E3_uint32 cookie; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->CookieLock, flags); -+ cookie = DMA_COOKIE (rail->MainCookies[remoteNode], EP_VP_DATA(rail->Generic.Position.pos_nodeid)); -+ spin_unlock_irqrestore (&rail->CookieLock, flags); -+ -+ /* Main processor cookie for srcCookie - this is what is sent -+ * to the remote node along with the setevent from the put -+ * or the dma descriptor for a get */ -+ return (cookie); -+} -+ -+E3_uint32 -+RemoteCookie (EP3_RAIL *rail, u_int remoteNode) -+{ -+ uint32_t cookie; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->CookieLock, flags); -+ cookie = DMA_REMOTE_COOKIE (rail->MainCookies[remoteNode], EP_VP_DATA(remoteNode)); -+ spin_unlock_irqrestore (&rail->CookieLock, flags); -+ -+ /* Main processor cookie for dstCookie - this is the cookie -+ * that the "remote put" dma uses for it's setevent packets for -+ * a get dma */ -+ -+ return (cookie); -+} -+ -+/****************************************************************************************/ -+/* -+ * Event Cookie management. -+ * -+ * We find the ep_cookie in one of two ways: -+ * 1) for block copy events -+ * the cookie value is stored in the ev_Source - for EVIRQ events -+ * it is also stored in the ev_Type -+ * 2) for normal events -+ * we just use the event address. -+ */ -+void -+InitialiseCookieTable (EP3_COOKIE_TABLE *table) -+{ -+ register int i; -+ -+ spin_lock_init (&table->Lock); -+ -+ for (i = 0; i < EP3_COOKIE_HASH_SIZE; i++) -+ table->Entries[i] = NULL; -+} -+ -+void -+DestroyCookieTable (EP3_COOKIE_TABLE *table) -+{ -+ register int i; -+ -+ for (i = 0; i < EP3_COOKIE_HASH_SIZE; i++) -+ if (table->Entries[i]) -+ printk ("DestroyCookieTable: entry %d not empty\n", i); -+ -+ spin_lock_destroy (&table->Lock); -+} -+ -+void -+RegisterCookie (EP3_COOKIE_TABLE *table, EP3_COOKIE *cp, E3_uint32 cookie, EP3_COOKIE_OPS *ops, void *arg) -+{ -+ EP3_COOKIE *tcp; -+ int hashval = EP3_HASH_COOKIE(cookie); -+ unsigned long flags; -+ -+ spin_lock_irqsave (&table->Lock, flags); -+ -+ cp->Operations = ops; -+ cp->Arg = arg; -+ cp->Cookie = cookie; -+ -+#if defined(DEBUG) -+ /* Check that the cookie is unique */ -+ for (tcp = table->Entries[hashval]; tcp; tcp = tcp->Next) -+ if (tcp->Cookie == cookie) -+ panic ("RegisterEventCookie: non unique cookie\n"); -+#endif -+ cp->Next = table->Entries[hashval]; -+ -+ table->Entries[hashval] = cp; -+ -+ spin_unlock_irqrestore (&table->Lock, flags); -+} -+ -+void -+DeregisterCookie (EP3_COOKIE_TABLE *table, EP3_COOKIE *cp) -+{ -+ EP3_COOKIE **predCookiep; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&table->Lock, flags); -+ -+ for (predCookiep = &table->Entries[EP3_HASH_COOKIE (cp->Cookie)]; *predCookiep; predCookiep = &(*predCookiep)->Next) -+ { -+ if (*predCookiep == cp) -+ { -+ *predCookiep = cp->Next; -+ break; -+ } -+ } -+ -+ spin_unlock_irqrestore (&table->Lock, flags); -+ -+ cp->Operations = NULL; -+ cp->Arg = NULL; -+ cp->Cookie = 0; -+ cp->Next = NULL; -+} -+ -+EP3_COOKIE * -+LookupCookie (EP3_COOKIE_TABLE *table, E3_Addr cookie) -+{ -+ EP3_COOKIE *cp; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&table->Lock, flags); -+ -+ for (cp = table->Entries[EP3_HASH_COOKIE(cookie)]; cp; cp = cp->Next) -+ if (cp->Cookie == cookie) -+ break; -+ -+ spin_unlock_irqrestore (&table->Lock, flags); -+ return (cp); -+} -+ -+EP3_COOKIE * -+LookupEventCookie (EP3_RAIL *rail, EP3_COOKIE_TABLE *table, E3_Addr eaddr) -+{ -+ sdramaddr_t event; -+ E3_uint32 type; -+ -+ if ((event = ep_elan2sdram (&rail->Generic, eaddr)) != (sdramaddr_t) 0) -+ { -+ type = elan3_sdram_readl (rail->Device, event + offsetof (E3_BlockCopyEvent, ev_Type)); -+ -+ if (type & EV_TYPE_BCOPY) -+ return (LookupCookie (table, elan3_sdram_readl (rail->Device, event + offsetof (E3_BlockCopyEvent, ev_Source)) & ~EV_WCOPY)); -+ else -+ return (LookupCookie (table, eaddr)); -+ } -+ -+ return (NULL); -+} -+ -+/****************************************************************************************/ -+/* -+ * Elan context operations - note only support interrupt ops. -+ */ -+static int ep3_event (ELAN3_CTXT *ctxt, E3_uint32 cookie, int flag); -+static int ep3_dprocTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap); -+static int ep3_tprocTrap (ELAN3_CTXT *ctxt, THREAD_TRAP *trap); -+static int ep3_iprocTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, int chan); -+static int ep3_cprocTrap (ELAN3_CTXT *ctxt, COMMAND_TRAP *trap); -+static int ep3_cprocReissue (ELAN3_CTXT *ctxt, CProcTrapBuf_BE *tbuf); -+ -+static E3_uint8 ep3_load8 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void ep3_store8 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint8 val); -+static E3_uint16 ep3_load16 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void ep3_store16 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint16 val); -+static E3_uint32 ep3_load32 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void ep3_store32 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint32 val); -+static E3_uint64 ep3_load64 (ELAN3_CTXT *ctxt, E3_Addr addr); -+static void ep3_store64 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint64 val); -+ -+ELAN3_OPS ep3_elan3_ops = -+{ -+ ELAN3_OPS_VERSION, /* Version */ -+ -+ NULL, /* Exception */ -+ NULL, /* GetWordItem */ -+ NULL, /* GetBlockItem */ -+ NULL, /* PutWordItem */ -+ NULL, /* PutBlockItem */ -+ NULL, /* PutbackItem */ -+ NULL, /* FreeWordItem */ -+ NULL, /* FreeBlockItem */ -+ NULL, /* CountItems */ -+ ep3_event, /* Event */ -+ NULL, /* SwapIn */ -+ NULL, /* SwapOut */ -+ NULL, /* FreePrivate */ -+ NULL, /* FixupNetworkError */ -+ ep3_dprocTrap, /* DProcTrap */ -+ ep3_tprocTrap, /* TProcTrap */ -+ ep3_iprocTrap, /* IProcTrap */ -+ ep3_cprocTrap, /* CProcTrap */ -+ ep3_cprocReissue, /* CProcReissue */ -+ NULL, /* StartFaultCheck */ -+ NULL, /* EndFaulCheck */ -+ ep3_load8, /* Load8 */ -+ ep3_store8, /* Store8 */ -+ ep3_load16, /* Load16 */ -+ ep3_store16, /* Store16 */ -+ ep3_load32, /* Load32 */ -+ ep3_store32, /* Store32 */ -+ ep3_load64, /* Load64 */ -+ ep3_store64, /* Store64 */ -+}; -+ -+static int -+ep3_event (ELAN3_CTXT *ctxt, E3_uint32 cookie, int flag) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ EP3_COOKIE *cp = LookupCookie (&rail->CookieTable, cookie); -+ -+ if (cp == NULL) -+ { -+ printk ("ep3_event: cannot find event cookie for %x\n", cookie); -+ return (OP_HANDLED); -+ } -+ -+ if (cp->Operations->Event) -+ cp->Operations->Event(rail, cp->Arg); -+ -+ return (OP_HANDLED); -+} -+ -+/* Trap interface */ -+int -+ep3_dprocTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = rail->Device; -+ EP3_COOKIE *cp; -+ E3_FaultSave_BE *FaultArea; -+ E3_uint16 vp; -+ int validTrap; -+ int numFaults; -+ int i; -+ sdramaddr_t event; -+ E3_uint32 type; -+ sdramaddr_t dma; -+ E3_DMA_BE dmabe; -+ int status = EAGAIN; -+ -+ EPRINTF4 (DBG_EPTRAP, "ep3_dprocTrap: WakeupFnt=%x Cntx=%x SuspAddr=%x TrapType=%s\n", -+ trap->Status.s.WakeupFunction, trap->Status.s.Context, -+ trap->Status.s.SuspendAddr, MiToName (trap->Status.s.TrapType)); -+ EPRINTF4 (DBG_EPTRAP, " type %08x size %08x source %08x dest %08x\n", -+ trap->Desc.s.dma_type, trap->Desc.s.dma_size, trap->Desc.s.dma_source, trap->Desc.s.dma_dest); -+ EPRINTF2 (DBG_EPTRAP, " Dest event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_destEvent, trap->Desc.s.dma_destCookieVProc); -+ EPRINTF2 (DBG_EPTRAP, " Source event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_srcEvent, trap->Desc.s.dma_srcCookieVProc); -+ -+ ASSERT (trap->Status.s.Context & SYS_CONTEXT_BIT); -+ -+ switch (trap->Status.s.TrapType) -+ { -+ case MI_DmaPacketTimedOutOrPacketError: -+ if (trap->Desc.s.dma_direction == DMA_WRITE) -+ vp = trap->Desc.s.dma_destVProc; -+ else -+ vp = trap->Desc.s.dma_srcVProc; -+ -+ if (! trap->PacketInfo.s.PacketTimeout) -+ status = ETIMEDOUT; -+ else -+ { -+ status = EHOSTDOWN; -+ -+ /* XXXX: dma timedout - might want to "restart" tree ? */ -+ } -+ goto retry_dma; -+ -+ case MI_DmaFailCountError: -+ goto retry_dma; -+ -+ case MI_TimesliceDmaQueueOverflow: -+ IncrStat (rail, DprocDmaQueueOverflow); -+ -+ goto retry_dma; -+ -+ case MI_RemoteDmaCommand: -+ case MI_RunDmaCommand: -+ case MI_DequeueNonSysCntxDma: -+ case MI_DequeueSysCntxDma: -+ /* -+ * The DMA processor has trapped due to outstanding prefetches from the previous -+ * dma. The "current" dma has not been consumed, so we just ignore the trap -+ */ -+ return (OP_HANDLED); -+ -+ case MI_EventQueueOverflow: -+ IncrStat (rail, DprocEventQueueOverflow); -+ -+ if ((event = ep_elan2sdram (&rail->Generic, trap->Desc.s.dma_srcEvent)) != (sdramaddr_t) 0 && -+ ((type = elan3_sdram_readl (dev, event + offsetof(E3_Event,ev_Type))) & EV_TYPE_MASK_EVIRQ) == EV_TYPE_EVIRQ) -+ { -+ spin_unlock (&ctxt->Device->IntrLock); -+ ep3_event (ctxt, (type & ~(EV_TYPE_MASK_EVIRQ | EV_TYPE_MASK_BCOPY)), OP_LWP); -+ spin_lock (&ctxt->Device->IntrLock); -+ } -+ return (OP_HANDLED); -+ -+ case MI_DmaQueueOverflow: -+ IncrStat (rail, DprocDmaQueueOverflow); -+ -+ if ((event = ep_elan2sdram (&rail->Generic, trap->Desc.s.dma_srcEvent)) != (sdramaddr_t) 0 && -+ ((type = elan3_sdram_readl (dev, event + offsetof (E3_Event, ev_Type))) & EV_TYPE_MASK_DMA) == EV_TYPE_DMA && -+ (dma = ep_elan2sdram (&rail->Generic, (type & ~EV_TYPE_MASK2))) != (sdramaddr_t) 0) -+ { -+ elan3_sdram_copyq_from_sdram (dev, dma, &dmabe, sizeof (E3_DMA)); -+ -+ /* We only chain together DMA's of the same direction, so since -+ * we took a DmaQueueOverflow trap - this means that DMA which -+ * trapped was a WRITE dma - hence the one we chain to must also -+ * be a WRITE dma. -+ */ -+ ASSERT (dmabe.s.dma_direction == DMA_WRITE); -+ -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_srcEvent); -+ -+#ifdef DEBUG_ASSERT -+ { -+ E3_uint16 vp = dmabe.s.dma_destVProc; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ ASSERT (cp != NULL && (!EP_VP_ISDATA(vp) || (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE))); -+ } -+#endif -+ cp->Operations->DmaRetry (rail, cp->Arg, &dmabe, EAGAIN); -+ -+ return (OP_HANDLED); -+ } -+ -+ panic ("ep3_dprocTrap\n"); -+ return (OP_HANDLED); -+ -+ default: -+ break; -+ } -+ -+ /* If it's a dma which traps past the end of the source, then */ -+ /* just re-issue it */ -+ numFaults = validTrap = (trap->FaultSave.s.FSR.Status != 0); -+ for (i = 0, FaultArea = &trap->Data0; i < 4; i++, FaultArea++) -+ { -+ if (FaultArea->s.FSR.Status != 0) -+ { -+ numFaults++; -+ -+ /* XXXX: Rev B Elans can prefetch data past the end of the dma descriptor */ -+ /* if the fault relates to this, then just ignore it */ -+ if (FaultArea->s.FaultAddress >= (trap->Desc.s.dma_source+trap->Desc.s.dma_size)) -+ { -+ static int i; -+ if (i < 10 && i++ < 10) -+ printk ("ep3_dprocTrap: Rev B prefetch trap error %08x %08x\n", -+ FaultArea->s.FaultAddress, (trap->Desc.s.dma_source+trap->Desc.s.dma_size)); -+ continue; -+ } -+ -+ validTrap++; -+ } -+ } -+ -+ /* -+ * NOTE: for physical errors (uncorrectable ECC/PCI parity errors) the FSR will -+ * be zero - hence we will not see any faults - and none will be valid, -+ * so only ignore a Rev B prefetch trap if we've seen some faults. Otherwise -+ * we can reissue a DMA which has already sent it's remote event ! -+ */ -+ if (numFaults != 0 && validTrap == 0) -+ { -+ retry_dma: -+ if (trap->Desc.s.dma_direction == DMA_WRITE) -+ { -+ vp = trap->Desc.s.dma_destVProc; -+ cp = LookupEventCookie (rail, &rail->CookieTable, trap->Desc.s.dma_srcEvent); -+ } -+ else -+ { -+ ASSERT (EP3_CONTEXT_ISDATA(trap->Desc.s.dma_queueContext) || trap->Desc.s.dma_direction == DMA_READ_REQUEUE); -+ -+ vp = trap->Desc.s.dma_srcVProc; -+ cp = LookupEventCookie (rail, &rail->CookieTable, trap->Desc.s.dma_destEvent); -+ -+ /* for read dma's set the DMA_READ_REQUEUE bits as the dma_source has been -+ * modified by the elan to point at the dma in the rxd where it was issued -+ * from */ -+ trap->Desc.s.dma_direction = (trap->Desc.s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ } -+ -+#ifdef DEBUG_ASSERT -+ { -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE)); -+ } -+#endif -+ -+ if (cp != NULL) -+ cp->Operations->DmaRetry (rail, cp->Arg, &trap->Desc, status); -+ else -+ { -+ ASSERT (trap->Desc.s.dma_direction == DMA_WRITE && trap->Desc.s.dma_srcEvent == 0 && trap->Desc.s.dma_isRemote); -+ -+ QueueDmaForRetry (rail, &trap->Desc, EP_RETRY_ANONYMOUS); -+ } -+ -+ return (OP_HANDLED); -+ } -+ -+ printk ("ep3_dprocTrap: WakeupFnt=%x Cntx=%x SuspAddr=%x TrapType=%s\n", -+ trap->Status.s.WakeupFunction, trap->Status.s.Context, -+ trap->Status.s.SuspendAddr, MiToName (trap->Status.s.TrapType)); -+ printk (" FaultAddr=%x EventAddr=%x FSR=%x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, -+ trap->FaultSave.s.FSR.Status); -+ for (i = 0, FaultArea = &trap->Data0; i < 4; i++, FaultArea++) -+ printk (" %d FaultAddr=%x EventAddr=%x FSR=%x\n", i, -+ FaultArea->s.FaultAddress, FaultArea->s.EventAddress, FaultArea->s.FSR.Status); -+ -+ printk (" type %08x size %08x source %08x dest %08x\n", -+ trap->Desc.s.dma_type, trap->Desc.s.dma_size, trap->Desc.s.dma_source, trap->Desc.s.dma_dest); -+ printk (" Dest event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_destEvent, trap->Desc.s.dma_destCookieVProc); -+ printk (" Source event %08x cookie/proc %08x\n", -+ trap->Desc.s.dma_srcEvent, trap->Desc.s.dma_srcCookieVProc); -+ -+// panic ("ep3_dprocTrap"); -+ -+ return (OP_HANDLED); -+} -+ -+int -+ep3_tprocTrap (ELAN3_CTXT *ctxt, THREAD_TRAP *trap) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ -+ EPRINTF6 (DBG_EPTRAP, "ep3_tprocTrap: SP=%08x PC=%08x NPC=%08x DIRTY=%08x TRAP=%08x MI=%s\n", -+ trap->sp, trap->pc, trap->npc, trap->DirtyBits.Bits, trap->TrapBits.Bits, MiToName (trap->mi)); -+ EPRINTF4 (DBG_EPTRAP, " g0=%08x g1=%08x g2=%08x g3=%08x\n", -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)], trap->Registers[REG_GLOBALS+(1^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(2^WordEndianFlip)], trap->Registers[REG_GLOBALS+(3^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " g4=%08x g5=%08x g6=%08x g7=%08x\n", -+ trap->Registers[REG_GLOBALS+(4^WordEndianFlip)], trap->Registers[REG_GLOBALS+(5^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(6^WordEndianFlip)], trap->Registers[REG_GLOBALS+(7^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " o0=%08x o1=%08x o2=%08x o3=%08x\n", -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)], trap->Registers[REG_OUTS+(1^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(2^WordEndianFlip)], trap->Registers[REG_OUTS+(3^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " o4=%08x o5=%08x o6=%08x o7=%08x\n", -+ trap->Registers[REG_OUTS+(4^WordEndianFlip)], trap->Registers[REG_OUTS+(5^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)], trap->Registers[REG_OUTS+(7^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " l0=%08x l1=%08x l2=%08x l3=%08x\n", -+ trap->Registers[REG_LOCALS+(0^WordEndianFlip)], trap->Registers[REG_LOCALS+(1^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(2^WordEndianFlip)], trap->Registers[REG_LOCALS+(3^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " l4=%08x l5=%08x l6=%08x l7=%08x\n", -+ trap->Registers[REG_LOCALS+(4^WordEndianFlip)], trap->Registers[REG_LOCALS+(5^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(6^WordEndianFlip)], trap->Registers[REG_LOCALS+(7^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " i0=%08x i1=%08x i2=%08x i3=%08x\n", -+ trap->Registers[REG_INS+(0^WordEndianFlip)], trap->Registers[REG_INS+(1^WordEndianFlip)], -+ trap->Registers[REG_INS+(2^WordEndianFlip)], trap->Registers[REG_INS+(3^WordEndianFlip)]); -+ EPRINTF4 (DBG_EPTRAP, " i4=%08x i5=%08x i6=%08x i7=%08x\n", -+ trap->Registers[REG_INS+(4^WordEndianFlip)], trap->Registers[REG_INS+(5^WordEndianFlip)], -+ trap->Registers[REG_INS+(6^WordEndianFlip)], trap->Registers[REG_INS+(7^WordEndianFlip)]); -+ -+ ASSERT (trap->Status.s.Context & SYS_CONTEXT_BIT); -+ -+ switch (trap->mi) -+ { -+ case MI_UnimplementedError: -+ if (trap->TrapBits.s.ForcedTProcTrap) -+ { -+ ASSERT (trap->TrapBits.s.OutputWasOpen == 0); -+ -+ EPRINTF0 (DBG_EPTRAP, "ep3_tprocTrap: ForcedTProcTrap\n"); -+ -+ IssueRunThread (rail, SaveThreadToStack (ctxt, trap, FALSE)); -+ return (OP_HANDLED); -+ } -+ -+ if (trap->TrapBits.s.ThreadTimeout) -+ { -+ EPRINTF0 (DBG_EPTRAP, "ep3_tprocTrap: ThreadTimeout\n"); -+ -+ if (trap->Registers[REG_GLOBALS + (1^WordEndianFlip)] == 0) -+ RollThreadToClose (ctxt, trap, trap->TrapBits.s.PacketAckValue); -+ else -+ { -+ CompleteEnvelope (rail, trap->Registers[REG_GLOBALS + (1^WordEndianFlip)], trap->TrapBits.s.PacketAckValue); -+ -+ RollThreadToClose (ctxt, trap, EP3_PAckStolen); -+ } -+ -+ IssueRunThread (rail, SaveThreadToStack (ctxt, trap, FALSE)); -+ return (OP_HANDLED); -+ } -+ -+ if (trap->TrapBits.s.Unimplemented) -+ { -+ E3_uint32 instr = ELAN3_OP_LOAD32 (ctxt, trap->pc & PC_MASK); -+ -+ PRINTF1 (ctxt, DBG_EPTRAP, "ep3_tprocTrap: unimplemented instruction %08x\n", instr); -+ -+ if ((instr & OPCODE_MASK) == OPCODE_Ticc && -+ (instr & OPCODE_IMM) == OPCODE_IMM && -+ (Ticc_COND(instr) == Ticc_TA)) -+ { -+ switch (INSTR_IMM(instr)) -+ { -+ case EP3_UNIMP_TRAP_NO_DESCS: -+ StallThreadForNoDescs (rail, trap->Registers[REG_GLOBALS + (1^WordEndianFlip)], -+ SaveThreadToStack (ctxt, trap, TRUE)); -+ return (OP_HANDLED); -+ -+ case EP3_UNIMP_TRAP_PACKET_NACKED: -+ CompleteEnvelope (rail, trap->Registers[REG_GLOBALS + (1^WordEndianFlip)], E3_PAckDiscard); -+ -+ IssueRunThread (rail, SaveThreadToStack (ctxt, trap, TRUE)); -+ return (OP_HANDLED); -+ -+ case EP3_UNIMP_THREAD_HALTED: -+ StallThreadForHalted (rail, trap->Registers[REG_GLOBALS + (1^WordEndianFlip)], -+ SaveThreadToStack (ctxt, trap, TRUE)); -+ return (OP_HANDLED); -+ -+ default: -+ break; -+ -+ } -+ } -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ /* All other traps should not happen for kernel comms */ -+ printk ("ep3_tprocTrap: SP=%08x PC=%08x NPC=%08x DIRTY=%08x TRAP=%08x MI=%s\n", -+ trap->sp, trap->pc, trap->npc, trap->DirtyBits.Bits, -+ trap->TrapBits.Bits, MiToName (trap->mi)); -+ printk (" FaultSave : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, trap->FaultSave.s.FSR.Status); -+ printk (" DataFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->DataFaultSave.s.FaultAddress, trap->DataFaultSave.s.EventAddress, trap->DataFaultSave.s.FSR.Status); -+ printk (" InstFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->InstFaultSave.s.FaultAddress, trap->InstFaultSave.s.EventAddress, trap->InstFaultSave.s.FSR.Status); -+ printk (" OpenFault : FaultAddress %08x EventAddress %08x FSR %08x\n", -+ trap->OpenFaultSave.s.FaultAddress, trap->OpenFaultSave.s.EventAddress, trap->OpenFaultSave.s.FSR.Status); -+ -+ if (trap->DirtyBits.s.GlobalsDirty) -+ { -+ printk (" g0=%08x g1=%08x g2=%08x g3=%08x\n", -+ trap->Registers[REG_GLOBALS+(0^WordEndianFlip)], trap->Registers[REG_GLOBALS+(1^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(2^WordEndianFlip)], trap->Registers[REG_GLOBALS+(3^WordEndianFlip)]); -+ printk (" g4=%08x g5=%08x g6=%08x g7=%08x\n", -+ trap->Registers[REG_GLOBALS+(4^WordEndianFlip)], trap->Registers[REG_GLOBALS+(5^WordEndianFlip)], -+ trap->Registers[REG_GLOBALS+(6^WordEndianFlip)], trap->Registers[REG_GLOBALS+(7^WordEndianFlip)]); -+ } -+ if (trap->DirtyBits.s.OutsDirty) -+ { -+ printk (" o0=%08x o1=%08x o2=%08x o3=%08x\n", -+ trap->Registers[REG_OUTS+(0^WordEndianFlip)], trap->Registers[REG_OUTS+(1^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(2^WordEndianFlip)], trap->Registers[REG_OUTS+(3^WordEndianFlip)]); -+ printk (" o4=%08x o5=%08x o6=%08x o7=%08x\n", -+ trap->Registers[REG_OUTS+(4^WordEndianFlip)], trap->Registers[REG_OUTS+(5^WordEndianFlip)], -+ trap->Registers[REG_OUTS+(6^WordEndianFlip)], trap->Registers[REG_OUTS+(7^WordEndianFlip)]); -+ } -+ if (trap->DirtyBits.s.LocalsDirty) -+ { -+ printk (" l0=%08x l1=%08x l2=%08x l3=%08x\n", -+ trap->Registers[REG_LOCALS+(0^WordEndianFlip)], trap->Registers[REG_LOCALS+(1^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(2^WordEndianFlip)], trap->Registers[REG_LOCALS+(3^WordEndianFlip)]); -+ printk (" l4=%08x l5=%08x l6=%08x l7=%08x\n", -+ trap->Registers[REG_LOCALS+(4^WordEndianFlip)], trap->Registers[REG_LOCALS+(5^WordEndianFlip)], -+ trap->Registers[REG_LOCALS+(6^WordEndianFlip)], trap->Registers[REG_LOCALS+(7^WordEndianFlip)]); -+ } -+ if (trap->DirtyBits.s.InsDirty) -+ { -+ printk (" i0=%08x i1=%08x i2=%08x i3=%08x\n", -+ trap->Registers[REG_INS+(0^WordEndianFlip)], trap->Registers[REG_INS+(1^WordEndianFlip)], -+ trap->Registers[REG_INS+(2^WordEndianFlip)], trap->Registers[REG_INS+(3^WordEndianFlip)]); -+ printk (" i4=%08x i5=%08x i6=%08x i7=%08x\n", -+ trap->Registers[REG_INS+(4^WordEndianFlip)], trap->Registers[REG_INS+(5^WordEndianFlip)], -+ trap->Registers[REG_INS+(6^WordEndianFlip)], trap->Registers[REG_INS+(7^WordEndianFlip)]); -+ } -+ -+// panic ("ep3_tprocTrap"); -+ -+ return (OP_HANDLED); -+} -+ -+int -+ep3_iprocTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, int channel) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ EP3_COOKIE *cp; -+ sdramaddr_t event; -+ E3_uint32 type; -+ sdramaddr_t dma; -+ E3_DMA_BE dmabe; -+ -+ ASSERT (trap->Transactions[0].s.TrTypeCntx.s.Context & SYS_CONTEXT_BIT); -+ -+ /* -+ * first process the trap to determine the cause -+ */ -+ InspectIProcTrap (ctxt, trap); -+ -+ if (! trap->AckSent && trap->LockQueuePointer) /* Must be a network error in a queueing DMA */ -+ { /* packet - unlock the queue */ -+ IncrStat (rail, QueueingPacketTrap); -+ -+ SimulateUnlockQueue (ctxt, trap->LockQueuePointer, FALSE); -+ return (OP_HANDLED); -+ } -+ -+ if (trap->AckSent && trap->BadTransaction) -+ { -+ spin_unlock (&dev->IntrLock); -+ -+ /* NOTE - no network error fixup is necessary for system context -+ * messages since they are idempotent and are single packet -+ * dmas -+ */ -+ if (EP3_CONTEXT_ISDATA (trap->Transactions[0].s.TrTypeCntx.s.Context)) -+ { -+ int nodeId = EP3_CONTEXT_TO_NODE(trap->Transactions[0].s.TrTypeCntx.s.Context); -+ -+ if (trap->DmaIdentifyTransaction) -+ ep_queue_network_error (&rail->Generic, nodeId, EP_NODE_NETERR_ATOMIC_PACKET, channel, trap->DmaIdentifyTransaction->s.TrAddr); -+ else if (trap->ThreadIdentifyTransaction) -+ ep_queue_network_error (&rail->Generic, nodeId, EP_NODE_NETERR_ATOMIC_PACKET, channel, trap->ThreadIdentifyTransaction->s.TrAddr); -+ else -+ ep_queue_network_error (&rail->Generic, nodeId, EP_NODE_NETERR_DMA_PACKET, channel, 0); -+ } -+ -+ spin_lock (&dev->IntrLock); -+ return (OP_HANDLED); -+ } -+ -+ if (trap->AckSent) -+ { -+ if (trap->TrappedTransaction == NULL) -+ return (OP_HANDLED); -+ -+ while (! trap->TrappedTransaction->s.TrTypeCntx.s.LastTrappedTrans) -+ { -+ E3_IprocTrapHeader_BE *hdrp = trap->TrappedTransaction; -+ E3_IprocTrapData_BE *datap = trap->TrappedDataBuffer; -+ -+ ASSERT (hdrp->s.TrTypeCntx.s.StatusRegValid != 0); -+ -+ if ((hdrp->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) != 0) -+ { -+ printk ("ep3_iprocTrap: WRITEBLOCK : Addr %x\n", hdrp->s.TrAddr); -+// panic ("ep3_iprocTrap\n"); -+ } -+ else -+ { -+ switch (hdrp->s.TrTypeCntx.s.Type & TR_OPCODE_TYPE_MASK) -+ { -+ case TR_SETEVENT & TR_OPCODE_TYPE_MASK: -+ switch (GET_STATUS_TRAPTYPE (hdrp->s.IProcTrapStatus)) -+ { -+ case MI_DmaQueueOverflow: -+ IncrStat (rail, IprocDmaQueueOverflow); -+ -+ if ((event = ep_elan2sdram (&rail->Generic, hdrp->s.TrAddr)) != (sdramaddr_t) 0 && -+ ((type = elan3_sdram_readl (dev, event + offsetof (E3_Event, ev_Type))) & EV_TYPE_MASK_DMA) == EV_TYPE_DMA && -+ (dma = ep_elan2sdram (&rail->Generic, (type & ~EV_TYPE_MASK2))) != (sdramaddr_t) 0) -+ { -+ elan3_sdram_copyq_from_sdram (dev, dma, &dmabe, sizeof (E3_DMA)); -+ -+ if (dmabe.s.dma_direction == DMA_WRITE) -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_srcEvent); -+ else -+ { -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_destEvent); -+ -+ /* we MUST convert this into a DMA_READ_REQUEUE dma as if we don't the -+ * DMA descriptor will be read from the EP3_RETRY_DMA rather than the -+ * original DMA - this can then get reused and an incorrect DMA -+ * descriptor sent -+ * eventp->ev_Type contains the dma address with type in the lower bits -+ */ -+ -+ dmabe.s.dma_source = (type & ~EV_TYPE_MASK2); -+ dmabe.s.dma_direction = (dmabe.s.dma_direction & ~DMA_READ) | DMA_READ_REQUEUE; -+ } -+ -+#ifdef DEBUG_ASSERT -+ { -+ E3_uint16 vp = (dmabe.s.dma_direction == DMA_WRITE ? dmabe.s.dma_destVProc : dmabe.s.dma_srcVProc); -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE)); -+ } -+#endif -+ -+ if (cp != NULL) -+ cp->Operations->DmaRetry (rail, cp->Arg, &dmabe, EAGAIN); -+ else -+ { -+ ASSERT (dmabe.s.dma_direction == DMA_WRITE && dmabe.s.dma_srcEvent == 0 && dmabe.s.dma_isRemote); -+ -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_ANONYMOUS); -+ } -+ break; -+ } -+ -+ printk ("ep3_iprocTrap: SETEVENT : %x - cannot find dma to restart\n", hdrp->s.TrAddr); -+// panic ("ep3_iprocTrap\n"); -+ break; -+ -+ case MI_EventQueueOverflow: -+ { -+ sdramaddr_t event; -+ E3_uint32 type; -+ -+ IncrStat (rail, IprocEventQueueOverflow); -+ -+ if ((event = ep_elan2sdram (&rail->Generic, hdrp->s.TrAddr)) != (sdramaddr_t) 0 && -+ ((type = elan3_sdram_readl (dev, event + offsetof (E3_Event, ev_Type))) & EV_TYPE_MASK_EVIRQ) == EV_TYPE_EVIRQ) -+ { -+ spin_unlock (&dev->IntrLock); -+ ep3_event (ctxt, (type & ~(EV_TYPE_MASK_EVIRQ|EV_TYPE_MASK_BCOPY)), OP_LWP); -+ spin_lock (&dev->IntrLock); -+ -+ break; -+ } -+ -+ printk ("ep3_iprocTrap: SETEVENT : %x - cannot find event\n", hdrp->s.TrAddr); -+// panic ("ep3_iprocTrap\n"); -+ break; -+ } -+ -+ default: -+ printk ("ep3_iprocTrap: SETEVENT : %x MI=%x\n", hdrp->s.TrAddr, GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus)); -+// panic ("ep3_iprocTrap\n"); -+ break; -+ } -+ break; -+ -+ case TR_SENDDISCARD & TR_OPCODE_TYPE_MASK: -+ /* Just ignore send-discard transactions */ -+ break; -+ -+ case TR_REMOTEDMA & TR_OPCODE_TYPE_MASK: -+ { -+ E3_DMA_BE *dmap = (E3_DMA_BE *) datap; -+ -+ if (GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus) != MI_DmaQueueOverflow) -+ { -+ printk ("ep3_iprocTrap: MI=%x\n", GET_STATUS_TRAPTYPE(hdrp->s.IProcTrapStatus)); -+ break; -+ } -+ -+ IncrStat (rail, IprocDmaQueueOverflow); -+ -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmap->s.dma_srcEvent); -+ -+ /* modify the dma type since it will still be a "read" dma */ -+ dmap->s.dma_type = (dmap->s.dma_type & ~DMA_TYPE_READ) | DMA_TYPE_ISREMOTE; -+ -+#ifdef DEBUG_ASSERT -+ { -+ E3_uint16 vp = dmap->s.dma_destVProc; -+ EP_NODE_RAIL *nodeRail = &rail->Generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE)); -+ } -+#endif -+ if (cp != NULL) -+ cp->Operations->DmaRetry (rail, cp->Arg, dmap, EAGAIN); -+ else -+ { -+ ASSERT (dmap->s.dma_direction == DMA_WRITE && dmap->s.dma_srcEvent == 0 && dmap->s.dma_isRemote); -+ -+ QueueDmaForRetry (rail, dmap, EP_RETRY_ANONYMOUS); -+ } -+ break; -+ } -+ default: -+ printk ("ep3_iprocTrap: %s\n", IProcTrapString (hdrp, datap)); -+ break; -+ } -+ } -+ -+ /* -+ * We've successfully processed this transaction, so move onto the -+ * next one. -+ */ -+ trap->TrappedTransaction++; -+ trap->TrappedDataBuffer++; -+ } -+ -+ return (OP_HANDLED); -+ } -+ -+ /* Workaround WRITEBLOCK transaction executed when LOCKQUEUE transaction missed */ -+ if ((trap->TrappedTransaction->s.TrTypeCntx.s.Type & TR_WRITEBLOCK_BIT) && /* a DMA packet */ -+ trap->LockQueuePointer == 0 && trap->UnlockQueuePointer && /* a queueing DMA */ -+ trap->TrappedTransaction->s.TrAddr == trap->FaultSave.s.FaultAddress) /* and missed lockqueue */ -+ { -+ printk ("ep3_iprocTrap: missed lockqueue transaction for queue %x\n", trap->UnlockQueuePointer); -+ return (OP_HANDLED); -+ } -+ -+ if (trap->FaultSave.s.FaultContext != 0) -+ printk ("ep3_iprocTrap: pagefault at %08x in context %x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.FaultContext); -+ -+// panic ("ep3_iprocTrap: unexpected inputter trap\n"); -+ -+ return (OP_HANDLED); -+} -+ -+/* -+ * Command processor trap -+ * kernel comms should only be able to generate -+ * queue overflow traps -+ */ -+int -+ep3_cprocTrap (ELAN3_CTXT *ctxt, COMMAND_TRAP *trap) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ int ctxnum = (trap->TrapBuf.r.Breg >> 16) & MAX_ROOT_CONTEXT_MASK; -+ ELAN3_DEV *dev = rail->Device; -+ EP3_DMA_RING *ring; -+ EP3_COOKIE *cp; -+ E3_DMA_BE dmabe; -+ int vp, slot; -+ unsigned long flags; -+ -+ switch (trap->Status.s.TrapType) -+ { -+ case MI_DmaQueueOverflow: -+ IncrStat (rail, CprocDmaQueueOverflow); -+ -+ /* Use the context number that the setevent was issued in, -+ * to find the appropriate dma ring, then since they are guaranteed -+ * to be issued in order, we just search backwards till we find the -+ * last one which has completed its word copy - this must be the -+ * one which had caused the DmaQueueOverflow trap ! */ -+ -+ ASSERT (ctxnum >= ELAN3_DMARING_BASE_CONTEXT_NUM && ctxnum < (ELAN3_DMARING_BASE_CONTEXT_NUM+EP3_NUM_RINGS)); -+ -+ spin_lock_irqsave (&dev->CProcLock, flags); -+ -+ ring = &rail->DmaRings[ctxnum - ELAN3_DMARING_BASE_CONTEXT_NUM]; -+ slot = DMA_RING_PREV_POS(ring, ring->Position); -+ -+ while (ring->pDoneBlk[slot] == EP3_EVENT_ACTIVE) -+ slot = DMA_RING_PREV_POS(ring, slot); -+ -+ elan3_sdram_copyq_from_sdram (rail->Device , DMA_RING_DMA(ring,slot), &dmabe, sizeof (E3_DMA)); -+ -+#if defined(DEBUG_ASSERT) -+ while (slot != DMA_RING_PREV_POS(ring, ring->Position)) -+ { -+ ASSERT (ring->pDoneBlk[slot] != EP3_EVENT_ACTIVE); -+ -+ slot = DMA_RING_PREV_POS(ring, slot); -+ } -+#endif -+ spin_unlock_irqrestore (&dev->CProcLock, flags); -+ -+ if (dmabe.s.dma_direction == DMA_WRITE) -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_srcEvent); -+ else -+ { -+ ASSERT (dmabe.s.dma_direction = DMA_READ_REQUEUE); -+ -+ cp = LookupEventCookie (rail, &rail->CookieTable, dmabe.s.dma_destEvent); -+ } -+ -+#if defined(DEBUG_ASSERT) -+ if (dmabe.s.dma_direction == DMA_WRITE) -+ vp = dmabe.s.dma_destVProc; -+ else -+ vp = dmabe.s.dma_srcVProc; -+ -+ ASSERT (!EP_VP_ISDATA(vp) || (rail->Generic.Nodes[EP_VP_TO_NODE(vp)].State >= EP_NODE_CONNECTED && -+ rail->Generic.Nodes[EP_VP_TO_NODE(vp)].State <= EP_NODE_LOCAL_PASSIVATE)); -+#endif -+ -+ if (cp != NULL) -+ cp->Operations->DmaRetry (rail, cp->Arg, &dmabe, EAGAIN); -+ else -+ { -+ ASSERT (dmabe.s.dma_direction == DMA_WRITE && dmabe.s.dma_srcEvent == 0 && dmabe.s.dma_isRemote); -+ -+ QueueDmaForRetry (rail, &dmabe, EP_RETRY_ANONYMOUS); -+ } -+ -+ return (OP_HANDLED); -+ -+ case MI_EventQueueOverflow: -+ ASSERT (ctxnum == ELAN3_MRF_CONTEXT_NUM); -+ -+ IncrStat (rail, CprocEventQueueOverflow); -+ -+ rail->CommandPortEventTrap = TRUE; -+ return (OP_HANDLED); -+ -+#if defined(PER_CPU_TIMEOUT) -+ case MI_SetEventReadWait: -+ if (ctxnum == ELAN3_MRF_CONTEXT_NUM && trap->FaultSave.s.EventAddress == EP_PACEMAKER_EVENTADDR) -+ { -+ HeartbeatPacemaker (rail); -+ return (OP_HANDLED); -+ } -+#endif -+ -+ default: -+ printk ("ep3_cprocTrap : Context=%x Status=%x TrapType=%x\n", ctxnum, trap->Status.Status, trap->Status.s.TrapType); -+ printk (" FaultAddr=%x EventAddr=%x FSR=%x\n", -+ trap->FaultSave.s.FaultAddress, trap->FaultSave.s.EventAddress, -+ trap->FaultSave.s.FSR.Status); -+ break; -+ } -+ -+// panic ("ep3_cprocTrap"); -+ -+ return (OP_HANDLED); -+} -+ -+static int -+ep3_cprocReissue (ELAN3_CTXT *ctxt, CProcTrapBuf_BE *tbuf) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ unsigned cmdoff = (tbuf->s.ContextType >> 5) & 0xFF; -+ int ctxnum = (tbuf->s.ContextType >> 16) & MAX_ROOT_CONTEXT_MASK; -+ -+ if (ctxnum >= ELAN3_DMARING_BASE_CONTEXT_NUM && ctxnum < (ELAN3_DMARING_BASE_CONTEXT_NUM+EP3_NUM_RINGS)) -+ { -+ EP3_DMA_RING *ring = &rail->DmaRings[ctxnum - ELAN3_DMARING_BASE_CONTEXT_NUM]; -+ -+ ASSERT ((cmdoff << 2) == offsetof (E3_CommandPort, SetEvent)); /* can only be setevent commands! */ -+ ASSERT (tbuf->s.Addr >= DMA_RING_EVENT_ELAN(ring,0) && tbuf->s.Addr < DMA_RING_EVENT_ELAN(ring, ring->Entries)); -+ -+ writel (tbuf->s.Addr, ring->CommandPort + (cmdoff << 2)); -+ } -+ else -+ { -+ ASSERT (ctxnum == ELAN3_MRF_CONTEXT_NUM); -+ -+ writel (tbuf->s.Addr, ctxt->CommandPort + (cmdoff << 2)); -+ } -+ -+ return (OP_HANDLED); -+} -+ -+static E3_uint8 -+ep3_load8 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint8 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ return (elan3_sdram_readb (dev, offset)); -+ if ((ptr = ep_elan2main (&rail->Generic, addr)) != NULL) -+ return (*ptr); -+ -+ printk ("ep3_load8: %08x\n", addr); -+ return (0); -+} -+ -+static void -+ep3_store8 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint8 val) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint8 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ elan3_sdram_writeb (dev, offset, val); -+ else if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ *ptr = val; -+ else -+ printk ("ep3_store8 %08x\n", addr); -+} -+ -+static E3_uint16 -+ep3_load16 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint16 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ return (elan3_sdram_readw (dev, offset)); -+ if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ return (*ptr); -+ -+ printk ("ep3_load16 %08x\n", addr); -+ return (0); -+} -+ -+static void -+ep3_store16 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint16 val) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint16 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ elan3_sdram_writew (dev, offset, val); -+ else if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ *ptr = val; -+ else -+ printk ("ep3_store16 %08x\n", addr); -+} -+ -+static E3_uint32 -+ep3_load32 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint32 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ return (elan3_sdram_readl(dev, offset)); -+ if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ return (*ptr); -+ -+ printk ("ep3_load32 %08x\n", addr); -+ return (0); -+} -+ -+static void -+ep3_store32 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint32 val) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint32 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ elan3_sdram_writel (dev, offset, val); -+ else if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ *ptr = val; -+ else -+ printk ("ep3_store32 %08x\n", addr); -+} -+ -+static E3_uint64 -+ep3_load64 (ELAN3_CTXT *ctxt, E3_Addr addr) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint64 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ return (elan3_sdram_readq (dev, offset)); -+ if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ return (*ptr); -+ -+ printk ("ep3_load64 %08x\n", addr); -+ return (0); -+} -+ -+static void -+ep3_store64 (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint64 val) -+{ -+ EP3_RAIL *rail = (EP3_RAIL *) ctxt->Private; -+ ELAN3_DEV *dev = ctxt->Device; -+ sdramaddr_t offset; -+ E3_uint64 *ptr; -+ -+ if ((offset = ep_elan2sdram (&rail->Generic, addr)) != 0) -+ elan3_sdram_writeq (dev, offset, val); -+ else if ((ptr = ep_elan2main (&rail->Generic, addr)) != 0) -+ *ptr = val; -+ else -+ printk ("ep3_store64 %08x\n", addr); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/support_elan4.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/support_elan4.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/support_elan4.c 2005-06-01 23:12:54.689425424 -0400 -@@ -0,0 +1,1184 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: support_elan4.c,v 1.18.2.3 2004/11/18 12:05:00 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/support_elan4.c,v $*/ -+ -+#include -+#include -+ -+#include -+ -+#include "kcomm_vp.h" -+#include "kcomm_elan4.h" -+#include "debug.h" -+ -+#include -+#include -+ -+void -+ep4_register_intcookie (EP4_RAIL *rail, EP4_INTCOOKIE *cp, E4_uint64 cookie, void (*callback)(EP4_RAIL *r, void *arg), void *arg) -+{ -+ unsigned long flags; -+ -+ cp->int_val = cookie; -+ cp->int_callback = callback; -+ cp->int_arg = arg; -+ -+ spin_lock_irqsave (&rail->r_intcookie_lock, flags); -+ list_add_tail (&cp->int_link, &rail->r_intcookie_hash[EP4_INTCOOKIE_HASH(cookie)]); -+ spin_unlock_irqrestore (&rail->r_intcookie_lock, flags); -+} -+ -+void -+ep4_deregister_intcookie (EP4_RAIL *rail, EP4_INTCOOKIE *cp) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_intcookie_lock, flags); -+ list_del (&cp->int_link); -+ spin_unlock_irqrestore (&rail->r_intcookie_lock, flags); -+} -+ -+ -+EP4_INTCOOKIE * -+ep4_lookup_intcookie (EP4_RAIL *rail, E4_uint64 cookie) -+{ -+ struct list_head *el; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_intcookie_lock, flags); -+ list_for_each (el, &rail->r_intcookie_hash[EP4_INTCOOKIE_HASH(cookie)]) { -+ EP4_INTCOOKIE *cp = list_entry (el, EP4_INTCOOKIE, int_link); -+ -+ if (cp->int_val == cookie) -+ { -+ spin_unlock_irqrestore (&rail->r_intcookie_lock, flags); -+ return cp; -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_intcookie_lock, flags); -+ return NULL; -+} -+ -+E4_uint64 -+ep4_neterr_cookie (EP4_RAIL *rail, unsigned int node) -+{ -+ E4_uint64 cookie; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_cookie_lock, flags); -+ cookie = rail->r_cookies[node]; -+ -+ rail->r_cookies[node] += EP4_COOKIE_INC; -+ -+ spin_unlock_irqrestore (&rail->r_cookie_lock, flags); -+ -+ return cookie; -+} -+ -+void -+ep4_eproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status) -+{ -+ EP4_RAIL *rail = EP4_CTXT_TO_RAIL (ctxt); -+ ELAN4_EPROC_TRAP trap; -+ -+ elan4_extract_eproc_trap (ctxt->ctxt_dev, status, &trap, 0); -+ -+ if (epdebug & DBG_EPTRAP) -+ elan4_display_eproc_trap (DBG_BUFFER, 0, "ep4_eproc_trap", &trap); -+ -+ switch (EPROC_TrapType (status)) -+ { -+ case EventProcNoFault: -+ EPRINTF1 (DBG_EPTRAP, "%s: EventProcNoFault\n", rail->r_generic.Name); -+ return; -+ -+ default: -+ printk ("%s: unhandled eproc trap %d\n", rail->r_generic.Name, EPROC_TrapType (status)); -+ elan4_display_eproc_trap (DBG_CONSOLE, 0, "ep4_eproc_trap", &trap); -+ } -+} -+ -+void -+ep4_cproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned cqnum) -+{ -+ EP4_RAIL *rail = EP4_CTXT_TO_RAIL (ctxt); -+ ELAN4_CPROC_TRAP trap; -+ struct list_head *el; -+ register int i; -+ -+ elan4_extract_cproc_trap (ctxt->ctxt_dev, status, &trap, cqnum); -+ -+ if (epdebug & DBG_EPTRAP) -+ elan4_display_cproc_trap (DBG_BUFFER, 0, "ep4_cproc_trap", &trap); -+ -+ switch (CPROC_TrapType (status)) -+ { -+ case CommandProcInterruptQueueOverflow: -+ /* -+ * Try and handle a bunch of elan main interrupts -+ */ -+ for (i = 0; i r_ecq_list[i]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ if (elan4_cq2num (ecq->ecq_cq) == cqnum) -+ { -+ printk ("%s: defer command queue %d after trap %x\n", -+ rail->r_generic.Name, cqnum, CPROC_TrapType (status)); -+ -+ elan4_queue_mainintop (ctxt->ctxt_dev, &ecq->ecq_intop); -+ return; -+ } -+ } -+ } -+ break; -+ -+ case CommandProcDmaQueueOverflow: -+ case CommandProcThreadQueueOverflow: -+ for (i = 0; i r_ecq_list[i]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ if (elan4_cq2num (ecq->ecq_cq) == cqnum) -+ { -+ printk ("%s: restart command queue %d after trap %x\n", -+ rail->r_generic.Name, cqnum, CPROC_TrapType (status)); -+ -+ elan4_restartcq (ctxt->ctxt_dev, ecq->ecq_cq); -+ return; -+ } -+ } -+ } -+ break; -+ } -+ -+ printk ("%s: unhandled cproc trap %d for cqnum %d\n", rail->r_generic.Name, CPROC_TrapType (status), cqnum); -+ elan4_display_cproc_trap (DBG_CONSOLE, 0, "ep4_cproc_trap", &trap); -+} -+ -+void -+ep4_dproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit) -+{ -+ EP4_RAIL *rail = EP4_CTXT_TO_RAIL (ctxt); -+ ELAN4_DPROC_TRAP trap; -+ -+ elan4_extract_dproc_trap (ctxt->ctxt_dev, status, &trap, unit); -+ -+ if (epdebug & DBG_EPTRAP) -+ elan4_display_dproc_trap (DBG_BUFFER, 0, "ep4_dproc_trap", &trap); -+ -+ if (! DPROC_PrefetcherFault (trap.tr_status)) -+ { -+ switch (DPROC_TrapType (trap.tr_status)) -+ { -+ case DmaProcFailCountError: -+ goto retry_this_dma; -+ -+ case DmaProcPacketAckError: -+ goto retry_this_dma; -+ -+ case DmaProcQueueOverflow: -+ goto retry_this_dma; -+ } -+ } -+ -+ printk ("%s: unhandled dproc trap\n", rail->r_generic.Name); -+ elan4_display_dproc_trap (DBG_CONSOLE, 0, "ep4_dproc_trap", &trap); -+ return; -+ -+ retry_this_dma: -+ /*XXXX implement backoff .... */ -+ -+ ep4_queue_dma_retry (rail, &trap.tr_desc, EP_RETRY_LOW_PRI); -+} -+ -+void -+ep4_tproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status) -+{ -+ EP4_RAIL *rail = EP4_CTXT_TO_RAIL (ctxt); -+ ELAN4_TPROC_TRAP *trap = &rail->r_tproc_trap; -+ -+ elan4_extract_tproc_trap (ctxt->ctxt_dev, status, trap); -+ -+ if (epdebug & DBG_EPTRAP) -+ elan4_display_tproc_trap (DBG_BUFFER, 0, "ep4_tproc_trap", trap); -+ -+ printk ("%s: unhandled tproc trap\n", rail->r_generic.Name); -+ elan4_display_tproc_trap (DBG_CONSOLE, 0, "ep4_tproc_trap", trap); -+} -+ -+void -+ep4_iproc_trap (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit) -+{ -+ EP4_RAIL *rail = EP4_CTXT_TO_RAIL (ctxt); -+ ELAN4_IPROC_TRAP *trap = &rail->r_iproc_trap; -+ -+ elan4_extract_iproc_trap (ctxt->ctxt_dev, status, trap, unit); -+ -+ if (epdebug & DBG_EPTRAP) -+ elan4_display_iproc_trap (DBG_BUFFER, 0, "ep4_iproc_trap", trap); -+ -+ elan4_inspect_iproc_trap (trap); -+ -+ switch (IPROC_TrapValue (trap->tr_transactions[trap->tr_trappedTrans].IProcStatusCntxAndTrType)) -+ { -+ case InputDmaQueueOverflow: -+ ep4_queue_dma_retry (rail, (E4_DMA *) &trap->tr_dataBuffers[trap->tr_trappedTrans], EP_RETRY_LOW_PRI); -+ return; -+ -+ case InputEventEngineTrapped: -+ { -+ E4_IprocTrapHeader *hdrp = &trap->tr_transactions[trap->tr_trappedTrans]; -+ sdramaddr_t inputq; -+ E4_Addr event; -+ -+ /* XXXX: flow control on the command queue which we issue to is -+ * rather difficult, we don't want to have space for an event -+ * for each possible context, nor the mechanism to hold the -+ * context filter up until the event has been executed. Given -+ * that the event engine will be restarted by this same interrupt -+ * and we're using high priority command queues, then we just use -+ * a single small command queue for this. -+ */ -+ switch (IPROC_TransactionType(hdrp->IProcStatusCntxAndTrType) & TR_OPCODE_MASK) -+ { -+ case TR_SETEVENT & TR_OPCODE_MASK: -+ if (hdrp->TrAddr != 0) -+ ep4_set_event_cmd (rail->r_event_ecq, hdrp->TrAddr); -+ return; -+ -+ case TR_INPUT_Q_COMMIT & TR_OPCODE_MASK: -+ if ((inputq = ep_elan2sdram (&rail->r_generic, hdrp->TrAddr)) == 0) -+ printk ("%s: TR_INPUT_Q_COMMIT at %llx is not sdram\n", rail->r_generic.Name, hdrp->TrAddr); -+ else -+ { -+ if ((event = elan4_sdram_readq (rail->r_ctxt.ctxt_dev, inputq + offsetof (E4_InputQueue, q_event))) != 0) -+ ep4_set_event_cmd (rail->r_event_ecq, event); -+ return; -+ } -+ } -+ break; -+ } -+ -+ case InputEopErrorOnWaitForEop: -+ case InputEopErrorTrap: -+ case InputCrcErrorAfterPAckOk: -+ if (! (trap->tr_flags & TR_FLAG_ACK_SENT) || (trap->tr_flags & TR_FLAG_EOP_BAD)) -+ return; -+ -+ if (EP4_CONTEXT_ISDATA (IPROC_NetworkContext (status))) -+ { -+ unsigned int nodeId = EP4_CONTEXT_TO_NODE (IPROC_NetworkContext (status)); -+ -+ if ((trap->tr_flags & (TR_FLAG_DMA_PACKET | TR_FLAG_BAD_TRANS)) || -+ ((trap->tr_flags & TR_FLAG_EOP_ERROR) && (trap->tr_identifyTrans == TR_TRANS_INVALID))) -+ { -+ printk ("%s: network error on dma packet from node %d\n", rail->r_generic.Name, nodeId); -+ -+ ep_queue_network_error (&rail->r_generic, EP4_CONTEXT_TO_NODE(IPROC_NetworkContext (status)), EP_NODE_NETERR_DMA_PACKET, unit & 1, 0); -+ return; -+ } -+ -+ if (trap->tr_flags & TR_FLAG_EOP_ERROR) -+ { -+ E4_uint64 status = trap->tr_transactions[trap->tr_identifyTrans].IProcStatusCntxAndTrType; -+ EP_NETERR_COOKIE cookie = 0; -+ -+ switch (IPROC_TransactionType (status) & TR_OPCODE_MASK) -+ { -+ case TR_SETEVENT_IDENTIFY & TR_OPCODE_MASK: -+ if (IPROC_TrapValue(status) == InputNoFault) -+ cookie = trap->tr_transactions[trap->tr_identifyTrans].TrAddr; -+ else -+ cookie = trap->tr_dataBuffers[trap->tr_identifyTrans].Data[0]; -+ printk ("%s: network error on setevent <%lld%s%s%s%s> from node %d\n", rail->r_generic.Name, EP4_COOKIE_STRING(cookie), nodeId); -+ break; -+ -+ case TR_INPUT_Q_COMMIT & TR_OPCODE_MASK: -+ if (IPROC_TrapValue(status) == InputNoFault) -+ cookie = trap->tr_transactions[trap->tr_identifyTrans].TrAddr; -+ else -+ cookie = trap->tr_dataBuffers[trap->tr_identifyTrans].Data[0]; -+ printk ("%s: network error on queue commit <%lld%s%s%s%s> from node %d\n", rail->r_generic.Name, EP4_COOKIE_STRING(cookie), nodeId); -+ break; -+ -+ case TR_REMOTEDMA & TR_OPCODE_MASK: -+ cookie = trap->tr_transactions[trap->tr_identifyTrans].TrAddr; -+ printk ("%s: network error on remote dma <%lld%s%s%s%s> from node %d\n", rail->r_generic.Name, EP4_COOKIE_STRING(cookie), nodeId); -+ break; -+ -+ case TR_IDENTIFY & TR_OPCODE_MASK: -+ cookie = trap->tr_transactions[trap->tr_identifyTrans].TrAddr; -+ printk ("%s: network error on identify <%lld%s%s%s%s> from node %d\n", rail->r_generic.Name, EP4_COOKIE_STRING(cookie), nodeId); -+ break; -+ -+ default: -+ panic ("%s: unknown identify transaction type %x for eop error from node %d\n", rail->r_generic.Name, -+ IPROC_TransactionType (trap->tr_transactions[trap->tr_identifyTrans].IProcStatusCntxAndTrType), nodeId); -+ break; -+ } -+ -+ ep_queue_network_error (&rail->r_generic, nodeId, EP_NODE_NETERR_ATOMIC_PACKET, unit & 1, cookie); -+ } -+ } -+ return; -+ } -+ -+ printk ("%s: unhandled iproc trap\n", rail->r_generic.Name); -+ elan4_display_iproc_trap (DBG_CONSOLE, 0, "ep4_iproc_trap", trap); -+} -+ -+void -+ep4_interrupt (ELAN4_CTXT *ctxt, E4_uint64 cookie) -+{ -+ EP4_RAIL *rail = EP4_CTXT_TO_RAIL (ctxt); -+ EP4_INTCOOKIE *cp = ep4_lookup_intcookie (rail, cookie); -+ -+ if (cp == NULL) -+ { -+ printk ("ep4_interrupt: cannot find event cookie for %016llx\n", (long long) cookie); -+ return; -+ } -+ -+ cp->int_callback (rail, cp->int_arg); -+} -+ -+ELAN4_TRAP_OPS ep4_trap_ops = -+{ -+ ep4_eproc_trap, -+ ep4_cproc_trap, -+ ep4_dproc_trap, -+ ep4_tproc_trap, -+ ep4_iproc_trap, -+ ep4_interrupt, -+}; -+ -+void -+ep4_flush_filters (EP_RAIL *r) -+{ -+ /* nothing to do here as elan4_set_filter() flushes the context filter */ -+} -+ -+struct flush_queues_desc -+{ -+ EP4_RAIL *rail; -+ volatile int done; -+} ; -+ -+static void -+ep4_flush_queues_flushop (ELAN4_DEV *dev, void *arg, int qfull) -+{ -+ struct flush_queues_desc *desc = (struct flush_queues_desc *) arg; -+ EP4_RAIL *rail = desc->rail; -+ E4_uint64 qptrs = read_reg64 (dev, DProcHighPriPtrs); -+ E4_uint32 qsize = E4_QueueSize (E4_QueueSizeValue (qptrs)); -+ E4_uint32 qfptr = E4_QueueFrontPointer (qptrs); -+ E4_uint32 qbptr = E4_QueueBackPointer (qptrs); -+ E4_DProcQueueEntry qentry; -+ unsigned long flags; -+ -+ while ((qfptr != qbptr) || qfull) -+ { -+ E4_uint64 typeSize = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_typeSize)); -+ -+ if (DMA_Context (qentry.Desc.dma_typeSize) == rail->r_ctxt.ctxt_num) -+ { -+ E4_uint64 vp = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_vproc)); -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[EP_VP_TO_NODE(vp)]; -+ -+ EP4_ASSERT (rail, !EP_VP_ISDATA(vp) || (nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE)); -+ -+ if (EP_VP_ISDATA(vp) && nodeRail->State == EP_NODE_LOCAL_PASSIVATE) -+ { -+ /* -+ * This is a DMA going to the node which is being removed, -+ * so move it onto the node dma list where it will get -+ * handled later. -+ */ -+ qentry.Desc.dma_typeSize = typeSize; -+ qentry.Desc.dma_cookie = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_cookie)); -+ qentry.Desc.dma_vproc = vp; -+ qentry.Desc.dma_srcAddr = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_srcAddr)); -+ qentry.Desc.dma_dstAddr = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_dstAddr)); -+ qentry.Desc.dma_srcEvent = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_srcEvent)); -+ qentry.Desc.dma_dstEvent = elan4_sdram_readq (dev, qfptr + offsetof (E4_DProcQueueEntry, Desc.dma_dstEvent)); -+ -+ EPRINTF4 (DBG_RETRY, "ep4_flush_dmas: %016llx %016llx %016llx %016llx\n", qentry.Desc.dma_typeSize, -+ qentry.Desc.dma_cookie, qentry.Desc.dma_vproc, qentry.Desc.dma_srcAddr); -+ EPRINTF3 (DBG_RETRY, " %016llx %016llx %016llx\n", qentry.Desc.dma_dstAddr, -+ qentry.Desc.dma_srcEvent, qentry.Desc.dma_dstEvent); -+ -+ ep4_queue_dma_stalled (rail, &qentry.Desc); -+ -+ qentry.Desc.dma_typeSize = DMA_ShMemWrite | dev->dev_ctxt.ctxt_num; -+ qentry.Desc.dma_cookie = 0; -+ qentry.Desc.dma_vproc = 0; -+ qentry.Desc.dma_srcAddr = 0; -+ qentry.Desc.dma_dstAddr = 0; -+ qentry.Desc.dma_srcEvent = 0; -+ qentry.Desc.dma_dstEvent = 0; -+ -+ elan4_sdram_copyq_to_sdram (dev, &qentry, qfptr, sizeof (E4_DProcQueueEntry)); -+ } -+ } -+ -+ qfptr = (qfptr & ~(qsize-1)) | ((qfptr + sizeof (E4_DProcQueueEntry)) & (qsize-1)); -+ qfull = 0; -+ } -+ -+ spin_lock_irqsave (&rail->r_haltop_lock, flags); -+ desc->done = 1; -+ kcondvar_wakeupall (&rail->r_haltop_sleep, &rail->r_haltop_lock); -+ spin_unlock_irqrestore (&rail->r_haltop_lock, flags); -+} -+ -+static void -+ep4_flush_queues_haltop (ELAN4_DEV *dev, void *arg) -+{ -+ struct flush_queues_desc *desc = (struct flush_queues_desc *) arg; -+ -+ elan4_queue_dma_flushop (dev, &desc->rail->r_flushop, 1); -+} -+ -+void -+ep4_flush_queues (EP_RAIL *r) -+{ -+ EP4_RAIL *rail = (EP4_RAIL *) r; -+ struct flush_queues_desc desc; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ int i; -+ -+ /* initialise descriptor */ -+ desc.rail = rail; -+ desc.done = 0; -+ -+ /* First - stall the dma retry thread, so that it will no longer restart -+ * any dma's from the retry list */ -+ ep_kthread_stall (&rail->r_retry_thread); -+ -+ /* Second - flush through all command queues targetted by events, thread etc */ -+ ep4_flush_ecqs (rail); -+ -+ /* Third - queue a halt operation to flush through all DMA's which are executing -+ * or on the run queues */ -+ kmutex_lock (&rail->r_haltop_mutex); -+ -+ rail->r_haltop.op_mask = INT_DProcHalted; -+ rail->r_haltop.op_function = ep4_flush_queues_haltop; -+ rail->r_haltop.op_arg = &desc; -+ -+ rail->r_flushop.op_function = ep4_flush_queues_flushop; -+ rail->r_flushop.op_arg = &desc; -+ -+ elan4_queue_haltop (rail->r_ctxt.ctxt_dev, &rail->r_haltop); -+ -+ spin_lock_irqsave (&rail->r_haltop_lock, flags); -+ while (! desc.done) -+ kcondvar_wait (&rail->r_haltop_sleep, &rail->r_haltop_lock, &flags); -+ spin_unlock_irqrestore (&rail->r_haltop_lock, flags); -+ kmutex_unlock (&rail->r_haltop_mutex); -+ -+ /* Fourth - run down the dma retry lists and move all entries to the cancelled -+ * list. Any dma's which were on the run queues have already been -+ * moved there */ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ list_for_each_safe (el,nel, &rail->r_dma_retrylist[i]) { -+ EP4_DMA_RETRY *retry = list_entry (el, EP4_DMA_RETRY, retry_link); -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[EP_VP_TO_NODE(retry->retry_dma.dma_vproc)]; -+ -+ EP4_ASSERT (rail, nodeRail->State >= EP_NODE_CONNECTED && nodeRail->State <= EP_NODE_LOCAL_PASSIVATE); -+ -+ if (nodeRail->State == EP_NODE_LOCAL_PASSIVATE) -+ { -+ list_del (&retry->retry_link); -+ list_add_tail (&retry->retry_link, &nodeRail->StalledDmas); -+ } -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ -+ /* Finally - allow the retry thread to run again */ -+ ep_kthread_resume (&rail->r_retry_thread); -+} -+ -+struct write_qdesc_desc -+{ -+ EP4_RAIL *rail; -+ sdramaddr_t qaddr; -+ E4_InputQueue *qdesc; -+ volatile int done; -+} ; -+ -+static void -+ep4_write_qdesc_haltop (ELAN4_DEV *dev, void *arg) -+{ -+ struct write_qdesc_desc *desc = (struct write_qdesc_desc *) arg; -+ EP4_RAIL *rail = desc->rail; -+ unsigned long flags; -+ -+ elan4_sdram_copyq_to_sdram (dev, desc->qdesc, desc->qaddr, sizeof (E4_InputQueue)); -+ -+ spin_lock_irqsave (&rail->r_haltop_lock, flags); -+ desc->done = 1; -+ kcondvar_wakeupall (&rail->r_haltop_sleep, &rail->r_haltop_lock); -+ spin_unlock_irqrestore (&rail->r_haltop_lock, flags); -+} -+ -+void -+ep4_write_qdesc (EP4_RAIL *rail, sdramaddr_t qaddr, E4_InputQueue *qdesc) -+{ -+ struct write_qdesc_desc desc; -+ unsigned long flags; -+ -+ /* initialise descriptor */ -+ desc.rail = rail; -+ desc.qaddr = qaddr; -+ desc.qdesc = qdesc; -+ desc.done = 0; -+ -+ kmutex_lock (&rail->r_haltop_mutex); -+ -+ rail->r_haltop.op_mask = INT_DiscardingHighPri; -+ rail->r_haltop.op_function = ep4_write_qdesc_haltop; -+ rail->r_haltop.op_arg = &desc; -+ -+ elan4_queue_haltop (rail->r_ctxt.ctxt_dev, &rail->r_haltop); -+ -+ spin_lock_irqsave (&rail->r_haltop_lock, flags); -+ while (! desc.done) -+ kcondvar_wait (&rail->r_haltop_sleep, &rail->r_haltop_lock, &flags); -+ spin_unlock_irqrestore (&rail->r_haltop_lock, flags); -+ -+ kmutex_unlock (&rail->r_haltop_mutex); -+} -+#define CQ_SIZE_NWORDS ((CQ_Size (ecq->ecq_cq->cq_size) >> 3) - 8) /* available number of dwords (less enough to flush) */ -+EP4_ECQ * -+ep4_alloc_ecq (EP4_RAIL *rail, unsigned cqsize) -+{ -+ EP4_ECQ *ecq; -+ unsigned long pgoff; -+ -+ /* no space available, so allocate a new entry */ -+ KMEM_ZALLOC (ecq, EP4_ECQ *, sizeof (EP4_ECQ), 1); -+ -+ if (ecq == NULL) -+ return 0; -+ -+ if ((ecq->ecq_cq = elan4_alloccq (&rail->r_ctxt, cqsize, CQ_EnableAllBits, CQ_Priority)) == NULL) -+ { -+ KMEM_FREE (ecq, sizeof (EP4_ECQ)); -+ return 0; -+ } -+ -+ pgoff = (ecq->ecq_cq->cq_mapping & (PAGE_SIZE-1)); -+ -+ ecq->ecq_addr = ep_rmalloc (rail->r_ecq_rmap, PAGESIZE, 0) + pgoff; -+ ecq->ecq_avail = CQ_SIZE_NWORDS; /* available number of dwords (less enough to flush) */ -+ -+ ecq->ecq_intop.op_function = (ELAN4_HALTFN *) elan4_restartcq; -+ ecq->ecq_intop.op_arg = ecq->ecq_cq; -+ -+ ep4_ioaddr_map (&rail->r_generic, ecq->ecq_addr - pgoff, ecq->ecq_cq->cq_mapping - pgoff, PAGESIZE, EP_PERM_WRITE); -+ -+ spin_lock_init (&ecq->ecq_lock); -+ -+ return ecq; -+} -+ -+void -+ep4_free_ecq (EP4_RAIL *rail, EP4_ECQ *ecq) -+{ -+ unsigned long pgoff = (ecq->ecq_cq->cq_mapping & (PAGE_SIZE-1)); -+ -+ spin_lock_destroy (&ecq->ecq_lock); -+ -+ ep4_unmap (&rail->r_generic, ecq->ecq_addr - pgoff, PAGESIZE); -+ ep_rmfree (rail->r_ecq_rmap, PAGESIZE, ecq->ecq_addr - pgoff); -+ -+ elan4_freecq (&rail->r_ctxt, ecq->ecq_cq); -+ -+ KMEM_FREE (ecq, sizeof (EP4_ECQ)); -+} -+ -+EP4_ECQ * -+ep4_get_ecq (EP4_RAIL *rail, unsigned which, unsigned ndwords) -+{ -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el; -+ unsigned long flags; -+ EP4_ECQ *ecq; -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ list_for_each (el, &rail->r_ecq_list[which]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ if (ecq->ecq_avail >= ndwords) -+ { -+ ecq->ecq_avail -= ndwords; -+ -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ -+ return ecq; -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ -+ if ((ecq = ep4_alloc_ecq (rail, EP4_ECQ_Size (which))) == NULL) -+ return NULL; -+ -+ if (which == EP4_ECQ_EVENT) -+ { -+ if ((ecq->ecq_event = ep_alloc_elan (&rail->r_generic, sizeof (E4_Event32), 0, &ecq->ecq_event_addr)) == 0) -+ { -+ ep4_free_ecq (rail, ecq); -+ return NULL; -+ } -+ -+ elan4_sdram_writeq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_CountAndType), -+ E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ elan4_sdram_writeq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_WritePtr), -+ ecq->ecq_addr); -+ elan4_sdram_writeq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_WriteValue), -+ SET_EVENT_CMD | (rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_flush_event))); -+ -+ if ((ecq->ecq_flushcq = ep4_get_ecq (rail, EP4_ECQ_SINGLE, 1)) == NULL) -+ { -+ ep_free_elan (&rail->r_generic, ecq->ecq_event_addr, sizeof (E4_Event32)); -+ ep4_free_ecq (rail, ecq); -+ return NULL; -+ } -+ } -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ list_add (&ecq->ecq_link, &rail->r_ecq_list[which]); -+ -+ ecq->ecq_avail -= ndwords; -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ -+ return ecq; -+} -+ -+void -+ep4_put_ecq (EP4_RAIL *rail, EP4_ECQ *ecq, unsigned ndwords) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ -+ ecq->ecq_avail += ndwords; -+ -+ if (ecq->ecq_avail != CQ_SIZE_NWORDS) -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ else -+ { -+ list_del (&ecq->ecq_link); -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ -+ if (ecq->ecq_flushcq) -+ ep4_put_ecq (rail, ecq->ecq_flushcq, 1); -+ if (ecq->ecq_event_addr) -+ ep_free_elan (&rail->r_generic, ecq->ecq_event_addr, sizeof (E4_Event32)); -+ -+ ep4_free_ecq (rail, ecq); -+ } -+} -+ -+void -+ep4_nop_cmd (EP4_ECQ *ecq, E4_uint64 tag) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&ecq->ecq_lock, flags); -+ elan4_nop_cmd (ecq->ecq_cq, tag); -+ spin_unlock_irqrestore (&ecq->ecq_lock, flags); -+ -+} -+ -+void -+ep4_set_event_cmd (EP4_ECQ *ecq, E4_Addr event) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&ecq->ecq_lock, flags); -+ elan4_set_event_cmd (ecq->ecq_cq, event); -+ spin_unlock_irqrestore (&ecq->ecq_lock, flags); -+} -+ -+void -+ep4_wait_event_cmd (EP4_ECQ *ecq, E4_Addr event, E4_uint64 candt, E4_uint64 param0, E4_uint64 param1) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&ecq->ecq_lock, flags); -+ elan4_wait_event_cmd (ecq->ecq_cq, event, candt, param0, param1); -+ spin_unlock_irqrestore (&ecq->ecq_lock, flags); -+} -+ -+void -+ep4_flush_interrupt (EP4_RAIL *rail, void *arg) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ rail->r_flush_count = 0; -+ kcondvar_wakeupone (&rail->r_flush_sleep, &rail->r_ecq_lock); -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+} -+ -+void -+ep4_flush_ecqs (EP4_RAIL *rail) -+{ -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el; -+ unsigned long flags; -+ int i; -+ -+ kmutex_lock (&rail->r_flush_mutex); -+ -+ EP4_SDRAM_ASSERT (rail, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_flush_event), E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG,0)); -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ /* first flush all the "event" queues */ -+ list_for_each (el, &rail->r_ecq_list[EP4_ECQ_EVENT]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ elan4_sdram_writeq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_CountAndType), -+ E4_EVENT_INIT_VALUE (-32, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0)); -+ -+ ep4_set_event_cmd (ecq->ecq_flushcq, ecq->ecq_event_addr); -+ -+ rail->r_flush_count++; -+ } -+ -+ /* next issue the setevents to all the other queues */ -+ for (i = EP4_ECQ_ATOMIC; i r_ecq_list[i]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ ep4_set_event_cmd (ecq, rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_flush_event)); -+ -+ rail->r_flush_count++; -+ } -+ } -+ -+ /* issue the waitevent command */ -+ ep4_wait_event_cmd (rail->r_flush_mcq, rail->r_elan_addr + offsetof (EP4_RAIL_ELAN, r_flush_event), -+ E4_EVENT_INIT_VALUE (-32 * rail->r_flush_count, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG,0), -+ rail->r_flush_ecq->ecq_addr, -+ INTERRUPT_CMD | (rail->r_flush_intcookie.int_val << E4_MAIN_INT_SHIFT)); -+ -+ while (rail->r_flush_count) -+ kcondvar_wait (&rail->r_flush_sleep, &rail->r_ecq_lock, &flags); -+ -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ -+ EP4_SDRAM_ASSERT (rail, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_flush_event), E4_EVENT_INIT_VALUE (0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG,0)); -+ -+ kmutex_unlock (&rail->r_flush_mutex); -+} -+ -+void -+ep4_init_thread (EP4_RAIL *rail, E4_ThreadRegs *regs, sdramaddr_t stackTop, -+ EP_ADDR stackAddr, E4_Addr startpc, int nargs,...) -+{ -+ sdramaddr_t sp = stackTop - roundup (nargs * sizeof (E4_uint64), E4_STACK_ALIGN); -+ int i; -+ va_list ap; -+ -+ /* -+ * the thread start code expects the following : -+ * %r1 = stack pointer -+ * %r6 = frame pointer -+ * %r2 = function to call -+ * -+ * function args are store on stack above %sp -+ */ -+ -+ va_start(ap, nargs); -+ for (i = 0; i < nargs; i++) -+ elan4_sdram_writeq (rail->r_ctxt.ctxt_dev, sp + (i * sizeof (E4_uint64)), va_arg (ap, E4_uint64)); -+ va_end (ap); -+ -+ regs->Registers[0] = ep_symbol (&rail->r_threadcode, ".thread_start"); /* %r0 - PC */ -+ regs->Registers[1] = stackAddr - (stackTop - sp); /* %r1 - stack pointer */ -+ regs->Registers[2] = startpc; /* %r2 - start pc */ -+ regs->Registers[3] = 0; -+ regs->Registers[4] = 0; -+ regs->Registers[5] = 0; -+ regs->Registers[6] = stackTop; /* %r6 - frame pointer */ -+} -+ -+/* retransmission thread */ -+ -+void -+ep4_add_retry_ops (EP4_RAIL *rail, EP4_RETRY_OPS *ops) -+{ -+ ep_kthread_stall (&rail->r_retry_thread); -+ list_add_tail (&ops->op_link, &rail->r_retry_ops); -+ ep_kthread_resume (&rail->r_retry_thread); -+} -+ -+void -+ep4_remove_retry_ops (EP4_RAIL *rail, EP4_RETRY_OPS *ops) -+{ -+ ep_kthread_stall (&rail->r_retry_thread); -+ list_del (&ops->op_link); -+ ep_kthread_resume (&rail->r_retry_thread); -+} -+ -+void -+ep4_retry_thread (EP4_RAIL *rail) -+{ -+ struct list_head *el; -+ -+ kernel_thread_init ("ep4_retry"); -+ -+ for (;;) -+ { -+ long nextRunTime = 0; -+ -+ list_for_each (el, &rail->r_retry_ops) { -+ EP4_RETRY_OPS *ops = list_entry (el, EP4_RETRY_OPS, op_link); -+ -+ nextRunTime = ops->op_func (rail, ops->op_arg, nextRunTime); -+ } -+ -+ if (ep_kthread_sleep (&rail->r_retry_thread, nextRunTime) < 0) -+ break; -+ } -+ -+ ep_kthread_stopped (&rail->r_retry_thread); -+ -+ kernel_thread_exit(); -+} -+ -+/* DMA retransmission */ -+static unsigned ep4_dma_retry_times[EP_NUM_RETRIES]; -+ -+static unsigned long -+ep4_retry_dmas (EP4_RAIL *rail, void *arg, unsigned long nextRunTime) -+{ -+ unsigned long yieldAt = lbolt + (hz/10); -+ unsigned long flags; -+ int i; -+ -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ while (! list_empty (&rail->r_dma_retrylist[i])) -+ { -+ EP4_DMA_RETRY *retry = list_entry (rail->r_dma_retrylist[i].next, EP4_DMA_RETRY, retry_link); -+ -+ if (! AFTER(lbolt, retry->retry_time)) -+ break; -+ -+ if (ep_kthread_should_stall (&rail->r_retry_thread) || AFTER (lbolt, yieldAt)) -+ goto cant_do_more; -+ -+ EPRINTF3 (DBG_RETRY, "%s: ep4_retry_dmas: flowcnt %llx %llx\n", rail->r_generic.Name, rail->r_dma_flowcnt, rail->r_main->r_dma_flowcnt); -+ -+ if ((rail->r_dma_flowcnt - rail->r_main->r_dma_flowcnt) > EP4_DMA_RETRY_FLOWCNT) -+ { -+ printk ("ep4_retry_dmas: flowcnt %llx %llx\n", rail->r_dma_flowcnt, rail->r_main->r_dma_flowcnt); -+ -+ goto cant_do_more; -+ } -+ -+ EPRINTF4 (DBG_RETRY, "%s: ep4_retry_dmas: %016llx %016llx %016llx\n", rail->r_generic.Name, -+ retry->retry_dma.dma_typeSize, retry->retry_dma.dma_cookie, retry->retry_dma.dma_vproc); -+ EPRINTF5 (DBG_RETRY, "%s: %016llx %016llx %016llx %016llx\n", rail->r_generic.Name, -+ retry->retry_dma.dma_srcAddr, retry->retry_dma.dma_dstAddr, retry->retry_dma.dma_srcEvent, -+ retry->retry_dma.dma_dstEvent); -+ -+ elan4_run_dma_cmd (rail->r_dma_ecq->ecq_cq, &retry->retry_dma); -+ elan4_write_dword_cmd (rail->r_dma_ecq->ecq_cq, rail->r_main_addr + offsetof (EP4_RAIL_MAIN, r_dma_flowcnt), ++rail->r_dma_flowcnt); -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ list_del (&retry->retry_link); -+ list_add (&retry->retry_link, &rail->r_dma_freelist); -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ } -+ } -+ cant_do_more: -+ -+ /* re-compute the next retry time */ -+ for (i = EP_RETRY_BASE; i < EP_NUM_RETRIES; i++) -+ { -+ if (! list_empty (&rail->r_dma_retrylist[i])) -+ { -+ EP4_DMA_RETRY *retry = list_entry (rail->r_dma_retrylist[i].next, EP4_DMA_RETRY, retry_link); -+ -+ SET_NEXT_RUN_TIME (nextRunTime, retry->retry_time); -+ } -+ } -+ -+ return nextRunTime; -+} -+ -+void -+ep4_initialise_dma_retries (EP4_RAIL *rail) -+{ -+ int i; -+ -+ spin_lock_init (&rail->r_dma_lock); -+ -+ for (i = 0; i < EP_NUM_RETRIES; i++) -+ INIT_LIST_HEAD (&rail->r_dma_retrylist[i]); -+ -+ INIT_LIST_HEAD (&rail->r_dma_freelist); -+ -+ rail->r_dma_ecq = ep4_alloc_ecq (rail, EP4_DMA_RETRY_CQSIZE); -+ -+ rail->r_dma_allocated = 0; -+ rail->r_dma_reserved = 0; -+ -+ ep4_dma_retry_times[EP_RETRY_HIGH_PRI] = EP_RETRY_HIGH_PRI_TIME; -+ -+ for (i =0 ; i < EP_NUM_BACKOFF; i++) -+ ep4_dma_retry_times[EP_RETRY_HIGH_PRI_RETRY+i] = EP_RETRY_HIGH_PRI_TIME << i; -+ -+ ep4_dma_retry_times[EP_RETRY_LOW_PRI] = EP_RETRY_LOW_PRI_TIME; -+ -+ for (i =0 ; i < EP_NUM_BACKOFF; i++) -+ ep4_dma_retry_times[EP_RETRY_LOW_PRI_RETRY+i] = EP_RETRY_LOW_PRI_TIME << i; -+ -+ ep4_dma_retry_times[EP_RETRY_ANONYMOUS] = EP_RETRY_ANONYMOUS_TIME; -+ ep4_dma_retry_times[EP_RETRY_NETERR] = EP_RETRY_NETERR_TIME; -+ -+ rail->r_dma_ops.op_func = ep4_retry_dmas; -+ rail->r_dma_ops.op_arg = NULL; -+ -+ ep4_add_retry_ops (rail, &rail->r_dma_ops); -+} -+ -+void -+ep4_finalise_dma_retries (EP4_RAIL *rail) -+{ -+ ep4_remove_retry_ops (rail, &rail->r_dma_ops); -+ -+ /* Everyone should have given back their retry dma's by now */ -+ EP4_ASSERT (rail, rail->r_dma_reserved == 0); -+ -+ while (! list_empty (&rail->r_dma_freelist)) -+ { -+ EP4_DMA_RETRY *retry = list_entry (rail->r_dma_freelist.next, EP4_DMA_RETRY, retry_link); -+ -+ list_del (&retry->retry_link); -+ -+ KMEM_FREE (retry, sizeof (EP4_DMA_RETRY)); -+ } -+ -+ ep4_free_ecq (rail, rail->r_dma_ecq); -+ -+ spin_lock_destroy (&rail->r_dma_lock); -+} -+ -+int -+ep4_reserve_dma_retries (EP4_RAIL *rail, unsigned int count, EP_ATTRIBUTE attr) -+{ -+ EP4_DMA_RETRY *retry; -+ unsigned int remaining = count; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ -+ if (remaining <= (rail->r_dma_allocated - rail->r_dma_reserved)) -+ { -+ rail->r_dma_reserved += remaining; -+ -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ -+ return 0; -+ } -+ -+ remaining -= (rail->r_dma_allocated - rail->r_dma_reserved); -+ -+ rail->r_dma_reserved = rail->r_dma_allocated; -+ -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ -+ while (remaining > 0) -+ { -+ KMEM_ALLOC (retry, EP4_DMA_RETRY *, sizeof (EP4_DMA_RETRY), !(attr & EP_NO_SLEEP)); -+ -+ if (retry == NULL) -+ goto failed; -+ -+ remaining--; -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ list_add (&retry->retry_link, &rail->r_dma_freelist); -+ -+ rail->r_dma_allocated++; -+ rail->r_dma_reserved++; -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ } -+ -+ return 0; -+ -+ failed: -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ rail->r_dma_reserved -= (count - remaining); -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+ -+ return 1; -+} -+ -+void -+ep4_release_dma_retries (EP4_RAIL *rail, unsigned int count) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ rail->r_dma_reserved -= count; -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+} -+ -+void -+ep4_queue_dma_retry (EP4_RAIL *rail, E4_DMA *dma, int interval) -+{ -+ EP4_DMA_RETRY *retry; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ -+ EP4_ASSERT (rail, !list_empty (&rail->r_dma_freelist)); -+ -+ /* take an item of the free list */ -+ retry = list_entry (rail->r_dma_freelist.next, EP4_DMA_RETRY, retry_link); -+ -+ list_del (&retry->retry_link); -+ -+ EPRINTF5 (DBG_RETRY, "%s: ep4_queue_dma_retry: %016llx %016llx %016llx %016llx\n", rail->r_generic.Name, -+ dma->dma_typeSize, dma->dma_cookie, dma->dma_vproc, dma->dma_srcAddr); -+ EPRINTF5 (DBG_RETRY, "%s: %016llx %016llx %016llx (%d)\n", rail->r_generic.Name, -+ dma->dma_dstAddr, dma->dma_srcEvent, dma->dma_dstEvent, interval); -+ -+ retry->retry_dma.dma_typeSize = dma->dma_typeSize; -+ retry->retry_dma.dma_cookie = dma->dma_cookie; -+ retry->retry_dma.dma_vproc = dma->dma_vproc; -+ retry->retry_dma.dma_srcAddr = dma->dma_srcAddr; -+ retry->retry_dma.dma_dstAddr = dma->dma_dstAddr; -+ retry->retry_dma.dma_srcEvent = dma->dma_srcEvent; -+ retry->retry_dma.dma_dstEvent = dma->dma_dstEvent; -+ -+ retry->retry_time = lbolt + ep4_dma_retry_times[interval]; -+ -+ /* chain onto the end of the approriate retry list */ -+ list_add_tail (&retry->retry_link, &rail->r_dma_retrylist[interval]); -+ -+ ep_kthread_schedule (&rail->r_retry_thread, retry->retry_time); -+ -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+} -+ -+void -+ep4_queue_dma_stalled (EP4_RAIL *rail, E4_DMA *dma) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[EP_VP_TO_NODE(dma->dma_vproc)]; -+ EP4_DMA_RETRY *retry; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ -+ EP4_ASSERT (rail, !list_empty (&rail->r_dma_freelist)); -+ -+ /* take an item of the free list */ -+ retry = list_entry (rail->r_dma_freelist.next, EP4_DMA_RETRY, retry_link); -+ -+ list_del (&retry->retry_link); -+ -+ EPRINTF5 (DBG_RETRY, "%s: ep4_queue_dma_stalled: %016llx %016llx %016llx %016llx\n", rail->r_generic.Name, -+ dma->dma_typeSize, dma->dma_cookie, dma->dma_vproc, dma->dma_srcAddr); -+ EPRINTF4 (DBG_RETRY, "%s: %016llx %016llx %016llx\n", rail->r_generic.Name, -+ dma->dma_dstAddr, dma->dma_srcEvent, dma->dma_dstEvent); -+ -+ retry->retry_dma.dma_typeSize = dma->dma_typeSize; -+ retry->retry_dma.dma_cookie = dma->dma_cookie; -+ retry->retry_dma.dma_vproc = dma->dma_vproc; -+ retry->retry_dma.dma_srcAddr = dma->dma_srcAddr; -+ retry->retry_dma.dma_dstAddr = dma->dma_dstAddr; -+ retry->retry_dma.dma_srcEvent = dma->dma_srcEvent; -+ retry->retry_dma.dma_dstEvent = dma->dma_dstEvent; -+ -+ /* chain onto the node cancelled dma list */ -+ list_add_tail (&retry->retry_link, &nodeRail->StalledDmas); -+ -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+} -+ -+void -+ep4_free_stalled_dmas (EP4_RAIL *rail, unsigned int nodeId) -+{ -+ EP_NODE_RAIL *nodeRail = &rail->r_generic.Nodes[nodeId]; -+ struct list_head *el, *nel; -+ unsigned long flags; -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ list_for_each_safe (el, nel, &nodeRail->StalledDmas) { -+ list_del (el); -+ list_add (el, &rail->r_dma_freelist); -+ } -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+} -+ -+void -+ep4_display_rail (EP4_RAIL *rail) -+{ -+ ELAN4_DEV *dev = rail->r_ctxt.ctxt_dev; -+ struct list_head *el; -+ register int i; -+ unsigned long flags; -+ -+ ep_debugf (DBG_DEBUG, "%s: vendorid=%x deviceid=%x\n", rail->r_generic.Name, -+ rail->r_generic.Devinfo.dev_vendor_id, rail->r_generic.Devinfo.dev_device_id); -+ -+ spin_lock_irqsave (&rail->r_ecq_lock, flags); -+ for (i = 0; i < EP4_NUM_ECQ; i++) -+ { -+ list_for_each (el, &rail->r_ecq_list[i]) { -+ EP4_ECQ *ecq = list_entry (el, EP4_ECQ, ecq_link); -+ -+ if (i == EP4_ECQ_EVENT) -+ ep_debugf (DBG_DEBUG, " ECQ[%d] ecq=%p cqnum=%d addr=%llx avail=%d event=%llx,%llx,%llx\n", -+ i, ecq, elan4_cq2num (ecq->ecq_cq), ecq->ecq_addr, ecq->ecq_avail, -+ elan4_sdram_readq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_CountAndType)), -+ elan4_sdram_readq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_WriteValue)), -+ elan4_sdram_readq (dev, ecq->ecq_event + offsetof (E4_Event32, ev_WritePtr))); -+ -+ else -+ ep_debugf (DBG_DEBUG, " ECQ[%d] ecq=%p cqnum=%d addr=%llx avail=%d\n", -+ i, ecq, elan4_cq2num (ecq->ecq_cq), ecq->ecq_addr, ecq->ecq_avail); -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_ecq_lock, flags); -+ -+ ep_debugf (DBG_DEBUG, " flush count=%ld mcq=%p ecq=%p event %llx.%llx.%llx\n", -+ rail->r_flush_count, rail->r_flush_mcq, rail->r_flush_ecq, -+ elan4_sdram_readq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_flush_event.ev_CountAndType)), -+ elan4_sdram_readq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_flush_event.ev_WritePtr)), -+ elan4_sdram_readq (dev, rail->r_elan + offsetof (EP4_RAIL_ELAN, r_flush_event.ev_WriteValue))); -+ -+ spin_lock_irqsave (&rail->r_dma_lock, flags); -+ for (i = 0; i < EP_NUM_RETRIES; i++) -+ { -+ list_for_each (el, &rail->r_dma_retrylist[i]) { -+ EP4_DMA_RETRY *retry = list_entry (el, EP4_DMA_RETRY, retry_link); -+ -+ ep_debugf (DBG_DEBUG, " RETRY[%d] typeSize %llx cookie %llx vproc %llx events %llx %llx\n", -+ i, retry->retry_dma.dma_typeSize, retry->retry_dma.dma_cookie, -+ retry->retry_dma.dma_vproc, retry->retry_dma.dma_srcEvent, retry->retry_dma.dma_dstEvent); -+ } -+ } -+ spin_unlock_irqrestore (&rail->r_dma_lock, flags); -+} -Index: linux-2.4.21/drivers/net/qsnet/ep/threadcode.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/threadcode.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/threadcode.c 2005-06-01 23:12:54.689425424 -0400 -@@ -0,0 +1,146 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: threadcode.c,v 1.11 2003/10/07 13:22:38 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/threadcode.c,v $ */ -+ -+#include -+ -+#include -+ -+EP_ADDR -+ep_symbol (EP_CODE *code, char *name) -+{ -+ EP_SYMBOL *s = code->symbols; -+ -+ while (s->name && strcmp (s->name, name)) -+ s++; -+ -+ return (s->name ? s->value : (EP_ADDR) 0); -+} -+ -+int -+ep_loadcode (EP_RAIL *rail, EP_CODE *code) -+{ -+ register int i; -+ -+ EP_ADDR _stext = ep_symbol (code, "_stext"); -+ EP_ADDR _etext = ep_symbol (code, "_etext"); -+ EP_ADDR _sdata = ep_symbol (code, "_sdata"); -+ EP_ADDR _edata = ep_symbol (code, "_edata"); -+ EP_ADDR _end = ep_symbol (code, "_end"); -+ EP_ADDR _rodata = roundup (_etext, sizeof (uint64_t)); -+ -+ if (_stext == (EP_ADDR) 0 || _etext == (EP_ADDR) 0 || -+ _sdata == (EP_ADDR) 0 || _edata == (EP_ADDR) 0 || -+ _end == (EP_ADDR) 0) -+ { -+ printk ("ep_loadcode: symbols not defined correctly for code at %p\n", code); -+ return (EINVAL); -+ } -+ -+ /* -+ * Include the rodata in the text segment -+ */ -+ _etext = _rodata + code->rodata_size; -+ -+ /* -+ * If _etext is in the same page as _sdata, then allocate a contiguous -+ * chunk of memory and map it as read/write. otherwise allocate two chunks -+ * and map the code in as read-only. -+ */ -+ if ((_etext & PAGEMASK) == (_sdata & PAGEMASK)) -+ { -+ code->ntext = btopr (_end - (_stext & PAGEMASK)); -+ code->pptext = ep_alloc_memory_elan (rail, _stext & PAGEMASK, ptob (code->ntext), EP_PERM_EXECUTE, 0); -+ -+ if (code->pptext == (sdramaddr_t) 0) -+ return (ENOMEM); -+ -+ code->_stext = code->pptext + (_stext & PAGEOFFSET); -+ code->_rodata = code->_stext + (_rodata - _stext); -+ code->_sdata = code->_stext + (_sdata - _stext); -+ } -+ else -+ { -+ code->ntext = btopr (_etext - (_stext & PAGEMASK)); -+ code->ndata = btopr (_end - (_sdata & PAGEMASK)); -+ -+ if (code->ntext) -+ { -+ code->pptext = ep_alloc_memory_elan (rail, _stext & PAGEMASK, ptob (code->ntext), EP_PERM_EXECUTE, 0); -+ -+ if (code->pptext == (sdramaddr_t) 0) -+ return (ENOMEM); -+ -+ code->_stext = code->pptext + (_stext & PAGEOFFSET); -+ code->_rodata = code->_stext + (_rodata - _stext); -+ } -+ -+ if (code->ndata) -+ { -+ code->ppdata = ep_alloc_memory_elan (rail, _sdata & PAGEMASK, ptob (code->ndata), EP_PERM_WRITE, 0); -+ -+ if (code->ppdata == (sdramaddr_t) 0) -+ { -+ if (code->ntext) ep_free_memory_elan (rail, _sdata & PAGEMASK); -+ code->ntext = 0; -+ -+ return (ENOMEM); -+ } -+ -+ code->_sdata = code->ppdata + (_sdata & PAGEOFFSET); -+ } -+ } -+ -+#ifdef __LITTLE_ENDIAN__ -+# define Flip 3 -+#else -+# define Flip 0 -+#endif -+ -+ /* -+ * Now copy the text and rodata into the SDRAM -+ * this is linked into the module to be byte -+ * copied to the SDRAM, since we want to copy -+ * with word accesses we have to do the byte -+ * assembly correctly. -+ */ -+ for (i = 0; i < code->text_size; i++) -+ rail->Operations.SdramWriteb (rail, code->_stext + i, code->text[i^Flip]); -+ -+ for (i = 0; i < code->rodata_size; i++) -+ rail->Operations.SdramWriteb (rail, code->_rodata + i, code->rodata[i^Flip]); -+ -+ /* -+ * And the initialised data segment. -+ */ -+ for (i = 0; i < code->data_size; i++) -+ rail->Operations.SdramWriteb (rail, code->_sdata + i, code->data[i^Flip]); -+ -+ return (ESUCCESS); -+} -+ -+void -+ep_unloadcode (EP_RAIL *rail, EP_CODE *code) -+{ -+ EP_ADDR _stext = ep_symbol (code, "_stext"); -+ EP_ADDR _sdata = ep_symbol (code, "_sdata"); -+ -+ if (code->pptext) -+ ep_free_memory_elan (rail, _stext & PAGEMASK); -+ if (code->ppdata) -+ ep_free_memory_elan (rail, _sdata & PAGEMASK); -+ code->pptext = code->ppdata = 0; -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/threadcode_elan3.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/threadcode_elan3.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/threadcode_elan3.c 2005-06-01 23:12:54.690425272 -0400 -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: threadcode_elan3.c,v 1.11 2003/10/07 13:22:38 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/threadcode_elan3.c,v $ */ -+ -+#include -+ -+#include -+ -+#include "kcomm_elan3.h" -+#include "debug.h" -+ -+#include -+ -+E3_Addr -+ep3_init_thread (ELAN3_DEV *dev, -+ E3_Addr fn, /* Elan address of function */ -+ E3_Addr addr, /* Elan address of stack */ -+ sdramaddr_t stack, /* sdram address of stack */ -+ int stackSize, /* stack size (in bytes) */ -+ int nargs, -+ ...) -+{ -+ sdramaddr_t frame; -+ sdramaddr_t regs; -+ sdramaddr_t argsp; -+ int i; -+ va_list ap; -+ -+ /* -+ * Align the stack pointer at the top of the stack and leave space for a stack frame -+ */ -+ stack = ((stack + stackSize) & ~(E3_STACK_ALIGN-1)) - sizeof (E3_Frame); -+ addr = ((addr + stackSize) & ~(E3_STACK_ALIGN-1)) - sizeof (E3_Frame); -+ -+ va_start (ap, nargs); -+ -+ if (nargs > 6) -+ { -+ stack -= (((nargs*sizeof (E3_uint32))+E3_STACK_ALIGN-1) & ~(E3_STACK_ALIGN-1)); -+ addr -= (((nargs*sizeof (E3_uint32))+E3_STACK_ALIGN-1) & ~(E3_STACK_ALIGN-1)); -+ } -+ -+ frame = stack; -+ regs = stack - sizeof (E3_OutsRegs); -+ -+ /* -+ * Initialise the registers, and stack frame. -+ */ -+ elan3_sdram_writel (dev, regs + offsetof (E3_OutsRegs, o[6]), fn); -+ elan3_sdram_writel (dev, regs + offsetof (E3_OutsRegs, o[7]), 0); -+ -+ if (nargs <= 6) -+ { -+ for (i = 0; i < nargs; i++) -+ elan3_sdram_writel (dev, regs + offsetof (E3_OutsRegs, o[i]), va_arg (ap, E3_uint32)); -+ } -+ else -+ { -+ for (i = 0; i < 6; i++) -+ elan3_sdram_writel (dev, regs + offsetof (E3_OutsRegs, o[i]), va_arg (ap, E3_uint32)); -+ -+ for (argsp = frame + offsetof (E3_Frame, fr_argx[0]); i < nargs; i++, argsp += sizeof (E3_uint32)) -+ elan3_sdram_writel (dev, argsp, va_arg (ap, int)); -+ } -+ -+ elan3_sdram_writel (dev, frame + offsetof (E3_Frame, fr_savefp), 0); -+ elan3_sdram_writel (dev, frame + offsetof (E3_Frame, fr_savepc), 0); -+ -+ va_end (ap); -+ -+ return (addr); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/ep/threadcode_elan3_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/threadcode_elan3_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/threadcode_elan3_Linux.c 2005-06-01 23:12:54.690425272 -0400 -@@ -0,0 +1,112 @@ -+/* --------------------------------------------------------*/ -+/* MACHINE GENERATED ELAN CODE */ -+#include -+#include -+#include "kcomm_elan3.h" -+static uint32_t threadcode_elan3_text[] = { -+0x80a0239c, 0x00001082, 0x00e0a280, 0x47008002, 0x0020a380, 0x20600288, 0x20200286, 0x43008002, -+0x00000001, 0x0a006081, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, -+0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, -+0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, -+0x00000001, 0x00000001, 0xa800c613, 0xa300c609, 0x0020108a, 0x0080900b, 0x00006885, 0x0580a080, -+0x06008002, 0x02a0a080, 0x06008022, 0xffff0296, 0x04008010, 0xff3f0398, 0x1f008010, 0x00201090, -+0x00007081, 0x1600801c, 0x00000001, 0x60a0239c, 0x00a0a3c0, 0x20a0a3f0, 0x40a0a3e0, 0x00c03f3f, -+0xf8e017be, 0x04e08f80, 0x06008012, 0x00000001, 0x00c01ffc, 0x0000a081, 0x06008010, 0x40a083e0, -+0x14e007be, 0x00c01ffc, 0x0000a081, 0x40a083e0, 0x20a083f0, 0x00a083c0, 0x60a0039c, 0x00e0a280, -+0xbfffbf12, 0x0020a380, 0x03008012, 0x02201090, 0x03201090, 0x08e0c381, 0x80a0039c, 0xe0a0239c, -+0x60a023de, 0x80a0a3e0, 0xa0a0a3f0, 0x080010b8, 0x090010b0, 0x0a0010b2, 0x04000037, 0x402006b4, -+0x50200690, 0x01201092, 0x20a0239c, 0x00a0a3f0, 0x00c03f3f, 0x8ce117be, 0x04e08f80, 0x06008012, -+0x00000001, 0x00c01ff8, 0x0000b081, 0x06008010, 0x00a083f0, 0x14e007be, 0x00c01ff8, 0x0000b081, -+0x00a083f0, 0x20a0039c, 0x582006d0, 0x0020a280, 0x05008002, 0x0900a280, 0x10008002, 0x50200690, -+0xeaffbf30, 0x5c2006d4, 0x18001090, 0x19001092, 0x1b800294, 0x0a201096, 0x8affff7f, 0x05201098, -+0x446026d0, 0x302027f4, 0xdfffbf10, 0x50200690, 0xfdffbf10, 0x446026c0, 0x5c2006e0, 0x0020a480, -+0xf9ffbf06, 0x18001090, 0x19001092, 0x1b000494, 0x14201096, 0x7bffff7f, 0x0a201098, 0x0020a280, -+0xf4ffbf22, 0x486026e0, 0x00007081, 0x1600801c, 0x00000001, 0x60a0239c, 0x00a0a3c0, 0x20a0a3f0, -+0x40a0a3e0, 0x00c03f3f, 0x60e217be, 0x04e08f80, 0x06008012, 0x00000001, 0x00c01ffc, 0x0000a081, -+0x06008010, 0x40a083e0, 0x14e007be, 0x00c01ffc, 0x0000a081, 0x40a083e0, 0x20a083f0, 0x00a083c0, -+0x60a0039c, 0xff3f84a0, 0xe0ffbf1c, 0x18001090, 0xd5ffbf30, 0x60a003de, 0x80a083e0, 0xa0a083f0, -+0x08e0c381, 0xe0a0039c, 0x00a1239c, 0x60a023de, 0x80a0a3e0, 0xa0a0a3f0, 0x44a123d0, 0x090010b0, -+0x0a0010b6, 0x0b0010b8, 0x0c0010b4, 0x012010ba, 0xdca023fa, 0x142007d2, 0x082007d0, 0x084002b2, -+0x000027c0, 0xf42006d0, 0x0020a280, 0x15008032, 0xf42006d0, 0x18200790, 0xdca003d2, 0x20a0239c, -+0x00a0a3f0, 0x00c03f3f, 0x20e317be, 0x04e08f80, 0x06008012, 0x00000001, 0x00c01ff8, 0x0000b081, -+0x06008010, 0x00a083f0, 0x14e007be, 0x00c01ff8, 0x0000b081, 0x00a083f0, 0x20a0039c, 0xf42006d0, -+0x0020a280, 0x0a008022, 0xdca023c0, 0x042007d0, 0x0840a680, 0x06008032, 0xdca023c0, 0x18001082, -+0x0220d091, 0xe1ffbf10, 0xf42006d0, 0x06008010, 0x190010a2, 0x042006d0, 0x00c026d0, 0x18001082, -+0x0020d091, 0x042006d0, 0x01200290, 0x042026d0, 0x000006d0, 0x0020a280, 0x04008002, 0x18001090, -+0x4f010040, 0x1b001092, 0xf02006e0, 0x0020a480, 0xf1ffbf02, 0x40b03611, 0x004004d2, 0x01201290, -+0x0840a280, 0x0e018012, 0x10001096, 0x046004d0, 0x01208a80, 0x33008002, 0xa0200484, 0x0c2610ba, -+0x000024fa, 0x00211090, 0x042024d0, 0x246004d0, 0x80200290, 0x082024d0, 0xec2004d0, 0x00210290, -+0x0c2024d0, 0x102024c4, 0x186004d2, 0x02602a93, 0x098006d0, 0x0001003b, 0x1d000290, 0x098026d0, -+0xc0ff3f3b, 0x1d000a90, 0x44a103fa, 0x606007d2, 0x00680292, 0x09001290, 0x4000003b, 0x1d001290, -+0x142024d0, 0x206004d0, 0x10210290, 0x182024d0, 0x186004d0, 0x02202a91, 0x088006d2, 0x0001003b, -+0x1d400292, 0x088026d2, 0xc0ff3f3b, 0x1d400a92, 0x186004d0, 0x00280290, 0x80000015, 0x0a001290, -+0x08401292, 0x4000003b, 0x1d401292, 0x1c2024d2, 0x01201090, 0xa02024d0, 0x20200496, 0xa8200484, -+0x306004d0, 0x0020a280, 0x2b008012, 0x00201098, 0x0c2610ba, 0x00c022fa, 0x04e022c0, 0xc0200490, -+0x10e022d0, 0x186004d2, 0x02602a93, 0x098006d0, 0x0001003b, 0x1d000290, 0x098026d0, 0xc0ff3f3b, -+0x1d000a90, 0x44a103fa, 0x606007d2, 0x00680292, 0x09001290, 0x4000003b, 0x1d001290, 0x14e022d0, -+0x206004d0, 0x10210290, 0x18e022d0, 0x186004d0, 0x02202a91, 0x088006d2, 0x0001003b, 0x1d400292, -+0x088026d2, 0xc0ff3f3b, 0x1d400a92, 0x186004d0, 0x00280290, 0x80000015, 0x0a001290, 0x08401292, -+0x4000003b, 0x1d401292, 0x1ce022d2, 0x4f008010, 0x0020109a, 0x0c00109a, 0x306004d0, 0x0840a380, -+0x3b00801a, 0xe02004c6, 0x0c2610ba, 0x00c022fa, 0x01202b91, 0x0c000290, 0x02202a91, 0x08400490, -+0x382002d2, 0x04e022d2, 0x342002d0, 0x08e022d0, 0x0ce022c6, 0x10e022c4, 0x186004d0, 0x02202a91, -+0x088006d2, 0x0001003b, 0x1d400292, 0x088026d2, 0xc0ff3f3b, 0x1d400a92, 0x44a103fa, 0x606007d0, -+0x00280290, 0x08401292, 0x4000003b, 0x1d401292, 0x14e022d2, 0x206004d0, 0x10210290, 0x18e022d0, -+0x186004d0, 0x02202a91, 0x088006d4, 0x0001003b, 0x1d800294, 0x088026d4, 0xc0ff3f3b, 0x1d800a94, -+0x186004d0, 0x00280290, 0x80000013, 0x09001290, 0x08801294, 0x4000003b, 0x1d801294, 0x1ce022d4, -+0x01201090, 0x008020d0, 0x04e002d0, 0x08c00086, 0x0840039a, 0x01200398, 0x20e00296, 0x306004d0, -+0x0800a380, 0xc9ffbf0a, 0x08a00084, 0xc0200490, 0xf0ff22d0, 0xe42004d0, 0x0d00a280, 0x0b00801a, -+0x00201098, 0x04008010, 0x10001096, 0x01200398, 0x20e00296, 0x306004d0, 0x0800a380, 0xfcffbf2a, -+0x04e022c0, 0xfc3f109a, 0xe42024da, 0x10001082, 0x186004d0, 0x00280290, 0x08006081, 0x00000001, -+0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, -+0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, -+0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00201098, -+0x0c00109a, 0x142004fa, 0xec00823b, 0x3080d61b, 0x00006891, 0x0420a280, 0x3b008002, 0x0c00a280, -+0x04008002, 0x00000001, 0x0120d091, 0x36008030, 0x7c2006d0, 0x01200290, 0x7c2026d0, 0x782006d0, -+0x0020a280, 0x04008002, 0x78200690, 0x64000040, 0x40e00692, 0xf02004d0, 0x0020a280, 0x03008012, -+0xf02026d0, 0x80e026c0, 0x7c2006d0, 0x40e026d0, 0x046004d0, 0x04208a80, 0x13008002, 0x1100108a, -+0xec2004cc, 0x3fa00b8e, 0x40e0018e, 0x0780239c, 0x0080bbe0, 0x006099e0, 0x00a0b9e0, 0x406099e0, -+0x40a0b9e0, 0x806099e0, 0x80a0b9e0, 0xc06099e0, 0xc0a0b9e0, 0x00809be0, 0x0780039c, 0x0e008010, -+0xec2004d2, 0xec2004cc, 0x3fa00b8e, 0x40e0018e, 0x0780239c, 0x0080bbe0, 0x006099e0, 0x00a0b9e0, -+0x406099e0, 0x40a0b9e0, 0x00809be0, 0x0780039c, 0xec2004d2, 0xe42004d0, 0x886222d0, 0x042006d0, -+0x00c026d0, 0x000007d0, 0x01208a80, 0x05008012, 0x00000001, 0x142027f2, 0x06008010, 0xdca003fa, -+0x142027f2, 0xfe3f0a90, 0x000027d0, 0xdca003fa, 0x016007ba, 0xdca023fa, 0x0c2007d0, 0x0840a680, -+0x04008032, 0x082007d0, 0x03008010, 0x102007f2, 0x084006b2, 0x00007081, 0x1600801c, 0x00000001, -+0x60a0239c, 0x00a0a3c0, 0x20a0a3f0, 0x40a0a3e0, 0x02c03f3f, 0x8ce017be, 0x04e08f80, 0x06008012, -+0x00000001, 0x00c01ffc, 0x0000a081, 0x06008010, 0x40a083e0, 0x14e007be, 0x00c01ffc, 0x0000a081, -+0x40a083e0, 0x20a083f0, 0x00a083c0, 0x60a0039c, 0x042007d0, 0x0840a680, 0xb3febf12, 0x190010a2, -+0x8afebf10, 0xf42006d0, 0x60a003de, 0x80a083e0, 0xa0a083f0, 0x08e0c381, 0x00a1039c, 0x80a0239c, -+0x042002c4, 0x004022c4, 0x18008030, 0x00007081, 0x16008012, 0x00000001, 0x60a0239c, 0x00a0a3c0, -+0x20a0a3f0, 0x40a0a3e0, 0x02c03f3f, 0x24e117be, 0x04e08f80, 0x06008012, 0x00000001, 0x00c01ffc, -+0x0000a081, 0x06008010, 0x40a083e0, 0x14e007be, 0x00c01ffc, 0x0000a081, 0x40a083e0, 0x20a083f0, -+0x00a083c0, 0x60a0039c, 0x000002c4, 0x00a0a080, 0xe7ffbf12, 0x00000001, 0x042002c4, 0x01a00084, -+0x042022c4, 0x000002c4, 0x00a0a080, 0xddffbf12, 0x00000001, 0x08e0c381, 0x80a0039c, }; -+#define threadcode_elan3_text_size 0x97c -+static uint32_t threadcode_elan3_data[] = { -+0}; -+#define threadcode_elan3_data_size 0x0 -+static uint32_t threadcode_elan3_rodata[] = { -+0}; -+#define threadcode_elan3_rodata_size 0x0 -+static EP_SYMBOL threadcode_elan3_symbols[] = { -+ {"__bss_start", 0xff00297c}, -+ {"_edata", 0xff00297c}, -+ {"_end", 0xff002988}, -+ {"_etext", 0xff00097c}, -+ {"_sdata", 0xff00297c}, -+ {"_stext", 0xff000000}, -+ {"ep3_spinblock", 0xff0008dc}, -+ {"ep3comms_rcvr", 0xff0002a8}, -+ {"kcomm_probe", 0xff00013c}, -+ {"r", 0xff00297c}, -+ {"rail", 0xff002984}, -+ {"rm", 0xff002980}, -+ {0, 0}}; -+EP_CODE threadcode_elan3 = { -+ (unsigned char *) threadcode_elan3_text, -+ threadcode_elan3_text_size, -+ (unsigned char *) threadcode_elan3_data, -+ threadcode_elan3_data_size, -+ (unsigned char *) threadcode_elan3_rodata, -+ threadcode_elan3_rodata_size, -+ threadcode_elan3_symbols, -+}; -Index: linux-2.4.21/drivers/net/qsnet/ep/threadcode_elan4_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/ep/threadcode_elan4_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/ep/threadcode_elan4_Linux.c 2005-06-01 23:12:54.691425120 -0400 -@@ -0,0 +1,112 @@ -+/* --------------------------------------------------------*/ -+/* MACHINE GENERATED ELAN CODE */ -+#include -+#include -+#include "kcomm_elan4.h" -+static uint32_t threadcode_elan4_text[] = { -+0x00a00087, 0xc04060cb, 0x00003080, 0x80001080, 0x02606180, 0x02004032, 0x807f60cb, 0x04606180, -+0x02004032, 0x407f60d3, 0x08606180, 0x02004032, 0x007f60db, 0x10606180, 0x02004032, 0xc07e60e3, -+0x20606180, 0x02004032, 0x807e60eb, 0x40606180, 0x02004032, 0x407e60f3, 0x80606180, 0x02004032, -+0x007e60fb, 0x40001180, 0xc3801080, 0xc07f60c3, 0x20002000, 0x20002000, 0x20002000, 0x20002000, -+0x407f8001, 0x4060c0c7, 0x4860c0d0, 0x5060c0d1, 0x5860c0d2, 0x6060c0d3, 0x6860c0d4, 0x00208292, -+0x00608291, 0x00a08294, 0xff3f8088, 0x1c381293, 0xc04044c8, 0x13004290, 0xc000c5d0, 0x08004030, -+0x00001088, 0x04204288, 0x0020b200, 0x04004003, 0x00208080, 0x9c010040, 0x00a08488, 0xc04044c8, -+0x20381288, 0x0020b200, 0xf6ff7f13, 0x01208408, 0x11161282, 0x804094c2, 0xc04044c8, 0x20381288, -+0x0020b200, 0xebff7f13, 0x00208080, 0x406040c7, 0x486040d0, 0x506040d1, 0x586040d2, 0x606040d3, -+0x686040d4, 0x08e00180, 0xc0608001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, -+0x807e8001, 0x4060c0c7, 0x4860c0d0, 0x5060c0d1, 0x5860c0d2, 0x6060c0d3, 0x6860c0d4, 0x7060c0d5, -+0x7860c0d6, 0x8060c0d7, 0x8860c0d8, 0x9060c0d9, 0x9860c0da, 0xa060c0db, 0xa860c0dc, 0xb060c0dd, -+0xb860c0de, 0xc060c0df, 0x8061c0c8, 0x00608296, 0x00a0829a, 0x9861c0cb, 0xa061c0cc, 0xa861c0cd, -+0x01208088, 0x3861c0c8, 0x08e042d2, 0x386140c9, 0x0900900a, 0xa06140c8, 0x986140cb, 0x18e042c9, -+0x72010040, 0x05b4128a, 0x0020808c, 0x3861c0cc, 0x986140c9, 0xc04042c8, 0x0880b400, 0x39014003, -+0xffff3f08, 0x90a0851c, 0xe023829f, 0x20f4179f, 0x10e3879f, 0xffff3f08, 0xe023829e, 0x20b4179e, -+0x03a3879e, 0xffff3f08, 0xe023829d, 0x2074179d, 0x0363879d, 0x00a08495, 0x18a08408, 0x800012c2, -+0x089a109b, 0x20f4169b, 0x20f8169b, 0x00e88609, 0x20741289, 0x01120008, 0x0a381288, 0x08408297, -+0x45208088, 0x06341288, 0x806140ca, 0xc88042c8, 0x00288218, 0x04a08408, 0x800012c2, 0x089a1088, -+0x20341288, 0x20381288, 0x00281299, 0x20a08408, 0x800012c2, 0x089a108a, 0x20b4128a, 0x20b8128a, -+0x30a08408, 0x800012c2, 0x089a1093, 0x20f41493, 0x20f81493, 0x03f41689, 0x806140cb, 0x2922808c, -+0x0334138c, 0xccc042c8, 0xc90042d1, 0x02604688, 0x0020b200, 0x03004002, 0x60a08214, 0x80a08214, -+0x90a08509, 0x804012c8, 0x01208208, 0x804092c8, 0x046012c8, 0x043a1288, 0x0020b200, 0x04004003, -+0xa86140c8, 0x67ffff7f, 0x00a0868a, 0x88a045d0, 0x0020b400, 0x12004013, 0x00208080, 0x800017c8, -+0x808096c8, 0x72010040, 0x00a08588, 0x00208290, 0x90a08509, 0x804012c8, 0x01208208, 0x804092c8, -+0x046012c8, 0x043a1288, 0x0020b200, 0x04004003, 0xa86140c8, 0x53ffff7f, 0x00a0868a, 0x804015c2, -+0x159a1089, 0x20741289, 0x20781289, 0x40b03608, 0x01208288, 0x0840b200, 0x06004023, 0xa02344c4, -+0x800017c8, 0x808096c8, 0xbb004010, 0xa8a045c8, 0x01604688, 0x00281288, 0x08009008, 0x00e0b400, -+0x05004003, 0x3f381289, 0x13408209, 0x03004010, 0x05208088, 0x04208088, 0x09009220, 0x07341889, -+0x0900840b, 0x05341888, 0x0023820a, 0x01604688, 0x0020b200, 0x1d004002, 0x0a00840c, 0xc900c4d7, -+0x40c40f08, 0x09208288, 0x08e0c2c8, 0x0a608488, 0x10e0c2c8, 0x81001008, 0x0a341288, 0x18e0c2c8, -+0x1d608488, 0x20e0c2c8, 0x28e0c2d8, 0x24608508, 0x800012c2, 0x089a1088, 0x20341288, 0x20381288, -+0x80208208, 0x30e0c2c8, 0x00218108, 0x38e0c2c8, 0x40e0c2d4, 0x48e0c2cc, 0xca00c4df, 0x20608411, -+0x80e0820b, 0x2020830c, 0x00e0b400, 0x13004013, 0x0020808e, 0xc0c0c2d7, 0x40c40f09, 0x09608289, -+0x08e0c2c9, 0x0a608488, 0x10e0c2c8, 0x00040008, 0x18e0c2c8, 0x1d608488, 0x20e0c2c8, 0x28e0c2d8, -+0x40e0c2d4, 0x48e0c2cc, 0xc000c3de, 0x00208083, 0x4c004010, 0x20608411, 0xb8238408, 0x800012c2, -+0x089a108f, 0x20f4138f, 0x20f8138f, 0x00208083, 0x13c0b000, 0x2e00401b, 0x40c40f08, 0x092082a2, -+0x00040021, 0xffff3f08, 0xe023828d, 0x2074138d, 0x1063838d, 0x0e808309, 0x0e408209, 0x02741289, -+0x1540820a, 0x38a0820a, 0x808012c2, 0x0a9a108a, 0x20b4128a, 0x20b8128a, 0xc0c0c2d7, 0x08e0c2e2, -+0x0a608488, 0x10e0c2c8, 0x20b41288, 0x21008288, 0x18e0c2c8, 0x1d608488, 0x20e0c2c8, 0x28e0c2d8, -+0x15408209, 0x34608209, 0x804012c2, 0x099a1089, 0x20741289, 0x20781289, 0x30e0c2c9, 0x38e0c2cf, -+0x40e0c2d4, 0x48e0c2cc, 0xc000c3cd, 0x0ac0830f, 0x0ac08003, 0x20608411, 0x80e0820b, 0x01a0830e, -+0x1380b300, 0xdcff7f0b, 0x2020830c, 0xe03f830c, 0xc000c3dd, 0xbc238408, 0x800012c2, 0x089a1088, -+0x20341288, 0x20381288, 0x0300b200, 0x0d00401b, 0x07341888, 0x0020888e, 0x0420b800, 0x08004019, -+0x0800840b, 0x00040008, 0x18e0c2c8, 0x01a0830e, 0x04a0b300, 0xfdff7f09, 0x80e0820b, 0xfc3f8083, -+0x07341888, 0x08008408, 0xa06140ca, 0xc00062e3, 0x402062f3, 0xc080e2e3, 0xc080e2f3, 0x982244c8, -+0x88a0c5c8, 0x88a045c8, 0x0020b200, 0x05004013, 0x04604688, 0x88a08508, 0x80a0c5c8, 0x04604688, -+0x0020b200, 0x0c004002, 0xd822c4c0, 0xc04065e3, 0x406065f3, 0xc000e1e3, 0x806065e3, 0x4020e1f3, -+0xc06065f3, 0x8020e1e3, 0xc020e1f3, 0x07004010, 0x88228108, 0xc04065e3, 0x406065f3, 0xc000e1e3, -+0x4020e1f3, 0x88228108, 0x08d61082, 0x800092c2, 0x03f41689, 0x806140cb, 0x2922808c, 0x0334138c, -+0xccc042c8, 0xc900c2d1, 0x800017c8, 0x808096c8, 0xa8a045c8, 0x0880b400, 0x03004013, 0x00a18412, -+0xa0a045d2, 0x98a045c8, 0x0020b200, 0x05004013, 0x386140c9, 0x986140c8, 0x0820c2d2, 0x386140c9, -+0x01608209, 0xfe61b200, 0x0e004015, 0x3861c0c9, 0x00001088, 0x02204288, 0x0020b200, 0x05004003, -+0x986140ca, 0x28000040, 0xa06140c8, 0x986140ca, 0xc08042c8, 0x0880b400, 0xd8fe7f13, 0x00a08495, -+0x98a045cb, 0x00e0b200, 0xbafe7f03, 0x386140c9, 0xa06140c8, 0x60a08509, 0x48000040, 0xe03f808a, -+0x986140cb, 0x08e0c2d2, 0x386140cc, 0x0120830c, 0xaffe7f10, 0x3861c0cc, 0x406040c7, 0x486040d0, -+0x506040d1, 0x586040d2, 0x606040d3, 0x686040d4, 0x706040d5, 0x786040d6, 0x806040d7, 0x886040d8, -+0x906040d9, 0x986040da, 0xa06040db, 0xa86040dc, 0xb06040dd, 0xb86040de, 0xc06040df, 0x08e00180, -+0x80618001, 0x807f8001, 0xc040e0d3, 0x4060e0db, 0x00208490, 0x00208698, 0x00208080, 0x00208080, -+0x00e08192, 0x02000040, 0x00608091, 0x14e08110, 0x17208097, 0xc000f2d3, 0xc04060d3, 0x406060db, -+0x08a00080, 0x80608001, 0x407f8001, 0x4060e0d3, 0x8060e0db, 0x00208490, 0x00208698, 0x00208080, -+0x00208080, 0x00e08192, 0x02000040, 0x00608091, 0x40e08110, 0xc040e0d1, 0x37208097, 0x3860c0d7, -+0x00208490, 0x00e08597, 0x00208080, 0x00208080, 0x1f608290, 0x20b41291, 0x08638491, 0x00608092, -+0x00208293, 0xc000f2d1, 0x406060d3, 0x806060db, 0x08a00080, 0xc0608001, 0x407f8001, 0x4060e0d3, -+0x8060e0db, 0x00208490, 0x00208698, 0x00208080, 0x00208080, 0x00e08192, 0x02000040, 0x00608091, -+0x54e08110, 0xc040e0d1, 0x37208097, 0x3860c0d7, 0x00208490, 0x00e08597, 0x00208080, 0x00208080, -+0x1f608290, 0x20b41291, 0x08638491, 0x00608092, 0x00208293, 0x0ef41294, 0x0d208594, 0x17208095, -+0x17208096, 0x17208097, 0xc000f2d3, 0x406060d3, 0x806060db, 0x08a00080, 0xc0608001, 0x01208097, -+0xb0e3c0d7, 0x80a060d2, 0x98e28004, 0x98e2c0c0, 0x80a0c0c4, 0xc080c4c3, 0x01e0b400, 0x06004002, -+0x00a08490, 0x00e08097, 0x02208097, 0xb0e3c0d7, 0xd8e2d0d0, 0xd8e2c0d0, 0x03208097, 0xb0e3c0d7, -+0x00e08088, 0x0e004010, 0x00a060c3, 0x407f8001, 0x4060e0d3, 0x8060e0db, 0x00208490, 0x00208698, -+0x00208080, 0x00208080, 0x01208089, 0x8820c2c9, 0x00608091, 0x00e08197, 0x0020f2d3, 0x406060d3, -+0x806060db, 0x08e00180, 0xc0608001, }; -+#define threadcode_elan4_text_size 0x90c -+static uint32_t threadcode_elan4_data[] = { -+0}; -+#define threadcode_elan4_data_size 0x0 -+static uint32_t threadcode_elan4_rodata[] = { -+0}; -+#define threadcode_elan4_rodata_size 0x0 -+static EP_SYMBOL threadcode_elan4_symbols[] = { -+ {".thread_restart", 0x00000000f800000c}, -+ {".thread_start", 0x00000000f8000000}, -+ {"__bss_start", 0x00000000f810090c}, -+ {"_edata", 0x00000000f810090c}, -+ {"_end", 0x00000000f8100910}, -+ {"_etext", 0x00000000f800090c}, -+ {"_sdata", 0x00000000f810090c}, -+ {"_stext", 0x00000000f8000000}, -+ {"c_queue_rxd", 0x00000000f800087c}, -+ {"c_reschedule", 0x00000000f8000744}, -+ {"c_stall_thread", 0x00000000f80008cc}, -+ {"c_waitevent", 0x00000000f8000788}, -+ {"c_waitevent_interrupt", 0x00000000f80007f8}, -+ {"ep4_spinblock", 0x00000000f8000080}, -+ {"ep4comms_rcvr", 0x00000000f8000140}, -+ {0, 0}}; -+EP_CODE threadcode_elan4 = { -+ (unsigned char *) threadcode_elan4_text, -+ threadcode_elan4_text_size, -+ (unsigned char *) threadcode_elan4_data, -+ threadcode_elan4_data_size, -+ (unsigned char *) threadcode_elan4_rodata, -+ threadcode_elan4_rodata_size, -+ threadcode_elan4_symbols, -+}; -Index: linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/jtagdrv.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv.c 2005-06-01 23:12:54.692424968 -0400 -@@ -0,0 +1,451 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: jtagdrv.c,v 1.12 2003/06/07 16:02:35 david Exp $" -+/* $Source: /cvs/master/quadrics/jtagmod/jtagdrv.c,v $*/ -+ -+#include -+ -+#include "jtagdrv.h" -+#include -+ -+int -+jtagdrv_strobe_data (JTAG_DEV *dev, u_char data) -+{ -+ u_char dsr; -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_strobe_data: %s %s %s -> ", (data & LPT_DATA_TRST) ? "TRST" : "trst", -+ (data & LPT_DATA_TDI) ? "TDI" : "tdi", (data & LPT_DATA_TMS) ? "TMS" : "tms")); -+ -+ -+ LPT_WRITE_DATA (dev, data); DELAY(5); /* Drive NEW values on data wires */ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_TCLK); DELAY(5); /* Drive strobe low */ -+ LPT_READ_STAT (dev, dsr); DELAY(5); /* Sample TDI from ring */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* Drive strobe high */ -+ -+ PRINTF (DBG_ECPP, ("%s\n", (dsr & LPT_STAT_PE) ? "TDO" : "tdo")); -+ -+ return ((dsr & LPT_STAT_PE) ? 1 : 0); -+} -+ -+void -+jtagdrv_select_ring (JTAG_DEV *dev, u_int ring) -+{ -+ PRINTF (DBG_ECPP, ("jtagdrv_select_ring: ring=0x%x\n", ring)); -+ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* Drive strobe and TCLK high */ -+ LPT_WRITE_DATA (dev, ring); DELAY(5); /* Drive ring address */ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_RCLK); DELAY(5); /* Drive strobe low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* Drive strobe high */ -+} -+ -+void -+jtagdrv_reset (JTAG_DEV *dev) -+{ -+ register int i; -+ -+ for (i = 0; i < 5; i++) -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS); /* 5 clocks to Reset from any state */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Run-Test/Idle */ -+} -+ -+void -+jtagdrv_shift_ir (JTAG_DEV *dev, u_char *value, int nbits) -+{ -+ register int i; -+ register int bit; -+ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS); /* to Select DR-Scan */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS); /* to Select IR-Scan */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Capture-IR */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Shift-IR */ -+ -+ for (i = 0; i < nbits; i++) -+ { -+ /* strobe through the instruction bits, asserting TMS on the last bit */ -+ -+ if (i == (nbits-1)) -+ bit = jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS | (JTAG_BIT(value, i) ? LPT_DATA_TDI : 0)); -+ else -+ bit = jtagdrv_strobe_data (dev, LPT_DATA_TRST | (JTAG_BIT(value, i) ? LPT_DATA_TDI : 0)); -+ -+ if (bit) -+ JTAG_SET_BIT(value, i); -+ else -+ JTAG_CLR_BIT(value, i); -+ } -+ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS); /* to Update-IR */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Run-Test/Idle */ -+} -+ -+ -+void -+jtagdrv_shift_dr (JTAG_DEV *dev, u_char *value, int nbits) -+{ -+ register int i; -+ register int bit; -+ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS); /* to Select DR-Scan */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Capture-DR */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Shift-DR */ -+ -+ for (i = 0; i < nbits; i++) -+ { -+ /* strobe through the data bits, asserting TMS on the last bit */ -+ -+ if (i == (nbits-1)) -+ bit = jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS | (JTAG_BIT(value, i) ? LPT_DATA_TDI : 0)); -+ else -+ bit = jtagdrv_strobe_data (dev, LPT_DATA_TRST | (JTAG_BIT(value, i) ? LPT_DATA_TDI : 0)); -+ -+ if (bit) -+ JTAG_SET_BIT(value, i); -+ else -+ JTAG_CLR_BIT(value, i); -+ } -+ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST | LPT_DATA_TMS); /* to Update-DR */ -+ jtagdrv_strobe_data (dev, LPT_DATA_TRST); /* to Run-Test/Idle */ -+} -+ -+static int -+jtagdrv_i2c_start (JTAG_DEV *dev) -+{ -+ u_char dsr; -+ int i; -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_start\n")); -+ -+ /* Issue a stop sequence */ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(1); /* SCLK low */ -+ LPT_WRITE_DATA (dev, 0); DELAY(5); /* SDA low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* SCLK high */ -+ LPT_WRITE_DATA (dev, LPT_DATA_SDA); DELAY(5); /* SDA high */ -+ -+ /* sample the line to see if we're idle */ -+ LPT_READ_STAT (dev, dsr); /* sample SDA */ -+ if ((dsr & LPT_STAT_SDA) == 0) /* Cannot start if SDA already driven */ -+ { -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_start: cannot start - sda driven low\n")); -+ -+ for (i = 0; i < 16 ; i++) -+ { -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(5); /* SCLK low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* SCLK high */ -+ LPT_READ_STAT (dev, dsr); -+ -+ if (dsr & LPT_STAT_SDA) -+ { -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_start - stopped after %d clocks\n", i)); -+ break; -+ } -+ } -+ -+ if ((dsr & LPT_STAT_SDA) == 0) -+ { -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_start - cannot start - not idle\n")); -+ return (0); -+ } -+ -+ /* seen SDA float high, so issue a stop sequence */ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(1); /* SCLK low */ -+ LPT_WRITE_DATA (dev, 0); DELAY(5); /* SDA low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* SCLK high */ -+ LPT_WRITE_DATA (dev, LPT_DATA_SDA); DELAY(5); /* SDA high */ -+ } -+ -+ LPT_WRITE_DATA (dev, 0); DELAY(4); /* drive SDA low */ -+ return (1); -+} -+ -+static void -+jtagdrv_i2c_stop (JTAG_DEV *dev) -+{ -+ u_char dsr; -+ int i; -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_stop\n")); -+ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(1); /* SCLK low */ -+ LPT_WRITE_DATA (dev, 0); DELAY(5); /* SDA low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* SCLK high */ -+ LPT_WRITE_DATA (dev, LPT_DATA_SDA); DELAY(5); /* SDA high */ -+ -+ /* -+ * bug fix for temperature sensor chip -+ * if it's still driving SDA, then clock -+ * it until it stops driving it -+ */ -+ LPT_READ_STAT (dev, dsr); -+ if ((dsr & LPT_STAT_SDA) == 0) -+ { -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_stop - slave not stodeved\n")); -+ for (i = 0; i < 16 ; i++) -+ { -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(5); /* SCLK low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(5); /* SCLK high */ -+ LPT_READ_STAT (dev, dsr); -+ -+ if (dsr & LPT_STAT_SDA) -+ break; -+ } -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_stop - stodeved after %d clocks\n", i)); -+ } -+} -+ -+static int -+jtagdrv_i2c_strobe (JTAG_DEV *dev, u_char data) -+{ -+ u_char dsr; -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_strobe : %s", (data & LPT_DATA_SDA) ? "SDA" : "sda")); -+ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(1); /* SCLK low */ -+ LPT_WRITE_DATA (dev, data); DELAY(5); /* write data */ -+ LPT_WRITE_CTRL (dev, 0); /* SCLK high */ -+ LPT_READ_STAT (dev, dsr); DELAY(4); /* Sample SDA */ -+ -+ PRINTF (DBG_ECPP, (" -> %s\n", (dsr & LPT_STAT_SDA) ? "SDA" : "sda")); -+ -+ return ((dsr & LPT_STAT_SDA) ? 1 : 0); -+} -+ -+static int -+jtagdrv_i2c_get_ack (JTAG_DEV *dev) -+{ -+ u_char dsr; -+ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(1); /* SCLK low */ -+ LPT_WRITE_DATA (dev, LPT_DATA_SDA); DELAY(5); /* SDA high */ -+ LPT_WRITE_CTRL (dev, 0); /* SCLK high */ -+ LPT_READ_STAT (dev, dsr); DELAY(4); /* Sample SDA */ -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_get_ack -> %s\n", (dsr & LPT_STAT_SDA) ? "no ack" : "ack")); -+ -+ return ((dsr & LPT_STAT_SDA) ? 0 : 1); -+} -+ -+static int -+jtagdrv_i2c_drive_ack (JTAG_DEV *dev, int nack) -+{ -+ u_char dsr; -+ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_SCLK); DELAY(1); /* SCLK low */ -+ LPT_WRITE_DATA (dev, nack ? LPT_DATA_SDA : 0); DELAY(5); /* SDA low for ack, high for nack */ -+ LPT_WRITE_CTRL (dev, 0); /* SCLK high */ -+ LPT_READ_STAT (dev, dsr); DELAY(4); /* Sample SDA for ack */ -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_drive_ack %d -> %s\n", nack, (dsr & LPT_STAT_SDA) ? "done" : "more")); -+ -+ return ((dsr & LPT_STAT_SDA) ? 1 : 0); -+} -+ -+static void -+jtagdrv_i2c_shift_addr (JTAG_DEV *dev, u_int address, int readNotWrite) -+{ -+ register int i; -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_shift_addr: %x\n", address)); -+ -+ for (i = I2C_ADDR_LEN-1; i >= 0; i--) -+ jtagdrv_i2c_strobe (dev, (address & (1 << i)) ? LPT_DATA_SDA : 0); -+ -+ jtagdrv_i2c_strobe (dev, readNotWrite ? LPT_DATA_SDA : 0); -+} -+ -+static u_char -+jtagdrv_i2c_shift_data (JTAG_DEV *dev, u_char data) -+{ -+ register int i; -+ u_char val = 0; -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_shift_data : %02x\n", data)); -+ -+ for (i = I2C_DATA_LEN-1; i >= 0; i--) -+ if (jtagdrv_i2c_strobe (dev, data & (1 << i) ? LPT_DATA_SDA : 0)) -+ val |= (1 << i); -+ -+ PRINTF (DBG_ECPP, ("jtagdrv_i2c_shift_data : -> %02x\n", val)); -+ -+ return (val); -+} -+ -+int -+jtagdrv_i2c_write (JTAG_DEV *dev, u_int address, u_int count, u_char *data) -+{ -+ register int i; -+ -+ PRINTF (DBG_FN, ("jtagdrv_i2c_write: address=%x count=%d data=%02x\n", address, count, data[0])); -+ -+ if (! jtagdrv_i2c_start (dev)) -+ return (I2C_OP_NOT_IDLE); -+ -+ jtagdrv_i2c_shift_addr (dev, address, 0); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_write: no ack on address phase\n")); -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_NO_DEVICE); -+ } -+ -+ for (i = 0; i < count; i++) -+ { -+ jtagdrv_i2c_shift_data (dev, data[i]); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_write: no ack on data phase %d\n", i)); -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_WRITE_TO_BIG); -+ } -+ } -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_SUCCESS); -+} -+ -+int -+jtagdrv_i2c_read (JTAG_DEV *dev, u_int address, u_int count, u_char *data) -+{ -+ register int i; -+ -+ PRINTF (DBG_FN, ("jtagdrv_i2c_read: address=%x count=%d\n", address, count)); -+ -+ if (! jtagdrv_i2c_start (dev)) -+ return (I2C_OP_NOT_IDLE); -+ -+ jtagdrv_i2c_shift_addr (dev, address, 1); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_read: no ack on address phase\n")); -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_NO_DEVICE); -+ } -+ -+ for (i = 0; i < count; i++) -+ { -+ data[i] = jtagdrv_i2c_shift_data (dev, 0xff); -+ -+ jtagdrv_i2c_drive_ack (dev, (i == (count-1) ? 1 : 0)); -+ } -+ -+ jtagdrv_i2c_stop (dev); -+ -+ return (I2C_OP_SUCCESS); -+} -+ -+int -+jtagdrv_i2c_writereg (JTAG_DEV *dev, u_int address, u_int intaddress, u_int count, u_char *data) -+{ -+ register int i; -+ -+ PRINTF (DBG_FN, ("jtagdrv_i2c_writereg: address=%x count=%d\n", address, count)); -+ -+ if (! jtagdrv_i2c_start (dev)) -+ return (I2C_OP_NOT_IDLE); -+ -+ jtagdrv_i2c_shift_addr (dev, address, 0); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_writereg: no ack on address phase\n")); -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_NO_DEVICE); -+ } -+ -+ jtagdrv_i2c_shift_data (dev, intaddress); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_writereg: no ack on intaddress phase\n")); -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_NO_DEVICE); -+ } -+ -+ for (i = 0; i < count; i++) -+ { -+ jtagdrv_i2c_shift_data (dev, data[i]); -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_writedate: no ack on byte %d\n", i)); -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_WRITE_TO_BIG); -+ } -+ } -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_SUCCESS); -+} -+ -+int -+jtagdrv_i2c_readreg (JTAG_DEV *dev, u_int address, u_int intaddress, u_int count, u_char *data) -+{ -+ PRINTF (DBG_FN, ("jtagdrv_i2c_readreg: address=%x count=%d\n", address, count)); -+ -+ if (! jtagdrv_i2c_start (dev)) -+ return (I2C_OP_NOT_IDLE); -+ -+ jtagdrv_i2c_shift_addr (dev, address, 0); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_readreg: no ack on address phase\n")); -+ -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_NO_DEVICE); -+ } -+ -+ jtagdrv_i2c_shift_data (dev, intaddress); -+ -+ if (! jtagdrv_i2c_get_ack (dev)) -+ { -+ PRINTF (DBG_FN, ("jtagdrv_i2c_readreg: no ack on intaddress phase\n")); -+ jtagdrv_i2c_stop (dev); -+ return (I2C_OP_NO_DEVICE); -+ } -+ -+ jtagdrv_i2c_stop (dev); -+ -+ return (jtagdrv_i2c_read (dev, address, count, data)); -+} -+ -+void -+jtagdrv_i2c_clock_shift (JTAG_DEV *dev, u_int t, u_int n, u_int m) -+{ -+ int i; -+ -+ for (i = 2; i >= 0; i--) -+ { -+ LPT_WRITE_DATA (dev, ((t & (1 << i)) ? LPT_DATA_TDI : 0)); DELAY(1); /* clock low | data */ -+ LPT_WRITE_DATA (dev, ((t & (1 << i)) ? LPT_DATA_TDI : 0) | LPT_DATA_TMS); DELAY(1); /* clock high | data */ -+ } -+ -+ for (i = 1; i >= 0; i--) -+ { -+ LPT_WRITE_DATA (dev, ((n & (1 << i)) ? LPT_DATA_TDI : 0)); DELAY(1); /* clock low | data */ -+ LPT_WRITE_DATA (dev, ((n & (1 << i)) ? LPT_DATA_TDI : 0)| LPT_DATA_TMS); DELAY(1); /* clock high | data */ -+ } -+ -+ for (i = 6; i >= 0; i--) -+ { -+ LPT_WRITE_DATA (dev, ((m & (1 << i)) ? LPT_DATA_TDI : 0)); DELAY(1); /* clock low | data */ -+ LPT_WRITE_DATA (dev, ((m & (1 << i)) ? LPT_DATA_TDI : 0) | LPT_DATA_TMS); DELAY(1); /* clock high | data */ -+ } -+ -+ LPT_WRITE_DATA (dev, 0); DELAY(1); /* clock low | 0 */ -+ -+ LPT_WRITE_CTRL (dev, LPT_CTRL_TCLK); DELAY(1); /* strobe low */ -+ LPT_WRITE_CTRL (dev, 0); DELAY(1); /* strobe low */ -+} -+ -Index: linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/jtagdrv.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv.h 2005-06-01 23:12:54.692424968 -0400 -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __JTAGDRV_COMMON_H -+#define __JTAGDRV_COMMON_H -+ -+#ident "@(#)$Id: jtagdrv.h,v 1.5 2002/08/09 11:18:37 addy Exp $" -+/* $Source: /cvs/master/quadrics/jtagmod/jtagdrv.h,v $*/ -+ -+#include -+ -+/* include OS specific header file */ -+#if defined(LINUX) -+# include "jtagdrv_Linux.h" -+#elif defined(DIGITAL_UNIX) -+# include "jtagdrv_OSF1.h" -+#elif defined(QNX) -+# include "jtagdrv_QNX.h" -+#else -+# error cannot determint os type -+#endif -+ -+extern int jtagdebug; -+ -+#define DBG_CFG (1 << 0) -+#define DBG_OPEN (1 << 1) -+#define DBG_IOCTL (1 << 2) -+#define DBG_ECPP (1 << 3) -+#define DBG_FN (1 << 4) -+ -+#define DRIVER_NAME "jtag" -+ -+#if defined(LINUX) -+#define PRINTF(n,X) ((n) & jtagdebug ? (void) printk X : (void) 0) -+#define PRINTMSG(fmt, arg...) printk(KERN_INFO DRIVER_NAME ": " fmt, ##arg) -+#else -+#define PRINTF(n,X) ((n) & jtagdebug ? (void) printf X : (void) 0) -+#define PRINTMSG(M, A) printf ("jtag: " M, A) -+#endif -+ -+extern void jtagdrv_select_ring (JTAG_DEV *pp, u_int ring); -+extern void jtagdrv_reset (JTAG_DEV *pp); -+extern void jtagdrv_shift_ir (JTAG_DEV *pp, u_char *value, int nbits); -+extern void jtagdrv_shift_dr (JTAG_DEV *pp, u_char *value, int nbits); -+ -+extern int jtagdrv_i2c_write (JTAG_DEV *pp, u_int address, u_int count, u_char *data); -+extern int jtagdrv_i2c_read (JTAG_DEV *pp, u_int address, u_int count, u_char *data); -+extern int jtagdrv_i2c_writereg (JTAG_DEV *pp, u_int address, u_int intaddress, u_int count, u_char *data); -+extern int jtagdrv_i2c_readreg (JTAG_DEV *pp, u_int address, u_int intaddress, u_int count, u_char *data); -+extern void jtagdrv_i2c_clock_shift (JTAG_DEV *pp, u_int t, u_int n, u_int m); -+ -+ -+#endif /* __JTAGDRV_COMMON_H */ -Index: linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/jtagdrv_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv_Linux.c 2005-06-01 23:12:54.693424816 -0400 -@@ -0,0 +1,319 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* -+ * $Id: jtagdrv_Linux.c,v 1.18 2004/01/06 11:15:46 fabien Exp $ -+ * $Source: /cvs/master/quadrics/jtagmod/jtagdrv_Linux.c,v $ -+ */ -+ -+#include "jtagdrv.h" -+#include -+ -+#include -+#include -+ -+MODULE_AUTHOR("Quadrics Ltd."); -+MODULE_DESCRIPTION("JTAG Parallel port QsNet switch interface"); -+ -+MODULE_LICENSE("GPL"); -+ -+#define MAJOR_INSTANCE 0 /* 0 is dynamic assign of device major */ -+#define MAX_JTAG_DEV 4 -+ -+int jtag_major = MAJOR_INSTANCE; -+int jtagdebug = 0; -+MODULE_PARM(jtag_major, "i"); -+MODULE_PARM(jtagdebug, "i"); -+ -+JTAG_DEV jtag_devs[MAX_JTAG_DEV]; -+ -+int io[MAX_JTAG_DEV]= { 0, }; -+MODULE_PARM(io, "1-4i"); -+ -+ -+/* The fops functions */ -+int jtag_open(struct inode *, struct file *); -+int jtag_close(struct inode *, struct file *); -+int jtag_ioctl(struct inode *, struct file *, unsigned int, unsigned long ); -+ -+struct file_operations jtag_fops = { -+ ioctl: jtag_ioctl, -+ open: jtag_open, -+ release: jtag_close, -+}; -+ -+int -+jtag_probe(void) -+{ -+ int i=0; -+ int default_io = 1; -+ JTAG_DEV *dev; -+ unsigned char value=0xff; -+ -+ /* see if there are any user supplied io addr */ -+ for ( i = 0; i < MAX_JTAG_DEV; i++) { -+ if ( io[i] != 0x00) -+ default_io = 0; -+ jtag_devs[i].base = io[i]; -+ } -+ -+ if ( default_io ) { -+ jtag_devs[0].base = 0x3bc; -+ jtag_devs[1].base = 0x378; -+ jtag_devs[2].base = 0x278; -+ jtag_devs[3].base = 0x268; -+ } -+ -+ for ( i = 0 ; i < MAX_JTAG_DEV; i++) { -+ if ( jtag_devs[i].base == 0x3bc ) -+ jtag_devs[i].region = 3; -+ else -+ jtag_devs[i].region = 8; -+ jtag_devs[i].present = 0; -+ } -+ -+ -+ if( default_io ) -+ { -+ for( i = 0 ; i < MAX_JTAG_DEV; i++) { -+ dev=&(jtag_devs[i]); -+ if(dev->base && request_region(dev->base, dev->region, "jtag")) { -+ LPT_WRITE(dev, 0,0); -+ LPT_READ(dev, 0,value); -+ if ( value != 0xff) { -+ PRINTMSG("(%d , %d) present, io=0x%04lx\n",jtag_major,i,dev->base); -+ -+ dev->present=1; -+ } -+ else -+ release_region(dev->base, dev->region); -+ } -+ } -+ return 0; -+ } -+ else /* Force the region to be present, this makes the PCI parallel cards work */ -+ { -+ for( i = 0 ; i < MAX_JTAG_DEV; i++) -+ { -+ dev=&(jtag_devs[i]); -+ if(dev->base && request_region(dev->base, dev->region, "jtag") && (dev->base != 0)) -+ { -+ PRINTMSG("(%d , %d) forced by user, io=0x%04lx\n",jtag_major,i,dev->base); -+ dev->present=1; -+ } -+ else -+ { -+ if( dev->base != 0) -+ release_region(dev->base, dev->region); -+ } -+ } -+ return 0; -+ } -+} -+ -+int init_module(void) -+{ -+ int result,i; -+ result = register_chrdev(jtag_major, DRIVER_NAME, &jtag_fops); -+ if (result < 0) { -+ PRINTMSG("Couldn't register char device err == %d\n",jtag_major); -+ return -1; -+ } -+ -+ if ( jtag_major == 0 ) -+ jtag_major = result; -+ -+ for ( i = 0; i < MAX_JTAG_DEV; i++) { -+ jtag_devs[i].base=io[i]; -+ } -+ -+ jtag_probe(); -+ -+ PRINTMSG("Registered character device, major == %d\n",jtag_major); -+ return 0; -+} -+ -+void cleanup_module(void) -+{ -+ int i=0; -+ -+ for( i = 0; i < MAX_JTAG_DEV; i++) { -+ if( jtag_devs[i].present) -+ release_region(jtag_devs[i].base, jtag_devs[i].region); -+ } -+ -+ unregister_chrdev(jtag_major, DRIVER_NAME); -+ PRINTMSG("Unloaded char device\n"); -+} -+ -+ -+int -+jtag_open (struct inode *inode, struct file *filp) -+{ -+ int unit = MINOR(inode->i_rdev); -+ JTAG_DEV *dev = &jtag_devs[unit]; -+ -+ if (unit < 0 || unit > MAX_JTAG_DEV || !dev->present) -+ return (-ENXIO); -+ -+ /* -+ * Only allow a single open at a time -+ */ -+ if (dev->open) -+ return (-EBUSY); -+ dev->open = 1; -+ -+ /* -+ * Initialise the hardware registers -+ */ -+ -+ LPT_WRITE (dev, LPT_CTRL, 0); -+ DELAY(50); -+ LPT_WRITE (dev, LPT_CTRL, LPT_CTRL_INIT); -+ -+ MOD_INC_USE_COUNT; -+ -+ return (0); -+} -+ -+int -+jtag_close(struct inode *inode, struct file *filp) -+{ -+ -+ int unit = MINOR(inode->i_rdev); -+ JTAG_DEV *dev = &jtag_devs[unit]; -+ -+ if (unit < 0 || unit > MAX_JTAG_DEV || !dev->present) -+ return (-ENXIO); -+ -+ dev->open = 0; -+ -+ MOD_DEC_USE_COUNT; -+ -+ return (0); -+} -+ -+int -+jtag_ioctl (struct inode *inode, struct file *filp, unsigned int io_cmd, unsigned long io_data) -+{ -+ int unit = MINOR(inode->i_rdev); -+ JTAG_DEV *dev = &jtag_devs[unit]; -+ JTAG_RESET_ARGS *resetargs; -+ JTAG_SHIFT_ARGS *shiftargs; -+ I2C_ARGS *i2cargs; -+ I2C_CLOCK_SHIFT_ARGS *clockargs; -+ u_char *buf; -+ int freq; -+ -+ if (unit < 0 || unit > MAX_JTAG_DEV || !dev->present) -+ return (-ENXIO); -+ -+ PRINTF (DBG_IOCTL, ("jtag_ioctl: device %d cmd=%x\n", unit, io_cmd)); -+ -+ switch (io_cmd) -+ { -+ case JTAG_RESET: -+ resetargs = (JTAG_RESET_ARGS *) io_data; -+ -+ if (! VALID_JTAG_RING (resetargs->ring)) -+ return (-EINVAL); -+ -+ jtagdrv_select_ring (dev, resetargs->ring); -+ jtagdrv_reset (dev); -+ return (0); -+ -+ case JTAG_SHIFT_IR: -+ case JTAG_SHIFT_DR: -+ shiftargs = (JTAG_SHIFT_ARGS *) io_data; -+ -+ if (! VALID_JTAG_RING (shiftargs->ring) || shiftargs->nbits > (JTAG_MAX_DATA_LEN*JTAG_MAX_CHIPS)) { -+ return (-EFAULT); -+ } -+ -+ buf = (u_char *) kmalloc (JTAG_NBYTES(shiftargs->nbits), GFP_KERNEL); -+ -+ if (buf == (u_char *) NULL) -+ return (-ENOMEM); -+ -+ if (copy_from_user (buf, shiftargs->value, JTAG_NBYTES(shiftargs->nbits))) -+ { -+ kfree(buf); -+ return (-EFAULT); -+ } -+ -+ -+ jtagdrv_select_ring (dev, shiftargs->ring); -+ -+ if (io_cmd == JTAG_SHIFT_IR) -+ jtagdrv_shift_ir (dev, buf, shiftargs->nbits); -+ else -+ jtagdrv_shift_dr (dev, buf, shiftargs->nbits); -+ -+ if (copy_to_user (shiftargs->value, buf, JTAG_NBYTES (shiftargs->nbits))) -+ { -+ kfree (buf); -+ return (-EFAULT); -+ } -+ -+ kfree (buf); -+ return (0); -+ -+ case I2C_WRITE: -+ case I2C_READ: -+ case I2C_WRITEREG: -+ case I2C_READREG: -+ i2cargs = (I2C_ARGS *) io_data; -+ -+ if (! VALID_I2C_RING(i2cargs->ring) || i2cargs->count > I2C_MAX_DATA_LEN) -+ return (-EFAULT); -+ -+ jtagdrv_select_ring (dev, RING_I2C_BIT | i2cargs->ring); -+ switch (io_cmd) -+ { -+ case I2C_WRITE: -+ i2cargs->ok = jtagdrv_i2c_write (dev, i2cargs->device, i2cargs->count, i2cargs->data); -+ break; -+ -+ case I2C_READ: -+ i2cargs->ok = jtagdrv_i2c_read (dev, i2cargs->device, i2cargs->count, i2cargs->data); -+ break; -+ -+ case I2C_WRITEREG: -+ i2cargs->ok = jtagdrv_i2c_writereg (dev, i2cargs->device, i2cargs->reg, i2cargs->count, i2cargs->data); -+ break; -+ -+ case I2C_READREG: -+ i2cargs->ok = jtagdrv_i2c_readreg (dev, i2cargs->device, i2cargs->reg, i2cargs->count, i2cargs->data); -+ break; -+ } -+ return (0); -+ -+ case I2C_CLOCK_SHIFT: -+ clockargs = (I2C_CLOCK_SHIFT_ARGS *) io_data; -+ -+ freq = (10 * clockargs->m / (1 << (((clockargs->n + 1) & 3)))); -+ -+ /* validate the value, and initialise the ring */ -+ if (clockargs->t != 0 || clockargs->n > 3 || clockargs->m > 127) -+ return (-EINVAL); -+ -+ jtagdrv_select_ring (dev, RING_I2C_BIT | RING_CLOCK_SHIFT); -+ jtagdrv_i2c_clock_shift (dev, clockargs->t, clockargs->n, clockargs->m); -+ jtagdrv_select_ring (dev, 0); -+ return (0); -+ -+ default: -+ return (-EINVAL); -+ } -+ return (-EINVAL); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv_Linux.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/jtagdrv_Linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/jtagdrv_Linux.h 2005-06-01 23:12:54.693424816 -0400 -@@ -0,0 +1,174 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: jtagdrv_Linux.h,v 1.3 2002/08/09 11:18:37 addy Exp $" -+/* $Source: /cvs/master/quadrics/jtagmod/jtagdrv_Linux.h,v $*/ -+ -+#ifndef __JTAGDRV_LINUX_H -+#define __JTAGDRV_LINUX_H -+ -+#include -+#include -+ -+typedef struct jtag_dev -+{ -+ unsigned long base; -+ int region; -+ -+ u_int present:1; -+ u_int open:1; -+} JTAG_DEV; -+ -+/* -+** -+** Hardware Defines -+** -+*/ -+ -+/* -+ * Assume that bit 4 of the Control Register is set to 1 (by default) -+ * to enable the printer port (CS3). -+ * -+ * The default base address is 3BC-3BF. -+ */ -+ -+#define LPT0 0x3BC /* CSR Base Address - note this can -+ * change depending on the setting -+ * in the Control Register 0. -+ * -+ * LPT1 0x378 -+ * LPT2 0x278 -+ * LPT3 0x268 -+ */ -+ -+/* -+ * Register offsets from the port base address -+ */ -+ -+#define LPT_REGISTER_0 0 -+#define LPT_REGISTER_1 1 -+#define LPT_REGISTER_2 2 -+#define LPT_REGISTER_3 0x400 -+#define LPT_REGISTER_4 0x401 -+#define LPT_REGISTER_5 0x402 -+ -+/* -+ * Chip control registers -+ */ -+ /* Base address for Super I/O National*/ -+ -+#define SIO_BASE_ADDR 0x26e /* Semiconductor PC87332VLJ combo-chip*/ -+#define CR4_REG 0x04 /* index 4, printer control reg 4 */ -+ -+#define LPT_EPP 0x01 /* Enable bit for epp */ -+#define LPT_ECP 0x04 /* Enable bit for ecp */ -+ -+/* -+ * Registers for use with centronics, nibble and byte modes. -+ */ -+ -+#define LPT_DATA LPT_REGISTER_0 /* line printer port data */ -+#define LPT_STAT LPT_REGISTER_1 /* LPT port status */ -+#define LPT_CTRL LPT_REGISTER_2 /* LPT port control */ -+ -+/* -+ * Registers for use with ECP mode. -+ */ -+ -+#define LPT_DFIFO LPT_REGISTER_3 /* r/w fifo register */ -+#define LPT_CFGB LPT_REGISTER_4 /* Configuration B */ -+#define LPT_ECR LPT_REGISTER_5 /* Exteded control */ -+ -+/* -+ * Bit assignments for ECR register. -+ */ -+ -+ /* Bits 0-4 */ -+ -+#define LPT_ECR_EMPTY 0x01 /* FIFO is empty */ -+#define LPT_ECR_FULL 0x02 /* FIFO is full */ -+#define LPT_ECR_SERV 0x04 /* Service bit */ -+#define LPT_ECR_DMA 0x08 /* DMA enable */ -+#define LPT_ECR_nINTR 0x10 /* Interrupt disable */ -+ -+ /* -+ * Bits 5-7 are ECR modes. -+ */ -+ -+#define LPT_ECR_PAR 0x20 /* Parallel port FIFO mode */ -+#define LPT_ECR_ECP 0x60 /* ECP mode */ -+#define LPT_ECR_CFG 0xE0 /* Configuration mode */ -+#define LPT_ECR_CLEAR ~0xE0 /* Cear mode bits */ -+ -+/* -+ * Bit assignments for the parallel port STATUS register: -+ */ -+ -+#define LPT_STAT_BIT0 0X1 /* Reserved. Bit always set. */ -+#define LPT_STAT_BIT1 0X2 /* Reserved. Bit always set. */ -+#define LPT_STAT_IRQ 0x4 /* interrupt status bit */ -+#define LPT_STAT_ERROR 0x8 /* set to 0 to indicate error */ -+#define LPT_STAT_SLCT 0x10 /* status of SLCT lead from printer */ -+#define LPT_STAT_PE 0x20 /* set to 1 when out of paper */ -+#define LPT_STAT_ACK 0x40 /* acknowledge - set to 0 when ready */ -+#define LPT_STAT_nBUSY 0x80 /* busy status bit, 0=busy, 1=ready */ -+ -+/* -+ * Bit assignments for the parallel port CONTROL register: -+ */ -+ -+#define LPT_CTRL_nSTROBE 0x1 /* Printer Strobe Control */ -+#define LPT_CTRL_nAUTOFD 0x2 /* Auto Feed Control */ -+#define LPT_CTRL_INIT 0x4 /* Initialize Printer Control */ -+#define LPT_CTRL_nSLCTIN 0x8 /* 0=select printer, 1=not selected */ -+#define LPT_CTRL_IRQ 0x10 /* Interrupt Request Enable Control */ -+#define LPT_CTRL_DIR 0x20 /* Direction control */ -+#define LPT_CTRL_BIT6 0X40 /* Reserved. Bit always set. */ -+#define LPT_CTRL_BIT7 0X80 /* Reserved. Bit always set. */ -+ -+ -+#define LPT_WRITE(dev, regname, value) do { outb(value, (dev)->base + regname); } while (0) -+#define LPT_READ(dev, regname,value) do { value = inb((dev)->base + regname); } while (0) -+ -+ -+ -+/* Standard register access macros */ -+#define LPT_WRITE_CTRL(dev, value) LPT_WRITE(dev, LPT_CTRL, LPT_CTRL_INIT | value) -+#define LPT_WRITE_DATA(dev, value) LPT_WRITE(dev, LPT_DATA, value) -+#define LPT_READ_STAT(dev, value) LPT_READ(dev, LPT_STAT, value) -+ -+/* -+ * The jtag signals are connected to the parallel port as follows : -+ * -+ * TRST bit 0 -+ * TDI bit 1 -+ * TMS bit 2 -+ * TCLK AFX -+ * TDO PE -+ */ -+#define LPT_DATA_TRST 1 -+#define LPT_DATA_TDI 2 -+#define LPT_DATA_TMS 4 -+#define LPT_CTRL_TCLK LPT_CTRL_nAUTOFD -+#define LPT_STAT_TDO LPT_STAT_PE -+ -+/* -+ * The I2C signals are connected as follows : -+ */ -+#define LPT_DATA_SDA 2 -+#define LPT_CTRL_SCLK LPT_CTRL_nAUTOFD -+#define LPT_STAT_SDA LPT_STAT_PE -+ -+/* -+ * The ring selection signals are as follows : -+ * addr bit 0-7 -+ * clock nSLCTIN -+ */ -+#define LPT_CTRL_RCLK LPT_CTRL_nSLCTIN -+ -+ -+#endif /* __JTAGDRV_LINUX_H */ -Index: linux-2.4.21/drivers/net/qsnet/jtag/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/Makefile 2005-06-01 23:12:54.694424664 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/jtag/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/jtag/Makefile -+# -+ -+list-multi := jtag.o -+jtag-objs := jtagdrv_Linux.o jtagdrv.o -+export-objs := -+obj-$(CONFIG_JTAG) := jtag.o -+ -+jtag.o : $(jtag-objs) -+ $(LD) -r -o $@ $(jtag-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/jtag/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/Makefile.conf 2005-06-01 23:12:54.694424664 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = jtag.o -+MODULENAME = jtag -+KOBJFILES = jtagdrv_Linux.o jtagdrv.o -+EXPORT_KOBJS = -+CONFIG_NAME = CONFIG_JTAG -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/jtag/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/jtag/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/jtag/quadrics_version.h 2005-06-01 23:12:54.694424664 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/Makefile 2005-06-01 23:12:54.695424512 -0400 -@@ -0,0 +1,17 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2003 Quadrics Ltd. -+# -+# File: driver/net/qsnet/Makefile -+# -+ -+subdir-$(CONFIG_QSNET) += qsnet elan -+subdir-$(CONFIG_ELAN3) += elan3 -+subdir-$(CONFIG_ELAN4) += elan4 -+subdir-$(CONFIG_EP) += ep -+subdir-$(CONFIG_EIP) += eip -+subdir-$(CONFIG_RMS) += rms -+subdir-$(CONFIG_JTAG) += jtag -+ -+include $(TOPDIR)/Rules.make -Index: linux-2.4.21/drivers/net/qsnet/qsnet/debug.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/debug.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/debug.c 2005-06-01 23:12:54.696424360 -0400 -@@ -0,0 +1,583 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: debug.c,v 1.21 2004/08/19 08:09:57 david Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/debug.c,v $ */ -+ -+#include -+#include -+#include -+ -+caddr_t qsnet_debug_buffer_ptr = NULL; -+int qsnet_debug_front = 0; -+int qsnet_debug_back = 0; -+int qsnet_debug_lost_lines = 0; -+int qsnet_debug_disabled = 0; -+ -+int qsnet_debug_line_size = 256; -+int qsnet_debug_num_lines = 8192; -+ -+int qsnet_assfail_mode = 1; /* default to BUG() */ -+ -+int qsnet_debug_running = 0; -+int kqsnet_debug_running = 0; -+ -+static spinlock_t qsnet_debug_lock; -+static kcondvar_t qsnet_debug_wait; -+static char qsnet_debug_buffer_space[8192]; -+ -+#define QSNET_DEBUG_PREFIX_MAX_SIZE 32 -+#define QSNET_DEBUG_MAX_WORDWRAP 15 -+ -+/* must be larger than QSNET_DEBUG_PREFIX_MAX_SIZE + QSNET_DEBUG_MAX_WORDWRAP + 2 */ -+#if defined(DIGITAL_UNIX) -+#define QSNET_DEBUG_CONSOLE_WIDTH 80 -+#elif defined(LINUX) -+#define QSNET_DEBUG_CONSOLE_WIDTH 128 -+#endif -+ -+#define isspace(CH) ((CH==' ') | (CH=='\t') | (CH=='\n')) -+ -+#ifdef LINUX -+#define ALLOC_DEBUG_BUFFER(ptr) do { (ptr) = (void *)__get_free_pages (GFP_KERNEL, get_order (qsnet_debug_num_lines * qsnet_debug_line_size)); } while (0) -+#define FREE_DEBUG_BUFFER(ptr) free_pages ((unsigned long) ptr, get_order (qsnet_debug_num_lines * qsnet_debug_line_size)) -+#else -+#define ALLOC_DEBUG_BUFFER(ptr) KMEM_ALLOC (ptr, caddr_t, qsnet_debug_num_lines * qsnet_debug_line_size, 1) -+#define FREE_DEBUG_BUFFER(ptr) KMEM_FREE (ptr, qsnet_debug_num_lines * qsnet_debug_line_size) -+#endif -+ -+void -+qsnet_debug_init () -+{ -+ spin_lock_init (&qsnet_debug_lock); -+ kcondvar_init (&qsnet_debug_wait); -+ -+ qsnet_debug_front = 0; -+ qsnet_debug_back = 0; -+ qsnet_debug_lost_lines = 0; -+ -+ if (qsnet_debug_line_size < (QSNET_DEBUG_PREFIX_MAX_SIZE + QSNET_DEBUG_MAX_WORDWRAP + 2)) -+ qsnet_debug_line_size = 256; -+ -+ qsnet_debug_running = 1; -+ -+ qsnet_proc_register_int (qsnet_procfs_config, "assfail_mode", &qsnet_assfail_mode, 0); -+} -+ -+void -+qsnet_debug_fini() -+{ -+ if (!qsnet_debug_running) return; -+ -+ remove_proc_entry ("assfail_mode", qsnet_procfs_config); -+ -+ spin_lock_destroy (&qsnet_debug_lock); -+ kcondvar_destroy (&qsnet_debug_wait); -+ -+ if (qsnet_debug_buffer_ptr) -+ FREE_DEBUG_BUFFER (qsnet_debug_buffer_ptr); -+ -+ qsnet_debug_buffer_ptr = NULL; -+ qsnet_debug_lost_lines = 0; -+ qsnet_debug_running = 0; -+} -+ -+void -+qsnet_debug_disable(int val) -+{ -+ qsnet_debug_disabled = val; -+} -+ -+void -+qsnet_debug_alloc() -+{ -+ caddr_t ptr; -+ unsigned long flags; -+ -+ if (!qsnet_debug_running) return; -+ -+ if (qsnet_debug_buffer_ptr == NULL) -+ { -+ ALLOC_DEBUG_BUFFER (ptr); -+ -+ if (ptr != NULL) -+ { -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ if (qsnet_debug_buffer_ptr == NULL) -+ { -+ qsnet_debug_buffer_ptr = ptr; -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+ } -+ else -+ { -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+ -+ FREE_DEBUG_BUFFER (ptr); -+ } -+ } -+ } -+ -+} -+ -+static void -+qsnet_prefix_debug(unsigned int mode, char *prefix, char *buffer) -+{ -+ /* assumes caller has lock */ -+ -+ int prefixlen = strlen(prefix); -+ char pref[QSNET_DEBUG_PREFIX_MAX_SIZE]; -+ int prefix_done = 0; -+ -+ if (!qsnet_debug_running) return; -+ -+ if (qsnet_debug_disabled) -+ return; -+ -+ if (prefixlen >= QSNET_DEBUG_PREFIX_MAX_SIZE) -+ { -+ strncpy(pref,prefix,QSNET_DEBUG_PREFIX_MAX_SIZE -2); -+ strcpy (&pref[QSNET_DEBUG_PREFIX_MAX_SIZE-5],"... "); -+ -+ prefix = pref; -+ prefixlen = strlen(prefix); -+ } -+ -+#ifdef CONFIG_MPSAS -+ { -+ char *p; -+#define TRAP_PUTCHAR_B (0x17a - 256) -+#define SAS_PUTCHAR(c) do {\ -+ register int o0 asm ("o0") = (c);\ -+\ -+ asm volatile ("ta %0; nop" \ -+ : /* no outputs */\ -+ : /* inputs */ "i" (TRAP_PUTCHAR_B), "r" (o0)\ -+ : /* clobbered */ "o0");\ -+\ -+ if (o0 == '\n') {\ -+ o0 = '\r';\ -+\ -+ asm volatile ("ta %0; nop" \ -+ : /* no outputs */\ -+ : /* inputs */ "i" (TRAP_PUTCHAR_B), "r" (o0)\ -+ : /* clobbered */ "o0");\ -+ }\ -+ } while(0) -+ -+ for (p = prefix; *p; p++) -+ SAS_PUTCHAR (*p); -+ -+ for (p = buffer; *p; p++) -+ SAS_PUTCHAR (*p); -+ } -+#else -+ if (mode & QSNET_DEBUG_BUFFER) -+ { -+ if (qsnet_debug_buffer_ptr == NULL) -+ qsnet_debug_lost_lines++; -+ else -+ { -+ caddr_t base = &qsnet_debug_buffer_ptr[qsnet_debug_line_size * qsnet_debug_back]; -+ caddr_t lim = base + qsnet_debug_line_size - 2; -+ caddr_t p; -+ -+ p = buffer; -+ prefix_done = 0; -+ while (*p) -+ { -+ /* sort out prefix */ -+ if ( prefix_done++ ) -+ { -+ int i; -+ for(i=0;i 0 ) -+ { -+ int i; -+ for(i=0;i remaining) len = remaining; -+ -+ strncpy(line, p, len); -+ line[len] = 0; -+ p += len; -+ -+ /* word wrap */ -+ if ((len == remaining) && *p && !isspace(*p)) -+ { -+ /* lets see if we can back track and find a white space to break on */ -+ char * ptr = &line[len-1]; -+ int count = 1; -+ -+ while ( ( !isspace(*ptr) ) && ( count < QSNET_DEBUG_MAX_WORDWRAP )) -+ { -+ count++; -+ ptr--; -+ } -+ -+ if ( isspace(*ptr) ) -+ { -+ /* found somewhere to wrap to */ -+ p -= (count-1); /* need to loose the white space */ -+ len -= count; -+ } -+ } -+ -+ if (line[len-1] != '\n' ) -+ { -+ line[len] = '\n'; -+ line[len+1] = 0; -+ } -+ -+ /* we put a \n in so dont need another one next */ -+ if ( *p == '\n') -+ p++; -+ -+#if defined(DIGITAL_UNIX) -+ { -+ char *pr; -+ -+ for (pr = pref; *pr; pr++) -+ cnputc (*pr); -+ -+ for (pr = line; *pr; pr++) -+ cnputc (*pr); -+ } -+#elif defined(LINUX) -+ printk("%s%s",pref,line); -+#endif -+ } -+ } -+#endif /* CONFIG_MPSAS */ -+} -+ -+void -+qsnet_vdebugf (unsigned int mode, char *prefix, char *fmt, va_list ap) -+{ -+ unsigned long flags; -+ -+ if (!qsnet_debug_running) return; -+ -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ -+ qsnet_debug_buffer_space[0] = '\0'; -+ -+#if defined(DIGITAL_UNIX) -+ prf (qsnet_debug_buffer_space+strlen(qsnet_debug_buffer_space), NULL, fmt, ap); -+#elif defined(LINUX) -+ vsprintf (qsnet_debug_buffer_space+strlen(qsnet_debug_buffer_space), fmt, ap); -+#endif -+ -+ if (prefix == NULL) -+ printk ("qsnet_vdebugf: prefix==NULL\n"); -+ else -+ qsnet_prefix_debug(mode, prefix, qsnet_debug_buffer_space); -+ -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+} -+ -+void kqsnet_debugf(char *fmt,...) -+{ -+ if ( kqsnet_debug_running ) { -+ va_list ap; -+ char string[20]; -+ -+ sprintf (string, "mm=%p:", current->mm); -+ va_start(ap, fmt); -+ qsnet_vdebugf(QSNET_DEBUG_BUFFER, string, fmt, ap); -+ va_end(ap); -+ } -+} -+void -+qsnet_debugf(unsigned int mode, char *fmt,...) -+{ -+ va_list ap; -+ unsigned long flags; -+ -+ if (!qsnet_debug_running) return; -+ -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ -+ qsnet_debug_buffer_space[0] = '\0'; -+ -+ va_start (ap, fmt); -+#if defined(DIGITAL_UNIX) -+ prf (qsnet_debug_buffer_space+strlen(qsnet_debug_buffer_space), NULL, fmt, ap); -+#elif defined(LINUX) -+ vsprintf (qsnet_debug_buffer_space+strlen(qsnet_debug_buffer_space), fmt, ap); -+#endif -+ va_end (ap); -+ -+ qsnet_prefix_debug(mode, "", qsnet_debug_buffer_space); -+ -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+} -+ -+int -+qsnet_debug_buffer (caddr_t ubuffer, int len) -+{ -+ caddr_t buffer, ptr, base; -+ int remain, len1; -+ unsigned long flags; -+ static char qsnet_space[65536]; -+ -+ if (!qsnet_debug_running) return (0); -+ -+ if (len < qsnet_debug_line_size) -+ return (-1); -+ -+ if (len > (qsnet_debug_line_size * qsnet_debug_num_lines)) -+ len = qsnet_debug_line_size * qsnet_debug_num_lines; -+ -+ if ( len > 65536 ) { -+ KMEM_ZALLOC (buffer, caddr_t, len, 1); -+ } else -+ buffer = qsnet_space; -+ -+ if (buffer == NULL) -+ return (-1); -+ -+ if (qsnet_debug_buffer_ptr == NULL) -+ qsnet_debug_alloc(); -+ -+ if (qsnet_debug_buffer_ptr == NULL) -+ { -+ if ( len > 65536 ) -+ KMEM_FREE (buffer, len); -+ return (-1); -+ } -+ -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ -+ while (!qsnet_debug_lost_lines && (qsnet_debug_back == qsnet_debug_front)) -+ if (kcondvar_waitsig (&qsnet_debug_wait, &qsnet_debug_lock, &flags) == 0) -+ break; -+ -+ ptr = buffer; -+ remain = len; -+ -+ if (qsnet_debug_lost_lines) -+ { -+ qsnet_debug_lost_lines = 0; -+ strcpy (ptr, "Debug Buffer has overflowed!!\n"); -+ len1 = strlen (ptr); -+ -+ remain -= len1; -+ ptr += len1; -+ } -+ -+ while (qsnet_debug_front != qsnet_debug_back) -+ { -+ /* copy the line from DebugFront */ -+ base = &qsnet_debug_buffer_ptr[qsnet_debug_front*qsnet_debug_line_size]; -+ -+ len1 = strlen (base); -+ -+ if (len1 > remain) -+ break; -+ -+ bcopy (base, ptr, len1); -+ -+ ptr += len1; -+ remain -= len1; -+ -+ qsnet_debug_front = (++qsnet_debug_front == qsnet_debug_num_lines) ? 0 : qsnet_debug_front; -+ } -+ -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+ -+ len1 = ptr - buffer; -+ -+ if (len1 != 0 && copyout (buffer, ubuffer, len1)) -+ len1 = -1; -+ -+ if ( len > 65536 ) -+ KMEM_FREE (buffer, len); -+ -+ return (len1); -+} -+ -+void -+qsnet_debug_buffer_on() -+{ -+ if (qsnet_debug_buffer_ptr == NULL) -+ qsnet_debug_alloc(); -+} -+ -+void -+qsnet_debug_buffer_clear() -+{ -+ unsigned long flags; -+ -+ qsnet_debug_buffer_on(); -+ -+ if (qsnet_debug_buffer_ptr != NULL){ -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ qsnet_debug_front = 0; -+ qsnet_debug_back = 0; -+ qsnet_prefix_debug(QSNET_DEBUG_BUFFER,"Clear",""); -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+ } -+} -+ -+void -+qsnet_debug_buffer_mark(char *str) -+{ -+ unsigned long flags; -+ -+ qsnet_debug_buffer_on(); -+ -+ if (qsnet_debug_buffer_ptr != NULL) { -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ qsnet_prefix_debug(QSNET_DEBUG_BUFFER,"Mark",str); -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+ } -+} -+int -+qsnet_debug_dump () -+{ -+ unsigned long flags; -+ -+ if (!qsnet_debug_running) return (0); -+ -+ if (qsnet_debug_buffer_ptr == NULL) -+ qsnet_debug_alloc(); -+ -+ if (qsnet_debug_buffer_ptr == NULL) -+ return (-1); -+ -+ spin_lock_irqsave (&qsnet_debug_lock, flags); -+ -+ while (qsnet_debug_front != qsnet_debug_back) -+ { -+ printk ("%s", &qsnet_debug_buffer_ptr[qsnet_debug_front*qsnet_debug_line_size]); -+ -+ qsnet_debug_front = (++qsnet_debug_front == qsnet_debug_num_lines) ? 0 : qsnet_debug_front; -+ } -+ -+ if (qsnet_debug_lost_lines) -+ printk ("\n**** Debug buffer has lost %d lines\n****\n",qsnet_debug_lost_lines); -+ -+ spin_unlock_irqrestore (&qsnet_debug_lock, flags); -+ -+ return (0); -+} -+ -+int -+qsnet_debug_kmem (void *handle) -+{ -+ if (!qsnet_debug_running) return (0); -+ -+#ifdef KMEM_DEBUG -+ qsnet_kmem_display(handle); -+#endif -+ return (0); -+} -+ -+int -+qsnet_assfail (char *ex, const char *func, char *file, int line) -+{ -+ qsnet_debugf (QSNET_DEBUG_BUFFER, "qsnet: assertion failure: %s, function: %s, file %s, line: %d\n", ex, func, file, line); -+ -+ printk (KERN_EMERG "qsnet: assertion failure: %s, function: %s, file %s, line: %d\n", ex, func, file, line); -+ -+ if (panicstr) -+ return (0); -+ -+ if (qsnet_assfail_mode & 1) /* return to BUG() */ -+ return 1; -+ -+ if (qsnet_assfail_mode & 2) -+ panic ("qsnet: assertion failure: %s, function: %s, file %s, line: %d\n", ex, func, file, line); -+ if (qsnet_assfail_mode & 4) -+ qsnet_debug_disable (1); -+ -+ return 0; -+ -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/qsnet/i686_mmx.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/i686_mmx.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/i686_mmx.c 2005-06-01 23:12:54.696424360 -0400 -@@ -0,0 +1,99 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: i686_mmx.c,v 1.11 2004/01/05 12:08:25 mike Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/i686_mmx.c,v $*/ -+ -+#include -+ -+#if defined(LINUX_I386) -+ -+#include -+#include -+#include -+#include -+ -+int mmx_disabled = 0; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+/* These functions are lifted from arch/i386/kernel/i387.c -+ * and MUST be kept in step with the kernel (currently 2.4.17) -+ * alternatively we should export the kernel_fpu_begin() function -+ */ -+static inline void __save_init_fpu( struct task_struct *tsk ) -+{ -+ if ( cpu_has_fxsr ) { -+ asm volatile( "fxsave %0 ; fnclex" -+ : "=m" (tsk->thread.i387.fxsave) ); -+ } else { -+ asm volatile( "fnsave %0 ; fwait" -+ : "=m" (tsk->thread.i387.fsave) ); -+ } -+ tsk->flags &= ~PF_USEDFPU; -+} -+#if defined(MODULE) -+void kernel_fpu_begin(void) -+{ -+ struct task_struct *tsk = current; -+ -+ if (tsk->flags & PF_USEDFPU) { -+ __save_init_fpu(tsk); -+ return; -+ } -+ clts(); -+} -+#endif -+#endif -+ -+extern inline int -+mmx_preamble(void) -+{ -+ if (mmx_disabled || in_interrupt()) -+ return (0); -+ -+ kernel_fpu_begin(); -+ -+ return (1); -+} -+ -+extern inline void -+mmx_postamble(void) -+{ -+ kernel_fpu_end(); -+} -+ -+extern u64 -+qsnet_readq (volatile u64 *ptr) -+{ -+ u64 value; -+ -+ if (! mmx_preamble()) -+ value = *ptr; -+ else -+ { -+ asm volatile ("movq (%0), %%mm0\n" -+ "movq %%mm0, (%1)\n" -+ : : "r" (ptr), "r" (&value) : "memory"); -+ mmx_postamble(); -+ } -+ return (value); -+} -+ -+void -+qsnet_writeq(u64 value, volatile u64 *ptr) -+{ -+ if (! mmx_preamble()) -+ *ptr = value; -+ else -+ { -+ asm volatile ("movq (%0), %%mm0\n" -+ "movq %%mm0, (%1)\n" -+ : : "r" (&value), "r" (ptr) : "memory"); -+ mmx_postamble(); -+ } -+} -+#endif -Index: linux-2.4.21/drivers/net/qsnet/qsnet/kernel_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/kernel_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/kernel_linux.c 2005-06-01 23:12:54.697424208 -0400 -@@ -0,0 +1,856 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: kernel_linux.c,v 1.71.2.3 2004/11/04 11:03:47 david Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/kernel_linux.c,v $*/ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include /* for smp_call_function() prototype */ -+#include -+#include -+ -+#include -+ -+extern int mmx_disabled; -+extern int qsnet_debug_line_size; -+extern int qsnet_debug_num_lines; -+ -+gid_t qsnet_procfs_gid; -+struct proc_dir_entry *qsnet_procfs_root; -+struct proc_dir_entry *qsnet_procfs_config; -+ -+MODULE_AUTHOR("Quadrics Ltd."); -+MODULE_DESCRIPTION("QsNet Kernel support code"); -+ -+MODULE_LICENSE("GPL"); -+ -+#if defined(LINUX_I386) -+MODULE_PARM(mmx_disabled, "i"); -+#endif -+ -+MODULE_PARM(qsnet_debug_line_size, "i"); -+MODULE_PARM(qsnet_debug_num_lines, "i"); -+ -+MODULE_PARM(qsnet_procfs_gid, "i"); -+ -+#ifdef KMEM_DEBUG -+EXPORT_SYMBOL(qsnet_kmem_alloc_debug); -+EXPORT_SYMBOL(qsnet_kmem_free_debug); -+#else -+EXPORT_SYMBOL(qsnet_kmem_alloc); -+EXPORT_SYMBOL(qsnet_kmem_free); -+#endif -+ -+EXPORT_SYMBOL(qsnet_kmem_display); -+EXPORT_SYMBOL(kmem_to_phys); -+ -+EXPORT_SYMBOL(cpu_hold_all); -+EXPORT_SYMBOL(cpu_release_all); -+ -+#if defined(LINUX_I386) -+EXPORT_SYMBOL(qsnet_readq); -+EXPORT_SYMBOL(qsnet_writeq); -+#endif -+ -+/* debug.c */ -+EXPORT_SYMBOL(qsnet_debugf); -+EXPORT_SYMBOL(kqsnet_debugf); -+EXPORT_SYMBOL(qsnet_vdebugf); -+EXPORT_SYMBOL(qsnet_debug_buffer); -+EXPORT_SYMBOL(qsnet_debug_alloc); -+EXPORT_SYMBOL(qsnet_debug_dump); -+EXPORT_SYMBOL(qsnet_debug_kmem); -+EXPORT_SYMBOL(qsnet_debug_disable); -+ -+EXPORT_SYMBOL(qsnet_assfail); -+ -+EXPORT_SYMBOL(qsnet_procfs_gid); -+EXPORT_SYMBOL(qsnet_procfs_root); -+ -+static int qsnet_open (struct inode *ino, struct file *fp); -+static int qsnet_release (struct inode *ino, struct file *fp); -+static int qsnet_ioctl (struct inode *ino, struct file *fp, unsigned int cmd, unsigned long arg); -+ -+static struct file_operations qsnet_ioctl_fops = -+{ -+ ioctl: qsnet_ioctl, -+ open: qsnet_open, -+ release: qsnet_release, -+}; -+ -+static int -+qsnet_open (struct inode *inode, struct file *fp) -+{ -+ MOD_INC_USE_COUNT; -+ fp->private_data = NULL; -+ return (0); -+} -+ -+static int -+qsnet_release (struct inode *inode, struct file *fp) -+{ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static int -+qsnet_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, unsigned long arg) -+{ -+ int res=0; -+ -+ switch (cmd) -+ { -+ case QSNETIO_DEBUG_KMEM: -+ { -+ QSNETIO_DEBUG_KMEM_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (QSNETIO_DEBUG_KMEM_STRUCT))) -+ return (-EFAULT); -+ -+ /* doesnt use handle as a pointer */ -+ qsnet_kmem_display(args.handle); -+ break; -+ } -+ -+ case QSNETIO_DEBUG_DUMP : -+ { -+ res = qsnet_debug_dump(); -+ break; -+ } -+ -+ case QSNETIO_DEBUG_BUFFER : -+ { -+ QSNETIO_DEBUG_BUFFER_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (QSNETIO_DEBUG_BUFFER_STRUCT))) -+ return (-EFAULT); -+ -+ /* qsnet_debug_buffer uses copyout */ -+ if ((res = qsnet_debug_buffer (args.addr, args.len)) != -1) -+ { -+ args.len = res; -+ if (copy_to_user ((void *) arg, &args, sizeof (QSNETIO_DEBUG_BUFFER_STRUCT))) -+ return (-EFAULT); -+ res = 0; -+ } -+ break; -+ } -+ default: -+ res = EINVAL; -+ break; -+ } -+ -+ return ((res == 0) ? 0 : -res); -+} -+ -+#ifdef KMEM_DEBUG -+static int qsnet_kmem_open (struct inode *ino, struct file *fp); -+static int qsnet_kmem_release (struct inode *ino, struct file *fp); -+static ssize_t qsnet_kmem_read (struct file *file, char *buf, size_t count, loff_t *ppos); -+ -+static struct file_operations qsnet_kmem_fops = -+{ -+ open: qsnet_kmem_open, -+ release: qsnet_kmem_release, -+ read: qsnet_kmem_read, -+}; -+ -+typedef struct qsnet_private_space -+{ -+ char * space; -+ int size; -+ struct qsnet_private_space *next; -+} QSNET_PRIVATE_SPACE; -+ -+typedef struct qsnet_private -+{ -+ QSNET_PRIVATE_SPACE *space_chain; -+ QSNET_PRIVATE_SPACE *current_space; -+ int current_pos; -+ -+} QSNET_PRIVATE; -+ -+#define QSNET_KMEM_DEBUG_LINE_SIZE ((int)512) -+#define QSNET_PRIVATE_PAGE_SIZE ((int)(4*1024)) -+ -+static int qsnet_kmem_fill(QSNET_PRIVATE *pd); -+ -+void -+destroy_chain(QSNET_PRIVATE * pd) -+{ -+ QSNET_PRIVATE_SPACE *mem, *next; -+ -+ if (pd == NULL) return; -+ -+ for(mem = pd->space_chain ; mem != NULL; ) -+ { -+ next = mem->next; -+ if ( mem->space ) -+ kfree ( mem->space); -+ kfree(mem); -+ mem = next; -+ } -+ kfree (pd); -+} -+ -+QSNET_PRIVATE * -+make_chain(int len) -+{ -+ QSNET_PRIVATE * pd; -+ QSNET_PRIVATE_SPACE * mem; -+ int i; -+ -+ /* make the private data block */ -+ if ((pd = kmalloc (sizeof (QSNET_PRIVATE), GFP_KERNEL)) == NULL) -+ return NULL; -+ pd->space_chain = NULL; -+ -+ /* first make the holders */ -+ for(i=0;inext = pd->space_chain; -+ mem->size = 0; -+ mem->space = 0; -+ pd->space_chain = mem; -+ -+ /* now add the space */ -+ if ((mem->space = kmalloc (QSNET_PRIVATE_PAGE_SIZE, GFP_KERNEL)) == NULL) -+ { -+ destroy_chain(pd); -+ return (NULL); -+ } -+ -+ mem->space[0] = 0; -+ -+ } -+ -+ pd->current_space = pd->space_chain; -+ pd->current_pos = 0; -+ -+ return pd; -+} -+ -+static int -+qsnet_kmem_open (struct inode *inode, struct file *fp) -+{ -+ MOD_INC_USE_COUNT; -+ fp->private_data = NULL; -+ return (0); -+} -+ -+static int -+qsnet_kmem_release (struct inode *inode, struct file *fp) -+{ -+ if ( fp->private_data ) -+ { -+ QSNET_PRIVATE * pd = (QSNET_PRIVATE *) fp->private_data; -+ -+ /* free the space */ -+ if (pd->space_chain) -+ kfree (pd->space_chain); -+ -+ /* free struct */ -+ kfree (pd); -+ } -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static ssize_t -+qsnet_kmem_read (struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ QSNET_PRIVATE * pd = (QSNET_PRIVATE *) file->private_data; -+ int error; -+ int output_count; -+ int num_of_links=10; -+ -+ /* make a buffer to output count bytes in */ -+ if ((error = verify_area (VERIFY_WRITE, buf, count)) != 0) -+ return (error); -+ -+ if ( pd == NULL) -+ { -+ /* first time */ -+ -+ /* ok we have to guess at how much space we are going to need */ -+ /* if it fails we up the space and carry try again */ -+ /* we have to do it this way as we cant get more memory whilst */ -+ /* holding the lock */ -+ if ((pd = make_chain(num_of_links)) == NULL) -+ return (-ENOMEM); -+ -+ while ( qsnet_kmem_fill(pd) ) -+ { -+ destroy_chain(pd); -+ num_of_links += 10; -+ if ((pd = make_chain(num_of_links)) == NULL) -+ return (-ENOMEM); -+ } -+ -+ /* we have the space and filled it */ -+ file->private_data = (void *)pd; -+ } -+ -+ /* output buffer */ -+ if ( pd->current_pos >= pd->current_space->size ) -+ return (0); /* finished */ -+ -+ output_count = pd->current_space->size - pd->current_pos; -+ if ( output_count > count ) -+ output_count = count; -+ -+ copy_to_user(buf, (pd->current_space->space + pd->current_pos), output_count); -+ -+ pd->current_pos += output_count; -+ ppos += output_count; -+ -+ /* just check to see if we have finished the current space */ -+ if ( pd->current_pos >= pd->current_space->size ) -+ { -+ if ( pd->current_space->next ) -+ { -+ pd->current_space = pd->current_space->next; -+ pd->current_pos = 0; -+ } -+ } -+ -+ return (output_count); -+} -+#endif /* KMEM_DEBUG */ -+ -+static int -+proc_write_qsnetdebug(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char tmpbuf[128]; -+ int res; -+ -+ if (count > sizeof (tmpbuf)-1) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ -+ if (copy_from_user (tmpbuf, buffer, count)) -+ res = -EFAULT; -+ else -+ { -+ tmpbuf[count] = '\0'; -+ -+ if (tmpbuf[count-1] == '\n') -+ tmpbuf[count-1] = '\0'; -+ -+ if (! strcmp (tmpbuf, "on")) -+ qsnet_debug_buffer_on(); -+ -+ if (! strcmp (tmpbuf, "clear")) -+ qsnet_debug_buffer_clear(); -+ -+ if (! strncmp (tmpbuf, "mark",4)) -+ qsnet_debug_buffer_mark( &tmpbuf[4] ); -+ -+ res = count; -+ } -+ -+ MOD_DEC_USE_COUNT; -+ -+ return (res); -+} -+ -+static int -+proc_read_qsnetdebug(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len = sprintf (page, "echo command > /proc/qsnet/config/qsnetdebug\ncommand = on | off | clear | mark text\n"); -+ return (qsnet_proc_calc_metrics (page, start, off, count, eof, len)); -+} -+ -+#include "quadrics_version.h" -+extern int kqsnet_debug_running; -+static char quadrics_version[] = QUADRICS_VERSION; -+ -+static int __init qsnet_init(void) -+{ -+ struct proc_dir_entry *p; -+ -+ if ((qsnet_procfs_root = proc_mkdir ("qsnet", 0)) == NULL) -+ { -+ printk ("qsnet: failed to create /proc/qsnet \n"); -+ return (-ENXIO); -+ } -+ -+ if ((p = create_proc_entry ("ioctl", S_IRUGO|S_IWUSR|S_IWGRP, qsnet_procfs_root)) == NULL) -+ { -+ printk ("qsnet: failed to register /proc/qsnet/ioctl\n"); -+ return (-ENXIO); -+ } -+ p->proc_fops = &qsnet_ioctl_fops; -+ p->owner = THIS_MODULE; -+ p->data = NULL; -+ p->gid = qsnet_procfs_gid; -+ -+ qsnet_proc_register_str (qsnet_procfs_root, "version", quadrics_version, S_IRUGO); -+ -+ if ((qsnet_procfs_config = proc_mkdir ("config", qsnet_procfs_root)) == NULL) -+ { -+ printk ("qsnet: failed to create /proc/qsnet/config \n"); -+ return (-ENXIO); -+ } -+ -+#ifdef KMEM_DEBUG -+ if ((p = create_proc_entry ("kmem_debug", S_IRUGO|S_IWUSR|S_IWGRP, qsnet_procfs_config)) == NULL) -+ { -+ printk ("qsnet: failed to register /proc/qsnet/config/kmem_debug\n"); -+ return (-ENXIO); -+ } -+ p->proc_fops = &qsnet_kmem_fops; -+ p->owner = THIS_MODULE; -+ p->data = NULL; -+ p->gid = qsnet_procfs_gid; -+#endif -+ -+ qsnet_debug_init(); -+ -+ qsnet_proc_register_int (qsnet_procfs_config, "kqsnet_debug_running", &kqsnet_debug_running, 0); -+ -+ if ((p = create_proc_entry ("qsnetdebug", S_IRUGO|S_IWUSR|S_IWGRP, qsnet_procfs_config)) == NULL) -+ { -+ printk ("qsnet: failed to register /proc/qsnet/config/qsnetdebug\n"); -+ return (-ENXIO); -+ } -+ p->read_proc = proc_read_qsnetdebug; -+ p->write_proc = proc_write_qsnetdebug; -+ p->owner = THIS_MODULE; -+ p->data = NULL; -+ p->gid = qsnet_procfs_gid; -+ -+ return (0); -+} -+ -+static void __exit qsnet_exit(void) -+{ -+#ifdef KMEM_DEBUG -+ qsnet_kmem_display(0); -+#endif -+ qsnet_debug_fini(); -+ -+ remove_proc_entry ("qsnetdebug", qsnet_procfs_config); -+ remove_proc_entry ("kqsnet_debug_running", qsnet_procfs_config); -+#ifdef KMEM_DEBUG -+ remove_proc_entry ("kmem_debug", qsnet_procfs_config); -+#endif -+ remove_proc_entry ("config", qsnet_procfs_root); -+ -+ remove_proc_entry ("version", qsnet_procfs_root); -+ remove_proc_entry ("ioctl", qsnet_procfs_root); -+ -+ remove_proc_entry ("qsnet", 0); -+} -+ -+/* Declare the module init and exit functions */ -+module_init(qsnet_init); -+module_exit(qsnet_exit); -+ -+#ifdef KMEM_DEBUG -+/* -+ * Kernel memory allocation. We maintain our own list of allocated mem -+ * segments so we can free them on module cleanup. -+ * -+ * We use kmalloc for allocations less than one page in size; vmalloc for -+ * larger sizes. -+ */ -+ -+typedef struct { -+ struct list_head list; -+ void *ptr; -+ int len; -+ int used_vmalloc; -+ void *owner; -+ void *caller; -+ unsigned int time; -+ int line; -+ char filename[20]; -+} kmalloc_t; -+ -+static LIST_HEAD(kmalloc_head); -+ -+static spinlock_t kmalloc_lock = SPIN_LOCK_UNLOCKED; -+ -+/* -+ * Kernel memory allocation. We use kmalloc for allocations less -+ * than one page in size; vmalloc for larger sizes. -+ */ -+ -+static int -+qsnet_kmem_fill(QSNET_PRIVATE *pd) -+{ -+ kmalloc_t *kp; -+ struct list_head *lp; -+ unsigned long flags; -+ char str[QSNET_KMEM_DEBUG_LINE_SIZE]; -+ QSNET_PRIVATE_SPACE * current_space; -+ int current_pos; -+ int len; -+ current_space = pd->space_chain; -+ current_pos = 0; -+ -+ -+ current_space->space[0] = 0; -+ spin_lock_irqsave(&kmalloc_lock, flags); -+ for (lp = kmalloc_head.next; lp != &kmalloc_head; lp = lp->next) { -+ kp = list_entry(lp, kmalloc_t, list); -+ -+ /* make the next line */ -+ sprintf(str,"%p %d %d %p %p %u %d %s\n", -+ kp->ptr, kp->len, kp->used_vmalloc, kp->caller, kp->owner, kp->time, kp->line, kp->filename); -+ len = strlen(str); -+ -+ /* does it fit on the current page */ -+ if ( (current_pos + len + 1) >= QSNET_PRIVATE_PAGE_SIZE) -+ { -+ /* move onto next page */ -+ if ((current_space = current_space->next) == NULL) -+ { -+ /* run out of space !!!! */ -+ spin_unlock_irqrestore(&kmalloc_lock, flags); -+ return (1); -+ } -+ current_space->space[0] = 0; -+ current_pos = 0; -+ } -+ strcat( current_space->space + current_pos, str); -+ current_pos += len; -+ -+ /* remember how much we wrote to this page */ -+ current_space->size = current_pos; -+ -+ } -+ spin_unlock_irqrestore(&kmalloc_lock, flags); -+ -+ return (0); -+} -+ -+void * -+qsnet_kmem_alloc_debug(int len, int cansleep, int zerofill, char *file, int line) -+{ -+ void *new; -+ unsigned long flags; -+ kmalloc_t *kp; -+ -+ if (len < PAGE_SIZE || !cansleep) -+ new = kmalloc(len, cansleep ? GFP_KERNEL : GFP_ATOMIC); -+ else -+ new = vmalloc(len); -+ -+ if (len >= PAGE_SIZE) -+ ASSERT(PAGE_ALIGNED((uintptr_t) new)); -+ -+ if (new && zerofill) -+ memset(new,0,len); -+ -+ /* record allocation */ -+ kp = kmalloc(sizeof(kmalloc_t), cansleep ? GFP_KERNEL : GFP_ATOMIC); -+ ASSERT(kp != NULL); -+ kp->len = len; -+ kp->ptr = new; -+ kp->used_vmalloc = (len >= PAGE_SIZE || cansleep); -+ kp->owner = current; -+ kp->caller = __builtin_return_address(0); -+ kp->time = lbolt; -+ kp->line = line; -+ len = strlen(file); -+ -+ if (len > 18) -+ strcpy(kp->filename,&file[len-18]); -+ else -+ strcpy(kp->filename,file); -+ -+ spin_lock_irqsave(&kmalloc_lock, flags); -+ list_add(&kp->list, &kmalloc_head); -+ spin_unlock_irqrestore(&kmalloc_lock, flags); -+ -+ return new; -+} -+ -+void -+qsnet_kmem_free_debug(void *ptr, int len, char *file, int line) -+{ -+ unsigned long flags; -+ kmalloc_t *kp; -+ struct list_head *lp; -+ -+ spin_lock_irqsave(&kmalloc_lock, flags); -+ for (lp = kmalloc_head.next; lp != &kmalloc_head; lp = lp->next) { -+ kp = list_entry(lp, kmalloc_t, list); -+ if (kp->ptr == ptr) { -+ if (kp->len != len) -+ printk("qsnet_kmem_free_debug(%p) ptr %p len %d mismatch: expected %d caller %p owner %p (%s:%d)\n", -+ current, ptr, len, kp->len, __builtin_return_address(0), kp->caller, file, line); -+ list_del(lp); -+ kfree(kp); /* free off descriptor */ -+ break; -+ } -+ } -+ spin_unlock_irqrestore(&kmalloc_lock, flags); -+ -+ if (lp == &kmalloc_head) /* segment must be found */ -+ { -+ printk( "qsnet_kmem_free_debug(%p) ptr %p len %d not found: caller %p (%s:%d)\n", -+ current, ptr, len, __builtin_return_address(0), file, line); -+ } -+ -+ if ((((unsigned long) ptr) >= VMALLOC_START && ((unsigned long) ptr) < VMALLOC_END)) -+ vfree (ptr); -+ else -+ kfree (ptr); -+} -+ -+#else /* !KMEM_DEBUG */ -+ -+void * -+qsnet_kmem_alloc(int len, int cansleep, int zerofill) -+{ -+ void *new; -+ -+ if (len < PAGE_SIZE || !cansleep) -+ new = kmalloc(len, cansleep ? GFP_KERNEL : GFP_ATOMIC); -+ else -+ new = vmalloc(len); -+ -+ if (len >= PAGE_SIZE) -+ ASSERT(PAGE_ALIGNED((unsigned long) new)); -+ -+ if (new && zerofill) -+ memset(new,0,len); -+ -+ return new; -+} -+ -+void -+qsnet_kmem_free(void *ptr, int len) -+{ -+ if ((((unsigned long) ptr) >= VMALLOC_START && ((unsigned long) ptr) < VMALLOC_END)) -+ vfree (ptr); -+ else -+ kfree (ptr); -+} -+#endif /* !KMEM_DEBUG */ -+ -+void -+qsnet_kmem_display(void *handle) -+{ -+#ifdef KMEM_DEBUG -+ kmalloc_t *kp; -+ struct list_head *lp; -+ unsigned long flags; -+ int count = 0, totsize = 0; -+ -+ spin_lock_irqsave(&kmalloc_lock, flags); -+ for (lp = kmalloc_head.next; lp != &kmalloc_head; lp = lp->next) { -+ kp = list_entry(lp, kmalloc_t, list); -+ -+ if (!handle || handle == kp->owner) -+ { -+ printk("qsnet_kmem_display(%p): mem %p len %d unfreed caller %p (%p) \n", -+ handle, kp->ptr, kp->len, kp->caller, kp->owner); -+ -+ count++; -+ totsize += kp->len; -+ } -+ } -+ spin_unlock_irqrestore(&kmalloc_lock, flags); -+ -+ printk("qsnet_kmem_display(%p): %d bytes left in %d objects\n", handle, totsize, count); -+#endif -+} -+ -+physaddr_t -+kmem_to_phys(void *ptr) -+{ -+ virtaddr_t virt = (virtaddr_t) ptr; -+ physaddr_t phys; -+ pte_t *pte; -+ -+ if ((virt >= VMALLOC_START && virt < VMALLOC_END)) -+ { -+ pte = find_pte_kernel(virt); -+ ASSERT(pte && !pte_none(*pte)); -+ phys = pte_phys(*pte) + (virt & (PAGE_SIZE-1)); -+ } -+#if defined(PKMAP_BASE) -+ else if (virt >= PKMAP_BASE && virt < (PKMAP_BASE + LAST_PKMAP * PAGE_SIZE)) -+ { -+ pte = find_pte_kernel(virt); -+ ASSERT(pte && !pte_none(*pte)); -+ phys = pte_phys(*pte) + (virt & (PAGE_SIZE-1)); -+ } -+#endif -+#if defined(__ia64) -+ else if (virt >= __IA64_UNCACHED_OFFSET && virt < PAGE_OFFSET) -+ { -+ /* ia64 non-cached KSEG */ -+ phys = ((physaddr_t) ptr - __IA64_UNCACHED_OFFSET); -+ } -+#endif -+ else /* otherwise it's KSEG */ -+ { -+ phys = __pa(virt); -+ } -+ -+#if defined(CONFIG_ALPHA_GENERIC) || (defined(CONFIG_ALPHA_EV6) && !defined(USE_48_BIT_KSEG)) -+ /* -+ * with TS_BIAS as bit 40 - the tsunami pci space is mapped into -+ * the kernel at 0xfffff500.00000000 however we need to convert -+ * this to the true physical address 0x00000800.00000000. -+ * -+ * there is no need for PHYS_TWIDDLE since we knew we'd get a kernel -+ * virtual address already and handled this with __pa(). -+ */ -+ if (phys & (1ul << 40)) { -+ phys &= ~(1ul << 40); /* clear bit 40 (kseg I/O select) */ -+ phys |= (1ul << 43); /* set bit 43 (phys I/O select) */ -+ } -+#endif -+ return phys; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -+ -+EXPORT_SYMBOL(pci_resource_size); -+EXPORT_SYMBOL(pci_get_base_address); -+EXPORT_SYMBOL(pci_base_to_kseg); -+ -+ -+/* -+ * PCI stuff. -+ * -+ * XXX pci_base_to_kseg() and pci_kseg_to_phys() are problematic -+ * in that they may not work on non-Tsunami (DS20, ES40, etc) -+ * architectures, and may not work in non-zero PCI bus numbers. -+ */ -+ -+unsigned long -+pci_get_base_address(struct pci_dev *pdev, int index) -+{ -+ unsigned long base; -+ -+ ASSERT(index >= 0 && index <= 5); -+ /* borrowed in part from drivers/scsi/sym53c8xx.c */ -+ base = pdev->base_address[index++]; -+ -+#if BITS_PER_LONG > 32 -+ if ((base & 0x7) == 0x4) -+ base |= (((unsigned long)pdev->base_address[index]) << 32); -+#endif -+ return base; -+} -+ -+unsigned long -+pci_resource_size(struct pci_dev *pdev, int index) -+{ -+ u32 addr, mask, size; -+ -+ static u32 bar_addr[] = { -+ PCI_BASE_ADDRESS_0, -+ PCI_BASE_ADDRESS_1, -+ PCI_BASE_ADDRESS_2, -+ PCI_BASE_ADDRESS_3, -+ PCI_BASE_ADDRESS_4, -+ PCI_BASE_ADDRESS_5, -+ }; -+ ASSERT(index >= 0 && index <= 5); -+ -+ /* algorithm from Rubini book */ -+ pci_read_config_dword (pdev, bar_addr[index], &addr); -+ pci_write_config_dword(pdev, bar_addr[index], ~0); -+ pci_read_config_dword (pdev, bar_addr[index], &mask); -+ pci_write_config_dword(pdev, bar_addr[index], addr); -+ -+ mask &= PCI_BASE_ADDRESS_MEM_MASK; -+ size = ~mask + 1; -+ return size; -+} -+ -+/* -+ * Convert BAR register value to KSEG address. -+ */ -+void * -+pci_base_to_kseg(u64 baddr, int bus) -+{ -+ u64 kseg; -+ -+ /* XXX tsunami specific */ -+ baddr &= ~(u64)0x100000000; /* mask out hose bit */ -+ kseg = TSUNAMI_MEM(bus) + baddr; -+ return (void *)kseg; -+} -+ -+#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,0) */ -+ -+/* -+ * Spin the other CPU's in an SMP system. -+ * smp_call_function() needed to be exported to modules. It will be -+ * papered over in if running on a non-SMP box. -+ */ -+static spinlock_t hold_lock = SPIN_LOCK_UNLOCKED; -+ -+#if 0 -+static void cpu_hold(void *unused) -+{ -+ spin_lock(&hold_lock); -+ spin_unlock(&hold_lock); -+} -+#endif -+ -+void cpu_hold_all(void) -+{ -+ spin_lock(&hold_lock); -+ -+#if 0 -+ { -+ int res; -+ int retries = 10; -+ -+ /* XXXXX: cannot call smp_call_function() from interrupt context */ -+ -+ do { -+ /* only request blocking retry if not in interrupt context */ -+ res = smp_call_function(cpu_hold, NULL, !in_interrupt(), 0); -+ if (res) -+ mdelay(5); -+ } while (res && retries--); -+ -+ if (res) -+ printk("cpu_hold_all: IPI timeout\n"); -+ } -+#endif -+} -+ -+void cpu_release_all(void) -+{ -+ spin_unlock(&hold_lock); -+} -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/qsnet/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/Makefile 2005-06-01 23:12:54.697424208 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/qsnet/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/qsnet/Makefile -+# -+ -+list-multi := qsnet.o -+qsnet-objs := debug.o kernel_linux.o i686_mmx.o -+export-objs := kernel_linux.o -+obj-$(CONFIG_QSNET) := qsnet.o -+ -+qsnet.o : $(qsnet-objs) -+ $(LD) -r -o $@ $(qsnet-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/qsnet/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/Makefile.conf 2005-06-01 23:12:54.698424056 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = qsnet.o -+MODULENAME = qsnet -+KOBJFILES = debug.o kernel_linux.o i686_mmx.o -+EXPORT_KOBJS = kernel_linux.o -+CONFIG_NAME = CONFIG_QSNET -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/qsnet/qsnetkmem_linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/qsnetkmem_linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/qsnetkmem_linux.c 2005-06-01 23:12:54.698424056 -0400 -@@ -0,0 +1,325 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: qsnetkmem_linux.c,v 1.3 2003/08/13 10:03:27 fabien Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/qsnetkmem_linux.c,v $*/ -+ -+/* macro macros */ -+#define MACRO_BEGIN do { -+#define MACRO_END } while (0) -+#define offsetof(T,F) ((int )&(((T *)0)->F)) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define LIST_HEAD_INIT(name) { &(name), &(name) } -+ -+#define LIST_HEAD(name) \ -+ struct list_head name = LIST_HEAD_INIT(name) -+ -+typedef struct { -+ struct list_head list; -+ void *ptr; -+ int len; -+ int used_vmalloc; -+ void *owner; -+ void *caller; -+ unsigned int time; -+ int mark; -+ int line; -+ char file[256]; -+ -+} kmalloc_t; -+ -+ -+static LIST_HEAD(current_kmem); -+static LIST_HEAD(stored_kmem); -+ -+void -+count_kmem(struct list_head * list, long * count, long * size ) -+{ -+ long c,s; -+ struct list_head *tmp; -+ kmalloc_t *kmem_ptr = NULL; -+ -+ -+ c = s = 0L; -+ -+ list_for_each(tmp, list) { -+ kmem_ptr = list_entry(tmp, kmalloc_t , list); -+ c++; -+ s += kmem_ptr->len; -+ } -+ -+ *count = c; -+ *size = s; -+} -+ -+void -+clear_kmem(struct list_head * list) -+{ -+ struct list_head *tmp,*tmp2; -+ kmalloc_t *kmem_ptr = NULL; -+ -+ list_for_each_safe(tmp, tmp2, list) { -+ kmem_ptr = list_entry(tmp, kmalloc_t , list); -+ list_del_init(&kmem_ptr->list); -+ free( kmem_ptr ); -+ } -+} -+ -+void -+move_kmem(struct list_head * dest, struct list_head *src) -+{ -+ struct list_head *tmp,*tmp2; -+ kmalloc_t *kp= NULL; -+ -+ list_for_each_safe(tmp, tmp2, src) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ list_del_init(&kp->list); -+ -+/* -+ printf("mem %p len %d (vm=%d) caller %p owner %p (%s:%d)\n", -+ kp->ptr, kp->len, kp->used_vmalloc, kp->caller, kp->owner, kp->file, kp->line); -+*/ -+ -+ list_add_tail(&kp->list, dest); -+ } -+} -+ -+void -+read_kmem(struct list_head * list) -+{ -+ FILE * fd; -+ char line[1024]; -+ int line_size = 100; -+ char * rep; -+ kmalloc_t * kp; -+ -+ clear_kmem(list); -+ -+ fd = fopen(QSNET_PROCFS_KMEM_DEBUG,"r"); -+ if ( fd == NULL) -+ { -+ printf("No Kmem Debug\n"); -+ return; -+ } -+ -+ rep = fgets(line,line_size, fd); -+ -+ while ( rep != NULL ) -+ { -+ kp = malloc(sizeof(kmalloc_t)); -+ -+ sscanf(line,"%p %d %d %p %p %u %d %s\n", -+ &kp->ptr, &kp->len, &kp->used_vmalloc, &kp->caller, &kp->owner, &kp->time, &kp->line, &kp->file[0]); -+ -+/* -+ printf(">>%s<<\n",line); -+ printf("%p %d %d %p %p %u %d %s\n", -+ kp->ptr, kp->len, kp->used_vmalloc, kp->caller, kp->owner, kp->time, kp->line, kp->file); -+*/ -+ -+ list_add_tail(&kp->list, list); -+ -+ rep = fgets(line,line_size, fd); -+ } -+ fclose(fd); -+} -+ -+void -+mark_kmem(struct list_head * list, int mark) -+{ -+ struct list_head *tmp; -+ kmalloc_t *kp = NULL; -+ -+ list_for_each(tmp, list) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ -+ kp->mark = mark; -+ } -+} -+ -+kmalloc_t * -+find_kmem(kmalloc_t * value, struct list_head * list) -+{ -+ struct list_head *tmp; -+ kmalloc_t *kp = NULL; -+ -+ -+ list_for_each(tmp, list) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ if ( (kp->ptr == value->ptr) -+ && (kp->len == value->len) -+ && (kp->used_vmalloc == value->used_vmalloc ) -+ && (kp->owner == value->owner ) -+ && (kp->caller == value->caller ) -+ && (kp->time == value->time ) -+ && (kp->line == value->line ) -+ && !(strcmp(kp->file,value->file) )) -+ return kp; -+ } -+ return NULL; -+} -+ -+void -+diff_kmem(struct list_head *curr, struct list_head *stored) -+{ -+ struct list_head *tmp; -+ kmalloc_t *kp = NULL; -+ long c,s; -+ -+ mark_kmem(stored, 0); -+ mark_kmem(curr, 0); -+ -+ list_for_each(tmp, stored) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ if (find_kmem( kp, curr) != NULL) -+ kp->mark = 1; -+ } -+ -+ list_for_each(tmp, curr) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ if (find_kmem( kp, stored) != NULL) -+ kp->mark = 1; -+ } -+ -+ c=s=0L; -+ list_for_each(tmp, stored) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ if (kp->mark != 1) -+ { -+ printf("-- mem %p len %d (vm=%d) caller %p owner %p (%s:%d)\n", -+ kp->ptr, kp->len, kp->used_vmalloc, kp->caller, kp->owner, kp->file, kp->line); -+ c++; -+ s+= kp->len; -+ } -+ } -+ printf("-- %4ld %10ld \n",c,s); -+ -+ c=s=0L; -+ list_for_each(tmp, curr) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ if (kp->mark != 1) -+ { -+ printf("++ mem %p len %d (vm=%d) caller %p owner %p (%s:%d)\n", -+ kp->ptr, kp->len, kp->used_vmalloc, kp->caller, kp->owner, kp->file, kp->line); -+ c++; -+ s+= kp->len; -+ } -+ } -+ printf("++ %4ld %10ld \n",c,s); -+} -+ -+ -+void -+print_kmem(struct list_head * list) -+{ -+ struct list_head *tmp; -+ kmalloc_t *kp = NULL; -+ -+ list_for_each(tmp, list) { -+ kp = list_entry(tmp, kmalloc_t , list); -+ -+ printf("mem %p len %d (vm=%d) caller %p owner %p (%s:%d)\n", -+ kp->ptr, kp->len, kp->used_vmalloc, kp->caller, kp->owner, kp->file, kp->line); -+ -+ } -+} -+ -+void -+print_cmds() -+{ -+ long c,s; -+ -+ printf("q : quits \n"); -+ printf("r : read\n"); -+ printf("c : print current\n"); -+ printf("o : print stored\n"); -+ printf("s : store\n"); -+ -+ count_kmem(¤t_kmem, &c, &s ); -+ printf("\ncurrent : %4ld %10ld\n", c , s); -+ -+ count_kmem(&stored_kmem, &c, &s ); -+ printf("store : %4ld %10ld\n", c , s); -+ -+} -+ -+int -+main() -+{ -+ char line[128]; -+ int line_size=127; -+ int len; -+ -+ -+ while (1) -+ { -+ -+ printf(">> "); -+ fgets(line,line_size, stdin); -+ -+ -+ len = strlen( line ) -1; -+ if ( len ) -+ { -+ switch ( tolower(line[0]) ) -+ { -+ case 'q': -+ exit(0); -+ -+ case 'r' : -+ read_kmem(¤t_kmem); -+ break; -+ -+ case 'c' : -+ print_kmem(¤t_kmem); -+ break; -+ -+ case 'o' : -+ print_kmem(&stored_kmem); -+ break; -+ -+ case 's' : -+ clear_kmem(&stored_kmem); -+ move_kmem(&stored_kmem, ¤t_kmem); -+ break; -+ -+ case 'd' : -+ diff_kmem(¤t_kmem, &stored_kmem); -+ break; -+ -+ default: -+ print_cmds(); -+ } -+ -+ -+ -+ } -+ else -+ print_cmds(); -+ } -+ -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/drivers/net/qsnet/qsnet/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/qsnet/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/qsnet/quadrics_version.h 2005-06-01 23:12:54.699423904 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/rms/Makefile -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/rms/Makefile 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/rms/Makefile 2005-06-01 23:12:54.699423904 -0400 -@@ -0,0 +1,31 @@ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2002-2004 Quadrics Ltd -+# -+# File: drivers/net/qsnet/rms/Makefile -+# -+ -+ -+# -+ -+# -+# Makefile for Quadrics QsNet -+# -+# Copyright (c) 2004 Quadrics Ltd. -+# -+# File: driver/net/qsnet/rms/Makefile -+# -+ -+list-multi := rms.o -+rms-objs := rms_kern.o rms_kern_Linux.o -+export-objs := -+obj-$(CONFIG_RMS) := rms.o -+ -+rms.o : $(rms-objs) -+ $(LD) -r -o $@ $(rms-objs) -+ -+EXTRA_CFLAGS += -DDEBUG -DDEBUG_PRINTF -DDEBUG_ASSERT -+ -+include $(TOPDIR)/Rules.make -+ -Index: linux-2.4.21/drivers/net/qsnet/rms/Makefile.conf -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/rms/Makefile.conf 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/rms/Makefile.conf 2005-06-01 23:12:54.699423904 -0400 -@@ -0,0 +1,10 @@ -+# Flags for generating QsNet Linux Kernel Makefiles -+MODNAME = rms.o -+MODULENAME = rms -+KOBJFILES = rms_kern.o rms_kern_Linux.o -+EXPORT_KOBJS = -+CONFIG_NAME = CONFIG_RMS -+SGALFC = -+# EXTRALINES START -+ -+# EXTRALINES END -Index: linux-2.4.21/drivers/net/qsnet/rms/quadrics_version.h -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/rms/quadrics_version.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/rms/quadrics_version.h 2005-06-01 23:12:54.700423752 -0400 -@@ -0,0 +1 @@ -+#define QUADRICS_VERSION "4.30qsnet" -Index: linux-2.4.21/drivers/net/qsnet/rms/rms_kern.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/rms/rms_kern.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/rms/rms_kern.c 2005-06-01 23:12:54.702423448 -0400 -@@ -0,0 +1,1757 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ * rms_kern.c: RMS kernel module -+ * -+ * $Source: /cvs/master/quadrics/rmsmod/rms_kern.c,v $ -+ */ -+ -+#ident "@(#)$Id: rms_kern.c,v 1.62.2.4 2005/01/18 11:05:45 duncan Exp $" -+ -+#include -+#include -+#include -+#include -+ -+/* -+ * extend stats added in version 5 -+ */ -+#define RMS_MODVERSION 5 -+ -+#if defined(SOLARIS) -+ -+#define CURUID() CURPROC()->p_cred->cr_uid -+#define RMS_NCPUS() 4 -+#define PROC_STRUCT proc -+ -+#include -+ -+#elif defined(LINUX) -+ -+#ifdef PROCESS_ACCT -+#define TIMEVAL_TO_MSEC(tv) ((tv)->tv_sec * 1000 + (tv)->tv_usec / 1000) -+#define TIMEVAL_TO_CT(tv) ((tv)->tv_sec * HZ + (tv)->tv_usec / (1000000L / HZ)) -+#endif -+ -+#ifdef RSS_ATOMIC -+#define PROC_RSS(proc) ((proc)->mm ? atomic_read(&(proc)->mm->rss) : 0) -+#else -+#define PROC_RSS(proc) ((proc)->mm ? (proc)->mm->rss : 0) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+# define RMS_NCPUS() smp_num_cpus -+#else -+# define RMS_NCPUS() num_online_cpus() -+#endif -+ -+#define CURUID() CURPROC()->uid -+#define p_pid pid -+#define PROC_STRUCT task_struct -+ -+/* care needed with conversion to millisecs on 32-bit Linux */ -+#ifdef LINUX -+#ifdef LINUX_I386 -+#define CT_TO_MSEC(x) ct_to_msec(x) -+ -+uint64_t ct_to_msec(clock_t t) -+{ -+ uint64_t msecs; -+ if (t < 2000000) -+ { -+ t = (1000 * t)/HZ; -+ msecs = t; -+ } -+ else -+ { -+ t = t / HZ; -+ msecs = t * 1000; -+ } -+ return(msecs); -+} -+ -+#else -+#define CT_TO_MSEC(x) (((x) * 1000)/HZ) -+#endif -+#endif -+ -+#ifndef FALSE -+#define FALSE (0) -+#define TRUE (!FALSE) -+#endif -+ -+#include -+#include -+#include -+ -+#include -+ -+#elif defined(DIGITAL_UNIX) -+ -+#define CURUID() CURPROC()->p_ruid -+extern int ncpus; -+#define RMS_NCPUS() ncpus -+#define PROC_STRUCT proc -+#define TIMEVAL_TO_MSEC(tv) ((tv)->tv_sec * 1000 + (tv)->tv_usec / 1000) -+ -+#include -+ -+#else -+#error cannot determine operating system -+#endif -+ -+int shm_cleanup(void); -+ -+struct cap_desc { -+ -+ struct cap_desc *next; -+ int index; /* index of capability in program */ -+ ELAN_CAPABILITY cap; /* elan capability */ -+ -+}; -+ -+struct proc_desc { -+ -+ struct proc_desc *next; -+ struct PROC_STRUCT *proc; -+ struct prg_desc *program; /* controlling program */ -+ int mycap; /* index of my capability */ -+ int myctx; /* context number for process */ -+ int flags; -+ int vp; /* elan virtual process number */ -+}; -+ -+struct prg_desc { -+ -+ struct prg_desc *next; -+ int id; /* program id */ -+ int flags; /* program status flags */ -+ uid_t uid; /* user id */ -+ int ncpus; /* number of cpus allocated to program */ -+ int nprocs; /* number of processes in program */ -+ struct proc_desc *pdescs; /* processes in this program */ -+ int ncaps; /* number of capabilities */ -+ struct cap_desc *caps; /* elan capabilities */ -+ char *corepath; /* core path for parallel program */ -+ int psid; /* processor set id */ -+ -+ uint64_t cutime; /* user time accumulated by children */ -+ uint64_t cstime; /* system time accumulated by children */ -+ uint64_t start_time; /* time program created */ -+ uint64_t end_time; /* time last process exited */ -+ uint64_t sched_time; /* last time job was scheduled */ -+ uint64_t accum_atime; /* allocated time last deschedule */ -+ uint64_t memint; /* accumulated memory integral */ -+ uint64_t ebytes; /* data transferred by the Elan(s) */ -+ uint64_t exfers; /* number of Elan data transfers */ -+ long maxrss; /* maximum size to date */ -+ long majflt; -+ -+#ifdef LINUX -+ struct proc_dir_entry *proc_entry; -+#endif -+ -+}; -+ -+#if defined(LINUX) -+static int rms_ptrack_callback (void *arg, int phase, struct task_struct *child); -+#else -+static void rms_xd_callback(void *arg, int phase, void *ctask); -+static void rms_xa_callback (void *arg, int phase, void *ctask); -+#endif -+ -+static void prgsignal(struct prg_desc *program, int signo); -+static uint64_t gettime(void); -+static void freeProgram(struct prg_desc *program); -+ -+static struct prg_desc *programs = 0; -+ -+kmutex_t rms_lock; -+ -+int rms_init(void) -+{ -+ kmutex_init (&rms_lock); -+ -+ DBG(printk("rms: initialising\n")); -+ -+ return(ESUCCESS); -+} -+ -+int rms_reconfigure(void) -+{ -+ return(ESUCCESS); -+} -+ -+int rms_programs_registered(void) -+{ -+ /* -+ ** Called when trying to unload rms.mod will not succeed -+ ** if programs registered -+ */ -+ -+ struct prg_desc *program, **pp; -+ -+ kmutex_lock(&rms_lock); -+ -+ for (program = programs; program; program = program->next) -+ { -+ if (program->nprocs != 0) -+ { -+ kmutex_unlock(&rms_lock); -+ return(EBUSY); -+ } -+ } -+ -+ /* -+ ** We have traversed the programs list and no processes registered -+ ** Now free the memory -+ */ -+ -+ pp = &programs; -+ while ((program = *pp) != NULL) -+ { -+ *pp = program->next; -+ freeProgram(program); -+ } -+ kmutex_unlock(&rms_lock); -+ -+ return(ESUCCESS); -+ -+} -+ -+int rms_fini(void) -+{ -+ /* -+ * don't allow an unload if there are programs registered -+ */ -+ if (rms_programs_registered()) -+ return(EBUSY); -+ -+ kmutex_destroy (&rms_lock); -+ -+ DBG(printk("rms: removed\n")); -+ -+ return(ESUCCESS); -+} -+ -+#ifdef LINUX -+ -+extern struct proc_dir_entry *rms_procfs_programs; -+ -+/* -+ * display one pid per line if there isn't enough space -+ * for another pid then add "...\n" and stop -+ */ -+int pids_callback(char* page, char** start, off_t off, int count, int* eof, void* data) -+{ -+ struct prg_desc *program = (struct prg_desc *)data; -+ struct proc_desc *pdesc; -+ char *ptr = page; -+ int bytes = 0, nb; -+ -+ kmutex_lock(&rms_lock); -+ -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+ if (bytes > count - 15) -+ { -+ bytes += sprintf(ptr,"...\n"); -+ break; -+ } -+ nb = sprintf(ptr, "%d %d\n", pdesc->proc->p_pid, pdesc->vp); -+ bytes += nb; -+ ptr += nb; -+ } -+ kmutex_unlock(&rms_lock); -+ -+ return(bytes); -+} -+ -+int status_callback(char* page, char** start, off_t off, int count, int* eof, void* data) -+{ -+ struct prg_desc *program = (struct prg_desc *)data; -+ int bytes; -+ if (program->flags & PRG_KILLED) -+ bytes = sprintf(page, "killed\n"); -+ else -+ bytes = sprintf(page, "running\n"); -+ return(bytes); -+} -+ -+void rms_create_proc_entry(struct prg_desc *program) -+{ -+ struct proc_dir_entry *p; -+ char name[32]; -+ -+ if (rms_procfs_programs) -+ { -+ sprintf(name,"%d", program->id); -+ if ((program->proc_entry = proc_mkdir(name, rms_procfs_programs)) != NULL) -+ { -+ if ((p = create_proc_entry ("pids", S_IRUGO, program->proc_entry)) != NULL) -+ { -+ p->owner = THIS_MODULE; -+ p->data = program; -+ p->read_proc = pids_callback; -+ } -+ if ((p = create_proc_entry ("status", S_IRUGO, program->proc_entry)) != NULL) -+ { -+ p->owner = THIS_MODULE; -+ p->data = program; -+ p->read_proc = status_callback; -+ } -+ } -+ } -+} -+ -+void rms_remove_proc_entry(struct prg_desc *program) -+{ -+ char name[32]; -+ if (rms_procfs_programs) -+ { -+ if (program->proc_entry) -+ { -+ remove_proc_entry ("pids", program->proc_entry); -+ remove_proc_entry ("status", program->proc_entry); -+ } -+ sprintf(name,"%d", program->id); -+ remove_proc_entry (name, rms_procfs_programs); -+ } -+} -+ -+#endif -+ -+/* -+ * find a program from its index/pid -+ * -+ * Duncan: make the lookup more efficient for large numbers of programs/processes -+ */ -+static struct prg_desc *findProgram(const int id) -+{ -+ struct prg_desc *program; -+ for (program = programs; program; program = program->next) -+ if (program->id == id) -+ return(program); -+ return(0); -+} -+ -+static struct proc_desc *findProcess(const int pid) -+{ -+ struct prg_desc *program; -+ struct proc_desc *pdesc; -+ for (program = programs; program; program = program->next) -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ if (pdesc->proc->p_pid == pid) -+ return(pdesc); -+ return(0); -+} -+ -+static void freeProgram(struct prg_desc *program) -+{ -+ struct proc_desc *pdesc; -+ struct cap_desc *cdesc; -+ -+#ifdef LINUX -+ rms_remove_proc_entry(program); -+#endif -+ -+ while ((pdesc = program->pdescs) != NULL) -+ { -+ program->pdescs = pdesc->next; -+ KMEM_FREE(pdesc, sizeof(struct proc_desc)); -+ } -+ -+ while ((cdesc = program->caps) != NULL) -+ { -+ program->caps = cdesc->next; -+ KMEM_FREE(cdesc, sizeof(struct cap_desc)); -+ } -+ -+ if (program->corepath) -+ KMEM_FREE(program->corepath, MAXCOREPATHLEN + 1); -+ -+ KMEM_FREE(program, sizeof(struct prg_desc)); -+ -+#ifdef LINUX -+ MOD_DEC_USE_COUNT; -+#endif -+} -+ -+/* -+ * rms_prgcreate -+ * -+ * create a new program description -+ */ -+int rms_prgcreate(int id, uid_t uid, int cpus) -+{ -+ struct prg_desc *program; -+ struct proc_desc *pdesc; -+ -+ DBG(printk("rms_prgcreate :: program %d pid %d uid %d cpus %d\n", id, CURPROC()->p_pid, uid, cpus)); -+ -+ /* -+ * parallel programs are created as root by the rmsd as it forks the loader -+ */ -+ if (CURUID()) -+ return(EACCES); -+ -+ /* -+ * program ids must be unique -+ */ -+ kmutex_lock(&rms_lock); -+ program = findProgram(id); -+ kmutex_unlock(&rms_lock); -+ if (program) -+ return(EINVAL); -+ -+ /* -+ * create a new program description -+ */ -+ KMEM_ALLOC(program, struct prg_desc *, sizeof(struct prg_desc), TRUE); -+ if (!program) -+ return(ENOMEM); -+ -+ program->id = id; -+ program->flags = PRG_RUNNING; -+ program->ncpus = cpus; -+ program->nprocs = 1; -+ program->uid = uid; -+ program->ncaps = 0; -+ program->caps = 0; -+ program->corepath = 0; -+ program->psid = 0; -+ program->start_time = program->sched_time = gettime(); -+ program->end_time = 0; -+ program->accum_atime = 0; -+ program->cutime = 0; -+ program->cstime = 0; -+ program->maxrss = 0; -+ program->memint = 0; -+ program->majflt = 0; -+ program->ebytes = 0; -+ program->exfers = 0; -+ -+ KMEM_ALLOC(pdesc, struct proc_desc *, sizeof(struct proc_desc), TRUE); -+ if (!pdesc) -+ return(ENOMEM); -+ -+ pdesc->proc = CURPROC(); -+ pdesc->next = 0; -+ pdesc->mycap = ELAN_CAP_UNINITIALISED; -+ pdesc->myctx = ELAN_CAP_UNINITIALISED; -+ pdesc->vp = -1; /* rmsloader */ -+ pdesc->program = program; -+ program->pdescs = pdesc; -+ -+#ifdef LINUX -+ rms_create_proc_entry(program); -+#endif -+ -+ kmutex_lock(&rms_lock); -+ -+#if defined(LINUX) -+ if (ptrack_register (rms_ptrack_callback, NULL) != 0) -+ { -+ kmutex_unlock(&rms_lock); -+ KMEM_FREE(pdesc,sizeof(struct proc_desc)); -+ KMEM_FREE(program,sizeof(struct prg_desc)); -+ return(ENOMEM); -+ } -+#else -+ /* -+ * install a fork handler -+ */ -+ if (HANDLER_REGISTER((void *)(unsigned long)rms_xa_callback, NULL, XA_FORK | XA_EXIT | XA_IOF | XA_KOF | XA_KOE) == NULL) -+ { -+ kmutex_unlock(&rms_lock); -+ KMEM_FREE(pdesc,sizeof(struct proc_desc)); -+ KMEM_FREE(program,sizeof(struct prg_desc)); -+ return(ENOMEM); -+ } -+#endif -+ -+ program->next = programs; -+ programs = program; -+ -+#ifdef LINUX -+ MOD_INC_USE_COUNT; -+#endif -+ -+ kmutex_unlock(&rms_lock); -+ return(ESUCCESS); -+} -+ -+ -+/* -+ * rms_prgdestroy -+ * -+ * destroy a program description -+ */ -+int rms_prgdestroy(int id) -+{ -+ struct prg_desc *program, **pp; -+ int status = ESRCH; -+ -+ /* -+ * parallel programs are created and destroyed by the rmsd -+ */ -+ if (CURUID()) -+ return(EACCES); -+ -+ kmutex_lock(&rms_lock); -+ -+ pp = &programs; -+ while ((program = *pp) != NULL) -+ { -+ if (program->id == id) -+ { -+ if (program->nprocs == 0) -+ { -+ DBG(printk("rms_prgdestro :: removing program %d\n", program->id)); -+ *pp = program->next; -+ freeProgram(program); -+ status = ESUCCESS; -+ } -+ else -+ { -+ DBG(printk("rms_prgdestro :: failed to remove program %d: %d\n", program->id, program->nprocs)); -+ status = ECHILD; -+ pp = &program->next; -+ } -+ } -+ else -+ pp = &program->next; -+ } -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+/* -+ * rms_prgids -+ */ -+int rms_prgids(int maxids, int *prgids, int *nprgs) -+{ -+ struct prg_desc *program; -+ int count = 0, *buf, *bufp; -+ int status = ESUCCESS; -+ -+ if (maxids < 1) -+ return(EINVAL); -+ -+ kmutex_lock(&rms_lock); -+ -+ for (program = programs; program; program = program->next) -+ count++; -+ count = MIN(count, maxids); -+ -+ if (count > 0) -+ { -+ KMEM_ALLOC(buf, int *, count * sizeof(int), TRUE); -+ if (buf) -+ { -+ for (program = programs, bufp=buf; bufp < buf + count; -+ program = program->next) -+ *bufp++ = program->id; -+ -+ if (copyout(buf, prgids, sizeof(int) * count)) -+ status = EFAULT; -+ -+ KMEM_FREE(buf, count * sizeof(int)); -+ } -+ else -+ status = ENOMEM; -+ } -+ -+ if (copyout(&count, nprgs, sizeof(int))) -+ status = EFAULT; -+ -+ kmutex_unlock(&rms_lock); -+ -+ return(status); -+} -+ -+/* -+ * rms_prginfo -+ */ -+int rms_prginfo(int id, int maxpids, pid_t *pids, int *nprocs) -+{ -+ struct prg_desc *program; -+ struct proc_desc *pdesc; -+ pid_t *pidp, *buf; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (program->nprocs > 0) -+ { -+ KMEM_ALLOC(buf, pid_t *, program->nprocs * sizeof(pid_t), TRUE); -+ if (buf) -+ { -+ for (pidp = buf, pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ *pidp++ = pdesc->proc->p_pid; -+ -+ if (copyout(buf, pids, sizeof(pid_t) * MIN(program->nprocs, maxpids))) -+ status = EFAULT; -+ -+ KMEM_FREE(buf, program->nprocs * sizeof(pid_t)); -+ } -+ else -+ status = ENOMEM; -+ } -+ -+ if (copyout(&program->nprocs, nprocs, sizeof(int))) -+ status = EFAULT; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ -+ return(status); -+} -+ -+/* -+ * rmsmod always used to use psignal but this doesn't work -+ * on Linux 2.6.7 so we have changed to kill_proc -+ */ -+static void prgsignal(struct prg_desc *program, int signo) -+{ -+ struct proc_desc *pdesc; -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ kill_proc(pdesc->proc->p_pid, signo, 1); -+} -+ -+ -+int rms_prgsignal(int id, int signo) -+{ -+ struct prg_desc *program; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (CURUID() == 0 || CURUID() == program->uid) -+ { -+ prgsignal(program, signo); -+ if (signo == SIGKILL) -+ program->flags |= PRG_KILLED; -+ } -+ else -+ status = EACCES; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ -+ return(status); -+} -+ -+int rms_prgaddcap(int id, int index, ELAN_CAPABILITY *cap) -+{ -+ struct prg_desc *program; -+ struct cap_desc *cdesc; -+ int status = ESUCCESS; -+ -+ if (cap == NULL) -+ return(EINVAL); -+ -+ kmutex_lock(&rms_lock); -+ if ((program = findProgram(id)) != NULL) -+ { -+ KMEM_ALLOC(cdesc, struct cap_desc *, sizeof(struct cap_desc), TRUE); -+ if (cdesc) -+ { -+ cdesc->index = index; -+ if (copyin(cap, &cdesc->cap, sizeof(ELAN_CAPABILITY))) -+ { -+ KMEM_FREE(cdesc, sizeof(struct cap_desc)); -+ status = EFAULT; -+ } -+ else -+ { -+ DBG(printk("rms_prgaddcap :: program %d index %d context %d<-->%d\n", -+ program->id, index, cdesc->cap.cap_lowcontext, cdesc->cap.cap_highcontext)); -+ cdesc->next = program->caps; -+ program->caps = cdesc; -+ program->ncaps++; -+ } -+ } -+ else -+ status = ENOMEM; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+static uint64_t gettime(void) -+{ -+ uint64_t now; -+ -+#if defined(SOLARIS) -+ timespec_t tv; -+ gethrestime(&tv); -+ now = tv.tv_sec * 1000 + tv.tv_nsec / 1000000; -+#elif defined(LINUX) -+ struct timeval tv; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) -+ get_fast_time(&tv); -+#else -+ do_gettimeofday(&tv); -+#endif -+ now = tv.tv_sec * 1000 + tv.tv_usec / 1000; -+#elif defined(DIGITAL_UNIX) -+ struct timeval tv; -+ microtime(&tv); -+ now = tv.tv_sec * 1000 + tv.tv_usec / 1000; -+#endif -+ -+ return(now); -+} -+ -+#ifdef DIGITAL_UNIX -+ -+int rms_getrusage(struct proc_desc *pdesc, struct rusage *ru) -+{ -+ task_t task; -+ thread_t thread; -+ -+ if (!pdesc->proc) -+ return(-1); -+ -+ /* -+ * locking required unless called from the current proc -+ */ -+ if (pdesc->proc != CURPROC()) -+ { -+ if (!P_REF(pdesc->proc)) -+ return(-1); -+ -+ task = proc_to_task(pdesc->proc); -+ if (!task) -+ { -+ P_UNREF(pdesc->proc); -+ DBG(printk("rms_getrusage :: process (%d) has no task\n", pdesc->proc->p_pid)); -+ return(-1); -+ } -+ -+ task_reference(task); -+ task_lock(task); -+ -+ if (!queue_empty(&task->thread_list)) -+ thread = (thread_t) queue_first(&task->thread_list); -+ else -+ { -+ task_unlock(task); -+ task_deallocate(task); -+ P_UNREF(pdesc->proc); -+ return(-1); -+ } -+ -+ thread_reference(thread); -+ task_unlock(task); -+ } -+ -+ *ru = proc_to_utask(pdesc->proc)->uu_ru; -+ task_get_rusage(ru, proc_to_task(pdesc->proc)); -+ -+ if (pdesc->proc != CURPROC()) -+ { -+ task_deallocate(task); -+ thread_deallocate(thread); -+ P_UNREF(pdesc->proc); -+ } -+ return(0); -+} -+ -+#endif -+ -+/* -+ * new stats collection interface, 64-bit with addition of Elan stats -+ */ -+int rms_prggetstats(int id, prgstats_t *stats) -+{ -+#ifdef DIGITAL_UNIX -+ long ruixrss, ruidrss, ruisrss, rumaxrss, rumajflt; -+#endif -+ struct prg_desc *program = 0; -+ struct proc_desc *pdesc; -+ int status = ESUCCESS; -+ prgstats_t totals; -+ uint64_t now = gettime(); -+#if defined(SOLARIS) -+ clock_t utime, stime; -+#elif defined(LINUX) -+ uint64_t utime, stime; -+#endif -+ -+ long maxrss; -+ -+ kmutex_lock(&rms_lock); -+ -+ if (id < 0) -+ { -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ program = pdesc->program; -+ } -+ else -+ program = findProgram(id); -+ -+ if (program) -+ { -+ if (CURUID() == 0 || CURUID() == program->uid) -+ { -+ totals.flags = program->flags; -+ totals.ncpus = program->ncpus; -+ maxrss = 0; -+ -+ if (program->nprocs > 0) -+ totals.etime = now - program->start_time; -+ else -+ totals.etime = program->end_time - program->start_time; -+ -+ totals.atime = program->accum_atime; -+ if (program->flags & PRG_RUNNING) -+ totals.atime += program->ncpus * (now - program->sched_time); -+ -+#if defined(SOLARIS) -+ utime = stime = 0; -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+ utime += pdesc->proc->p_utime; -+ stime += pdesc->proc->p_stime; -+ } -+ totals.utime = TICK_TO_MSEC(utime); -+ totals.stime = TICK_TO_MSEC(stime); -+ -+#elif defined(LINUX) -+ utime = stime = 0; -+ totals.memint = program->memint; -+ totals.pageflts = program->majflt; -+ -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+#ifdef PROCESS_ACCT -+ DBG(printk("rms_prggetsta :: process %d utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, TIMEVAL_TO_CT(&pdesc->proc->utime), -+ TIMEVAL_TO_CT(&pdesc->proc->stime))); -+ utime += TIMEVAL_TO_CT(&pdesc->proc->utime); -+ stime += TIMEVAL_TO_CT(&pdesc->proc->stime); -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+ DBG(printk("rms_prggetsta :: process %d utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, pdesc->proc->times.tms_utime, -+ pdesc->proc->times.tms_stime)); -+ utime += pdesc->proc->times.tms_utime; -+ stime += pdesc->proc->times.tms_stime; -+#else -+ DBG(printk("rms_prggetsta :: process %d utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, pdesc->proc->utime, pdesc->proc->stime)); -+ utime += pdesc->proc->utime; -+ stime += pdesc->proc->stime; -+#endif -+ -+ totals.pageflts += pdesc->proc->maj_flt; -+ -+ maxrss += PROC_RSS(pdesc->proc) >> (20 - PAGE_SHIFT); -+ } -+ -+ /* convert user and system times to millisecs */ -+ totals.utime = CT_TO_MSEC(utime); -+ totals.stime = CT_TO_MSEC(stime); -+ -+#elif defined(DIGITAL_UNIX) -+ totals.utime = totals.stime = 0; -+ totals.memint = program->memint; -+ totals.pageflts = program->majflt; -+ -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+ struct rusage ru; -+ if (rms_getrusage(pdesc, &ru) < 0) -+ continue; -+ -+ totals.utime += TIMEVAL_TO_MSEC(&ru.ru_utime); -+ totals.stime += TIMEVAL_TO_MSEC(&ru.ru_stime); -+ -+ /* convert maxrss to megabytes */ -+ rumaxrss = ru.ru_maxrss >> 10; -+ rumajflt = ru.ru_majflt; -+ totals.pageflts += rumajflt; -+ -+ /* -+ * memory intergals are still broken in 5.1 -+ */ -+ -+#ifdef FIXED_MEMINIT -+ -+ /* convert from pages * clock ticks to Mbytes * secs */ -+ ruixrss = (ru.ru_ixrss >> (20 - PAGE_SHIFT)) / hz; -+ ruidrss = (ru.ru_idrss >> (20 - PAGE_SHIFT)) / hz; -+ ruisrss = (ru.ru_isrss >> (20 - PAGE_SHIFT)) / hz; -+ -+ DBG(printk("rms_prggetsta :: process %d mem %d int %d %d %d flt %d\n", pdesc->proc->p_pid, -+ rumaxrss, ruixrss, ruidrss, ruisrss, rumajflt)); -+ -+ totals.memint += ruixrss + ruidrss + ruisrss; -+#else -+ DBG(printk("rms_prggetsta :: process %d mem %d flt %d\n", pdesc->proc->p_pid, rumaxrss, rumajflt)); -+ totals.memint = 0; -+#endif -+ maxrss += rumaxrss; -+ } -+#endif /* DIGITAL_UNIX */ -+ -+ if (maxrss > program->maxrss) -+ program->maxrss = maxrss; -+ -+ totals.utime += program->cutime; -+ totals.stime += program->cstime; -+ totals.mem = program->maxrss; -+ totals.ebytes = program->ebytes; -+ totals.exfers = program->exfers; -+ -+ DBG(printk("rms_prggetsta :: program %d mem %d flt %d\n", program->id, totals.mem, totals.pageflts)); -+ -+ if (copyout(&totals, stats, sizeof(prgstats_t))) -+ status = EFAULT; -+ } -+ else -+ status = EACCES; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+/* -+ * preserve the old stats stats collection interface -+ */ -+ -+int rms_prggetoldstats(int id, prgstats_old_t *stats) -+{ -+#ifdef DIGITAL_UNIX -+ long ruixrss, ruidrss, ruisrss, rumaxrss, rumajflt; -+#endif -+ struct prg_desc *program = 0; -+ struct proc_desc *pdesc; -+ int status = ESUCCESS; -+ prgstats_old_t totals; -+ uint64_t now = gettime(); -+#if defined(SOLARIS) || defined(LINUX) -+ clock_t utime, stime; -+#endif -+ long maxrss; -+ -+ kmutex_lock(&rms_lock); -+ -+ if (id < 0) -+ { -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ program = pdesc->program; -+ } -+ else -+ program = findProgram(id); -+ -+ if (program) -+ { -+ if (CURUID() == 0 || CURUID() == program->uid) -+ { -+ totals.flags = program->flags; -+ totals.ncpus = program->ncpus; -+ maxrss = 0; -+ -+ if (program->nprocs > 0) -+ totals.etime = now - program->start_time; -+ else -+ totals.etime = program->end_time - program->start_time; -+ -+ totals.atime = program->accum_atime; -+ if (program->flags & PRG_RUNNING) -+ totals.atime += program->ncpus * (now - program->sched_time); -+ -+#if defined(SOLARIS) -+ utime = stime = 0; -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+ utime += pdesc->proc->p_utime; -+ stime += pdesc->proc->p_stime; -+ } -+ totals.utime = TICK_TO_MSEC(utime); -+ totals.stime = TICK_TO_MSEC(stime); -+ -+#elif defined(LINUX) -+ utime = stime = 0; -+ totals.memint = program->memint; -+ totals.pageflts = program->majflt; -+ -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+#ifdef PROCESS_ACCT -+ DBG(printk("rms_getoldsta :: process %d utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, TIMEVAL_TO_CT(&pdesc->proc->utime), -+ TIMEVAL_TO_CT(&pdesc->proc->stime))); -+ utime += TIMEVAL_TO_CT(&pdesc->proc->utime); -+ stime += TIMEVAL_TO_CT(&pdesc->proc->stime); -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+ DBG(printk("rms_getoldsta :: process %d utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, pdesc->proc->times.tms_utime, -+ pdesc->proc->times.tms_stime)); -+ utime += pdesc->proc->times.tms_utime; -+ stime += pdesc->proc->times.tms_stime; -+#else -+ DBG(printk("rms_getoldsta :: process %d utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, pdesc->proc->utime, pdesc->proc->stime)); -+ utime += pdesc->proc->utime; -+ stime += pdesc->proc->stime; -+#endif -+ -+ totals.pageflts += pdesc->proc->maj_flt; -+ maxrss += PROC_RSS(pdesc->proc) >> (20 - PAGE_SHIFT); -+ } -+ -+ /* convert user and system times to millisecs */ -+ totals.utime = CT_TO_MSEC(utime); -+ totals.stime = CT_TO_MSEC(stime); -+ -+#elif defined(DIGITAL_UNIX) -+ totals.utime = totals.stime = 0; -+ totals.memint = program->memint; -+ totals.pageflts = program->majflt; -+ -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ { -+ struct rusage ru; -+ if (rms_getrusage(pdesc, &ru) < 0) -+ continue; -+ -+ totals.utime += TIMEVAL_TO_MSEC(&ru.ru_utime); -+ totals.stime += TIMEVAL_TO_MSEC(&ru.ru_stime); -+ -+ /* convert maxrss to megabytes */ -+ rumaxrss = ru.ru_maxrss >> 10; -+ rumajflt = ru.ru_majflt; -+ totals.pageflts += rumajflt; -+ -+ /* -+ * memory intergals are still broken in 5.1 -+ */ -+ -+#ifdef FIXED_MEMINIT -+ -+ /* convert from pages * clock ticks to Mbytes * secs */ -+ ruixrss = (ru.ru_ixrss >> (20 - PAGE_SHIFT)) / hz; -+ ruidrss = (ru.ru_idrss >> (20 - PAGE_SHIFT)) / hz; -+ ruisrss = (ru.ru_isrss >> (20 - PAGE_SHIFT)) / hz; -+ -+ DBG(printk("rms_getoldsta :: process %d mem %d int %d %d %d flt %d\n", pdesc->proc->p_pid, -+ rumaxrss, ruixrss, ruidrss, ruisrss, rumajflt)); -+ -+ totals.memint += ruixrss + ruidrss + ruisrss; -+#else -+ DBG(printk("rms_getoldsta :: process %d mem %d flt %d\n", pdesc->proc->p_pid, rumaxrss, rumajflt)); -+ totals.memint = 0; -+#endif -+ maxrss += rumaxrss; -+ } -+#endif /* DIGITAL_UNIX */ -+ -+ if (maxrss > program->maxrss) -+ program->maxrss = maxrss; -+ -+ totals.utime += program->cutime; -+ totals.stime += program->cstime; -+ totals.mem = program->maxrss; -+ -+ DBG(printk("rms_getoldsta :: program %d mem %d flt %d\n", program->id, totals.mem, totals.pageflts)); -+ -+ if (copyout(&totals, stats, sizeof(prgstats_old_t))) -+ status = EFAULT; -+ } -+ else -+ status = EACCES; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+ -+int rms_prgsuspend(int id) -+{ -+ struct prg_desc *program; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (CURUID() == 0 || CURUID() == program->uid) -+ { -+ program->flags &= ~PRG_RUNNING; -+ program->flags |= PRG_SUSPEND; -+ program->accum_atime += program->ncpus * (gettime() - program->sched_time); -+ -+ /* suspend/resume just use signals for now */ -+ prgsignal(program, SIGSTOP); -+ } -+ else -+ status = EACCES; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+int rms_prgresume(int id) -+{ -+ struct prg_desc *program; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (CURUID() == 0 || CURUID() == program->uid) -+ { -+ program->flags &= ~PRG_SUSPEND; -+ program->flags |= PRG_RUNNING; -+ program->sched_time = gettime(); -+ prgsignal(program, SIGCONT); -+ } -+ else -+ status = EACCES; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+ -+int rms_ncaps(int *ncaps) -+{ -+ struct proc_desc *pdesc; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ { -+ if (copyout(&pdesc->program->ncaps, ncaps, sizeof(int))) -+ status = EFAULT; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+int rms_getprgid(pid_t pid, int *id) -+{ -+ struct proc_desc *pdesc; -+ int status = ESUCCESS; -+ -+ if (pid == 0) -+ pid = CURPROC()->p_pid; -+ -+ kmutex_lock(&rms_lock); -+ if ((pdesc = findProcess(pid)) != NULL) -+ { -+ if (copyout(&pdesc->program->id, id, sizeof(int))) -+ status = EFAULT; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+int rms_setcap(int index, int ctx) -+{ -+ struct proc_desc *pdesc; -+ struct cap_desc *cdesc; -+ int status = EINVAL; -+ -+ DBG(printk("rms_setcap :: process %d cap %d ctx %d\n",CURPROC()->p_pid,index,ctx)); -+ -+ kmutex_lock(&rms_lock); -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ { -+ for (cdesc = pdesc->program->caps; cdesc; cdesc = cdesc->next) -+ if (cdesc->index == index && 0 <= ctx && ctx <= (cdesc->cap.cap_highcontext - cdesc->cap.cap_lowcontext + 1)) -+ { -+ pdesc->mycap = index; -+ pdesc->myctx = cdesc->cap.cap_lowcontext + ctx; -+ status = ESUCCESS; -+ } -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+ -+int rms_mycap(int *index) -+{ -+ struct proc_desc *pdesc; -+ int status = ESUCCESS; -+ -+ DBG(printk("rms_mycap :: process %d\n", CURPROC()->p_pid)); -+ -+ kmutex_lock(&rms_lock); -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ { -+ DBG(printk("rms_mycap :: found process %d mycap = %d\n", CURPROC()->p_pid, pdesc->mycap)); -+ if (copyout(&pdesc->mycap, index, sizeof(int))) -+ status = EFAULT; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+int rms_getcap(int index, ELAN_CAPABILITY *cap) -+{ -+ struct proc_desc *pdesc; -+ struct cap_desc *cdesc; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ { -+ for (cdesc = pdesc->program->caps; cdesc; cdesc = cdesc->next) -+ if (cdesc->index == index) -+ break; -+ -+ if (cdesc) -+ { -+ /* tell each process about its own context */ -+ cdesc->cap.cap_mycontext = pdesc->myctx; -+ -+ if (copyout(&cdesc->cap, cap, ELAN_CAP_SIZE(&cdesc->cap))) -+ status = EFAULT; -+ -+ DBG(printk("rms_getcap :: program %d index %d context %d<-->%d\n", pdesc->program->id, -+ cdesc->index, cdesc->cap.cap_lowcontext, cdesc->cap.cap_highcontext)); -+ } -+ else -+ status = EINVAL; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+ -+static int -+rms_fork_callback (struct PROC_STRUCT *curproc, struct PROC_STRUCT *child) -+{ -+ struct prg_desc *program; -+ struct proc_desc *parent; -+ struct proc_desc *pdesc = NULL; -+ -+ kmutex_lock(&rms_lock); -+ -+ DBG(printk("rms_fork_func :: phase is fork pid %d child %d\n", curproc->p_pid, child->p_pid)); -+ -+ /* -+ * find the process that forked -+ */ -+ if ((parent = findProcess(curproc->p_pid)) != NULL) -+ { -+ program = parent->program; -+ -+ DBG(printk("rms_fork_func :: program is %d flags %d\n", program->id, program->flags)); -+ -+ /* -+ * processes can be blocked in fork while prgsignal is in progress -+ * so check to see if the PRG_KILLED flag is set -+ */ -+ if (program->flags & PRG_KILLED) -+ DBG(printk("rms_fork_func :: fork handler called after program killed\n")); -+ else -+ { -+ /* -+ * create a new process description and add to program -+ */ -+ KMEM_ALLOC(pdesc, struct proc_desc *, sizeof(struct proc_desc), TRUE); -+ if (pdesc) -+ { -+ pdesc->next = program->pdescs; -+ program->pdescs = pdesc; -+ pdesc->proc = child; -+ pdesc->mycap = parent->mycap; -+ pdesc->myctx = parent->myctx; -+ pdesc->program = program; -+ pdesc->vp = -1; /* assigned by elaninitdone */ -+ program->nprocs++; -+ } -+ else -+ printk("rms_fork_func :: memory allocation failed\n"); -+ } -+ } -+ else -+ DBG(printk("rms_fork_func :: no program\n")); -+ -+ kmutex_unlock (&rms_lock); -+ -+ return pdesc == NULL; -+} -+ -+static void -+rms_exit_callback (struct PROC_STRUCT *curproc) -+{ -+ struct prg_desc *program; -+ struct proc_desc *pdesc, **pdescp, *p; -+#ifdef DIGITAL_UNIX -+ struct rusage ru; -+#endif -+ long maxrss; -+ -+ kmutex_lock(&rms_lock); -+ -+ DBG(printk("rms_exit_func :: process %d exiting\n", curproc->p_pid)); -+ -+ /* -+ * find the process that exited and accumulate -+ * resource usage in its parent program -+ */ -+ for (program = programs, pdesc = 0; program && !pdesc; program = program->next) -+ { -+ pdescp = &program->pdescs; -+ while ((pdesc = *pdescp) != NULL) -+ { -+ if (pdesc->proc->p_pid == curproc->p_pid) -+ { -+ /* -+ * keep track of the resources used -+ */ -+#if defined(SOLARIS) -+ program->cutime += TICK_TO_MSEC(pdesc->proc->p_utime); -+ program->cstime += TICK_TO_MSEC(pdesc->proc->p_stime); -+ -+#elif defined(LINUX) -+#ifdef PROCESS_ACCT -+ DBG(printk("rms_exit_func :: process %d exit utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, -+ TIMEVAL_TO_CT(&pdesc->proc->utime), -+ TIMEVAL_TO_CT(&pdesc->proc->stime))); -+ program->cutime += TIMEVAL_TO_MSEC(&pdesc->proc->utime); -+ program->cstime += TIMEVAL_TO_MSEC(&pdesc->proc->stime); -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+ DBG(printk("rms_exit_func :: process %d exit utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, pdesc->proc->times.tms_utime, -+ pdesc->proc->times.tms_stime)); -+ -+ program->cutime += CT_TO_MSEC(pdesc->proc->times.tms_utime); -+ program->cstime += CT_TO_MSEC(pdesc->proc->times.tms_stime); -+#else -+ DBG(printk("rms_exit_func :: process %d exit utime %ld clks stime %ld clks\n", -+ pdesc->proc->p_pid, pdesc->proc->utime, pdesc->proc->stime)); -+ -+ program->cutime += CT_TO_MSEC(pdesc->proc->utime); -+ program->cstime += CT_TO_MSEC(pdesc->proc->stime); -+#endif -+ program->majflt += pdesc->proc->maj_flt; -+ maxrss = PROC_RSS(pdesc->proc) >> (20 - PAGE_SHIFT); -+ -+#elif defined(DIGITAL_UNIX) -+ if (rms_getrusage(pdesc, &ru) == 0) -+ { -+ program->cutime += TIMEVAL_TO_MSEC(&ru.ru_utime); -+ program->cstime += TIMEVAL_TO_MSEC(&ru.ru_stime); -+ program->majflt += ru.ru_majflt; -+ -+ /* convert maxrss to megabytes */ -+ maxrss = ru.ru_maxrss >> 10; -+ } -+#endif -+ -+ /* -+ * shared memory segment cleanup -+ */ -+#if defined(DIGITAL_UNIX) -+ rms_shmcleanup(-1); -+#elif defined(LINUX) -+ shm_cleanup(); -+#endif -+ -+ /* -+ * remove process from program -+ */ -+ *pdescp = pdesc->next; -+ KMEM_FREE(pdesc, sizeof(struct proc_desc)); -+ program->nprocs--; -+ -+ /* -+ * update the memory high water mark for the program -+ */ -+ for (p = program->pdescs; p; p = p->next) -+ { -+#if defined(DIGITAL_UNIX) -+ if (rms_getrusage(p, &ru) < 0) -+ continue; -+ -+ /* convert maxrss to megabytes */ -+ maxrss += ru.ru_maxrss >> 10; -+ -+#elif defined(LINUX) -+ maxrss += PROC_RSS(p->proc) >> (20 - PAGE_SHIFT); -+#endif -+ } -+ if (maxrss > program->maxrss) -+ program->maxrss = maxrss; -+ -+ DBG(printk("rms_exit_func :: program %d procs %d mem %ld\n", program->id, program->nprocs, program->maxrss)); -+ -+ /* -+ * final update to the program if this is the last process -+ */ -+ if (program->nprocs == 0) -+ { -+ program->end_time = gettime(); -+ program->flags &= ~PRG_RUNNING; -+ program->accum_atime += program->ncpus * (program->end_time - program->sched_time); -+ DBG(printk("rms_exit_func :: last process has gone\n")); -+ } -+ break; -+ } -+ else -+ pdescp = &pdesc->next; -+ } -+ } -+ kmutex_unlock (&rms_lock); -+} -+ -+#if defined(LINUX) -+static int -+rms_ptrack_callback (void *arg, int phase, struct task_struct *child) -+{ -+ switch (phase) -+ { -+ case PTRACK_PHASE_CLONE: -+ if (rms_fork_callback (current, child)) -+ return PTRACK_DENIED; -+ else -+ return PTRACK_INNHERIT; -+ -+ case PTRACK_PHASE_CLONE_FAIL: -+ DBG(printk("rms_fork_func :: fork failed pid %d child %d\n", current->p_pid, child->p_pid)); -+ rms_exit_callback(child); -+ break; -+ -+ case PTRACK_PHASE_EXIT: -+ rms_exit_callback(current); -+ break; -+ } -+ return PTRACK_FINISHED; -+} -+ -+#else -+ -+static void -+rms_xa_callback (void *arg, int phase, void *ctask) -+{ -+ switch (phase) -+ { -+ case XA_FORK: -+ if (rms_fork_callback (CURPROC(), (struct PROC_STRUCT *)task_to_proc(ctask))) -+ psignal(task_to_proc(ctask), SIGKILL); -+ break; -+ case XA_EXIT: -+ rms_exit_callback (CURPROC()); -+ break; -+ } -+} -+ -+#endif -+ -+#ifdef DIGITAL_UNIX -+ -+/* -+ * NB: These functions will only work on steelos. -+ */ -+ -+/* -+ * rms_setcorepath -+ * -+ * set a path at which to dump core if the task aborts -+ * -+ * enhanced core file names must be enabled for this to work -+ */ -+int rms_setcorepath(char *corepath) -+{ -+ int length; -+ char *path; -+ int status; -+ struct proc_desc *pdesc; -+ -+ /* -+ * access restricted - we don't want users moving -+ * their corepath and generating a huge I/O load -+ */ -+ if (CURUID()) -+ return(EACCES); -+ -+ if (!(pdesc = findProcess(CURPROC()->p_pid))) -+ return(ESRCH); -+ -+ if (pdesc->program->corepath) -+ return(EEXIST); -+ -+ KMEM_ALLOC(path, char *, MAXCOREPATHLEN + 1, TRUE); -+ if (path == 0) -+ return(ENOMEM); -+ -+ if (copyinstr(corepath, path, MAXCOREPATHLEN, &length)) -+ return(EFAULT); -+ -+ path[length] = 0; -+ status = add_corepath(path); -+ -+ DBG(printk("rms_setcorepa :: id %d corepath %s status %d\n", pdesc->program->id, path, status)); -+ -+ if (status == ESUCCESS) -+ pdesc->program->corepath = path; -+ else -+ KMEM_FREE(path, MAXCOREPATHLEN + 1); -+ -+ return(status); -+} -+ -+static int find_corepath(pid_t pid, char *path, int len) -+{ -+ struct proc *procp; -+ struct utask *utask; -+ int status = ESUCCESS; -+ -+ procp = pfind(pid); -+ if (procp == NULL) -+ return(ENOENT); -+ -+ utask = proc_to_utask(procp); -+ -+ if (utask->uu_coredir) -+ bcopy(utask->uu_coredir,path,len); -+ else -+ status = ENOENT; -+ -+ /* pfind takes out a reference */ -+ P_UNREF(procp); -+ -+ return(status); -+} -+ -+int rms_getcorepath(pid_t pid, char *corepath, int maxlen) -+{ -+ char src[MAXCOREPATHLEN]; -+ int len; -+ int status; -+ -+ if (maxlen < 2) -+ return(EINVAL); -+ -+ len = MIN(maxlen, MAXCOREPATHLEN); -+ -+ status = find_corepath(pid, src, len); -+ -+ if (status == ESUCCESS) -+ len = strlen(src)+1; -+ else if (status == ENOENT) -+ { -+ len = 2; -+ src[0] = '.'; -+ src[1] = '\0'; -+ status = ESUCCESS; -+ } -+ -+ if (copyout(src, corepath, len)) -+ return(EFAULT); -+ -+ return(status); -+} -+ -+#endif -+ -+/* -+ * rms_elaninitdone - mark a process as having successfully completed elan initialisation -+ */ -+int rms_elaninitdone(int vp) -+{ -+ int status = ESUCCESS; -+ struct proc_desc *pdesc; -+ -+ DBG(printk("rms_elaninit :: process %d vp %d\n", CURPROC()->p_pid, vp)); -+ -+ kmutex_lock(&rms_lock); -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ pdesc->vp = vp; -+ else -+ status = ESRCH; -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+ -+/* -+ * rms_prgelanpids - return the ids of processes that have completed elan initialisation -+ */ -+int rms_prgelanpids(int id, int maxpids, int *vps, pid_t *pids, int *npids) -+{ -+ struct prg_desc *program; -+ struct proc_desc *pdesc; -+ pid_t *pidbuf; -+ int status = ESUCCESS, count = 0, *vpbuf; -+ -+ DBG(printk("rms_elanpids :: process %d id %d\n", CURPROC()->p_pid, id)); -+ -+ kmutex_lock(&rms_lock); -+ -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (program->nprocs > 0) -+ { -+ KMEM_ALLOC(pidbuf, pid_t *, program->nprocs * sizeof(pid_t), TRUE); -+ KMEM_ALLOC(vpbuf, int *, program->nprocs * sizeof(int), TRUE); -+ if (pidbuf && vpbuf) -+ { -+ for (pdesc = program->pdescs; pdesc; pdesc = pdesc->next) -+ if (pdesc->vp >= 0) -+ { -+ pidbuf[count] = pdesc->proc->p_pid; -+ vpbuf[count] = pdesc->vp; -+ count++; -+ } -+ -+ if (count > 0 && (copyout(pidbuf, pids, sizeof(pid_t) * MIN(count, maxpids)) || -+ copyout(vpbuf, vps, sizeof(int) * MIN(count, maxpids)))) -+ status = EFAULT; -+ -+ KMEM_FREE(pidbuf, program->nprocs * sizeof(pid_t)); -+ KMEM_FREE(vpbuf, program->nprocs * sizeof(int)); -+ } -+ else -+ status = ENOMEM; -+ } -+ -+ if (copyout(&count, npids, sizeof(int))) -+ status = EFAULT; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ -+ return(status); -+ -+} -+ -+int rms_setpset(int psid) -+{ -+ struct prg_desc *program; -+ struct proc_desc *pdesc; -+ int status = ESUCCESS; -+ -+ if (CURUID()) -+ return(EACCES); -+ -+ kmutex_lock(&rms_lock); -+ -+ if ((pdesc = findProcess(CURPROC()->p_pid)) != NULL) -+ { -+ program = pdesc->program; -+ program->psid = psid; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+ -+int rms_getpset(int id, int *psid) -+{ -+ struct prg_desc *program; -+ int status = ESUCCESS; -+ -+ kmutex_lock(&rms_lock); -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (copyout(&program->psid, psid, sizeof(int))) -+ status = EFAULT; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+int -+rms_setelanstats(int id, uint64_t ebytes, uint64_t exfers) -+{ -+ struct prg_desc *program; -+ int status = ESUCCESS; -+ -+ DBG(printk("rms_setelanst :: process %d id %d\n", CURPROC()->p_pid, id)); -+ -+ kmutex_lock(&rms_lock); -+ if ((program = findProgram(id)) != NULL) -+ { -+ if (CURUID() == 0 || CURUID() == program->uid) -+ { -+ program->ebytes = ebytes; -+ program->exfers = exfers; -+ } -+ else -+ status = EACCES; -+ } -+ else -+ status = ESRCH; -+ -+ kmutex_unlock(&rms_lock); -+ return(status); -+} -+ -+rms_modversion() -+{ -+ return(RMS_MODVERSION); -+} -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+ -+ -+ -+ -+ -+ -+ -Index: linux-2.4.21/drivers/net/qsnet/rms/rms_kern_Linux.c -=================================================================== ---- linux-2.4.21.orig/drivers/net/qsnet/rms/rms_kern_Linux.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/drivers/net/qsnet/rms/rms_kern_Linux.c 2005-06-01 23:12:54.703423296 -0400 -@@ -0,0 +1,430 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: rms_kern_Linux.c,v 1.20 2004/05/14 08:55:57 duncan Exp $" -+/* $Source: /cvs/master/quadrics/rmsmod/rms_kern_Linux.c,v $*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+MODULE_AUTHOR("Quadrics Ltd"); -+MODULE_DESCRIPTION("RMS support module"); -+MODULE_LICENSE("GPL"); -+ -+int rms_debug = 0; -+ -+ctl_table rms_table[] = { -+ { -+ .ctl_name = 1, -+ .procname = "rms_debug", -+ .data = &rms_debug, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .child = NULL, -+ .proc_handler = &proc_dointvec, -+ }, -+ {0} -+}; -+ -+ctl_table rms_root_table[] = { -+ { -+ .ctl_name = CTL_DEBUG, -+ .procname = "rms", -+ .data = NULL, -+ .maxlen = 0, -+ .mode = 0555, -+ .child = rms_table, -+ }, -+ {0} -+}; -+ -+static struct ctl_table_header *rms_sysctl_header; -+ -+static int rms_open (struct inode *ino, struct file *fp); -+static int rms_release (struct inode *ino, struct file *fp); -+static int rms_ioctl (struct inode *inode, struct file *fp, unsigned int cmd, unsigned long arg); -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+static int -+rms_ioctl32_cmds[] = -+{ -+ RMSIO_GETPRGID32, -+ RMSIO_GETCAP32 -+}; -+ -+static int rms_ioctl32 (unsigned int fd, unsigned int cmd, -+ unsigned long arg, struct file *file); -+#endif -+ -+static struct file_operations rms_fops = -+{ -+ .owner = THIS_MODULE, -+ .ioctl = rms_ioctl, -+ .open = rms_open, -+ .release = rms_release, -+}; -+ -+struct proc_dir_entry *rms_procfs_programs; -+static struct proc_dir_entry *rms_procfs_root; -+ -+int version_callback(char* page, char** start, off_t off, int count, int* eof, void* data) -+{ -+ return(sprintf(page, "$Id: rms_kern_Linux.c,v 1.20 2004/05/14 08:55:57 duncan Exp $\n")); -+} -+ -+static int __init rms_start(void) -+{ -+ struct proc_dir_entry *p; -+ int res; -+ -+ if ((rms_sysctl_header = register_sysctl_table(rms_root_table, 1)) == 0) -+ { -+ printk ("rmsmod: failed to register sysctl table\n"); -+ return (-ENXIO); -+ } -+ -+ if ((rms_procfs_root = proc_mkdir("rms", NULL)) == NULL || -+ (rms_procfs_programs = proc_mkdir("programs", rms_procfs_root)) == NULL || -+ (p = create_proc_entry ("control", S_IRUGO, rms_procfs_root)) == NULL) -+ { -+ unregister_sysctl_table (rms_sysctl_header); -+ printk ("rmsmod: failed to register /proc/rms\n"); -+ return (-ENXIO); -+ } -+ p->proc_fops = &rms_fops; -+ p->owner = THIS_MODULE; -+ p->data = NULL; -+ -+ if ((p = create_proc_entry ("version", S_IRUGO, rms_procfs_root)) != NULL) -+ { -+ p->owner = THIS_MODULE; -+ p->data = NULL; -+ p->read_proc = version_callback; -+ } -+ -+ if ((res = rms_init()) != ESUCCESS) -+ { -+ remove_proc_entry ("programs", rms_procfs_root); -+ remove_proc_entry ("control", rms_procfs_root); -+ remove_proc_entry ("rms", NULL); -+ unregister_sysctl_table (rms_sysctl_header); -+ return (-res); -+ } -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+ lock_kernel(); -+ { -+ extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); -+ register int i; -+ for (i = 0; i < sizeof (rms_ioctl32_cmds)/sizeof(rms_ioctl32_cmds[0]); i++) -+ register_ioctl32_conversion (rms_ioctl32_cmds[i], rms_ioctl32); -+ } -+ unlock_kernel(); -+#endif -+ return (0); -+} -+ -+static void __exit rms_exit(void) -+{ -+ rms_fini(); -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+ lock_kernel(); -+ { -+ extern void unregister_ioctl32_conversion(unsigned int cmd); -+ register int i; -+ -+ for (i = 0; i < sizeof (rms_ioctl32_cmds)/sizeof(rms_ioctl32_cmds[0]); i++) -+ unregister_ioctl32_conversion (rms_ioctl32_cmds[i]); -+ } -+ unlock_kernel(); -+#endif -+ -+ remove_proc_entry ("version", rms_procfs_root); -+ remove_proc_entry ("programs", rms_procfs_root); -+ remove_proc_entry ("control", rms_procfs_root); -+ remove_proc_entry ("rms", NULL); -+ unregister_sysctl_table(rms_sysctl_header); -+} -+ -+/* Declare the module init and exit functions */ -+module_init(rms_start); -+module_exit(rms_exit); -+ -+static int -+rms_open (struct inode *inode, struct file *fp) -+{ -+ MOD_INC_USE_COUNT; -+ fp->private_data = NULL; -+ -+ return (0); -+} -+ -+static int -+rms_release (struct inode *inode, struct file *fp) -+{ -+ MOD_DEC_USE_COUNT; -+ return (0); -+} -+ -+static int -+rms_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, unsigned long arg) -+{ -+ int res; -+ -+ switch (cmd) -+ { -+/* no corepath support in Linux yet */ -+#if 0 -+ case RMSIO_SETCOREPATH: -+ res = rms_setcorepath((caddr_t)arg); -+ break; -+ -+ case RMSIO_GETCOREPATH: -+ { -+ RMSIO_GETCOREPATH_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_getcorepath(args.pid, args.corepath, args.maxlen); -+ break; -+ } -+#endif -+ -+ case RMSIO_PRGCREATE: -+ { -+ RMSIO_PRGCREATE_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prgcreate(args.id, args.uid, args.cpus); -+ break; -+ } -+ -+ case RMSIO_PRGDESTROY: -+ res = rms_prgdestroy(arg); -+ break; -+ -+ case RMSIO_PRGIDS: -+ { -+ RMSIO_PRGIDS_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prgids(args.maxids, args.prgids, args.nprgs); -+ break; -+ } -+ -+ case RMSIO_PRGINFO: -+ { -+ RMSIO_PRGINFO_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prginfo(args.id, args.maxpids, args.pids, args.nprocs); -+ break; -+ } -+ -+ case RMSIO_PRGSIGNAL: -+ { -+ RMSIO_PRGSIGNAL_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prgsignal(args.id, args.signo); -+ break; -+ } -+ -+ case RMSIO_PRGADDCAP: -+ { -+ RMSIO_PRGADDCAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prgaddcap(args.id, args.index, args.cap); -+ break; -+ } -+ -+ case RMSIO_SETCAP: -+ { -+ RMSIO_SETCAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_setcap(args.index, args.ctx); -+ break; -+ } -+ -+ case RMSIO_NCAPS: -+ res = rms_ncaps((int *)arg); -+ break; -+ -+ case RMSIO_GETPRGID: -+ { -+ RMSIO_GETPRGID_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_getprgid(args.pid, args.id); -+ break; -+ } -+ -+ case RMSIO_GETMYCAP: -+ res = rms_mycap((int *)arg); -+ break; -+ -+ case RMSIO_GETCAP: -+ { -+ RMSIO_GETCAP_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_getcap(args.index, args.cap); -+ break; -+ } -+ -+ case RMSIO_PRGGETSTATS: -+ { -+ RMSIO_PRGGETSTATS_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prggetoldstats(args.id, args.stats); -+ break; -+ } -+ -+ case RMSIO_PRGGETSTATS2: -+ { -+ RMSIO_PRGGETSTATS2_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prggetstats(args.id, args.stats); -+ break; -+ } -+ -+ case RMSIO_PRGSUSPEND: -+ res = rms_prgsuspend(arg); -+ break; -+ -+ case RMSIO_PRGRESUME: -+ res = rms_prgresume(arg); -+ break; -+ -+ case RMSIO_ELANINITDONE: -+ res = rms_elaninitdone(arg); -+ break; -+ -+ case RMSIO_PRGELANPIDS: -+ { -+ RMSIO_PRGELANPIDS_STRUCT args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_prgelanpids(args.id, args.maxpids, args.vps, args.pids, args.npids); -+ break; -+ } -+ -+ case RMSIO_SETELANSTATS: -+ { -+ RMSIO_SETELANSTATS_STRUCT args; -+ elanstats_t estats; -+ -+ if (copy_from_user(&args, (void *)arg, sizeof(args)) || -+ copy_from_user(&estats, (void *)args.estats, sizeof(estats))) -+ return(-EFAULT); -+ -+ res = rms_setelanstats(args.id, estats.ebytes, estats.exfers); -+ break; -+ } -+ -+ case RMSIO_MODVERSION: -+ { -+ RMSIO_MODVERSION_STRUCT args; -+ int version = rms_modversion(); -+ -+ if (copy_from_user (&args, (void *)arg, sizeof (args))) -+ return (-EFAULT); -+ -+ if (copyout(&version, args.version, sizeof(int))) -+ res = EFAULT; -+ else -+ res = ESUCCESS; -+ -+ break; -+ } -+ -+ default: -+ res = EINVAL; -+ break; -+ } -+ -+ return ((res == 0) ? 0 : -res); -+} -+ -+#if defined(CONFIG_PPC64) || defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) -+static int -+rms_ioctl32 (unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) -+{ -+ int res; -+ -+ switch (cmd) -+ { -+ case RMSIO_GETPRGID32: -+ { -+ RMSIO_GETPRGID_STRUCT32 args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_getprgid(args.pid, (int *)(unsigned long) args.idptr); -+ break; -+ } -+ -+ case RMSIO_GETCAP32: -+ { -+ RMSIO_GETCAP_STRUCT32 args; -+ -+ if (copy_from_user (&args, (void *) arg, sizeof (args))) -+ return (-EFAULT); -+ -+ res = rms_getcap(args.index, (ELAN_CAPABILITY *)(unsigned long) args.capptr); -+ break; -+ } -+ -+ default: -+ return (sys_ioctl (fd, cmd, arg)); -+ } -+ -+ return ((res == 0) ? 0 : -res); -+} -+#endif -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/fs/exec.c -=================================================================== ---- linux-2.4.21.orig/fs/exec.c 2005-06-01 22:58:09.044063984 -0400 -+++ linux-2.4.21/fs/exec.c 2005-06-01 23:12:54.704423144 -0400 -@@ -51,6 +51,7 @@ - #ifdef CONFIG_KMOD - #include - #endif -+#include - - int core_uses_pid; - char core_pattern[65] = "core"; -@@ -1125,6 +1126,10 @@ - if (retval < 0) - goto out; - -+ -+ /* Notify any ptrack callbacks of the process exec */ -+ ptrack_call_callbacks (PTRACK_PHASE_EXEC, NULL); -+ - retval = search_binary_handler(&bprm,regs); - if (retval >= 0) - /* execve success */ -Index: linux-2.4.21/include/elan/bitmap.h -=================================================================== ---- linux-2.4.21.orig/include/elan/bitmap.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/bitmap.h 2005-06-01 23:12:54.704423144 -0400 -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_BITMAP_H -+#define __QSNET_BITMAP_H -+ -+#ident "$Id: bitmap.h,v 1.5 2004/01/20 17:32:15 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/bitmap.h,v $ */ -+ -+typedef unsigned int bitmap_t; -+ -+#define BT_NBIPUL 32 /* n bits per bitmap_t */ -+#define BT_ULSHIFT 5 /* log 2 BT_NBIPUL to extract word index */ -+#define BT_ULMASK 0x1f /* to extract bit index */ -+ -+#define BT_WIM(bitmap,bitindex) ((bitmap)[(bitindex) >> BT_ULSHIFT]) /* word in map */ -+#define BT_BIW(bitindex) (1 << ((bitindex) & BT_ULMASK)) /* bit in word */ -+ -+/* BT_BITOUL -- n bits to n words */ -+#define BT_BITOUL(nbits) (((nbits) + BT_NBIPUL -1) / BT_NBIPUL) -+ -+#define BT_TEST(bitmap,bitindex) ((BT_WIM((bitmap), (bitindex)) & BT_BIW(bitindex)) ? 1 : 0) -+#define BT_SET(bitmap,bitindex) do { BT_WIM((bitmap), (bitindex)) |= BT_BIW(bitindex); } while (0) -+#define BT_CLEAR(bitmap,bitindex) do { BT_WIM((bitmap), (bitindex)) &= ~BT_BIW(bitindex); } while (0) -+ -+/* return first free bit in the bitmap, or -1 for failure */ -+extern int bt_freebit (bitmap_t *bitmap, int nbits); -+ -+/* return the index of the lowest set bit in the bitmap or -1 for failure */ -+extern int bt_lowbit (bitmap_t *bitmap, int nbits); -+ -+/* return the index of the next set/clear bit in the bitmap or -1 for failure */ -+extern int bt_nextbit (bitmap_t *bitmap, int nbits, int last, int isset); -+ -+/* copy/zero/fill/compare a bit map */ -+extern void bt_copy (bitmap_t *a, bitmap_t *b, int nbits); -+extern void bt_zero (bitmap_t *a, int nbits); -+extern void bt_fill (bitmap_t *a, int nbits); -+extern int bt_cmp (bitmap_t *a, bitmap_t *b, int nbits); -+ -+/* intersect bitmap 'a' with bitmap 'b' and return in 'a' */ -+extern void bt_intersect (bitmap_t *a, bitmap_t *b, int nbits); -+ -+/* remove/add bitmap 'b' from bitmap 'a' */ -+extern void bt_remove (bitmap_t *a, bitmap_t *b, int nbits); -+extern void bt_add (bitmap_t *a, bitmap_t *b, int nbits); -+ -+/* check whether bitmap 'a' spans bitmap 'b' */ -+extern int bt_spans (bitmap_t *a, bitmap_t *b, int nbits); -+ -+/* copy [base,base+nbits-1] from 'a' to 'b' */ -+extern void bt_subset (bitmap_t *a, bitmap_t *b, int base, int nbits); -+ -+/* find bits clear in 'a' and set in 'b', put result in 'c' */ -+extern void bt_up (bitmap_t *a, bitmap_t *b, bitmap_t *c, int nbits); -+ -+/* find bits set in 'a' and clear in 'b', put result in 'c' */ -+extern void bt_down (bitmap_t *a, bitmap_t *b, bitmap_t *c, int nbits); -+ -+/* return number of bits set in bitmap */ -+extern int bt_nbits (bitmap_t *a, int nbits); -+ -+ -+#endif /* __QSNET_BITMAP_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/capability.h -=================================================================== ---- linux-2.4.21.orig/include/elan/capability.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/capability.h 2005-06-01 23:12:54.705422992 -0400 -@@ -0,0 +1,197 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: capability.h,v 1.16 2004/07/20 10:15:33 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/capability.h,v $*/ -+ -+#ifndef __ELAN_CAPABILITY_H -+#define __ELAN_CAPABILITY_H -+ -+#include -+ -+/* Maximum number of rails */ -+#define ELAN_MAX_RAILS (31) -+/* Maximum number of virtual processes we support */ -+#define ELAN_MAX_VPS (16384) -+ -+/* Number of words in a bitmap capability */ -+#define ELAN_BITMAPSIZE BT_BITOUL(ELAN_MAX_VPS) -+ -+/* Guaranteed invalid values */ -+#define ELAN_INVALID_PROCESS (0x7fffffff) /* A GUARANTEED invalid process # */ -+#define ELAN_INVALID_NODE (0xFFFF) -+#define ELAN_INVALID_CONTEXT (0xFFFF) -+ -+/* Number of values in a user key */ -+#define ELAN_USERKEY_ENTRIES 4 -+ -+typedef void * ELAN_CAP_OWNER; -+ -+/* -+ * When used in userspace this is relative to the base of -+ * the capabality but is an absolute location for kernel space. -+ */ -+typedef struct elan_location -+{ -+ unsigned short loc_node; -+ unsigned short loc_context; -+} ELAN_LOCATION; -+ -+typedef struct elan_userkey -+{ -+ unsigned key_values[ELAN_USERKEY_ENTRIES]; -+} ELAN_USERKEY; -+ -+typedef struct elan_capability -+{ -+ ELAN_USERKEY cap_userkey; /* User defined protection */ -+ -+ int cap_version; /* Version number */ -+ unsigned short cap_type; /* Capability Type */ -+ unsigned short cap_spare; /* spare was cap_elan_type */ -+ -+ int cap_lowcontext; /* low context number in block */ -+ int cap_highcontext; /* high context number in block */ -+ int cap_mycontext; /* my context number */ -+ -+ int cap_lownode; /* low elan id of group */ -+ int cap_highnode; /* high elan id of group */ -+ -+ unsigned int cap_railmask; /* which rails this capability is valid for */ -+ -+ bitmap_t cap_bitmap[ELAN_BITMAPSIZE]; /* Bitmap of process to processor translation */ -+} ELAN_CAPABILITY; -+ -+#define ELAN_CAP_UNINITIALISED (-1) -+ -+#define ELAN_CAP_VERSION_NUMBER (0x00010002) -+ -+#define ELAN_CAP_NUM_NODES(cap) ((cap)->cap_highnode - (cap)->cap_lownode + 1) -+#define ELAN_CAP_NUM_CONTEXTS(cap) ((cap)->cap_highcontext - (cap)->cap_lowcontext + 1) -+ -+/* using or defining our own MIN/MAX had confilicts with dunix so we define ELAN_ ones */ -+#define ELAN_MIN(a,b) ((a) > (b) ? (b) : (a)) -+#define ELAN_MAX(a,b) ((a) > (b) ? (a) : (b)) -+#define ELAN_CAP_BITMAPSIZE(cap) (ELAN_MAX (ELAN_MIN (ELAN_CAP_NUM_NODES(cap) * ELAN_CAP_NUM_CONTEXTS(cap), ELAN_MAX_VPS), 0)) -+ -+#define ELAN_CAP_SIZE(cap) (offsetof (ELAN_CAPABILITY, cap_bitmap[BT_BITOUL(ELAN_CAP_BITMAPSIZE(cap))])) -+#define ELAN_CAP_ENTRIES(cap) (((cap)->cap_type & ELAN_CAP_TYPE_NO_BITMAP) ? ELAN_CAP_BITMAPSIZE((cap)) : bt_nbits((cap)->cap_bitmap, ELAN_CAP_BITMAPSIZE((cap)))) -+ -+#define ELAN_CAP_IS_RAIL_SET(cap,rail) ((cap)->cap_railmask & (1<cap_userkey.key_values[0] == (cap2)->cap_userkey.key_values[0] && \ -+ (cap1)->cap_userkey.key_values[1] == (cap2)->cap_userkey.key_values[1] && \ -+ (cap1)->cap_userkey.key_values[2] == (cap2)->cap_userkey.key_values[2] && \ -+ (cap1)->cap_userkey.key_values[3] == (cap2)->cap_userkey.key_values[3]) -+ -+#define ELAN_CAP_TYPE_MATCH(cap1,cap2) ((cap1)->cap_version == (cap2)->cap_version && \ -+ (cap1)->cap_type == (cap2)->cap_type) -+ -+#define ELAN_CAP_GEOM_MATCH(cap1,cap2) ((cap1)->cap_lowcontext == (cap2)->cap_lowcontext && \ -+ (cap1)->cap_highcontext == (cap2)->cap_highcontext && \ -+ (cap1)->cap_lownode == (cap2)->cap_lownode && \ -+ (cap1)->cap_highnode == (cap2)->cap_highnode && \ -+ (cap1)->cap_railmask == (cap2)->cap_railmask && \ -+ !bcmp (&(cap1)->cap_bitmap[0], &(cap2)->cap_bitmap[0], \ -+ BT_BITOUL(ELAN_CAP_BITMAPSIZE(cap1)*sizeof(bitmap_t)))) -+ -+#define ELAN_CAP_MATCH(cap1,cap2) (ELAN_CAP_KEY_MATCH (cap1, cap2) && \ -+ ELAN_CAP_TYPE_MATCH (cap1, cap2) && \ -+ ELAN_CAP_GEOM_MATCH (cap1, cap2)) -+ -+#define ELAN_CAP_VALID_MYCONTEXT(cap) ( ((cap)->cap_lowcontext != ELAN_CAP_UNINITIALISED) \ -+ && ((cap)->cap_mycontext != ELAN_CAP_UNINITIALISED) \ -+ && ((cap)->cap_highcontext != ELAN_CAP_UNINITIALISED) \ -+ && ((cap)->cap_lowcontext <= (cap)->cap_mycontext) \ -+ && ((cap)->cap_mycontext <= (cap)->cap_highcontext)) -+ -+/* -+ * Definitions for type -+ */ -+#define ELAN_CAP_TYPE_BLOCK 1 /* Block distribution */ -+#define ELAN_CAP_TYPE_CYCLIC 2 /* Cyclic distribution */ -+#define ELAN_CAP_TYPE_KERNEL 3 /* Kernel capability */ -+ -+#define ELAN_CAP_TYPE_MASK (0xFFF) /* Mask for type */ -+ -+/* OR these bits in for extra features */ -+#define ELAN_CAP_TYPE_HWTEST (1 << 12) /* Hardware test capability type */ -+#define ELAN_CAP_TYPE_MULTI_RAIL (1 << 13) /* "new" multi rail capability */ -+#define ELAN_CAP_TYPE_NO_BITMAP (1 << 14) /* don't use bit map */ -+#define ELAN_CAP_TYPE_BROADCASTABLE (1 << 15) /* broadcastable */ -+ -+ -+extern void elan_nullcap (ELAN_CAPABILITY *cap); -+extern char *elan_capability_string (ELAN_CAPABILITY *cap, char *str); -+extern ELAN_LOCATION elan_vp2location (unsigned process, ELAN_CAPABILITY *cap); -+extern int elan_location2vp (ELAN_LOCATION location, ELAN_CAPABILITY *cap); -+extern int elan_nvps (ELAN_CAPABILITY *cap); -+extern int elan_nlocal (int node, ELAN_CAPABILITY *cap); -+extern int elan_maxlocal (ELAN_CAPABILITY *cap); -+extern int elan_localvps (int node, ELAN_CAPABILITY *cap, int *vps, int size); -+extern int elan_nrails (ELAN_CAPABILITY *cap); -+extern int elan_rails (ELAN_CAPABILITY *cap, int *rails); -+extern int elan_cap_overlap (ELAN_CAPABILITY *cap1, ELAN_CAPABILITY *cap2); -+ -+/* -+ * capability creation/access fns provide for running -+ * new libelan code on old OS releases -+ */ -+extern int elan_lowcontext(ELAN_CAPABILITY *cap); -+extern int elan_mycontext(ELAN_CAPABILITY *cap); -+extern int elan_highcontext(ELAN_CAPABILITY *cap); -+extern int elan_lownode(ELAN_CAPABILITY *cap); -+extern int elan_highnode(ELAN_CAPABILITY *cap); -+extern int elan_captype(ELAN_CAPABILITY *cap); -+extern int elan_railmask(ELAN_CAPABILITY *cap); -+ -+extern int elan_getenvCap (ELAN_CAPABILITY *cap, int index); -+extern ELAN_CAPABILITY *elan_createCapability(void); -+extern ELAN_CAPABILITY *elan_copyCapability(ELAN_CAPABILITY *from, int ctxShift); -+extern int elan_generateCapability(char *string); -+ -+typedef struct elan_cap_struct -+{ -+ ELAN_CAP_OWNER owner; -+ ELAN_CAPABILITY cap; -+ -+ unsigned int attached; /* count of people attached */ -+ unsigned int active; /* ie not being destroyed */ -+} ELAN_CAP_STRUCT; -+ -+#if ! defined(__KERNEL__) -+extern void elan_get_random_key(ELAN_USERKEY *key); -+extern int elan_prefrails(ELAN_CAPABILITY *cap, int *pref, int nvp); -+#endif -+ -+#if defined(__KERNEL__) -+/* capability.c */ -+extern int elan_validate_cap (ELAN_CAPABILITY *cap); -+extern int elan_validate_map (ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map); -+ -+extern int elan_create_cap (ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap); -+extern int elan_destroy_cap (ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap); -+extern int elan_create_vp (ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map); -+extern int elan_destroy_vp (ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map); -+ -+typedef void (*ELAN_DESTROY_CB)(void *args, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map); -+ -+extern int elan_attach_cap (ELAN_CAPABILITY *cap, unsigned int rail, void *args, ELAN_DESTROY_CB callback); -+extern int elan_detach_cap (ELAN_CAPABILITY *cap, unsigned int rail); -+ -+extern int elan_get_caps (uint *number_of_results, uint array_size, ELAN_CAP_STRUCT *caps); -+extern int elan_cap_dump (void); -+#endif /* __KERNEL__ */ -+ -+ -+#endif /* __ELAN_CAPABILITY_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/cm.h -=================================================================== ---- linux-2.4.21.orig/include/elan/cm.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/cm.h 2005-06-01 23:12:54.706422840 -0400 -@@ -0,0 +1,412 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_CM_H -+#define __ELAN_CM_H -+ -+#ident "@(#)$Id: cm.h,v 1.14.2.1 2004/11/12 10:54:50 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/cm.h,v $*/ -+ -+#include -+ -+#if defined(DIGITAL_UNIX) -+/* -+ * On Tru64 - SMP doesn't mean Symmetric - cpu 0 is a master cpu and is responsible -+ * for handling all PCI interrupts and "funneled" operations. When a kernel thread -+ * is made runnable, the scheduler will choose which cpu it will run on at that time, -+ * and will only execute a higher priority thread from another cpu's run queue when -+ * it becomes totally idle (apparently also including user processes). Also the -+ * assert_wait_mesg_timo function uses a per-cpu timeout - these can only get executed -+ * at "preemptable" places - so again have no guarantee on when they will execute if -+ * they happen to be queued on a "hogged" cpu. The combination of these mean that the Tru64 -+ * is incapable of scheduling a high priority kernel thread within a deterministic time -+ * of when it should have become runnable - wonderfull. -+ * -+ * Hence the solution Compaq have proposed it to schedule a timeout onto all of the -+ * cpu's timeouts lists at the maximum frequency that we could want to execute code, -+ * then to handle the scheduling of work between these ourselves. With a bit of luck -+ * ..... at least one cpu will be sufficiently unloaded to allow us to get a chance -+ * to do our important work. -+ * -+ * However ..... this still is not reliable, since timeouts under Tru64 are still -+ * only run when the currently running kernel thread "co-operates" by calling one -+ * of a number of functions which is permitted to run the "lwc"s AND is not holding -+ * any spinlocks AND is running ai IPL 0. However Compaq are unable to provide -+ * any upper limit on the time between the "lwc"'s being run and so it is possible -+ * for all 4 cpus to not run them for an unbounded time. -+ * -+ * The solution proposed is to use the RM_TEMP_BACKDOOR hook which was added to -+ * hardclock() to "solve" this problem for Memory Channel. However, since it -+ * is called within the clock interrupt it is not permissible to aquire any -+ * spinlocks, nor to run for "too long". This means that it is not possible to -+ * call the heartbeat algorithm from this hook. -+ * -+ * Our solution to these limitations is to use the hook to cause an elan interrupt -+ * to be delivered, by issueing a mis-aligned SetEvent command - this causes the device -+ * to trap and ep_cprocTrap() can then run the heartbeat code. However there is a lock -+ * order violation between the elan_dev::IntrLock and ep_dev::Lock, so we have to -+ * use a trylock and if we fail, then hope that when the interrupt is delievered again -+ * some time later we will succeed. -+ * -+ * However this only works if the kernel is able to respond to the Elan interrupt, -+ * so we panic inside the RM_TEMP_BACKDOOR hook if the SetEvent's interrupt has -+ * not been taken for more than an CM_TIMER_SCHEDULE_TIMEOUT interval. -+ * -+ * In fact this is exactly the mechanism that other operating systems use to -+ * execute timeouts, since the hardclock interrupt posts a low priority -+ * "soft interrupt" which "pre-eempts" the currently running thread and then -+ * executes the timeouts.To block timeouts you use splsoftclock() the same as -+ * in Tru64. -+ */ -+#define PER_CPU_TIMEOUT TRUE -+#endif -+ -+ -+#define CM_SGMTS_PER_LEVEL 8 /* maximum nodes in each segment */ -+#define CM_MAX_LEVELS 6 /* maximum depth of tree */ -+ -+/* message buffers/dmas/events etc */ -+#define CM_NUM_NODE_MSG_BUFFERS (CM_MAX_LEVELS * CM_SGMTS_PER_LEVEL) /* subordinates and leader */ -+#define CM_NUM_SPARE_MSG_BUFFERS 8 /* spare msg buffers for non-connected nodes */ -+#define CM_NUM_MSG_BUFFERS (CM_NUM_NODE_MSG_BUFFERS + CM_NUM_SPARE_MSG_BUFFERS) -+ -+#define CM_INPUTQ_ENTRIES 128 /* # entries in input queue */ -+ -+#define CM_PERIODIC_DISCOVER_INTERVAL (5000) /* 5s (infrequent resolution of established leader conflicts) */ -+#define CM_URGENT_DISCOVER_INTERVAL (50) /* 0.05s (more frequently than heartbeats 'cause they don't retry) */ -+#define CM_HEARTBEAT_INTERVAL (125) /* 0.125s */ -+#define CM_TIMER_SCHEDULE_TIMEOUT (4000) /* 4s Maximum time before a timer that's secheduled to run gets to run (eg blocked in interrupt handlers etc) */ -+#define CM_THREAD_SCHEDULE_TIMEOUT (30000) /* 30s Maximum time before a thread that's scheduled to run gets to run */ -+#define CM_THREAD_RUNNING_TIMEOUT (30000) /* 30s Don't expect the manager thread to be running longer than this */ -+ -+#ifdef PER_CPU_TIMEOUT -+#define CM_PERCPU_TIMEOUT_INTERVAL (50) /* 0.05s (must be less than all above intervals) */ -+#define CM_PACEMAKER_INTERVAL (500) /* 0.05s */ -+ -+#define CM_HEARTBEAT_OVERDUE (250) /* 0.25s Maximum time a timeout can be overdue before taking extreme action */ -+#endif -+ -+#define CM_P2P_DMA_RETRIES 31 -+ -+/* We expect at least 1 point-to-point message in CM_P2P_MSG_RETRIES -+ * attempts to send one to be successfully received */ -+#define CM_P2P_MSG_RETRIES 8 -+ -+/* We expect at least 1 broadcast message in CM_BCAST_MSG_RETRIES attempts -+ * to send one to be successfully received. */ -+#define CM_BCAST_MSG_RETRIES 40 -+ -+/* Heartbeat timeout allows for a node stalling and still getting its -+ * heartbeat. The 2 is to allow for unsynchronised polling times. */ -+#define CM_HEARTBEAT_TIMEOUT (CM_TIMER_SCHEDULE_TIMEOUT + (2 + CM_P2P_MSG_RETRIES) * CM_HEARTBEAT_INTERVAL) -+ -+/* Discover timeout must be > CM_HEARTBEAT_TIMEOUT to guarantee that people -+ * who don't see discovery are considered dead by their leader. This -+ * ensures that by the time a node "discovers" it is a leader of a segment, -+ * the previous leader of that segment will have been deemed to be dead by -+ * its the parent segment's leader */ -+#define CM_DISCOVER_TIMEOUT (CM_TIMER_SCHEDULE_TIMEOUT + (2 + CM_BCAST_MSG_RETRIES) * CM_URGENT_DISCOVER_INTERVAL) -+ -+#define CM_WAITING_TIMEOUT (CM_DISCOVER_TIMEOUT * 100) -+ -+/* -+ * Convert all timeouts specified in mS into "ticks" -+ */ -+#define MSEC2TICKS(MSEC) (((MSEC)*HZ)/1000) -+ -+ -+/* statemap entry */ -+typedef struct cm_state_entry -+{ -+ int16_t level; /* cluster level to apply to */ -+ int16_t offset; /* from statemap_findchange() */ -+ uint16_t seg[BT_NBIPUL/16]; /* ditto */ -+} CM_STATEMAP_ENTRY; -+ -+/* offset is >= 0 for a change to apply and */ -+#define STATEMAP_NOMORECHANGES (-1) /* end of a set of updates */ -+#define STATEMAP_RESET (-2) /* reset the target map */ -+#define STATEMAP_NOOP (-3) /* null token */ -+ -+/* CM message format */ -+typedef int8_t CM_SEQ; /* heartbeat sequence numbers; at least 2 bits, signed */ -+ -+/* -+ * The message header is received into the last 64 byte block of -+ * the input queue and the Version *MUST* be the last word of the -+ * block to ensure that we can see that the whole of the message -+ * has reached main memory after we've seen the input queue pointer -+ * have been updated. -+ */ -+typedef struct ep_cm_hdr -+{ -+ uint32_t Pad0; -+ uint32_t Pad1; -+ -+ uint8_t Type; -+ uint8_t Level; -+ CM_SEQ Seq; /* precision at least 2 bits each*/ -+ CM_SEQ AckSeq; -+ -+ uint16_t NumMaps; -+ uint16_t MachineId; -+ -+ uint16_t NodeId; -+ uint16_t Checksum; -+ -+ uint32_t Timestamp; -+ uint32_t ParamHash; -+ uint32_t Version; -+} CM_HDR; -+ -+#define CM_HDR_SIZE sizeof (CM_HDR) -+ -+typedef struct cm_msg -+{ -+ union { -+ CM_STATEMAP_ENTRY Statemaps[1]; /* piggy-backed statemap updates start here */ -+ uint8_t Space[EP_SYSTEMQ_MSG_MAX - CM_HDR_SIZE]; -+ } Payload; -+ -+ CM_HDR Hdr; -+} CM_MSG; -+ -+/* The maximum number of statemap entries that can fit within an EP_CM_MSG_BUFFER */ -+#define CM_MSG_MAXMAPS (offsetof (CM_MSG, Hdr) / sizeof (CM_STATEMAP_ENTRY)) -+#define CM_MSG_MAP(mapno) (CM_MSG_MAXMAPS - (mapno) - 1) -+ -+/* The actual special message base & size, including 'nmaps' piggy-backed statemap entries */ -+#define CM_MSG_BASE(nmaps) (nmaps == 0 ? offsetof (CM_MSG, Hdr) : offsetof (CM_MSG, Payload.Statemaps[CM_MSG_MAXMAPS - nmaps])) -+#define CM_MSG_SIZE(nmaps) (sizeof (CM_MSG) - CM_MSG_BASE(nmaps)) -+ -+#define CM_MSG_VERSION 0xcad00005 -+#define CM_MSG_TYPE_RESOLVE_LEADER 0 -+#define CM_MSG_TYPE_DISCOVER_LEADER 1 -+#define CM_MSG_TYPE_NOTIFY 2 -+#define CM_MSG_TYPE_DISCOVER_SUBORDINATE 3 -+#define CM_MSG_TYPE_IMCOMING 4 -+#define CM_MSG_TYPE_HEARTBEAT 5 -+#define CM_MSG_TYPE_REJOIN 6 -+ -+/* CM machine segment */ -+typedef struct cm_sgmtMaps -+{ -+ u_char InputMapValid; /* Input map has been set */ -+ u_char OutputMapValid; /* Output map has been set */ -+ u_char SentChanges; /* got an outstanding STATEMAP_NOMORECHANGES to send */ -+ statemap_t *OutputMap; /* state to send */ -+ statemap_t *InputMap; /* state received */ -+ statemap_t *CurrentInputMap; /* state being received */ -+} CM_SGMTMAPS; -+ -+typedef struct cm_sgmt -+{ -+ u_char State; -+ u_char SendMaps; -+ u_char MsgAcked; -+ CM_SEQ MsgSeq; -+ CM_SEQ AckSeq; -+ u_int NodeId; -+ long UpdateTick; -+ long WaitingTick; -+ uint32_t Timestamp; -+ CM_SGMTMAPS Maps[CM_MAX_LEVELS]; /* Maps[i] == state for cluster level i */ -+ u_short MsgNumber; /* msg buffer to use */ -+ u_short NumMaps; /* # maps in message buffer */ -+ u_short Level; -+ u_short Sgmt; -+} CM_SGMT; -+ -+#define CM_SGMT_ABSENT 0 /* no one there at all */ -+#define CM_SGMT_WAITING 1 /* waiting for subtree to connect */ -+#define CM_SGMT_COMING 2 /* expecting a subtree to reconnect */ -+#define CM_SGMT_PRESENT 3 /* connected */ -+ -+typedef struct cm_level -+{ -+ int SwitchLevel; -+ u_int MinNodeId; -+ u_int NumNodes; -+ u_int NumSegs; -+ u_int MySgmt; -+ -+ /* SubordinateMap[i] == OR of all subordinate maps on this level and down for cluster level i */ -+ u_char SubordinateMapValid[CM_MAX_LEVELS]; -+ statemap_t *SubordinateMap[CM_MAX_LEVELS]; -+ -+ /* maps/flags for this cluster level */ -+ u_int Online:1; /* I've gone online (seen myself running) */ -+ u_int Restarting:1; /* driving my owm restart bit */ -+ u_char OfflineReasons; /* forced offline by broadcast */ -+ -+ u_char GlobalMapValid; -+ u_char SubTreeMapValid; -+ u_long Connected; -+ -+ statemap_t *LocalMap; /* state bits I drive */ -+ statemap_t *SubTreeMap; /* OR of my and my subtree states */ -+ statemap_t *GlobalMap; /* OR of all node states */ -+ statemap_t *LastGlobalMap; /* last map I saw */ -+ statemap_t *TmpMap; /* scratchpad */ -+ -+ CM_SGMT Sgmts[CM_SGMTS_PER_LEVEL]; -+} CM_LEVEL; -+ -+#define CM_ROLE_LEADER_CANDIDATE 0 -+#define CM_ROLE_LEADER 1 -+#define CM_ROLE_SUBORDINATE 2 -+ -+/* global status bits */ -+#define CM_GSTATUS_STATUS_MASK 0x03 /* bits nodes drive to broadcast their status */ -+#define CM_GSTATUS_ABSENT 0x00 /* Off the network */ -+#define CM_GSTATUS_STARTING 0x01 /* I'm waiting for everyone to see me online */ -+#define CM_GSTATUS_RUNNING 0x03 /* up and running */ -+#define CM_GSTATUS_CLOSING 0x02 /* I'm waiting for everyone to see me offline */ -+ -+#define CM_GSTATUS_ACK_MASK 0x0c /* bits node drive to ack other status */ -+#define CM_GSTATUS_MAY_START 0x04 /* Everyone thinks I may not start */ -+#define CM_GSTATUS_MAY_RUN 0x08 /* Everyone thinks I may not run */ -+ -+#define CM_GSTATUS_RESTART 0x10 /* Someone thinks I should restart */ -+#define CM_GSTATUS_BITS 5 -+ -+#define CM_GSTATUS_BASE(node) ((node) * CM_GSTATUS_BITS) -+ -+#if defined(PER_CPU_TIMEOUT) -+typedef struct cm_timeout_data -+{ -+ long ScheduledAt; /* lbolt timeout was scheduled to run at */ -+ -+ unsigned long EarlyCount; /* # times run early than NextRun */ -+ unsigned long MissedCount; /* # times run on time - but someone else was running it */ -+ unsigned long WastedCount; /* # times we failed to get the spinlock */ -+ unsigned long WorkCount; /* # times we're the one running */ -+ -+ unsigned long WorstDelay; /* worst scheduling delay */ -+ unsigned long BestDelay; /* best scheduling delay */ -+ -+ unsigned long WorstLockDelay; /* worst delay before getting rail->Lock */ -+ -+ unsigned long WorstHearbeatDelay; /* worst delay before calling DoHeartbeatWork */ -+} CM_TIMEOUT_DATA; -+#endif -+ -+typedef struct cm_rail -+{ -+ EP_RAIL *Rail; /* rail we're associated with */ -+ struct list_head Link; /* and linked on the CM_SUBSYS */ -+ -+ uint32_t ParamHash; /* hash of critical parameters */ -+ uint32_t Timestamp; -+ long DiscoverStartTick; /* when discovery start */ -+ -+ unsigned int NodeId; /* my node id */ -+ unsigned int NumNodes; /* and number of nodes */ -+ unsigned int NumLevels; /* number of levels computed from machine size */ -+ int BroadcastLevel; -+ long BroadcastLevelTick; -+ unsigned int TopLevel; /* level at which I'm not a leader */ -+ unsigned char Role; /* state at TopLevel */ -+ -+ EP_INPUTQ *PolledQueue; /* polled input queue */ -+ EP_INPUTQ *IntrQueue; /* intr input queue */ -+ EP_OUTPUTQ *MsgQueue; /* message */ -+ unsigned int NextSpareMsg; /* next "spare" message buffer to use */ -+ -+ EP_CM_RAIL_STATS Stats; /* statistics */ -+ -+ kmutex_t Mutex; -+ spinlock_t Lock; -+ -+ long NextHeartbeatTime; /* next time to check/send heartbeats */ -+ long NextDiscoverTime; /* next time to progress discovery */ -+ long NextRunTime; /* the earlier of the above two or intr requires inputq poll*/ -+ -+ unsigned int OfflineReasons; /* forced offline by procfs/manager thread stuck */ -+ -+#if defined(PER_CPU_TIMEOUT) -+ spinlock_t HeartbeatTimeoutsLock; /* spinlock to sequentialise per-cpu timeouts */ -+ long HeartbeatTimeoutsStarted; /* bitmap of which timeouts have started */ -+ long HeartbeatTimeoutsStopped; /* bitmap of which timeouts have stopped */ -+ long HeartbeatTimeoutsShouldStop; /* flag to indicate timeouts should stop */ -+ kcondvar_t HeartbeatTimeoutsWait; /* place to sleep waiting for timeouts to stop */ -+ long HeartbeatTimeoutRunning; /* someone is running the timeout - don't try for the lock */ -+ -+ long HeartbeatTimeoutOverdue; /* heartbeat seen as overdue - interrupt requested */ -+ -+ CM_TIMEOUT_DATA *HeartbeatTimeoutsData; /* per timeout data */ -+#else -+ struct timer_list HeartbeatTimer; /* timer for heartbeat/discovery */ -+#endif -+ -+ CM_LEVEL Levels[CM_MAX_LEVELS]; -+} CM_RAIL; -+ -+/* OfflineReasons (both per-rail and */ -+#define CM_OFFLINE_BROADCAST (1 << 0) -+#define CM_OFFLINE_PROCFS (1 << 1) -+#define CM_OFFLINE_MANAGER (1 << 2) -+ -+typedef struct cm_subsys -+{ -+ EP_SUBSYS Subsys; -+ CM_RAIL *Rails[EP_MAX_RAILS]; -+} CM_SUBSYS; -+ -+extern int MachineId; -+ -+extern void cm_node_disconnected (EP_RAIL *rail, unsigned nodeId); -+extern void cm_restart_node (EP_RAIL *rail, unsigned nodeId); -+extern void cm_restart_comms (CM_RAIL *cmRail); -+extern int cm_init (EP_SYS *sys); -+ -+extern void DisplayRail(EP_RAIL *rail); -+extern void DisplaySegs (EP_RAIL *rail); -+extern void DisplayStatus (EP_RAIL *rail); -+ -+typedef struct proc_private -+{ -+ struct nodeset_private *pr_next; -+ EP_RAIL *pr_rail; -+ char *pr_data; -+ int pr_data_len; -+ unsigned pr_off; -+ unsigned pr_len; -+ DisplayInfo pr_di; -+} PROC_PRIVATE; -+ -+extern void proc_character_fill (long mode, char *fmt, ...); -+extern int proc_release (struct inode *inode, struct file *file); -+extern ssize_t proc_read (struct file *file, char *buf, size_t count, loff_t *ppos); -+ -+ -+extern void DisplayNodeMaps (DisplayInfo *di, CM_RAIL *cmRail); -+extern void DisplayNodeSgmts (DisplayInfo *di, CM_RAIL *cmRail); -+extern void DisplayRailDo (DisplayInfo *di, EP_RAIL *rail); -+ -+extern int cm_read_cluster(EP_RAIL *rail,char *page); -+extern void cm_force_offline (EP_RAIL *rail, int offline, unsigned int reason); -+ -+extern int cm_svc_indicator_set (EP_RAIL *rail, int svc_indicator); -+extern int cm_svc_indicator_clear (EP_RAIL *rail, int svc_indicator); -+extern int cm_svc_indicator_is_set (EP_RAIL *rail, int svc_indicator, int nodeId); -+extern int cm_svc_indicator_bitmap (EP_RAIL *rail, int svc_indicator, bitmap_t * bitmap, int low, int nnodes); -+ -+/* cm_procfs.c */ -+extern void cm_procfs_init (CM_SUBSYS *subsys); -+extern void cm_procfs_fini (CM_SUBSYS *subsys); -+extern void cm_procfs_rail_init (CM_RAIL *rail); -+extern void cm_procfs_rail_fini (CM_RAIL *rail); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN_CM_H */ -+ -Index: linux-2.4.21/include/elan/compat.h -=================================================================== ---- linux-2.4.21.orig/include/elan/compat.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/compat.h 2005-06-01 23:12:54.706422840 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: compat.h,v 1.1 2003/12/03 13:18:48 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/compat.h,v $*/ -+ -+#ifndef __ELAN_COMPAT_H -+#define __ELAN_COMPAT_H -+ -+#define ELANMOD_STATS_MAP ELAN_STATS_MAP -+ -+#endif /* __ELAN_COMPAT_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/device.h -=================================================================== ---- linux-2.4.21.orig/include/elan/device.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/device.h 2005-06-01 23:12:54.707422688 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: device.h,v 1.5 2003/09/24 13:55:37 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/device.h,v $*/ -+ -+#ifndef __ELAN_DEVICE_H -+#define __ELAN_DEVICE_H -+ -+/* non-kernel headings */ -+typedef unsigned int ELAN_DEV_IDX; -+ -+#if defined(__KERNEL__) -+ -+/* device callbacks */ -+#define ELAN_DEV_OPS_VERSION ((u_int)1) -+ -+typedef struct elan_dev_ops -+{ -+ /* dev info */ -+ int (*get_position) (void *user_data, ELAN_POSITION *position); -+ int (*set_position) (void *user_data, unsigned short nodeId, unsigned short numNodes); -+ -+ /* cap */ -+ -+ u_int ops_version; -+} ELAN_DEV_OPS; -+ -+typedef struct elan_dev_struct -+{ -+ struct list_head node; -+ -+ ELAN_DEV_IDX devidx; -+ ELAN_DEVINFO *devinfo; -+ void *user_data; -+ ELAN_DEV_OPS *ops; -+} ELAN_DEV_STRUCT; -+ -+/* device.c */ -+extern ELAN_DEV_IDX elan_dev_register (ELAN_DEVINFO *devinfo, -+ ELAN_DEV_OPS *ops, -+ void *userdata); -+extern int elan_dev_deregister (ELAN_DEVINFO *devinfo); -+ -+extern ELAN_DEV_STRUCT * elan_dev_find (ELAN_DEV_IDX devidx); -+ -+extern ELAN_DEV_STRUCT * elan_dev_find_byrail(unsigned short deviceid, unsigned rail); -+extern int elan_dev_dump (void); -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* __ELAN_DEVICE_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/devinfo.h -=================================================================== ---- linux-2.4.21.orig/include/elan/devinfo.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/devinfo.h 2005-06-01 23:12:54.707422688 -0400 -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: devinfo.h,v 1.11 2004/03/12 14:27:39 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/devinfo.h,v $*/ -+ -+#ifndef __ELAN_DEVINFO_H -+#define __ELAN_DEVINFO_H -+ -+#define ELAN_MAX_LEVELS 8 /* maximum number of levels in switch network */ -+ -+typedef struct elan_position -+{ -+ unsigned pos_mode; /* mode we're operating in */ -+ unsigned pos_nodeid; /* port this device connected to */ -+ unsigned pos_levels; /* number of levels to top switch */ -+ unsigned pos_nodes; /* number of nodes in the machine */ -+ unsigned pos_random_disabled; /* levels at which "random" routing is not possible */ -+ unsigned char pos_arity[ELAN_MAX_LEVELS]; /* number of downlinks per switch level */ -+} ELAN_POSITION; -+ -+#define ELAN4_PARAM_PCI_PADDING_FLAGS 0 /* A bit field, representing good places to burst across the pci */ -+#define ELAN4_PARAM_EVENT_COPY_WIN 1 /* The num of cmds when it becomes quicker to send via event copy than write directly */ -+#define ELAN4_PARAM_WRITE_COMBINING 2 /* If set the device supports bursts accesses across the pci bus */ -+#define ELAN4_PARAM_COUNT 12 -+ -+typedef struct elan_params -+{ -+ unsigned values[ELAN4_PARAM_COUNT]; -+} ELAN_PARAMS; -+ -+/* values for pos_mode */ -+#define ELAN_POS_UNKNOWN 0 /* network position unknown */ -+#define ELAN_POS_MODE_SWITCHED 1 /* connected to a switch */ -+#define ELAN_POS_MODE_LOOPBACK 2 /* loopback connector */ -+#define ELAN_POS_MODE_BACKTOBACK 3 /* cabled back-to-back to another node */ -+ -+typedef struct elan_devinfo -+{ -+ unsigned short dev_vendor_id; /* pci vendor id */ -+ unsigned short dev_device_id; /* pci device id */ -+ unsigned char dev_revision_id; /* pci revision id */ -+ unsigned char dev_instance; /* device instance number */ -+ unsigned char dev_rail; /* device rail number */ -+ -+ unsigned short dev_driver_version; /* device driver version */ -+ unsigned short dev_params_mask; /* mask for valid entries in dev_params array */ -+ ELAN_PARAMS dev_params; /* device parametization */ -+ -+ unsigned dev_num_down_links_value; /* MRH hint as to machine size NEEDS coding XXXXX */ -+} ELAN_DEVINFO; -+ -+#define PCI_VENDOR_ID_QUADRICS 0x14fc -+#define PCI_DEVICE_ID_ELAN3 0x0000 -+#define PCI_REVISION_ID_ELAN3_REVA 0x0000 -+#define PCI_REVISION_ID_ELAN3_REVB 0x0001 -+#define PCI_DEVICE_ID_ELAN4 0x0001 -+#define PCI_REVISION_ID_ELAN4_REVA 0x0000 -+#define PCI_REVISION_ID_ELAN4_REVB 0x0001 -+ -+#if defined(__KERNEL__) -+/* devinfo.c */ -+#include -+#include -+extern int elan_get_devinfo (ELAN_DEV_IDX devidx, ELAN_DEVINFO *devinfo); -+extern int elan_get_position (ELAN_DEV_IDX devidx, ELAN_POSITION *position); -+extern int elan_set_position (ELAN_DEV_IDX devidx, unsigned short nodeId, unsigned short numNodes); -+#endif /* __KERNEL__ */ -+ -+ -+#endif /* __ELAN_DEVINFO_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/elanmoddebug.h -=================================================================== ---- linux-2.4.21.orig/include/elan/elanmoddebug.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/elanmoddebug.h 2005-06-01 23:12:54.707422688 -0400 -@@ -0,0 +1,63 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN_DEBUG_H -+#define _ELAN_DEBUG_H -+ -+ -+#ident "$Id: elanmoddebug.h,v 1.5 2003/09/24 13:55:37 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/elanmoddebug.h,v $ */ -+ -+#if defined(__KERNEL__) -+ -+/* 0 | QSNET_DEBUG_BUFFER | QSNET_DEBUG_CONSOLE */ -+extern int elan_debug_mode; -+extern int elan_debug_mask; -+ -+#define ELAN_DBG_VP 0x00000001 -+#define ELAN_DBG_CAP 0x00000002 -+#define ELAN_DBG_CTRL 0x00000004 -+#define ELAN_DBG_SYS_FN 0x00000008 -+#define ELAN_DBG_ALL 0xffffffff -+ -+ -+#if defined(DEBUG_PRINTF) -+# define ELAN_DEBUG0(m,fmt) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt) : (void)0) -+# define ELAN_DEBUG1(m,fmt,a) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt,a) : (void)0) -+# define ELAN_DEBUG2(m,fmt,a,b) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt,a,b) : (void)0) -+# define ELAN_DEBUG3(m,fmt,a,b,c) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt,a,b,c) : (void)0) -+# define ELAN_DEBUG4(m,fmt,a,b,c,d) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt,a,b,c,d) : (void)0) -+# define ELAN_DEBUG5(m,fmt,a,b,c,d,e) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt,a,b,c,d,e) : (void)0) -+# define ELAN_DEBUG6(m,fmt,a,b,c,d,e,f) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode,fmt,a,b,c,d,e,f) : (void)0) -+#ifdef __GNUC__ -+# define ELAN_DEBUG(m,args...) ((elan_debug_mask&(m)) ? qsnet_debugf(elan_debug_mode, ##args) : (void)0) -+#endif -+ -+#else -+ -+# define ELAN_DEBUG0(m,fmt) (0) -+# define ELAN_DEBUG1(m,fmt,a) (0) -+# define ELAN_DEBUG2(m,fmt,a,b) (0) -+# define ELAN_DEBUG3(m,fmt,a,b,c) (0) -+# define ELAN_DEBUG4(m,fmt,a,b,c,d) (0) -+# define ELAN_DEBUG5(m,fmt,a,b,c,d,e) (0) -+# define ELAN_DEBUG6(m,fmt,a,b,c,d,e,f) (0) -+#ifdef __GNUC__ -+# define ELAN_DEBUG(m,args...) -+#endif -+ -+#endif /* DEBUG_PRINTF */ -+ -+ -+#endif /* __KERNEL__ */ -+#endif /* _ELAN_DEBUG_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/elanmod.h -=================================================================== ---- linux-2.4.21.orig/include/elan/elanmod.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/elanmod.h 2005-06-01 23:12:54.708422536 -0400 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elanmod.h,v 1.10 2004/06/18 09:28:16 mike Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/elanmod.h,v $*/ -+ -+#ifndef __ELAN_MOD_H -+#define __ELAN_MOD_H -+ -+#include -+#include -+#include -+#include -+ -+#if defined(__KERNEL__) -+ -+#include -+ -+extern kmutex_t elan_mutex; -+ -+/* elan_general.c */ -+extern int elan_init(void); -+extern int elan_fini(void); -+ -+/* return codes, -ve => errno, +ve => success */ -+#define ELAN_CAP_OK (0) -+#define ELAN_CAP_RMS (1) -+ -+#define ELAN_USER_ATTACH (1) -+#define ELAN_USER_DETACH (2) -+#define ELAN_USER_P2P (3) -+#define ELAN_USER_BROADCAST (4) -+ -+extern int elanmod_classify_cap (ELAN_POSITION *position, ELAN_CAPABILITY *cap, unsigned use); -+ -+#define ELAN_USER_BASE_CONTEXT_NUM 0x000 /* first user allowable context */ -+#define ELAN_USER_TOP_CONTEXT_NUM 0x7FF /* last user allowable context */ -+ -+#define ELAN_RMS_BASE_CONTEXT_NUM 0x400 /* reserved for RMS allocation */ -+#define ELAN_RMS_TOP_CONTEXT_NUM 0x7FF -+ -+#define ELAN_USER_CONTEXT(ctx) ((ctx) >= ELAN_USER_BASE_CONTEXT_NUM && \ -+ (ctx) <= ELAN_USER_TOP_CONTEXT_NUM) -+ -+#define ELAN_RMS_CONTEXT(ctx) ((ctx) >= ELAN_RMS_BASE_CONTEXT_NUM && \ -+ (ctx) <= ELAN_RMS_TOP_CONTEXT_NUM) -+#endif /* __KERNEL__ */ -+ -+#endif /* __ELAN_MOD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/elanmod_linux.h -=================================================================== ---- linux-2.4.21.orig/include/elan/elanmod_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/elanmod_linux.h 2005-06-01 23:12:54.708422536 -0400 -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: elanmod_linux.h,v 1.6 2003/09/29 15:36:20 mike Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/elanmod_linux.h,v $*/ -+ -+#ifndef __ELAN_MOD_LINUX_H -+#define __ELAN_MOD_LINUX_H -+ -+#define ELANCRTL_USER_BASE 0x40 -+ -+/* stats */ -+typedef struct elanctrl_stats_get_next_struct -+{ -+ ELAN_STATS_IDX statidx; -+ ELAN_STATS_IDX *next_statidx; /* return value */ -+} ELANCTRL_STATS_GET_NEXT_STRUCT; -+#define ELANCTRL_STATS_GET_NEXT _IOR ('e', ELANCRTL_USER_BASE + 0, ELANCTRL_STATS_GET_NEXT_STRUCT) -+ -+typedef struct elanctrl_stats_find_index_struct -+{ -+ caddr_t block_name; -+ ELAN_STATS_IDX *statidx; /* return value */ -+ uint *num_entries; /* return value */ -+} ELANCTRL_STATS_FIND_INDEX_STRUCT; -+#define ELANCTRL_STATS_FIND_INDEX _IOR ('e', ELANCRTL_USER_BASE + 1, ELANCTRL_STATS_FIND_INDEX_STRUCT) -+ -+typedef struct elanctrl_stats_get_block_info_struct -+{ -+ ELAN_STATS_IDX statidx; -+ caddr_t block_name; /* return value */ -+ uint *num_entries; /* return value */ -+} ELANCTRL_STATS_GET_BLOCK_INFO_STRUCT; -+#define ELANCTRL_STATS_GET_BLOCK_INFO _IOR ('e', ELANCRTL_USER_BASE + 2, ELANCTRL_STATS_GET_BLOCK_INFO_STRUCT) -+ -+typedef struct elanctrl_stats_get_index_name_struct -+{ -+ ELAN_STATS_IDX statidx; -+ uint index; -+ caddr_t name; /* return value */ -+} ELANCTRL_STATS_GET_INDEX_NAME_STRUCT; -+#define ELANCTRL_STATS_GET_INDEX_NAME _IOR ('e', ELANCRTL_USER_BASE + 3, ELANCTRL_STATS_GET_INDEX_NAME_STRUCT) -+ -+typedef struct elanctrl_stats_clear_block_struct -+{ -+ ELAN_STATS_IDX statidx; -+} ELANCTRL_STATS_CLEAR_BLOCK_STRUCT; -+#define ELANCTRL_STATS_CLEAR_BLOCK _IOR ('e', ELANCRTL_USER_BASE + 4, ELANCTRL_STATS_CLEAR_BLOCK_STRUCT) -+ -+typedef struct elanctrl_stats_get_block_struct -+{ -+ ELAN_STATS_IDX statidx; -+ uint entries; -+ ulong *values; /* return values */ -+} ELANCTRL_STATS_GET_BLOCK_STRUCT; -+#define ELANCTRL_STATS_GET_BLOCK _IOR ('e', ELANCRTL_USER_BASE + 5, ELANCTRL_STATS_GET_BLOCK_STRUCT) -+ -+ -+typedef struct elanctrl_get_devinfo_struct -+{ -+ ELAN_DEV_IDX devidx; -+ ELAN_DEVINFO *devinfo; /* return values */ -+} ELANCTRL_GET_DEVINFO_STRUCT; -+#define ELANCTRL_GET_DEVINFO _IOR ('e', ELANCRTL_USER_BASE + 6, ELANCTRL_GET_DEVINFO_STRUCT) -+ -+typedef struct elanctrl_get_position_struct -+{ -+ ELAN_DEV_IDX devidx; -+ ELAN_POSITION *position; /* return values */ -+} ELANCTRL_GET_POSITION_STRUCT; -+#define ELANCTRL_GET_POSITION _IOR ('e', ELANCRTL_USER_BASE + 7, ELANCTRL_GET_POSITION_STRUCT) -+ -+typedef struct elanctrl_set_position_struct -+{ -+ ELAN_DEV_IDX devidx; -+ unsigned short nodeId; -+ unsigned short numNodes; -+} ELANCTRL_SET_POSITION_STRUCT; -+#define ELANCTRL_SET_POSITION _IOR ('e', ELANCRTL_USER_BASE + 8, ELANCTRL_SET_POSITION_STRUCT) -+ -+typedef struct elanctrl_create_cap_struct -+{ -+ ELAN_CAPABILITY cap; -+} ELANCTRL_CREATE_CAP_STRUCT; -+#define ELANCTRL_CREATE_CAP _IOW ('e', ELANCRTL_USER_BASE + 9, ELANCTRL_CREATE_CAP_STRUCT) -+ -+typedef struct elanctrl_destroy_cap_struct -+{ -+ ELAN_CAPABILITY cap; -+} ELANCTRL_DESTROY_CAP_STRUCT; -+#define ELANCTRL_DESTROY_CAP _IOW ('e', ELANCRTL_USER_BASE + 10, ELANCTRL_DESTROY_CAP_STRUCT) -+ -+typedef struct elanctrl_create_vp_struct -+{ -+ ELAN_CAPABILITY cap; -+ ELAN_CAPABILITY map; -+} ELANCTRL_CREATE_VP_STRUCT; -+#define ELANCTRL_CREATE_VP _IOW ('e', ELANCRTL_USER_BASE + 11, ELANCTRL_CREATE_VP_STRUCT) -+ -+typedef struct elanctrl_destroy_vp_struct -+{ -+ ELAN_CAPABILITY cap; -+ ELAN_CAPABILITY map; -+} ELANCTRL_DESTROY_VP_STRUCT; -+#define ELANCTRL_DESTROY_VP _IOW ('e', ELANCRTL_USER_BASE + 12, ELANCTRL_DESTROY_VP_STRUCT) -+ -+#define ELANCTRL_DEBUG_DUMP _IO ('e', ELANCRTL_USER_BASE + 13) -+ -+typedef struct elanctrl_get_caps_struct -+{ -+ uint *number_of_results; -+ uint array_size; -+ ELAN_CAP_STRUCT *caps; -+} ELANCTRL_GET_CAPS_STRUCT; -+#define ELANCTRL_GET_CAPS _IOW ('e', ELANCRTL_USER_BASE + 14, ELANCTRL_GET_CAPS_STRUCT) -+ -+ -+typedef struct elanctrl_debug_buffer_struct -+{ -+ caddr_t buffer; -+ int size; -+} ELANCTRL_DEBUG_BUFFER_STRUCT; -+#define ELANCTRL_DEBUG_BUFFER _IOW ('e', ELANCRTL_USER_BASE + 15, ELANCTRL_DEBUG_BUFFER_STRUCT) -+ -+#define ELANMOD_PROCFS_IOCTL "/proc/qsnet/elan/ioctl" -+#define ELANMOD_PROCFS_VERSION "/proc/qsnet/elan/version" -+#define ELANMOD_PROCFS_DEBUG_MASK "/proc/qsnet/elan/debug_mask" -+#define ELANMOD_PROCFS_DEBUG_MODE "/proc/qsnet/elan/debug_mode" -+ -+#endif /* __ELAN_MOD_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/elanmod_subsystem.h -=================================================================== ---- linux-2.4.21.orig/include/elan/elanmod_subsystem.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/elanmod_subsystem.h 2005-06-01 23:12:54.708422536 -0400 -@@ -0,0 +1,138 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_SUBSYSTEM_H -+#define __ELAN_SUBSYSTEM_H -+ -+#include -+#include -+ -+#if defined( __KERNEL__) -+int elan_configure( -+ cfg_op_t op, -+ caddr_t indata, -+ ulong indata_size, -+ caddr_t outdata, -+ ulong outdata_size); -+#endif -+ -+#define ELAN_KMOD_CODE(x) ((x)+CFG_OP_SUBSYS_MIN) -+#define ELAN_MAX_KMOD_CODES 100 -+ -+#define ELAN_SUBSYS "elan" -+ -+#define ELAN_STATS_GET_NEXT 0x01 -+typedef struct { -+ ELAN_STATS_IDX statidx; -+ ELAN_STATS_IDX *next_statidx; -+} elan_stats_get_next_struct; -+ -+ -+#define ELAN_STATS_FIND_INDEX 0x02 -+typedef struct { -+ caddr_t block_name; -+ ELAN_STATS_IDX *statidx; /* return value */ -+ uint *num_entries; /* return value */ -+} elan_stats_find_index_struct; -+ -+#define ELAN_STATS_GET_BLOCK_INFO 0x03 -+typedef struct { -+ ELAN_STATS_IDX statidx; -+ caddr_t block_name; /* return value */ -+ uint *num_entries; /* return value */ -+} elan_stats_get_block_info_struct; -+ -+#define ELAN_STATS_GET_INDEX_NAME 0x04 -+typedef struct { -+ ELAN_STATS_IDX statidx; -+ uint index; -+ caddr_t name; /* return value */ -+} elan_stats_get_index_name_struct; -+ -+#define ELAN_STATS_CLEAR_BLOCK 0x05 -+typedef struct { -+ ELAN_STATS_IDX statidx; -+} elan_stats_clear_block_struct; -+ -+#define ELAN_STATS_GET_BLOCK 0x06 -+typedef struct -+{ -+ ELAN_STATS_IDX statidx; -+ uint entries; -+ ulong *values; /* return values */ -+} elan_stats_get_block_struct; -+ -+#define ELAN_GET_DEVINFO 0x07 -+typedef struct -+{ -+ ELAN_DEV_IDX devidx; -+ ELAN_DEVINFO *devinfo; /* return values */ -+} elan_get_devinfo_struct; -+ -+#define ELAN_GET_POSITION 0x08 -+typedef struct { -+ ELAN_DEV_IDX devidx; -+ ELAN_POSITION *position; /* return values */ -+} elan_get_position_struct; -+ -+#define ELAN_SET_POSITION 0x09 -+typedef struct { -+ ELAN_DEV_IDX devidx; -+ unsigned short nodeId; -+ unsigned short numNodes; -+} elan_set_position_struct; -+ -+#define ELAN_CREATE_CAP 0x0a -+typedef struct { -+ ELAN_CAPABILITY cap; -+} elan_create_cap_struct; -+ -+#define ELAN_DESTROY_CAP 0x0b -+typedef struct { -+ ELAN_CAPABILITY cap; -+} elan_destroy_cap_struct; -+ -+#define ELAN_CREATE_VP 0x0c -+typedef struct { -+ ELAN_CAPABILITY cap; -+ ELAN_CAPABILITY map; -+} elan_create_vp_struct; -+ -+#define ELAN_DESTROY_VP 0x0d -+typedef struct { -+ ELAN_CAPABILITY cap; -+ ELAN_CAPABILITY map; -+} elan_destroy_vp_struct; -+ -+ -+#define ELAN_DEBUG_DUMP 0x0e -+ -+#define ELAN_GET_CAPS 0x0f -+typedef struct { -+ uint *number_of_results; -+ uint array_size; -+ ELAN_CAP_STRUCT *caps; -+} elan_get_caps_struct; -+ -+#define ELAN_DEBUG_BUFFER 0x10 -+typedef struct { -+ caddr_t addr; -+ int len; -+} elan_debug_buffer_struct; -+ -+#define ELANMOD_PROCFS_IOCTL "/proc/qsnet/elan/ioctl" -+#define ELANMOD_PROCFS_VERSION "/proc/qsnet/elan/version" -+#define ELANMOD_PROCFS_DEBUG_MASK "/proc/qsnet/elan/debug_mask" -+#define ELANMOD_PROCFS_DEBUG_MODE "/proc/qsnet/elan/debug_mode" -+ -+#endif /* __ELAN_SUBSYSTEM_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/epcomms.h -=================================================================== ---- linux-2.4.21.orig/include/elan/epcomms.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/epcomms.h 2005-06-01 23:12:54.710422232 -0400 -@@ -0,0 +1,635 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_EPCOMMS_H -+#define __ELAN_EPCOMMS_H -+ -+#ident "$Id: epcomms.h,v 1.44.2.2 2004/11/12 10:54:50 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epcomms.h,v $ */ -+ -+#include -+#include -+ -+#define EPCOMMS_SUBSYS_NAME "epcomms" -+ -+/* message service numbers */ -+#define EP_MSG_SVC_EIP512 0x00 /* Quadrics EIP services */ -+#define EP_MSG_SVC_EIP1K 0x01 -+#define EP_MSG_SVC_EIP2K 0x02 -+#define EP_MSG_SVC_EIP4K 0x03 -+#define EP_MSG_SVC_EIP8K 0x04 -+#define EP_MSG_SVC_EIP16K 0x05 -+#define EP_MSG_SVC_EIP32K 0x06 -+#define EP_MSG_SVC_EIP64K 0x07 -+#define EP_MSG_SVC_EIP128K 0x08 -+ -+#define EP_MSG_SVC_PFS 0x09 /* Quadrics PFS rpc service */ -+ -+#define EP_MSG_SVC_PORTALS_SMALL 0x10 /* Lustre Portals */ -+#define EP_MSG_SVC_PORTALS_LARGE 0x11 -+ -+#define EP_MSG_NSVC 0x40 /* Max number of services */ -+ -+#define EP_MSGQ_ADDR(qnum) (EP_EPCOMMS_QUEUE_BASE + (qnum) * EP_QUEUE_DESC_SIZE) -+ -+/* -+ * EP_ENVELOPE -+ * Messages are sent by sending an envelope to the destination -+ * describing the source buffers to transfer. The receiving thread -+ * then allocates a receive buffer and fetches the data by issuing -+ * "get" dmas. -+ * -+ * NOTE: envelopes are not explicitly converted to network byte order -+ * since they are always transferred little endian as they are -+ * copied to/from elan memory using word operations. -+ */ -+typedef struct ep_envelope -+{ -+ uint32_t Version; /* Protocol version field */ -+ -+ EP_ATTRIBUTE Attr; /* Attributes */ -+ -+ EP_XID Xid; /* transaction id */ -+ -+ uint32_t NodeId; /* Source processor */ -+ uint32_t Range; /* range we're sending to (high << 16 | low) */ -+ -+ EP_ADDR TxdRail; /* address of per-rail txd */ -+ EP_NMD TxdMain; /* address of main memory portion of txd */ -+ -+ uint32_t nFrags; /* # fragments */ -+ EP_NMD Frags[EP_MAXFRAG]; /* network mapping handles of source data */ -+ -+ uint32_t CheckSum; /* holds the check sum value when active -+ * must be after all members to be checksum'd -+ */ -+ -+ uint32_t Pad[6]; /* Pad to 128 bytes */ -+} EP_ENVELOPE; -+ -+#define EP_ENVELOPE_VERSION 0xdac10001 -+#define EP_ENVELOPE_SIZE roundup (sizeof (EP_ENVELOPE), EP_BLK_SIZE) -+ -+/* -+ * RPC payload - this small amount of data is transfered in -+ * the envelope for RPCs -+ */ -+typedef struct ep_payload -+{ -+ uint32_t Data[128/sizeof(uint32_t)]; -+} EP_PAYLOAD; -+ -+#define EP_PAYLOAD_SIZE roundup (sizeof (EP_PAYLOAD), EP_BLK_SIZE) -+ -+#define EP_INPUTQ_SIZE (EP_ENVELOPE_SIZE + EP_PAYLOAD_SIZE) -+ -+/* -+ * EP_STATUSBLK -+ * RPC completion transfers a status block to the client. -+ */ -+typedef struct ep_statusblk -+{ -+ uint32_t Data[128/sizeof(uint32_t)]; -+} EP_STATUSBLK; -+ -+#define EP_STATUSBLK_SIZE roundup (sizeof(EP_STATUSBLK), EP_BLK_SIZE) -+ -+#define EP_RANGE(low,high) ((high) << 16 | (low)) -+#define EP_RANGE_LOW(range) ((range) & 0xFFFF) -+#define EP_RANGE_HIGH(range) (((range) >> 16) & 0xFFFF) -+ -+/* return codes from functions, + 'res' parameter to txd callback, ep_rxd_status() */ -+typedef enum -+{ -+ EP_SUCCESS = 0, /* message sent/received successfully */ -+ EP_RXD_PENDING = -1, /* rxd not completed by thread */ -+ EP_CONN_RESET = -2, /* virtual circuit reset */ -+ EP_NODE_DOWN = -3, /* node down - transmit not attempted */ -+ EP_MSG_TOO_BIG = -4, /* received message larger than buffer */ -+ EP_ENOMEM = -5, /* memory alloc failed */ -+ EP_EINVAL = -6, /* invalid parameters */ -+ EP_SHUTDOWN = -7, /* receiver is being shut down */ -+} EP_STATUS; -+ -+/* forward declarations */ -+typedef struct ep_rxd EP_RXD; -+typedef struct ep_txd EP_TXD; -+typedef struct ep_rcvr_rail EP_RCVR_RAIL; -+typedef struct ep_rcvr EP_RCVR; -+typedef struct ep_xmtr_rail EP_XMTR_RAIL; -+typedef struct ep_xmtr EP_XMTR; -+typedef struct ep_comms_rail EP_COMMS_RAIL; -+typedef struct ep_comms_subsys EP_COMMS_SUBSYS; -+ -+typedef struct ep_rcvr_stats EP_RCVR_STATS; -+typedef struct ep_xmtr_stats EP_XMTR_STATS; -+typedef struct ep_rcvr_rail_stats EP_RCVR_RAIL_STATS; -+typedef struct ep_xmtr_rail_stats EP_XMTR_RAIL_STATS; -+ -+typedef void (EP_RXH)(EP_RXD *rxd); /* callback function from receive completion */ -+typedef void (EP_TXH)(EP_TXD *txd, void *arg, EP_STATUS res); /* callback function from transmit completion */ -+ -+/* Main memory portion shared descriptor */ -+typedef struct ep_rxd_main -+{ -+ EP_ENVELOPE Envelope; /* 128 byte aligned envelope */ -+ EP_PAYLOAD Payload; /* 128 byte aligned payload */ -+ bitmap_t Bitmap[BT_BITOUL(EP_MAX_NODES)]; /* broadcast bitmap */ -+ EP_STATUSBLK StatusBlk; /* RPC status block to return */ -+ uint64_t Next; /* linked list when on active list (main address) */ -+ int32_t Len; /* Length of message received */ -+} EP_RXD_MAIN; -+ -+#define EP_RXD_MAIN_SIZE roundup (sizeof (EP_RXD_MAIN), EP_BLK_SIZE) -+ -+/* Phases for message/rpc */ -+#ifndef __ELAN__ -+ -+/* Kernel memory portion of per-rail receive descriptor */ -+typedef struct ep_rxd_rail -+{ -+ struct list_head Link; /* linked on freelist */ -+ EP_RCVR_RAIL *RcvrRail; /* rvcr we're associated with */ -+ -+ EP_RXD *Rxd; /* receive descriptor we're bound to */ -+} EP_RXD_RAIL; -+ -+#define RXD_BOUND2RAIL(rxdRail,rcvrRail) ((rxdRail) != NULL && ((EP_RXD_RAIL *) (rxdRail))->RcvrRail == (EP_RCVR_RAIL *) rcvrRail) -+ -+struct ep_rxd -+{ -+ struct list_head Link; /* linked on free/active list */ -+ EP_RCVR *Rcvr; /* owning receiver */ -+ -+ EP_RXD_MAIN *RxdMain; /* shared main memory portion. */ -+ EP_NMD NmdMain; /* and network mapping descriptor */ -+ -+ EP_RXD_RAIL *RxdRail; /* per-rail rxd we're bound to */ -+ -+ EP_RXH *Handler; /* completion function */ -+ void *Arg; /* and arguement */ -+ -+ unsigned int State; /* RXD status (active,stalled,failed) */ -+ -+ EP_NMD Data; /* network mapping descriptor for user buffer */ -+ -+ int nFrags; /* network mapping descriptor for put/get/complete */ -+ EP_NMD Local[EP_MAXFRAG]; -+ EP_NMD Remote[EP_MAXFRAG]; -+ -+ long NextRunTime; /* time to resend failover/map requests */ -+ EP_XID MsgXid; /* and transaction id */ -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ struct list_head CheckSumLink; /* linked on check sum list */ -+#endif -+}; -+ -+#define EP_NUM_RXD_PER_BLOCK 16 -+ -+/* rxd->State */ -+#define EP_RXD_FREE 0 -+ -+#define EP_RXD_RECEIVE_UNBOUND 1 -+#define EP_RXD_RECEIVE_ACTIVE 2 -+ -+#define EP_RXD_PUT_ACTIVE 3 -+#define EP_RXD_PUT_STALLED 4 -+#define EP_RXD_GET_ACTIVE 5 -+#define EP_RXD_GET_STALLED 6 -+ -+#define EP_RXD_COMPLETE_ACTIVE 7 -+#define EP_RXD_COMPLETE_STALLED 8 -+ -+#define EP_RXD_RPC_IN_PROGRESS 9 -+#define EP_RXD_COMPLETED 10 -+ -+#define EP_RXD_BEEN_ABORTED 11 /* rxd was aborted while in a private state */ -+ -+typedef struct ep_rxd_block -+{ -+ struct list_head Link; -+ -+ EP_NMD NmdMain; -+ -+ EP_RXD Rxd[EP_NUM_RXD_PER_BLOCK]; -+} EP_RXD_BLOCK; -+ -+struct ep_rcvr_rail_stats -+{ -+ EP_STATS_COUNT rx; -+ EP_STATS_COUNT rx_len; -+}; -+ -+struct ep_rcvr_rail -+{ -+ EP_RCVR *Rcvr; /* associated receiver */ -+ EP_COMMS_RAIL *CommsRail; /* comms rail */ -+ -+ struct proc_dir_entry *procfs_root; /* root of this rcvr_rail's procfs entry */ -+ EP_RCVR_RAIL_STATS stats; /* generic rcvr_rail stats */ -+}; -+ -+struct ep_rcvr_stats -+{ -+ EP_STATS_COUNT rx; -+ EP_STATS_COUNT rx_len; -+}; -+ -+struct ep_rcvr -+{ -+ struct list_head Link; /* queued on subsystem */ -+ EP_COMMS_SUBSYS *Subsys; /* kernel comms subsystem */ -+ EP_SERVICE Service; /* service number */ -+ -+ unsigned int InputQueueEntries; /* # entries on receive queue */ -+ -+ EP_RAILMASK RailMask; /* bitmap of which rails are available */ -+ EP_RCVR_RAIL *Rails[EP_MAX_RAILS]; -+ -+ spinlock_t Lock; /* spinlock for rails/receive lists */ -+ -+ struct list_head ActiveDescList; /* List of pending/active receive descriptors */ -+ -+ EP_XID_CACHE XidCache; /* XID cache (protected by Lock) */ -+ -+ struct list_head FreeDescList; /* List of free receive descriptors */ -+ unsigned int FreeDescCount; /* and number on free list */ -+ unsigned int TotalDescCount; /* total number created */ -+ spinlock_t FreeDescLock; /* and lock for free list */ -+ kcondvar_t FreeDescSleep; /* with place to sleep for rx desc */ -+ int FreeDescWanted; /* and flag */ -+ struct list_head DescBlockList; -+ -+ unsigned int ForwardRxdCount; /* count of rxd's being forwarded */ -+ unsigned int CleanupWaiting; /* waiting for cleanup */ -+ kcondvar_t CleanupSleep; /* and place to sleep */ -+ -+ struct proc_dir_entry *procfs_root; /* place where this rcvr's proc entry is */ -+ EP_RCVR_STATS stats; -+}; -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+#define EP_ENVELOPE_CHECK_SUM (1<<31) -+extern uint32_t ep_calc_check_sum (EP_SYS *sys, EP_ENVELOPE *env, EP_NMD *nmd, int nFrags); -+#endif -+ -+#endif /* ! __ELAN__ */ -+ -+typedef struct ep_txd_main -+{ -+ EP_STATUSBLK StatusBlk; /* RPC status block */ -+ bitmap_t Bitmap[BT_BITOUL(EP_MAX_NODES)]; /* broadcast bitmap */ -+} EP_TXD_MAIN; -+ -+#define EP_TXD_MAIN_SIZE roundup (sizeof (EP_TXD_MAIN), EP_BLK_SIZE) -+ -+#ifndef __ELAN__ -+typedef struct ep_txd_rail -+{ -+ struct list_head Link; /* linked on freelist */ -+ EP_XMTR_RAIL *XmtrRail; /* xmtr we're associated with */ -+ -+ EP_TXD *Txd; /* txd we're bound to */ -+} EP_TXD_RAIL; -+ -+#define TXD_BOUND2RAIL(rxdRail,xmtrRail) ((txdRail) != NULL && ((EP_TXD_RAIL *) (txdRail))->XmtrRail == (EP_XMTR_RAIL *) xmtrRail) -+ -+struct ep_txd -+{ -+ struct list_head Link; /* linked on free/active list */ -+ EP_XMTR *Xmtr; /* service we're associated with */ -+ -+ EP_TXD_MAIN *TxdMain; /* shared main memory portion */ -+ EP_NMD NmdMain; /* and network mapping descriptor */ -+ -+ EP_TXD_RAIL *TxdRail; /* per-rail txd for this phase */ -+ -+ EP_TXH *Handler; /* completion function */ -+ void *Arg; /* and arguement */ -+ -+ unsigned short NodeId; /* node transmit is to. */ -+ EP_SERVICE Service; /* and seervice */ -+ -+ long TimeStamp; /* time we where created at, to find sends taking too long */ -+ long RetryTime; -+ EP_BACKOFF Backoff; -+ -+ EP_ENVELOPE Envelope; /* envelope for transmit */ -+ EP_PAYLOAD Payload; /* payload for transmit */ -+}; -+ -+#define EP_NUM_TXD_PER_BLOCK 16 -+ -+/* "phase" parameter to BindTxd */ -+#define EP_TXD_PHASE_ACTIVE 1 -+#define EP_TXD_PHASE_PASSIVE 2 -+ -+typedef struct ep_txd_block -+{ -+ struct list_head Link; -+ EP_NMD NmdMain; -+ EP_TXD Txd[EP_NUM_TXD_PER_BLOCK]; /* transmit descriptors */ -+} EP_TXD_BLOCK; -+ -+struct ep_xmtr_rail_stats -+{ -+ EP_STATS_COUNT tx; -+ EP_STATS_COUNT tx_len; -+}; -+ -+struct ep_xmtr_rail -+{ -+ EP_COMMS_RAIL *CommsRail; /* associated comms rail */ -+ EP_XMTR *Xmtr; /* associated transmitter */ -+ -+ struct proc_dir_entry *procfs_root; /* place where this xmtr's proc entry is */ -+ -+ EP_XMTR_RAIL_STATS stats; -+}; -+ -+struct ep_xmtr_stats -+{ -+ EP_STATS_COUNT tx; -+ EP_STATS_COUNT tx_len; -+}; -+ -+struct ep_xmtr -+{ -+ struct list_head Link; /* Linked on subsys */ -+ EP_COMMS_SUBSYS *Subsys; /* kernel comms subsystem */ -+ -+ EP_RAILMASK RailMask; /* bitmap of which rails are available */ -+ EP_XMTR_RAIL *Rails[EP_MAX_RAILS]; /* per-rail state */ -+ -+ spinlock_t Lock; /* lock for active descriptor list */ -+ -+ struct list_head ActiveDescList; /* list of active transmit descriptors */ -+ -+ EP_XID_CACHE XidCache; /* XID cache (protected by Lock) */ -+ -+ struct list_head FreeDescList; /* List of free receive descriptors */ -+ unsigned int FreeDescCount; /* and number on free list */ -+ unsigned int TotalDescCount; -+ spinlock_t FreeDescLock; /* and lock for free list */ -+ kcondvar_t FreeDescSleep; /* with place to sleep for rx desc */ -+ int FreeDescWanted; /* and flag */ -+ struct list_head DescBlockList; -+ -+ struct proc_dir_entry *procfs_root; /* place where this rcvr's proc entry is */ -+ EP_XMTR_STATS stats; -+}; -+ -+/* forward descriptor */ -+#define EP_TREE_ARITY 3 -+ -+typedef struct ep_fwd_desc -+{ -+ struct list_head Link; /* linked on forward/free lists */ -+ EP_RXD *Rxd; /* rxd to forward */ -+ EP_NMD Data; /* nmd of subset of receive buffer */ -+ unsigned NumChildren; /* number of places we're forwarding */ -+ unsigned Children[EP_TREE_ARITY]; -+} EP_FWD_DESC; -+ -+typedef struct ep_comms_ops -+{ -+ void (*DelRail) (EP_COMMS_RAIL *rail); -+ void (*DisplayRail) (EP_COMMS_RAIL *rail); -+ -+ struct { -+ void (*AddRail) (EP_RCVR *rcvr, EP_COMMS_RAIL *rail); -+ void (*DelRail) (EP_RCVR *rcvr, EP_COMMS_RAIL *rail); -+ -+ long (*Check) (EP_RCVR_RAIL *rcvrRail, long nextRunTime); -+ -+ int (*QueueRxd) (EP_RXD *rxd, EP_RCVR_RAIL *rcvrRail); -+ void (*RpcPut)(EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+ void (*RpcGet)(EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+ void (*RpcComplete)(EP_RXD *rxd, EP_NMD *local, EP_NMD *remote, unsigned nFrags); -+ -+ EP_RXD *(*StealRxd)(EP_RCVR_RAIL *rcvrRail); -+ -+ void (*DisplayRcvr) (DisplayInfo *di, EP_RCVR_RAIL *rcvrRail); -+ void (*DisplayRxd) (DisplayInfo *di, EP_RXD_RAIL *rxdRail); -+ -+ void (*FillOutRailStats) (EP_RCVR_RAIL *rcvr_rail, char *str); -+ -+ } Rcvr; -+ -+ struct { -+ void (*AddRail) (EP_XMTR *xmtr, EP_COMMS_RAIL *rail); -+ void (*DelRail) (EP_XMTR *xmtr, EP_COMMS_RAIL *rail); -+ -+ long (*Check) (EP_XMTR_RAIL *xmtrRail, long nextRunTime); -+ -+ int (*BindTxd) (EP_TXD *txd, EP_XMTR_RAIL *xmtrRail, unsigned int phase); -+ void (*UnbindTxd) (EP_TXD *txd, unsigned int phase); -+ int (*PollTxd) (EP_XMTR_RAIL *xmtrRail, EP_TXD_RAIL *txdRail, int how); -+ -+ void (*DisplayXmtr) (DisplayInfo *di, EP_XMTR_RAIL *xmtrRail); -+ void (*DisplayTxd) (DisplayInfo *di, EP_TXD_RAIL *txdRail); -+ -+ int (*CheckTxdState) (EP_TXD *txd); -+ -+ void (*FillOutRailStats) (EP_XMTR_RAIL *xmtr_rail, char *str); -+ -+ } Xmtr; -+} EP_COMMS_OPS; -+ -+#define EP_RAIL_OP(commsRail, Which) (commsRail)->Ops.Which -+#define EP_RCVR_OP(rcvrRail, Which) (rcvrRail)->CommsRail->Ops.Rcvr.Which -+#define EP_XMTR_OP(xmtrRail, Which) (xmtrRail)->CommsRail->Ops.Xmtr.Which -+ -+/* "how" parameter to PollTxd */ -+#define POLL_TX_LIST 0 -+#define ENABLE_TX_CALLBACK 1 -+#define DISABLE_TX_CALLBACK 2 -+ -+struct ep_comms_rail -+{ -+ struct list_head Link; /* Linked on subsys */ -+ EP_RAIL *Rail; /* kernel comms rail */ -+ EP_COMMS_SUBSYS *Subsys; -+ EP_COMMS_OPS Ops; -+ -+ EP_COMMS_RAIL_STATS Stats; /* statistics */ -+}; -+ -+struct ep_comms_subsys -+{ -+ EP_SUBSYS Subsys; /* is a kernel comms subsystem */ -+ -+ kmutex_t Lock; /* global lock */ -+ -+ EP_COMMS_STATS Stats; /* statistics */ -+ -+ struct list_head Rails; /* list of all rails */ -+ -+ struct list_head Receivers; /* list of receivers */ -+ struct list_head Transmitters; /* and transmitters */ -+ -+ /* forward/allocator thread */ -+ EP_KTHREAD Thread; /* place thread sleeps */ -+ -+ /* message passing "broadcast" forward lists */ -+ spinlock_t ForwardDescLock; /* Lock for broadcast forwarding */ -+ struct list_head ForwardDescList; /* List of rxd's to forward */ -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ spinlock_t CheckSumDescLock; /* Lock for CheckSums */ -+ struct list_head CheckSumDescList; /* List of rxd's to be CheckSumed */ -+#endif -+ -+ EP_XMTR *ForwardXmtr; /* and transmitter to forward with */ -+}; -+ -+/* epcomms.c subsystem initialisation */ -+extern unsigned int epcomms_forward_limit; -+ -+extern int ep_comms_init (EP_SYS *sys); -+extern void ep_comms_display (EP_SYS *sys, char *how); -+extern EP_RAILMASK ep_rcvr_railmask (EP_SYS *epsys, EP_SERVICE service); -+ -+/* epcomms_elan3.c */ -+extern EP_COMMS_RAIL *ep3comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *rail); -+ -+/* epcomms_elan4.c */ -+extern EP_COMMS_RAIL *ep4comms_add_rail (EP_SUBSYS *s, EP_SYS *sys, EP_RAIL *rail); -+ -+/* epcommsTx.c */ -+extern int TxdShouldStabalise (EP_TXD_RAIL *txdRail, EP_RAIL *rail); -+extern void FreeTxd (EP_XMTR *xmtr, EP_TXD *txd); -+ -+extern unsigned int ep_txd_lowat; -+extern long ep_check_xmtr (EP_XMTR *xmtr, long nextRunTime); -+extern void ep_display_xmtr (DisplayInfo *di, EP_XMTR *xmtr); -+extern void ep_xmtr_flush_callback (EP_XMTR *xmtr, EP_XMTR_RAIL *xmtrRail); -+extern void ep_xmtr_reloc_callback (EP_XMTR *xmtr, EP_XMTR_RAIL *xmtrRail); -+ -+extern void ep_xmtr_fillout_stats (EP_XMTR *xmtr, char *str); -+extern void ep_xmtr_rail_fillout_stats (EP_XMTR_RAIL *xmtr_rail, char *str); -+ -+extern void ep_xmtr_txd_stat (EP_XMTR *xmtr, EP_TXD *txd); -+ -+/* epcommsRx.c */ -+extern EP_RXD *StealRxdFromOtherRail (EP_RCVR *rcvr); -+ -+extern unsigned int ep_rxd_lowat; -+extern long ep_check_rcvr (EP_RCVR *rcvr, long nextRunTime); -+extern void ep_rcvr_flush_callback (EP_RCVR *rcvr, EP_RCVR_RAIL *rcvrRail); -+extern void ep_rcvr_reloc_callback (EP_RCVR *rcvr, EP_RCVR_RAIL *rcvrRail); -+extern void ep_display_rcvr (DisplayInfo *di, EP_RCVR *rcvr, int full); -+ -+extern long ep_forward_rxds (EP_COMMS_SUBSYS *subsys, long nextRunTime); -+ -+extern void ep_rcvr_fillout_stats (EP_RCVR *rcvr, char *str); -+extern void ep_rcvr_rail_fillout_stats (EP_RCVR_RAIL *rcvr_rail, char *str); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+extern void ep_csum_rxds (EP_COMMS_SUBSYS *subsys); -+extern void ep_rxd_queue_csum (EP_RXD *rxd); -+#endif -+ -+extern void ep_rxd_received (EP_RXD *rxd); -+extern void ep_rxd_received_now (EP_RXD *rxd); -+ -+/* ep_procfs.c */ -+extern struct proc_dir_entry *ep_procfs_root; -+ -+extern void ep_procfs_rcvr_xmtr_init(void); -+extern void ep_procfs_rcvr_xmtr_fini(void); -+ -+extern void ep_procfs_rcvr_add(EP_RCVR *rcvr); -+extern void ep_procfs_rcvr_del(EP_RCVR *rcvr); -+ -+extern void ep_procfs_rcvr_add_rail(EP_RCVR_RAIL *rcvrRail); -+extern void ep_procfs_rcvr_del_rail(EP_RCVR_RAIL *rcvrRail); -+ -+extern void ep_procfs_xmtr_add(EP_XMTR *xmtr); -+extern void ep_procfs_xmtr_del(EP_XMTR *xmtr); -+ -+extern void ep_procfs_xmtr_add_rail(EP_XMTR_RAIL *xmtrRail); -+extern void ep_procfs_xmtr_del_rail(EP_XMTR_RAIL *xmtrRail); -+ -+ -+/* Public Interface */ -+ -+ -+/* epcomms.c message xmtr functions */ -+extern EP_XMTR *ep_alloc_xmtr (EP_SYS *sys); -+extern void ep_free_xmtr (EP_XMTR *xmtr); -+ -+extern EP_STATUS ep_transmit_message (EP_XMTR *xmtr, unsigned int dest, EP_SERVICE service, EP_ATTRIBUTE attr, -+ EP_TXH *handler, void *arg, EP_PAYLOAD *payload, -+ EP_NMD *nmd, int nFrag); -+extern EP_STATUS ep_multicast_message (EP_XMTR *xmtr, unsigned int destLo, unsigned int destHi, bitmap_t *bitmap, -+ EP_SERVICE service, EP_ATTRIBUTE attr, EP_TXH *handler, void *arg, -+ EP_PAYLOAD *payload, EP_NMD *nmd, int nFrag); -+extern EP_STATUS ep_transmit_rpc (EP_XMTR *xmtr, unsigned int dest, EP_SERVICE service, EP_ATTRIBUTE attr, -+ EP_TXH *handler, void *arg, EP_PAYLOAD *payload, -+ EP_NMD *nmd, int nFrag); -+extern EP_STATUS ep_multicast_forward (EP_XMTR *xmtr, unsigned int dest, EP_SERVICE service, EP_ATTRIBUTE attr, -+ EP_TXH *handler, void *arg, EP_ENVELOPE *env, EP_PAYLOAD *payload, -+ bitmap_t *bitmap, EP_NMD *nmd, int nFrags); -+ -+/* epcomms.c functions for use with polled transmits */ -+extern int ep_poll_transmits (EP_XMTR *xmtr); -+extern int ep_enable_txcallbacks (EP_XMTR *xmtr); -+extern int ep_disable_txcallbacks (EP_XMTR *xmtr); -+ -+/* epcomms.c message rcvr functions */ -+extern EP_RCVR *ep_alloc_rcvr (EP_SYS *sys, EP_SERVICE svc, unsigned int nenvelopes); -+extern void ep_free_rcvr (EP_RCVR *rcvr); -+ -+extern EP_STATUS ep_queue_receive (EP_RCVR *rcvr, EP_RXH *handler, void *arg, EP_NMD *nmd, EP_ATTRIBUTE attr); -+extern void ep_requeue_receive (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_NMD *nmd, EP_ATTRIBUTE attr); -+extern EP_STATUS ep_rpc_put (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_NMD *from, EP_NMD *to, int nFrags); -+extern EP_STATUS ep_rpc_get (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_NMD *from, EP_NMD *to, int nFrags); -+extern EP_STATUS ep_complete_rpc (EP_RXD *rxd, EP_RXH *handler, void *arg, EP_STATUSBLK *blk, -+ EP_NMD *from, EP_NMD *to, int nFrags); -+extern void ep_complete_receive (EP_RXD *rxd); -+ -+/* railhints.c */ -+extern int ep_xmtr_bcastrail (EP_XMTR *xmtr, EP_RAILMASK allowedRails); -+extern int ep_xmtr_prefrail (EP_XMTR *xmtr, EP_RAILMASK allowedRails, unsigned nodeId); -+extern EP_RAILMASK ep_xmtr_availrails (EP_XMTR *xmtr); -+extern EP_RAILMASK ep_xmtr_noderails (EP_XMTR *xmtr, unsigned nodeId); -+extern int ep_rcvr_prefrail (EP_RCVR *rcvr, EP_RAILMASK allowedRails); -+extern EP_RAILMASK ep_rcvr_availrails (EP_RCVR *rcvr); -+extern EP_RAILMASK ep_rxd_railmask (EP_RXD *rxd); -+ -+/* epcomms.c functions for accessing fields of rxds */ -+extern void *ep_rxd_arg(EP_RXD *rxd); -+extern int ep_rxd_len(EP_RXD *rxd); -+extern EP_STATUS ep_rxd_status(EP_RXD *rxd); -+extern int ep_rxd_isrpc(EP_RXD *rxd); -+extern EP_ENVELOPE *ep_rxd_envelope(EP_RXD *rxd); -+extern EP_PAYLOAD *ep_rxd_payload(EP_RXD *rxd); -+extern int ep_rxd_node(EP_RXD *rxd); -+extern EP_STATUSBLK *ep_rxd_statusblk(EP_RXD *rxd); -+ -+/* functions for accessing fields of txds */ -+extern int ep_txd_node(EP_TXD *txd); -+extern EP_STATUSBLK *ep_txd_statusblk(EP_TXD *txd); -+ -+/* functions for controlling how many processes are using module */ -+extern void ep_mod_dec_usecount (void); -+extern void ep_mod_inc_usecount (void); -+ -+extern EP_RAILMASK ep_xmtr_svc_indicator_railmask (EP_XMTR *xmtr, int svc_indicator, int nodeId); -+extern int ep_xmtr_svc_indicator_bitmap (EP_XMTR *xmtr, int svc_indicator, bitmap_t * bitmap, int low, int nnodes); -+ -+#endif /* ! __ELAN__ */ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN_EPCOMMS_H */ -+ -Index: linux-2.4.21/include/elan/epsvc.h -=================================================================== ---- linux-2.4.21.orig/include/elan/epsvc.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/epsvc.h 2005-06-01 23:12:54.710422232 -0400 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_EPSVC_H -+#define __ELAN_EPSVC_H -+ -+#ident "@(#)$Id: epsvc.h,v 1.9 2004/02/13 10:03:27 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/epsvc.h,v $ */ -+ -+ -+#define EP_SVC_NUM_INDICATORS 8 -+#define EP_SVC_INDICATOR_MAX_NAME 32 -+ -+#define EP_SVC_EIP 0 -+#define EP_SVC_NAMES {"eip", "1", "2", "3", "4", "5", "6", "7"}; -+ -+#if defined(__KERNEL__) -+extern int ep_svc_indicator_set (EP_SYS *epsys, int svc_indicator); -+extern int ep_svc_indicator_clear (EP_SYS *epsys, int svc_indicator); -+extern int ep_svc_indicator_is_set (EP_SYS *epsys, int svc_indicator, int nodeId); -+extern int ep_svc_indicator_bitmap (EP_SYS *epsys, int svc_indicator, bitmap_t * bitmap, int low, int nnodes); -+extern EP_RAILMASK ep_svc_indicator_railmask (EP_SYS *epsys, int svc_indicator, int nodeId); -+#endif -+ -+#endif /* __ELAN_EPSVC_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/kalloc.h -=================================================================== ---- linux-2.4.21.orig/include/elan/kalloc.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/kalloc.h 2005-06-01 23:12:54.710422232 -0400 -@@ -0,0 +1,108 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_KALLOC_H -+#define __ELAN3_KALLOC_H -+ -+#ident "$Id: kalloc.h,v 1.11 2004/05/19 10:23:59 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kalloc.h,v $ */ -+ -+#include -+ -+/* -+ * Memory allocator -+ */ -+#define LN2_MIN_SIZE 6 /* 64 bytes */ -+#define LN2_MAX_SIZE 16 /* 64k bytes */ -+#define NUM_FREELISTS (LN2_MAX_SIZE-LN2_MIN_SIZE + 1) -+#define MIN_SIZE (1 << LN2_MIN_SIZE) -+#define MAX_SIZE (1 << LN2_MAX_SIZE) -+ -+#define HASHSHIFT LN2_MAX_SIZE -+#define NHASH 32 -+#define HASH(addr) (((addr) >> HASHSHIFT) & (NHASH-1)) -+ -+typedef enum -+{ -+ EP_ALLOC_TYPE_PRIVATE_SDRAM, -+ EP_ALLOC_TYPE_PRIVATE_MAIN, -+ EP_ALLOC_TYPE_SHARED_MAIN, -+} EP_ALLOC_TYPE; -+ -+typedef struct ep_pool -+{ -+ EP_NMH Handle; /* network mapping handle */ -+ -+ struct list_head HashBase; /* linked on hash lists */ -+ struct list_head HashTop; /* linked on hash lists */ -+ -+ struct list_head Link[NUM_FREELISTS]; /* linked on free lists */ -+ bitmap_t *Bitmaps[NUM_FREELISTS]; /* bitmaps for each size */ -+ -+ union { -+ sdramaddr_t Sdram; -+ unsigned long Ptr; -+ } Buffer; -+} EP_POOL; -+ -+typedef struct ep_alloc -+{ -+ spinlock_t Lock; -+ -+ EP_ALLOC_TYPE Type; -+ unsigned int Perm; -+ -+ EP_RMAP *ResourceMap; -+ -+ struct list_head HashBase[NHASH]; -+ struct list_head HashTop[NHASH]; -+ struct list_head Freelists[NUM_FREELISTS]; -+ -+ union { -+ struct { -+ EP_SYS *System; -+ struct list_head Rails; -+ } Shared; -+ -+ struct { -+ EP_RAIL *Rail; -+ } Private; -+ } Data; -+} EP_ALLOC; -+ -+extern void ep_display_alloc (EP_ALLOC *alloc); -+ -+extern void ep_alloc_init (EP_RAIL *rail); -+extern void ep_alloc_fini (EP_RAIL *rail); -+ -+extern sdramaddr_t ep_alloc_memory_elan (EP_RAIL *rail, EP_ADDR addr, unsigned size, unsigned int perm, EP_ATTRIBUTE attr); -+extern void ep_free_memory_elan (EP_RAIL *rail, EP_ADDR addr); -+ -+extern sdramaddr_t ep_alloc_elan (EP_RAIL *rail, unsigned size, EP_ATTRIBUTE attr, EP_ADDR *addrp); -+extern void ep_free_elan (EP_RAIL *rail, EP_ADDR addr, unsigned size); -+extern void *ep_alloc_main (EP_RAIL *rail, unsigned size, EP_ATTRIBUTE attr, EP_ADDR *addr); -+extern void ep_free_main (EP_RAIL *rail, EP_ADDR addr, unsigned size); -+ -+extern sdramaddr_t ep_elan2sdram (EP_RAIL *rail, EP_ADDR addr); -+extern void *ep_elan2main (EP_RAIL *rail, EP_ADDR addr); -+ -+extern void ep_shared_alloc_init (EP_SYS *sys); -+extern void ep_shared_alloc_fini (EP_SYS *sys); -+extern int ep_shared_alloc_add_rail (EP_SYS *sys, EP_RAIL *rail); -+extern void ep_shared_alloc_remove_rail (EP_SYS *sys, EP_RAIL *rail); -+ -+extern void *ep_shared_alloc_main (EP_SYS *sys, unsigned size, EP_ATTRIBUTE attr, EP_NMD *nmd); -+extern void ep_shared_free_main (EP_SYS *sys, EP_NMD *nmd); -+ -+#endif /* __ELAN_KALLOC_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/kcomm.h -=================================================================== ---- linux-2.4.21.orig/include/elan/kcomm.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/kcomm.h 2005-06-01 23:12:54.712421928 -0400 -@@ -0,0 +1,839 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_KCOMM_H -+#define __ELAN_KCOMM_H -+ -+#ident "$Id: kcomm.h,v 1.71.2.8 2004/12/14 10:19:14 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm.h,v $*/ -+#define EP_KCOMM_MAJOR_VERSION 3 -+#define EP_KCOMM_MINOR_VERSION 1 -+ -+#define EP_PROTOCOL_VERSION 1 /* CM/KCOMM protocol revision */ -+ -+#define EP_MAX_NODES 2048 /* Max nodes we support */ -+#define EP_MAX_RAILS 16 /* max number of rails (we use an unsigned short for bitmaps !) */ -+#define EP_MAXFRAG 4 /* max number of fragments */ -+ -+#define EP_BLK_SIZE 64 /* align objects for elan access */ -+ -+/* Elan virtual address address space */ -+#define EP_SYSTEM_QUEUE_BASE 0x00010000 /* Base address for system queues */ -+#define EP_MSGSYS_QUEUE_BASE 0x00020000 /* Base address for msgsys queues */ -+#define EP_EPCOMMS_QUEUE_BASE 0x00030000 /* Base address for message queues */ -+#define EP_DVMA_BASE 0x10000000 /* elan address range for dvma mapping. */ -+#define EP_DVMA_TOP 0xE0000000 -+ -+#define EP_SHARED_BASE 0xE0000000 /* shared main/elan allocators */ -+#define EP_SHARED_TOP 0xF0000000 -+ -+#define EP_PRIVATE_BASE 0xF0000000 /* private main/elan allocators */ -+#define EP_PRIVATE_TOP 0xF8000000 -+ -+#define EP_DVMA_RMAP_SIZE 1024 /* size of resource map for dvma address space */ -+#define EP_SHARED_RMAP_SIZE 1024 /* size of resource map for shared address space */ -+#define EP_PRIVATE_RMAP_SIZE 1024 /* size of resource map for private address space */ -+ -+/* Input queue descriptors fit into 64 bytes */ -+#define EP_QUEUE_DESC_SIZE 64 -+ -+/* Timeouts for checking network position */ -+#define EP_POSITION_TIMEOUT (4*HZ) /* 1s time to notice CheckNetworkPosition changes */ -+#define EP_WITHDRAW_TIMEOUT (2*HZ) /* 2s time before withdrawing from unreachable nodes */ -+ -+/* Time to try again due to resource failue (eg malloc etc) */ -+#define RESOURCE_RETRY_TIME (HZ/20) -+ -+/* Time to retransmit message when send failed */ -+#define MSGBUSY_RETRY_TIME (HZ/20) -+ -+/* Time between retransmits of messages network flush requests */ -+#define MESSAGE_RETRY_TIME (HZ/5) -+ -+/* time to hold the context filter up to ensure that the -+ * next packet of a dma is guaranteed to get nacked (8mS) */ -+#define NETWORK_ERROR_TIMEOUT (1 + roundup (HZ * 8 / 1000, 1)) -+ -+/* Time between retransmits of message failover requests */ -+#define FAILOVER_RETRY_TIME (HZ/5) -+ -+/* compute earliest time */ -+#define SET_NEXT_RUN_TIME(nextRunTime, time) \ -+do { \ -+ if ((nextRunTime) == 0 || AFTER(nextRunTime, (time)))\ -+ (nextRunTime) = (time);\ -+} while (0) -+ -+/* DMA retry backoff/priorities/issue rings */ -+#define EP_NUM_BACKOFF 8 -+#define EP_RETRY_STABALISING 0 -+#define EP_RETRY_BASE 1 -+ -+#define EP_RETRY_CRITICAL EP_RETRY_BASE -+#define EP_RETRY_HIGH_PRI (EP_RETRY_CRITICAL + 1) -+#define EP_RETRY_HIGH_PRI_TIME (1) -+#define EP_RETRY_HIGH_PRI_RETRY (EP_RETRY_HIGH_PRI + 1) -+#define EP_RETRY_HIGH_PRI_RETRY_TIME (2) -+#define EP_RETRY_LOW_PRI (EP_RETRY_HIGH_PRI_RETRY + EP_NUM_BACKOFF) -+#define EP_RETRY_LOW_PRI_TIME (2) -+#define EP_RETRY_LOW_PRI_RETRY (EP_RETRY_LOW_PRI + 1) -+#define EP_RETRY_LOW_PRI_RETRY_TIME (4) -+#define EP_RETRY_ANONYMOUS (EP_RETRY_LOW_PRI_RETRY + EP_NUM_BACKOFF) -+#define EP_RETRY_ANONYMOUS_TIME (10) -+#define EP_RETRY_NETERR (EP_RETRY_ANONYMOUS + EP_NUM_BACKOFF) -+#define EP_RETRY_NETERR_TIME (10) -+#define EP_NUM_RETRIES (EP_RETRY_NETERR + 1) -+ -+typedef unsigned short EP_SERVICE; -+ -+/* EP_ATTRIBUTE 32 bits -+ * -+ * 0-2 -+ * for initial call :- -+ * 0 (0x1) EP_NO_ALLOC used once -+ * 1 (0x2) EP_NO_SLEEP used once -+ * 2 (0x4) EP_NOT_MYSELF used once -+ * -+ * when stored and transmited :- -+ * 0 (0x0) EP_MULTICAST envelope -+ * 1 (0x2) EP_RPC envelope -+ * 2 (0x4) EP_HAS_PAYLOAD envelope -+ * -+ * 3-11 -+ * 3 (0x08) EP_PREFRAIL_SET preserved -+ * 4-7 (0xf0) Pref Rail -+ * 8 (0x100) EP_NO_INTERUPT -+ * 9 (0x200) EP_NO_FAILOVER -+ * -+ * 10 (0x400) EP_INTERRUPT_ENABLED internal -+ * 11 (0x800) EP_TXD_STABALISING internal -+ * -+ * 12-13 Not Used. -+ * -+ * 14-15 (0xC000) Data Type. passed in -+ * 00 none. -+ * 01 Service Indicator. -+ * 10 TimeOut. -+ * 11 RailMask -+ * -+ * 16-31 (0x10000) Data. Service Indicator, TimeOut, RailMask, Pref Rail. -+ * -+*/ -+ -+typedef uint32_t EP_ATTRIBUTE; -+ -+#define EP_LOCAL_ATTR_MASK 0x07 -+#define EP_CLEAR_LOCAL_ATTR(ATTR) ( (ATTR) & ~EP_LOCAL_ATTR_MASK ) -+ -+#define EP_NO_ALLOC 0x01 /* Don't call allocators if no free descriptors */ -+#define EP_NO_SLEEP 0x02 /* Don't sleep if no free descriptors */ -+#define EP_NOT_MYSELF 0x04 /* Don't send multicast to me */ -+ -+#define EP_MULTICAST 0x01 /* Message is a multicast */ -+#define EP_RPC 0x02 /* Wait for RPC reply */ -+#define EP_HAS_PAYLOAD_BIT 0x04 /* transfer payload */ -+ -+ -+#define EP_PREFRAIL_SET 0x08 /* preferred rail is set (otherwise pick one from the NMDs) */ -+ -+#define EP_PREFRAIL_SHIFT (4) -+#define EP_PREFRAIL_MASK 0xf0 -+#define EP_IS_PREFRAIL_SET(ATTR) (((ATTR) & EP_PREFRAIL_SET) != 0) -+#define EP_CLEAR_PREFRAIL(ATTR) (((ATTR) & ~EP_PREFRAIL_SET) & ~EP_PREFRAIL_MASK) -+#define EP_SET_PREFRAIL(ATTR,RAIL) (EP_CLEAR_PREFRAIL(ATTR) | (((RAIL) << EP_PREFRAIL_SHIFT ) & EP_PREFRAIL_MASK ) | EP_PREFRAIL_SET) -+ -+ -+#define EP_ATTR2PREFRAIL(ATTR) (((ATTR) & EP_PREFRAIL_MASK) >> EP_PREFRAIL_SHIFT) -+ -+ -+#define EP_INTERRUPT_ENABLED 0x400 /* event interrupt enabled on EP_NO_INTERRUPT */ -+#define EP_TXD_STABALISING 0x800 /* flag to indicate this is attempting to stabalise */ -+ -+#define EP_IS_MULTICAST(ATTR) (((ATTR) & EP_MULTICAST) != 0) -+#define EP_SET_MULTICAST(ATTR) ( (ATTR) | EP_MULTICAST) -+#define EP_CLEAR_MULTICAST(ATTR) ( (ATTR) & ~EP_MULTICAST) -+ -+#define EP_IS_RPC(ATTR) (((ATTR) & EP_RPC) != 0) -+#define EP_SET_RPC(ATTR) ( (ATTR) | EP_RPC) -+#define EP_CLEAR_RPC(ATTR) ( (ATTR) & ~EP_RPC) -+ -+#define EP_HAS_PAYLOAD(ATTR) (((ATTR) & EP_HAS_PAYLOAD_BIT) != 0) -+#define EP_SET_HAS_PAYLOAD(ATTR) ( (ATTR) | EP_HAS_PAYLOAD_BIT) -+#define EP_CLEAR_HAS_PAYLOAD(ATTR) ( (ATTR) & ~EP_HAS_PAYLOAD_BIT) -+ -+#define EP_IS_INTERRUPT_ENABLED(ATTR) (((ATTR) & EP_INTERRUPT_ENABLED) != 0) -+#define EP_SET_INTERRUPT_ENABLED(ATTR) ( (ATTR) | EP_INTERRUPT_ENABLED) -+#define EP_CLEAR_INTERRUPT_ENABLED(ATTR) ( (ATTR) & ~EP_INTERRUPT_ENABLED) -+ -+#define EP_IS_TXD_STABALISING(ATTR) (((ATTR) & EP_TXD_STABALISING) != 0) -+#define EP_SET_TXD_STABALISING(ATTR) ( (ATTR) | EP_TXD_STABALISING) -+#define EP_CLEAR_TXD_STABALISING(ATTR) ( (ATTR) & ~EP_TXD_STABALISING) -+ -+#define EP_NO_INTERRUPT 0x100 /* Don't generate completion interrupt (tx) */ -+#define EP_NO_FAILOVER 0x200 /* don't attempt rail failover, just abort */ -+ -+#define EP_IS_NO_INTERRUPT(ATTR) (((ATTR) & EP_NO_INTERRUPT) != 0) -+#define EP_SET_NO_INTERRUPT(ATTR) ( (ATTR) | EP_NO_INTERRUPT) -+#define EP_CLEAR_NO_INTERRUPT(ATTR) ( (ATTR) & ~EP_NO_INTERRUPT) -+ -+#define EP_IS_NO_FAILOVER(ATTR) (((ATTR) & EP_NO_FAILOVER) != 0) -+#define EP_SET_NO_FAILOVER(ATTR) ( (ATTR) | EP_NO_FAILOVER) -+#define EP_CLEAR_NO_FAILOVER(ATTR) ( (ATTR) & ~EP_NO_FAILOVER) -+ -+#define EP_TYPE_MASK 0xC000 -+#define EP_TYPE_SVC_INDICATOR 0x4000 -+#define EP_TYPE_TIMEOUT 0x8000 -+#define EP_TYPE_RAILMASK 0xC000 -+ -+#define EP_ATTR2TYPE(ATTR) ( (ATTR) & EP_TYPE_MASK ) -+ -+#define EP_IS_SVC_INDICATOR(ATTR) (EP_ATTR2TYPE(ATTR) == EP_TYPE_SVC_INDICATOR) -+#define EP_IS_TIMEOUT(ATTR) (EP_ATTR2TYPE(ATTR) == EP_TYPE_TIMEOUT) -+#define EP_IS_RAILMASK(ATTR) (EP_ATTR2TYPE(ATTR) == EP_TYPE_RAILMASK) -+#define EP_IS_NO_TYPE(ATTR) (EP_ATTR2TYPE(ATTR) == 0) -+ -+#define EP_DATA_SHIFT (16) -+#define EP_DATA_MASK 0xffff0000 -+ -+#define EP_ATTR2DATA(ATTR) (((ATTR) & EP_DATA_MASK) >> EP_DATA_SHIFT) -+#define EP_DATA2ATTR(DATA) (((DATA) << EP_DATA_SHIFT) & EP_DATA_MASK) -+ -+#define EP_CLEAR_DATA(ATTR) (((ATTR) & ~EP_TYPE_MASK) & ~EP_DATA_MASK) -+#define EP_SET_DATA(ATTR,TYPE,DATA) (EP_CLEAR_DATA(ATTR) | ((TYPE) & EP_TYPE_MASK) | (((DATA) << EP_DATA_SHIFT) & EP_DATA_MASK)) -+ -+#define EP_DEFAULT_TIMEOUT (HZ*30) -+ -+#if !defined(offsetof) -+#define offsetof(s, m) (unsigned long)(&(((s *)0)->m)) -+#endif -+#if !defined(roundup) -+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -+#endif -+ -+/* -+ * Message transaction ID's - these are unique 64 bts -+ * numbers which include the initial rail number. -+ */ -+typedef struct ep_xid -+{ -+ uint32_t Generation; -+ uint32_t Handle; -+ uint64_t Unique; -+} EP_XID; -+ -+#define EP_INVALIDATE_XID(xid) ((xid).Generation = (xid).Handle = (xid).Unique = 0) -+ -+#define EP_XID_INVALID(xid) ((xid).Generation == 0 && (xid).Handle == 0 && (xid).Unique == 0) -+#define EP_XIDS_MATCH(a,b) ((a).Generation == (b).Generation && (a).Handle == (b).Handle && (a).Unique == (b).Unique) -+ -+typedef struct ep_backoff -+{ -+ unsigned char type; -+ unsigned char indx; -+ unsigned short count; -+} EP_BACKOFF; -+ -+/* values for "type" */ -+#define EP_BACKOFF_FREE 0 -+#define EP_BACKOFF_ENVELOPE 1 -+#define EP_BACKOFF_FETCH 2 -+#define EP_BACKOFF_DATA 3 -+#define EP_BACKOFF_DONE 4 -+#define EP_BACKOFF_STABILISE 5 -+ -+#ifndef __ELAN__ -+ -+/* forward declaration of types */ -+typedef struct ep_rail EP_RAIL; -+typedef struct ep_sys EP_SYS; -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+typedef struct ep_callback -+{ -+ struct ep_callback *Next; -+ void (*Routine)(void *, statemap_t *); -+ void *Arg; -+} EP_CALLBACK; -+ -+#define EP_CB_FLUSH_FILTERING 0 -+#define EP_CB_FLUSH_FLUSHING 1 -+#define EP_CB_PASSIVATED 2 -+#define EP_CB_FAILOVER 3 -+#define EP_CB_DISCONNECTING 4 -+#define EP_CB_DISCONNECTED 5 -+#define EP_CB_NODESET 6 -+#define EP_CB_COUNT 7 -+ -+#endif /* !defined(__ELAN__) */ -+ -+/* Small unreliable system message queues */ -+#define EP_SYSTEMQ_INTR 0 /* input queue for cluster membership generating an interrupt */ -+#define EP_SYSTEMQ_POLLED 1 /* input queue for cluster membership polled on clock tick */ -+#define EP_SYSTEMQ_MANAGER 2 /* input queue for manager messages */ -+#define EP_NUM_SYSTEMQ 64 -+ -+#define EP_SYSTEMQ_ADDR(qnum) (EP_SYSTEM_QUEUE_BASE + (qnum) * EP_QUEUE_DESC_SIZE) -+#define EP_SYSTEMQ_DESC(base,qnum) ((base) + (qnum) * EP_QUEUE_DESC_SIZE) -+ -+#define EP_SYSTEMQ_MSG_ALIGN 64 /* message sizes aligned to 64 byte boundaries */ -+#define EP_SYSTEMQ_MSG_MAX (4*64) /* max message size */ -+ -+/* Special flag for Version field to indicate message not -+ * seen in main memory yet and time limit to poll for it */ -+#define EP_SYSTEMQ_UNRECEIVED 0xdeadbabe -+#define EP_SYSTEMQ_UNRECEIVED_TLIMIT 16384 /* 1023 uS */ -+ -+#ifndef __ELAN__ -+ -+typedef void (EP_INPUTQ_HANDLER) (EP_RAIL *rail, void *arg, void *msg); -+typedef void (EP_INPUTQ_CALLBACK) (EP_RAIL *rail, void *arg); -+ -+typedef struct ep_inputq -+{ -+ unsigned long q_hidden; /* implementation hidden as ep3 or ep4 */ -+} EP_INPUTQ; -+ -+typedef struct ep_outputq -+{ -+ unsigned long q_hidden; /* implementation hidden as ep3 or ep4 */ -+} EP_OUTPUTQ; -+ -+/* returned values for ep_outputq_state */ -+#define EP_OUTPUTQ_BUSY 0 -+#define EP_OUTPUTQ_FAILED 1 -+#define EP_OUTPUTQ_FINISHED 2 -+ -+typedef struct ep_switch -+{ -+ unsigned present:1; -+ unsigned invalid:1; -+ unsigned link:3; -+ unsigned bcast:3; -+ unsigned lnr; -+} EP_SWITCH; -+ -+/* -+ * Network error fixup, flush, relocation messges -+ */ -+typedef struct ep_map_nmd_body -+{ -+ uint32_t nFrags; -+ EP_RAILMASK Railmask; -+ EP_NMD Nmd[EP_MAXFRAG]; -+} EP_MAP_NMD_BODY; -+ -+typedef struct ep_failover_body -+{ -+ EP_XID Xid; -+ EP_RAILMASK Railmask; -+} EP_FAILOVER_BODY; -+ -+typedef struct ep_failover_txd -+{ -+ EP_XID Xid; -+ uint32_t Rail; -+ EP_ADDR TxdRail; -+} EP_FAILOVER_TXD; -+ -+typedef uint64_t EP_NETERR_COOKIE; -+ -+#define EP_PANIC_STRLEN 31 -+ -+typedef struct ep_node_state -+{ -+ unsigned char State; -+ unsigned char NetworkErrorState; -+ EP_RAILMASK Railmask; -+} EP_NODE_STATE; -+ -+#define EP_MANAGER_MSG_SIZE (2 * EP_SYSTEMQ_MSG_ALIGN) -+ -+typedef struct ep_manager_msg_hdr -+{ -+ EP_XID Xid; /* Message transaction id */ -+ -+ uint16_t NodeId; /* Originating node number */ -+ uint16_t DestId; /* destination node id */ -+ -+ uint16_t Checksum; /* Message checksum */ -+ uint8_t Rail; /* Rail message associated with */ -+ uint8_t Type; /* Message type */ -+ -+ uint32_t Pad; /* pad to 32 bytes */ -+ -+ uint32_t Version; /* Message Version */ -+} EP_MANAGER_MSG_HDR; -+ -+typedef union ep_manager_msg_body -+{ -+ unsigned char Space[EP_MANAGER_MSG_SIZE - sizeof (EP_MANAGER_MSG_HDR)]; -+ -+ EP_NETERR_COOKIE Cookies[2]; /* EP_MSG_TYPE_NETERR */ -+ EP_MAP_NMD_BODY MapNmd; /* EP_MSG_TYPE_MAP_NMD */ -+ EP_FAILOVER_BODY Failover; /* EP_MSG_TYPE_FAILOVER_REQUEST */ -+ EP_FAILOVER_TXD FailoverTxd; /* EP_MSG_TYPE_FAILOVER_RESPONSE */ -+ unsigned char PanicReason[EP_PANIC_STRLEN+1]; /* EP_MSG_TYPE_REMOTE_PANIC */ -+ EP_NODE_STATE NodeState; /* EP_MSG_TYPE_GET_NODE_STATE_RESPONSE */ -+ EP_SERVICE Service; /* EP_MSG_TYPE_GET_NODE_STATE */ -+} EP_MANAGER_MSG_BODY; -+ -+typedef struct ep_manager_msg -+{ -+ EP_MANAGER_MSG_BODY Body; -+ EP_MANAGER_MSG_HDR Hdr; -+} EP_MANAGER_MSG; -+ -+#define EP_MANAGER_MSG_VERSION 0xcad01000 -+#define EP_MANAGER_MSG_TYPE_REMOTE_PANIC 0x00 -+#define EP_MANAGER_MSG_TYPE_NETERR_REQUEST 0x01 -+#define EP_MANAGER_MSG_TYPE_NETERR_RESPONSE 0x02 -+#define EP_MANAGER_MSG_TYPE_FLUSH_REQUEST 0x03 -+#define EP_MANAGER_MSG_TYPE_FLUSH_RESPONSE 0x04 -+#define EP_MANAGER_MSG_TYPE_MAP_NMD_REQUEST 0x05 -+#define EP_MANAGER_MSG_TYPE_MAP_NMD_RESPONSE 0x06 -+#define EP_MANAGER_MSG_TYPE_FAILOVER_REQUEST 0x07 -+#define EP_MANAGER_MSG_TYPE_FAILOVER_RESPONSE 0x08 -+#define EP_MANAGER_MSG_TYPE_GET_NODE_STATE 0x09 -+#define EP_MANAGER_MSG_TYPE_GET_NODE_STATE_RESPONSE 0x0a -+ -+/* Message types which should only be sent when a rail is connected */ -+#define EP_MANAGER_MSG_TYPE_CONNECTED(type) (((type) & 1) == 1) -+ -+#define EP_MANAGER_OUTPUTQ_SLOTS 128 /* # entries in outputq */ -+#define EP_MANAGER_INPUTQ_SLOTS 128 /* # entries in inputq */ -+#define EP_MANAGER_OUTPUTQ_RETRIES 31 /* # retries for manager messages */ -+ -+/* XID's are allocated from a cache, which doesn't -+ * require locking since it relies on the caller to -+ * manage the locking for us. -+ */ -+typedef struct ep_xid_cache -+{ -+ struct list_head Link; -+ -+ uint32_t Handle; /* my XID cache handle */ -+ uint64_t Current; /* range of XID.Unique we can allocate from */ -+ uint64_t Last; -+ -+ void (*MessageHandler)(void *arg, EP_MANAGER_MSG *); -+ void *Arg; -+} EP_XID_CACHE; -+ -+#define EP_XID_CACHE_CHUNKS (10000) -+ -+typedef struct ep_node_rail -+{ -+ struct list_head Link; /* can be linked on work lists */ -+ -+ unsigned char State; /* node connection state */ -+ unsigned char NetworkErrorState; /* reasons for keeping the context filter up */ -+ unsigned char MessageState; /* state of messages during passivate/relocate */ -+ -+ EP_XID MsgXid; /* neterr/flush transaction id */ -+ long NextRunTime; /* time to drop context filter for destroyed dma packet, or to send next request */ -+ EP_NETERR_COOKIE NetworkErrorCookies[2]; /* identify cookie for destroyed atomic packet */ -+ -+ uint32_t Cookie; /* per-node network error cookie */ -+ spinlock_t CookieLock; /* and spinlock for it. */ -+ -+ struct list_head StalledDmas; /* list of stalled DMAs */ -+} EP_NODE_RAIL; -+ -+#define EP_NODE_DISCONNECTED 0 /* node is disconnected */ -+#define EP_NODE_CONNECTING 1 /* awaiting connection */ -+#define EP_NODE_CONNECTED 2 /* node is connected */ -+#define EP_NODE_LEAVING_CONNECTED 3 /* node is starting to disconnect */ -+#define EP_NODE_LOCAL_PASSIVATE 4 /* flushing context filter/run queues */ -+#define EP_NODE_REMOTE_PASSIVATE 5 /* stalling for neterr flush */ -+#define EP_NODE_PASSIVATED 6 /* relocating active/passive messages */ -+#define EP_NODE_DISCONNECTING 7 /* entering disconncted - abort remaining comms */ -+#define EP_NODE_NUM_STATES 8 -+ -+#define EP_NODE_NETERR_ATOMIC_PACKET (1 << 0) -+#define EP_NODE_NETERR_DMA_PACKET (1 << 1) -+ -+#define EP_NODE_PASSIVE_MESSAGES (1 << 0) -+#define EP_NODE_ACTIVE_MESSAGES (1 << 1) -+ -+/* -+ * Kernel thread code is loaded as a table. -+ */ -+typedef struct ep_symbol -+{ -+ char *name; -+ EP_ADDR value; -+} EP_SYMBOL; -+ -+typedef struct ep_code -+{ -+ u_char *text; -+ u_int text_size; -+ u_char *data; -+ u_int data_size; -+ u_char *rodata; -+ u_int rodata_size; -+ EP_SYMBOL *symbols; -+ -+ int ntext; -+ sdramaddr_t pptext; -+ EP_ADDR etext; -+ sdramaddr_t _stext; -+ sdramaddr_t _rodata; -+ -+ int ndata; -+ sdramaddr_t ppdata; -+ EP_ADDR edata; -+ sdramaddr_t _sdata; -+} EP_CODE; -+ -+typedef struct ep_switchstate -+{ -+ unsigned char linkid; -+ unsigned char LNR; -+ unsigned char bcast; -+ unsigned char uplink; -+} EP_SWITCHSTATE; -+ -+typedef struct ep_rail_ops -+{ -+ void (*DestroyRail) (EP_RAIL *rail); -+ -+ int (*StartRail) (EP_RAIL *rail); -+ void (*StallRail) (EP_RAIL *rail); -+ void (*StopRail) (EP_RAIL *rail); -+ -+ sdramaddr_t (*SdramAlloc) (EP_RAIL *rail, EP_ADDR addr, unsigned size); -+ void (*SdramFree) (EP_RAIL *rail, sdramaddr_t addr, unsigned size); -+ void (*SdramWriteb) (EP_RAIL *rail, sdramaddr_t addr, unsigned char val); -+ -+ void (*KaddrMap) (EP_RAIL *rail, EP_ADDR eaddr, virtaddr_t kaddr, unsigned len, unsigned int perm, int ep_attr); -+ void (*SdramMap) (EP_RAIL *rail, EP_ADDR eaddr, sdramaddr_t saddr, unsigned len, unsigned int perm, int ep_attr); -+ void (*Unmap) (EP_RAIL *rail, EP_ADDR eaddr, unsigned len); -+ -+ void *(*DvmaReserve) (EP_RAIL *rail, EP_ADDR eaddr, unsigned npages); -+ void (*DvmaRelease) (EP_RAIL *rail, EP_ADDR eaddr, unsigned npages, void *private); -+ void (*DvmaSetPte) (EP_RAIL *rail, void *private, unsigned index, physaddr_t phys, unsigned int perm); -+ physaddr_t (*DvmaReadPte) (EP_RAIL *rail, void *private, unsigned index); -+ void (*DvmaUnload)(EP_RAIL *rail, void *private, unsigned index, unsigned npages); -+ void (*FlushTlb) (EP_RAIL *rail); -+ -+ int (*ProbeRoute) (EP_RAIL *r, int level, int sw, int nodeid, int *linkup, -+ int *linkdown, int attempts, EP_SWITCH *lsw); -+ void (*PositionFound) (EP_RAIL *rail, ELAN_POSITION *pos); -+ int (*CheckPosition) (EP_RAIL *rail); -+ void (*NeterrFixup) (EP_RAIL *rail, unsigned int nodeId, EP_NETERR_COOKIE *cookies); -+ -+ void (*LoadSystemRoute) (EP_RAIL *rail, unsigned int vp, unsigned int lowNode, unsigned int highNode); -+ -+ void (*LoadNodeRoute) (EP_RAIL *rail, unsigned nodeId); -+ void (*UnloadNodeRoute) (EP_RAIL *rail, unsigned nodeId); -+ void (*LowerFilter) (EP_RAIL *rail, unsigned nodeId); -+ void (*RaiseFilter) (EP_RAIL *rail, unsigned nodeId); -+ void (*NodeDisconnected) (EP_RAIL *rail, unsigned nodeId); -+ -+ void (*FlushFilters) (EP_RAIL *rail); -+ void (*FlushQueues) (EP_RAIL *rail); -+ -+ -+ EP_INPUTQ *(*AllocInputQ) (EP_RAIL *rail, unsigned qnum, unsigned slotSize, unsigned slotCount, -+ void (*callback)(EP_RAIL *rail, void *arg), void *arg); -+ void (*FreeInputQ) (EP_RAIL *rail, EP_INPUTQ *q); -+ void (*EnableInputQ) (EP_RAIL *rail, EP_INPUTQ *q); -+ void (*DisableInputQ) (EP_RAIL *rail, EP_INPUTQ *q); -+ int (*PollInputQ) (EP_RAIL *rail, EP_INPUTQ *q, int maxCount, EP_INPUTQ_HANDLER *handler, void *arg); -+ -+ EP_OUTPUTQ *(*AllocOutputQ) (EP_RAIL *rail, unsigned slotSize, unsigned slotCount); -+ void (*FreeOutputQ) (EP_RAIL *rail, EP_OUTPUTQ *outputq); -+ void *(*OutputQMsg) (EP_RAIL *rail, EP_OUTPUTQ *outputq, unsigned slotNum); -+ int (*OutputQState) (EP_RAIL *rail, EP_OUTPUTQ *outputq, unsigned slotNum); -+ int (*OutputQSend) (EP_RAIL *rail, EP_OUTPUTQ *outputq, unsigned slotNum, unsigned size, -+ unsigned vp, unsigned qnum, unsigned retries); -+ -+ void (*FillOutStats) (EP_RAIL *rail, char *str); -+ void (*Debug) (EP_RAIL *rail); -+ -+} EP_RAIL_OPS; -+ -+#define ep_alloc_inputq(rail,qnum,slotSize,slotCount,callback,arg) \ -+ (rail)->Operations.AllocInputQ(rail,qnum,slotSize,slotCount,callback,arg) -+#define ep_free_inputq(rail,inputq) \ -+ (rail)->Operations.FreeInputQ(rail,inputq) -+#define ep_enable_inputq(rail,inputq) \ -+ (rail)->Operations.EnableInputQ(rail,inputq) -+#define ep_disable_inputq(rail,inputq) \ -+ (rail)->Operations.DisableInputQ(rail,inputq) -+#define ep_poll_inputq(rail,inputq,maxCount,handler,arg) \ -+ (rail)->Operations.PollInputQ(rail,inputq,maxCount,handler,arg) -+#define ep_alloc_outputq(rail,slotSize,slotCount)\ -+ (rail)->Operations.AllocOutputQ(rail,slotSize,slotCount) -+#define ep_free_outputq(rail,outputq)\ -+ (rail)->Operations.FreeOutputQ(rail,outputq) -+#define ep_outputq_msg(rail,outputq,slotNum)\ -+ (rail)->Operations.OutputQMsg(rail,outputq,slotNum) -+#define ep_outputq_state(rail,outputq,slotNum)\ -+ (rail)->Operations.OutputQState(rail,outputq,slotNum) -+#define ep_outputq_send(rail,outputq,slotNum,size,vp,qnum,retries)\ -+ (rail)->Operations.OutputQSend(rail,outputq,slotNum,size,vp,qnum,retries) -+ -+struct ep_rail -+{ -+ EP_SYS *System; /* "system" we've attached to */ -+ -+ unsigned char Number; /* Rail number */ -+ unsigned char State; /* Rail state */ -+ char Name[32]; /* Rail name */ -+ -+ struct list_head ManagerLink; /* linked on ManagedRails list */ -+ -+ ELAN_DEVINFO Devinfo; /* Device information for this rail */ -+ ELAN_POSITION Position; /* Position on switch device is connected to */ -+ -+ EP_RAIL_OPS Operations; /* device specific operations */ -+ EP_RAIL_STATS Stats; /* statistics */ -+ -+ EP_ALLOC ElanAllocator; /* per-rail elan memory allocator */ -+ EP_ALLOC MainAllocator; /* per-rail main memory allocator */ -+ -+ unsigned TlbFlushRequired; /* lazy TLB flushing */ -+ -+ int SwitchBroadcastLevel; /* current switch level ok for broadcast */ -+ unsigned long SwitchBroadcastLevelTick; -+ -+ int SwitchProbeLevel; /* result of last switch probe */ -+ EP_SWITCHSTATE SwitchState[ELAN_MAX_LEVELS]; -+ EP_SWITCHSTATE SwitchLast[ELAN_MAX_LEVELS]; -+ unsigned long SwitchProbeTick[ELAN_MAX_LEVELS]; -+ -+ /* Node disconnecting/connecting state */ -+ EP_CALLBACK *CallbackList[EP_CB_COUNT]; /* List of callbacks */ -+ kmutex_t CallbackLock; /* and lock for it. */ -+ unsigned CallbackStep; /* step through UpdateConnectionState. */ -+ -+ /* back pointer for cluster membership */ -+ void *ClusterRail; -+ -+ /* Per node state for message passing */ -+ EP_NODE_RAIL *Nodes; /* array of per-node state */ -+ statemap_t *NodeSet; /* per-rail statemap of connected nodes */ -+ statemap_t *NodeChangeMap; /* statemap of nodes to being connected/disconnected */ -+ statemap_t *NodeChangeTmp; /* and temporary copies */ -+ -+ struct list_head NetworkErrorList; /* list of nodes resolving network errors */ -+ struct list_head LocalPassivateList; /* list of nodes in state LOCAL_PASSIVATE */ -+ struct list_head RemotePassivateList; /* list of nodes waiting for remote network error flush */ -+ struct list_head PassivatedList; /* list of nodes performing message relocation */ -+ struct list_head DisconnectingList; /* list of nodes transitioning to disconnected */ -+ -+ EP_XID_CACHE XidCache; /* XID cache for node messages (single threaded access) */ -+ -+ /* Manager messages */ -+ EP_INPUTQ *ManagerInputQ; -+ EP_OUTPUTQ *ManagerOutputQ; -+ unsigned ManagerOutputQNextSlot; -+ spinlock_t ManagerOutputQLock; -+ -+ /* /proc entries */ -+ struct proc_dir_entry *ProcDir; -+ struct proc_dir_entry *SvcIndicatorDir; -+ int CallbackRegistered; -+}; -+ -+/* values for State */ -+#define EP_RAIL_STATE_UNINITIALISED 0 /* device uninitialised */ -+#define EP_RAIL_STATE_STARTED 1 /* device started but network position unknown */ -+#define EP_RAIL_STATE_RUNNING 2 /* device started and position known */ -+#define EP_RAIL_STATE_INCOMPATIBLE 3 /* device started, but position incompatible */ -+ -+typedef struct ep_rail_entry -+{ -+ struct list_head Link; -+ EP_RAIL *Rail; -+} EP_RAIL_ENTRY; -+ -+typedef struct ep_subsys -+{ -+ EP_SYS *Sys; -+ -+ struct list_head Link; /* Linked on sys->Subsystems */ -+ char *Name; /* Name to lookup */ -+ -+ void (*Destroy) (struct ep_subsys *subsys, EP_SYS *sys); -+ -+ int (*AddRail) (struct ep_subsys *subsys, EP_SYS *sys, EP_RAIL *rail); -+ void (*RemoveRail) (struct ep_subsys *subsys, EP_SYS *sys, EP_RAIL *rail); -+} EP_SUBSYS; -+ -+typedef struct ep_node -+{ -+ EP_RAILMASK ConnectedRails; -+} EP_NODE; -+ -+struct ep_sys -+{ -+ EP_RAIL *Rails[EP_MAX_RAILS]; /* array of all available devices */ -+ -+ kmutex_t StartStopLock; /* lock for starting stopping rails */ -+ -+ ELAN_POSITION Position; /* primary node position */ -+ -+ EP_NMH_TABLE MappingTable; /* Network mapping handle table */ -+ -+ EP_ALLOC Allocator; /* shared main memory allocator */ -+ -+ EP_DVMA_STATE DvmaState; /* dvma state */ -+ -+ kmutex_t SubsysLock; /* lock on the Subsytems list */ -+ struct list_head Subsystems; /* list of subsystems */ -+ -+ /* device manager state */ -+ struct list_head ManagedRails; /* list of managed devices */ -+ EP_KTHREAD ManagerThread; /* place for manager thread to sleep */ -+ -+ /* global node state */ -+ spinlock_t NodeLock; /* spinlock for node state (including per-device node state) */ -+ EP_NODE *Nodes; /* system wide node state */ -+ statemap_t *NodeSet; /* system wide nodeset */ -+ struct list_head NodesetCallbackList; /* list of "callbacks" */ -+ -+ /* Transaction Id */ -+ struct list_head XidCacheList; /* list of XID caches */ -+ uint32_t XidGeneration; /* XID generation number (distinguishes reboots) */ -+ uint32_t XidHandle; /* XID handles (distinguishes XID caches) */ -+ uint64_t XidNext; /* next XID to prime cache */ -+ spinlock_t XidLock; /* and it's spinlock */ -+ -+ /* Shutdown/Panic */ -+ unsigned int Shutdown; /* node has shutdown/panic'd */ -+}; -+ -+#if defined(DEBUG_ASSERT) -+extern int ep_assfail (EP_RAIL *rail, const char *string, const char *func, const char *file, const int line); -+extern int sdram_assert; -+extern int assfail_mode; -+ -+#define EP_ASSERT(rail, EX) do { \ -+ if (!(EX) && ep_assfail ((EP_RAIL *) (rail), #EX, __FUNCTION__, __FILE__, __LINE__)) { \ -+ BUG(); \ -+ } \ -+} while (0) -+#define EP_ASSFAIL(rail,EX) do { \ -+ if (ep_assfail ((EP_RAIL *) (rail), EX, __FUNCTION__, __FILE__, __LINE__)) { \ -+ BUG(); \ -+ } \ -+} while (0) -+#define SDRAM_ASSERT(EX) (sdram_assert ? (EX) : 1) -+#else -+#define EP_ASSERT(rail, EX) ((void) 0) -+#define EP_ASSFAIL(rail,str) ((void) 0) -+#define SDRAM_ASSERT(EX) (1) -+#endif -+ -+/* conf_osdep.c */ -+extern EP_SYS *ep_system(void); -+extern void ep_mod_dec_usecount (void); -+extern void ep_mod_inc_usecount (void); -+ -+/* procfs_osdep.c */ -+extern struct proc_dir_entry *ep_procfs_root; -+extern struct proc_dir_entry *ep_config_root; -+ -+/* kcomm.c */ -+extern int ep_sys_init (EP_SYS *sys); -+extern void ep_sys_fini (EP_SYS *sys); -+extern void ep_shutdown (EP_SYS *sys); -+extern int ep_init_rail (EP_SYS *sys, EP_RAIL *rail); -+extern void ep_destroy_rail (EP_RAIL *rail); -+extern int ep_start_rail (EP_RAIL *rail); -+extern void ep_stop_rail (EP_RAIL *rail); -+ -+extern void ep_connect_node (EP_RAIL *rail, int nodeId); -+extern int ep_disconnect_node (EP_RAIL *rail, int nodeId); -+ -+extern EP_XID ep_xid_cache_alloc (EP_SYS *sys, EP_XID_CACHE *cache); -+extern void ep_xid_cache_init (EP_SYS *sys, EP_XID_CACHE *cache); -+extern void ep_xid_cache_destroy (EP_SYS *sys, EP_XID_CACHE *cache); -+ -+extern int ep_send_message (EP_RAIL *rail, int nodeId, int type, EP_XID xid, EP_MANAGER_MSG_BODY *body); -+ -+extern void ep_panic_node (EP_SYS *sys, int nodeId, unsigned char *reason); -+ -+extern void ep_subsys_add (EP_SYS *sys, EP_SUBSYS *subsys); -+extern void ep_subsys_del (EP_SYS *sys, EP_SUBSYS *subsys); -+extern EP_SUBSYS *ep_subsys_find (EP_SYS *sys, char *name); -+ -+extern void DisplayNodes (EP_RAIL *rail); -+ -+extern void ep_fillout_stats(EP_RAIL *rail, char *str); -+ -+/* neterr.c */ -+extern void ep_queue_network_error (EP_RAIL *rail, int nodeId, int what, int channel, EP_NETERR_COOKIE cookie); -+ -+/* kcomm_elan3.c */ -+extern unsigned int ep3_create_rails (EP_SYS *sys, unsigned int disabled); -+ -+/* kcomm_elan4.c */ -+extern unsigned int ep4_create_rails (EP_SYS *sys, unsigned int disabled); -+ -+/* probenetwork.c */ -+extern int ProbeNetwork (EP_RAIL *rail, ELAN_POSITION *pos); -+extern void CheckPosition (EP_RAIL *rail); -+ -+extern uint16_t CheckSum (char *msg, int nob); -+ -+/* threadcode.c */ -+extern EP_ADDR ep_symbol (EP_CODE *code, char *name); -+extern int ep_loadcode (EP_RAIL *rail, EP_CODE *code); -+extern void ep_unloadcode (EP_RAIL *rail, EP_CODE *code); -+ -+/* Public interface */ -+/* debug.c */ -+extern int ep_sprintf_bitmap (char *str, unsigned nbytes, bitmap_t *bitmap, int base, int count, int off); -+extern void ep_display_bitmap (char *prefix, char *tag, bitmap_t *bitmap, unsigned base, unsigned nbits); -+ -+/* epcomms.c */ -+extern int ep_waitfor_nodeid (EP_SYS *sys); -+extern int ep_nodeid (EP_SYS *sys); -+extern int ep_numnodes (EP_SYS *sys); -+ -+/* railhints.c */ -+extern int ep_pickRail(EP_RAILMASK railmask); -+ -+/* support.c */ -+extern int ep_register_nodeset_callback (EP_SYS *sys, void (*routine)(void *, statemap_t *), void *arg); -+extern void ep_remove_nodeset_callback (EP_SYS *sys, void (*routine)(void *, statemap_t *), void *arg); -+extern void ep_call_nodeset_callbacks (EP_SYS *sys, statemap_t *map); -+ -+extern int ep_register_callback (EP_RAIL *rail, unsigned idx, void (*routine)(void *, statemap_t *), void *arg); -+extern void ep_remove_callback (EP_RAIL *rail, unsigned idx, void (*routine)(void *, statemap_t *), void *arg); -+extern void ep_call_callbacks (EP_RAIL *rail, unsigned idx, statemap_t *); -+extern unsigned int ep_backoff (EP_BACKOFF *backoff, int type); -+ -+#endif /* !__ELAN__ */ -+ -+typedef struct display_info { -+ void (*func)(long, char *, ...); -+ long arg; -+} DisplayInfo; -+ -+extern DisplayInfo di_ep_debug; -+ -+ -+#endif /* __ELAN_KCOMM_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/kcomm_stats.h -=================================================================== ---- linux-2.4.21.orig/include/elan/kcomm_stats.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/kcomm_stats.h 2005-06-01 23:12:54.712421928 -0400 -@@ -0,0 +1,153 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __EP_EPSTATS_H -+#define __EP_EPSTATS_H -+ -+#ident "$Id: kcomm_stats.h,v 1.4.8.1 2004/11/12 10:54:51 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kcomm_stats.h,v $ */ -+ -+#define EP_BUCKET_SLOTS 8 -+ -+#define BucketStat(obj,stat,size) ((size) < 128 ? (obj)->Stats.stat[0]++ : \ -+ (size) < 512 ? (obj)->Stats.stat[1]++ : \ -+ (size) < 1024 ? (obj)->Stats.stat[2]++ : \ -+ (size) < 8192 ? (obj)->Stats.stat[3]++ : \ -+ (size) < 16384 ? (obj)->Stats.stat[4]++ : \ -+ (size) < 32768 ? (obj)->Stats.stat[5]++ : \ -+ (size) < 65536 ? (obj)->Stats.stat[6]++ : \ -+ (obj)->Stats.stat[7]++) -+#define IncrStat(obj,stat) ((obj)->Stats.stat++) -+ -+ -+#define EP3_NUM_DMA_FAIL 11 /* NOTE - the same as EP_NUM_RETRIES */ -+ -+#define ADD_STAT(STATS,STAT,VALUE) { unsigned long now = lbolt;\ -+ STATS.STAT.total += VALUE; \ -+ if ( ( now - STATS.STAT.last_time ) > HZ ) { \ -+ STATS.STAT.last_per_sec = ( STATS.STAT.total - STATS.STAT.last_count)/ ( (( now - STATS.STAT.last_time ) + (HZ/2)) / HZ);\ -+ STATS.STAT.last_time = now; \ -+ STATS.STAT.last_count = STATS.STAT.total; \ -+ }} \ -+ -+#define INC_STAT(STATS,STAT) ADD_STAT(STATS,STAT,1) -+ -+#define GET_STAT_PER_SEC(STATS, STAT) ( (( lbolt - STATS.STAT.last_time ) < (HZ * 5)) ? STATS.STAT.last_per_sec : 0 ) -+#define GET_STAT_TOTAL(STATS, STAT) ( STATS.STAT.total ) -+ -+struct ep_stats_count -+{ -+ unsigned long total; -+ unsigned long last_time; -+ unsigned long last_count; -+ unsigned long last_per_sec; -+}; -+ -+typedef struct ep_stats_count EP_STATS_COUNT; -+ -+typedef struct ep3_rail_stats -+{ -+ unsigned long IssueDmaFail[EP3_NUM_DMA_FAIL]; -+ -+ unsigned long DmaQueueLength[EP_BUCKET_SLOTS]; -+ unsigned long CprocDmaQueueOverflow; -+ unsigned long DprocDmaQueueOverflow; -+ unsigned long IprocDmaQueueOverflow; -+ unsigned long CprocEventQueueOverflow; -+ unsigned long DprocEventQueueOverflow; -+ unsigned long IprocEventQueueOverflow; -+ -+ unsigned long QueueingPacketTrap; -+ unsigned long DmaIdentifyTrap; -+ unsigned long ThreadIdentifyTrap; -+ unsigned long DmaPacketTrap; -+} EP3_RAIL_STATS; -+ -+typedef struct ep4_rail_stats -+{ -+ unsigned long somestatsgohere; -+} EP4_RAIL_STATS; -+ -+typedef struct ep_rail_stats -+{ -+ unsigned long SendMessageFailed; -+ unsigned long NeterrAtomicPacket; -+ unsigned long NeterrDmaPacket; -+ -+ EP_STATS_COUNT rx; -+ EP_STATS_COUNT rx_len; -+ -+ EP_STATS_COUNT tx; -+ EP_STATS_COUNT tx_len; -+ -+} EP_RAIL_STATS; -+ -+typedef struct ep_cm_rail_stats -+{ -+ /* cluster membership statistics */ -+ unsigned long HeartbeatsSent; -+ unsigned long HeartbeatsRcvd; -+ -+ unsigned long RetryHeartbeat; -+ unsigned long RejoinRequest; -+ unsigned long RejoinTooSlow; -+ unsigned long LaunchMessageFail; -+ unsigned long MapChangesSent; -+ -+ /* Heartbeat scheduling stats */ -+ unsigned long HeartbeatOverdue; -+} EP_CM_RAIL_STATS; -+ -+typedef struct ep_comms_rail_stats -+{ -+ /* kernel comms large message statistics */ -+ unsigned long TxEnveEvent; -+ unsigned long TxDataEvent; -+ unsigned long TxDoneEvent; -+ unsigned long RxDoneEvent; -+ unsigned long MulticastTxDone; -+ unsigned long QueueReceive; -+ -+ unsigned long TxEnveRetry; -+ unsigned long TxDataRetry; -+ unsigned long TxDoneRetry; -+ unsigned long RxThrdEvent; -+ unsigned long RxDataRetry; -+ unsigned long RxDoneRetry; -+ unsigned long StallThread; -+ unsigned long ThrdWaiting; -+ unsigned long CompleteEnvelope; -+ -+ unsigned long NoFreeTxds; -+ unsigned long NoFreeRxds; -+ -+ unsigned long LockRcvrTrapped; -+} EP_COMMS_RAIL_STATS; -+ -+typedef struct ep_comms_stats -+{ -+ unsigned long DataXmit[8]; -+ unsigned long McastXmit[8]; -+ unsigned long RPCXmit[8]; -+ unsigned long RPCPut[8]; -+ unsigned long RPCGet[8]; -+ unsigned long CompleteRPC[8]; -+ unsigned long RxData[8]; -+ unsigned long RxMcast[8]; -+ -+ unsigned long NoFreeTxds; -+ unsigned long NoFreeRxds; -+} EP_COMMS_STATS; -+ -+#endif /* __EP_EPSTATS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/kmap.h -=================================================================== ---- linux-2.4.21.orig/include/elan/kmap.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/kmap.h 2005-06-01 23:12:54.713421776 -0400 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_KMAP_H -+#define __ELAN_KMAP_H -+ -+#ident "$Id: kmap.h,v 1.3.8.1 2004/12/14 10:19:14 mike Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmap.h,v $ */ -+ -+#include -+ -+extern void ep_perrail_kaddr_map (EP_RAIL *rail, EP_ADDR eaddr, virtaddr_t vaddr, unsigned long len, unsigned int perm, int ep_attr); -+extern void ep_perrail_sdram_map (EP_RAIL *rail, EP_ADDR eaddr, sdramaddr_t saddr, unsigned long len, unsigned int perm, int ep_attr); -+extern void ep_perrail_unmap (EP_RAIL *rail, EP_ADDR eaddr, unsigned long len); -+extern void ep_perrail_dvma_sync (EP_RAIL *rail); -+ -+typedef struct ep_dvma_nmh -+{ -+ EP_NMH dvma_nmh; -+ -+ struct list_head dvma_link; /* chained on ep_dvma_state */ -+ unsigned dvma_perm; /* permissions for region */ -+ -+ spinlock_t dvma_lock; -+ EP_RAILMASK dvma_railmask; /* bitmap of rails */ -+ EP_RAIL *dvma_rails[EP_MAX_RAILS]; /* assoicated rails */ -+ void *dvma_private[EP_MAX_RAILS]; /* pointers to rail private data */ -+ unsigned int dvma_attrs[1]; /* bitmap of which rails pages are loaded NOTE - max 32 rails */ -+} EP_DVMA_NMH; -+ -+/* values for dvma_perm */ -+#define EP_PERM_EXECUTE 0 -+#define EP_PERM_READ 1 -+#define EP_PERM_WRITE 2 -+#define EP_PERM_ALL 3 -+ -+typedef struct ep_dvma_state -+{ -+ kmutex_t dvma_lock; -+ struct list_head dvma_handles; -+ struct list_head dvma_rails; -+ EP_RMAP *dvma_rmap; -+} EP_DVMA_STATE; -+ -+extern void ep_dvma_init (EP_SYS *sys); -+extern void ep_dvma_fini (EP_SYS *sys); -+extern EP_NMH *ep_dvma_reserve (EP_SYS *sys, unsigned npages, unsigned perm); -+extern void ep_dvma_release (EP_SYS *sys, EP_NMH *nmh); -+extern void ep_dvma_load (EP_SYS *sys, void *map, caddr_t vaddr, unsigned len, -+ EP_NMH *nmh, unsigned index, EP_RAILMASK *hints, EP_NMD *subset); -+extern void ep_dvma_unload (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd); -+ -+extern void ep_dvma_remove_rail (EP_SYS *sys, EP_RAIL *rail); -+extern int ep_dvma_add_rail (EP_SYS *sys, EP_RAIL *rail); -+ -+extern uint16_t rolling_check_sum (char *msg, int nob, uint16_t sum); -+ -+#endif /* __ELAN_KMAP_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/kmsg.h -=================================================================== ---- linux-2.4.21.orig/include/elan/kmsg.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/kmsg.h 2005-06-01 23:12:54.713421776 -0400 -@@ -0,0 +1,14 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_KMSG_H -+#define __ELAN_KMSG_H -+ -+#ident "@(#)$Id: kmsg.h,v 1.1 2003/09/23 13:55:12 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/kmsg.h,v $ */ -+ -+#endif /* __ELAN_KMSG_H */ -Index: linux-2.4.21/include/elan/kthread.h -=================================================================== ---- linux-2.4.21.orig/include/elan/kthread.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/kthread.h 2005-06-01 23:12:54.713421776 -0400 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_KTHREAD_H -+#define __ELAN3_KTHREAD_H -+ -+#ident "@(#)$Id: kthread.h,v 1.4 2004/05/06 14:24:08 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/epmod/kthread.h,v $*/ -+ -+typedef struct ep_kthread -+{ -+ kcondvar_t wait; /* place to sleep */ -+ spinlock_t lock; /* and lock */ -+ long next_run; /* tick when thread should next run */ -+ long running; /* tick when thread started to run */ -+ unsigned short should_stall; -+ unsigned char state; -+ unsigned int started:1; -+ unsigned int should_stop:1; -+ unsigned int stopped:1; -+} EP_KTHREAD; -+ -+#define KT_STATE_SLEEPING 0 -+#define KT_STATE_SCHEDULED 1 -+#define KT_STATE_RUNNING 2 -+#define KT_STATE_STALLED 3 -+ -+#define AFTER(a, b) ((((long)(a)) - ((long)(b))) > 0) -+#define BEFORE(a,b) ((((long)(a)) - ((long)(b))) < 0) -+ -+extern void ep_kthread_init (EP_KTHREAD *kt); -+extern void ep_kthread_destroy (EP_KTHREAD *kt); -+extern void ep_kthread_started (EP_KTHREAD *kt); -+extern void ep_kthread_stopped (EP_KTHREAD *kt); -+extern int ep_kthread_should_stall (EP_KTHREAD *kth); -+extern int ep_kthread_sleep (EP_KTHREAD *kth, long next_run); -+extern void ep_kthread_schedule (EP_KTHREAD *kt, long when); -+extern void ep_kthread_stall (EP_KTHREAD *kth); -+extern void ep_kthread_resume (EP_KTHREAD *kt); -+extern void ep_kthread_stop (EP_KTHREAD *kt); -+extern int ep_kthread_state (EP_KTHREAD *kt, long *time); -+#endif /* __ELAN3_KTHREAD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/nmh.h -=================================================================== ---- linux-2.4.21.orig/include/elan/nmh.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/nmh.h 2005-06-01 23:12:54.714421624 -0400 -@@ -0,0 +1,95 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_NMH_H -+#define __ELAN3_NMH_H -+ -+#ident "@(#)$Id: nmh.h,v 1.7 2004/01/06 10:29:55 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/nmh.h,v $*/ -+ -+ -+/* Forward declarations */ -+typedef struct ep_nmd EP_NMD; -+typedef struct ep_nmh_ops EP_NMH_OPS; -+typedef struct ep_nmh EP_NMH; -+ -+/* Railmask held in 16 bit field (packs with nodeId into NMD */ -+typedef uint16_t EP_RAILMASK; -+ -+#define EP_RAIL2RAILMASK(rnum) (1 << (rnum)) -+#define EP_RAILMASK_ALL 0xffff -+ -+/* kernel comms elan network address */ -+typedef uint32_t EP_ADDR; -+ -+/* network mapping descriptor - this is returned to the user from a map operation, -+ * and is what is passed to all communication functions */ -+struct ep_nmd -+{ -+ EP_ADDR nmd_addr; /* base address */ -+ uint32_t nmd_len; /* size in bytes */ -+ uint32_t nmd_attr; /* nodeid << 16 | railmask */ -+}; -+ -+#define EP_NMD_ATTR(nodeid,railmask) (((nodeid) << 16) | (railmask)) -+#define EP_NMD_NODEID(nmd) ((nmd)->nmd_attr >> 16) -+#define EP_NMD_RAILMASK(nmd) ((nmd)->nmd_attr & EP_RAILMASK_ALL) -+ -+#if !defined(__ELAN__) -+ -+struct ep_nmh_ops -+{ -+ int (*op_map_rails) (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd, EP_RAILMASK mask); /* add mappings to different rail(s) */ -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+ uint16_t (*op_calc_check_sum) (EP_SYS *sys, EP_NMH *nmh, EP_NMD *nmd, uint16_t check_sum); /* calculates check sum */ -+#endif -+}; -+ -+struct ep_nmh -+{ -+ EP_NMD nmh_nmd; /* public field */ -+ struct list_head nmh_link; /* linked on hash table */ -+ EP_NMH_OPS *nmh_ops; /* operations to perform on object */ -+}; -+ -+#define EP_NMH_NUMHASH (32 - 11 + 1) /* one hash table for each power of 2 above pagesize */ -+#define EP_NMH_HASHSIZE (64) /* max size of each hash table */ -+ -+typedef struct ep_nmh_table -+{ -+ struct list_head *tbl_hash[EP_NMH_NUMHASH]; -+ unsigned tbl_size[EP_NMH_NUMHASH]; -+} EP_NMH_TABLE; -+ -+extern int ep_nmh_init (EP_NMH_TABLE *tbl); -+extern void ep_nmh_fini (EP_NMH_TABLE *tbl); -+ -+extern void ep_nmh_insert (EP_NMH_TABLE *tbl, EP_NMH *nmd); -+extern void ep_nmh_remove (EP_NMH_TABLE *tbl, EP_NMH *nmd); -+extern EP_NMH *ep_nmh_find (EP_NMH_TABLE *tbl, EP_NMD *nmh); -+ -+#if ! defined(CONFIG_EP_NO_CHECK_SUM) -+extern uint32_t ep_nmd_calc_data_check_sum(EP_SYS *sys, EP_NMD *nmd, int nFrags); -+#endif -+ -+/* Public interface */ -+extern EP_RAILMASK ep_nmd2railmask (EP_NMD *frags, int nFrags); -+extern void ep_nmd_subset (EP_NMD *subset, EP_NMD *nmd, unsigned off, unsigned len); -+extern int ep_nmd_merge (EP_NMD *merged, EP_NMD *a, EP_NMD *b); -+extern int ep_nmd_map_rails (EP_SYS *sys, EP_NMD *nmd, unsigned railmask); -+ -+#endif /* __ELAN__ */ -+ -+#endif /* __ELAN3_NMH_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/rmap.h -=================================================================== ---- linux-2.4.21.orig/include/elan/rmap.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/rmap.h 2005-06-01 23:12:54.714421624 -0400 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_RMAP_H -+#define __ELAN_RMAP_H -+ -+#ident "$Id: rmap.h,v 1.8 2004/05/19 10:24:40 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/rmap.h,v $ */ -+ -+ -+typedef struct ep_rmap_entry -+{ -+ size_t m_size; -+ u_long m_addr; -+} EP_RMAP_ENTRY; -+ -+typedef struct ep_rmap -+{ -+ spinlock_t m_lock; -+ kcondvar_t m_wait; -+ u_int m_size; -+ u_int m_free; -+ u_int m_want; -+ char *m_name; -+ EP_RMAP_ENTRY m_map[1]; -+} EP_RMAP; -+ -+extern void ep_display_rmap (EP_RMAP *map); -+ -+extern void ep_rmapinit (EP_RMAP *rmap, char *name, u_int mapsize); -+extern unsigned long ep_rmalloc (EP_RMAP *rmap, size_t size, int cansleep); -+extern unsigned long ep_rmalloc_constrained (EP_RMAP *mp, size_t size, unsigned long alo, unsigned long ahi, unsigned long align, int cansleep); -+extern void ep_rmfree (EP_RMAP *rmap, size_t size, unsigned long addr); -+extern unsigned long ep_rmget (EP_RMAP *rmap, size_t size, unsigned long addr); -+extern EP_RMAP *ep_rmallocmap (size_t size, char *name, int cansleep); -+extern void ep_rmfreemap (EP_RMAP *map); -+ -+#endif /* __ELAN3_RMAP_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/statemap.h -=================================================================== ---- linux-2.4.21.orig/include/elan/statemap.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/statemap.h 2005-06-01 23:12:54.714421624 -0400 -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN_STATEMAP_H -+#define __ELAN_STATEMAP_H -+ -+#ident "$Id: statemap.h,v 1.8 2003/10/07 13:22:38 david Exp $" -+/* $Source: /cvs/master/quadrics/epmod/statemap.h,v $ */ -+ -+#include -+ -+/******************************** global state bitmap stuff **********************************/ -+typedef struct -+{ -+ unsigned int size; -+ unsigned int nob; -+ unsigned int changemap_nob; -+ unsigned int bitmap_nob; -+ bitmap_t *changemap0; -+ bitmap_t *changemap1; -+ bitmap_t *changemap2; -+ bitmap_t *bitmap; -+} statemap_t; -+ -+extern bitmap_t statemap_getseg (statemap_t *map, unsigned int offset); -+extern void statemap_setseg (statemap_t *map, unsigned int offset, bitmap_t seg); -+extern bitmap_t statemap_getbits (statemap_t *map, unsigned int offset, int nbits); -+extern void statemap_setbits (statemap_t *map, unsigned int offset, bitmap_t bits, int nbits); -+extern void statemap_zero (statemap_t *map); -+extern void statemap_setmap (statemap_t *dst, statemap_t *src); -+extern void statemap_ormap (statemap_t *dst, statemap_t *src); -+extern int statemap_findchange (statemap_t *map, bitmap_t *newseg, int clearchange); -+extern int statemap_changed (statemap_t *map); -+extern void statemap_reset (statemap_t *map); -+extern void statemap_copy (statemap_t *dst, statemap_t *src); -+extern void statemap_clearchanges (statemap_t *map); -+extern bitmap_t *statemap_tobitmap (statemap_t *map); -+extern statemap_t *statemap_create (int size); -+extern void statemap_destroy (statemap_t *map); -+ -+#endif /* __ELAN_STATEMAP_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan/stats.h -=================================================================== ---- linux-2.4.21.orig/include/elan/stats.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan/stats.h 2005-06-01 23:12:54.715421472 -0400 -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: stats.h,v 1.5 2003/09/24 13:55:37 david Exp $" -+/* $Source: /cvs/master/quadrics/elanmod/modsrc/stats.h,v $*/ -+ -+#ifndef __ELAN_STATS_H -+#define __ELAN_STATS_H -+ -+ -+/* non-kernel headings */ -+#define ELAN_STATS_NAME_MAX_LEN ((uint)64) -+typedef unsigned int ELAN_STATS_IDX; -+ -+typedef struct elan_stats_map -+{ -+ char entry_name[ELAN_STATS_NAME_MAX_LEN]; -+ int index; -+} ELAN_STATS_MAP; -+ -+#if defined(__KERNEL__) -+ -+/* stats callbacks */ -+#define ELAN_STATS_OPS_VERSION ((u_int)1) -+typedef struct elan_stats_ops -+{ -+ u_int ops_version; -+ -+ int (*elan_stats_get_name) (void * arg, uint index, caddr_t name); -+ int (*elan_stats_get_block) (void * arg, uint entries, ulong *values); -+ int (*elan_stats_clear_block) (void * arg); -+ -+} ELAN_STATS_OPS; -+ -+typedef struct elan_stats_struct -+{ -+ struct list_head node; -+ -+ ELAN_STATS_IDX statidx; -+ char block_name[ELAN_STATS_NAME_MAX_LEN]; -+ uint num_entries; -+ ELAN_STATS_OPS *ops; -+ void *arg; -+ -+} ELAN_STATS_STRUCT; -+ -+/* stats.c */ -+extern int elan_stats_register (ELAN_STATS_IDX *statidx, -+ char *block_name, -+ uint num_entries, -+ ELAN_STATS_OPS *ops, -+ void *arg); -+ -+extern int elan_stats_deregister (ELAN_STATS_IDX statidx); -+extern ELAN_STATS_STRUCT *elan_stats_find (ELAN_STATS_IDX statidx); -+extern ELAN_STATS_STRUCT *elan_stats_find_by_name(caddr_t block_name); -+extern ELAN_STATS_STRUCT *elan_stats_find_next (ELAN_STATS_IDX statidx); -+ -+ -+/* elan_stats.c */ -+extern int elan_stats_get_next_index (ELAN_STATS_IDX statidx, ELAN_STATS_IDX *next_statidx); -+ -+extern int elan_stats_find_index (caddr_t block_name, ELAN_STATS_IDX *statidx, uint *num_entries); -+ -+extern int elan_stats_get_block_info (ELAN_STATS_IDX statidx, caddr_t block_name, uint *num_entries); -+ -+extern int elan_stats_get_index_name (ELAN_STATS_IDX statidx, uint index, caddr_t name); -+ -+extern int elan_stats_get_block (ELAN_STATS_IDX statidx, uint entries, ulong *values); -+ -+extern int elan_stats_clear_block (ELAN_STATS_IDX statidx); -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* __ELAN_STATS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/compat.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/compat.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/compat.h 2005-06-01 23:12:54.715421472 -0400 -@@ -0,0 +1,177 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: compat.h,v 1.4 2004/06/09 09:07:03 mike Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/compat.h,v $*/ -+ -+#ifndef __ELAN3_COMPAT_H -+#define __ELAN3_COMPAT_H -+ -+/* compatibility header to allow Eagle branch QSNETLIBS -+ * to compile against head kernel */ -+ -+#define ELAN_EAGLE_COMPAT -+ -+/* vmseg.h */ -+#define ELAN_FLAGSTATS ELAN3_FLAGSTATS -+ -+/* uregs.h */ -+#define ELAN_STATS_NAME ELAN3_STATS_NAME -+#define elan3_stats_names elan_stats_names -+ -+/* spinlock.h */ -+#define ELAN_SPINLOCK ELAN3_SPINLOCK -+#define ELAN_SPINLOCK_MAIN ELAN3_SPINLOCK_MAIN -+#define ELAN_SPINLOCK_ELAN ELAN3_SPINLOCK_ELAN -+#define ELAN_ME_SPINENTER ELAN3_ME_SPINENTER -+#define ELAN_ME_FORCEENTER ELAN3_ME_FORCEENTER -+#define ELAN_ME_SPINEXIT ELAN3_ME_SPINEXIT -+#define ELAN_SPINENTER ELAN3_SPINENTER -+#define ELAN_SPINEXIT ELAN3_SPINEXIT -+#define elan3_me_spinblock elan_me_spinblock -+#define elan3_spinenter elan_spinenter -+ -+/* elanio.h */ -+#define ELANIO_CONTROL_PATHNAME ELAN3IO_CONTROL_PATHNAME -+#define ELANIO_USER_PATHNAME ELAN3IO_USER_PATHNAME -+#define ELANIO_SDRAM_PATHNAME ELAN3IO_SDRAM_PATHNAME -+#define ELANIO_MAX_PATHNAMELEN ELAN3IO_MAX_PATHNAMELEN -+ -+#define ELANIO_SET_BOUNDARY_SCAN ELAN3IO_SET_BOUNDARY_SCAN -+#define ELANIO_CLEAR_BOUNDARY_SCAN ELAN3IO_CLEAR_BOUNDARY_SCAN -+#define ELANIO_READ_LINKVAL ELAN3IO_READ_LINKVAL -+#define ELANIO_WRITE_LINKVAL ELAN3IO_WRITE_LINKVAL -+#define ELANIO_SET_DEBUG_STRUCT ELAN3IO_SET_DEBUG_STRUCT -+#define ELANIO_SET_DEBUG ELAN3IO_SET_DEBUG -+#define ELANIO_DEBUG_BUFFER_STRUCT ELAN3IO_DEBUG_BUFFER_STRUCT -+#define ELANIO_DEBUG_BUFFER ELAN3IO_DEBUG_BUFFER -+#define ELANIO_NETERR_SERVER_STRUCT ELAN3IO_NETERR_SERVER_STRUCT -+#define ELANIO_NETERR_SERVER ELAN3IO_NETERR_SERVER -+#define ELANIO_NETERR_FIXUP ELAN3IO_NETERR_FIXUP -+ -+#define ELANIO_FREE ELAN3IO_FREE -+#define ELANIO_ATTACH ELAN3IO_ATTACH -+#define ELANIO_DETACH ELAN3IO_DETACH -+#define ELANIO_ADDVP_STRUCT ELAN3IO_ADDVP_STRUCT -+#define ELANIO_ADDVP ELAN3IO_ADDVP -+#define ELANIO_REMOVEVP ELAN3IO_REMOVEVP -+#define ELANIO_BCASTVP_STRUCT ELAN3IO_BCASTVP_STRUCT -+#define ELANIO_BCASTVP ELAN3IO_BCASTVP -+#define ELANIO_LOAD_ROUTE_STRUCT ELAN3IO_LOAD_ROUTE_STRUCT -+#define ELANIO_LOAD_ROUTE ELAN3IO_LOAD_ROUTE -+#define ELANIO_PROCESS ELAN3IO_PROCESS -+#define ELANIO_SETPERM_STRUCT ELAN3IO_SETPERM_STRUCT -+#define ELANIO_SETPERM ELAN3IO_SETPERM -+#define ELANIO_CLEARPERM_STRUCT ELAN3IO_CLEARPERM_STRUCT -+#define ELANIO_CLEARPERM ELAN3IO_CLEARPERM -+#define ELANIO_CHANGEPERM_STRUCT ELAN3IO_CHANGEPERM_STRUCT -+#define ELANIO_CHANGEPERM ELAN3IO_CHANGEPERM -+#define ELANIO_HELPER_THREAD ELAN3IO_HELPER_THREAD -+#define ELANIO_WAITCOMMAND ELAN3IO_WAITCOMMAND -+#define ELANIO_BLOCK_INPUTTER ELAN3IO_BLOCK_INPUTTER -+#define ELANIO_SET_FLAGS ELAN3IO_SET_FLAGS -+#define ELANIO_WAITEVENT ELAN3IO_WAITEVENT -+#define ELANIO_ALLOC_EVENTCOOKIE ELAN3IO_ALLOC_EVENTCOOKIE -+#define ELANIO_FREE_EVENTCOOKIE ELAN3IO_FREE_EVENTCOOKIE -+#define ELANIO_ARM_EVENTCOOKIE ELAN3IO_ARM_EVENTCOOKIE -+#define ELANIO_WAIT_EVENTCOOKIE ELAN3IO_WAIT_EVENTCOOKIE -+#define ELANIO_SWAPSPACE ELAN3IO_SWAPSPACE -+#define ELANIO_EXCEPTION_SPACE ELAN3IO_EXCEPTION_SPACE -+#define ELANIO_GET_EXCEPTION ELAN3IO_GET_EXCEPTION -+#define ELANIO_UNLOAD_STRUCT ELAN3IO_UNLOAD_STRUCT -+#define ELANIO_UNLOAD ELAN3IO_UNLOAD -+#define ELANIO_GET_ROUTE_STRUCT ELAN3IO_GET_ROUTE_STRUCT -+#define ELANIO_GET_ROUTE ELAN3IO_GET_ROUTE -+#define ELANIO_RESET_ROUTE_STRUCT ELAN3IO_RESET_ROUTE_STRUCT -+#define ELANIO_RESET_ROUTE ELAN3IO_RESET_ROUTE -+#define ELANIO_CHECK_ROUTE_STRUCT ELAN3IO_CHECK_ROUTE_STRUCT -+#define ELANIO_CHECK_ROUTE ELAN3IO_CHECK_ROUTE -+#define ELANIO_VP2NODEID_STRUCT ELAN3IO_VP2NODEID_STRUCT -+#define ELANIO_VP2NODEID ELAN3IO_VP2NODEID -+#define ELANIO_SET_SIGNAL ELAN3IO_SET_SIGNAL -+#define ELANIO_PROCESS_2_LOCATION_STRUCT ELAN3IO_PROCESS_2_LOCATION_STRUCT -+#define ELANIO_PROCESS_2_LOCATION ELAN3IO_PROCESS_2_LOCATION -+#define ELANIO_GET_DEVINFO_STRUCT ELAN3IO_GET_DEVINFO_STRUCT -+#define ELANIO_GET_DEVINFO ELAN3IO_GET_DEVINFO -+#define ELANIO_GET_POSITION_STRUCT ELAN3IO_GET_POSITION_STRUCT -+#define ELANIO_GET_POSITION ELAN3IO_GET_POSITION -+#define ELANIO_STATS_STRUCT ELAN3IO_STATS_STRUCT -+#define ELANIO_STATS ELAN3IO_STATS -+# define ELAN_SYS_STATS_DEVICE ELAN3_SYS_STATS_DEVICE -+# define ELAN_SYS_STATS_ELAN3MMU ELAN3_SYS_STATS_MMU -+ -+#define ELANIO_OFF_FLAG_PAGE ELAN3IO_OFF_FLAG_PAGE -+#define ELANIO_OFF_UREG_PAGE ELAN3IO_OFF_UREG_PAGE -+#define ELANIO_OFF_COMMAND_PAGE ELAN3IO_OFF_COMMAND_PAGE -+ -+ -+/* elanvp.h */ -+#define ELAN_ROUTE_SUCCESS ELAN3_ROUTE_SUCCESS -+#define ELAN_ROUTE_SYSCALL_FAILED ELAN3_ROUTE_SYSCALL_FAILED -+#define ELAN_ROUTE_INVALID ELAN3_ROUTE_INVALID -+#define ELAN_ROUTE_TOO_LONG ELAN3_ROUTE_TOO_LONG -+#define ELAN_ROUTE_LOAD_FAILED ELAN3_ROUTE_LOAD_FAILED -+#define ELAN_ROUTE_PROC_RANGE ELAN3_ROUTE_PROC_RANGE -+#define ELAN_ROUTE_INVALID_LEVEL ELAN3_ROUTE_INVALID_LEVEL -+#define ELAN_ROUTE_OCILATES ELAN3_ROUTE_OCILATES -+#define ELAN_ROUTE_WRONG_DEST ELAN3_ROUTE_WRONG_DEST -+#define ELAN_ROUTE_TURN_LEVEL ELAN3_ROUTE_TURN_LEVEL -+#define ELAN_ROUTE_NODEID_UNKNOWN ELAN3_ROUTE_NODEID_UNKNOWN -+ -+/* elandev.h */ -+#define ELAN_STATS ELAN3_STATS -+#define ELAN_STATS_VERSION ELAN3_STATS_VERSION -+ -+/* perm.h */ -+#define ELAN_PERM_NOREMOTE ELAN3_PERM_NOREMOTE -+#define ELAN_PERM_LOCAL_READ ELAN3_PERM_LOCAL_READ -+#define ELAN_PERM_REMOTEALL ELAN3_PERM_REMOTEALL -+ -+/* threadsyscall.h */ -+#define ELAN_ABORT_TRAPNUM ELAN3_ABORT_TRAPNUM -+#define ELAN_ELANCALL_TRAPNUM ELAN3_ELANCALL_TRAPNUM -+#define ELAN_SYSCALL_TRAPNUM ELAN3_SYSCALL_TRAPNUM -+#define ELAN_SYS_close ELAN3_SYS_close -+#define ELAN_SYS_getpid ELAN3_SYS_getpid -+#define ELAN_SYS_ioctl ELAN3_SYS_ioctl -+#define ELAN_SYS_kill ELAN3_SYS_kill -+#define ELAN_SYS_lseek ELAN3_SYS_lseek -+#define ELAN_SYS_mmap ELAN3_SYS_mmap -+#define ELAN_SYS_munmap ELAN3_SYS_munmap -+#define ELAN_SYS_open ELAN3_SYS_open -+#define ELAN_SYS_poll ELAN3_SYS_poll -+#define ELAN_SYS_read ELAN3_SYS_read -+#define ELAN_SYS_write ELAN3_SYS_write -+#define ELAN_T_SYSCALL_CODE ELAN3_T_SYSCALL_CODE -+#define ELAN_T_SYSCALL_ERRNO ELAN3_T_SYSCALL_ERRNO -+ -+/* elansyscall.h */ -+#define ELAN_SYS_FLAG_DMA_BADVP ELAN3_SYS_FLAG_DMA_BADVP -+#define ELAN_SYS_FLAG_THREAD_BADVP ELAN3_SYS_FLAG_THREAD_BADVP -+#define ELAN_SYS_FLAG_DMAFAIL ELAN3_SYS_FLAG_DMAFAIL -+#define ELAN_SYS_FLAG_NETERR ELAN3_SYS_FLAG_NETERR -+ -+/* intrinsics.h */ -+#define elan_copy64w elan3_copy64w -+#define elan_read64dw elan3_read64dw -+#define elan_write64dw elan3_write64dw -+ -+#ifndef ELAN_POLL_EVENT -+#define ELAN_POLL_EVENT ELAN3_POLL_EVENT -+#endif -+#ifndef ELAN_WAIT_EVENT -+#define ELAN_WAIT_EVENT ELAN3_WAIT_EVENT -+#endif -+ -+#endif /* __ELAN3_COMPAT_H */ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+ -Index: linux-2.4.21/include/elan3/dma.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/dma.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/dma.h 2005-06-01 23:12:54.716421320 -0400 -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_DMA_H -+#define __ELAN3_DMA_H -+ -+#ident "$Id: dma.h,v 1.38 2002/08/21 12:43:27 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/dma.h,v $ */ -+ -+#include -+#include -+ -+/* Alignment for a DMA descriptor */ -+#define E3_DMA_ALIGN (32) -+ -+/* The maximum size a DMA can be (i.e. < 2GB) */ -+#define E3_MAX_DMA_SIZE 0x7fffffff -+ -+/* This macro returns TRUE if a fixup for the ELAN_REVB_BUG_2 problem is required -+ * i.e. if the DMA begins in the last 64-bytes of a page and its size causes it to enter the -+ * next page, hence causing the Elan to issue 2 (64-byte) block reads to different pages. -+ * See GNAT hw-elan3/3263 -+ */ -+#define E3_DMA_REVB_BUG_2(SIZE, ADDR, PAGESIZE) \ -+ ( (((int) (ADDR) & (PAGESIZE-64)) == (PAGESIZE-64)) && (-(((int) (ADDR) | ~(PAGESIZE-1))) < (SIZE)) ) -+ -+/* There is a point where a dma runs quicker from main memory than -+ * when running from sdram and having to copy all the data down -+ * first. -+ */ -+#define E3_DMA_SDRAM_CUTOFF 128 -+ -+typedef union _e3_DmaType -+{ -+ E3_uint32 type; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 dataType:2; /* Bits 0 to 1 */ -+ E3_uint32 direction:3; /* Bit 4 to 2 */ -+ E3_uint32 opCode:4; /* Bits 5 to 8 */ -+ E3_uint32 failCount:6; /* Bits 9 to 14 */ -+ E3_uint32 isRemote:1; /* Bit 15 */ -+ E3_uint32 Context:13; /* Bits 16 to 28 */ -+ E3_uint32 :3; /* Bits 29 to 31 */ -+#else -+ E3_uint32 :3; /* Bits 29 to 31 */ -+ E3_uint32 Context:13; /* Bits 16 to 28 */ -+ E3_uint32 isRemote:1; /* Bit 15 */ -+ E3_uint32 failCount:6; /* Bits 9 to 14 */ -+ E3_uint32 opCode:4; /* Bits 5 to 8 */ -+ E3_uint32 direction:3; /* Bit 4 to 2 */ -+ E3_uint32 dataType:2; /* Bits 0 to 1 */ -+#endif -+ } s; -+} E3_DmaType; -+ -+#define E3_DMA_CONTEXT_MASK (ALL_CONTEXT_BITS << 16) -+ -+#define E3_DMA_CONTEXT(type) (((type) >> 16) & ALL_CONTEXT_BITS) -+#define E3_DMA_ISREMOTE(type) (((type) >> 15) & 1) -+#define E3_DMA_FAILCOUNT(type) (((type) >> 9) & 0x3F) -+#define E3_DMA_OPCODE(type) (((type) >> 5) & 0xF) -+#define E3_DMA_DIRECTION(type) (((type) >> 2) & 0x7) -+#define EP_DMA_DATATYPE(type) (((type) >> 0) & 0x3) -+ -+#define E3_DMA_TYPE(dataType, direction, opCode, failCount) \ -+ (((dataType) & 0x3) | (((direction) & 7) << 2) | (((opCode) & 0xF) << 5) | (((failCount) & 0x3F) << 9)) -+ -+ -+typedef union _e3_CookieVProc -+{ -+ E3_uint32 cookie_vproc; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 vproc:16; /* Bit 15 to 0 */ -+ E3_uint32 cookie:16; /* Bits 31 to 16 */ -+#else -+ E3_uint32 cookie:16; /* Bits 31 to 16 */ -+ E3_uint32 vproc:16; /* Bit 15 to 0 */ -+#endif -+ } s; -+} E3_CookieVProc; -+ -+#define E3_DMA_COOKIE_PROC(Cookie, VProc) (((VProc) & 0xffff) | (((Cookie) << 16))) -+ -+#define DMA_COOKIE_MASK (0xffff0000) -+#define DMA_PROCESS_MASK (0x0000ffff) -+ -+/* We use the bottom bit of the cookie to -+ * distinguish main/thread generated cookies -+ */ -+#define DMA_COOKIE_THREAD (0x01 << 16) -+ -+/* We use the next bit of the cookie to -+ * distinguish locally/remotely generated cookies -+ */ -+#define DMA_COOKIE_REMOTE (0x02 << 16) -+ -+/* Assign and increment cookie (NB: we have reserved the bottom two bits) -+ */ -+#define DMA_COOKIE(COOKIE, VPROC) ((((COOKIE) += (0x4 << 16)) & DMA_COOKIE_MASK) | VPROC) -+#define DMA_REMOTE_COOKIE(COOKIE, VPROC) ((((COOKIE) += (0x4 << 16)) & DMA_COOKIE_MASK) | DMA_COOKIE_REMOTE | VPROC) -+ -+#define DMA_COOKIE_REFRESH(COOKIEVP, COOKIE) \ -+do { \ -+ COOKIEVP &= ~DMA_COOKIE_MASK; /* Clear cookie */ \ -+ COOKIEVP |= DMA_COOKIE(COOKIE,0); /* Assign new cookie */ \ -+} while (0) -+ -+typedef struct e3_dma -+{ -+ E3_DmaType dma_u; -+ E3_uint32 dma_size; -+ E3_Addr dma_source; -+ E3_Addr dma_dest; -+ E3_Addr dma_destEvent; -+ E3_CookieVProc dma_destCookieProc; -+ E3_Addr dma_srcEvent; -+ E3_CookieVProc dma_srcCookieProc; -+} E3_DMA; -+ -+ -+/* -+ * Word-swapped version of DMA descriptor. -+ * This is used by the UltraSPARC code to format the descriptor -+ * in main memory before block-copying it down to Elan SDRAM. -+ * In the process it does a dword (64-bit) conversion and so swaps -+ * the word order on a double-word pair basis -+ */ -+typedef struct e3_dma_swapped -+{ -+ E3_uint32 dma_size; -+ E3_DmaType dma_u; -+ E3_Addr dma_dest; -+ E3_Addr dma_source; -+ E3_CookieVProc dma_destCookieProc; -+ E3_Addr dma_destEvent; -+ E3_CookieVProc dma_srcCookieProc; -+ E3_Addr dma_srcEvent; -+} E3_DMA_SWAPPED; -+ -+/* Define a Main memory structure for DMA desc based on Endianess of machine */ -+#if defined(__LITTLE_ENDIAN__) -+#define E3_DMA_MAIN E3_DMA -+#else -+#define E3_DMA_MAIN E3_DMA_SWAPPED; -+#endif -+ -+#define dma_type dma_u.type -+#define dma_failCount dma_u.s.failCount -+#define dma_isRemote dma_u.s.isRemote -+#define dma_opCode dma_u.s.opCode -+#define dma_direction dma_u.s.direction -+#define dma_dataType dma_u.s.dataType -+#define dma_queueContext dma_u.s.Context -+ -+#define dma_destCookieVProc dma_destCookieProc.cookie_vproc -+#define dma_destVProc dma_destCookieProc.s.vproc -+#define dma_destCookie dma_destCookieProc.s.cookie -+#define dma_srcCookieVProc dma_srcCookieProc.cookie_vproc -+#define dma_srcVProc dma_srcCookieProc.s.vproc -+#define dma_srcCookie dma_srcCookieProc.s.cookie -+ -+/* -+ * Values for dma_opCode -+ */ -+#define DMA_NORMAL 0 -+#define DMA_QUEUED 1 -+#define DMA_NORMAL_BROADCAST 2 -+#define DMA_QUEUED_BROADCAST 3 -+#define DMA_NORMAL_UNSAFE 4 -+#define DMA_QUEUED_UNSAFE 5 -+#define DMA_NORMAL_BROADCAST_UNSAFE 6 -+#define DMA_QUEUED_BROADCAST_UNSAFE 7 -+ -+/* -+ * Values for dma_direction -+ */ -+#define DMA_WRITE 0 -+#define DMA_READ_REQUEUE 1 -+#define DMA_READ 3 -+#define DMA_READ_BROADCAST 7 -+ -+/* -+ * Values for dma_dataType -+ */ -+#define DMA_BYTE 0 -+#define DMA_HALFWORD 1 -+#define DMA_WORD 2 -+#define DMA_DOUBLE 3 -+ -+/* OUT OF DATE ? -+ #define DMA_OPCODE_SHIFT 3 -+ #define DMA_FAILCOUNT_SHIFT 9 -+*/ -+#define DMA_TYPE_ISREMOTE (1 << 15) -+#define DMA_TYPE_READ (3 << 2) -+#define DMA_TYPE_READ_REQUEUE (1 << 2) -+#define DMA_TYPE_DIRECTION_MASK (3 << 2) -+ -+#endif /* __ELAN3_DMA_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/e3types.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/e3types.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/e3types.h 2005-06-01 23:12:54.716421320 -0400 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_E3TYPES_H -+#define __ELAN3_E3TYPES_H -+ -+#ident "$Id: e3types.h,v 1.18 2002/08/09 11:23:33 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/e3types.h,v $ */ -+ -+#include -+/* -+ * "flip" values for correctly indexing into -+ * block data which was copied from the Elan -+ * using 64 bit accesses. -+ */ -+#if defined(__LITTLE_ENDIAN__) -+# define ByteEndianFlip 0 -+# define ShortEndianFlip 0 -+# define WordEndianFlip 0 -+#else -+# define ByteEndianFlip 7 -+# define ShortEndianFlip 3 -+# define WordEndianFlip 1 -+#endif -+ -+ -+#ifndef _ASM -+ -+typedef signed int E3_int; -+typedef unsigned int E3_uint; -+ -+typedef signed char E3_int8; -+typedef unsigned char E3_uint8; -+ -+typedef signed short E3_int16; -+typedef unsigned short E3_uint16; -+ -+typedef signed int E3_int32; -+typedef unsigned int E3_uint32; -+ -+#ifdef __ELAN3__ -+typedef signed long long E3_int64; -+typedef unsigned long long E3_uint64; -+#ifdef _MAIN_LP64 -+/* NOTE: If the Main is 64-bit we declare the Elan thread's -+ * E3_uintptr to be 64-bits too -+ */ -+typedef unsigned long long E3_uintptr; -+#else -+typedef unsigned long E3_uintptr; -+#endif -+ -+#else -+ -+#ifdef _LP64 -+typedef signed long E3_int64; -+typedef unsigned long E3_uint64; -+typedef unsigned long E3_uintptr; -+#else /* _ILP32 */ -+typedef signed long long E3_int64; -+typedef unsigned long long E3_uint64; -+typedef unsigned long E3_uintptr; -+#endif -+ -+#endif /* __ELAN3__ */ -+ -+/* 32-bit Elan3 address */ -+typedef E3_uint32 E3_Addr; -+ -+#endif /* _ASM */ -+ -+#endif /* __ELAN3_E3TYPES_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elan3mmu.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elan3mmu.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elan3mmu.h 2005-06-01 23:12:54.717421168 -0400 -@@ -0,0 +1,346 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_ELAN3MMU_H -+#define __ELAN3_ELAN3MMU_H -+ -+#ident "$Id: elan3mmu.h,v 1.40.2.1 2004/12/14 10:19:48 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elan3mmu.h,v $*/ -+ -+ -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+typedef struct elan3mmu_global_stats -+{ -+ int version; -+ int pteload; -+ int pteunload; -+ int ptereload; -+ -+ int streamable_alloc; -+ int streamable_free; -+ int streamable_alloc_failed; -+ -+ int num_ptbl_level[4]; /* number of level N ptbls */ -+ -+ int create_ptbl_failed; /* count of ptbl creation failure */ -+ -+ int lX_alloc_l3; /* count of l3 ptbls used as lX */ -+ int lX_freed_l3; /* count of lX ptbls freed as l3 */ -+ -+ int l2_alloc_l3; /* count of l3 ptbls used as l2 */ -+ int l2_freed_l3; /* count of l2 ptbls freed as l3 */ -+ -+ int stolen_ptbls; /* count of l3 ptbls stolen */ -+} ELAN3MMU_GLOBAL_STATS; -+ -+#define ELAN3MMU_STATS_VERSION 1 -+ -+#define ELAN3MMU_STAT(what) (elan3mmu_global_stats.what++) -+#define ELAN3MMU_SET_STAT(what,count) (elan3mmu_global_stats.what = count) -+ -+#ifdef __KERNEL__ -+ -+#define ELAN3_PT_SHIFT (ELAN3_L2_SHIFT + 2) -+ -+typedef struct elan3_ptbl -+{ -+ struct elan3_ptbl *ptbl_parent; /* Parent page table, or next on freelist */ -+ struct elan3mmu *ptbl_elan3mmu; /* elan3mmu we're allocated for */ -+ E3_Addr ptbl_base; /* Virtual address we're mapping */ -+ u_char ptbl_index; /* Index in ptbl group */ -+ u_char ptbl_valid; /* Number of valid entries */ -+ u_char ptbl_flags; /* Flags, defined below. */ -+ u_char ptbl_spare; -+} ELAN3_PTBL; -+ -+#define ptbl_next ptbl_parent /* Parent pointer is next pointer when on free list */ -+ -+#define PTBL_LEVEL_X 0x00 -+#define PTBL_LEVEL_1 0x01 -+#define PTBL_LEVEL_2 0x02 -+#define PTBL_LEVEL_3 0x03 -+#define PTBL_LEVEL_MASK 0x03 -+#define PTBL_LOCKED 0x04 /* Page table is locked, protects all fields */ -+#define PTBL_KEEP 0x08 /* This ptbl is not to be stolen */ -+#define PTBL_ALLOCED 0x10 /* This ptbl has been allocated, and is not free */ -+#define PTBL_GROUPED 0x20 /* This ptbl is a member of a group of ptbls */ -+#define PTBL_KERNEL 0x80 /* This ptbl is allocated for the kernel */ -+ -+#define PTBL_LEVEL(flags) ((flags) & PTBL_LEVEL_MASK) -+#define PTBL_IS_LOCKED(flags) (((flags) & (PTBL_LOCKED|PTBL_ALLOCED)) == (PTBL_LOCKED|PTBL_ALLOCED)) -+ -+#if ELAN3_PAGE_SHIFT == 13 -+# define PTBL_GROUP_SIZE 8192 /* page table groups are 8k bytes */ -+# define PTBLS_PER_GROUP_L1 8 /* Number of level 1 tables in a group */ -+# define PTBLS_PER_GROUP_L2 32 /* ... level 2 */ -+# define PTBLS_PER_GROUP_L3 32 /* ... level 3 */ -+# define PTBLS_PER_GROUP_LX 32 /* ... level X */ -+# define PTBLS_PER_GROUP_MAX 32 /* max of l1,l2,l3,lX */ -+#else -+# define PTBL_GROUP_SIZE 4096 /* page table groups are 4k bytes */ -+# define PTBLS_PER_GROUP_L1 4 /* Number of level 1 tables in a group */ -+# define PTBLS_PER_GROUP_L2 16 /* ... level 2 */ -+# define PTBLS_PER_GROUP_L3 8 /* ... level 3 */ -+# define PTBLS_PER_GROUP_LX 16 /* ... level X */ -+# define PTBLS_PER_GROUP_MAX 16 /* max of l1,l2,l3,lX */ -+#endif -+ -+#define HMES_PER_GROUP (PTBLS_PER_GROUP_L3*ELAN3_L3_ENTRIES) -+ -+#if ELAN3_PAGE_SHIFT == 13 -+# define PTBLS_PER_PTBL_L1 4 /* 256 PTPs */ -+# define PTBLS_PER_PTBL_L2 1 /* 64 PTPs */ -+# define PTBLS_PER_PTBL_L3 1 /* 32 PTEs */ -+#else -+# define PTBLS_PER_PTBL_L1 4 /* 256 PTPs */ -+# define PTBLS_PER_PTBL_L2 1 /* 64 PTPs */ -+# define PTBLS_PER_PTBL_L3 2 /* 64 PTEs */ -+#endif -+ -+#define ELAN3_LX_ENTRIES (32) -+#define PTBLS_PER_PTBL_LX (1) -+ -+#define L1_VA_PER_PTBL (ELAN3_L1_SIZE*(ELAN3_L1_ENTRIES/PTBLS_PER_PTBL_L1)) /* 4 ptbl for L1 */ -+#define L2_VA_PER_PTBL (ELAN3_L2_SIZE*(ELAN3_L2_ENTRIES/PTBLS_PER_PTBL_L2)) /* 1 ptbl for L2 */ -+#define L3_VA_PER_PTBL (ELAN3_L3_SIZE*(ELAN3_L3_ENTRIES/PTBLS_PER_PTBL_L3)) /* 1 ptbl for L3 */ -+ -+typedef struct elan3_ptbl_gr -+{ -+ struct elan3_ptbl_gr *pg_next; /* Next in list. */ -+ int pg_level; /* Level PG allocated for */ -+ sdramaddr_t pg_addr; /* sdram offset of ptes/ptps */ -+ ELAN3_PTBL pg_ptbls[PTBLS_PER_GROUP_MAX]; /* The actual page tables */ -+} ELAN3_PTBL_GR; -+ -+ -+/* -+ * The elan3mmu structure is the mmu dependant hardware address translation -+ * structure linked to the address space structure to show the translatioms -+ * provided by the elan for an address sapce. -+ * -+ * We also have a doubly linked list of 'regions' which allow the -+ * elan3mmu code to determine the access permissions for the elan -+ * dependant on the virtual address that the translation is being -+ * loaded at. -+ */ -+ -+typedef struct elan3mmu_rgn -+{ -+ struct elan3mmu_rgn *rgn_mnext; /* Doubly linked list of regions */ -+ struct elan3mmu_rgn *rgn_mprev; /* sorted on main address */ -+ caddr_t rgn_mbase; /* main address of base of region */ -+ -+ struct elan3mmu_rgn *rgn_enext; /* Doubly linked list of regions */ -+ struct elan3mmu_rgn *rgn_eprev; /* sorted on elan address */ -+ E3_Addr rgn_ebase; /* elan address of base of region */ -+ -+ u_int rgn_len; /* length of region */ -+ u_int rgn_perm; /* elan access permission */ -+} ELAN3MMU_RGN; -+ -+typedef struct elan3mmu -+{ -+ spinlock_t elan3mmu_lock; /* spinlock lock for regions */ -+ ELAN3MMU_RGN *elan3mmu_mrgns; /* Doubly linked list of memory regions */ -+ ELAN3MMU_RGN *elan3mmu_mtail; /* Last memory region on list */ -+ ELAN3MMU_RGN *elan3mmu_mrgnlast; /* Last region 'hit' */ -+ -+ ELAN3MMU_RGN *elan3mmu_ergns; /* Doubly linked list of memory regions */ -+ ELAN3MMU_RGN *elan3mmu_etail; /* Last memory region on list */ -+ ELAN3MMU_RGN *elan3mmu_ergnlast; /* Last region 'hit' */ -+ -+ struct elan3_dev *elan3mmu_dev; /* Elan device we're using. */ -+ struct elan3_ctxt *elan3mmu_ctxt; /* Elan ctxt we're associated with */ -+ -+ sdramaddr_t elan3mmu_ctp; /* Context table entry for our context */ -+ ELAN3_PTBL *elan3mmu_l1ptbl; /* Level 1 Page table (first of 4) */ -+ -+ spinlock_t elan3mmu_lXptbl_lock; /* spinlock for level X table list */ -+ ELAN3_PTBL *elan3mmu_lXptbl; /* Level X Page table list */ -+ -+#ifdef LINUX -+ struct mm_struct *elan3mmu_coproc_mm; /* Linux mm we're mapping */ -+#endif -+} ELAN3MMU; -+ -+_NOTE(LOCK_ORDER(elan3mmu::elan3mmu_lock elan3_dev::IntrLock)) -+ -+_NOTE(MUTEX_PROTECTS_DATA(elan3mmu::elan3mmu_lock, -+ elan3mmu::elan3mmu_mrgns elan3mmu::elan3mmu_mtail -+ elan3mmu::elan3mmu_ergns elan3mmu::elan3mmu_etail)) -+/* protected by dev->IntrLock for read by device driver */ -+_NOTE(DATA_READABLE_WITHOUT_LOCK(elan3mmu::elan3mmu_mrgns elan3mmu::elan3mmu_mtail -+ elan3mmu::elan3mmu_ergns elan3mmu::elan3mmu_etail)) -+ -+_NOTE(SCHEME_PROTECTS_DATA("only set to valid region", -+ elan3mmu::elan3mmu_ergnlast elan3mmu::elan3mmu_mrgnlast)) -+ -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::IntrLock, -+ elan3mmu::elan3mmu_l1ptbl -+ elan3mmu::elan3mmu_ctp -+ elan3mmu::elan3mmu_dev)) -+ -+_NOTE(DATA_READABLE_WITHOUT_LOCK(elan3mmu::elan3mmu_l1ptbl -+ elan3mmu::elan3mmu_ctp -+ elan3mmu::elan3mmu_dev)) -+ -+/* -+ * Macros for accessing ptes/ptbls/ptbl_grs -+ */ -+ -+#define OFFSETOF(object,member) /* calculate offset of structure member */ \ -+ ((size_t) (&(((object *)0)->member))) -+#define PTBL_TO_GR(ptbl) /* convert ptbl to ptbl group */ \ -+ ((ELAN3_PTBL_GR *) ((caddr_t) ((ptbl) - (ptbl)->ptbl_index) - OFFSETOF(ELAN3_PTBL_GR,pg_ptbls[0]))) -+#define PTBL_TO_PTADDR(ptbl) /* convert ptbl to a ptp pointing at it */ \ -+ (PTBL_TO_GR(ptbl)->pg_addr + ((ptbl)->ptbl_index<pg_hmes + ((pte) - (ELAN3_PTE *) PTBL_TO_GR(ptbl)->pg_vaddr)) -+#define HME_TO_PTE(ptebl,hme) /* convert hme to corresponding pte */ \ -+ ((ELAN3_PTE *) PTBL_TO_GR(ptbl)->pg_vaddr + ((hme) - (PTBL_TO_GR(ptbl)->pg_hmes))) -+ -+ -+/* Flags for lock_ptbl */ -+#define LK_PTBL_NOWAIT 0x1 -+#define LK_PTBL_FAILOK 0x2 -+ -+/* Return values for lock_ptbl */ -+#define LK_PTBL_OK 0x0 -+#define LK_PTBL_MISMATCH 0x1 -+#define LK_PTBL_FAILED 0x2 -+ -+/* Flags for elan3mmu_ptesync */ -+#define NO_MLIST_LOCK 0 -+#define MLIST_LOCKED 1 -+ -+/* Flags for elan3mmu_pteload */ -+#define PTE_LOAD 0x00 -+#define PTE_LOAD_LOCK 0x01 /* translation should be locked */ -+#define PTE_LOAD_NOSYNC 0x02 /* ref/mod bits should not be sync'ed to page */ -+#define PTE_NO_SLEEP 0x04 /* true if we cant sleep */ -+#define PTE_NO_STEAL 0x08 /* true if we don't want to steal ptbls */ -+ -+#define PTE_LOAD_ENDIAN_MASK 0x10 /* mask for endian-ness */ -+#define PTE_LOAD_LITTLE_ENDIAN 0x00 /* translation is to little-endian memory */ -+#define PTE_LOAD_BIG_ENDIAN 0x10 /* translation is to big-endian memory */ -+ -+ -+/* Flags for elan3mmu_unload */ -+#define PTE_UNLOAD 0x00 -+#define PTE_UNLOAD_UNLOCK 0x01 -+#define PTE_UNLOAD_NOFLUSH 0x02 -+#define PTE_UNLOAD_NOSYNC 0x04 -+ -+extern int elan3mmu_debug; -+#ifdef DEBUG_PRINTF -+# define HAT_PRINTF0(n,msg) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg) : (void) 0) -+# define HAT_PRINTF1(n,msg,a) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg,a) : (void) 0) -+# define HAT_PRINTF2(n,msg,a,b) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg,a,b) : (void) 0) -+# define HAT_PRINTF3(n,msg,a,b,c) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg,a,b,c) : (void) 0) -+# define HAT_PRINTF4(n,msg,a,b,c,d) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg,a,b,c,d) : (void) 0) -+# define HAT_PRINTF5(n,msg,a,b,c,d,e) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg,a,b,c,d,e) : (void) 0) -+# define HAT_PRINTF6(n,msg,a,b,c,d,e,f) ((elan3mmu_debug & n) ? (void) elan3_debugf (NULL, DBG_HAT, msg,a,b,c,d,e,f) : (void) 0) -+# ifdef LINUX -+# define HAT_PRINTF(n,args...) ((elan3mmu_debug & n) ? (void) elan3_debugf(NULL, DBG_HAT, ##args) : (void) 0) -+# endif -+#else -+# define HAT_PRINTF0(n,msg) -+# define HAT_PRINTF1(n,msg,a) -+# define HAT_PRINTF2(n,msg,a,b) -+# define HAT_PRINTF3(n,msg,a,b,c) -+# define HAT_PRINTF4(n,msg,a,b,c,d) -+# define HAT_PRINTF5(n,msg,a,b,c,d,e) -+# define HAT_PRINTF6(n,msg,a,b,c,d,e,f) -+# ifdef LINUX -+# define HAT_PRINTF(n,args...) -+# endif -+#endif -+ -+/* elan3mmu_generic.c */ -+extern ELAN3MMU_GLOBAL_STATS elan3mmu_global_stats; -+ -+extern void elan3mmu_init (void); -+extern void elan3mmu_fini (void); -+ -+extern ELAN3MMU *elan3mmu_alloc (struct elan3_ctxt *ctxt); -+extern void elan3mmu_free (ELAN3MMU *elan3mmu); -+ -+extern void elan3mmu_set_context_filter (ELAN3_DEV *dev, int ctx, int disabled, E3_uint32 Pend, E3_uint32 *Maskp); -+extern int elan3mmu_attach (ELAN3_DEV *dev, int ctx, ELAN3MMU *elan3mmu, sdramaddr_t routeTable, E3_uint32 routeMask); -+extern void elan3mmu_detach (ELAN3_DEV *dev, int ctx); -+ -+extern ELAN3MMU_RGN *elan3mmu_findrgn_elan (ELAN3MMU *elan3mmu, E3_Addr addr, int tail); -+extern int elan3mmu_addrgn_elan (ELAN3MMU *elan3mmu, ELAN3MMU_RGN *nrgn); -+extern ELAN3MMU_RGN *elan3mmu_removergn_elan (ELAN3MMU *elan3mmu, E3_Addr addr); -+extern ELAN3MMU_RGN *elan3mmu_rgnat_elan (ELAN3MMU *elan3mmu, E3_Addr addr); -+extern ELAN3MMU_RGN *elan3mmu_findrgn_main (ELAN3MMU *elan3mmu, caddr_t addr, int tail); -+extern int elan3mmu_addrgn_main (ELAN3MMU *elan3mmu, ELAN3MMU_RGN *nrgn); -+extern ELAN3MMU_RGN *elan3mmu_removergn_main (ELAN3MMU *elan3mmu, caddr_t addr); -+extern ELAN3MMU_RGN *elan3mmu_rgnat_main (ELAN3MMU *elan3mmu, caddr_t addr); -+ -+extern int elan3mmu_setperm (ELAN3MMU *elan3mmu, caddr_t maddr, E3_Addr eaddr, u_int len, u_int perm); -+extern void elan3mmu_clrperm (ELAN3MMU *elan3mmu, E3_Addr addr, u_int len); -+extern int elan3mmu_checkperm (ELAN3MMU *elan3mmu, E3_Addr addr, u_int len, u_int access); -+extern caddr_t elan3mmu_mainaddr (ELAN3MMU *elan3mmu, E3_Addr addr); -+extern E3_Addr elan3mmu_elanaddr (ELAN3MMU *elan3mmu, caddr_t addr); -+ -+extern void elan3mmu_expand (ELAN3MMU *elan3mmu, E3_Addr addr, int len, int level, int attr); -+extern void elan3mmu_reserve (ELAN3MMU *elan3mmu, E3_Addr addr, u_int npages, sdramaddr_t *); -+extern void elan3mmu_release (ELAN3MMU *elan3mmu, E3_Addr addr, u_int npages, sdramaddr_t *); -+ -+extern void elan3mmu_pteload (ELAN3MMU *elan3mmu, int level, E3_Addr addr, physaddr_t paddr, int perm, int attr); -+extern void elan3mmu_unload (ELAN3MMU *elan3mmu, E3_Addr addr, u_int len, int flags); -+extern void elan3mmu_sync (ELAN3MMU *elan3mmu, E3_Addr addr, u_int len, u_int clearflag); -+extern void elan3mmu_pteunload (ELAN3_PTBL *ptbl, sdramaddr_t pte, int flags, int got_mlist_lock); -+extern void elan3mmu_ptesync (ELAN3_PTBL *ptbl, sdramaddr_t pte, int flags, int got_mlist_lock); -+extern sdramaddr_t elan3mmu_ptp2pte (ELAN3MMU *elan3mmu, sdramaddr_t ptp, int level); -+extern sdramaddr_t elan3mmu_ptefind (ELAN3MMU *elan3mmu, E3_Addr, int *level, ELAN3_PTBL **pptbl, spinlock_t **plock, unsigned long *flags); -+extern sdramaddr_t elan3mmu_ptealloc (ELAN3MMU *elan3mmu, E3_Addr, int level, ELAN3_PTBL **pptbl, spinlock_t **plock, int attr, unsigned long *flags); -+extern void elan3mmu_l1inval (ELAN3MMU *elan3mmu, ELAN3_PTBL *l1ptbl, int flags); -+extern int elan3mmu_l2inval (ELAN3MMU *elan3mmu, ELAN3_PTBL *l2ptbl, int flags, E3_Addr addr, spinlock_t **pl2lock, unsigned long *lock_flags); -+extern int elan3mmu_l3inval (ELAN3MMU *elan3mmu, ELAN3_PTBL *l3ptbl, int flags, E3_Addr addr, spinlock_t **pl3lock, unsigned long *lock_flags); -+ -+extern void elan3mmu_free_l1ptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags); -+extern void elan3mmu_free_l2ptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags); -+extern void elan3mmu_free_l3ptbl (ELAN3_DEV *dev, ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags); -+ -+extern int elan3mmu_lock_this_ptbl (ELAN3_PTBL *ptbl, int flag, spinlock_t **plock, unsigned long *flags); -+extern int elan3mmu_lock_ptbl (ELAN3_PTBL *ptbl, u_int flag, ELAN3MMU *elan3mmu, E3_Addr va, int level, spinlock_t **plock, unsigned long *flags); -+extern void elan3mmu_unlock_ptbl (ELAN3_PTBL *ptbl, spinlock_t *lock, unsigned long flags); -+ -+/* elan3mmu_osdep.c */ -+extern void elan3mmu_init_osdep (void); -+extern void elan3mmu_fini_osdep (void); -+extern void elan3mmu_alloc_osdep (ELAN3MMU *elan3mmu); -+extern void elan3mmu_free_osdep (ELAN3MMU *elan3mmu); -+extern ELAN3_PTE elan3mmu_phys_to_pte (ELAN3_DEV *dev, physaddr_t paddr, int perm); -+extern ELAN3_PTE elan3mmu_kernel_invalid_pte (ELAN3MMU *elan3mmu); -+ -+#if defined (DIGITAL_UNIX) -+# include -+#elif defined (LINUX) -+# include -+#endif -+ -+#endif /* __KERNEL__ */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __ELAN3_ELAN3MMU_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elan3mmu_linux.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elan3mmu_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elan3mmu_linux.h 2005-06-01 23:12:54.717421168 -0400 -@@ -0,0 +1,39 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_MMU_LINUX_H -+#define __ELAN3_MMU_LINUX_H -+ -+#ident "$Id: elan3mmu_linux.h,v 1.12 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elan3mmu_linux.h,v $*/ -+ -+/* XXX copy of elan3mmu_dunix.h */ -+ -+#define ALLOC_ELAN3MMU(ptr,cansleep) KMEM_ALLOC(ptr, ELAN3MMU *, sizeof (ELAN3MMU), cansleep) -+#define ALLOC_PTBL_GR(ptr,cansleep) KMEM_ALLOC(ptr, ELAN3_PTBL_GR *, sizeof (ELAN3_PTBL_GR), cansleep) -+#define ALLOC_ELAN3MMU_RGN(ptr,cansleep) KMEM_ALLOC(ptr, ELAN3MMU_RGN *, sizeof (ELAN3MMU_RGN), cansleep) -+#define ALLOC_HMENTS(ptr,cansleep) KMEM_ALLOC((ptr,ELAN3_HMENT *, sizeof (ELAN3_HMENT), cansleep) -+ -+#define FREE_ELAN3MMU(ptr) KMEM_FREE(ptr,sizeof (ELAN3MMU)) -+#define FREE_PTBL_GR(ptr) KMEM_FREE(ptr,sizeof (ELAN3_PTBL_GR)) -+#define FREE_ELAN3MMU_RGN(ptr) KMEM_FREE(ptr,sizeof (ELAN3MMU_RGN)) -+#define FREE_HMENTS(ptr) KMEM_FREE(ptr,sizeof (ELAN3_HMENT)) -+ -+extern void elan3mmu_init_osdep(void); -+extern void elan3mmu_fini_osdep(void); -+ -+extern void elan3mmu_pte_range_unload (ELAN3MMU *elan3mmu, struct mm_struct *mm, caddr_t addr, unsigned long len); -+extern void elan3mmu_pte_range_update (ELAN3MMU *elan3mmu, struct mm_struct *mm, caddr_t addr, unsigned long len); -+extern void elan3mmu_pte_ctxt_unload(ELAN3MMU *elan3mmu); -+ -+#endif -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elan3ops.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elan3ops.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elan3ops.h 2005-06-01 23:12:54.718421016 -0400 -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* $Id: elan3ops.h,v 1.3 2003/09/24 13:57:24 david Exp $ */ -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elan3ops.h,v $ */ -+ -+#ifndef _ELAN3_OPS_H -+#define _ELAN3_OPS_H -+ -+int get_position (void *arg, ELAN_POSITION *position); -+int set_position (void *arg, unsigned short nodeId, unsigned short numNodes); -+ -+int elan3mod_create_cap (void *arg, ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap); -+int elan3mod_destroy_cap (void *arg, ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap); -+ -+int elan3mod_create_vp (void *arg, ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map); -+int elan3mod_destroy_vp (void *arg, ELAN_CAP_OWNER owner, ELAN_CAPABILITY *cap, ELAN_CAPABILITY *map); -+ -+int elan3mod_attach_cap (void *arg_ctxt, ELAN_CAPABILITY *cap); -+int elan3mod_detach_cap (void *arg_ctxt); -+ -+extern ELAN_DEV_OPS elan3_dev_ops; -+ -+int stats_get_index_name (void *arg, uint index, caddr_t name); -+int stats_get_block (void *arg, uint entries, ulong *value); -+int stats_clear_block (void *arg); -+ -+int elan3_register_dev_stats (ELAN3_DEV * dev); -+void elan3_deregister_dev_stats (ELAN3_DEV * dev); -+ -+ -+#endif /* __ELAN3_OPS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elanctxt.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elanctxt.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elanctxt.h 2005-06-01 23:12:54.719420864 -0400 -@@ -0,0 +1,856 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_ELANCTXT_H -+#define _ELAN3_ELANCTXT_H -+ -+#ident "$Id: elanctxt.h,v 1.81 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elanctxt.h,v $*/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#define BumpUserStat(ctxt, stat) ((ctxt)->FlagPage->stat++) -+ -+#if defined(__LITTLE_ENDIAN__) -+ -+typedef union _CProcTrapBuf -+{ -+ E3_uint64 Align64; -+ struct -+ { -+ E3_uint32 Areg; -+ E3_uint32 Breg; -+ } r; -+ struct -+ { -+ E3_uint32 Addr; -+ E3_uint32 ContextType; -+ } s; -+} CProcTrapBuf_BE; -+ -+typedef E3_EventInt E3_EventInt_BE; -+typedef E3_IprocTrapHeader E3_IprocTrapHeader_BE; -+typedef E3_IprocTrapData E3_IprocTrapData_BE; -+typedef E3_FaultSave E3_FaultSave_BE; -+ -+typedef union -+{ -+ E3_uint64 Align64; -+ E3_DMA s; -+} E3_DMA_BE; -+ -+typedef E3_ThreadQueue E3_ThreadQueue_BE; -+ -+#else -+ -+/* "Big-Endian" data structures copied by 64 bit loads, these are 32 bit word flipped */ -+/* from the corresponding data structure. */ -+ -+typedef union _CProcTrapBuf -+{ -+ E3_uint64 Align64; -+ struct -+ { -+ E3_uint32 Breg; -+ E3_uint32 Areg; -+ } r; -+ struct -+ { -+ E3_uint32 ContextType; -+ E3_uint32 Addr; -+ } s; -+} CProcTrapBuf_BE; -+ -+typedef union _E3_EventInt_BE -+{ -+ E3_uint64 Align64; -+ struct { -+ E3_uint32 EventContext; /* Bits 16 to 28 */ -+ E3_uint32 IntCookie; -+ } s; -+} E3_EventInt_BE; -+ -+typedef union _E3_IprocTrapHeader_BE -+{ -+ E3_uint64 Align64; -+ -+ struct -+ { -+ E3_uint32 TrAddr; -+ E3_TrTypeCntx TrTypeCntx; -+ union -+ { -+ E3_IProcStatus_Reg u_IProcStatus; -+ E3_uint32 u_TrData1; -+ } ipsotd; -+ E3_uint32 TrData0; -+ } s; -+} E3_IprocTrapHeader_BE; -+ -+typedef E3_IprocTrapData E3_IprocTrapData_BE; -+ -+typedef union _E3_FaultSave_be -+{ -+ E3_uint64 Align64; -+ struct { -+ volatile E3_uint32 FaultContext; -+ E3_FaultStatusReg FSR; -+ volatile E3_uint32 EventAddress; -+ volatile E3_uint32 FaultAddress; -+ } s; -+} E3_FaultSave_BE; -+ -+typedef union _e3_dma_be -+{ -+ E3_uint64 Align64; -+ struct { -+ E3_uint32 dma_size; -+ E3_DmaType dma_u; -+ E3_Addr dma_dest; -+ E3_Addr dma_source; -+ E3_CookieVProc dma_destCookieProc; -+ E3_Addr dma_destEvent; -+ E3_CookieVProc dma_srcCookieProc; -+ E3_Addr dma_srcEvent; -+ } s; -+} E3_DMA_BE; -+ -+typedef union _E3_ThreadQueue_BE -+{ -+ E3_uint64 Align64; -+ struct -+ { -+ /* copied by 64 bit copy from elan to main */ -+ E3_uint32 :3; /* Bits 29 to 31 */ -+ E3_uint32 Context:13; /* Bits 16 to 28 */ -+ E3_uint32 :16; /* Bits 0 to 15 */ -+ E3_Addr Thread; /* Bits 32 to 63 */ -+ } s; -+} E3_ThreadQueue_BE; -+ -+#endif /* defined(LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) */ -+ -+typedef struct neterr_msg -+{ -+ E3_uint32 Rail; /* Rail error received on */ -+ ELAN_CAPABILITY SrcCapability; /* Capability of source of packet */ -+ ELAN_CAPABILITY DstCapability; /* Capability of dest of packet */ -+ -+ E3_uint32 DstProcess; /* Virtual Process of dest of packet */ -+ E3_Addr CookieAddr; /* Cookie Address (or NULL for DMA) */ -+ E3_uint32 CookieVProc; /* Cookie and VP (identifies DMA) */ -+ E3_uint32 NextCookie; /* Next Cookie value (for thread) */ -+ E3_uint32 WaitForEop; /* Wait for EOP transaction */ -+} NETERR_MSG; -+ -+#ifdef __KERNEL__ -+ -+/* -+ * Associated with each input channel can be a network error -+ * resolver structure, which can be queued on the network -+ * error resolver threads to perform RPCs to the other kernels -+ * when a network error occurs with an identify transaction -+ * included -+ */ -+typedef struct neterr_resolver -+{ -+ struct neterr_resolver *Next; -+ -+ spinlock_t Lock; -+ -+ struct elan3_ctxt *Ctxt; -+ ELAN_LOCATION Location; -+ -+ int Completed; -+ int Status; -+ long Timestamp; -+ -+ NETERR_MSG Message; -+} NETERR_RESOLVER; -+ -+ -+typedef struct neterr_fixup -+{ -+ struct neterr_fixup *Next; -+ -+ kcondvar_t Wait; -+ int Completed; -+ int Status; -+ -+ NETERR_MSG Message; -+} NETERR_FIXUP; -+ -+#endif /* __KERNEL__ */ -+ -+/* Each of the following structures must be padded to a whole */ -+/* number of 64 bit words since the kernel uses 64 bit load/stores */ -+/* to transfer the elan register state. */ -+typedef struct command_trap -+{ -+ E3_Status_Reg Status; /* 4 bytes */ -+ E3_uint32 Pad; /* 4 bytes */ -+ E3_FaultSave_BE FaultSave; /* 16 bytes */ -+ CProcTrapBuf_BE TrapBuf; /* 8 bytes */ -+} COMMAND_TRAP; -+ -+typedef struct thread_trap -+{ -+ E3_uint32 Registers[32]; /* 128 bytes */ -+#define REG_GLOBALS 0 -+#define REG_OUTS 8 -+#define REG_LOCALS 16 -+#define REG_INS 24 -+ -+ E3_FaultSave_BE FaultSave; /* 16 bytes */ -+ E3_FaultSave_BE DataFaultSave; /* 16 bytes */ -+ E3_FaultSave_BE InstFaultSave; /* 16 bytes */ -+ E3_FaultSave_BE OpenFaultSave; /* 16 bytes */ -+ -+ E3_Status_Reg Status; /* 4 bytes */ -+ -+ E3_Addr pc; /* 4 bytes */ -+ E3_Addr npc; /* 4 bytes */ -+ E3_Addr StartPC; /* 4 bytes */ -+ E3_Addr sp; /* 4 bytes */ -+ E3_uint32 mi; /* 4 bytes */ -+ E3_TrapBits TrapBits; /* 4 bytes */ -+ E3_DirtyBits DirtyBits; /* 4 bytes */ -+} THREAD_TRAP; -+ -+typedef struct dma_trap -+{ -+ E3_DMA_BE Desc; /* 32 bytes */ -+ E3_FaultSave_BE FaultSave; /* 16 bytes */ -+ E3_FaultSave_BE Data0; /* 16 bytes */ -+ E3_FaultSave_BE Data1; /* 16 bytes */ -+ E3_FaultSave_BE Data2; /* 16 bytes */ -+ E3_FaultSave_BE Data3; /* 16 bytes */ -+ E3_Status_Reg Status; /* 4 bytes */ -+ E3_DmaInfo PacketInfo; /* 4 bytes */ -+} DMA_TRAP; -+ -+typedef struct input_trap -+{ -+ E3_uint32 State; /* 4 bytes */ -+ E3_Status_Reg Status; /* 4 bytes */ -+ E3_FaultSave_BE FaultSave; /* 16 bytes */ -+ -+ u_int NumTransactions; /* 4 bytes */ -+ u_int Overflow; /* 4 bytes */ -+ u_int AckSent; /* 4 bytes */ -+ u_int BadTransaction; /* 4 bytes */ -+ -+ E3_IprocTrapHeader_BE *TrappedTransaction; /* 4 bytes */ -+ E3_IprocTrapData_BE *TrappedDataBuffer; /* 4 bytes */ -+ E3_IprocTrapHeader_BE *WaitForEopTransaction; /* 4 bytes */ -+ E3_IprocTrapData_BE *WaitForEopDataBuffer; /* 4 bytes */ -+ E3_IprocTrapHeader_BE *DmaIdentifyTransaction; /* 4 bytes */ -+ E3_IprocTrapHeader_BE *ThreadIdentifyTransaction; /* 4 bytes */ -+ E3_Addr LockQueuePointer; /* 4 bytes */ -+ E3_Addr UnlockQueuePointer; /* 4 bytes */ -+ -+ E3_IprocTrapHeader_BE Transactions[MAX_TRAPPED_TRANS]; /* n * 8 bytes */ -+ E3_IprocTrapData_BE DataBuffers[MAX_TRAPPED_TRANS]; /* n * 64 bytes */ -+} INPUT_TRAP; -+ -+typedef struct input_fault_save -+{ -+ struct input_fault_save *Next; -+ E3_Addr Addr; -+ E3_uint32 Count; -+} INPUT_FAULT_SAVE; -+ -+#define NUM_INPUT_FAULT_SAVE 32 -+#define MIN_INPUT_FAULT_PAGES 8 -+#define MAX_INPUT_FAULT_PAGES 128 -+ -+typedef E3_uint32 EVENT_COOKIE; -+ -+#ifdef __KERNEL__ -+ -+typedef struct event_cookie_entry -+{ -+ struct event_cookie_entry *ent_next; -+ struct event_cookie_entry *ent_prev; -+ -+ spinlock_t ent_lock; -+ unsigned ent_ref; -+ -+ EVENT_COOKIE ent_cookie; -+ EVENT_COOKIE ent_fired; -+ kcondvar_t ent_wait; -+} EVENT_COOKIE_ENTRY; -+ -+typedef struct event_cookie_table -+{ -+ struct event_cookie_table *tbl_next; -+ struct event_cookie_table *tbl_prev; -+ -+ unsigned long tbl_task; -+ unsigned long tbl_handle; -+ -+ spinlock_t tbl_lock; -+ unsigned tbl_ref; -+ EVENT_COOKIE_ENTRY *tbl_entries; -+} EVENT_COOKIE_TABLE; -+ -+#define NBYTES_PER_SMALL_ROUTE 8 -+#define NBYTES_PER_LARGE_ROUTE 16 -+ -+#define ROUTE_BLOCK_SIZE ELAN3_PAGE_SIZE -+#define NROUTES_PER_BLOCK (ROUTE_BLOCK_SIZE/NBYTES_PER_LARGE_ROUTE) -+ -+typedef struct elan3_routes -+{ -+ struct elan3_routes *Next; /* Can be chained together */ -+ -+ sdramaddr_t Routes; /* sdram offset of route entries */ -+ bitmap_t Bitmap[BT_BITOUL(NROUTES_PER_BLOCK)]; /* Bitmap of which entries are used */ -+} ELAN3_ROUTES; -+ -+ -+typedef struct elan3_route_table -+{ -+ spinlock_t Lock; /* Route lock */ -+ sdramaddr_t Table; /* Kernel address for route table */ -+ u_int Size; /* # entries in route table */ -+ -+ ELAN3_ROUTES *LargeRoutes; /* Large routes */ -+} ELAN3_ROUTE_TABLE; -+ -+typedef struct elan3_vpseg -+{ -+ struct elan3_vpseg *Next; -+ int Process; /* Virtual process */ -+ int Entries; /* and # processes */ -+ int Type; /* Type of cookie */ -+ -+ union -+ { -+ -+ ELAN_CAPABILITY Capability; /* Capability of remote segment */ -+# define SegCapability SegUnion.Capability -+ struct { -+ u_short LowProc; /* Base process number */ -+ u_short HighProc; /* and high process number */ -+# define SegLowProc SegUnion.BROADCAST.LowProc -+# define SegHighProc SegUnion.BROADCAST.HighProc -+ } BROADCAST; -+ } SegUnion; -+} ELAN3_VPSEG; -+ -+#define ELAN3_VPSEG_UNINT 0 /* Unitialised */ -+#define ELAN3_VPSEG_P2P 1 /* Point to Point */ -+#define ELAN3_VPSEG_BROADCAST 2 /* Broadcast */ -+ -+#define NUM_LISTS 7 /* Number of "swap" lists */ -+ -+typedef struct elan3_ctxt -+{ -+ struct elan3_ctxt *Next; /* can be queued on a task */ -+ struct elan3_ctxt *Prev; -+ -+ CtxtHandle Handle; /* user handle */ -+ int RefCnt; /* reference count */ -+ -+ ELAN3MMU *Elan3mmu; /* elan3mmu allocated for Elan translations */ -+ -+ struct elan3_ops *Operations; /* User supplied helper functions */ -+ void *Private; /* Users private pointer */ -+ -+ int Status; /* Status (guarded by dev_mutex) */ -+ int OthersState; /* State of halt queueing for dma/thread */ -+ int LwpCount; /* Number of lwp's running */ -+ -+ ELAN3_DEV *Device; /* Elan device */ -+ -+ ELAN_CAPABILITY Capability; /* Capability I've attached as */ -+ ELAN_POSITION Position; /* Position when I was created */ -+ -+ ELAN3_VPSEG *VpSegs; /* List of virtual process segments */ -+ ELAN3_ROUTE_TABLE *RouteTable; -+ -+ krwlock_t VpLock; /* Reader/writer lock for vp list */ -+ kmutex_t SwapListsLock; /* mutex to lock swap lists */ -+ kmutex_t CmdLock; /* mutex to lock trapped dma command */ -+ kmutex_t CmdPortLock; /* mutex to load/unload commandport xlation */ -+ -+ kcondvar_t Wait; /* Condition variable to sleep on */ -+ kcondvar_t CommandPortWait; /* Condition variable to wait for commandport */ -+ kcondvar_t LwpWait; /* Condition variable to wait for lwps to stop */ -+ kcondvar_t HaltWait; /* Condition variable to wait for halt */ -+ int Halted; /* and flag for halt cv */ -+ -+ caddr_t CommandPageMapping; /* user virtual address for command page mapping */ -+ ioaddr_t CommandPage; /* Elan command port mapping page */ -+ DeviceMappingHandle CommandPageHandle; /* DDI Handle */ -+ ioaddr_t CommandPort; /* Elan command port */ -+ void *CommandPortItem; /* Item we're re-issuing to commandport */ -+ -+ ELAN3_FLAGSTATS *FlagPage; /* Page visible to user process */ -+ -+ COMMAND_TRAP *CommandTraps; /* Command port traps */ -+ ELAN3_SPLIT_QUEUE CommandTrapQ; -+ -+ CProcTrapBuf_BE *Commands; /* Overflowed commands */ -+ ELAN3_QUEUE CommandQ; -+ -+ THREAD_TRAP *ThreadTraps; /* Thread processor traps */ -+ ELAN3_QUEUE ThreadTrapQ; -+ -+ DMA_TRAP *DmaTraps; /* Dma processor tra[ed */ -+ ELAN3_QUEUE DmaTrapQ; -+ -+ INPUT_TRAP Input0Trap; /* Inputter channel 0 trap */ -+ INPUT_TRAP Input1Trap; /* Inputter channel 1 trap */ -+ NETERR_RESOLVER *Input0Resolver; /* Inputter channel 0 network error resolver */ -+ NETERR_RESOLVER *Input1Resolver; /* Inputter channel 1 network error resolver */ -+ -+ INPUT_FAULT_SAVE InputFaults[NUM_INPUT_FAULT_SAVE]; /* stored writeblock addresses */ -+ INPUT_FAULT_SAVE *InputFaultList; /* organized in list for LRU */ -+ spinlock_t InputFaultLock; /* and lock for list */ -+ -+ kmutex_t NetworkErrorLock; -+ NETERR_FIXUP *NetworkErrorFixups; -+ -+ EVENT_COOKIE *EventCookies; /* Event cookies. */ -+ ELAN3_QUEUE EventCookieQ; -+ -+ E3_Addr *SwapThreads; /* Swapped Thread Queue */ -+ ELAN3_QUEUE SwapThreadQ; -+ -+ E3_DMA_BE *SwapDmas; /* Swapped Dmas Queue */ -+ ELAN3_QUEUE SwapDmaQ; -+ -+ int ItemCount[NUM_LISTS]; /* Count of items on each swap list */ -+ int inhibit; /* if set lwp not to reload translations */ -+ -+ int Disabled; -+} ELAN3_CTXT; -+ -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::IntrLock, -+ elan3_ctxt::Status elan3_ctxt::OthersState -+ elan3_ctxt::CommandTrapQ elan3_ctxt::CommandQ elan3_ctxt::ThreadTrapQ elan3_ctxt::DmaTrapQ -+ elan3_ctxt::Input0Trap elan3_ctxt::Input1Trap elan3_ctxt::EventCookieQ elan3_ctxt::SwapThreadQ -+ elan3_ctxt::SwapDmaQ elan3_ctxt::CommandPortItem elan3_ctxt::LwpCount)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_ctxt::SwapListsLock, -+ elan3_ctxt::ItemCount)) -+_NOTE(RWLOCK_PROTECTS_DATA(elan3_ctxt::VpLock, -+ elan3_ctxt::VpSegs elan3_vpseg::Next elan3_vpseg::Process -+ elan3_vpseg::Entries elan3_vpseg::Type)) -+ -+_NOTE(DATA_READABLE_WITHOUT_LOCK(elan3_ctxt::ItemCount elan3_ctxt::Status elan3_ctxt::CommandPortItem)) -+ -+_NOTE(LOCK_ORDER(elan3_ctxt::SwapListsLock elan3_ctxt::CmdLock elan3_dev::IntrLock)) -+_NOTE(LOCK_ORDER(elan3_ctxt::SwapListsLock as::a_lock)) /* implicit by pagefault */ -+ -+#define CTXT_DETACHED (1 << 0) /* Context is detached. */ -+#define CTXT_NO_LWPS (1 << 1) /* No lwp's to handle faults */ -+#define CTXT_EXITING (1 << 2) /* User process is exiting */ -+ -+#define CTXT_SWAPPING_OUT (1 << 3) /* Context is swapping out */ -+#define CTXT_SWAPPED_OUT (1 << 4) /* Context is swapped out */ -+ -+#define CTXT_SWAP_FREE (1 << 5) /* Swap buffer is free */ -+#define CTXT_SWAP_VALID (1 << 6) /* Swap buffer has queue entries in it */ -+ -+#define CTXT_DMA_QUEUE_FULL (1 << 7) /* Dma trap queue is full */ -+#define CTXT_THREAD_QUEUE_FULL (1 << 8) /* Thread trap queue is full */ -+#define CTXT_EVENT_QUEUE_FULL (1 << 9) /* Event interrupt queue is full */ -+#define CTXT_COMMAND_OVERFLOW_ERROR (1 << 10) /* Trap queue overflow */ -+ -+#define CTXT_SWAP_WANTED (1 << 11) /* Some one wanted to swap */ -+#define CTXT_WAITING_SWAPIN (1 << 12) /* Someone waiting on swapin */ -+ -+#define CTXT_WAITING_COMMAND (1 << 13) /* swgelan waiting on command port */ -+#define CTXT_COMMAND_MAPPED_MAIN (1 << 14) /* segelan has mapped command port */ -+ -+#define CTXT_QUEUES_EMPTY (1 << 15) /* dma/thread run queues are empty */ -+#define CTXT_QUEUES_EMPTYING (1 << 16) /* dma/thread run queues are being emptied */ -+ -+#define CTXT_USER_FILTERING (1 << 17) /* user requested context filter */ -+ -+#define CTXT_KERNEL (1 << 18) /* context is a kernel context */ -+#define CTXT_COMMAND_MAPPED_ELAN (1 << 19) /* command port is mapped for elan */ -+#define CTXT_FIXUP_NETERR (1 << 20) /* fixing up a network error */ -+ -+ -+#define CTXT_SWAPPED_REASONS (CTXT_NO_LWPS | \ -+ CTXT_DETACHED | \ -+ CTXT_EXITING | \ -+ CTXT_FIXUP_NETERR) -+ -+#define CTXT_OTHERS_REASONS (CTXT_EVENT_QUEUE_FULL | \ -+ CTXT_DMA_QUEUE_FULL | \ -+ CTXT_THREAD_QUEUE_FULL | \ -+ CTXT_COMMAND_OVERFLOW_ERROR | \ -+ CTXT_SWAPPED_REASONS) -+ -+#define CTXT_INPUTTER_REASONS (CTXT_USER_FILTERING | \ -+ CTXT_OTHERS_REASONS) -+ -+#define CTXT_COMMAND_MAPPED (CTXT_COMMAND_MAPPED_MAIN | \ -+ CTXT_COMMAND_MAPPED_ELAN) -+ -+#define CTXT_IS_KERNEL(ctxt) ((ctxt)->Status & CTXT_KERNEL) -+ -+/* -+ * State values for ctxt_inputterState/ctxt_commandportStats -+ */ -+#define CTXT_STATE_OK 0 -+#define CTXT_STATE_TRAPPED 1 /* Inputter channel 0 trapped */ -+#define CTXT_STATE_RESOLVING 2 /* An LWP is resolving the trap */ -+#define CTXT_STATE_NEEDS_RESTART 3 /* Th trapped packet needs to be executed */ -+#define CTXT_STATE_NETWORK_ERROR 4 /* We're waiting on an RPC for the identify transaction */ -+#define CTXT_STATE_EXECUTING 5 /* An LWP is executing the trapped packet */ -+ -+/* -+ * State values for OthersState. -+ */ -+#define CTXT_OTHERS_RUNNING 0 -+#define CTXT_OTHERS_HALTING 1 -+#define CTXT_OTHERS_SWAPPING 2 -+#define CTXT_OTHERS_HALTING_MORE 3 -+#define CTXT_OTHERS_SWAPPING_MORE 4 -+#define CTXT_OTHERS_SWAPPED 5 -+ -+typedef struct elan3_ops -+{ -+ u_int Version; -+ -+ int (*Exception) (ELAN3_CTXT *ctxt, int type, int proc, void *trap, va_list ap); -+ -+ /* swap item list functions */ -+ int (*GetWordItem) (ELAN3_CTXT *ctxt, int list, void **itemp, E3_uint32 *valuep); -+ int (*GetBlockItem) (ELAN3_CTXT *ctxt, int list, void **itemp, E3_Addr *valuep); -+ void (*PutWordItem) (ELAN3_CTXT *ctxt, int list, E3_Addr value); -+ void (*PutBlockItem) (ELAN3_CTXT *ctxt, int list, E3_uint32 *ptr); -+ void (*PutbackItem) (ELAN3_CTXT *ctxt, int list, void *item); -+ void (*FreeWordItem) (ELAN3_CTXT *ctxt, void *item); -+ void (*FreeBlockItem) (ELAN3_CTXT *ctxt, void *item); -+ int (*CountItems) (ELAN3_CTXT *ctxt, int list); -+ -+ /* event interrupt cookie */ -+ int (*Event) (ELAN3_CTXT *ctxt, E3_uint32 cookie, int flag); -+ -+ /* swapin/swapout functions. */ -+ void (*Swapin) (ELAN3_CTXT *ctxt); -+ void (*Swapout) (ELAN3_CTXT *ctxt); -+ -+ /* Free of private data */ -+ void (*FreePrivate) (ELAN3_CTXT *ctxt); -+ -+ /* Fixup a network error */ -+ int (*FixupNetworkError) (ELAN3_CTXT *ctxt, NETERR_FIXUP *nef); -+ -+ /* Interrupt handler trap interface */ -+ int (*DProcTrap) (ELAN3_CTXT *ctxt, DMA_TRAP *trap); -+ int (*TProcTrap) (ELAN3_CTXT *ctxt, THREAD_TRAP *trap); -+ int (*IProcTrap) (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, int chan); -+ int (*CProcTrap) (ELAN3_CTXT *ctxt, COMMAND_TRAP *trap); -+ int (*CProcReissue) (ELAN3_CTXT *ctxt, CProcTrapBuf_BE *TrapBuf); -+ -+ /* User memory access functions */ -+ int (*StartFaultCheck)(ELAN3_CTXT *ctxt); -+ void (*EndFaultCheck) (ELAN3_CTXT *ctxt); -+ -+ E3_uint8 (*Load8) (ELAN3_CTXT *ctxt, E3_Addr addr); -+ void (*Store8) (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint8 val); -+ E3_uint16 (*Load16) (ELAN3_CTXT *ctxt, E3_Addr addr); -+ void (*Store16) (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint16 val); -+ E3_uint32 (*Load32) (ELAN3_CTXT *ctxt, E3_Addr addr); -+ void (*Store32) (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint32 val); -+ E3_uint64 (*Load64) (ELAN3_CTXT *ctxt, E3_Addr addr); -+ void (*Store64) (ELAN3_CTXT *ctxt, E3_Addr addr, E3_uint64 val); -+ -+} ELAN3_OPS; -+ -+#define ELAN3_OPS_VERSION 0xdeef0001 -+ -+/* -+ * Flags for ops_event. -+ */ -+#define OP_INTR 0 /* Called from interrupt handler */ -+#define OP_LWP 1 /* Called from "lwp" */ -+ -+/* -+ * Return codes for "ops" functions. -+ */ -+#define OP_DEFER 0 /* Defer to next lower interrupt */ -+#define OP_IGNORE 1 /* No event hander, so ignore it */ -+#define OP_HANDLED 2 /* Handled event (resume thread) */ -+#define OP_FAILED 3 /* Failed */ -+ -+#define ELAN3_CALL_OP(ctxt,fn) ((ctxt)->Operations && (ctxt)->Operations->fn) ? (ctxt)->Operations->fn -+ -+#define ELAN3_OP_EXCEPTION(ctxt,type,proc,trap,ap) (ELAN3_CALL_OP(ctxt,Exception) (ctxt,type,proc,trap,ap) : OP_IGNORE) -+#define ELAN3_OP_GET_WORD_ITEM(ctxt,list,itemp,valuep) (ELAN3_CALL_OP(ctxt,GetWordItem) (ctxt,list,itemp,valuep) : 0) -+#define ELAN3_OP_GET_BLOCK_ITEM(ctxt,list,itemp,valuep) (ELAN3_CALL_OP(ctxt,GetBlockItem) (ctxt,list,itemp,valuep) : 0) -+#define ELAN3_OP_PUT_WORD_ITEM(ctxt,list,value) (ELAN3_CALL_OP(ctxt,PutWordItem) (ctxt,list,value) : (void)0) -+#define ELAN3_OP_PUT_BLOCK_ITEM(ctxt,list,ptr) (ELAN3_CALL_OP(ctxt,PutBlockItem) (ctxt,list,ptr) : (void)0) -+#define ELAN3_OP_PUTBACK_ITEM(ctxt,list,item) (ELAN3_CALL_OP(ctxt,PutbackItem) (ctxt,list,item) : (void)0) -+#define ELAN3_OP_FREE_WORD_ITEM(ctxt,item) (ELAN3_CALL_OP(ctxt,FreeWordItem) (ctxt,item) : (void)0) -+#define ELAN3_OP_FREE_BLOCK_ITEM(ctxt,item) (ELAN3_CALL_OP(ctxt,FreeBlockItem)(ctxt,item) : (void)0) -+#define ELAN3_OP_COUNT_ITEMS(ctxt,list) (ELAN3_CALL_OP(ctxt,CountItems)(ctxt,list) : 0) -+#define ELAN3_OP_EVENT(ctxt,cookie,flag) (ELAN3_CALL_OP(ctxt,Event)(ctxt,cookie,flag) : OP_IGNORE) -+#define ELAN3_OP_SWAPIN(ctxt) (ELAN3_CALL_OP(ctxt,Swapin)(ctxt) : (void)0) -+#define ELAN3_OP_SWAPOUT(ctxt) (ELAN3_CALL_OP(ctxt,Swapout)(ctxt) : (void)0) -+#define ELAN3_OP_FREE_PRIVATE(ctxt) (ELAN3_CALL_OP(ctxt,FreePrivate)(ctxt) : (void)0) -+#define ELAN3_OP_FIXUP_NETWORK_ERROR(ctxt, nef) (ELAN3_CALL_OP(ctxt,FixupNetworkError)(ctxt,nef) : OP_FAILED) -+ -+#define ELAN3_OP_DPROC_TRAP(ctxt, trap) (ELAN3_CALL_OP(ctxt,DProcTrap)(ctxt,trap) : OP_DEFER) -+#define ELAN3_OP_TPROC_TRAP(ctxt, trap) (ELAN3_CALL_OP(ctxt,TProcTrap)(ctxt,trap) : OP_DEFER) -+#define ELAN3_OP_IPROC_TRAP(ctxt, trap, chan) (ELAN3_CALL_OP(ctxt,IProcTrap)(ctxt,trap,chan) : OP_DEFER) -+#define ELAN3_OP_CPROC_TRAP(ctxt, trap) (ELAN3_CALL_OP(ctxt,CProcTrap)(ctxt,trap) : OP_DEFER) -+#define ELAN3_OP_CPROC_REISSUE(ctxt,tbuf) (ELAN3_CALL_OP(ctxt,CProcReissue)(ctxt, tbuf) : OP_DEFER) -+ -+#define ELAN3_OP_START_FAULT_CHECK(ctxt) (ELAN3_CALL_OP(ctxt,StartFaultCheck)(ctxt) : 0) -+#define ELAN3_OP_END_FAULT_CHECK(ctxt) (ELAN3_CALL_OP(ctxt,EndFaultCheck)(ctxt) : (void)0) -+#define ELAN3_OP_LOAD8(ctxt,addr) (ELAN3_CALL_OP(ctxt,Load8)(ctxt,addr) : 0) -+#define ELAN3_OP_STORE8(ctxt,addr,val) (ELAN3_CALL_OP(ctxt,Store8)(ctxt,addr,val) : (void)0) -+#define ELAN3_OP_LOAD16(ctxt,addr) (ELAN3_CALL_OP(ctxt,Load16)(ctxt,addr) : 0) -+#define ELAN3_OP_STORE16(ctxt,addr,val) (ELAN3_CALL_OP(ctxt,Store16)(ctxt,addr,val) : (void)0) -+#define ELAN3_OP_LOAD32(ctxt,addr) (ELAN3_CALL_OP(ctxt,Load32)(ctxt,addr) : 0) -+#define ELAN3_OP_STORE32(ctxt,addr,val) (ELAN3_CALL_OP(ctxt,Store32)(ctxt,addr,val) : (void)0) -+#define ELAN3_OP_LOAD64(ctxt,addr) (ELAN3_CALL_OP(ctxt,Load64)(ctxt,addr) : 0) -+#define ELAN3_OP_STORE64(ctxt,addr,val) (ELAN3_CALL_OP(ctxt,Store64)(ctxt,addr,val) : (void)0) -+ -+#endif /* __KERNEL__ */ -+ -+/* "list" arguement to ops functions */ -+#define LIST_DMA_PTR 0 -+#define LIST_DMA_DESC 1 -+#define LIST_THREAD 2 -+#define LIST_COMMAND 3 -+#define LIST_SETEVENT 4 -+#define LIST_FREE_WORD 5 -+#define LIST_FREE_BLOCK 6 -+ -+#define MAX_LISTS 7 -+ -+#if defined(__KERNEL__) && MAX_LISTS != NUM_LISTS -+# error Check NUM_LISTS == MAX_LISTS -+#endif -+ -+/* -+ * Values for the 'type' field to PostException(). -+ */ -+#define EXCEPTION_INVALID_ADDR 1 /* FaultArea, res */ -+#define EXCEPTION_UNIMP_INSTR 2 /* instr */ -+#define EXCEPTION_INVALID_PROCESS 3 /* proc, res */ -+#define EXCEPTION_SIMULATION_FAILED 4 /* */ -+#define EXCEPTION_UNIMPLEMENTED 5 /* */ -+#define EXCEPTION_SWAP_FAULT 6 /* */ -+#define EXCEPTION_SWAP_FAILED 7 /* */ -+#define EXCEPTION_BAD_PACKET 8 /* */ -+#define EXCEPTION_FAULTED 9 /* addr */ -+#define EXCEPTION_QUEUE_OVERFLOW 10 /* FaultArea, TrapType */ -+#define EXCEPTION_COMMAND_OVERFLOW 11 /* count */ -+#define EXCEPTION_DMA_RETRY_FAIL 12 /* */ -+#define EXCEPTION_CHAINED_EVENT 13 /* EventAddr */ -+#define EXCEPTION_THREAD_KILLED 14 /* */ -+#define EXCEPTION_CANNOT_SAVE_THREAD 15 -+#define EXCEPTION_BAD_SYSCALL 16 /* */ -+#define EXCEPTION_DEBUG 17 -+#define EXCEPTION_BAD_EVENT 18 /* */ -+#define EXCEPTION_NETWORK_ERROR 19 /* rvp */ -+#define EXCEPTION_BUS_ERROR 20 -+#define EXCEPTION_COOKIE_ERROR 21 -+#define EXCEPTION_PACKET_TIMEOUT 22 -+#define EXCEPTION_BAD_DMA 23 /* */ -+#define EXCEPTION_ENOMEM 24 -+ -+/* -+ * Values for the 'proc' field to ElanException(). -+ */ -+#define COMMAND_PROC 1 -+#define THREAD_PROC 2 -+#define DMA_PROC 3 -+#define INPUT_PROC 4 -+#define EVENT_PROC 5 -+ -+/* Flags to IssueDmaCommand */ -+#define ISSUE_COMMAND_FOR_CPROC 1 -+#define ISSUE_COMMAND_CANT_WAIT 2 -+ -+/* Return code from IssueDmaCommand.*/ -+#define ISSUE_COMMAND_OK 0 -+#define ISSUE_COMMAND_TRAPPED 1 -+#define ISSUE_COMMAND_RETRY 2 -+#define ISSUE_COMMAND_WAIT 3 -+ -+#ifdef __KERNEL__ -+ -+extern ELAN3_CTXT *elan3_alloc(ELAN3_DEV *dev, int kernel); -+extern void elan3_free (ELAN3_CTXT *ctxt); -+ -+extern int elan3_attach (ELAN3_CTXT *ctxt, ELAN_CAPABILITY *cap); -+extern int elan3_doattach (ELAN3_CTXT *ctxt, ELAN_CAPABILITY *cap); -+extern void elan3_detach (ELAN3_CTXT *ctxt); -+extern void elan3_dodetach (ELAN3_CTXT *ctxt); -+ -+extern int elan3_addvp (ELAN3_CTXT *ctxt, int process, ELAN_CAPABILITY *cap); -+extern int elan3_removevp (ELAN3_CTXT *ctxt, int process); -+extern int elan3_addbcastvp(ELAN3_CTXT *ctxt, int process, int base, int count); -+ -+extern int elan3_process (ELAN3_CTXT *ctxt); -+ -+extern int elan3_load_route (ELAN3_CTXT *ctxt, int process, E3_uint16 *flits); -+extern int elan3_check_route(ELAN3_CTXT *ctxt, int process, E3_uint16 *flits, E3_uint32 *routeError); -+ -+extern int elan3_lwp (ELAN3_CTXT *ctxt); -+ -+extern void elan3_swapin (ELAN3_CTXT *ctxt, int reason); -+extern void elan3_swapout (ELAN3_CTXT *ctxt, int reason); -+extern int elan3_pagefault (ELAN3_CTXT *ctxt, E3_FaultSave_BE *FaultSave, int npages); -+extern void elan3_block_inputter (ELAN3_CTXT *ctxt, int block); -+ -+ -+extern E3_Addr elan3_init_thread (ELAN3_DEV *dev, E3_Addr fn, E3_Addr addr, sdramaddr_t stack, int stackSize, int nargs, ...); -+ -+extern void SetInputterState (ELAN3_CTXT *ctxt, E3_uint32 Pend, E3_uint32 *Maskp); -+extern void SetInputterStateForContext (ELAN3_CTXT *ctxt, E3_uint32 Pend, E3_uint32 *Maskp); -+extern void UnloadCommandPageMapping (ELAN3_CTXT *ctxt); -+extern void StartSwapoutContext (ELAN3_CTXT *ctxt, E3_uint32 Pend, E3_uint32 *Maskp); -+ -+extern int HandleExceptions (ELAN3_CTXT *ctxt, unsigned long *flags); -+extern int RestartContext (ELAN3_CTXT *ctxt, unsigned long *flags); -+extern int CheckCommandQueueFlushed (ELAN3_CTXT *ctxt, E3_uint32 cflags, int how, unsigned long *flags); -+extern int IssueCommand (ELAN3_CTXT *ctxt, unsigned cmdoff, E3_Addr value, int flags); -+extern int IssueDmaCommand (ELAN3_CTXT *ctxt, E3_Addr value, void *item, int flags); -+extern int WaitForDmaCommand (ELAN3_CTXT *ctxt, void *item, int flags); -+extern void FixupEventTrap (ELAN3_CTXT *ctxt, int proc, void *trap, E3_uint32 TrapType, -+ E3_FaultSave_BE *FaultSaveArea, int flags); -+extern int SimulateBlockCopy (ELAN3_CTXT *ctxt, E3_Addr EventAddress); -+extern void ReissueEvent (ELAN3_CTXT *ctxt, E3_Addr addr,int flags); -+extern int SetEventsNeedRestart (ELAN3_CTXT *ctxt); -+extern void RestartSetEvents (ELAN3_CTXT *ctxt); -+extern int RunEventType (ELAN3_CTXT *ctxt, E3_FaultSave_BE *FaultSaveArea, E3_uint32 EventType); -+extern void WakeupLwp (ELAN3_DEV *dev, void *arg); -+extern void QueueEventInterrupt (ELAN3_CTXT *ctxt, E3_uint32 cookie); -+extern int WaitForCommandPort (ELAN3_CTXT *ctxt); -+ -+extern int ElanException (ELAN3_CTXT *ctxt, int type, int proc, void *trap, ...); -+ -+/* context_osdep.c */ -+extern int LoadElanTranslation (ELAN3_CTXT *ctxt, E3_Addr elanAddr, int len, int protFault, int writeable); -+extern void LoadCommandPortTranslation (ELAN3_CTXT *ctxt); -+ -+#if defined(DIGITAL_UNIX) -+/* seg_elan.c */ -+extern caddr_t elan3_segelan3_create (ELAN3_CTXT *ctxt); -+extern void elan3_segelan3_destroy (ELAN3_CTXT *ctxt); -+extern int elan3_segelan3_map (ELAN3_CTXT *ctxt); -+extern void elan3_segelan3_unmap (ELAN3_CTXT *ctxt); -+ -+/* seg_elanmem.c */ -+extern int elan3_segelanmem_create (ELAN3_DEV *dev, unsigned object, unsigned off, vm_offset_t *addrp, int len); -+#endif /* defined(DIGITAL_UNIX) */ -+ -+/* route_table.c */ -+extern ELAN3_ROUTE_TABLE *AllocateRouteTable (ELAN3_DEV *dev, int size); -+extern void FreeRouteTable (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl); -+extern int LoadRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int vp, int ctxnum, int nflits, E3_uint16 *flits); -+extern int GetRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int process, E3_uint16 *flits); -+extern void InvalidateRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int vp); -+extern void ValidateRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int vp); -+extern void ClearRoute (ELAN3_DEV *dev, ELAN3_ROUTE_TABLE *tbl, int vp); -+ -+extern int GenerateRoute (ELAN_POSITION *pos, E3_uint16 *flits, int lowid, int highid, int timeout, int highPri); -+extern int GenerateProbeRoute (E3_uint16 *flits, int nodeid, int level, int *linkup, int *linkdown, int adaptive); -+extern int GenerateCheckRoute (ELAN_POSITION *pos, E3_uint16 *flits, int level, int adaptive); -+ -+/* virtual_process.c */ -+extern ELAN_LOCATION ProcessToLocation (ELAN3_CTXT *ctxt, ELAN3_VPSEG *seg, int process, ELAN_CAPABILITY *cap); -+extern int ResolveVirtualProcess (ELAN3_CTXT *ctxt, int process); -+extern caddr_t CapabilityString (ELAN_CAPABILITY *cap); -+extern void UnloadVirtualProcess (ELAN3_CTXT *ctxt, ELAN_CAPABILITY *cap); -+ -+extern int elan3_get_route (ELAN3_CTXT *ctxt, int process, E3_uint16 *flits); -+extern int elan3_reset_route (ELAN3_CTXT *ctxt, int process); -+ -+/* cproc.c */ -+extern int NextCProcTrap (ELAN3_CTXT *ctxt, COMMAND_TRAP *trap); -+extern void ResolveCProcTrap (ELAN3_CTXT *ctxt); -+extern int RestartCProcTrap (ELAN3_CTXT *ctxt); -+ -+/* iproc.c */ -+extern void InspectIProcTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap); -+extern void ResolveIProcTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, NETERR_RESOLVER **rvp); -+extern int RestartIProcTrap (ELAN3_CTXT *ctxt, INPUT_TRAP *trap); -+extern char *IProcTrapString (E3_IprocTrapHeader_BE *hdrp, E3_IprocTrapData *datap); -+extern void SimulateUnlockQueue (ELAN3_CTXT *ctxt, E3_Addr QueuePointer, int SentAck); -+ -+/* tproc.c */ -+extern int NextTProcTrap (ELAN3_CTXT *ctxt, THREAD_TRAP *trap); -+extern void ResolveTProcTrap (ELAN3_CTXT *ctxt, THREAD_TRAP *trap); -+extern int TProcNeedsRestart (ELAN3_CTXT *ctxt); -+extern void RestartTProcItems (ELAN3_CTXT *ctxt); -+extern E3_Addr SaveThreadToStack (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, int SkipInstruction); -+extern void ReissueStackPointer (ELAN3_CTXT *ctxt, E3_Addr StackPointer); -+ -+/* tprocinsts.c */ -+extern int RollThreadToClose (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, E3_uint32 PAckVal); -+ -+/* tproc_osdep.c */ -+extern int ThreadSyscall (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, int *skip); -+extern int ThreadElancall (ELAN3_CTXT *ctxt, THREAD_TRAP *trap, int *skip); -+ -+/* dproc.c */ -+extern int NextDProcTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap); -+extern void ResolveDProcTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap); -+extern int DProcNeedsRestart (ELAN3_CTXT *ctxt); -+extern void RestartDProcItems (ELAN3_CTXT *ctxt); -+extern void RestartDmaDesc (ELAN3_CTXT *ctxt, E3_DMA_BE *desc); -+extern void RestartDmaTrap (ELAN3_CTXT *ctxt, DMA_TRAP *trap); -+extern void RestartDmaPtr (ELAN3_CTXT *ctxt, E3_Addr ptr); -+ -+/* network_error.c */ -+extern void InitialiseNetworkErrorResolver (void); -+extern void FinaliseNetworkErrorResolver (void); -+extern int QueueNetworkErrorResolver (ELAN3_CTXT *ctxt, INPUT_TRAP *trap, NETERR_RESOLVER **rvpp); -+extern void FreeNetworkErrorResolver (NETERR_RESOLVER *rvp); -+extern void CancelNetworkErrorResolver (NETERR_RESOLVER *rvp); -+extern int ExecuteNetworkErrorFixup (NETERR_MSG *msg); -+extern void CompleteNetworkErrorFixup (ELAN3_CTXT *ctxt, NETERR_FIXUP *nef, int status); -+ -+extern int AddNeterrServerSyscall (int elanId, void *configp, void *addrp, char *namep); -+ -+/* eventcookie.c */ -+extern void cookie_init(void); -+extern void cookie_fini(void); -+extern EVENT_COOKIE_TABLE *cookie_alloc_table (unsigned long task, unsigned long handle); -+extern void cookie_free_table (EVENT_COOKIE_TABLE *tbl); -+extern int cookie_alloc_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie); -+extern int cookie_free_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie); -+extern int cookie_fire_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie); -+extern int cookie_wait_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie); -+extern int cookie_arm_cookie (EVENT_COOKIE_TABLE *tbl, EVENT_COOKIE cookie); -+ -+/* routecheck.c */ -+extern int elan3_route_check (ELAN3_CTXT *ctxt, E3_uint16 *flits, int destNode); -+extern int elan3_route_broadcast_check(ELAN3_CTXT *ctxt, E3_uint16 *flitsA, int lowNode, int highNode); -+ -+ -+#endif /* __KERNEL__ */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _ELAN3_ELANCTXT_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elandebug.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elandebug.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elandebug.h 2005-06-01 23:12:54.720420712 -0400 -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_ELANDEBUG_H -+#define _ELAN3_ELANDEBUG_H -+ -+#ident "$Id: elandebug.h,v 1.38 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elandebug.h,v $ */ -+ -+#if defined(__KERNEL__) -+ -+extern u_int elan3_debug; -+extern u_int elan3_debug_console; -+extern u_int elan3_debug_buffer; -+extern u_int elan3_debug_ignore_dev; -+extern u_int elan3_debug_ignore_kcomm; -+extern u_int elan3_debug_ignore_ctxt; -+extern u_int elan3_debug_display_ctxt; -+ -+#define DBG_CONFIG 0x00000001 /* Module configuration */ -+#define DBG_HAT 0x00000002 -+#define DBG_FN 0x00000004 -+#define DBG_SEG 0x00000008 -+#define DBG_INTR 0x00000010 -+#define DBG_LWP 0x00000020 -+#define DBG_FAULT 0x00000040 -+#define DBG_EVENT 0x00000080 -+#define DBG_CPROC 0x00000100 -+#define DBG_TPROC 0x00000200 -+#define DBG_DPROC 0x00000400 -+#define DBG_IPROC 0x00000800 -+#define DBG_SWAP 0x00001000 -+#define DBG_CMD 0x00002000 -+#define DBG_VP 0x00004000 -+#define DBG_SYSCALL 0x00008000 -+#define DBG_BSCAN 0x00010000 -+#define DBG_LINKERR 0x00020000 -+#define DBG_NETERR 0x00040000 -+#define DBG_NETRPC 0x00080000 -+#define DBG_EVENTCOOKIE 0x00100000 -+#define DBG_SDRAM 0x00200000 -+ -+#define DBG_EP 0x10000000 -+#define DBG_EPCONSOLE 0x20000000 -+ -+#define DBG_EIP 0x40000000 -+#define DBG_EIPFAIL 0x80000000 -+ -+#define DBG_ALL 0xffffffff -+ -+/* values to pass as "ctxt" rather than a "ctxt" pointer */ -+#define DBG_DEVICE ((void *) 0) -+#define DBG_KCOMM ((void *) 1) -+#define DBG_ICS ((void *) 2) -+#define DBG_USER ((void *) 3) -+#define DBG_NTYPES 64 -+ -+#if defined(DEBUG_PRINTF) -+# define DBG(m,fn) ((elan3_debug&(m)) ? (void)(fn) : (void)0) -+# define PRINTF0(ctxt,m,fmt) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt) : (void)0) -+# define PRINTF1(ctxt,m,fmt,a) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt,a) : (void)0) -+# define PRINTF2(ctxt,m,fmt,a,b) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt,a,b) : (void)0) -+# define PRINTF3(ctxt,m,fmt,a,b,c) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt,a,b,c) : (void)0) -+# define PRINTF4(ctxt,m,fmt,a,b,c,d) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt,a,b,c,d) : (void)0) -+# define PRINTF5(ctxt,m,fmt,a,b,c,d,e) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt,a,b,c,d,e) : (void)0) -+# define PRINTF6(ctxt,m,fmt,a,b,c,d,e,f) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m,fmt,a,b,c,d,e,f) : (void)0) -+#ifdef __GNUC__ -+# define PRINTF(ctxt,m,args...) ((elan3_debug&(m)) ? elan3_debugf(ctxt,m, ##args) : (void)0) -+#endif -+ -+#else -+ -+# define DBG(m, fn) do { ; } while (0) -+# define PRINTF0(ctxt,m,fmt) do { ; } while (0) -+# define PRINTF1(ctxt,m,fmt,a) do { ; } while (0) -+# define PRINTF2(ctxt,m,fmt,a,b) do { ; } while (0) -+# define PRINTF3(ctxt,m,fmt,a,b,c) do { ; } while (0) -+# define PRINTF4(ctxt,m,fmt,a,b,c,d) do { ; } while (0) -+# define PRINTF5(ctxt,m,fmt,a,b,c,d,e) do { ; } while (0) -+# define PRINTF6(ctxt,m,fmt,a,b,c,d,e,f) do { ; } while (0) -+#ifdef __GNUC__ -+# define PRINTF(ctxt,m,args...) do { ; } while (0) -+#endif -+ -+#endif /* DEBUG_PRINTF */ -+ -+#ifdef __GNUC__ -+extern void elan3_debugf (void *ctxt, unsigned int mode, char *fmt, ...) -+ __attribute__ ((format (printf,3,4))); -+#else -+extern void elan3_debugf (void *ctxt, unsigned int mode, char *fmt, ...); -+#endif -+ -+ -+#endif /* __KERNEL__ */ -+#endif /* _ELAN3_ELANDEBUG_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elandev.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elandev.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elandev.h 2005-06-01 23:12:54.721420560 -0400 -@@ -0,0 +1,581 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_ELANDEV_H -+#define __ELAN3_ELANDEV_H -+ -+#ident "$Id: elandev.h,v 1.74.2.2 2004/12/10 11:10:19 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elandev.h,v $ */ -+ -+#include -+#include -+#include -+ -+#if defined(DIGITAL_UNIX) -+# include -+#elif defined(LINUX) -+# include -+#elif defined(SOLARIS) -+# include -+#endif -+ -+#ifndef TRUE -+# define TRUE 1 -+#endif -+#ifndef FALSE -+# define FALSE 0 -+#endif -+ -+/* -+ * Elan base address registers defined as follows : -+ */ -+#define ELAN3_BAR_SDRAM 0 -+#define ELAN3_BAR_COMMAND_PORT 1 -+#define ELAN3_BAR_REGISTERS 2 -+#define ELAN3_BAR_EBUS 3 -+ -+/* Macro to generate 'offset' to mmap "mem" device */ -+#define OFF_TO_SPACE(off) ((off) >> 28) -+#define OFF_TO_OFFSET(off) ((off) & 0x0FFFFFFF) -+#define GEN_OFF(space,off) (((space) << 28) | ((off) & 0x0FFFFFFF)) -+ -+#ifdef __KERNEL__ -+ -+/* -+ * Elan EBUS is configured as follows : -+ */ -+#define ELAN3_EBUS_ROM_OFFSET 0x000000 /* rom */ -+#define ELAN3_EBUS_INTPAL_OFFSET 0x180000 /* interrupt pal (write only) */ -+ -+#define ELAN3_EBUS_ROM_SIZE 0x100000 -+ -+/* -+ * Elan SDRAM is arranged as follows : -+ */ -+#define ELAN3_TANDQ_SIZE 0x0020000 /* Trap And Queue Size */ -+#define ELAN3_CONTEXT_SIZE 0x0010000 /* Context Table Size */ -+#define ELAN3_COMMAND_TRAP_SIZE 0x0010000 /* Command Port Trap Size */ -+ -+#ifdef MPSAS -+#define ELAN3_LN2_NUM_CONTEXTS 8 /* Support 256 contexts */ -+#else -+#define ELAN3_LN2_NUM_CONTEXTS 12 /* Support 4096 contexts */ -+#endif -+#define ELAN3_NUM_CONTEXTS (1 << ELAN3_LN2_NUM_CONTEXTS) /* Entries in context table */ -+ -+#define ELAN3_SDRAM_NUM_BANKS 4 /* Elan supports 4 Banks of Sdram */ -+#define ELAN3_SDRAM_BANK_SHIFT 26 /* each of which can be 64 mbytes ? */ -+#define ELAN3_SDRAM_BANK_SIZE (1 << ELAN3_SDRAM_BANK_SHIFT) -+ -+#define ELAN3_MAX_CACHE_SIZE (64 * 1024) /* Maximum cache size */ -+#define ELAN3_CACHE_SIZE (64 * 4 * E3_CACHELINE_SIZE) /* Elan3 has 8K cache */ -+ -+#ifndef offsetof -+#define offsetof(s, m) (size_t)(&(((s *)0)->m)) -+#endif -+ -+/* -+ * circular queue and macros to access members. -+ */ -+typedef struct -+{ -+ u_int q_back; /* Next free space */ -+ u_int q_front; /* First object to remove */ -+ u_int q_size; /* Size of queue */ -+ u_int q_count; /* Current number of entries */ -+ u_int q_slop; /* FULL <=> (count+slop) == size */ -+} ELAN3_QUEUE; -+ -+typedef struct -+{ -+ u_int q_back; /* Next free space */ -+ u_int q_middle; /* Middle pointer */ -+ u_int q_front; /* First object to remove */ -+ u_int q_size; /* Size of queue */ -+ u_int q_count; /* Current number of entries */ -+ u_int q_slop; /* FULL <=> (count+slop) == size */ -+} ELAN3_SPLIT_QUEUE; -+ -+#define ELAN3_QUEUE_INIT(q,num,slop) ((q).q_size = (num), (q).q_slop = (slop)+1, (q).q_front = (q).q_back = 0, (q).q_count = 0) -+#define ELAN3_QUEUE_FULL(q) ((q).q_count == ((q).q_size - (q).q_slop)) -+#define ELAN3_QUEUE_REALLY_FULL(q) ((q).q_count == (q).q_size - 1) -+#define ELAN3_QUEUE_EMPTY(q) ((q).q_count == 0) -+#define ELAN3_QUEUE_FRONT_EMPTY(q) ((q).q_front == (q).q_middle) -+#define ELAN3_QUEUE_BACK_EMPTY(q) ((q).q_middle == (q).q_back) -+#define ELAN3_QUEUE_ADD(q) ((q).q_back = ((q).q_back+1) % (q).q_size, (q).q_count++) -+#define ELAN3_QUEUE_REMOVE(q) ((q).q_front = ((q).q_front+1) % (q).q_size, (q).q_count--) -+#define ELAN3_QUEUE_ADD_FRONT(q) ((q).q_front = ((q).q_front-1) % (q).q_size, (q).q_count++) -+#define ELAN3_QUEUE_CONSUME(q) ((q).q_middle = ((q).q_middle+1) % (q).q_size) -+#define ELAN3_QUEUE_FRONT(q,qArea) (&(qArea)[(q).q_front]) -+#define ELAN3_QUEUE_MIDDLE(q,qArea) (&(qArea)[(q).q_middle]) -+#define ELAN3_QUEUE_BACK(q,qArea) (&(qArea)[(q).q_back]) -+ -+#define SDRAM_MIN_BLOCK_SHIFT 10 -+#define SDRAM_NUM_FREE_LISTS 17 /* allows max 64Mb block */ -+#define SDRAM_MIN_BLOCK_SIZE (1 << SDRAM_MIN_BLOCK_SHIFT) -+#define SDRAM_MAX_BLOCK_SIZE (SDRAM_MIN_BLOCK_SIZE << (SDRAM_NUM_FREE_LISTS-1)) -+#define SDRAM_FREELIST_TRIGGER 32 -+ -+typedef struct elan3_sdram_bank -+{ -+ u_int Size; /* Size of bank of memory */ -+ -+ ioaddr_t Mapping; /* Where mapped in the kernel */ -+ DeviceMappingHandle Handle; /* and mapping handle */ -+ -+ struct elan3_ptbl_gr **PtblGroups; -+ -+ bitmap_t *Bitmaps[SDRAM_NUM_FREE_LISTS]; -+} ELAN3_SDRAM_BANK; -+ -+typedef struct elan3_haltop -+{ -+ struct elan3_haltop *Next; /* Chain to next in list. */ -+ E3_uint32 Mask; /* Interrupt mask to see before calling function */ -+ -+ void (*Function)(void *, void *); /* Function to call */ -+ void *Arguement; /* Arguement to pass to function */ -+} ELAN3_HALTOP; -+ -+#define HALTOP_BATCH 32 -+ -+#endif /* __KERNEL__ */ -+ -+typedef struct elan3_stats -+{ -+ u_long Version; /* version field */ -+ u_long Interrupts; /* count of elan interrupts */ -+ u_long TlbFlushes; /* count of tlb flushes */ -+ u_long InvalidContext; /* count of traps with invalid context */ -+ u_long ComQueueHalfFull; /* count of interrupts due to com queue being half full */ -+ -+ u_long CProcTraps; /* count of cproc traps */ -+ u_long DProcTraps; /* count of dproc traps */ -+ u_long TProcTraps; /* cound of tproc traps */ -+ u_long IProcTraps; /* count of iproc traps */ -+ u_long EventInterrupts; /* count of event interrupts */ -+ -+ u_long PageFaults; /* count of elan page faults */ -+ -+ /* inputter related */ -+ u_long EopBadAcks; /* count of EOP_BAD_ACKs */ -+ u_long EopResets; /* count of EOP_ERROR_RESET */ -+ u_long InputterBadLength; /* count of BadLength */ -+ u_long InputterCRCDiscards; /* count of CRC_STATUS_DISCARD */ -+ u_long InputterCRCErrors; /* count of CRC_STATUS_ERROR */ -+ u_long InputterCRCBad; /* count of CRC_STATUS_BAD */ -+ u_long DmaNetworkErrors; /* count of errors in dma data */ -+ u_long DmaIdentifyNetworkErrors; /* count of errors after dma identify */ -+ u_long ThreadIdentifyNetworkErrors; /* count of errors after thread identify */ -+ -+ /* dma related */ -+ u_long DmaRetries; /* count of dma retries (due to retry fail count) */ -+ u_long DmaOutputTimeouts; /* count of dma output timeouts */ -+ u_long DmaPacketAckErrors; /* count of dma packet ack errors */ -+ -+ /* thread related */ -+ u_long ForcedTProcTraps; /* count of forced tproc traps */ -+ u_long TrapForTooManyInsts; /* count of too many instruction traps */ -+ u_long ThreadOutputTimeouts; /* count of thread output timeouts */ -+ u_long ThreadPacketAckErrors; /* count of thread packet ack errors */ -+ -+ /* link related */ -+ u_long LockError; /* count of RegPtr->Exts.LinkErrorTypes:LS_LockError */ -+ u_long DeskewError; /* count of RegPtr->Exts.LinkErrorTypes:LS_DeskewError */ -+ u_long PhaseError; /* count of RegPtr->Exts.LinkErrorTypes:LS_PhaseError */ -+ u_long DataError; /* count of RegPtr->Exts.LinkErrorTypes:LS_DataError */ -+ u_long FifoOvFlow0; /* count of RegPtr->Exts.LinkErrorTypes:LS_FifoOvFlow0 */ -+ u_long FifoOvFlow1; /* count of RegPtr->Exts.LinkErrorTypes:LS_FifoOvFlow1 */ -+ u_long LinkErrorValue; /* link error value on data error */ -+ -+ /* memory related */ -+ u_long CorrectableErrors; /* count of correctable ecc errors */ -+ u_long UncorrectableErrors; /* count of uncorrectable ecc errors */ -+ u_long MultipleErrors; /* count of multiple ecc errors */ -+ u_long SdramBytesFree; /* count of sdram bytes free */ -+ -+ /* Interrupt related */ -+ u_long LongestInterrupt; /* length of longest interrupt in ticks */ -+ -+ u_long EventPunts; /* count of punts of event interrupts to thread */ -+ u_long EventRescheds; /* count of reschedules of event interrupt thread */ -+} ELAN3_STATS; -+ -+#define ELAN3_STATS_VERSION (ulong)2 -+#define ELAN3_NUM_STATS (sizeof (ELAN3_STATS)/sizeof (u_long)) -+ -+#define ELAN3_STATS_DEV_FMT "elan3_stats_dev_%d" -+ -+#ifdef __KERNEL__ -+ -+#define BumpStat(dev,stat) ((dev)->Stats.stat++) -+ -+typedef struct elan3_level_ptbl_block -+{ -+ spinlock_t PtblLock; /* Page table freelist lock */ -+ int PtblTotal; /* Count of level N page tables allocated */ -+ int PtblFreeCount; /* Count of free level N page tables */ -+ struct elan3_ptbl *PtblFreeList; /* Free level N page tables */ -+ struct elan3_ptbl_gr *PtblGroupList; /* List of Groups of level N page tables */ -+} ELAN3_LEVEL_PTBL_BLOCK; -+ -+typedef struct elan3_dev -+{ -+ ELAN3_DEV_OSDEP Osdep; /* OS specific entries */ -+ int Instance; /* Device number */ -+ ELAN_DEVINFO Devinfo; -+ ELAN_POSITION Position; /* position in switch network (for user code) */ -+ ELAN_DEV_IDX DeviceIdx; /* device index registered with elanmod */ -+ -+ int ThreadsShouldStop; /* flag that kernel threads should stop */ -+ -+ spinlock_t IntrLock; -+ spinlock_t TlbLock; -+ spinlock_t CProcLock; -+ kcondvar_t IntrWait; /* place event interrupt thread sleeps */ -+ unsigned EventInterruptThreadStarted:1; /* event interrupt thread started */ -+ unsigned EventInterruptThreadStopped:1; /* event interrupt thread stopped */ -+ -+ DeviceMappingHandle RegHandle; /* DDI Handle */ -+ ioaddr_t RegPtr; /* Elan Registers */ -+ -+ volatile E3_uint32 InterruptMask; /* copy of RegPtr->InterruptMask */ -+ volatile E3_uint32 Event_Int_Queue_FPtr; /* copy of RegPtr->Event_Int_Queue_FPtr */ -+ volatile E3_uint32 SchCntReg; /* copy of RegPtr->SchCntReg */ -+ volatile E3_uint32 Cache_Control_Reg; /* true value for RegPtr->Cache_Control_Reg */ -+ -+ ELAN3_SDRAM_BANK SdramBanks[ELAN3_SDRAM_NUM_BANKS]; /* Elan sdram banks */ -+ spinlock_t SdramLock; /* Sdram allocator */ -+ sdramaddr_t SdramFreeLists[SDRAM_NUM_FREE_LISTS]; -+ unsigned SdramFreeCounts[SDRAM_NUM_FREE_LISTS]; -+ -+ sdramaddr_t TAndQBase; /* Trap and Queue area */ -+ sdramaddr_t ContextTable; /* Elan Context Table */ -+ u_int ContextTableSize; /* # entries in context table */ -+ -+ struct elan3_ctxt **CtxtTable; /* array of ctxt pointers or nulls */ -+ -+ sdramaddr_t CommandPortTraps[2]; /* Command port trap overflow */ -+ int CurrentCommandPortTrap; /* Which overflow queue we're using */ -+ -+ u_int HaltAllCount; /* Count of reasons to halt context 0 queues */ -+ u_int HaltNonContext0Count; /* Count of reasons to halt non-context 0 queues */ -+ u_int HaltDmaDequeueCount; /* Count of reasons to halt dma from dequeuing */ -+ u_int HaltThreadCount; /* Count of reasons to halt the thread processor */ -+ u_int FlushCommandCount; /* Count of reasons to flush command queues */ -+ u_int DiscardAllCount; /* Count of reasons to discard context 0 */ -+ u_int DiscardNonContext0Count; /* Count of reasons to discard non context 0 */ -+ -+ struct thread_trap *ThreadTrap; /* Thread Processor trap space */ -+ struct dma_trap *DmaTrap; /* DMA Processor trap space */ -+ -+ spinlock_t FreeHaltLock; /* Lock for haltop free list */ -+ ELAN3_HALTOP *FreeHaltOperations; /* Free list of haltops */ -+ u_int NumHaltOperations; /* Number of haltops allocated */ -+ u_int ReservedHaltOperations; /* Number of haltops reserved */ -+ -+ ELAN3_HALTOP *HaltOperations; /* List of operations to call */ -+ ELAN3_HALTOP **HaltOperationsTailpp; /* Pointer to last "next" pointer in list */ -+ E3_uint32 HaltOperationsMask; /* Or of all bits in list of operations */ -+ -+ physaddr_t SdramPhysBase; /* Physical address of SDRAM */ -+ physaddr_t SdramPhysMask; /* and mask of significant bits */ -+ -+ physaddr_t PciPhysBase; /* physical address of local PCI segment */ -+ physaddr_t PciPhysMask; /* and mask of significant bits */ -+ -+ long ErrorTime; /* lbolt at last error (link,ecc etc) */ -+ long ErrorsPerTick; /* count of errors for this tick */ -+ timer_fn_t ErrorTimeoutId; /* id of timeout when errors masked out */ -+ timer_fn_t DmaPollTimeoutId; /* id of timeout to poll for "bad" dmas */ -+ int FilterHaltQueued; -+ -+ /* -+ * HAT layer specific entries. -+ */ -+ ELAN3_LEVEL_PTBL_BLOCK Level[4]; -+ spinlock_t PtblGroupLock; /* Lock for Page Table group lists */ -+ struct elan3_ptbl_gr *Level3PtblGroupHand; /* Hand for ptbl stealing */ -+ -+ /* -+ * Per-Context Information structures. -+ */ -+ struct elan3_info *Infos; /* List of "infos" for this device */ -+ -+ char LinkShutdown; /* link forced into reset by panic/shutdown/dump */ -+ -+ /* -+ * Device statistics. -+ */ -+ ELAN3_STATS Stats; -+ ELAN_STATS_IDX StatsIndex; -+ -+ struct { -+ E3_Regs *RegPtr; -+ char *Sdram[ELAN3_SDRAM_NUM_BANKS]; -+ } PanicState; -+} ELAN3_DEV; -+ -+#define ELAN3_DEV_CTX_TABLE(dev,ctxtn) ( (dev)->CtxtTable[ (ctxtn) & MAX_ROOT_CONTEXT_MASK] ) -+ -+/* macros for accessing dev->RegPtr.Tags/Sets. */ -+#define write_cache_tag(dev,what,val) writeq (val, dev->RegPtr + offsetof (E3_Regs, Tags.what)) -+#define read_cache_tag(dev,what) readq (dev->RegPtr + offsetof (E3_Regs, Tags.what)) -+#define write_cache_set(dev,what,val) writeq (val, dev->RegPtr + offsetof (E3_Regs, Sets.what)) -+#define read_cache_set(dev,what) readq (dev->RegPtr + offsetof (E3_Regs, Sets.what)) -+ -+/* macros for accessing dev->RegPtr.Regs. */ -+#define write_reg64(dev,what,val) writeq (val, dev->RegPtr + offsetof (E3_Regs, Regs.what)) -+#define write_reg32(dev,what,val) writel (val, dev->RegPtr + offsetof (E3_Regs, Regs.what)) -+#define read_reg64(dev,what) readq (dev->RegPtr + offsetof (E3_Regs, Regs.what)) -+#define read_reg32(dev,what) readl (dev->RegPtr + offsetof (E3_Regs, Regs.what)) -+ -+/* macros for accessing dev->RegPtr.uRegs. */ -+#define write_ureg64(dev,what,val) writeq (val, dev->RegPtr + offsetof (E3_Regs, URegs.what)) -+#define write_ureg32(dev,what,val) writel (val, dev->RegPtr + offsetof (E3_Regs, URegs.what)) -+#define read_ureg64(dev,what) readq (dev->RegPtr + offsetof (E3_Regs, URegs.what)) -+#define read_ureg32(dev,what) readl (dev->RegPtr + offsetof (E3_Regs, URegs.what)) -+ -+/* macros for accessing dma descriptor/thread regs */ -+#define copy_dma_regs(dev, desc) \ -+MACRO_BEGIN \ -+ register int i; \ -+ for (i = 0; i < sizeof (E3_DMA)/sizeof(E3_uint64); i++) \ -+ ((E3_uint64 *) desc)[i] = readq (dev->RegPtr + offsetof (E3_Regs, Regs.Dma_Desc) + i*sizeof (E3_uint64)); \ -+MACRO_END -+ -+#define copy_thread_regs(dev, regs) \ -+MACRO_BEGIN \ -+ register int i; \ -+ for (i = 0; i < (32*sizeof (E3_uint32))/sizeof(E3_uint64); i++) \ -+ ((E3_uint64 *) regs)[i] = readq (dev->RegPtr + offsetof (E3_Regs, Regs.Globals[0]) + i*sizeof (E3_uint64)); \ -+MACRO_END -+ -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::IntrLock, -+ _E3_DataBusMap::Exts _E3_DataBusMap::Input_Context_Fil_Flush -+ elan3_dev::CurrentCommandPortTrap elan3_dev::HaltAllCount elan3_dev::HaltDmaDequeueCount -+ elan3_dev::FlushCommandCount elan3_dev::DiscardAllCount elan3_dev::DiscardNonContext0Count -+ elan3_dev::HaltOperations elan3_dev::HaltOperationsMask)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::TlbLock, -+ _E3_DataBusMap::Cache_Control_Reg)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::InfoLock, -+ elan3_dev::Infos elan3_dev::InfoTable)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::FreeHaltLock, -+ elan3_dev::FreeHaltOperations elan3_dev::NumHaltOperations elan3_dev::ReservedHaltOperations)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::PageFreeListLock, -+ elan3_dev::PageFreeList elan3_dev::PageFreeListSize)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::Level1PtblLock, -+ elan3_dev::Level1PtblTotal elan3_dev::Level1PtblFreeCount elan3_dev::Level1PtblFreeList)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::Level2PtblLock, -+ elan3_dev::Level2PtblTotal elan3_dev::Level2PtblFreeCount elan3_dev::Level2PtblFreeList)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::Level3PtblLock, -+ elan3_dev::Level3PtblTotal elan3_dev::Level3PtblFreeCount elan3_dev::Level3PtblFreeList)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::PtblGroupLock, -+ elan3_dev::Level1PtblGroupList elan3_dev::Level2PtblGroupList elan3_dev::Level3PtblGroupList)) -+ -+_NOTE(DATA_READABLE_WITHOUT_LOCK(elan3_dev::InfoTable elan3_dev::Level1PtblFreeList -+ elan3_dev::Level2PtblFreeList elan3_dev::Level3PtblFreeList)) -+ -+_NOTE(LOCK_ORDER(elan3_dev::InfoLock elan3_dev::IntrLock)) -+_NOTE(LOCK_ORDER(as::a_lock elan3_dev::InfoLock)) -+_NOTE(LOCK_ORDER(as::a_lock elan3_dev::IntrLock)) -+ -+#define SET_INT_MASK(dev,Mask) MACRO_BEGIN write_reg32 (dev, Exts.InterruptMask, ((dev)->InterruptMask = (Mask))); mmiob(); MACRO_END -+#define ENABLE_INT_MASK(dev, bits) MACRO_BEGIN write_reg32 (dev, Exts.InterruptMask, ((dev->InterruptMask |= (bits)))); mmiob(); MACRO_END -+#define DISABLE_INT_MASK(dev, bits) MACRO_BEGIN write_reg32 (dev, Exts.InterruptMask, ((dev->InterruptMask &= ~(bits)))); mmiob(); MACRO_END -+ -+#define INIT_SCHED_STATUS(dev, val) \ -+MACRO_BEGIN \ -+ (dev)->SchCntReg = (val); \ -+ write_reg32 (dev, Exts.SchCntReg, (dev)->SchCntReg); \ -+ mmiob(); \ -+MACRO_END -+ -+#define SET_SCHED_STATUS(dev, val) \ -+MACRO_BEGIN \ -+ ASSERT (((val) & HaltStopAndExtTestMask) == (val)); \ -+ (dev)->SchCntReg |= (val); \ -+ write_reg32 (dev, Exts.SchCntReg, (dev)->SchCntReg); \ -+ mmiob (); \ -+MACRO_END -+ -+#define CLEAR_SCHED_STATUS(dev, val) \ -+MACRO_BEGIN \ -+ ASSERT (((val) & HaltStopAndExtTestMask) == (val)); \ -+ (dev)->SchCntReg &= ~(val); \ -+ write_reg32 (dev, Exts.SchCntReg, (dev)->SchCntReg); \ -+ mmiob(); \ -+MACRO_END -+ -+#define MODIFY_SCHED_STATUS(dev, SetBits, ClearBits) \ -+MACRO_BEGIN \ -+ ASSERT ((((SetBits)|(ClearBits)) & HaltStopAndExtTestMask) == ((SetBits)|(ClearBits))); \ -+ (dev)->SchCntReg = (((dev)->SchCntReg | (SetBits)) & ~(ClearBits)); \ -+ write_reg32 (dev, Exts.SchCntReg, (dev)->SchCntReg); \ -+ mmiob(); \ -+MACRO_END -+ -+#define PULSE_SCHED_STATUS(dev, RestartBits) \ -+MACRO_BEGIN \ -+ ASSERT (((RestartBits) & HaltStopAndExtTestMask) == 0); \ -+ write_reg32 (dev, Exts.SchCntReg, (dev)->SchCntReg | (RestartBits)); \ -+ mmiob(); \ -+MACRO_END -+ -+#define SET_SCHED_LINK_VALUE(dev, enabled, val) \ -+MACRO_BEGIN \ -+ (dev)->SchCntReg = (((dev)->SchCntReg & HaltAndStopMask) | ((enabled) ? LinkBoundaryScan : 0) | LinkSetValue(val, 0)); \ -+ write_reg32 (dev, Exts.SchCntReg, (dev)->SchCntReg); \ -+ mmiob(); \ -+MACRO_END -+ -+#ifdef DEBUG_ASSERT -+# define ELAN3_ASSERT(dev, EX) ((void)((EX) || elan3_assfail(dev, #EX, __FILE__, __LINE__))) -+#else -+# define ELAN3_ASSERT(dev, EX) -+#endif -+ -+/* elandev_generic.c */ -+extern int InitialiseElan (ELAN3_DEV *dev, ioaddr_t CmdPort); -+extern void FinaliseElan (ELAN3_DEV *dev); -+extern int InterruptHandler (ELAN3_DEV *dev); -+extern void PollForDmaHungup (void *arg); -+ -+extern int SetLinkBoundaryScan (ELAN3_DEV *dev); -+extern void ClearLinkBoundaryScan (ELAN3_DEV *dev); -+extern int WriteBoundaryScanValue (ELAN3_DEV *dev, int value); -+extern int ReadBoundaryScanValue(ELAN3_DEV *dev, int link); -+ -+extern int ReadVitalProductData (ELAN3_DEV *dev, int *CasLatency); -+ -+extern struct elan3_ptbl_gr *ElanGetPtblGr (ELAN3_DEV *dev, sdramaddr_t offset); -+extern void ElanSetPtblGr (ELAN3_DEV *dev, sdramaddr_t offset, struct elan3_ptbl_gr *ptg); -+ -+extern void ElanFlushTlb (ELAN3_DEV *dev); -+ -+extern void SetSchedStatusRegister (ELAN3_DEV *dev, E3_uint32 Pend, volatile E3_uint32 *Maskp); -+extern void FreeHaltOperation (ELAN3_DEV *dev, ELAN3_HALTOP *op); -+extern int ReserveHaltOperations (ELAN3_DEV *dev, int count, int cansleep); -+extern void ReleaseHaltOperations (ELAN3_DEV *dev, int count); -+extern void ProcessHaltOperations (ELAN3_DEV *dev, E3_uint32 Pend); -+extern void QueueHaltOperation (ELAN3_DEV *dev, E3_uint32 Pend, volatile E3_uint32 *Maskp, -+ E3_uint32 ReqMask, void (*Function)(ELAN3_DEV *, void *), void *Arguement); -+ -+extern int ComputePosition (ELAN_POSITION *pos, unsigned NodeId, unsigned NumNodes, unsigned numDownLinksVal); -+ -+extern caddr_t MiToName (int mi); -+extern void ElanBusError (ELAN3_DEV *dev); -+ -+extern void TriggerLsa (ELAN3_DEV *dev); -+ -+extern ELAN3_DEV *elan3_device (int instance); -+extern int DeviceRegisterSize (ELAN3_DEV *dev, int rnumber, int *sizep); -+extern int MapDeviceRegister (ELAN3_DEV *dev, int rnumber, ioaddr_t *addrp, int offset, -+ int len, DeviceMappingHandle *handlep); -+extern void UnmapDeviceRegister (ELAN3_DEV *dev, DeviceMappingHandle *handlep); -+ -+ -+/* sdram.c */ -+/* sdram accessing functions - define 4 different types for 8,16,32,64 bit accesses */ -+extern unsigned char elan3_sdram_readb (ELAN3_DEV *dev, sdramaddr_t ptr); -+extern unsigned short elan3_sdram_readw (ELAN3_DEV *dev, sdramaddr_t ptr); -+extern unsigned int elan3_sdram_readl (ELAN3_DEV *dev, sdramaddr_t ptr); -+extern unsigned long long elan3_sdram_readq (ELAN3_DEV *dev, sdramaddr_t ptr); -+extern void elan3_sdram_writeb (ELAN3_DEV *dev, sdramaddr_t ptr, unsigned char val); -+extern void elan3_sdram_writew (ELAN3_DEV *dev, sdramaddr_t ptr, unsigned short val); -+extern void elan3_sdram_writel (ELAN3_DEV *dev, sdramaddr_t ptr, unsigned int val); -+extern void elan3_sdram_writeq (ELAN3_DEV *dev, sdramaddr_t ptr, unsigned long long val); -+ -+extern void elan3_sdram_zerob_sdram (ELAN3_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan3_sdram_zerow_sdram (ELAN3_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan3_sdram_zerol_sdram (ELAN3_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan3_sdram_zeroq_sdram (ELAN3_DEV *dev, sdramaddr_t ptr, int nbytes); -+ -+extern void elan3_sdram_copyb_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan3_sdram_copyw_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan3_sdram_copyl_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan3_sdram_copyq_from_sdram (ELAN3_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan3_sdram_copyb_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+extern void elan3_sdram_copyw_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+extern void elan3_sdram_copyl_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+extern void elan3_sdram_copyq_to_sdram (ELAN3_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+ -+extern void elan3_sdram_init (ELAN3_DEV *dev); -+extern void elan3_sdram_fini (ELAN3_DEV *dev); -+extern void elan3_sdram_add (ELAN3_DEV *dev, sdramaddr_t base, sdramaddr_t top); -+extern sdramaddr_t elan3_sdram_alloc (ELAN3_DEV *dev, int nbytes); -+extern void elan3_sdram_free (ELAN3_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern physaddr_t elan3_sdram_to_phys (ELAN3_DEV *dev, sdramaddr_t addr); -+ -+/* cproc.c */ -+extern void HandleCProcTrap (ELAN3_DEV *dev, E3_uint32 Pend, E3_uint32 *Mask); -+ -+/* iproc.c */ -+extern void HandleIProcTrap (ELAN3_DEV *dev, int Channel, E3_uint32 Pend, sdramaddr_t FaultSaveOff, -+ sdramaddr_t TransactionsOff, sdramaddr_t DataOff); -+ -+/* tproc.c */ -+extern int HandleTProcTrap (ELAN3_DEV *dev, E3_uint32 *RestartBits); -+extern void DeliverTProcTrap (ELAN3_DEV *dev, struct thread_trap *threadTrap, E3_uint32 Pend); -+ -+/* dproc.c */ -+extern int HandleDProcTrap (ELAN3_DEV *dev, E3_uint32 *RestartBits); -+extern void DeliverDProcTrap (ELAN3_DEV *dev, struct dma_trap *dmaTrap, E3_uint32 Pend); -+ -+#if defined(LINUX) -+/* procfs_linux.h */ -+extern struct proc_dir_entry *elan3_procfs_root; -+extern struct proc_dir_entry *elan3_config_root; -+ -+extern void elan3_procfs_init(void); -+extern void elan3_procfs_fini(void); -+extern void elan3_procfs_device_init (ELAN3_DEV *dev); -+extern void elan3_procfs_device_fini (ELAN3_DEV *dev); -+#endif /* defined(LINUX) */ -+ -+/* elan3_osdep.c */ -+extern int BackToBackMaster; -+extern int BackToBackSlave; -+ -+#define ELAN_REG_REC_MAX (100) -+#define ELAN_REG_REC(REG) { \ -+elan_reg_rec_file [elan_reg_rec_index] = __FILE__; \ -+elan_reg_rec_line [elan_reg_rec_index] = __LINE__; \ -+elan_reg_rec_reg [elan_reg_rec_index] = REG; \ -+elan_reg_rec_cpu [elan_reg_rec_index] = smp_processor_id(); \ -+elan_reg_rec_lbolt[elan_reg_rec_index] = lbolt; \ -+elan_reg_rec_index = ((elan_reg_rec_index+1) % ELAN_REG_REC_MAX);} -+ -+extern char * elan_reg_rec_file [ELAN_REG_REC_MAX]; -+extern int elan_reg_rec_line [ELAN_REG_REC_MAX]; -+extern long elan_reg_rec_lbolt[ELAN_REG_REC_MAX]; -+extern int elan_reg_rec_cpu [ELAN_REG_REC_MAX]; -+extern E3_uint32 elan_reg_rec_reg [ELAN_REG_REC_MAX]; -+extern int elan_reg_rec_index; -+ -+#endif /* __KERNEL__ */ -+ -+ -+#define ELAN3_PROCFS_ROOT "/proc/qsnet/elan3" -+#define ELAN3_PROCFS_VERSION "/proc/qsnet/elan3/version" -+#define ELAN3_PROCFS_DEBUG "/proc/qsnet/elan3/config/elandebug" -+#define ELAN3_PROCFS_DEBUG_CONSOLE "/proc/qsnet/elan3/config/elandebug_console" -+#define ELAN3_PROCFS_DEBUG_BUFFER "/proc/qsnet/elan3/config/elandebug_buffer" -+#define ELAN3_PROCFS_MMU_DEBUG "/proc/qsnet/elan3/config/elan3mmu_debug" -+#define ELAN3_PROCFS_PUNT_LOOPS "/proc/qsnet/elan3/config/eventint_punt_loops" -+ -+#define ELAN3_PROCFS_DEVICE_STATS_FMT "/proc/qsnet/elan3/device%d/stats" -+#define ELAN3_PROCFS_DEVICE_POSITION_FMT "/proc/qsnet/elan3/device%d/position" -+#define ELAN3_PROCFS_DEVICE_NODESET_FMT "/proc/qsnet/elan3/device%d/nodeset" -+ -+#endif /* __ELAN3_ELANDEV_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elandev_linux.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elandev_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elandev_linux.h 2005-06-01 23:12:54.721420560 -0400 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELANDEV_LINUX_H -+#define __ELANDEV_LINUX_H -+ -+#ident "$Id: elandev_linux.h,v 1.11 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elandev_linux.h,v $*/ -+ -+#ifdef __KERNEL__ -+#include -+#include -+#include -+#endif -+ -+#define ELAN3_MAJOR 60 -+#define ELAN3_NAME "elan3" -+#define ELAN3_MAX_CONTROLLER 16 /* limited to 4 bits */ -+ -+#define ELAN3_MINOR_DEVNUM(m) ((m) & 0x0f) /* card number */ -+#define ELAN3_MINOR_DEVFUN(m) (((m) >> 4) & 0x0f) /* function */ -+#define ELAN3_MINOR_CONTROL 0 /* function values */ -+#define ELAN3_MINOR_MEM 1 -+#define ELAN3_MINOR_USER 2 -+ -+typedef void *DeviceMappingHandle; -+ -+/* task and ctxt handle types */ -+typedef struct mm_struct *TaskHandle; -+typedef int CtxtHandle; -+ -+#define ELAN3_MY_TASK_HANDLE() (current->mm) -+#define KERNEL_TASK_HANDLE() (get_kern_mm()) -+ -+/* -+ * OS-dependent component of ELAN3_DEV struct. -+ */ -+typedef struct elan3_dev_osdep -+{ -+ struct pci_dev *pci; /* PCI config data */ -+ int ControlDeviceOpen; /* flag to indicate control */ -+ /* device open */ -+ struct proc_dir_entry *procdir; -+} ELAN3_DEV_OSDEP; -+ -+#endif /* __ELANDEV_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elanio.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elanio.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elanio.h 2005-06-01 23:12:54.722420408 -0400 -@@ -0,0 +1,226 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_ELAN3IO_H -+#define __ELAN3_ELAN3IO_H -+ -+#ident "$Id: elanio.h,v 1.19 2003/12/08 15:40:26 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elanio.h,v $*/ -+ -+#define ELAN3IO_CONTROL_PATHNAME "/dev/elan3/control%d" -+#define ELAN3IO_MEM_PATHNAME "/dev/elan3/mem%d" -+#define ELAN3IO_USER_PATHNAME "/dev/elan3/user%d" -+#define ELAN3IO_SDRAM_PATHNAME "/dev/elan3/sdram%d" -+#define ELAN3IO_MAX_PATHNAMELEN 32 -+ -+/* ioctls on /dev/elan3/control */ -+#define ELAN3IO_CONTROL_BASE 0 -+ -+#define ELAN3IO_SET_BOUNDARY_SCAN _IO ('e', ELAN3IO_CONTROL_BASE + 0) -+#define ELAN3IO_CLEAR_BOUNDARY_SCAN _IO ('e', ELAN3IO_CONTROL_BASE + 1) -+#define ELAN3IO_READ_LINKVAL _IOWR ('e', ELAN3IO_CONTROL_BASE + 2, E3_uint32) -+#define ELAN3IO_WRITE_LINKVAL _IOWR ('e', ELAN3IO_CONTROL_BASE + 3, E3_uint32) -+ -+typedef struct elanio_set_debug_struct -+{ -+ char what[32]; -+ u_long value; -+} ELAN3IO_SET_DEBUG_STRUCT; -+#define ELAN3IO_SET_DEBUG _IOW ('e', ELAN3IO_CONTROL_BASE + 4, ELAN3IO_SET_DEBUG_STRUCT) -+ -+typedef struct elanio_debug_buffer_struct -+{ -+ caddr_t addr; -+ size_t len; -+} ELAN3IO_DEBUG_BUFFER_STRUCT; -+#define ELAN3IO_DEBUG_BUFFER _IOWR ('e', ELAN3IO_CONTROL_BASE + 5, ELAN3IO_DEBUG_BUFFER_STRUCT) -+ -+typedef struct elanio_neterr_server_struct -+{ -+ u_int elanid; -+ void *addr; -+ char *name; -+} ELAN3IO_NETERR_SERVER_STRUCT; -+#define ELAN3IO_NETERR_SERVER _IOW ('e', ELAN3IO_CONTROL_BASE + 6, ELAN3IO_NETERR_SERVER_STRUCT) -+#define ELAN3IO_NETERR_FIXUP _IOWR ('e', ELAN3IO_CONTROL_BASE + 7, NETERR_MSG) -+ -+typedef struct elanio_set_position_struct -+{ -+ u_int device; -+ unsigned short nodeId; -+ unsigned short numNodes; -+} ELAN3IO_SET_POSITION_STRUCT; -+#define ELAN3IO_SET_POSITION _IOW ('e', ELAN3IO_CONTROL_BASE + 8, ELAN3IO_SET_POSITION_STRUCT) -+ -+#if defined(LINUX) -+ -+/* ioctls on /dev/elan3/sdram */ -+#define ELAN3IO_SDRAM_BASE 20 -+ -+/* ioctls on /dev/elan3/user */ -+#define ELAN3IO_USER_BASE 30 -+ -+#define ELAN3IO_FREE _IO ('e', ELAN3IO_USER_BASE + 0) -+ -+#define ELAN3IO_ATTACH _IOWR('e', ELAN3IO_USER_BASE + 1, ELAN_CAPABILITY) -+#define ELAN3IO_DETACH _IO ('e', ELAN3IO_USER_BASE + 2) -+ -+typedef struct elanio_addvp_struct -+{ -+ u_int process; -+ ELAN_CAPABILITY capability; -+} ELAN3IO_ADDVP_STRUCT; -+#define ELAN3IO_ADDVP _IOWR('e', ELAN3IO_USER_BASE + 3, ELAN3IO_ADDVP_STRUCT) -+#define ELAN3IO_REMOVEVP _IOW ('e', ELAN3IO_USER_BASE + 4, int) -+ -+typedef struct elanio_bcastvp_struct -+{ -+ u_int process; -+ u_int lowvp; -+ u_int highvp; -+} ELAN3IO_BCASTVP_STRUCT; -+#define ELAN3IO_BCASTVP _IOW ('e', ELAN3IO_USER_BASE + 5, ELAN3IO_BCASTVP_STRUCT) -+ -+typedef struct elanio_loadroute_struct -+{ -+ u_int process; -+ E3_uint16 flits[MAX_FLITS]; -+} ELAN3IO_LOAD_ROUTE_STRUCT; -+#define ELAN3IO_LOAD_ROUTE _IOW ('e', ELAN3IO_USER_BASE + 6, ELAN3IO_LOAD_ROUTE_STRUCT) -+ -+#define ELAN3IO_PROCESS _IO ('e', ELAN3IO_USER_BASE + 7) -+ -+typedef struct elanio_setperm_struct -+{ -+ caddr_t maddr; -+ E3_Addr eaddr; -+ size_t len; -+ int perm; -+} ELAN3IO_SETPERM_STRUCT; -+#define ELAN3IO_SETPERM _IOW ('e', ELAN3IO_USER_BASE + 8, ELAN3IO_SETPERM_STRUCT) -+ -+typedef struct elanio_clearperm_struct -+{ -+ E3_Addr eaddr; -+ size_t len; -+} ELAN3IO_CLEARPERM_STRUCT; -+#define ELAN3IO_CLEARPERM _IOW ('e', ELAN3IO_USER_BASE + 9, ELAN3IO_CLEARPERM_STRUCT) -+ -+typedef struct elanio_changeperm_struct -+{ -+ E3_Addr eaddr; -+ size_t len; -+ int perm; -+} ELAN3IO_CHANGEPERM_STRUCT; -+#define ELAN3IO_CHANGEPERM _IOW ('e', ELAN3IO_USER_BASE + 10, ELAN3IO_CHANGEPERM_STRUCT) -+ -+ -+#define ELAN3IO_HELPER_THREAD _IO ('e', ELAN3IO_USER_BASE + 11) -+#define ELAN3IO_WAITCOMMAND _IO ('e', ELAN3IO_USER_BASE + 12) -+#define ELAN3IO_BLOCK_INPUTTER _IOW ('e', ELAN3IO_USER_BASE + 13, int) -+#define ELAN3IO_SET_FLAGS _IOW ('e', ELAN3IO_USER_BASE + 14, int) -+ -+#define ELAN3IO_WAITEVENT _IOW ('e', ELAN3IO_USER_BASE + 15, E3_Event) -+#define ELAN3IO_ALLOC_EVENTCOOKIE _IOW ('e', ELAN3IO_USER_BASE + 16, EVENT_COOKIE) -+#define ELAN3IO_FREE_EVENTCOOKIE _IOW ('e', ELAN3IO_USER_BASE + 17, EVENT_COOKIE) -+#define ELAN3IO_ARM_EVENTCOOKIE _IOW ('e', ELAN3IO_USER_BASE + 18, EVENT_COOKIE) -+#define ELAN3IO_WAIT_EVENTCOOKIE _IOW ('e', ELAN3IO_USER_BASE + 19, EVENT_COOKIE) -+ -+#define ELAN3IO_SWAPSPACE _IOW ('e', ELAN3IO_USER_BASE + 20, SYS_SWAP_SPACE) -+#define ELAN3IO_EXCEPTION_SPACE _IOW ('e', ELAN3IO_USER_BASE + 21, SYS_EXCEPTION_SPACE) -+#define ELAN3IO_GET_EXCEPTION _IOR ('e', ELAN3IO_USER_BASE + 22, SYS_EXCEPTION) -+ -+typedef struct elanio_unload_struct -+{ -+ void *addr; -+ size_t len; -+} ELAN3IO_UNLOAD_STRUCT; -+#define ELAN3IO_UNLOAD _IOW ('e', ELAN3IO_USER_BASE + 23, ELAN3IO_UNLOAD_STRUCT) -+ -+ -+ -+typedef struct elanio_getroute_struct -+{ -+ u_int process; -+ E3_uint16 flits[MAX_FLITS]; -+} ELAN3IO_GET_ROUTE_STRUCT; -+#define ELAN3IO_GET_ROUTE _IOW ('e', ELAN3IO_USER_BASE + 24, ELAN3IO_GET_ROUTE_STRUCT) -+ -+typedef struct elanio_resetroute_struct -+{ -+ u_int process; -+} ELAN3IO_RESET_ROUTE_STRUCT; -+#define ELAN3IO_RESET_ROUTE _IOW ('e', ELAN3IO_USER_BASE + 25, ELAN3IO_RESET_ROUTE_STRUCT) -+ -+typedef struct elanio_checkroute_struct -+{ -+ u_int process; -+ E3_uint32 routeError; -+ E3_uint16 flits[MAX_FLITS]; -+} ELAN3IO_CHECK_ROUTE_STRUCT; -+#define ELAN3IO_CHECK_ROUTE _IOW ('e', ELAN3IO_USER_BASE + 26, ELAN3IO_CHECK_ROUTE_STRUCT) -+ -+typedef struct elanio_vp2nodeId_struct -+{ -+ u_int process; -+ unsigned short nodeId; -+ ELAN_CAPABILITY cap; -+} ELAN3IO_VP2NODEID_STRUCT; -+#define ELAN3IO_VP2NODEID _IOWR('e', ELAN3IO_USER_BASE + 27, ELAN3IO_VP2NODEID_STRUCT) -+ -+#define ELAN3IO_SET_SIGNAL _IOW ('e', ELAN3IO_USER_BASE + 28, int) -+ -+typedef struct elanio_process_2_location_struct -+{ -+ u_int process; -+ ELAN_LOCATION loc; -+} ELAN3IO_PROCESS_2_LOCATION_STRUCT; -+#define ELAN3IO_PROCESS_2_LOCATION _IOW ('e', ELAN3IO_USER_BASE + 29, ELAN3IO_PROCESS_2_LOCATION_STRUCT) -+ -+ -+ -+/* ioctls on all device */ -+#define ELAN3IO_GENERIC_BASE 100 -+typedef struct elanio_get_devinfo_struct -+{ -+ ELAN_DEVINFO *devinfo; -+} ELAN3IO_GET_DEVINFO_STRUCT; -+#define ELAN3IO_GET_DEVINFO _IOR ('e', ELAN3IO_GENERIC_BASE + 0, ELAN_DEVINFO) -+ -+typedef struct elanio_get_position_struct -+{ -+ ELAN_POSITION *position; -+} ELAN3IO_GET_POSITION_STRUCT; -+#define ELAN3IO_GET_POSITION _IOR ('e', ELAN3IO_GENERIC_BASE + 1, ELAN_POSITION) -+ -+typedef struct elanio_stats_struct -+{ -+ int which; -+ void *ptr; -+} ELAN3IO_STATS_STRUCT; -+#define ELAN3IO_STATS _IOR ('e', ELAN3IO_GENERIC_BASE + 2, ELAN3IO_STATS_STRUCT) -+# define ELAN3_SYS_STATS_DEVICE 0 -+# define ELAN3_SYS_STATS_MMU 1 -+ -+/* offsets on /dev/elan3/control */ -+ -+/* offsets on /dev/elan3/mem */ -+ -+/* page numbers on /dev/elan3/user */ -+#define ELAN3IO_OFF_COMMAND_PAGE 0 -+#define ELAN3IO_OFF_FLAG_PAGE 1 -+#define ELAN3IO_OFF_UREG_PAGE 2 -+ -+#endif /* LINUX */ -+ -+#endif /* __ELAN3_ELAN3IO_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elanregs.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elanregs.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elanregs.h 2005-06-01 23:12:54.724420104 -0400 -@@ -0,0 +1,1063 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* -+ * Header file for internal slave mapping of the ELAN3 registers -+ */ -+ -+#ifndef _ELAN3_ELANREGS_H -+#define _ELAN3_ELANREGS_H -+ -+#ident "$Id: elanregs.h,v 1.87 2004/04/22 12:27:21 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elanregs.h,v $*/ -+ -+#include -+#include -+#include -+ -+#define MAX_ROOT_CONTEXT_MASK 0xfff -+#define SYS_CONTEXT_BIT 0x1000 -+#define ALL_CONTEXT_BITS (MAX_ROOT_CONTEXT_MASK | SYS_CONTEXT_BIT) -+#define ROOT_TAB_OFFSET(Cntxt) (((Cntxt) & MAX_ROOT_CONTEXT_MASK) << 4) -+#define CLEAR_SYS_BIT(Cntxt) ((Cntxt) & ~SYS_CONTEXT_BIT) -+ -+#define E3_CACHELINE_SIZE (32) -+#define E3_CACHE_SIZE (8192) -+ -+typedef volatile struct _E3_CacheSets -+{ -+ E3_uint64 Set0[256]; /* 2k bytes per set */ -+ E3_uint64 Set1[256]; /* 2k bytes per set */ -+ E3_uint64 Set2[256]; /* 2k bytes per set */ -+ E3_uint64 Set3[256]; /* 2k bytes per set */ -+} E3_CacheSets; -+ -+typedef union e3_cache_tag -+{ -+ E3_uint64 Value; -+ struct { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 pad2:8; /* Undefined value when read */ -+ E3_uint32 LineError:1; /* A line error has occured */ -+ E3_uint32 Modified:1; /* Cache data is modified */ -+ E3_uint32 FillPending:1; /* Pipelined fill occuring*/ -+ E3_uint32 AddrTag27to11:17; /* Tag address bits 27 to 11 */ -+ E3_uint32 pad1:4; /* Undefined value when read */ -+ E3_uint32 pad0; /* Undefined value when read */ -+#else -+ E3_uint32 pad0; /* Undefined value when read */ -+ E3_uint32 pad1:4; /* Undefined value when read */ -+ E3_uint32 AddrTag27to11:17; /* Tag address bits 27 to 11 */ -+ E3_uint32 FillPending:1; /* Pipelined fill occuring*/ -+ E3_uint32 Modified:1; /* Cache data is modified */ -+ E3_uint32 LineError:1; /* A line error has occured */ -+ E3_uint32 pad2:8; /* Undefined value when read */ -+#endif -+ } s; -+} E3_CacheTag; -+ -+#define E3_NumCacheLines 64 -+#define E3_NumCacheSets 4 -+ -+typedef volatile struct _E3_CacheTags -+{ -+ E3_CacheTag Tags[E3_NumCacheLines][E3_NumCacheSets]; /* 2k bytes per set */ -+} E3_CacheTags; -+ -+typedef union E3_IProcStatus_Reg -+{ -+ E3_uint32 Status; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 TrapType:8; /* iprocs trap ucode address */ -+ E3_uint32 SuspendAddr:8; /* iprocs suspend address */ -+ E3_uint32 EopType:2; /* Type of Eop Received */ -+ E3_uint32 QueueingPacket:1; /* receiving a queueing packet */ -+ E3_uint32 AckSent:1; /* a packet ack has been sent */ -+ E3_uint32 Reject:1; /* a packet nack has been sent */ -+ E3_uint32 CrcStatus:2; /* Crc Status value */ -+ E3_uint32 BadLength:1; /* Eop was received in a bad place */ -+ E3_uint32 Chan1:1; /* This packet received on v chan1 */ -+ E3_uint32 First:1; /* This is the first transaction in the packet */ -+ E3_uint32 Last:1; /* This is the last transaction in the packet */ -+ E3_uint32 Unused:2; -+ E3_uint32 WakeupFunction:3; /* iprocs wakeup function */ -+#else -+ E3_uint32 WakeupFunction:3; /* iprocs wakeup function */ -+ E3_uint32 Unused:2; -+ E3_uint32 Last:1; /* This is the last transaction in the packet */ -+ E3_uint32 First:1; /* This is the first transaction in the packet */ -+ E3_uint32 Chan1:1; /* This packet received on v chan1 */ -+ E3_uint32 BadLength:1; /* Eop was received in a bad place */ -+ E3_uint32 CrcStatus:2; /* Crc Status value */ -+ E3_uint32 Reject:1; /* a packet nack has been sent */ -+ E3_uint32 AckSent:1; /* a packet ack has been sent */ -+ E3_uint32 QueueingPacket:1; /* receiving a queueing packet */ -+ E3_uint32 EopType:2; /* Type of Eop Received */ -+ E3_uint32 SuspendAddr:8; /* iprocs suspend address */ -+ E3_uint32 TrapType:8; /* iprocs trap ucode address */ -+#endif -+ } s; -+} E3_IProcStatus_Reg; -+ -+#define CRC_STATUS_GOOD (0 << 21) -+#define CRC_STATUS_DISCARD (1 << 21) -+#define CRC_STATUS_ERROR (2 << 21) -+#define CRC_STATUS_BAD (3 << 21) -+ -+#define CRC_MASK (3 << 21) -+ -+#define EOP_GOOD (1 << 16) -+#define EOP_BADACK (2 << 16) -+#define EOP_ERROR_RESET (3 << 16) -+ -+#define E3_IPS_LastTrans (1 << 26) -+#define E3_IPS_FirstTrans (1 << 25) -+#define E3_IPS_VChan1 (1 << 24) -+#define E3_IPS_BadLength (1 << 23) -+#define E3_IPS_CrcMask (3 << 21) -+#define E3_IPS_Rejected (1 << 20) -+#define E3_IPS_AckSent (1 << 19) -+#define E3_IPS_QueueingPacket (1 << 18) -+#define E3_IPS_EopType (3 << 16) -+ -+typedef union E3_Status_Reg -+{ -+ E3_uint32 Status; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 TrapType:8; /* procs trap ucode address */ -+ E3_uint32 SuspendAddr:8; /* procs suspend address */ -+ E3_uint32 Context:13; /* procs current context */ -+ E3_uint32 WakeupFunction:3; /* procs wakeup function */ -+#else -+ E3_uint32 WakeupFunction:3; /* procs wakeup function */ -+ E3_uint32 Context:13; /* procs current context */ -+ E3_uint32 SuspendAddr:8; /* procs suspend address */ -+ E3_uint32 TrapType:8; /* procs trap ucode address */ -+#endif -+ } s; -+} E3_Status_Reg; -+ -+/* values for WakeupFunction */ -+#define SleepOneTick 0 -+#define WakeupToSendTransOrEop 1 -+#define SleepOneTickThenRunnable 2 -+#define WakeupNever 4 -+/* extra dma wakeup functions */ -+#define WakupeToSendTransOrEop 1 -+#define WakeupForPacketAck 3 -+#define WakeupToSendTrans 5 -+/* extra thread wakup function */ -+#define WakeupStopped 3 -+/* extra cproc wakup function */ -+#define WakeupSetEvent 3 -+ -+#define GET_STATUS_CONTEXT(Ptr) ((Ptr.Status >> 16) & 0x1fff) -+#define GET_STATUS_SUSPEND_ADDR(Ptr) ((Ptr.Status >> 8) & 0xff) -+#define GET_STATUS_TRAPTYPE(Ptr) ((E3_uint32)(Ptr.Status & 0xff)) -+ -+/* -+ * Interrupt register bits -+ */ -+#define INT_PciMemErr (1<<15) /* Pci memory access error */ -+#define INT_SDRamInt (1<<14) /* SDRam ECC interrupt */ -+#define INT_EventInterrupt (1<<13) /* Event Interrupt */ -+#define INT_LinkError (1<<12) /* Link Error */ -+#define INT_ComQueue (1<<11) /* a comm queue half full */ -+#define INT_TProcHalted (1<<10) /* Tproc Halted */ -+#define INT_DProcHalted (1<<9) /* Dmas Halted */ -+#define INT_DiscardingNonSysCntx (1<<8) /* Inputters Discarding Non-SysCntx */ -+#define INT_DiscardingSysCntx (1<<7) /* Inputters Discarding SysCntx */ -+#define INT_TProc (1<<6) /* tproc interrupt */ -+#define INT_CProc (1<<5) /* cproc interrupt */ -+#define INT_DProc (1<<4) /* dproc interrupt */ -+#define INT_IProcCh1NonSysCntx (1<<3) /* iproc non-SysCntx interrupt */ -+#define INT_IProcCh1SysCntx (1<<2) /* iproc SysCntx interrupt */ -+#define INT_IProcCh0NonSysCntx (1<<1) /* iproc non-SysCntx interrupt */ -+#define INT_IProcCh0SysCntx (1<<0) /* iproc SysCntx interrupt */ -+ -+#define INT_Inputters (INT_IProcCh0SysCntx | INT_IProcCh0NonSysCntx | INT_IProcCh1SysCntx | INT_IProcCh1NonSysCntx) -+#define INT_Discarding (INT_DiscardingSysCntx | INT_DiscardingNonSysCntx) -+#define INT_Halted (INT_DProcHalted | INT_TProcHalted) -+#define INT_ErrorInterrupts (INT_PciMemErr | INT_SDRamInt | INT_LinkError) -+ -+/* -+ * Link state bits. -+ */ -+#define LS_LinkNotReady (1 << 0) /* Link is in reset or recovering from an error */ -+#define LS_Locked (1 << 1) /* Linkinput PLL is locked */ -+#define LS_LockError (1 << 2) /* Linkinput PLL was unable to lock onto the input clock. */ -+#define LS_DeskewError (1 << 3) /* Linkinput was unable to Deskew all the inputs. (Broken wire?) */ -+#define LS_PhaseError (1 << 4) /* Linkinput Phase alignment error. */ -+#define LS_DataError (1 << 5) /* Received value was neither good data or a token. */ -+#define LS_FifoOvFlow0 (1 << 6) /* Channel 0 input fifo overflowed. */ -+#define LS_FifoOvFlow1 (1 << 7) /* Channel 1 input fifo overflowed. */ -+ -+/* -+ * Link State Constant defines, used for writing to LinkSetValue -+ */ -+ -+#define LRS_DataDel0 0x0 -+#define LRS_DataDel1 0x1 -+#define LRS_DataDel2 0x2 -+#define LRS_DataDel3 0x3 -+#define LRS_DataDel4 0x4 -+#define LRS_DataDel5 0x5 -+#define LRS_DataDel6 0x6 -+#define LRS_DataDel7 0x7 -+#define LRS_DataDel8 0x8 -+#define LRS_PllDelValue 0x9 -+#define LRS_ClockEven 0xA -+#define LRS_ClockOdd 0xB -+#define LRS_ErrorLSW 0xC -+#define LRS_ErrorMSW 0xD -+#define LRS_FinCoarseDeskew 0xE -+#define LRS_LinkInValue 0xF -+#define LRS_NumLinkDels 0x10 -+ -+#define LRS_Pllfast 0x40 -+ -+union Sched_Status -+{ -+ E3_uint32 Status; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 StopNonSysCntxs:1; -+ E3_uint32 FlushCommandQueues:1; -+ E3_uint32 HaltDmas:1; -+ E3_uint32 HaltDmaDequeue:1; -+ E3_uint32 HaltThread:1; -+ E3_uint32 CProcStop:1; -+ E3_uint32 DiscardSysCntxIn:1; -+ E3_uint32 DiscardNonSysCntxIn:1; -+ E3_uint32 RestartCh0SysCntx:1; -+ E3_uint32 RestartCh0NonSysCntx:1; -+ E3_uint32 RestartCh1SysCntx:1; -+ E3_uint32 RestartCh1NonSysCntx:1; -+ E3_uint32 RestartDProc:1; -+ E3_uint32 RestartTProc:1; -+ E3_uint32 RestartCProc:1; -+ E3_uint32 ClearLinkErrorInt:1; -+ E3_uint32 :3; -+ E3_uint32 LinkSetValue:10; -+ E3_uint32 FixLinkDelays:1; -+ E3_uint32 LinkBoundaryScan:1; -+#else -+ E3_uint32 LinkBoundaryScan:1; -+ E3_uint32 FixLinkDelays:1; -+ E3_uint32 LinkSetValue:10; -+ E3_uint32 :3; -+ E3_uint32 ClearLinkErrorInt:1; -+ E3_uint32 RestartCProc:1; -+ E3_uint32 RestartTProc:1; -+ E3_uint32 RestartDProc:1; -+ E3_uint32 RestartCh1NonSysCntx:1; -+ E3_uint32 RestartCh1SysCntx:1; -+ E3_uint32 RestartCh0NonSysCntx:1; -+ E3_uint32 RestartCh0SysCntx:1; -+ E3_uint32 DiscardNonSysCntxIn:1; -+ E3_uint32 DiscardSysCntxIn:1; -+ E3_uint32 CProcStop:1; -+ E3_uint32 HaltThread:1; -+ E3_uint32 HaltDmaDequeue:1; -+ E3_uint32 HaltDmas:1; -+ E3_uint32 FlushCommandQueues:1; -+ E3_uint32 StopNonSysCntxs:1; -+#endif -+ } s; -+}; -+ -+#define LinkBoundaryScan ((E3_uint32) 1<<31) /* Clears the link error interrupt */ -+#define FixLinkDelays ((E3_uint32) 1<<30) /* Clears the link error interrupt */ -+#define LinkSetValue(Val, OldVal) ((E3_uint32) (((Val) & 0x3ff) << 20) | ((OldVal) & ((~0x3ff) << 20))) -+ -+#define ClearLinkErrorInt ((E3_uint32) 1<<16) /* Clears the link error interrupt */ -+#define RestartCProc ((E3_uint32) 1<<15) /* Clears command proc interrupt */ -+#define RestartTProc ((E3_uint32) 1<<14) /* Clears thread interrupt */ -+#define RestartDProc ((E3_uint32) 1<<13) /* Clears dma0 interrupt */ -+#define RestartCh1NonSysCntx ((E3_uint32) 1<<12) /* Clears interrupt */ -+#define RestartCh1SysCntx ((E3_uint32) 1<<11) /* Clears interrupt */ -+#define RestartCh0NonSysCntx ((E3_uint32) 1<<10) /* Clears interrupt */ -+#define RestartCh0SysCntx ((E3_uint32) 1<<9) /* Clears interrupt */ -+#define CProcStopped ((E3_uint32) 1<<9) /* Read value only */ -+ -+#define TraceSetEvents ((E3_uint32) 1<<8) -+#define DiscardNonSysCntxIn ((E3_uint32) 1<<7) -+#define DiscardSysCntxIn ((E3_uint32) 1<<6) -+#define CProcStop ((E3_uint32) 1<<5) /* Will empty all the command port queues. */ -+#define HaltThread ((E3_uint32) 1<<4) /* Will stop the thread proc and clear the tproc command queue */ -+#define HaltDmaDequeue ((E3_uint32) 1<<3) /* Will stop the dmaers starting new dma's. */ -+#define HaltDmas ((E3_uint32) 1<<2) /* Will stop the dmaers and clear the dma command queues */ -+#define FlushCommandQueues ((E3_uint32) 1<<1) /* Causes the command ports to be flushed. */ -+#define StopNonSysCntxs ((E3_uint32) 1<<0) /* Prevents a non-SysCntx from starting. */ -+ -+/* Initial value of schedule status register */ -+#define LinkResetToken 0x00F -+ -+#define Sched_Initial_Value (LinkBoundaryScan | (LinkResetToken << 20) | \ -+ DiscardSysCntxIn | DiscardNonSysCntxIn | HaltThread | HaltDmas) -+ -+#define StopDmaQueues (HaltDmaDequeue | HaltDmas | \ -+ DiscardNonSysCntxIn | DiscardSysCntxIn) -+#define CheckDmaQueueStopped (INT_DiscardingNonSysCntx | INT_DiscardingSysCntx | INT_DProcHalted) -+ -+#define HaltStopAndExtTestMask 0xfff001ff -+#define HaltAndStopMask 0x000001ff -+ -+ -+#define DmaComQueueNotEmpty (1<<0) -+#define ThreadComQueueNotEmpty (1<<1) -+#define EventComQueueNotEmpty (1<<2) -+#define DmaComQueueHalfFull (1<<3) -+#define ThreadComQueueHalfFull (1<<4) -+#define EventComQueueHalfFull (1<<5) -+#define DmaComQueueError (1<<6) -+#define ThreadComQueueError (1<<7) -+#define EventComQueueError (1<<8) -+ -+#define ComQueueNotEmpty (DmaComQueueNotEmpty | ThreadComQueueNotEmpty | EventComQueueNotEmpty) -+#define ComQueueError (DmaComQueueError | ThreadComQueueError | EventComQueueError) -+ -+typedef union _E3_DmaInfo -+{ -+ E3_uint32 Value; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 DmaOutputOpen:1; /* The packet is currently open */ -+ E3_uint32 :7; -+ E3_uint32 TimeSliceCount:2; /* Time left to timeslice */ -+ E3_uint32 UseRemotePriv:1; /* Set for remote read dmas */ -+ E3_uint32 DmaLastPacket:1; /* Set for the last packet of a dma */ -+ E3_uint32 PacketAckValue:2; /* Packet ack type. Valid if AckBufferValid set. */ -+ E3_uint32 PacketTimeout:1; /* Packet timeout. Sent an EopError. Valid if AckBufferValid set. */ -+ E3_uint32 AckBufferValid:1; /* Packet ack is valid. */ -+ E3_uint32 :16; /* read as Zero */ -+#else -+ E3_uint32 :16; /* read as Zero */ -+ E3_uint32 AckBufferValid:1; /* Packet ack is valid. */ -+ E3_uint32 PacketTimeout:1; /* Packet timeout. Sent an EopError. Valid if AckBufferValid set. */ -+ E3_uint32 PacketAckValue:2; /* Packet ack type. Valid if AckBufferValid set. */ -+ E3_uint32 DmaLastPacket:1; /* Set for the last packet of a dma */ -+ E3_uint32 UseRemotePriv:1; /* Set for remote read dmas */ -+ E3_uint32 TimeSliceCount:2; /* Time left to timeslice */ -+ E3_uint32 :7; -+ E3_uint32 DmaOutputOpen:1; /* The packet is currently open */ -+#endif -+ } s; -+} E3_DmaInfo; -+ -+typedef volatile struct _E3_DmaRds -+{ -+ E3_uint32 DMA_Source4to0AndTwoReads; -+ E3_uint32 pad13; -+ E3_uint32 DMA_BytesToRead; -+ E3_uint32 pad14; -+ E3_uint32 DMA_MinusPacketSize; -+ E3_uint32 pad15; -+ E3_uint32 DMA_MaxMinusPacketSize; -+ E3_uint32 pad16; -+ E3_uint32 DMA_DmaOutputOpen; -+ E3_uint32 pad16a; -+ E3_DmaInfo DMA_PacketInfo; -+ E3_uint32 pad17[7]; -+ E3_uint32 IProcTrapBase; -+ E3_uint32 pad18; -+ E3_uint32 IProcBlockTrapBase; -+ E3_uint32 pad19[11]; -+} E3_DmaRds; -+ -+typedef volatile struct _E3_DmaWrs -+{ -+ E3_uint64 pad0; -+ E3_uint64 LdAlignment; -+ E3_uint64 ResetAckNLdBytesToWr; -+ E3_uint64 SetAckNLdBytesToWr; -+ E3_uint64 LdBytesToRd; -+ E3_uint64 LdDmaType; -+ E3_uint64 SendRoutes; -+ E3_uint64 SendEop; -+ E3_uint64 pad1[8]; -+} E3_DmaWrs; -+ -+typedef volatile struct _E3_Exts -+{ -+ E3_uint32 CurrContext; /* 0x12a00 */ -+ E3_uint32 pad0; -+ E3_Status_Reg DProcStatus; /* 0x12a08 */ -+ E3_uint32 pad1; -+ E3_Status_Reg CProcStatus; /* 0x12a10 */ -+ E3_uint32 pad2; -+ E3_Status_Reg TProcStatus; /* 0x12a18 */ -+ E3_uint32 pad3; -+ E3_IProcStatus_Reg IProcStatus; /* 0x12a20 */ -+ E3_uint32 pad4[3]; -+ -+ E3_uint32 IProcTypeContext; /* 0x12a30 */ -+ E3_uint32 pad5; -+ E3_uint32 IProcTransAddr; /* 0x12a38 */ -+ E3_uint32 pad6; -+ E3_uint32 IProcCurrTransData0; /* 0x12a40 */ -+ E3_uint32 pad7; -+ E3_uint32 IProcCurrTransData1; /* 0x12a48 */ -+ E3_uint32 pad8; -+ -+ E3_uint32 SchCntReg; /* 0x12a50 */ -+ E3_uint32 pad9; -+ E3_uint32 InterruptReg; /* 0x12a58 */ -+ E3_uint32 pad10; -+ E3_uint32 InterruptMask; /* 0x12a60 */ -+ E3_uint32 pad11; -+ E3_uint32 LinkErrorTypes; /* 0x12a68 */ -+ E3_uint32 pad12[3]; -+ E3_uint32 LinkState; /* a read here returens the DataDel value for the */ -+ /* link that has just been defined by a write to */ -+ /* Regs.Exts.SchCntReg.LinkSetValue */ -+ E3_uint32 pad13; -+ -+ union /* 0x12a80 */ -+ { -+ E3_DmaWrs DmaWrs; -+ E3_DmaRds DmaRds; -+ } Dmas; -+} E3_Exts; -+ -+typedef union com_port_entry -+{ -+ E3_uint64 type; -+ struct -+ { -+ E3_uint32 Address; /* Command VAddr */ -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 Context0Issue:1; /* Issue was for context 0 */ -+ E3_uint32 EventNotCommand:1; /* Issue address bit 3 */ -+ E3_uint32 RemoteDesc:1; /* Issue address bit 5 */ -+ E3_uint32 :13; /* read as Zero */ -+ E3_uint32 Context:12; /* Command Context */ -+ E3_uint32 :4; /* read as Zero */ -+#else -+ E3_uint32 :4; /* read as Zero */ -+ E3_uint32 Context:12; /* Command Context */ -+ E3_uint32 :13; /* read as Zero */ -+ E3_uint32 RemoteDesc:1; /* Issue address bit 5 */ -+ E3_uint32 EventNotCommand:1; /* Issue address bit 3 */ -+ E3_uint32 Context0Issue:1; /* Issue was for context 0 */ -+#endif -+ } s; -+} E3_ComPortEntry; -+ -+/* control reg bits */ -+#define CONT_MMU_ENABLE (1 << 0) /* bit 0 enables mmu */ -+#define CONT_ENABLE_8K_PAGES (1 << 1) /* When set smallest page is 8k instead of 4k. */ -+#define CONT_EN_ALL_SETS (1 << 2) /* enable cache */ -+#define CONT_CACHE_LEVEL0 (1 << 3) /* cache context table */ -+#define CONT_CACHE_LEVEL1 (1 << 4) /* cache up level 1 PTD/PTE */ -+#define CONT_CACHE_LEVEL2 (1 << 5) /* cache up level 2 PTD/PTE */ -+#define CONT_CACHE_LEVEL3 (1 << 6) /* cache up level 3 PTD/PTE */ -+#define CONT_CACHE_TRAPS (1 << 7) /* cache up traps */ -+#define CONT_CACHE_LEV0_ROUTES (1 << 8) /* cache up small routes */ -+#define CONT_CACHE_LEV1_ROUTES (1 << 9) /* cache up large routes */ -+#define CONT_CACHE_ALL (CONT_CACHE_LEVEL0 | CONT_CACHE_LEVEL1 | CONT_CACHE_LEVEL2 | \ -+ CONT_CACHE_LEVEL3 | CONT_CACHE_TRAPS | \ -+ CONT_CACHE_LEV0_ROUTES | CONT_CACHE_LEV1_ROUTES) -+ -+#define CONT_SYNCHRONOUS (1 << 10) /* PCI running sync */ -+#define CONT_SER (1 << 11) /* Single bit output (Elan1 SER bit) */ -+#define CONT_SIR (1 << 12) /* Writing 1 resets elan. */ -+ -+#define CONT_PSYCHO_MODE (1 << 13) /* Enables all the perversion required by psycho */ -+#define CONT_ENABLE_ECC (1 << 14) /* Enables error detecting on the ECC */ -+#define CONT_SDRAM_TESTING (1 << 15) /* Switches to test mode for checking EEC data bits */ -+ -+/* defines SDRam CasLatency. Once set will not change again unless reset is reasserted. */ -+/* 1 = Cas Latency is 3, 0 = Cas Latency is 2 */ -+#define CAS_LATENCY_2 (0 << 16) -+#define CAS_LATENCY_3 (1 << 16) -+#define REFRESH_RATE_2US (0 << 17) /* defines 2us SDRam Refresh rate. */ -+#define REFRESH_RATE_4US (1 << 17) /* defines 4us SDRam Refresh rate. */ -+#define REFRESH_RATE_8US (2 << 17) /* defines 8us SDRam Refresh rate. */ -+#define REFRESH_RATE_16US (3 << 17) /* defines 16us SDRam Refresh rate. */ -+ -+#define CONT_PCI_ERR (1 << 19) /* Read 1 if PCI Error */ -+#define CONT_CLEAR_PCI_ERROR (1 << 19) /* Clears an PCI error. */ -+ -+/* Will cause the PCI error bit to become set. This is used to force the threads proc -+ and the uProc to start to stall. */ -+#define CONT_SET_PCI_ERROR (1 << 20) -+ -+/* Writes SDram control reg when set. Also starts SDram memory system refreshing. */ -+#define SETUP_SDRAM (1 << 21) -+ -+/* Flushes the tlb */ -+#define MMU_FLUSH (1 << 22) -+/* and read back when it's finished */ -+#define MMU_FLUSHED (1 << 0) -+ -+/* Clears any ECC error detected by SDRam interface */ -+#define CLEAR_SDRAM_ERROR (1 << 23) -+ -+#define ECC_ADDR_MASK 0x0ffffff8 -+#define ECC_UE_MASK 0x1 -+#define ECC_CE_MASK 0x2 -+#define ECC_ME_MASK 0x4 -+#define ECC_SYN_MASK 0xff -+ -+/* define page table entry bit fields */ -+#define TLB_PageSizeBits (3 << 0) -+#define TLB_ACCBits (7 << 2) -+#define TLB_LocalBit (1 << 5) -+#define TLB_PCI64BitTargetBit (1 << 6) -+#define TLB_PCIBigEndianBit (1 << 7) -+ -+#define TLB_ModifiedBit (1 << 55) -+#define TLB_ReferencedBit (1 << 63) -+ -+/* Used to read values from the tlb. */ -+#define TLB_TlbReadCntBitsSh 56 -+#define TLB_UseSelAddrSh (1ULL << 60) -+#define TLB_WriteTlbLine (1ULL << 61) -+ -+#define TLB_SEL_LINE(LineNo) (TLB_UseSelAddrSh | \ -+ ((E3_uint64)((LineNo) & 0xf) << TLB_TlbReadCntBitsSh)) -+ -+typedef union _E3_CacheContReg -+{ -+ E3_uint32 ContReg; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 MMU_Enable:1; /* wr 1 to enable the MMU */ -+ E3_uint32 Set8kPages:1; /* wr 1 smallest page is 8k. */ -+ E3_uint32 EnableAllSets:1; /* wr 1 All the cache sets are enabled */ -+ E3_uint32 Cache_Level0:1; /* wr 1 lev0 page tabs will be cached */ -+ E3_uint32 Cache_Level1:1; /* wr 1 lev1 page tabs will be cached */ -+ E3_uint32 Cache_Level2:1; /* wr 1 lev2 page tabs will be cached */ -+ E3_uint32 Cache_Level3:1; /* wr 1 lev3 page tabs will be cached */ -+ E3_uint32 Cache_Traps:1; /* wr 1 trap info will be cached */ -+ E3_uint32 Cache_Lev0_Routes:1; /* wr 1 small routes will be cached */ -+ E3_uint32 Cache_Lev1_Routes:1; /* wr 1 big routes will be cached */ -+ E3_uint32 PCI_Synchronous:1; /* Pci and sys clocks are running synchronously*/ -+ E3_uint32 SER:1; /* 1 bit output port */ -+ E3_uint32 SIR:1; /* write 1 will reset elan */ -+ E3_uint32 PsychoMode:1; /* Enables psycho perversion mode. */ -+ E3_uint32 CasLatency:1; /* 1=cas latency=3, 1=cas latency=2 */ -+ E3_uint32 RefreshRate:2; /* 0=2us, 1=4us, 2=8us, 3=16us */ -+ E3_uint32 Pci_Err:1; /* pci error. Write 1 clears err */ -+ E3_uint32 Set_Pci_Error:1; /* Will simulate an Pci error */ -+ E3_uint32 StartSDRam:1; /* Starts the sdram subsystem */ -+ E3_uint32 FlushTlb:1; /* Flush the contence of the tlb */ -+ E3_uint32 :11; -+#else -+ E3_uint32 :11; -+ E3_uint32 FlushTlb:1; /* Flush the contence of the tlb */ -+ E3_uint32 StartSDRam:1; /* Starts the sdram subsystem */ -+ E3_uint32 Set_Pci_Error:1; /* Will simulate an Pci error */ -+ E3_uint32 Pci_Err:1; /* pci error. Write 1 clears err */ -+ E3_uint32 RefreshRate:2; /* 0=2us, 1=4us, 2=8us, 3=16us */ -+ E3_uint32 CasLatency:1; /* 1=cas latency=3, 1=cas latency=2 */ -+ E3_uint32 PsychoMode:1; /* Enables psycho perversion mode. */ -+ E3_uint32 SIR:1; /* write 1 will reset elan */ -+ E3_uint32 SER:1; /* 1 bit output port */ -+ E3_uint32 PCI_Synchronous:1; /* Pci and sys clocks are running synchronously*/ -+ E3_uint32 Cache_Lev1_Routes:1; /* wr 1 big routes will be cached */ -+ E3_uint32 Cache_Lev0_Routes:1; /* wr 1 small routes will be cached */ -+ E3_uint32 Cache_Traps:1; /* wr 1 trap info will be cached */ -+ E3_uint32 Cache_Level3:1; /* wr 1 lev3 page tabs will be cached */ -+ E3_uint32 Cache_Level2:1; /* wr 1 lev2 page tabs will be cached */ -+ E3_uint32 Cache_Level1:1; /* wr 1 lev1 page tabs will be cached */ -+ E3_uint32 Cache_Level0:1; /* wr 1 lev0 page tabs will be cached */ -+ E3_uint32 EnableAllSets:1; /* wr 1 All the cache sets are enabled */ -+ E3_uint32 Set8kPages:1; /* wr 1 smallest page is 8k. */ -+ E3_uint32 MMU_Enable:1; /* wr 1 to enable the MMU */ -+#endif -+ } s; -+} E3_CacheContReg; -+ -+typedef union _E3_TrapBits -+{ -+ volatile E3_uint32 Bits; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 ForcedTProcTrap:1; /* The theads proc has been halted */ -+ E3_uint32 InstAccessException:1; /* An instruction access exception */ -+ E3_uint32 Unimplemented:1; /* Unimplemented instruction executed */ -+ E3_uint32 DataAccessException:1; /* A data access exception */ -+ -+ E3_uint32 ThreadTimeout:1; /* The threads outputer has timed out */ -+ E3_uint32 OpenException:1; /* Invalid sequence of open, sendtr or close */ -+ E3_uint32 OpenRouteFetch:1; /* Fault while fetching routes for previous open*/ -+ E3_uint32 TrapForTooManyInsts:1; /* Thread has been executing for too long */ -+ -+ E3_uint32 PacketAckValue:2; /* Packet ack type. Valid if AckBufferValid set. */ -+ E3_uint32 PacketTimeout:1; /* Packet timeout. Sent an EopError. Valid if AckBufferValid set. */ -+ -+ E3_uint32 AckBufferValid:1; /* The PacketAckValue bits are valid */ -+ E3_uint32 OutputWasOpen:1; /* The output was open when tproc trapped */ -+ E3_uint32 TProcDeschedule:2; /* The reason the tproc stopped running. */ -+ E3_uint32 :17; -+#else -+ E3_uint32 :17; -+ E3_uint32 TProcDeschedule:2; /* The reason the tproc stopped running. */ -+ E3_uint32 OutputWasOpen:1; /* The output was open when tproc trapped */ -+ E3_uint32 AckBufferValid:1; /* The PacketAckValue bits are valid */ -+ -+ E3_uint32 PacketTimeout:1; /* Packet timeout. Sent an EopError. Valid if AckBufferValid set. */ -+ E3_uint32 PacketAckValue:2; /* Packet ack type. Valid if AckBufferValid set. */ -+ -+ E3_uint32 TrapForTooManyInsts:1; /* Thread has been executing for too long */ -+ E3_uint32 OpenRouteFetch:1; /* Fault while fetching routes for previous open*/ -+ E3_uint32 OpenException:1; /* Invalid sequence of open, sendtr or close */ -+ E3_uint32 ThreadTimeout:1; /* The threads outputer has timed out */ -+ -+ E3_uint32 DataAccessException:1; /* A data access exception */ -+ E3_uint32 Unimplemented:1; /* Unimplemented instruction executed */ -+ E3_uint32 InstAccessException:1; /* An instruction access exception */ -+ E3_uint32 ForcedTProcTrap:1; /* The theads proc has been halted */ -+#endif -+ } s; -+} E3_TrapBits; -+ -+typedef union _E3_DirtyBits -+{ -+ volatile E3_uint32 Bits; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 GlobalsDirty:8; -+ E3_uint32 OutsDirty:8; /* will always read as dirty. */ -+ E3_uint32 LocalsDirty:8; -+ E3_uint32 InsDirty:8; -+#else -+ E3_uint32 InsDirty:8; -+ E3_uint32 LocalsDirty:8; -+ E3_uint32 OutsDirty:8; /* will always read as dirty. */ -+ E3_uint32 GlobalsDirty:8; -+#endif -+ } s; -+} E3_DirtyBits; -+ -+#define E3_TProcDescheduleMask 0x6000 -+#define E3_TProcDescheduleWait 0x2000 -+#define E3_TProcDescheduleSuspend 0x4000 -+#define E3_TProcDescheduleBreak 0x6000 -+ -+#define E3_TrapBitsMask 0x7fff -+ -+#define ThreadRestartFromTrapBit 1 -+#define ThreadReloadAllRegs 2 -+ -+#define E3_PAckOk 0 -+#define E3_PAckTestFail 1 -+#define E3_PAckDiscard 2 -+#define E3_PAckError 3 -+ -+typedef volatile struct _E3_DataBusMap -+{ -+ E3_uint64 Dma_Alignment_Port[8]; /* 0x00002800 */ -+ E3_uint32 pad0[0x30]; /* 0x00002840 */ -+ -+ E3_uint32 Input_Trans0_Data[0x10]; /* 0x00002900 */ -+ E3_uint32 Input_Trans1_Data[0x10]; -+ E3_uint32 Input_Trans2_Data[0x10]; -+ E3_uint32 Input_Trans3_Data[0x10]; -+ -+/* this is the start of the exts directly addressable from the ucode. */ -+ E3_Exts Exts; /* 0x00002a00 */ -+ -+/* this is the start of the registers directly addressable from the ucode. */ -+ E3_DMA Dma_Desc; /* 0x00002b00 */ -+ -+ E3_uint32 Dma_Last_Packet_Size; /* 0x00002b20 */ -+ E3_uint32 Dma_This_Packet_Size; /* 0x00002b24 */ -+ E3_uint32 Dma_Tmp_Source; /* 0x00002b28 */ -+ E3_uint32 Dma_Tmp_Dest; /* 0x00002b2c */ -+ -+ E3_Addr Thread_SP_Save_Ptr; /* points to the thread desched save word. */ -+ E3_uint32 Dma_Desc_Size_InProg; /* 0x00002b34 */ -+ -+ E3_uint32 Thread_Desc_SP; /* 0x00002b38 */ -+ E3_uint32 Thread_Desc_Context; /* 0x00002b3c */ -+ -+ E3_uint32 uCode_TMP[0x10]; /* 0x00002b40 */ -+ -+ E3_uint32 TProc_NonSysCntx_FPtr; /* 0x00002b80 */ -+ E3_uint32 TProc_NonSysCntx_BPtr; /* 0x00002b84 */ -+ E3_uint32 TProc_SysCntx_FPtr; /* 0x00002b88 */ -+ E3_uint32 TProc_SysCntx_BPtr; /* 0x00002b8c */ -+ E3_uint32 DProc_NonSysCntx_FPtr; /* 0x00002b90 */ -+ E3_uint32 DProc_NonSysCntx_BPtr; /* 0x00002b94 */ -+ E3_uint32 DProc_SysCntx_FPtr; /* 0x00002b98 */ -+ E3_uint32 DProc_SysCntx_BPtr; /* 0x00002b9c */ -+ -+ E3_uint32 Input_Trap_Base; /* 0x00002ba0 */ -+ E3_uint32 Input_Queue_Offset; /* 0x00002ba4 */ -+ E3_uint32 CProc_TrapSave_Addr; /* 0x00002ba8 */ -+ E3_uint32 Input_Queue_Addr; /* 0x00002bac */ -+ E3_uint32 uCode_TMP10; /* 0x00002bb0 */ -+ E3_uint32 uCode_TMP11; /* 0x00002bb4 */ -+ E3_uint32 Event_Trace_Ptr; /* 0x00002bb8 */ -+ E3_uint32 Event_Trace_Mask; /* 0x00002bbc */ -+ -+ E3_ComPortEntry DmaComQueue[3]; /* 0x00002bc0 */ -+ -+ E3_uint32 Event_Int_Queue_FPtr; /* 0x00002bd8 */ -+ E3_uint32 Event_Int_Queue_BPtr; /* 0x00002bdc */ -+ -+ E3_ComPortEntry ThreadComQueue[2]; /* 0x00002be0 */ -+ E3_ComPortEntry SetEventComQueue[2]; /* 0x00002bf0 */ -+ -+ E3_uint32 pad1[96]; /* 0x00002c00 */ -+ E3_uint32 ComQueueStatus; /* 0x00002d80 */ -+ E3_uint32 pad2[31]; /* 0x00002d84 */ -+ -+/* These are the internal registers of the threads proc. */ -+ E3_uint32 Globals[8]; /* 0x00002e00 */ -+ E3_uint32 Outs[8]; -+ E3_uint32 Locals[8]; -+ E3_uint32 Ins[8]; -+ -+ E3_uint32 pad3[16]; -+ -+ E3_uint32 IBufferReg[4]; -+ -+ E3_uint32 ExecuteNPC; -+ E3_uint32 ExecutePC; -+ -+ E3_uint32 StartPC; -+ E3_uint32 pad4; -+ -+ E3_uint32 StartnPC; -+ E3_uint32 pad5; -+ -+ E3_TrapBits TrapBits; -+ E3_DirtyBits DirtyBits; -+ E3_uint64 LoadDataReg; -+ E3_uint64 StoreDataReg; -+ -+ E3_uint32 ECC_STATUS0; -+ E3_uint32 ECC_STATUS1; -+ E3_uint32 pad6[0xe]; -+ -+/* Pci slave port regs */ -+ E3_uint32 PciSlaveReadCache[0x10]; -+ -+ E3_uint32 Fault_Base_Ptr; -+ E3_uint32 pad7; -+ E3_uint32 Context_Ptr; -+ E3_uint32 pad8; -+ E3_uint32 Input_Context_Filter; /* write only, No data */ -+ E3_uint32 Input_Context_Fil_Flush; /* write only, No data */ -+ E3_CacheContReg Cache_Control_Reg; -+ E3_uint32 pad9; -+ -+ E3_uint64 Tlb_Line_Value; -+ -+ E3_uint32 Walk_Datareg1; -+ E3_uint32 Walk_VAddr_Tab_Base; -+ E3_uint32 Walk_Datareg; -+ E3_uint32 Walk_ContextReg; -+ E3_uint32 Walk_FaultAddr; -+ E3_uint32 Walk_EventAddr; -+ -+/* outputers output cont ext registers. */ -+ E3_uint64 Dma_Route_012345_Context; -+ E3_uint64 pad10; -+ E3_uint64 Dma_Route_01234567; -+ E3_uint64 Dma_Route_89ABCDEF; -+ -+ E3_uint64 Thread_Route_012345_Context; -+ E3_uint64 pad11; -+ E3_uint64 Thread_Route_01234567; -+ E3_uint64 Thread_Route_89ABCDEF; -+} E3_DataBusMap; -+ -+typedef volatile struct _E3_Regs -+{ -+ E3_CacheSets Sets; /* 0x00000000 */ -+ E3_CacheTags Tags; /* 0x00002000 */ -+ E3_DataBusMap Regs; /* 0x00002800 */ -+ E3_uint32 pad1[0x400]; -+ E3_User_Regs URegs; -+} E3_Regs; -+ -+#define MAX_TRAPPED_TRANS 16 -+#define TRANS_DATA_WORDS 16 -+#define TRANS_DATA_BYTES 64 -+ -+/* -+ * Event interrupt -+ */ -+typedef volatile union _E3_EventInt -+{ -+ E3_uint64 ForceAlign; -+ struct { -+ E3_uint32 IntCookie; -+ E3_uint32 EventContext; /* Bits 16 to 28 */ -+ } s; -+} E3_EventInt; -+ -+#define GET_EVENT_CONTEXT(Ptr) ((Ptr->s.EventContext >> 16) & MAX_ROOT_CONTEXT_MASK) -+ -+typedef volatile union _E3_ThreadQueue -+{ -+ E3_uint64 ForceAlign; -+ struct -+ { -+ E3_Addr Thread; -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 :16; /* Bits 0 to 15 */ -+ E3_uint32 Context:13; /* Bits 16 to 28 */ -+ E3_uint32 :3; /* Bits 29 to 31 */ -+#else -+ E3_uint32 :3; /* Bits 29 to 31 */ -+ E3_uint32 Context:13; /* Bits 16 to 28 */ -+ E3_uint32 :16; /* Bits 0 to 15 */ -+#endif -+ } s; -+} E3_ThreadQueue; -+ -+typedef volatile union _E3_FaultStatusReg -+{ -+ E3_uint32 Status; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 AccTypePerm:3; /* Access permission. See below. Bits 0 to 2 */ -+ E3_uint32 AccSize:4; /* Access size. See below for different types. Bits 3 to 6 */ -+ E3_uint32 WrAcc:1; /* Access was a write. Bit 7 */ -+ E3_uint32 NonAllocAcc:1; /* Access was a cache non allocate type. Bit 8 */ -+ E3_uint32 BlkDataType:2; /* Data size used for endian flips. Bits 9 to 10 */ -+ E3_uint32 RdLine:1; /* Access was a dma read line. Bit 11 */ -+ E3_uint32 RdMult:1; /* Access was a dma read multiple. Bit 12 */ -+ E3_uint32 Walking:1; /* The fault occued when walking. Bit 13 */ -+ E3_uint32 Level:2; /* Page table level when the fault occued. Bits 14 to 15 */ -+ E3_uint32 ProtFault:1; /* A protection fault occured. Bit 16 */ -+ E3_uint32 FaultPte:2; /* Page table type when the fault occured. Bit 17 */ -+ E3_uint32 AlignmentErr:1; /* Address alignment did not match the access size. Bit 19 */ -+ E3_uint32 VProcSizeErr:1; /* VProc number is out of range. Bit 20 */ -+ E3_uint32 WalkBadData:1; /* Memory CRC error during a walk. Bit 21 */ -+ E3_uint32 :10; /* Bits 22 to 31 */ -+#else -+ E3_uint32 :10; /* Bits 22 to 31 */ -+ E3_uint32 WalkBadData:1; /* Memory CRC error during a walk. Bit 21 */ -+ E3_uint32 VProcSizeErr:1; /* VProc number is out of range. Bit 20 */ -+ E3_uint32 AlignmentErr:1; /* Address alignment did not match the access size. Bit 19 */ -+ E3_uint32 FaultPte:2; /* Page table type when the fault occured. Bit 17 */ -+ E3_uint32 ProtFault:1; /* A protection fault occured. Bit 16 */ -+ E3_uint32 Level:2; /* Page table level when the fault occued. Bits 14 to 15 */ -+ E3_uint32 Walking:1; /* The fault occued when walking. Bit 13 */ -+ E3_uint32 RdMult:1; /* Access was a dma read multiple. Bit 12 */ -+ E3_uint32 RdLine:1; /* Access was a dma read line. Bit 11 */ -+ E3_uint32 BlkDataType:2; /* Data size used for endian flips. Bits 9 to 10 */ -+ E3_uint32 NonAllocAcc:1; /* Access was a cache non allocate type. Bit 8 */ -+ E3_uint32 WrAcc:1; /* Access was a write. Bit 7 */ -+ E3_uint32 AccSize:4; /* Access size. See below for different types. Bits 3 to 6 */ -+ E3_uint32 AccTypePerm:3; /* Access permission. See below. Bits 0 to 2 */ -+#endif -+ } s; -+} E3_FaultStatusReg; -+ -+typedef union _E3_FaultSave -+{ -+ E3_uint64 ForceAlign; -+ struct { -+ E3_FaultStatusReg FSR; -+ volatile E3_uint32 FaultContext; -+ volatile E3_uint32 FaultAddress; -+ volatile E3_uint32 EventAddress; -+ } s; -+} E3_FaultSave; -+ -+/* MMU fault status reg bit positions. */ -+#define FSR_WritePermBit 0 /* 1=Write access perm, 0=Read access perm */ -+#define FSR_RemotePermBit 1 /* 1=Remote access perm, 0=local access perm */ -+#define FSR_EventPermBit 2 /* 1=Event access perm, 0=data access perm */ -+#define FSR_Size0Bit 3 -+#define FSR_Size1Bit 4 -+#define FSR_Size2Bit 5 -+#define FSR_Size3Bit 6 -+#define FSR_WriteAccBit 7 /* 1=Write access, 0=Read access. */ -+#define FSR_NonAllocBit 8 /* 1=Do not fill cache with this data */ -+#define FSR_BlkDataTy0Bit 9 -+#define FSR_BlkDataTy1Bit 10 -+#define FSR_ReadLineBit 11 -+#define FSR_ReadMultipleBit 12 -+ -+#define FSR_PermMask (0xf << FSR_WritePermBit) -+#define FSR_SizeMask (0xf << FSR_Size0Bit) -+#define FSR_AccTypeMask (3 << FSR_WriteAccBit) -+#define FSR_BlkDataTyMask (3 << FSR_BlkDataTy0Bit) -+#define FSR_PciAccTyMask (3 << FSR_ReadLineBit) -+#define FSR_Walking (0x1 << 13) -+#define FSR_Level_Mask (0x3 << 14) -+#define FSR_ProtFault (0x1 << 16) -+#define FSR_FaultPTEType (0x2 << 17) -+#define FSR_AddrSizeError (0x1 << 19) -+#define FSR_VProcSizeError (0x1 << 20) -+#define FSR_WalkBadData (0x1 << 21) -+ -+#define FSR_PermRead 0 -+#define FSR_PermWrite 1 -+#define FSR_PermRemoteRead 2 -+#define FSR_PermRemoteWrite 3 -+#define FSR_PermEventRd 4 -+#define FSR_PermEventWr 5 -+#define FSR_PermRemoteEventRd 6 -+#define FSR_PermRemoteEventWr 7 -+ -+/* AT size values for each access type */ -+#define FSR_Word (0x0 << FSR_Size0Bit) -+#define FSR_DWord (0x1 << FSR_Size0Bit) -+#define FSR_QWord (0x2 << FSR_Size0Bit) -+#define FSR_Block32 (0x3 << FSR_Size0Bit) -+#define FSR_ReservedBlock (0x6 << FSR_Size0Bit) -+#define FSR_Block64 (0x7 << FSR_Size0Bit) -+#define FSR_GetCntxFilter (0x8 << FSR_Size0Bit) -+#define FSR_QueueDWord (0x9 << FSR_Size0Bit) -+#define FSR_RouteFetch (0xa << FSR_Size0Bit) -+#define FSR_QueueBlock (0xb << FSR_Size0Bit) -+#define FSR_Block32PartWrite (0xe << FSR_Size0Bit) -+#define FSR_Block64PartWrite (0xf << FSR_Size0Bit) -+ -+#define FSR_AllocRead (0 << FSR_WriteAccBit) -+#define FSR_AllocWrite (1 << FSR_WriteAccBit) -+#define FSR_NonAllocRd (2 << FSR_WriteAccBit) -+#define FSR_NonAllocWr (3 << FSR_WriteAccBit) -+ -+#define FSR_TypeByte (0 << FSR_BlkDataTy0Bit) -+#define FSR_TypeHWord (1 << FSR_BlkDataTy0Bit) -+#define FSR_TypeWord (2 << FSR_BlkDataTy0Bit) -+#define FSR_TypeDWord (3 << FSR_BlkDataTy0Bit) -+ -+typedef union E3_TrTypeCntx -+{ -+ E3_uint32 TypeContext; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 Type:16; /* Transaction type field */ -+ E3_uint32 Context:13; /* Transaction context */ -+ E3_uint32 TypeCntxInvalid:1; /* Bit 29 */ -+ E3_uint32 StatusRegValid:1; /* Bit 30 */ -+ E3_uint32 LastTrappedTrans:1; /* Bit 31 */ -+#else -+ E3_uint32 LastTrappedTrans:1; /* Bit 31 */ -+ E3_uint32 StatusRegValid:1; /* Bit 30 */ -+ E3_uint32 TypeCntxInvalid:1; /* Bit 29 */ -+ E3_uint32 Context:13; /* Transaction context */ -+ E3_uint32 Type:16; /* Transaction type field */ -+#endif -+ } s; -+} E3_TrTypeCntx; -+ -+#define GET_TRAP_TYPE(Ptr) (Ptr.TypeContext & 0xfff) -+#define GET_TRAP_CONTEXT(Ptr) ((Ptr.TypeContext >> 16) & 0x1fff) -+ -+/* Words have been swapped for big endian access when fetched with dword access from elan.*/ -+typedef union _E3_IprocTrapHeader -+{ -+ E3_uint64 forceAlign; -+ -+ struct -+ { -+ E3_TrTypeCntx TrTypeCntx; -+ E3_uint32 TrAddr; -+ E3_uint32 TrData0; -+ union -+ { -+ E3_IProcStatus_Reg u_IProcStatus; -+ E3_uint32 u_TrData1; -+ } ipsotd; -+ } s; -+} E3_IprocTrapHeader; -+ -+#define IProcTrapStatus ipsotd.u_IProcStatus -+#define TrData1 ipsotd.u_TrData1 -+ -+typedef struct E3_IprocTrapData -+{ -+ E3_uint32 TrData[TRANS_DATA_WORDS]; -+} E3_IprocTrapData; -+ -+/* -+ * 64 kbytes of elan local memory. Must be aligned on a 64k boundary -+ */ -+#define E3_NonSysCntxQueueSize 0x400 -+#define E3_SysCntxQueueSize 0x100 -+ -+typedef struct _E3_TrapAndQueue -+{ -+ E3_DMA NonSysCntxDmaQueue[E3_NonSysCntxQueueSize]; /* 0x000000 */ -+ E3_DMA SysCntxDmaQueue[E3_SysCntxQueueSize]; /* 0x008000 */ -+ E3_EventInt EventIntQueue[E3_NonSysCntxQueueSize]; /* 0x00A000 */ -+ E3_ThreadQueue NonSysCntxThreadQueue[E3_NonSysCntxQueueSize]; /* 0x00C000 */ -+ E3_ThreadQueue SysCntxThreadQueue[E3_SysCntxQueueSize]; /* 0x00E000 */ -+ E3_FaultSave IProcSysCntx; /* 0x00E800 */ -+ E3_Addr Thread_SP_Save; /* 0x00E810 */ -+ E3_uint32 dummy0[3]; /* 0x00E814 */ -+ E3_FaultSave ThreadProcData; /* 0x00E820 */ -+ E3_FaultSave ThreadProcInst; /* 0x00E830 */ -+ E3_FaultSave dummy1[2]; /* 0x00E840 */ -+ E3_FaultSave ThreadProcOpen; /* 0x00E860 */ -+ E3_FaultSave dummy2; /* 0x00E870 */ -+ E3_FaultSave IProcNonSysCntx; /* 0x00E880 */ -+ E3_FaultSave DProc; /* 0x00E890 */ -+ E3_FaultSave CProc; /* 0x00E8A0 */ -+ E3_FaultSave TProc; /* 0x00E8B0 */ -+ E3_FaultSave DProcData0; /* 0x00E8C0 */ -+ E3_FaultSave DProcData1; /* 0x00E8D0 */ -+ E3_FaultSave DProcData2; /* 0x00E8E0 */ -+ E3_FaultSave DProcData3; /* 0x00E8F0 */ -+ E3_uint32 dummy3[0xc0]; /* 0x00E900 */ -+ E3_IprocTrapHeader VCh0_C0_TrHead[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapHeader VCh0_NonC0_TrHead[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapHeader VCh1_C0_TrHead[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapHeader VCh1_NonC0_TrHead[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapData VCh0_C0_TrData[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapData VCh0_NonC0_TrData[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapData VCh1_C0_TrData[MAX_TRAPPED_TRANS]; -+ E3_IprocTrapData VCh1_NonC0_TrData[MAX_TRAPPED_TRANS]; -+ E3_uint64 DmaOverflowQueueSpace[0x1000]; -+ E3_uint64 ThreadOverflowQueueSpace[0x800]; -+ E3_uint64 EventOverflowQueueSpace[0x800]; -+} E3_TrapAndQueue; -+ -+ -+typedef struct _E3_ContextControlBlock -+{ -+ E3_uint32 rootPTP; -+ E3_uint32 filter; -+ E3_uint32 VPT_ptr; -+ E3_uint32 VPT_mask; -+} E3_ContextControlBlock; -+ -+#define E3_CCB_CNTX0 (0x20000000) -+#define E3_CCB_DISCARD_ALL (0x40000000) -+#define E3_CCB_ACKOK_ALL (0x80000000) -+#define E3_CCB_MASK (0xc0000000) -+ -+#define E3_NUM_CONTEXT_0 (0x20) -+ -+/* Macros to manipulate event queue pointers */ -+/* generate index in EventIntQueue */ -+#define E3_EVENT_INTQ_INDEX(fptr) (((fptr) & 0x1fff) >> 3) -+/* generate next fptr */ -+#define E3_EVENT_INTQ_NEXT(fptr) ((((fptr) + 8) & ~0x4000) | 0x2000) -+ -+ -+#endif /* notdef _ELAN3_ELANREGS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elansyscall.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elansyscall.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elansyscall.h 2005-06-01 23:12:54.724420104 -0400 -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_ELANSYSCALL_H -+#define __ELAN3_ELANSYSCALL_H -+ -+#ident "$Id: elansyscall.h,v 1.34 2004/06/07 13:50:06 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elansyscall.h,v $*/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#ifndef _ASM -+ -+typedef struct sys_word_item -+{ -+ struct sys_word_item *Next; -+ E3_uint32 Value; -+} SYS_WORD_ITEM; -+ -+typedef struct sys_block_item -+{ -+ struct sys_block_item *Next; -+ E3_uint32 *Pointer; -+} SYS_BLOCK_ITEM; -+ -+typedef struct sys_swap_space -+{ -+ int Magic; -+ void *ItemListsHead[MAX_LISTS]; -+ void **ItemListsTailp[MAX_LISTS]; -+} SYS_SWAP_SPACE; -+ -+typedef struct sys_exception -+{ -+ int Type; -+ int Proc; -+ u_long Res; -+ u_long Value; -+ E3_FaultSave_BE FaultArea; -+ -+ union -+ { -+ DMA_TRAP Dma; -+ THREAD_TRAP Thread; -+ COMMAND_TRAP Command; -+ INPUT_TRAP Input; -+ } Union; -+} SYS_EXCEPTION; -+ -+typedef struct sys_exception_space -+{ -+ struct sys_exception_space *Next; -+ int Magic; -+ int Front; -+ int Back; -+ int Count; -+ int Overflow; -+ SYS_EXCEPTION Exceptions[1]; -+} SYS_EXCEPTION_SPACE; -+ -+#ifdef __KERNEL__ -+ -+typedef struct sys_ctxt -+{ -+ SYS_SWAP_SPACE *Swap; -+ SYS_EXCEPTION_SPACE *Exceptions; -+ kmutex_t Lock; -+ -+ spinlock_t WaitLock; -+ kcondvar_t NetworkErrorWait; -+ -+ int Armed; -+ int Backoff; -+ long Time; -+ -+ u_long Flags; -+ int signal; -+ -+ EVENT_COOKIE_TABLE *Table; -+} SYS_CTXT; -+ -+extern SYS_CTXT *sys_init (ELAN3_CTXT *ctxt); -+extern int sys_waitevent (ELAN3_CTXT *ctxt, E3_Event *event); -+extern void sys_addException (SYS_CTXT *sctx, int type, int proc, caddr_t ptr, int size, -+ E3_FaultSave_BE *, u_long res, u_long value); -+extern int sys_getException (SYS_CTXT *sctx, SYS_EXCEPTION *ex); -+ -+/* returns -ve error or ELAN_CAP_OK or ELAN_CAP_RMS */ -+/* use = ELAN_USER_ATTACH, ELAN_USER_P2P, ELAN_USER_BROADCAST */ -+extern int elan3_validate_cap (ELAN3_DEV *dev, ELAN_CAPABILITY *cap ,int use); -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _ASM */ -+ -+/* values for "Flags" */ -+#define ELAN3_SYS_FLAG_DMA_BADVP 1 -+#define ELAN3_SYS_FLAG_THREAD_BADVP 2 -+#define ELAN3_SYS_FLAG_DMAFAIL 4 -+#define ELAN3_SYS_FLAG_NETERR 8 -+ -+#define SYS_SWAP_MAGIC 0xB23C52DF -+#define SYS_EXCEPTION_MAGIC 0xC34D63E0 -+ -+#define EXCEPTION_GLOBAL_STRING "elan3_exceptions" -+#define EXCEPTION_ABORT_STRING "elan3_abortstring" -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __ELAN3_ELANSYSCALL_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elanuregs.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elanuregs.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elanuregs.h 2005-06-01 23:12:54.725419952 -0400 -@@ -0,0 +1,295 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_ELANUREGS_H -+#define __ELAN3_ELANUREGS_H -+ -+#ident "$Id: elanuregs.h,v 1.10 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elanuregs.h,v $*/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* -+ * Statistic control reg values -+ * Each 4-bit nibble of the control word specifies what statistic -+ * is to be recorded in each of the 8 statistic counters -+ */ -+ -+/* Count reg 0 */ -+#define STC_INPUT_TRANSACTIONS 0 -+#define STP_DMA_EOP_WAIT_ACK 1 -+#define STP_THREAD_RUNNING 2 -+#define STP_UCODE_WAIT_MEM 3 -+#define STC_CACHE_WRITE_BACKS 4 -+#define STC_PCI_SLAVE_READS 5 -+#define STC_REG0_UNUSED6 6 -+#define STP_REG0_UNUSED7 7 -+ -+#define STATS_REG0_NAMES { \ -+ "STC_INPUT_TRANSACTIONS", \ -+ "STP_DMA_EOP_WAIT_ACK", \ -+ "STP_THREAD_RUNNING", \ -+ "STP_UCODE_WAIT_MEM", \ -+ "STC_CACHE_WRITE_BACKS", \ -+ "STC_PCI_SLAVE_READS", \ -+ "STC_REG0_UNUSED6", \ -+ "STP_REG0_UNUSED7" \ -+} -+ -+/* Count reg 1 */ -+#define STC_INPUT_WRITE_BLOCKS (0 << 4) -+#define STP_DMA_DATA_TRANSMITTING (1 << 4) -+#define STP_THEAD_WAITING_INST (2 << 4) -+#define STC_REG1_UNUSED3 (3 << 4) -+#define STP_FETCHING_ROUTES (4 << 4) -+#define STC_REG1_UNUSED5 (5 << 4) -+#define STC_PCI_SLAVE_WRITES (6 << 4) -+#define STP_PCI_SLAVE_READ_WAITING (7 << 4) -+ -+#define STATS_REG1_NAMES { \ -+ "STC_INPUT_WRITE_BLOCKS", \ -+ "STP_DMA_DATA_TRANSMITTING", \ -+ "STP_THEAD_WAITING_INST", \ -+ "STC_REG1_UNUSED3", \ -+ "STP_FETCHING_ROUTES", \ -+ "STC_REG1_UNUSED5", \ -+ "STC_PCI_SLAVE_WRITES", \ -+ "STP_PCI_SLAVE_READ_WAITING" \ -+} -+ -+/* Count reg 2 */ -+#define STC_INPUT_PKTS (0 << 8) -+#define STP_DMA_WAITING_MEM (1 << 8) -+#define STP_THREAD_WAIT_OPEN_PKT (2 << 8) -+#define STC_REG2_UNUSED3 (3 << 8) -+#define STC_ROUTE_FETCHES (4 << 8) -+#define STC_CACHE_NON_ALLOC_MISSES (5 << 8) -+#define STC_REG2_UNUSED6 (6 << 8) -+#define STP_PCI_SLAVE_WRITE_WAITING (7 << 8) -+ -+#define STATS_REG2_NAMES { \ -+ "STC_INPUT_PKTS", \ -+ "STP_DMA_WAITING_MEM", \ -+ "STP_THREAD_WAIT_OPEN_PKT", \ -+ "STC_REG2_UNUSED3", \ -+ "STC_ROUTE_FETCHES", \ -+ "STC_CACHE_NON_ALLOC_MISSES", \ -+ "STC_REG2_UNUSED6", \ -+ "STP_PCI_SLAVE_WRITE_WAITING" \ -+} -+ -+/* Count reg 3 */ -+#define STC_INPUT_PKTS_REJECTED (0 << 12) -+#define STP_DMA_WAIT_NETWORK_BUSY (1 << 12) -+#define STP_THREAD_WAIT_PACK (2 << 12) -+#define STP_UCODE_BLOCKED_UCODE (3 << 12) -+#define STC_TLB_HITS (4 << 12) -+#define STC_REG3_UNUSED5 (5 << 12) -+#define STC_PCI_MASTER_READS (6 << 12) -+#define STP_PCI_MASTER_WRITE_WAITING (7 << 12) -+ -+#define STATS_REG3_NAMES { \ -+ "STC_INPUT_PKTS_REJECTED", \ -+ "STP_DMA_WAIT_NETWORK_BUSY", \ -+ "STP_THREAD_WAIT_PACK", \ -+ "STP_UCODE_BLOCKED_UCODE", \ -+ "STC_TLB_HITS", \ -+ "STC_REG3_UNUSED5", \ -+ "STC_PCI_MASTER_READS", \ -+ "STP_PCI_MASTER_WRITE_WAITING"\ -+} -+ -+/* Count reg 4 */ -+#define STP_INPUT_DATA_TRANSMITTING (0 << 16) -+#define STC_DMA_NON_CTX0_PKTS (1 << 16) -+#define STP_THREAD_EOP_WAIT_ACK (2 << 16) -+#define STP_UCODE_DPROC_RUNNING (3 << 16) -+#define STC_TLB_MEM_WALKS (4 << 16) -+#define STC_REG4_UNUSED5 (5 << 16) -+#define STC_PCI_MASTER_WRITES (6 << 16) -+#define STP_PCI_MASTER_READ_WAITING (7 << 16) -+ -+#define STATS_REG4_NAMES { \ -+ "STP_INPUT_DATA_TRANSMITTING", \ -+ "STC_DMA_NON_CTX0_PKTS", \ -+ "STP_THREAD_EOP_WAIT_ACK", \ -+ "STP_UCODE_DPROC_RUNNING", \ -+ "STC_TLB_MEM_WALKS", \ -+ "STC_REG4_UNUSED5", \ -+ "STC_PCI_MASTER_WRITES", \ -+ "STP_PCI_MASTER_READ_WAITING" \ -+} -+ -+/* Count reg 5 */ -+#define STP_INPUT_WAITING_NETWORK_DATA (0 << 20) -+#define STC_DMA_NON_CTX0_PKTS_REJECTED (1 << 20) -+#define STP_THREAD_WAITING_DATA (2 << 20) -+#define STP_UCODE_CPROC_RUNNING (3 << 20) -+#define STP_THREAD_TRANSMITTING_DATA (4 << 20) -+#define STP_PCI_WAITING_MAIN (5 << 20) -+#define STC_REG5_UNUSED6 (6 << 20) -+#define STC_REG5_UNUSED7 (7 << 20) -+ -+#define STATS_REG5_NAMES { \ -+ "STP_INPUT_WAITING_NETWORK_DATA", \ -+ "STC_DMA_NON_CTX0_PKTS_REJECTED", \ -+ "STP_THREAD_WAITING_DATA", \ -+ "STP_UCODE_CPROC_RUNNING", \ -+ "STP_THREAD_TRANSMITTING_DATA", \ -+ "STP_PCI_WAITING_MAIN", \ -+ "STC_REG5_UNUSED6", \ -+ "STC_REG5_UNUSED7" \ -+} -+ -+/* Count reg 6 */ -+#define STP_INPUT_WAITING_MEMORY (0 << 24) -+#define STC_DMA_CTX0_PKTS (1 << 24) -+#define STP_THREAD_WAITING_MEMORY (2 << 24) -+#define STP_UCODE_TPROC_RUNNING (3 << 24) -+#define STC_CACHE_HITS (4 << 24) -+#define STP_PCI_WAITING_ELAN (5 << 24) -+#define STC_REG6_UNUSED4 (6 << 24) -+#define STC_REG6_UNUSED7 (7 << 24) -+ -+#define STATS_REG6_NAMES { \ -+ "STP_INPUT_WAITING_MEMORY", \ -+ "STC_DMA_CTX0_PKTS", \ -+ "STP_THREAD_WAITING_MEMORY", \ -+ "STP_UCODE_TPROC_RUNNING", \ -+ "STC_CACHE_HITS", \ -+ "STP_PCI_WAITING_ELAN", \ -+ "STC_REG6_UNUSED4", \ -+ "STC_REG6_UNUSED7" \ -+} -+ -+/* Count reg 7 */ -+#define STC_INPUT_CTX_FILTER_FILL (0 << 28) -+#define STC_DMA_CTX0_PKTS_REJECTED (1 << 28) -+#define STP_THREAD_WAIT_NETWORK_BUSY (2 << 28) -+#define STP_UCODE_IPROC_RUNNING (3 << 28) -+#define STP_TLB_MEM_WALKING (4 << 28) -+#define STC_CACHE_ALLOC_MISSES (5 << 28) -+#define STP_PCI_DATA_TRANSFER (6 << 28) -+#define STC_REG7_UNUSED7 (7 << 28) -+ -+#define STATS_REG7_NAMES { \ -+ "STC_INPUT_CTX_FILTER_FILL", \ -+ "STC_DMA_CTX0_PKTS_REJECTED", \ -+ "STP_THREAD_WAIT_NETWORK_BUSY",\ -+ "STP_UCODE_IPROC_RUNNING", \ -+ "STP_TLB_MEM_WALKING", \ -+ "STC_CACHE_ALLOC_MISSES", \ -+ "STP_PCI_DATA_TRANSFER", \ -+ "STC_REG7_UNUSED7" \ -+} -+ -+#define STATS_REG_NAMES { \ -+ STATS_REG0_NAMES, \ -+ STATS_REG1_NAMES, \ -+ STATS_REG2_NAMES, \ -+ STATS_REG3_NAMES, \ -+ STATS_REG4_NAMES, \ -+ STATS_REG5_NAMES, \ -+ STATS_REG6_NAMES, \ -+ STATS_REG7_NAMES, \ -+} -+ -+extern const char *elan3_stats_names[8][8]; -+ -+#define ELAN3_STATS_NAME(COUNT, CONTROL) (elan3_stats_names[(COUNT)][(CONTROL) & 7]) -+ -+typedef volatile union e3_StatsControl -+{ -+ E3_uint32 StatsControl; -+ struct -+ { -+#if defined(__LITTLE_ENDIAN__) -+ E3_uint32 StatCont0:4; -+ E3_uint32 StatCont1:4; -+ E3_uint32 StatCont2:4; -+ E3_uint32 StatCont3:4; -+ E3_uint32 StatCont4:4; -+ E3_uint32 StatCont5:4; -+ E3_uint32 StatCont6:4; -+ E3_uint32 StatCont7:4; -+#else -+ E3_uint32 StatCont7:4; -+ E3_uint32 StatCont6:4; -+ E3_uint32 StatCont5:4; -+ E3_uint32 StatCont4:4; -+ E3_uint32 StatCont3:4; -+ E3_uint32 StatCont2:4; -+ E3_uint32 StatCont1:4; -+ E3_uint32 StatCont0:4; -+#endif -+ } s; -+} E3_StatsControl; -+ -+typedef volatile union e3_StatsCount -+{ -+ E3_uint64 ClockStat; -+ struct -+ { -+ E3_uint32 ClockLSW; /* read only */ -+ E3_uint32 StatsCount; -+ } s; -+} E3_StatsCount; -+ -+typedef volatile union e3_clock -+{ -+ E3_uint64 NanoSecClock; -+ struct -+ { -+ E3_uint32 ClockLSW; -+ E3_uint32 ClockMSW; -+ } s; -+} E3_Clock; -+#define E3_TIME( X ) ((X).NanoSecClock) -+ -+typedef volatile struct _E3_User_Regs -+{ -+ E3_StatsCount StatCounts[8]; -+ E3_StatsCount InstCount; -+ E3_uint32 pad0; -+ E3_StatsControl StatCont; -+ E3_Clock Clock; -+ E3_uint32 pad1[0x7ea]; -+} E3_User_Regs; -+ -+typedef volatile struct _E3_CommandPort -+{ -+ E3_Addr PutDma; /* 0x000 */ -+ E3_uint32 Pad1; -+ E3_Addr GetDma; /* 0x008 */ -+ E3_uint32 Pad2; -+ E3_Addr RunThread; /* 0x010 */ -+ E3_uint32 Pad3[3]; -+ E3_Addr WaitEvent0; /* 0x020 */ -+ E3_uint32 Pad4; -+ E3_Addr WaitEvent1; /* 0x028 */ -+ E3_uint32 Pad5; -+ E3_Addr SetEvent; /* 0x030 */ -+ E3_uint32 Pad6[3]; -+ E3_uint32 Pad7[0x7f0]; /* Fill out to an 8K page */ -+} E3_CommandPort; -+/* Should have the new structures for the top four pages of the elan3 space */ -+ -+#define E3_COMMANDPORT_SIZE (sizeof (E3_CommandPort)) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __ELAN3_ELANUREGS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/elanvp.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/elanvp.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/elanvp.h 2005-06-01 23:12:54.726419800 -0400 -@@ -0,0 +1,165 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_ELANVP_H -+#define _ELAN3_ELANVP_H -+ -+#ident "$Id: elanvp.h,v 1.45 2004/06/18 09:28:06 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/elanvp.h,v $ */ -+ -+#include -+#include -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* -+ * Context number allocation. -+ * [0-31] system contexts -+ * [32-63] hardware test -+ * [64-1023] available -+ * [1024-2047] RMS allocatable -+ * [2048-4095] kernel comms data contexts -+ */ -+#define ELAN3_KCOMM_CONTEXT_NUM 0x001 /* old kernel comms context (system) */ -+#define ELAN3_CM_CONTEXT_NUM 0x002 /* new cluster member ship comms context (system) */ -+#define ELAN3_MRF_CONTEXT_NUM 0x003 /* multi-rail kernel comms context */ -+#define ELAN3_DMARING_BASE_CONTEXT_NUM 0x010 /* 16 contexts for dma ring issue (system) */ -+#define ELAN3_DMARING_TOP_CONTEXT_NUM 0x01f -+ -+#define ELAN3_HWTEST_BASE_CONTEXT_NUM 0x020 /* reserved for hardware test */ -+#define ELAN3_HWTEST_TOP_CONTEXT_NUM 0x03f -+ -+#define ELAN3_KCOMM_BASE_CONTEXT_NUM 0x800 /* kernel comms data transfer contexts */ -+#define ELAN3_KCOMM_TOP_CONTEXT_NUM 0xfff -+ -+#define ELAN3_HWTEST_CONTEXT(ctx) ((ctx) >= ELAN3_HWTEST_BASE_CONTEXT_NUM && \ -+ (ctx) <= ELAN3_HWTEST_TOP_CONTEXT_NUM) -+ -+#define ELAN3_SYSTEM_CONTEXT(ctx) (((ctx) & SYS_CONTEXT_BIT) != 0 || \ -+ (ctx) < E3_NUM_CONTEXT_0 || \ -+ (ctx) >= ELAN3_KCOMM_BASE_CONTEXT_NUM) -+ -+/* Maximum number of virtual processes */ -+#define ELAN3_MAX_VPS (16384) -+ -+#define ELAN3_INVALID_PROCESS (0x7fffffff) /* A GUARANTEED invalid process # */ -+#define ELAN3_INVALID_NODE (0xFFFF) -+#define ELAN3_INVALID_CONTEXT (0xFFFF) -+ -+ -+ -+#if defined(__KERNEL__) && !defined(__ELAN3__) -+ -+/* -+ * Contexts are accessible via Elan capabilities, -+ * for each context that can be "attached" to there -+ * is a ELAN3_CTXT_INFO structure created by its -+ * "owner". This also "remembers" all remote -+ * segments that have "blazed" a trail to it. -+ * -+ * If the "owner" goes away the soft info is -+ * destroyed when it is no longer "attached" or -+ * "referenced" by a remote segment. -+ * -+ * If the owner changes the capability, then -+ * the soft info must be not "referenced" or -+ * "attached" before a new process can "attach" -+ * to it. -+ */ -+ -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::InfoLock, -+ elan3_info::Next elan3_info::Prev elan3_info::Device elan3_info::Owner -+ elan3_info::Capability elan3_info::AttachedCapability elan3_info::Context)) -+_NOTE(MUTEX_PROTECTS_DATA(elan3_dev::IntrLock, -+ elan3_info::Nacking elan3_info::Disabled)) -+_NOTE(DATA_READABLE_WITHOUT_LOCK(elan3_info::Context elan3_info::Device elan3_info::Capability)) -+ -+#endif /* __KERNEL__ */ -+ -+#define LOW_ROUTE_PRIORITY 0 -+#define HIGH_ROUTE_PRIORITY 1 -+ -+#define DEFAULT_ROUTE_TIMEOUT 3 -+#define DEFAULT_ROUTE_PRIORITY LOW_ROUTE_PRIORITY -+ -+ -+/* a small route is 4 flits (8 bytes), a big route */ -+/* is 8 flits (16 bytes) - each packed route is 4 bits */ -+/* so giving us a maximum of 28 as flit0 does not contain */ -+/* packed routes */ -+#define MAX_FLITS 8 -+#define MAX_PACKED 28 -+ -+/* bit definitions for 64 bit route pointer */ -+#define ROUTE_VALID (1ULL << 63) -+#define ROUTE_PTR (1ULL << 62) -+#define ROUTE_CTXT_SHIFT 48 -+#define ROUTE_PTR_MASK ((1ull << ROUTE_CTXT_SHIFT)-1) -+#define ROUTE_GET_CTXT ((VAL >> ROUTE_CTXT_SHIFT) & 0x3fff ) -+ -+#define SMALL_ROUTE(flits, context) (((E3_uint64) (flits)[0] << 0) | ((E3_uint64) (flits)[1] << 16) | \ -+ ((E3_uint64) (flits)[2] << 32) | ((E3_uint64) (context) << ROUTE_CTXT_SHIFT) | \ -+ ROUTE_VALID) -+ -+#define BIG_ROUTE_PTR(paddr, context) ((E3_uint64) (paddr) | ((E3_uint64) context << ROUTE_CTXT_SHIFT) | ROUTE_VALID | ROUTE_PTR) -+ -+#define BIG_ROUTE0(flits) (((E3_uint64) (flits)[0] << 0) | ((E3_uint64) (flits)[1] << 16) | \ -+ ((E3_uint64) (flits)[2] << 32) | ((E3_uint64) (flits)[3] << 48)) -+#define BIG_ROUTE1(flits) (((E3_uint64) (flits)[4] << 0) | ((E3_uint64) (flits)[5] << 16) | \ -+ ((E3_uint64) (flits)[6] << 32) | ((E3_uint64) (flits)[7] << 48)) -+ -+ -+/* defines for first flit of a route */ -+#define FIRST_HIGH_PRI (1 << 15) -+#define FIRST_AGE(Val) ((Val) << 11) -+#define FIRST_TIMEOUT(Val) ((Val) << 9) -+#define FIRST_PACKED(X) ((X) << 7) -+#define FIRST_ROUTE(Val) (Val) -+#define FIRST_ADAPTIVE (0x30) -+#define FIRST_BCAST_TREE (0x20) -+#define FIRST_MYLINK (0x10) -+#define FIRST_BCAST(Top, Bot) (0x40 | ((Top) << 3) | (Bot)) -+ -+/* defines for 3 bit packed entries for subsequent flits */ -+#define PACKED_ROUTE(Val) (8 | (Val)) -+#define PACKED_ADAPTIVE (3) -+#define PACKED_BCAST_TREE (2) -+#define PACKED_MYLINK (1) -+#define PACKED_BCAST0(Top,Bot) (4 | (Bot & 3)) -+#define PACKED_BCAST1(Top,Bot) ((Top << 1) | (Bot >> 2)) -+ -+/* ---------------------------------------------------------- -+ * elan3_route functions -+ * return ELAN3_ROUTE_xxx codes -+ * ---------------------------------------------------------- */ -+ -+#define ELAN3_ROUTE_SUCCESS (0x00) -+#define ELAN3_ROUTE_SYSCALL_FAILED (0x01) -+#define ELAN3_ROUTE_INVALID (0x02) -+#define ELAN3_ROUTE_TOO_LONG (0x04) -+#define ELAN3_ROUTE_LOAD_FAILED (0x08) -+#define ELAN3_ROUTE_PROC_RANGE (0x0f) -+#define ELAN3_ROUTE_INVALID_LEVEL (0x10) -+#define ELAN3_ROUTE_OCILATES (0x20) -+#define ELAN3_ROUTE_WRONG_DEST (0x40) -+#define ELAN3_ROUTE_TURN_LEVEL (0x80) -+#define ELAN3_ROUTE_NODEID_UNKNOWN (0xf0) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _ELAN3_ELANVP_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/events.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/events.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/events.h 2005-06-01 23:12:54.726419800 -0400 -@@ -0,0 +1,183 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_EVENTS_H -+#define _ELAN3_EVENTS_H -+ -+#ident "$Id: events.h,v 1.45 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/events.h,v $*/ -+ -+/* -+ * Alignments for events, event queues and blockcopy blocks. -+ */ -+#define E3_EVENT_ALIGN (8) -+#define E3_QUEUE_ALIGN (32) -+#define E3_BLK_ALIGN (64) -+#define E3_BLK_SIZE (64) -+#define E3_BLK_PATTERN (0xfeedface) -+ -+#define E3_EVENT_FREE ((0 << 4) | EV_WCOPY) -+#define E3_EVENT_PENDING ((1 << 4) | EV_WCOPY) -+#define E3_EVENT_ACTIVE ((2 << 4) | EV_WCOPY) -+#define E3_EVENT_FIRED ((3 << 4) | EV_WCOPY) -+#define E3_EVENT_FAILED ((4 << 4) | EV_WCOPY) -+#define E3_EVENT_DONE ((5 << 4) | EV_WCOPY) -+#define E3_EVENT_PRIVATE ((6 << 4) | EV_WCOPY) -+ -+/* -+ * Event values and masks -+ * -+ * Block Copy event xxxxxxxxxxxxxxxx1 -+ * Chained event 30 bit ptr ....0x -+ * Event interrupt 29 bit cookie 01x -+ * Dma event 28 bit ptr 011x -+ * thread event 28 bit ptr 111x -+ */ -+#define EV_CLEAR (0x00000000) -+#define EV_TYPE_BCOPY (0x00000001) -+#define EV_TYPE_CHAIN (0x00000000) -+#define EV_TYPE_EVIRQ (0x00000002) -+#define EV_TYPE_DMA (0x00000006) -+#define EV_TYPE_THREAD (0x0000000e) -+ -+#define EV_TYPE_BCOPY_BYTE (0) -+#define EV_TYPE_BCOPY_HWORD (1) -+#define EV_TYPE_BCOPY_WORD (2) -+#define EV_TYPE_BCOPY_DWORD (3) -+ -+/* -+ * Data type is in the lowest two bits of the Dest pointer. -+ */ -+#define EV_BCOPY_DTYPE_MASK (3) -+#define EV_WCOPY (1) /* [DestWord] = Source */ -+#define EV_BCOPY (0) /* [DestBlock] = [SourceBlock] */ -+ -+#define EV_TYPE_MASK (0x0000000e) -+#define EV_TYPE_MASK_BCOPY (0x00000001) -+#define EV_TYPE_MASK_CHAIN (0x00000002) -+#define EV_TYPE_MASK_EVIRQ (0x00000006) -+#define EV_TYPE_MASK_DMA (0x0000000e) -+#define EV_TYPE_MASK_THREAD (0x0000000e) -+#define EV_TYPE_MASK2 (0x0000000f) -+ -+/* -+ * Min/Max size for Elan queue entries -+ */ -+#define E3_QUEUE_MIN E3_BLK_SIZE -+#define E3_QUEUE_MAX (E3_BLK_SIZE * 5) -+ -+/* -+ * Elan queue state bits -+ */ -+#define E3_QUEUE_FULL (1<<0) -+#define E3_QUEUE_LOCKED (1<<8) -+ -+#ifndef _ASM -+ -+typedef union _E3_Event -+{ -+ E3_uint64 ev_Int64; -+ struct { -+ volatile E3_int32 u_Count; -+ E3_uint32 u_Type; -+ } ev_u; -+} E3_Event; -+ -+typedef union _E3_BlockCopyEvent -+{ -+ E3_uint64 ev_ForceAlign; -+ struct E3_BlockCopyEvent_u { -+ volatile E3_int32 u_Count; -+ E3_uint32 u_Type; -+ E3_Addr u_Source; -+ E3_Addr u_Dest; /* lowest bits are the data type for endian conversion */ -+ } ev_u; -+} E3_BlockCopyEvent; -+ -+#define ev_Type ev_u.u_Type -+#define ev_Count ev_u.u_Count -+#define ev_Source ev_u.u_Source -+#define ev_Dest ev_u.u_Dest -+ -+typedef union _E3_WaitEvent0 -+{ -+ E3_uint64 we_ForceAlign; -+ struct { -+ E3_Addr u_EventLoc; -+ E3_int32 u_WaitCount; -+ } we_u; -+} E3_WaitEvent0; -+#define we_EventLoc we_u.u_EventLoc -+#define we_WaitCount we_u.u_WaitCount -+ -+typedef union _E3_Event_Blk -+{ -+ E3_uint8 eb_Bytes[E3_BLK_SIZE]; -+ E3_uint32 eb_Int32[E3_BLK_SIZE/sizeof (E3_uint32)]; -+ E3_uint64 eb_Int64[E3_BLK_SIZE/sizeof (E3_uint64)]; -+} E3_Event_Blk; -+ -+/* We make eb_done the last word of the blk -+ * so that we can guarantee the rest of the blk is -+ * correct when this value is set. -+ * However, when the TPORT code copies the envelope -+ * info into the blk, it uses a dword endian type. -+ * Thus we must correct for this when initialising -+ * the pattern in the Elan SDRAM blk (eeb_done) -+ */ -+#define eb_done eb_Int32[15] -+#define eeb_done eb_Int32[15^WordEndianFlip] -+ -+#define EVENT_WORD_READY(WORD) (*((volatile E3_uint32 *) WORD) != 0) -+#define EVENT_BLK_READY(BLK) (((volatile E3_Event_Blk *) (BLK))->eb_done != 0) -+#define EVENT_READY(EVENT) (((volatile E3_Event *) (EVENT))->ev_Count <= 0) -+ -+#define ELAN3_WAIT_EVENT (0) -+#define ELAN3_POLL_EVENT (-1) -+ -+#define SETUP_EVENT_TYPE(ptr,typeval) (((unsigned long)(ptr)) | (typeval)) -+ -+#define E3_RESET_BCOPY_BLOCK(BLK) \ -+ do { \ -+ (BLK)->eb_done = 0; \ -+ } while (0) -+ -+typedef struct e3_queue -+{ -+ volatile E3_uint32 q_state; /* queue is full=bit0, queue is locked=bit8 */ -+ volatile E3_Addr q_bptr; /* block aligned ptr to current back item */ -+ E3_uint32 q_size; /* size of queue item; 0x1 <= size <= (0x40 * 5) */ -+ E3_Addr q_top; /* block aligned ptr to last queue item */ -+ E3_Addr q_base; /* block aligned ptr to first queue item */ -+ volatile E3_Addr q_fptr; /* block aligned ptr to current front item */ -+ E3_Event q_event; /* queue event */ -+} E3_Queue; -+ -+typedef struct e3_blockcopy_queue -+{ -+ volatile E3_uint32 q_state; /* queue is full=bit0, queue is locked=bit8 */ -+ volatile E3_Addr q_bptr; /* block aligned ptr to current back item */ -+ E3_uint32 q_size; /* size of queue item; 0x1 <= size <= (0x40 * 5) */ -+ E3_Addr q_top; /* block aligned ptr to last queue item */ -+ E3_Addr q_base; /* block aligned ptr to first queue item */ -+ volatile E3_Addr q_fptr; /* block aligned ptr to current front item */ -+ E3_BlockCopyEvent q_event; /* queue event */ -+ E3_uint32 q_pad[6]; -+} E3_BlockCopyQueue; -+ -+#define E3_QUEUE_EVENT_OFFSET 24 -+#define QUEUE_FULL(Q) ((Q)->q_state & E3_QUEUE_FULL) -+ -+#endif /* ! _ASM */ -+ -+#endif /* _ELAN3_EVENTS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/intrinsics.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/intrinsics.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/intrinsics.h 2005-06-01 23:12:54.727419648 -0400 -@@ -0,0 +1,320 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_INTRINSICS_H -+#define _ELAN3_INTRINSICS_H -+ -+#ident "$Id: intrinsics.h,v 1.35 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/intrinsics.h,v $ */ -+ -+#include -+#include -+ -+/* -+ * This file contains definitions of the macros for accessing the QSW -+ * specific instructions, as if they were functions. -+ * The results from the function -+ */ -+ -+#define C_ACK_OK 0 /* return from c_close() */ -+#define C_ACK_TESTFAIL 1 /* return from c_close() */ -+#define C_ACK_DISCARD 2 /* return from c_close() */ -+#define C_ACK_ERROR 3 /* return from c_close() */ -+ -+/* -+ * Elan asi's for tproc block accesses -+ */ -+#define EASI_BYTE 0 -+#define EASI_HALF 1 -+#define EASI_WORD 2 -+#define EASI_DOUBLE 3 -+ -+#if defined(__ELAN3__) && !defined (_ASM) -+ -+extern inline void c_abort(void) -+{ -+ asm volatile (".word 0x0000 ! die you thread you " : : ); -+} -+ -+extern inline void c_suspend(void) -+{ -+ asm volatile ( -+ "set 1f, %%i7 ! RevB bug fix. get address of the wakeup inst\n" -+ "andcc %%i7,0x4,%%g0 ! RevB bug fix. check alignment\n" -+ "bne 1f ! RevB bug fix. jump to other alignment\n" -+ "nop ! RevB bug fix. delay slot\n" -+ "ldd [%%i7],%%i6 ! RevB bug fix. data fetch of instructions\n" -+ "suspend ! do the real suspend\n" -+ "1: add %%i7,5*4,%%i7 ! RevB bug fix. Point i7 to first ldblock\n" -+ "ldd [%%i7],%%i6 ! RevB bug fix. data fetch of instructions\n" -+ "suspend ! do the real suspend\n" : : ); -+} -+ -+extern inline int c_close(void) -+{ -+ register int rc asm("o0"); -+ -+ asm volatile ("close %0" : "=r" (rc) : ); -+ -+ return (rc); -+} -+ -+extern inline int c_close_cookie(volatile E3_uint32 *cookiep, E3_uint32 next) -+{ -+ register int rc asm("o0"); -+ -+ asm volatile ("close %0 ! close the packet\n" -+ "bz,a 1f ! ack received\n" -+ "st %1, [%2] ! update cookie on ack\n" -+ "1: ! label for not-ack\n" -+ : "=r" (rc) : "r" (next), "r" (cookiep)); -+ -+ return (rc); -+} -+ -+extern inline void c_break_busywait(void) -+{ -+ asm volatile ( -+ "breaktest ! test to see if break necessary\n" -+ "bpos 1f ! no other thread ready\n" -+ "nop ! delay slot\n" -+ "sub %%sp,3*8*4,%%sp ! Space to save the registers\n" -+ "stblock %%g0,[%%sp+0] ! save the globals\n" -+ "stblock %%i0,[%%sp+8*4] ! save the ins\n" -+ "stblock %%l0,[%%sp+16*4] ! save the locals\n" -+ "set 2f, %%i7 ! RevB bug fix. get address of the wakeup inst\n" -+ "andcc %%i7,0x4,%%g0 ! RevB bug fix. check alignment\n" -+ "bne 3f ! RevB bug fix. jump to other alignment\n" -+ "nop ! RevB bug fix. delay slot\n" -+ "ldd [%%i7],%%i6 ! RevB bug fix. data fetch of instructions\n" -+ "break ! do the real break\n" -+ "2: b 4f ! RevB bug fix. Branch over other alignment case\n" -+ " ldblock [%%sp+16*4],%%l0 ! RevB bug fix. restore locals in delay slot\n" -+ "3: add %%i7,5*4,%%i7 ! RevB bug fix. Point i7 to first ldblock\n" -+ "ldd [%%i7],%%i6 ! RevB bug fix. data fetch of instructions\n" -+ "break ! do the real break\n" -+ "ldblock [%%sp+16*4],%%l0 ! restore locals\n" -+ "4: ldblock [%%sp+8*4], %%i0 ! restore ins\n" -+ "ldblock [%%sp+0],%%g0 ! restore globals\n" -+ "add %%sp,3*8*4,%%sp ! restore stack pointer\n" -+ "1: " : : ); -+} -+ -+extern inline void c_break(void) -+{ -+ asm volatile ( -+ "breaktest ! test to see if break necessary\n" -+ "bne 1f ! haven't exceeded our inst count yet\n" -+ "nop ! delay slot\n" -+ "sub %%sp,3*8*4,%%sp ! Space to save the registers\n" -+ "stblock %%g0,[%%sp+0] ! save the globals\n" -+ "stblock %%i0,[%%sp+8*4] ! save the ins\n" -+ "stblock %%l0,[%%sp+16*4] ! save the locals\n" -+ "set 2f, %%i7 ! RevB bug fix. get address of the wakeup inst\n" -+ "andcc %%i7,0x4,%%g0 ! RevB bug fix. check alignment\n" -+ "bne 3f ! RevB bug fix. jump to other alignment\n" -+ "nop ! RevB bug fix. delay slot\n" -+ "ldd [%%i7],%%i6 ! RevB bug fix. data fetch of instructions\n" -+ "break ! do the real break\n" -+ "2: b 4f ! RevB bug fix. Branch over other alignment case\n" -+ " ldblock [%%sp+16*4],%%l0 ! RevB bug fix. restore locals in delay slot\n" -+ "3: add %%i7,5*4,%%i7 ! RevB bug fix. Point i7 to first ldblock\n" -+ "ldd [%%i7],%%i6 ! RevB bug fix. data fetch of instructions\n" -+ "break ! do the real break\n" -+ "ldblock [%%sp+16*4],%%l0 ! restore locals\n" -+ "4: ldblock [%%sp+8*4], %%i0 ! restore ins\n" -+ "ldblock [%%sp+0],%%g0 ! restore globals\n" -+ "add %%sp,3*8*4,%%sp ! restore stack pointer\n" -+ "1: " : : ); -+} -+ -+extern inline void c_open( const int arg ) -+{ -+ asm volatile ("open %0" : : "r" (arg) ); -+ asm volatile ("nop; nop; nop; nop"); -+ asm volatile ("nop; nop; nop; nop"); -+ asm volatile ("nop; nop; nop; nop"); -+ asm volatile ("nop; nop; nop; nop"); -+ asm volatile ("nop; nop; nop; nop"); -+ asm volatile ("nop; nop; nop; nop"); -+} -+ -+extern inline void c_waitevent( volatile E3_Event *const ptr, -+ const int count) -+{ -+ register volatile E3_Event *a_unlikely asm("o0") = ptr; -+ register int a_very_unlikely asm("o1") = count; -+ -+ asm volatile ( -+ "sub %%sp,1*8*4,%%sp ! Space to save the registers\n" -+ "stblock %%i0,[%%sp+0] ! save the ins\n" -+ "set 2f, %%i7 ! RevB bug fix. get address of the wakeup inst\n" -+ "andcc %%i7,0x4,%%g0 ! RevB bug fix. check alignment\n" -+ "bne 3f ! RevB bug fix. jump to other alignment\n" -+ "nop ! RevB bug fix. delay slot\n" -+ "ldd [%%i7],%%i4 ! RevB bug fix. data fetch of instructions\n" -+ "waitevent ! do the business\n" -+ "2: b 4f ! RevB bug fix. Branch over other alignment case\n" -+ " ldblock [%%sp+0],%%i0 ! RevB bug fix. restore ins in delay slot\n" -+ "3: add %%i7,5*4,%%i7 ! RevB bug fix. Point i7 to first ldblock\n" -+ "ldd [%%i7],%%i4 ! RevB bug fix. data fetch of instructions\n" -+ "waitevent ! do the business\n" -+ "ldblock [%%sp+0],%%i0 ! restore ins\n" -+ "4: add %%sp,1*8*4,%%sp ! restore stack pointer\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (a_unlikely), "r" (a_very_unlikely) -+ : /* clobbered */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", -+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7" ); -+ -+} -+ -+#define c_sendtrans0(type,dest) \ -+ asm volatile ("sendtrans %0, %%g0, %1" : : "i" (type), "r" (dest)) -+ -+#define c_sendtrans1(type,dest,arg) \ -+ asm volatile ("sendtrans %0, %2, %1" : : "i" (type), "r" (dest), "r" (arg)) -+ -+#define c_sendtrans2(type,dest,arg1,arg2) \ -+ do { \ -+ register const unsigned long a_unlikely_1 asm("o4") = arg1; \ -+ register const unsigned long a_unlikely_2 asm("o5") = arg2; \ -+ asm volatile ("sendtrans %0, %2, %1" \ -+ : : "i" (type), "r" (dest), "r" (a_unlikely_1), "r" (a_unlikely_2)); \ -+ } while(0) -+ -+#define c_sendmem(type,dest,ptr) \ -+ asm volatile ("sendtrans %0, [%2], %1" : : "i" (type), "r" (dest), "r" (ptr)) -+ -+/* Copy a single 64-byte block (src blk is read using a BYTE endian type) */ -+extern inline void elan3_copy64b(void *src, void *dst) -+{ -+ /* Copy 64 bytes using ldblock/stblock -+ * We save and restore the locals/ins because if we don't gcc -+ * really makes a bad job of optimisising the rest of the thread code! -+ * -+ * We force the parameters in g5, g6 so that they aren't -+ * trashed by the loadblk32 into the locals/ins -+ */ -+ register void *tmp1 asm("g5") = src; -+ register void *tmp2 asm("g6") = dst; -+ -+ asm volatile ( -+ "and %%sp,63,%%g7 ! Calculate stack alignment\n" -+ "sub %%sp,2*8*4,%%sp ! Space to save the registers\n" -+ "sub %%sp,%%g7,%%sp ! align stack\n" -+ "stblock64 %%l0,[%%sp] ! save the locals and ins\n" -+ "ldblock64a [%0]%2,%%l0 ! load 64-byte block into locals/ins\n" -+ "stblock64a %%l0,[%1]%2 ! store 64-byte block from local/ins\n" -+ "ldblock64 [%%sp],%%l0 ! restore locals and ins\n" -+ "add %%sp,%%g7, %%sp ! undo alignment\n" -+ "add %%sp,2*8*4,%%sp ! restore stack pointer\n" -+ : /* outputs */ -+ : /* inputs */ "r" (tmp1), "r" (tmp2), "n" (EASI_BYTE) -+ : /* clobbered */ "g5", "g6", "g7" ); -+} -+ -+/* Copy a single 64-byte block (src blk is read using a WORD endian type) */ -+extern inline void elan3_copy64w(void *src, void *dst) -+{ -+ /* Copy 64 bytes using ldblock/stblock -+ * We save and restore the locals/ins because if we don't gcc -+ * really makes a bad job of optimisising the rest of the thread code! -+ * -+ * We force the parameters in g5, g6 so that they aren't -+ * trashed by the loadblk32 into the locals/ins -+ */ -+ register void *tmp1 asm("g5") = src; -+ register void *tmp2 asm("g6") = dst; -+ -+ asm volatile ( -+ "and %%sp,63,%%g7 ! Calculate stack alignment\n" -+ "sub %%sp,2*8*4,%%sp ! Space to save the registers\n" -+ "sub %%sp,%%g7,%%sp ! align stack\n" -+ "stblock64 %%l0,[%%sp] ! save the locals and ins\n" -+ "ldblock64a [%0]%2,%%l0 ! load 64-byte block into locals/ins\n" -+ "stblock64a %%l0,[%1]%2 ! store 64-byte block from local/ins\n" -+ "ldblock64 [%%sp],%%l0 ! restore locals and ins\n" -+ "add %%sp,%%g7, %%sp ! undo alignment\n" -+ "add %%sp,2*8*4,%%sp ! restore stack pointer\n" -+ : /* outputs */ -+ : /* inputs */ "r" (tmp1), "r" (tmp2), "n" (EASI_WORD) -+ : /* clobbered */ "g5", "g6", "g7" ); -+} -+ -+/* Read a 64-bit value with a WORD (32-bit) endian type */ -+extern inline E3_uint64 elan3_read64w( volatile E3_uint64 *const ptr ) -+{ -+ E3_uint64 result; -+ -+ asm volatile ( -+ "ldblock8a [%1]%2, %0\n" -+ : /* outputs */ "=r" (result) -+ : /* inputs */ "r" (ptr), "n" (EASI_WORD) ); -+ -+ return( result ); -+} -+ -+/* Read a 64-bit value with a DOUBLEWORD (64-bit) endian type */ -+extern inline E3_uint64 elan3_read64dw( volatile E3_uint64 *const ptr ) -+{ -+ E3_uint64 result; -+ -+ asm volatile ( -+ "ldblock8a [%1]%2, %0\n" -+ : /* outputs */ "=r" (result) -+ : /* inputs */ "r" (ptr), "n" (EASI_DOUBLE) ); -+ -+ return( result ); -+} -+ -+/* Write a 32-bit value with a WORD (32-bit) endian type */ -+extern inline void elan3_write64w( volatile E3_uint64 *const ptr, E3_uint64 value ) -+{ -+ asm volatile ( -+ "stblock8a %1, [%0]%2\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (ptr), "r" (value), "n" (EASI_WORD) ); -+} -+ -+/* Write a 64-bit value with a DOUBLEWORD (64-bit) endian type */ -+extern inline void elan3_write64dw( volatile E3_uint64 *const ptr, E3_uint64 value ) -+{ -+ asm volatile ( -+ "stblock8a %1, [%0]%2\n" -+ : /* no outputs */ -+ : /* inputs */ "r" (ptr), "r" (value), "n" (EASI_DOUBLE) ); -+} -+ -+extern inline E3_uint32 c_swap(volatile E3_uint32 *source, E3_uint32 result) -+{ -+ asm volatile("swap [%1],%0\n" -+ : "=r" (result) -+ : "r" (source) ,"0" (result) -+ : "memory"); -+ return result; -+} -+ -+extern inline E3_uint32 c_swap_save(volatile E3_uint32 *source, const E3_uint32 result) -+{ -+ register E3_uint32 a_unlikely; -+ asm volatile("" : "=r" (a_unlikely) : ); -+ -+ asm volatile("mov %2,%0; swap [%1],%0\n" -+ : "=r" (a_unlikely) -+ : "r" (source) ,"r" (result), "0" (a_unlikely) -+ : "memory"); -+ return a_unlikely; -+} -+#endif /* (__ELAN3__) && !(_ASM) */ -+ -+#endif /* _ELAN3_INTRINSICS_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/minames.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/minames.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/minames.h 2005-06-01 23:12:54.728419496 -0400 -@@ -0,0 +1,256 @@ -+{MI_WaitForRemoteDescRead, "MI_WaitForRemoteDescRead"}, -+{MI_WaitForRemoteDescRead2, "MI_WaitForRemoteDescRead2"}, -+{MI_WaitForRemoteDescRead2_seq1, "MI_WaitForRemoteDescRead2_seq1"}, -+{MI_SendRemoteDmaRoutes, "MI_SendRemoteDmaRoutes"}, -+{MI_IProcTrapped, "MI_IProcTrapped"}, -+{MI_DProcTrapped, "MI_DProcTrapped"}, -+{MI_CProcTrapped, "MI_CProcTrapped"}, -+{MI_TProcTrapped, "MI_TProcTrapped"}, -+{MI_TestWhichDmaQueue, "MI_TestWhichDmaQueue"}, -+{MI_TestWhichDmaQueue_seq1, "MI_TestWhichDmaQueue_seq1"}, -+{MI_InputRemoteDmaUpdateBPtr, "MI_InputRemoteDmaUpdateBPtr"}, -+{MI_FixupQueueContextAndRemoteBit, "MI_FixupQueueContextAndRemoteBit"}, -+{MI_FixupQueueContextAndRemoteBit_seq1, "MI_FixupQueueContextAndRemoteBit_seq1"}, -+{MI_FixupQueueContextAndRemoteBit_seq2, "MI_FixupQueueContextAndRemoteBit_seq2"}, -+{MI_FixupQueueContextAndRemoteBit_seq3, "MI_FixupQueueContextAndRemoteBit_seq3"}, -+{MI_FixupQueueContextAndRemoteBit_seq4, "MI_FixupQueueContextAndRemoteBit_seq4"}, -+{MI_RunDmaCommand, "MI_RunDmaCommand"}, -+{MI_DoSendRemoteDmaDesc, "MI_DoSendRemoteDmaDesc"}, -+{MI_DequeueNonSysCntxDma, "MI_DequeueNonSysCntxDma"}, -+{MI_WaitForRemoteDescRead1, "MI_WaitForRemoteDescRead1"}, -+{MI_RemoteDmaCommand, "MI_RemoteDmaCommand"}, -+{MI_WaitForRemoteRoutes, "MI_WaitForRemoteRoutes"}, -+{MI_DequeueSysCntxDma, "MI_DequeueSysCntxDma"}, -+{MI_ExecuteDmaDescriptorForQueue, "MI_ExecuteDmaDescriptorForQueue"}, -+{MI_ExecuteDmaDescriptor1, "MI_ExecuteDmaDescriptor1"}, -+{MI_ExecuteDmaDescriptor1_seq1, "MI_ExecuteDmaDescriptor1_seq1"}, -+{MI_ExecuteDmaDescriptor1_seq2, "MI_ExecuteDmaDescriptor1_seq2"}, -+{MI_ExecuteDmaDescriptor1_seq3, "MI_ExecuteDmaDescriptor1_seq3"}, -+{MI_GetNewSizeInProg, "MI_GetNewSizeInProg"}, -+{MI_GetNewSizeInProg_seq1, "MI_GetNewSizeInProg_seq1"}, -+{MI_FirstBlockRead, "MI_FirstBlockRead"}, -+{MI_ExtraFirstBlockRead, "MI_ExtraFirstBlockRead"}, -+{MI_UnimplementedError, "MI_UnimplementedError"}, -+{MI_UpdateDescriptor, "MI_UpdateDescriptor"}, -+{MI_UpdateDescriptor_seq1, "MI_UpdateDescriptor_seq1"}, -+{MI_UpdateDescriptor_seq2, "MI_UpdateDescriptor_seq2"}, -+{MI_UpdateDescriptor_seq3, "MI_UpdateDescriptor_seq3"}, -+{MI_UpdateDescriptor_seq4, "MI_UpdateDescriptor_seq4"}, -+{MI_UpdateDescriptor_seq5, "MI_UpdateDescriptor_seq5"}, -+{MI_GetNextSizeInProg, "MI_GetNextSizeInProg"}, -+{MI_DoStopThisDma, "MI_DoStopThisDma"}, -+{MI_DoStopThisDma_seq1, "MI_DoStopThisDma_seq1"}, -+{MI_GenNewBytesToRead, "MI_GenNewBytesToRead"}, -+{MI_WaitForEventReadTy1, "MI_WaitForEventReadTy1"}, -+{MI_WaitUpdateEvent, "MI_WaitUpdateEvent"}, -+{MI_WaitUpdateEvent_seq1, "MI_WaitUpdateEvent_seq1"}, -+{MI_DoSleepOneTickThenRunable, "MI_DoSleepOneTickThenRunable"}, -+{MI_RunEvent, "MI_RunEvent"}, -+{MI_EnqueueThread, "MI_EnqueueThread"}, -+{MI_CheckContext0, "MI_CheckContext0"}, -+{MI_EnqueueDma, "MI_EnqueueDma"}, -+{MI_CprocTrapping, "MI_CprocTrapping"}, -+{MI_CprocTrapping_seq1, "MI_CprocTrapping_seq1"}, -+{MI_WaitForRemoteRoutes1, "MI_WaitForRemoteRoutes1"}, -+{MI_SetEventCommand, "MI_SetEventCommand"}, -+{MI_DoSetEvent, "MI_DoSetEvent"}, -+{MI_DoRemoteSetEventNowOrTrapQueueingDma, "MI_DoRemoteSetEventNowOrTrapQueueingDma"}, -+{MI_DoRemoteSetEventNowOrTrapQueueingDma_seq1, "MI_DoRemoteSetEventNowOrTrapQueueingDma_seq1"}, -+{MI_SendRemoteDmaRoutes2, "MI_SendRemoteDmaRoutes2"}, -+{MI_WaitForRemoteRoutes2, "MI_WaitForRemoteRoutes2"}, -+{MI_WaitEventCommandTy0, "MI_WaitEventCommandTy0"}, -+{MI_DequeueNonSysCntxDma2, "MI_DequeueNonSysCntxDma2"}, -+{MI_WaitEventCommandTy1, "MI_WaitEventCommandTy1"}, -+{MI_WaitEventCommandTy1_seq1, "MI_WaitEventCommandTy1_seq1"}, -+{MI_DequeueNonSysCntxThread, "MI_DequeueNonSysCntxThread"}, -+{MI_DequeueSysCntxDma1, "MI_DequeueSysCntxDma1"}, -+{MI_DequeueSysCntxThread, "MI_DequeueSysCntxThread"}, -+{MI_TestNonSysCntxDmaQueueEmpty, "MI_TestNonSysCntxDmaQueueEmpty"}, -+{MI_TestNonSysCntxDmaQueueEmpty_seq1, "MI_TestNonSysCntxDmaQueueEmpty_seq1"}, -+{MI_TestNonSysCntxDmaQueueEmpty_seq2, "MI_TestNonSysCntxDmaQueueEmpty_seq2"}, -+{MI_RunThreadCommand, "MI_RunThreadCommand"}, -+{MI_SetEventWaitForLastAcess, "MI_SetEventWaitForLastAcess"}, -+{MI_SetEventReadWait, "MI_SetEventReadWait"}, -+{MI_SetEventReadWait_seq1, "MI_SetEventReadWait_seq1"}, -+{MI_TestEventType, "MI_TestEventType"}, -+{MI_TestEventType_seq1, "MI_TestEventType_seq1"}, -+{MI_TestEventBit2, "MI_TestEventBit2"}, -+{MI_DmaDescOrBlockCopyOrChainedEvent, "MI_DmaDescOrBlockCopyOrChainedEvent"}, -+{MI_RunThread, "MI_RunThread"}, -+{MI_RunThread1, "MI_RunThread1"}, -+{MI_RunThread1_seq1, "MI_RunThread1_seq1"}, -+{MI_IncDmaSysCntxBPtr, "MI_IncDmaSysCntxBPtr"}, -+{MI_IncDmaSysCntxBPtr_seq1, "MI_IncDmaSysCntxBPtr_seq1"}, -+{MI_IncDmaSysCntxBPtr_seq2, "MI_IncDmaSysCntxBPtr_seq2"}, -+{MI_WaitForCntxDmaDescRead, "MI_WaitForCntxDmaDescRead"}, -+{MI_FillInContext, "MI_FillInContext"}, -+{MI_FillInContext_seq1, "MI_FillInContext_seq1"}, -+{MI_WriteNewDescToQueue, "MI_WriteNewDescToQueue"}, -+{MI_WriteNewDescToQueue_seq1, "MI_WriteNewDescToQueue_seq1"}, -+{MI_TestForQueueWrap, "MI_TestForQueueWrap"}, -+{MI_TestForQueueWrap_seq1, "MI_TestForQueueWrap_seq1"}, -+{MI_TestQueueIsFull, "MI_TestQueueIsFull"}, -+{MI_TestQueueIsFull_seq1, "MI_TestQueueIsFull_seq1"}, -+{MI_TestQueueIsFull_seq2, "MI_TestQueueIsFull_seq2"}, -+{MI_CheckPsychoShitFixup, "MI_CheckPsychoShitFixup"}, -+{MI_PsychoShitFixupForcedRead, "MI_PsychoShitFixupForcedRead"}, -+{MI_PrepareDMATimeSlice, "MI_PrepareDMATimeSlice"}, -+{MI_PrepareDMATimeSlice_seq1, "MI_PrepareDMATimeSlice_seq1"}, -+{MI_TProcRestartFromTrapOrTestEventBit2, "MI_TProcRestartFromTrapOrTestEventBit2"}, -+{MI_TProcRestartFromTrapOrTestEventBit2_seq1, "MI_TProcRestartFromTrapOrTestEventBit2_seq1"}, -+{MI_WaitForGlobalsRead, "MI_WaitForGlobalsRead"}, -+{MI_WaitForNPCRead, "MI_WaitForNPCRead"}, -+{MI_EventInterrupt, "MI_EventInterrupt"}, -+{MI_EventInterrupt_seq1, "MI_EventInterrupt_seq1"}, -+{MI_EventInterrupt_seq2, "MI_EventInterrupt_seq2"}, -+{MI_EventInterrupt_seq3, "MI_EventInterrupt_seq3"}, -+{MI_TestSysCntxDmaQueueEmpty, "MI_TestSysCntxDmaQueueEmpty"}, -+{MI_TestSysCntxDmaQueueEmpty_seq1, "MI_TestSysCntxDmaQueueEmpty_seq1"}, -+{MI_TestIfRemoteDesc, "MI_TestIfRemoteDesc"}, -+{MI_DoDmaLocalSetEvent, "MI_DoDmaLocalSetEvent"}, -+{MI_DoDmaLocalSetEvent_seq1, "MI_DoDmaLocalSetEvent_seq1"}, -+{MI_DoDmaLocalSetEvent_seq2, "MI_DoDmaLocalSetEvent_seq2"}, -+{MI_DmaLoop1, "MI_DmaLoop1"}, -+{MI_ExitDmaLoop, "MI_ExitDmaLoop"}, -+{MI_ExitDmaLoop_seq1, "MI_ExitDmaLoop_seq1"}, -+{MI_RemoteDmaTestPAckType, "MI_RemoteDmaTestPAckType"}, -+{MI_PacketDiscardOrTestFailRecIfCCis0, "MI_PacketDiscardOrTestFailRecIfCCis0"}, -+{MI_PacketDiscardOrTestFailRecIfCCis0_seq1, "MI_PacketDiscardOrTestFailRecIfCCis0_seq1"}, -+{MI_TestNackFailIsZero2, "MI_TestNackFailIsZero2"}, -+{MI_TestNackFailIsZero3, "MI_TestNackFailIsZero3"}, -+{MI_DmaFailCountError, "MI_DmaFailCountError"}, -+{MI_TestDmaForSysCntx, "MI_TestDmaForSysCntx"}, -+{MI_TestDmaForSysCntx_seq1, "MI_TestDmaForSysCntx_seq1"}, -+{MI_TestDmaForSysCntx_seq2, "MI_TestDmaForSysCntx_seq2"}, -+{MI_TestAeqB2, "MI_TestAeqB2"}, -+{MI_TestAeqB2_seq1, "MI_TestAeqB2_seq1"}, -+{MI_GetNextDmaDescriptor, "MI_GetNextDmaDescriptor"}, -+{MI_DequeueSysCntxDma2, "MI_DequeueSysCntxDma2"}, -+{MI_InputSetEvent, "MI_InputSetEvent"}, -+{MI_PutBackSysCntxDma, "MI_PutBackSysCntxDma"}, -+{MI_PutBackSysCntxDma_seq1, "MI_PutBackSysCntxDma_seq1"}, -+{MI_PutBackSysCntxDma_seq2, "MI_PutBackSysCntxDma_seq2"}, -+{MI_InputRemoteDma, "MI_InputRemoteDma"}, -+{MI_InputRemoteDma_seq1, "MI_InputRemoteDma_seq1"}, -+{MI_WaitOneTickForWakeup1, "MI_WaitOneTickForWakeup1"}, -+{MI_SendRemoteDmaDesc, "MI_SendRemoteDmaDesc"}, -+{MI_InputLockQueue, "MI_InputLockQueue"}, -+{MI_CloseTheTrappedPacketIfCCis1, "MI_CloseTheTrappedPacketIfCCis1"}, -+{MI_CloseTheTrappedPacketIfCCis1_seq1, "MI_CloseTheTrappedPacketIfCCis1_seq1"}, -+{MI_PostDmaInterrupt, "MI_PostDmaInterrupt"}, -+{MI_InputUnLockQueue, "MI_InputUnLockQueue"}, -+{MI_WaitForUnLockDescRead, "MI_WaitForUnLockDescRead"}, -+{MI_SendEOPforRemoteDma, "MI_SendEOPforRemoteDma"}, -+{MI_LookAtRemoteAck, "MI_LookAtRemoteAck"}, -+{MI_InputWriteBlockQueue, "MI_InputWriteBlockQueue"}, -+{MI_WaitForSpStore, "MI_WaitForSpStore"}, -+{MI_TProcNext, "MI_TProcNext"}, -+{MI_TProcStoppedRunning, "MI_TProcStoppedRunning"}, -+{MI_InputWriteBlock, "MI_InputWriteBlock"}, -+{MI_RunDmaOrDeqNonSysCntxDma, "MI_RunDmaOrDeqNonSysCntxDma"}, -+{MI_ExecuteDmaDescriptorForRun, "MI_ExecuteDmaDescriptorForRun"}, -+{MI_ConfirmQueueLock, "MI_ConfirmQueueLock"}, -+{MI_DmaInputIdentify, "MI_DmaInputIdentify"}, -+{MI_TProcStoppedRunning2, "MI_TProcStoppedRunning2"}, -+{MI_TProcStoppedRunning2_seq1, "MI_TProcStoppedRunning2_seq1"}, -+{MI_TProcStoppedRunning2_seq2, "MI_TProcStoppedRunning2_seq2"}, -+{MI_ThreadInputIdentify, "MI_ThreadInputIdentify"}, -+{MI_InputIdWriteAddrAndType3, "MI_InputIdWriteAddrAndType3"}, -+{MI_IProcTrappedWriteStatus, "MI_IProcTrappedWriteStatus"}, -+{MI_FinishTrappingEop, "MI_FinishTrappingEop"}, -+{MI_InputTestTrans, "MI_InputTestTrans"}, -+{MI_TestAeqB3, "MI_TestAeqB3"}, -+{MI_ThreadUpdateNonSysCntxBack, "MI_ThreadUpdateNonSysCntxBack"}, -+{MI_ThreadQueueOverflow, "MI_ThreadQueueOverflow"}, -+{MI_RunContext0Thread, "MI_RunContext0Thread"}, -+{MI_RunContext0Thread_seq1, "MI_RunContext0Thread_seq1"}, -+{MI_RunContext0Thread_seq2, "MI_RunContext0Thread_seq2"}, -+{MI_RunDmaDesc, "MI_RunDmaDesc"}, -+{MI_RunDmaDesc_seq1, "MI_RunDmaDesc_seq1"}, -+{MI_RunDmaDesc_seq2, "MI_RunDmaDesc_seq2"}, -+{MI_TestAeqB, "MI_TestAeqB"}, -+{MI_WaitForNonCntxDmaDescRead, "MI_WaitForNonCntxDmaDescRead"}, -+{MI_DmaQueueOverflow, "MI_DmaQueueOverflow"}, -+{MI_BlockCopyEvent, "MI_BlockCopyEvent"}, -+{MI_BlockCopyEventReadBlock, "MI_BlockCopyEventReadBlock"}, -+{MI_BlockCopyWaitForReadData, "MI_BlockCopyWaitForReadData"}, -+{MI_InputWriteWord, "MI_InputWriteWord"}, -+{MI_TraceSetEvents, "MI_TraceSetEvents"}, -+{MI_TraceSetEvents_seq1, "MI_TraceSetEvents_seq1"}, -+{MI_TraceSetEvents_seq2, "MI_TraceSetEvents_seq2"}, -+{MI_InputWriteDoubleWd, "MI_InputWriteDoubleWd"}, -+{MI_SendLockTransIfCCis1, "MI_SendLockTransIfCCis1"}, -+{MI_WaitForDmaRoutes1, "MI_WaitForDmaRoutes1"}, -+{MI_LoadDmaContext, "MI_LoadDmaContext"}, -+{MI_InputTestAndSetWord, "MI_InputTestAndSetWord"}, -+{MI_InputTestAndSetWord_seq1, "MI_InputTestAndSetWord_seq1"}, -+{MI_GetDestEventValue, "MI_GetDestEventValue"}, -+{MI_SendDmaIdentify, "MI_SendDmaIdentify"}, -+{MI_InputAtomicAddWord, "MI_InputAtomicAddWord"}, -+{MI_LoadBFromTransD0, "MI_LoadBFromTransD0"}, -+{MI_ConditionalWriteBackCCTrue, "MI_ConditionalWriteBackCCTrue"}, -+{MI_WaitOneTickForWakeup, "MI_WaitOneTickForWakeup"}, -+{MI_SendFinalUnlockTrans, "MI_SendFinalUnlockTrans"}, -+{MI_SendDmaEOP, "MI_SendDmaEOP"}, -+{MI_GenLastAddrForPsycho, "MI_GenLastAddrForPsycho"}, -+{MI_FailedAckIfCCis0, "MI_FailedAckIfCCis0"}, -+{MI_FailedAckIfCCis0_seq1, "MI_FailedAckIfCCis0_seq1"}, -+{MI_WriteDmaSysCntxDesc, "MI_WriteDmaSysCntxDesc"}, -+{MI_TimesliceDmaQueueOverflow, "MI_TimesliceDmaQueueOverflow"}, -+{MI_DequeueNonSysCntxThread1, "MI_DequeueNonSysCntxThread1"}, -+{MI_DequeueNonSysCntxThread1_seq1, "MI_DequeueNonSysCntxThread1_seq1"}, -+{MI_TestThreadQueueEmpty, "MI_TestThreadQueueEmpty"}, -+{MI_ClearThreadQueueIfCC, "MI_ClearThreadQueueIfCC"}, -+{MI_DequeueSysCntxThread1, "MI_DequeueSysCntxThread1"}, -+{MI_DequeueSysCntxThread1_seq1, "MI_DequeueSysCntxThread1_seq1"}, -+{MI_TProcStartUpGeneric, "MI_TProcStartUpGeneric"}, -+{MI_WaitForPCload2, "MI_WaitForPCload2"}, -+{MI_WaitForNPCWrite, "MI_WaitForNPCWrite"}, -+{MI_WaitForEventWaitAddr, "MI_WaitForEventWaitAddr"}, -+{MI_WaitForWaitEventAccess, "MI_WaitForWaitEventAccess"}, -+{MI_WaitForWaitEventAccess_seq1, "MI_WaitForWaitEventAccess_seq1"}, -+{MI_WaitForWaitEventDesc, "MI_WaitForWaitEventDesc"}, -+{MI_WaitForEventReadTy0, "MI_WaitForEventReadTy0"}, -+{MI_SendCondTestFail, "MI_SendCondTestFail"}, -+{MI_InputMoveToNextTrans, "MI_InputMoveToNextTrans"}, -+{MI_ThreadUpdateSysCntxBack, "MI_ThreadUpdateSysCntxBack"}, -+{MI_FinishedSetEvent, "MI_FinishedSetEvent"}, -+{MI_EventIntUpdateBPtr, "MI_EventIntUpdateBPtr"}, -+{MI_EventQueueOverflow, "MI_EventQueueOverflow"}, -+{MI_MaskLowerSource, "MI_MaskLowerSource"}, -+{MI_DmaLoop, "MI_DmaLoop"}, -+{MI_SendNullSetEvent, "MI_SendNullSetEvent"}, -+{MI_SendFinalSetEvent, "MI_SendFinalSetEvent"}, -+{MI_TestNackFailIsZero1, "MI_TestNackFailIsZero1"}, -+{MI_DmaPacketTimedOutOrPacketError, "MI_DmaPacketTimedOutOrPacketError"}, -+{MI_NextPacketIsLast, "MI_NextPacketIsLast"}, -+{MI_TestForZeroLengthDma, "MI_TestForZeroLengthDma"}, -+{MI_WaitForPCload, "MI_WaitForPCload"}, -+{MI_ReadInIns, "MI_ReadInIns"}, -+{MI_WaitForInsRead, "MI_WaitForInsRead"}, -+{MI_WaitForLocals, "MI_WaitForLocals"}, -+{MI_WaitForOutsWrite, "MI_WaitForOutsWrite"}, -+{MI_WaitForWaitEvWrBack, "MI_WaitForWaitEvWrBack"}, -+{MI_WaitForLockRead, "MI_WaitForLockRead"}, -+{MI_TestQueueLock, "MI_TestQueueLock"}, -+{MI_InputIdWriteAddrAndType, "MI_InputIdWriteAddrAndType"}, -+{MI_InputIdWriteAddrAndType2, "MI_InputIdWriteAddrAndType2"}, -+{MI_ThreadInputIdentify2, "MI_ThreadInputIdentify2"}, -+{MI_WriteIntoTrapArea0, "MI_WriteIntoTrapArea0"}, -+{MI_GenQueueBlockWrAddr, "MI_GenQueueBlockWrAddr"}, -+{MI_InputDiscardFreeLock, "MI_InputDiscardFreeLock"}, -+{MI_WriteIntoTrapArea1, "MI_WriteIntoTrapArea1"}, -+{MI_WriteIntoTrapArea2, "MI_WriteIntoTrapArea2"}, -+{MI_ResetBPtrToBase, "MI_ResetBPtrToBase"}, -+{MI_InputDoTrap, "MI_InputDoTrap"}, -+{MI_RemoteDmaCntxt0Update, "MI_RemoteDmaCntxt0Update"}, -+{MI_ClearQueueLock, "MI_ClearQueueLock"}, -+{MI_IProcTrappedBlockWriteData, "MI_IProcTrappedBlockWriteData"}, -+{MI_FillContextFilter, "MI_FillContextFilter"}, -+{MI_IProcTrapped4, "MI_IProcTrapped4"}, -+{MI_RunSysCntxDma, "MI_RunSysCntxDma"}, -+{MI_ChainedEventError, "MI_ChainedEventError"}, -+{MI_InputTrappingEOP, "MI_InputTrappingEOP"}, -+{MI_CheckForRunIfZero, "MI_CheckForRunIfZero"}, -+{MI_TestForBreakOrSuspend, "MI_TestForBreakOrSuspend"}, -+{MI_SwapForRunable, "MI_SwapForRunable"}, -Index: linux-2.4.21/include/elan3/neterr_rpc.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/neterr_rpc.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/neterr_rpc.h 2005-06-01 23:12:54.728419496 -0400 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_NETERR_RPC_H -+#define __ELAN3_NETERR_RPC_H -+ -+#ident "$Id: neterr_rpc.h,v 1.20 2003/06/26 16:05:22 fabien Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/neterr_rpc.h,v $*/ -+ -+#define NETERR_SERVICE "neterr-srv" -+#define NETERR_PROGRAM ((u_long) 170002) -+#define NETERR_VERSION ((u_long) 1) -+ -+#define NETERR_NULL_RPC 0 -+#define NETERR_FIXUP_RPC 1 -+ -+/* network error rpc timeout */ -+#define NETERR_RPC_TIMEOUT 5 -+ -+/* -+ * XDR functions for Tru64 and Linux in userspace. -+ * NB Linux kernelspace xdr routines are in network_error. -+ * and *must* be kept consistent. -+ */ -+#if defined(DIGITAL_UNIX) || !defined(__KERNEL__) -+bool_t -+xdr_capability (XDR *xdrs, void *arg) -+{ -+ ELAN_CAPABILITY *cap = (ELAN_CAPABILITY *) arg; -+ -+ return (xdr_opaque (xdrs, (caddr_t) &cap->cap_userkey, sizeof (cap->cap_userkey)) && -+ xdr_int (xdrs, &cap->cap_version) && -+ xdr_u_short (xdrs, &cap->cap_type) && -+ xdr_int (xdrs, &cap->cap_lowcontext) && -+ xdr_int (xdrs, &cap->cap_highcontext) && -+ xdr_int (xdrs, &cap->cap_mycontext) && -+ xdr_int (xdrs, &cap->cap_lownode) && -+ xdr_int (xdrs, &cap->cap_highnode) && -+ xdr_u_int (xdrs, &cap->cap_railmask) && -+ xdr_opaque (xdrs, (caddr_t) &cap->cap_bitmap[0], sizeof (cap->cap_bitmap))); -+} -+ -+bool_t -+xdr_neterr_msg (XDR *xdrs, void *req) -+{ -+ NETERR_MSG *msg = (NETERR_MSG *) req; -+ -+ return (xdr_u_int (xdrs, &msg->Rail) && -+ xdr_capability (xdrs, &msg->SrcCapability) && -+ xdr_capability (xdrs, &msg->DstCapability) && -+ xdr_u_int (xdrs, &msg->DstProcess) && -+ xdr_u_int (xdrs, &msg->CookieAddr) && -+ xdr_u_int (xdrs, &msg->CookieVProc) && -+ xdr_u_int (xdrs, &msg->NextCookie) && -+ xdr_u_int (xdrs, &msg->WaitForEop)); -+} -+#endif /* INCLUDE_XDR_INLINE */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN3_NETERR_RPC_H */ -Index: linux-2.4.21/include/elan3/perm.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/perm.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/perm.h 2005-06-01 23:12:54.728419496 -0400 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_PERM_H -+#define __ELAN3_PERM_H -+ -+#ident "$Id: perm.h,v 1.7 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/perm.h,v $*/ -+ -+#define ELAN3_PERM_NULL 0x00 -+#define ELAN3_PERM_LOCAL_READ 0x04 -+#define ELAN3_PERM_READ 0x08 -+#define ELAN3_PERM_NOREMOTE 0x0c -+#define ELAN3_PERM_REMOTEREAD 0x10 -+#define ELAN3_PERM_REMOTEWRITE 0x14 -+#define ELAN3_PERM_REMOTEEVENT 0x18 -+#define ELAN3_PERM_REMOTEALL 0x1c -+ -+#endif /* __ELAN3_PERM_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/pte.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/pte.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/pte.h 2005-06-01 23:12:54.729419344 -0400 -@@ -0,0 +1,139 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_PTE_H -+#define __ELAN3_PTE_H -+ -+#ident "$Id: pte.h,v 1.26 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/pte.h,v $*/ -+ -+#ifdef __cplusplus -+extern "C" -+{ -+#endif -+ -+#include -+#include -+ -+typedef E3_uint64 ELAN3_PTE; -+typedef E3_uint32 ELAN3_PTP; -+ -+#define ELAN3_PTE_SIZE (8) -+#define ELAN3_PTP_SIZE (4) -+ -+#define ELAN3_PTE_REF ((E3_uint64) 1 << 63) /* 63 - referenced bit */ -+#define ELAN3_PTE_MOD ((E3_uint64) 1 << 55) /* 55 - modified bit */ -+#define ELAN3_RM_MASK (ELAN3_PTE_REF | ELAN3_PTE_MOD) -+ -+#define ELAN3_PTE_PFN_MASK 0x0000fffffffff000ull /* [12:48] - Physical address */ -+ -+#define ELAN3_PTE_BIG_ENDIAN 0x80 /* 7 - big endian */ -+#define ELAN3_PTE_64_BIT 0x40 /* 6 - 64 bit pci address */ -+#define ELAN3_PTE_LOCAL 0x20 /* 5 - local sdram */ -+ -+#define ELAN3_PTE_PERM_MASK 0x1c /* [2:4] - Permissions */ -+#define ELAN3_PTE_PERM_SHIFT 2 -+ -+#define ELAN3_ET_MASK 0x3 -+#define ELAN3_ET_INVALID 0x0 /* [0:1] */ -+#define ELAN3_ET_PTP 0x1 -+#define ELAN3_ET_PTE 0x2 -+ -+#define ELAN3_INVALID_PTP ((ELAN3_PTP) 0) -+#define ELAN3_INVALID_PTE ((ELAN3_PTE) 0) -+ -+#define ELAN3_PTP_TYPE(ptp) ((ptp) & ELAN3_ET_MASK) -+#define ELAN3_PTE_TYPE(pte) ((pte) & ELAN3_ET_MASK) -+#define ELAN3_PTE_PERM(pte) ((pte) & ELAN3_PTE_PERM_MASK) -+#define ELAN3_PTE_VALID(pte) (((pte) & ELAN3_ET_MASK) == ELAN3_ET_PTE) -+#define ELAN3_PTE_ISREF(pte) ((pte) & ELAN3_PTE_REF) -+#define ELAN3_PTE_ISMOD(pte) ((pte) & ELAN3_PTE_MOD) -+#define ELAN3_PTE_WRITEABLE(pte) (ELAN3_PERM_WRITEABLE(ELAN3_PTE_PERM(pte))) -+ -+#define ELAN3_PERM_WRITEABLE(perm) ((perm) == ELAN3_PERM_NOREMOTE || (perm) > ELAN3_PERM_REMOTEREAD) -+#define ELAN3_PERM_REMOTE(perm) ((perm) > ELAN3_PERM_NOREMOTE) -+ -+#define ELAN3_PERM_READONLY(perm) ((perm) == ELAN3_PERM_NOREMOTE ? ELAN3_PERM_LOCAL_READ : \ -+ (perm) > ELAN3_PERM_REMOTEREAD ? ELAN3_PERM_READ : (perm)) -+#if PAGE_SHIFT == 12 -+# define ELAN3_PAGE_SHIFT 12 -+#else -+# define ELAN3_PAGE_SHIFT 13 -+#endif -+ -+#define ELAN3_PAGE_SIZE (1 << ELAN3_PAGE_SHIFT) -+#define ELAN3_PAGE_OFFSET (ELAN3_PAGE_SIZE-1) -+#define ELAN3_PAGE_MASK (~ELAN3_PAGE_OFFSET) -+ -+#if ELAN3_PAGE_SHIFT == 13 -+# define ELAN3_L3_SHIFT 5 -+#else -+# define ELAN3_L3_SHIFT 6 -+#endif -+#define ELAN3_L2_SHIFT 6 -+#define ELAN3_L1_SHIFT 8 -+ -+/* Number of entries in a given level ptbl */ -+#define ELAN3_L3_ENTRIES (1 << ELAN3_L3_SHIFT) -+#define ELAN3_L2_ENTRIES (1 << ELAN3_L2_SHIFT) -+#define ELAN3_L1_ENTRIES (1 << ELAN3_L1_SHIFT) -+ -+/* Virtual address spanned by each entry */ -+#define ELAN3_L3_SIZE (1 << (ELAN3_PAGE_SHIFT)) -+#define ELAN3_L2_SIZE (1 << (ELAN3_L3_SHIFT+ELAN3_PAGE_SHIFT)) -+#define ELAN3_L1_SIZE (1 << (ELAN3_L3_SHIFT+ELAN3_L2_SHIFT+ELAN3_PAGE_SHIFT)) -+ -+/* Virtual address size of page table */ -+#define ELAN3_L1_PTSIZE (ELAN3_L1_ENTRIES * ELAN3_L1_SIZE) -+#define ELAN3_L3_PTSIZE (ELAN3_L3_ENTRIES * ELAN3_L3_SIZE) -+#define ELAN3_L2_PTSIZE (ELAN3_L2_ENTRIES * ELAN3_L2_SIZE) -+ -+/* Mask for offset into page table */ -+#define ELAN3_L1_PTOFFSET ((ELAN3_L1_SIZE*ELAN3_L1_ENTRIES)-1) -+#define ELAN3_L3_PTOFFSET ((ELAN3_L3_SIZE*ELAN3_L3_ENTRIES)-1) -+#define ELAN3_L2_PTOFFSET ((ELAN3_L2_SIZE*ELAN3_L2_ENTRIES)-1) -+ -+#define ELAN3_L1_INDEX(addr) (((E3_Addr) (addr) & 0xFF000000) >> (ELAN3_L2_SHIFT+ELAN3_L3_SHIFT+ELAN3_PAGE_SHIFT)) -+#define ELAN3_L2_INDEX(addr) (((E3_Addr) (addr) & 0x00FD0000) >> (ELAN3_L3_SHIFT+ELAN3_PAGE_SHIFT)) -+#define ELAN3_L3_INDEX(addr) (((E3_Addr) (addr) & 0x0003F000) >> ELAN3_PAGE_SHIFT) -+ -+#define ELAN3_L1_BASE(addr) (((E3_Addr)(addr)) & 0x00000000) -+#define ELAN3_L2_BASE(addr) (((E3_Addr)(addr)) & 0xFF000000) -+#define ELAN3_L3_BASE(addr) (((E3_Addr)(addr)) & 0xFFFC0000) -+ -+/* Convert a page table pointer entry to the PT */ -+#define PTP_TO_PT_PADDR(ptp) ((E3_Addr)(ptp & 0xFFFFFFFC)) -+ -+#ifdef __KERNEL__ -+/* -+ * incompatible access for permission macro. -+ */ -+extern u_char elan3mmu_permissionTable[8]; -+#define ELAN3_INCOMPAT_ACCESS(perm,access) (! (elan3mmu_permissionTable[(perm)>>ELAN3_PTE_PERM_SHIFT] & (1 << (access)))) -+ -+#define elan3_readptp(dev, ptp) (elan3_sdram_readl (dev, ptp)) -+#define elan3_writeptp(dev, ptp, value) (elan3_sdram_writel (dev, ptp, value)) -+#define elan3_readpte(dev, pte) (elan3_sdram_readq (dev, pte)) -+#define elan3_writepte(dev,pte, value) (elan3_sdram_writeq (dev, pte, value)) -+ -+#define elan3_invalidatepte(dev, pte) (elan3_sdram_writel (dev, pte, 0)) -+#define elan3_modifypte(dev,pte,new) (elan3_sdram_writel (dev, pte, (int) (new))) -+#define elan3_clrref(dev,pte) (elan3_sdram_writeb (dev, pte + 7) -+ -+#endif /* __KERNEL__ */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __ELAN3_PTE_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/spinlock.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/spinlock.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/spinlock.h 2005-06-01 23:12:54.729419344 -0400 -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_SPINLOCK_ -+#define _ELAN3_SPINLOCK_ -+ -+#ident "$Id: spinlock.h,v 1.31 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/spinlock.h,v $*/ -+ -+/* -+ * This spinlock is designed for main/elan processor interactions. -+ * The lock is split over Elan/Main memory in such a way that -+ * we don't end up busy-polling over the PCI. -+ * In the Elan memory we have two words; one is a sequence number -+ * and the other is a lock word for main. -+ * In main memory we have a copy of the sequence number which main polls when it is -+ * waiting for the Elan to drop the lock. Main polls this word until it becomes -+ * equal to the sequence number it sampled. -+ * The Elan drops the lock by writing the current sequence number to main memory. -+ * It is coded to always give priority to the Elan thread, and so when both go for the -+ * lock, main will back off first. -+ * -+ * 18/3/98 -+ * This has been extended to avoid a starvation case where both the main and thread claim the -+ * lock and so both backoff (thread does a break). So now, main attempts to claim the -+ * lock by writing 'mainLock' then samples the 'sl_seq' and if it has the lock -+ * it sets 'mainGotLock'. The thread will now see the 'sl_mainLock' set, but will only -+ * backoff with a c_break_busywait() if 'mainGotLock' is set too. -+ */ -+typedef struct elan3_spinlock_elan { -+ union { -+ volatile E3_uint64 mainLocks; /* main writes this dble word */ -+ struct { -+ volatile E3_uint32 mainLock; /* main wants a lock */ -+ volatile E3_uint32 mainGotLock; /* main has the lock */ -+ } s; -+ } sl_u; -+ volatile E3_uint32 sl_seq; /* thread owns this word */ -+ volatile E3_uint32 sl_mainWait; /* performance counter */ -+ volatile E3_uint32 sl_elanWait; /* performance counter */ -+ volatile E3_uint32 sl_elanBusyWait; /* performance counter */ -+ /* NOTE: The lock/seq words must be within the same 32-byte Elan cache-line */ -+ E3_uint64 sl_pad[5]; /* pad to 64-bytes */ -+} ELAN3_SPINLOCK_ELAN; -+ -+#define sl_mainLocks sl_u.mainLocks -+#define sl_mainLock sl_u.s.mainLock -+#define sl_mainGotLock sl_u.s.mainGotLock -+ -+#define SL_MAIN_RECESSIVE 1 -+#define SL_MAIN_DOMINANT 2 -+ -+/* Declare this as a main memory cache block for efficiency */ -+typedef union elan3_spinlock_main { -+ volatile E3_uint32 sl_seq; /* copy of seq number updated by Elan */ -+ volatile E3_uint32 sl_Int32[E3_BLK_SIZE/sizeof (E3_uint32)]; -+} ELAN3_SPINLOCK_MAIN; -+ -+/* Main/Main or Elan/Elan lock word */ -+typedef volatile int ELAN3_SPINLOCK; -+ -+#ifdef __ELAN3__ -+ -+/* Main/Elan interlock */ -+ -+#define ELAN3_ME_SPINENTER(SLE,SL) do {\ -+ asm volatile ("! elan3_spinlock store barrier");\ -+ (SLE)->sl_seq++; \ -+ if ((SLE)->sl_mainLock) \ -+ elan3_me_spinblock(SLE, SL);\ -+ asm volatile ("! elan3_spinlock store barrier");\ -+ } while (0) -+#define ELAN3_ME_SPINEXIT(SLE,SL) do {\ -+ asm volatile ("! elan3_spinlock store barrier");\ -+ (SL)->sl_seq = (SLE)->sl_seq;\ -+ asm volatile ("! elan3_spinlock store barrier");\ -+ } while (0) -+ -+ -+/* Elan/Elan interlock */ -+#define ELAN3_SPINENTER(L) do {\ -+ asm volatile ("! store barrier");\ -+ if (c_swap ((L), 1)) elan3_spinenter(L);\ -+ asm volatile ("! store barrier");\ -+ } while (0) -+#define ELAN3_SPINEXIT(L) do {\ -+ asm volatile ("! store barrier");\ -+ c_swap((L), 0);\ -+ asm volatile ("! store barrier");\ -+ } while (0) -+ -+extern void elan3_me_spinblock (ELAN3_SPINLOCK_ELAN *sle, ELAN3_SPINLOCK_MAIN *sl); -+extern void elan3_spinenter (ELAN3_SPINLOCK *l); -+ -+#else -+ -+/* Main/Elan interlock */ -+#ifdef DEBUG -+#define ELAN3_ME_SPINENTER(SDRAM,SLE,SL) do {\ -+ register E3_int32 maxLoops = 0x7fffffff; \ -+ register E3_uint32 seq;\ -+ elan3_write32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), SL_MAIN_RECESSIVE); \ -+ MEMBAR_STORELOAD(); \ -+ seq = elan3_read32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+ while (seq != (SL)->sl_seq) {\ -+ elan3_write32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), 0); \ -+ while ((SL)->sl_seq == (seq-1) && maxLoops--) ; \ -+ if (maxLoops < 0) { \ -+ printf("Failed to get ME lock %lx/%lx seq %d sle_seq %d sl_seq %d\n", \ -+ SL, SLE, seq, \ -+ elan3_read32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)), \ -+ (SL)->sl_seq); \ -+ } \ -+ elan3_write32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), SL_MAIN_RECESSIVE); \ -+ MEMBAR_STORELOAD(); \ -+ seq = elan3_read32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+ }\ -+ elan3_write32_sdram(SDRAM, (SLE) + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainGotLock), 1); \ -+ MEMBAR_LOADLOAD();\ -+ } while (0) -+#else -+#define ELAN3_ME_SPINENTER(SDRAM,SLE,SL) do {\ -+ register E3_uint32 seq;\ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), SL_MAIN_RECESSIVE); \ -+ MEMBAR_STORELOAD(); \ -+ seq = elan3_read32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+ while (seq != (SL)->sl_seq) {\ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), 0); \ -+ while ((SL)->sl_seq == (seq-1)) ; \ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), SL_MAIN_RECESSIVE); \ -+ MEMBAR_STORELOAD(); \ -+ seq = elan3_read32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+ }\ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainGotLock), 1); \ -+ MEMBAR_LOADLOAD();\ -+ } while (0) -+#endif -+#define ELAN3_ME_FORCEENTER(SDRAM,SLE,SL) do { \ -+ register E3_uint32 seq; \ -+ MEMBAR_STORELOAD(); \ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), SL_MAIN_DOMINANT); \ -+ MEMBAR_STORELOAD(); \ -+ seq = elan3_read32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+ while (seq != (SL)->sl_seq) \ -+ { \ -+ /* NOTE: we MUST call elan3_usecspin here for kernel comms */\ -+ while ((SL)->sl_seq == (seq)-1) \ -+ elan3_usecspin (1); \ -+ seq = elan3_read32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+ } \ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainGotLock), 1); \ -+ MEMBAR_LOADLOAD(); \ -+} while (0) -+ -+#define ELAN3_ME_TRYENTER(SDRAM,SLE,SL,SEQ) do { \ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLock), SL_MAIN_RECESSIVE); \ -+ MEMBAR_STORELOAD(); \ -+ SEQ = elan3_read32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_seq)); \ -+} while (0) -+ -+#define ELAN3_ME_CHECKENTER(SDRAM,SLE,SL,SEQ) do { \ -+ if ((SEQ) == ((SL)->sl_seq)) { \ -+ elan3_write32_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainGotLock), 1); \ -+ MEMBAR_LOADLOAD();\ -+ } \ -+ else ELAN3_ME_SPINENTER(SLE,SL); \ -+} while (0) -+ -+#define ELAN3_ME_SPINEXIT(SDRAM,SLE,SL) do {\ -+ MEMBAR_STORESTORE(); \ -+ elan3_write64_sdram(SDRAM, SLE + offsetof(ELAN3_SPINLOCK_ELAN, sl_mainLocks), 0); \ -+ MEMBAR_STORESTORE(); \ -+ } while (0) -+ -+ -+/* Main/Main */ -+#define ELAN3_SPINENTER(L) do {\ -+ while (c_swap ((L), 1)) ; \ -+ } while (0) -+#define ELAN3_SPINEXIT(L) do {\ -+ c_swap((L), 0);\ -+ } while (0) -+#endif /* _ELAN3_ */ -+ -+#endif /* _ELAN3_SPINLOCK_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/thread.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/thread.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/thread.h 2005-06-01 23:12:54.730419192 -0400 -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_THREAD_H -+#define _ELAN3_THREAD_H -+ -+#ident "$Id: thread.h,v 1.17 2002/08/09 11:23:34 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/thread.h,v $*/ -+ -+/* Alignment for a stack frame */ -+#define E3_STACK_ALIGN (64) -+ -+typedef struct _E3_Frame { -+ E3_uint32 fr_local[8]; /* saved locals (not used) */ -+ E3_uint32 fr_arg[6]; /* saved arguements o0 -> o5 */ -+ E3_Addr fr_savefp; /* saved frame pointer o6 */ -+ E3_Addr fr_savepc; /* saved program counter o7 */ -+ E3_Addr fr_stret; /* stuct return addr */ -+ E3_uint32 fr_argd[6]; /* arg dump area */ -+ E3_uint32 fr_argx[1]; /* array of args past the sixth */ -+} E3_Frame; -+ -+typedef struct _E3_Stack { -+ E3_uint32 Locals[8]; -+ E3_uint32 Ins[8]; -+ E3_uint32 Globals[8]; -+ E3_uint32 Outs[8]; -+} E3_Stack; -+ -+typedef struct _E3_OutsRegs { -+ E3_uint32 o[8]; /* o6 == pc, o7 == fptr */ -+} E3_OutsRegs; -+ -+/* -+ * "Magic" value for stack pointer to be ignored. -+ */ -+#define VanishingStackPointer 0x42 -+ -+ -+/* -+ * When the Elan traps the N & Z CC bits are held in the NPC -+ * and the V & C bits are in the PC -+ */ -+#define PSR_C_BIT (1) -+#define PSR_V_BIT (2) -+#define PSR_Z_BIT (1) -+#define PSR_N_BIT (2) -+#define CC_MASK (3) -+#define PC_MASK (~3) -+#define SP_MASK (~3) -+ -+/* -+ * Threads processor Opcodes. -+ */ -+#define OPCODE_MASK (0xC1F80000) -+#define OPCODE_IMM (1 << 13) -+ -+#define OPCODE_CLASS(instr) ((instr) & 0xC0000000) -+#define OPCODE_CLASS_0 0x00000000 -+#define OPCODE_CLASS_1 0x40000000 -+#define OPCODE_CLASS_2 0x80000000 -+#define OPCODE_CLASS_3 0xC0000000 -+ -+#define OPCODE_CPOP 0x81B00000 -+#define OPCODE_Ticc 0x81D00000 -+ -+#define OPCODE_FCODE_SHIFT 19 -+#define OPCODE_FCODE_MASK 0x1f -+#define OPCODE_NOT_ALUOP 0x01000000 -+ -+#define OPCODE_SLL 0x81280000 -+#define OPCODE_SRL 0x81300000 -+#define OPCODE_SRA 0x81380000 -+ -+#define OPCODE_OPEN 0x81600000 -+#define OPCODE_CLOSE 0x81680000 -+#define OPCODE_BREAKTEST 0x81700000 -+ -+#define OPCODE_BREAK 0x81a00000 -+#define OPCODE_SUSPEND 0x81a80000 -+#define OPCODE_WAIT 0x81b00000 -+ -+#define OPCODE_JMPL 0x81c00000 -+ -+#define OPCODE_LD 0xC0000000 -+#define OPCODE_LDD 0xC0180000 -+ -+#define OPCODE_LDBLOCK16 0xC0900000 -+#define OPCODE_LDBLOCK32 0xC0800000 -+#define OPCODE_LDBLOCK64 0xC0980000 -+ -+#define OPCODE_ST 0xC0200000 -+#define OPCODE_STD 0xC0380000 -+ -+#define OPCODE_SWAP 0xC0780000 -+ -+#define OPCODE_STBLOCK16 0xC0b00000 -+#define OPCODE_STBLOCK32 0xC0a00000 -+#define OPCODE_STBLOCK64 0xC0b80000 -+ -+#define OPCODE_CLASS0_MASK 0xC1C00000 -+#define OPCODE_SETHI 0x01000000 -+#define OPCODE_BICC 0x00800000 -+#define OPCODE_SENDREG 0x01800000 -+#define OPCODE_SENDMEM 0x01c00000 -+ -+#define OPCODE_BICC_BN 0x00000000 -+#define OPCODE_BICC_BE 0x02000000 -+#define OPCODE_BICC_BLE 0x04000000 -+#define OPCODE_BICC_BL 0x06000000 -+#define OPCODE_BICC_BLEU 0x08000000 -+#define OPCODE_BICC_BCS 0x0A000000 -+#define OPCODE_BICC_BNEG 0x0C000000 -+#define OPCODE_BICC_BVS 0x0E000000 -+ -+#define OPCODE_BICC_MASK 0x0E000000 -+#define OPCODE_BICC_ANNUL 0x20000000 -+ -+#define INSTR_RS2(instr) (((instr) >> 0) & 0x1F) -+#define INSTR_RS1(instr) (((instr) >> 14) & 0x1F) -+#define INSTR_RD(instr) (((instr) >> 25) & 0x1F) -+#define INSTR_IMM(instr) (((instr) & 0x1000) ? ((instr) & 0xFFF) | 0xFFFFF000 : (instr) & 0xFFF) -+ -+#define Ticc_COND(instr) INSTR_RD(instr) -+#define Ticc_TA 8 -+ -+#endif /* _ELAN3_THREAD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/threadlinkage.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/threadlinkage.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/threadlinkage.h 2005-06-01 23:12:54.730419192 -0400 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_THREADLINKAGE_H -+#define __ELAN3_THREADLINKAGE_H -+ -+#ident "$Id: threadlinkage.h,v 1.6 2002/08/09 11:23:34 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/threadlinkage.h,v $*/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#if defined(_ASM) || defined(__LANGUAGE_ASSEMBLY__) -+ -+/* -+ * Macro to define weak symbol aliases. These are similar to the ANSI-C -+ * #pragma weak name = _name -+ * except a compiler can determine type. The assembler must be told. Hence, -+ * the second parameter must be the type of the symbol (i.e.: function,...) -+ */ -+#define ANSI_PRAGMA_WEAK(sym, stype) \ -+ .weak sym; \ -+ .type sym, #stype; \ -+/* CSTYLED */ \ -+sym = _/**/sym -+ -+/* -+ * ENTRY provides the standard procedure entry code -+ */ -+#define ENTRY(x) \ -+ .section ".text"; \ -+ .align 4; \ -+ .global x; \ -+x: -+ -+/* -+ * ENTRY2 is identical to ENTRY but provides two labels for the entry point. -+ */ -+#define ENTRY2(x, y) \ -+ .section ".text"; \ -+ .align 4; \ -+ .global x, y; \ -+/* CSTYLED */ \ -+x: ; \ -+y: -+ -+ -+/* -+ * ALTENTRY provides for additional entry points. -+ */ -+#define ALTENTRY(x) \ -+ .global x; \ -+x: -+ -+/* -+ * DGDEF and DGDEF2 provide global data declarations. -+ * -+ * DGDEF provides a word aligned word of storage. -+ * -+ * DGDEF2 allocates "sz" bytes of storage with **NO** alignment. This -+ * implies this macro is best used for byte arrays. -+ * -+ * DGDEF3 allocates "sz" bytes of storage with "algn" alignment. -+ */ -+#define DGDEF2(name, sz) \ -+ .section ".data"; \ -+ .global name; \ -+ .size name, sz; \ -+name: -+ -+#define DGDEF3(name, sz, algn) \ -+ .section ".data"; \ -+ .align algn; \ -+ .global name; \ -+ .size name, sz; \ -+name: -+ -+#define DGDEF(name) DGDEF3(name, 4, 4) -+ -+/* -+ * SET_SIZE trails a function and set the size for the ELF symbol table. -+ */ -+#define SET_SIZE(x) \ -+ .size x, (.-x) -+ -+#endif /* _ASM || __LANGUAGE_ASSEMBLY__ */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __ELAN3_THREADLINKAGE_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/threadsyscall.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/threadsyscall.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/threadsyscall.h 2005-06-01 23:12:54.730419192 -0400 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN3_SYSCALL_H -+#define __ELAN3_SYSCALL_H -+ -+#ident "$Id: threadsyscall.h,v 1.12 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/threadsyscall.h,v $*/ -+ -+/* -+ * This file contains the system calls supported from the Elan. -+ */ -+#define ELAN3_DEBUG_TRAPNUM 5 /* thread debugging trap */ -+#define ELAN3_ABORT_TRAPNUM 6 /* bad abort trap */ -+#define ELAN3_ELANCALL_TRAPNUM 7 /* elansyscall trap */ -+#define ELAN3_SYSCALL_TRAPNUM 8 /* new syscall trap */ -+ -+#define ELAN3_T_SYSCALL_CODE 0 /* offsets in struct elan3_t_syscall */ -+#define ELAN3_T_SYSCALL_ERRNO 4 -+ -+#define ELAN3_SYS_open 1 -+#define ELAN3_SYS_close 2 -+#define ELAN3_SYS_write 3 -+#define ELAN3_SYS_read 4 -+#define ELAN3_SYS_poll 5 -+#define ELAN3_SYS_ioctl 6 -+#define ELAN3_SYS_lseek 7 -+#define ELAN3_SYS_mmap 8 -+#define ELAN3_SYS_munmap 9 -+#define ELAN3_SYS_kill 10 -+#define ELAN3_SYS_getpid 11 -+ -+#if !defined(SYS_getpid) && defined(__NR_getxpid) -+#define SYS_getpid __NR_getxpid /* for linux */ -+#endif -+ -+#if !defined(_ASM) && !defined(__LANGUAGE_ASSEMBLY__) -+ -+extern int elan3_t_open (const char *, int, ...); -+extern ssize_t elan3_t_write (int, const void *, unsigned); -+extern ssize_t elan3_t_read(int, void *, unsigned); -+extern int elan3_t_ioctl(int, int, ...); -+extern int elan3_t_close(int); -+extern off_t elan3_t_lseek(int filedes, off_t offset, int whence); -+ -+extern caddr_t elan3_t_mmap(caddr_t, size_t, int, int, int, off_t); -+extern int elan3_t_munmap(caddr_t, size_t); -+ -+extern int elan3_t_getpid(void); -+extern void elan3_t_abort(char *str); -+ -+#endif /* !_ASM && ! __LANGUAGE_ASSEMBLY__ */ -+ -+#endif /* __ELAN3_SYSCALL_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/trtype.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/trtype.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/trtype.h 2005-06-01 23:12:54.731419040 -0400 -@@ -0,0 +1,116 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN3_TRTYPE_H -+#define _ELAN3_TRTYPE_H -+ -+#ident "$Id: trtype.h,v 1.13 2002/08/09 11:23:34 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/trtype.h,v $ */ -+ -+/*<15> ackNow */ -+#define TR_SENDACK (1 << 15) -+ -+#define TR_SIZE_SHIFT 12 -+#define TR_SIZE_MASK 7 -+ -+/*<14:12> Size 0, 1, 2, 4, 8, 16, 32, 64 Double Words -+ Bit 14 is forced to zero currently so that only size 0, 1, 2, 4 are -+ allowed */ -+ -+#define TR_SIZE0 (0 << TR_SIZE_SHIFT) -+#define TR_SIZE1 (1 << TR_SIZE_SHIFT) -+#define TR_SIZE2 (2 << TR_SIZE_SHIFT) -+#define TR_SIZE4 (3 << TR_SIZE_SHIFT) -+#define TR_SIZE8 (4 << TR_SIZE_SHIFT) -+ -+#define TR_64_BIT_ADDR (1 << 11) -+#define TR_LAST_TRANS (1 << 10) -+ -+#define TR_WRITEBLOCK_BIT (1 << 9) -+#define TR_WRITEBLOCK (TR_WRITEBLOCK_BIT | TR_SIZE8) -+ -+ -+#define TR_WRITEBLOCK_SIZE 64 -+ -+/* -+ * write-block -+ */ -+/* WriteBlock <8:7> Data type -+ <6:0> Part write size */ -+#define TR_TYPE_SHIFT 7 -+#define TR_TYPE_MASK ((1 << 2) - 1) -+ -+#define TR_TYPE_BYTE 0 -+#define TR_TYPE_SHORT 1 -+#define TR_TYPE_WORD 2 -+#define TR_TYPE_DWORD 3 -+ -+#define TR_PARTSIZE_MASK ((1 << 7) -1) -+ -+#define TR_WAIT_FOR_EOP (1 << 8) -+ -+/* -+ * trace-route format -+ */ -+#define TR_TRACEROUTE0_CHANID(val) ((val) & 1) /* 0 Chan Id */ -+#define TR_TRACEROUTE0_LINKID(val) (((val) >> 1) & 7) /* 1:3 Link Id */ -+#define TR_TRACEROUTE0_REVID(val) (((val) >> 4) & 7) /* 4:6 Revision ID */ -+#define TR_TRACEROUTE0_BCAST_TOP_PIN(val) (((val) >> 7) & 1) /* 7 Broadcast Top Pin (REV B) */ -+#define TR_TRACEROUTE0_LNR(val) ((val) >> 8) /* 8:15 Global Link Not Ready */ -+ -+#define TR_TRACEROUTE1_PRIO(val) ((val & 0xF)) /* 0:3 Arrival Priority (REV A) */ -+#define TR_TRACEROUTE1_AGE(val) (((val) >> 4) & 0xF) /* 4:7 Priority Held(Age) (REV A) */ -+#define TR_TRACEROUTE1_ROUTE_SELECTED(val) ((val) & 0xFF) /* 0:7 Arrival age (REV B) */ -+#define TR_TRACEROUTE1_BCAST_TOP(val) (((val) >> 8) & 7) /* 8:10 Broadcast Top */ -+#define TR_TRACEROUTE1_ADAPT(val) (((val) >> 12) & 3) /* 12:13 This Adaptive Value (REV A) */ -+#define TR_TRACEROUTE1_BCAST_BOT(val) (((val) >> 12) & 7) /* 12:14 Broadcast Bottom (REV B) */ -+ -+#define TR_TRACEROUTE2_ARRIVAL_AGE(val) ((val) & 0xF) /* 0:3 Arrival Age (REV B) */ -+#define TR_TRACEROUTE2_CURR_AGE(val) (((val) >> 4) & 0xF) /* 4:7 Current Age (REV B) */ -+#define TR_TRACEROUTE2_BUSY(val) (((val) >> 8) & 0xFF) /* 8:15 Busy (REV B) */ -+ -+#define TR_TRACEROUTE_SIZE 32 -+#define TR_TRACEROUTE_ENTRIES (TR_TRACEROUTE_SIZE/2) -+ -+/* -+ * non-write block -+ */ -+#define TR_OPCODE_MASK (((1 << 8) - 1) | \ -+ (TR_SIZE_MASK << TR_SIZE_SHIFT) | \ -+ TR_WRITEBLOCK_BIT) -+ -+#define TR_NOP_TRANS (0x0 | TR_SIZE0) -+#define TR_SETEVENT (0x0 | TR_SIZE0 | TR_SENDACK | TR_LAST_TRANS) -+#define TR_REMOTEDMA (0x1 | TR_SIZE4 | TR_SENDACK | TR_LAST_TRANS) -+#define TR_LOCKQUEUE (0x2 | TR_SIZE0) -+#define TR_UNLOCKQUEUE (0x3 | TR_SIZE0 | TR_SENDACK | TR_LAST_TRANS) -+ -+#define TR_SENDDISCARD (0x4 | TR_SIZE0) -+#define TR_TRACEROUTE (0x5 | TR_SIZE4) -+ -+#define TR_DMAIDENTIFY (0x6 | TR_SIZE0) -+#define TR_THREADIDENTIFY (0x7 | TR_SIZE1) -+ -+#define TR_GTE (0x8 | TR_SIZE1) -+#define TR_LT (0x9 | TR_SIZE1) -+#define TR_EQ (0xA | TR_SIZE1) -+#define TR_NEQ (0xB | TR_SIZE1) -+ -+#define TR_WRITEWORD (0xC | TR_SIZE1) -+#define TR_WRITEDOUBLEWORD (0xD | TR_SIZE1) -+#define TR_TESTANDWRITE (0xE | TR_SIZE1) -+#define TR_ATOMICADDWORD (0xF | TR_SIZE1 | TR_SENDACK | TR_LAST_TRANS) -+#define TR_OPCODE_TYPE_MASK 0xff -+ -+ -+#endif /* notdef _ELAN3_TRTYPE_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/urom_addrs.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/urom_addrs.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/urom_addrs.h 2005-06-01 23:12:54.731419040 -0400 -@@ -0,0 +1,262 @@ -+#define MI_WaitForRemoteDescRead 0x0 -+#define MI_WaitForRemoteDescRead2 0x1 -+#define MI_WaitForRemoteDescRead2_seq1 0x2 -+#define MI_SendRemoteDmaRoutes 0x3 -+#define MI_IProcTrapped 0x4 -+#define MI_DProcTrapped 0x5 -+#define MI_CProcTrapped 0x6 -+#define MI_TProcTrapped 0x7 -+#define MI_TestWhichDmaQueue 0x8 -+#define MI_TestWhichDmaQueue_seq1 0x9 -+#define MI_InputRemoteDmaUpdateBPtr 0xa -+#define MI_FixupQueueContextAndRemoteBit 0xb -+#define MI_FixupQueueContextAndRemoteBit_seq1 0xc -+#define MI_FixupQueueContextAndRemoteBit_seq2 0xd -+#define MI_FixupQueueContextAndRemoteBit_seq3 0xe -+#define MI_FixupQueueContextAndRemoteBit_seq4 0xf -+#define MI_RunDmaCommand 0x10 -+#define MI_DoSendRemoteDmaDesc 0x11 -+#define MI_DequeueNonSysCntxDma 0x12 -+#define MI_WaitForRemoteDescRead1 0x13 -+#define MI_RemoteDmaCommand 0x14 -+#define MI_WaitForRemoteRoutes 0x15 -+#define MI_DequeueSysCntxDma 0x16 -+#define MI_ExecuteDmaDescriptorForQueue 0x17 -+#define MI_ExecuteDmaDescriptor1 0x18 -+#define MI_ExecuteDmaDescriptor1_seq1 0x19 -+#define MI_ExecuteDmaDescriptor1_seq2 0x1a -+#define MI_ExecuteDmaDescriptor1_seq3 0x1b -+#define MI_GetNewSizeInProg 0x1c -+#define MI_GetNewSizeInProg_seq1 0x1d -+#define MI_FirstBlockRead 0x1e -+#define MI_ExtraFirstBlockRead 0x1f -+#define MI_UnimplementedError 0x20 -+#define MI_UpdateDescriptor 0x21 -+#define MI_UpdateDescriptor_seq1 0x22 -+#define MI_UpdateDescriptor_seq2 0x23 -+#define MI_UpdateDescriptor_seq3 0x24 -+#define MI_UpdateDescriptor_seq4 0x25 -+#define MI_UpdateDescriptor_seq5 0x26 -+#define MI_GetNextSizeInProg 0x27 -+#define MI_DoStopThisDma 0x28 -+#define MI_DoStopThisDma_seq1 0x29 -+#define MI_GenNewBytesToRead 0x2a -+#define MI_WaitForEventReadTy1 0x2b -+#define MI_WaitUpdateEvent 0x2c -+#define MI_WaitUpdateEvent_seq1 0x2d -+#define MI_DoSleepOneTickThenRunable 0x2e -+#define MI_RunEvent 0x2f -+#define MI_EnqueueThread 0x30 -+#define MI_CheckContext0 0x31 -+#define MI_EnqueueDma 0x32 -+#define MI_CprocTrapping 0x33 -+#define MI_CprocTrapping_seq1 0x34 -+#define MI_WaitForRemoteRoutes1 0x35 -+#define MI_SetEventCommand 0x36 -+#define MI_DoSetEvent 0x37 -+#define MI_DoRemoteSetEventNowOrTrapQueueingDma 0x38 -+#define MI_DoRemoteSetEventNowOrTrapQueueingDma_seq1 0x39 -+#define MI_SendRemoteDmaRoutes2 0x3a -+#define MI_WaitForRemoteRoutes2 0x3b -+#define MI_WaitEventCommandTy0 0x3c -+#define MI_DequeueNonSysCntxDma2 0x3d -+#define MI_WaitEventCommandTy1 0x3e -+#define MI_WaitEventCommandTy1_seq1 0x3f -+#define MI_DequeueNonSysCntxThread 0x40 -+#define MI_DequeueSysCntxDma1 0x41 -+#define MI_DequeueSysCntxThread 0x42 -+#define MI_TestNonSysCntxDmaQueueEmpty 0x43 -+#define MI_TestNonSysCntxDmaQueueEmpty_seq1 0x44 -+#define MI_TestNonSysCntxDmaQueueEmpty_seq2 0x45 -+#define MI_RunThreadCommand 0x46 -+#define MI_SetEventWaitForLastAcess 0x47 -+#define MI_SetEventReadWait 0x48 -+#define MI_SetEventReadWait_seq1 0x49 -+#define MI_TestEventType 0x4a -+#define MI_TestEventType_seq1 0x4b -+#define MI_TestEventBit2 0x4c -+#define MI_DmaDescOrBlockCopyOrChainedEvent 0x4d -+#define MI_RunThread 0x4e -+#define MI_RunThread1 0x4f -+#define MI_RunThread1_seq1 0x50 -+#define MI_IncDmaSysCntxBPtr 0x51 -+#define MI_IncDmaSysCntxBPtr_seq1 0x52 -+#define MI_IncDmaSysCntxBPtr_seq2 0x53 -+#define MI_WaitForCntxDmaDescRead 0x54 -+#define MI_FillInContext 0x55 -+#define MI_FillInContext_seq1 0x56 -+#define MI_WriteNewDescToQueue 0x57 -+#define MI_WriteNewDescToQueue_seq1 0x58 -+#define MI_TestForQueueWrap 0x59 -+#define MI_TestForQueueWrap_seq1 0x5a -+#define MI_TestQueueIsFull 0x5b -+#define MI_TestQueueIsFull_seq1 0x5c -+#define MI_TestQueueIsFull_seq2 0x5d -+#define MI_CheckPsychoShitFixup 0x5e -+#define MI_PsychoShitFixupForcedRead 0x5f -+#define MI_PrepareDMATimeSlice 0x60 -+#define MI_PrepareDMATimeSlice_seq1 0x61 -+#define MI_TProcRestartFromTrapOrTestEventBit2 0x62 -+#define MI_TProcRestartFromTrapOrTestEventBit2_seq1 0x63 -+#define MI_WaitForGlobalsRead 0x64 -+#define MI_WaitForNPCRead 0x65 -+#define MI_EventInterrupt 0x66 -+#define MI_EventInterrupt_seq1 0x67 -+#define MI_EventInterrupt_seq2 0x68 -+#define MI_EventInterrupt_seq3 0x69 -+#define MI_TestSysCntxDmaQueueEmpty 0x6a -+#define MI_TestSysCntxDmaQueueEmpty_seq1 0x6b -+#define MI_TestIfRemoteDesc 0x6c -+#define MI_DoDmaLocalSetEvent 0x6d -+#define MI_DoDmaLocalSetEvent_seq1 0x6e -+#define MI_DoDmaLocalSetEvent_seq2 0x6f -+#define MI_DmaLoop1 0x70 -+#define MI_ExitDmaLoop 0x71 -+#define MI_ExitDmaLoop_seq1 0x72 -+#define MI_RemoteDmaTestPAckType 0x73 -+#define MI_PacketDiscardOrTestFailRecIfCCis0 0x74 -+#define MI_PacketDiscardOrTestFailRecIfCCis0_seq1 0x75 -+#define MI_TestNackFailIsZero2 0x76 -+#define MI_TestNackFailIsZero3 0x77 -+#define MI_DmaFailCountError 0x78 -+#define MI_TestDmaForSysCntx 0x79 -+#define MI_TestDmaForSysCntx_seq1 0x7a -+#define MI_TestDmaForSysCntx_seq2 0x7b -+#define MI_TestAeqB2 0x7c -+#define MI_TestAeqB2_seq1 0x7d -+#define MI_GetNextDmaDescriptor 0x7e -+#define MI_DequeueSysCntxDma2 0x7f -+#define MI_InputSetEvent 0x80 -+#define MI_PutBackSysCntxDma 0x81 -+#define MI_PutBackSysCntxDma_seq1 0x82 -+#define MI_PutBackSysCntxDma_seq2 0x83 -+#define MI_InputRemoteDma 0x84 -+#define MI_InputRemoteDma_seq1 0x85 -+#define MI_WaitOneTickForWakeup1 0x86 -+#define MI_SendRemoteDmaDesc 0x87 -+#define MI_InputLockQueue 0x88 -+#define MI_CloseTheTrappedPacketIfCCis1 0x89 -+#define MI_CloseTheTrappedPacketIfCCis1_seq1 0x8a -+#define MI_PostDmaInterrupt 0x8b -+#define MI_InputUnLockQueue 0x8c -+#define MI_WaitForUnLockDescRead 0x8d -+#define MI_SendEOPforRemoteDma 0x8e -+#define MI_LookAtRemoteAck 0x8f -+#define MI_InputWriteBlockQueue 0x90 -+#define MI_WaitForSpStore 0x91 -+#define MI_TProcNext 0x92 -+#define MI_TProcStoppedRunning 0x93 -+#define MI_InputWriteBlock 0x94 -+#define MI_RunDmaOrDeqNonSysCntxDma 0x95 -+#define MI_ExecuteDmaDescriptorForRun 0x96 -+#define MI_ConfirmQueueLock 0x97 -+#define MI_DmaInputIdentify 0x98 -+#define MI_TProcStoppedRunning2 0x99 -+#define MI_TProcStoppedRunning2_seq1 0x9a -+#define MI_TProcStoppedRunning2_seq2 0x9b -+#define MI_ThreadInputIdentify 0x9c -+#define MI_InputIdWriteAddrAndType3 0x9d -+#define MI_IProcTrappedWriteStatus 0x9e -+#define MI_FinishTrappingEop 0x9f -+#define MI_InputTestTrans 0xa0 -+#define MI_TestAeqB3 0xa1 -+#define MI_ThreadUpdateNonSysCntxBack 0xa2 -+#define MI_ThreadQueueOverflow 0xa3 -+#define MI_RunContext0Thread 0xa4 -+#define MI_RunContext0Thread_seq1 0xa5 -+#define MI_RunContext0Thread_seq2 0xa6 -+#define MI_RunDmaDesc 0xa7 -+#define MI_RunDmaDesc_seq1 0xa8 -+#define MI_RunDmaDesc_seq2 0xa9 -+#define MI_TestAeqB 0xaa -+#define MI_WaitForNonCntxDmaDescRead 0xab -+#define MI_DmaQueueOverflow 0xac -+#define MI_BlockCopyEvent 0xad -+#define MI_BlockCopyEventReadBlock 0xae -+#define MI_BlockCopyWaitForReadData 0xaf -+#define MI_InputWriteWord 0xb0 -+#define MI_TraceSetEvents 0xb1 -+#define MI_TraceSetEvents_seq1 0xb2 -+#define MI_TraceSetEvents_seq2 0xb3 -+#define MI_InputWriteDoubleWd 0xb4 -+#define MI_SendLockTransIfCCis1 0xb5 -+#define MI_WaitForDmaRoutes1 0xb6 -+#define MI_LoadDmaContext 0xb7 -+#define MI_InputTestAndSetWord 0xb8 -+#define MI_InputTestAndSetWord_seq1 0xb9 -+#define MI_GetDestEventValue 0xba -+#define MI_SendDmaIdentify 0xbb -+#define MI_InputAtomicAddWord 0xbc -+#define MI_LoadBFromTransD0 0xbd -+#define MI_ConditionalWriteBackCCTrue 0xbe -+#define MI_WaitOneTickForWakeup 0xbf -+#define MI_SendFinalUnlockTrans 0xc0 -+#define MI_SendDmaEOP 0xc1 -+#define MI_GenLastAddrForPsycho 0xc2 -+#define MI_FailedAckIfCCis0 0xc3 -+#define MI_FailedAckIfCCis0_seq1 0xc4 -+#define MI_WriteDmaSysCntxDesc 0xc5 -+#define MI_TimesliceDmaQueueOverflow 0xc6 -+#define MI_DequeueNonSysCntxThread1 0xc7 -+#define MI_DequeueNonSysCntxThread1_seq1 0xc8 -+#define MI_TestThreadQueueEmpty 0xc9 -+#define MI_ClearThreadQueueIfCC 0xca -+#define MI_DequeueSysCntxThread1 0xcb -+#define MI_DequeueSysCntxThread1_seq1 0xcc -+#define MI_TProcStartUpGeneric 0xcd -+#define MI_WaitForPCload2 0xce -+#define MI_WaitForNPCWrite 0xcf -+#define MI_WaitForEventWaitAddr 0xd0 -+#define MI_WaitForWaitEventAccess 0xd1 -+#define MI_WaitForWaitEventAccess_seq1 0xd2 -+#define MI_WaitForWaitEventDesc 0xd3 -+#define MI_WaitForEventReadTy0 0xd4 -+#define MI_SendCondTestFail 0xd5 -+#define MI_InputMoveToNextTrans 0xd6 -+#define MI_ThreadUpdateSysCntxBack 0xd7 -+#define MI_FinishedSetEvent 0xd8 -+#define MI_EventIntUpdateBPtr 0xd9 -+#define MI_EventQueueOverflow 0xda -+#define MI_MaskLowerSource 0xdb -+#define MI_DmaLoop 0xdc -+#define MI_SendNullSetEvent 0xdd -+#define MI_SendFinalSetEvent 0xde -+#define MI_TestNackFailIsZero1 0xdf -+#define MI_DmaPacketTimedOutOrPacketError 0xe0 -+#define MI_NextPacketIsLast 0xe1 -+#define MI_TestForZeroLengthDma 0xe2 -+#define MI_WaitForPCload 0xe3 -+#define MI_ReadInIns 0xe4 -+#define MI_WaitForInsRead 0xe5 -+#define MI_WaitForLocals 0xe6 -+#define MI_WaitForOutsWrite 0xe7 -+#define MI_WaitForWaitEvWrBack 0xe8 -+#define MI_WaitForLockRead 0xe9 -+#define MI_TestQueueLock 0xea -+#define MI_InputIdWriteAddrAndType 0xeb -+#define MI_InputIdWriteAddrAndType2 0xec -+#define MI_ThreadInputIdentify2 0xed -+#define MI_WriteIntoTrapArea0 0xee -+#define MI_GenQueueBlockWrAddr 0xef -+#define MI_InputDiscardFreeLock 0xf0 -+#define MI_WriteIntoTrapArea1 0xf1 -+#define MI_WriteIntoTrapArea2 0xf2 -+#define MI_ResetBPtrToBase 0xf3 -+#define MI_InputDoTrap 0xf4 -+#define MI_RemoteDmaCntxt0Update 0xf5 -+#define MI_ClearQueueLock 0xf6 -+#define MI_IProcTrappedBlockWriteData 0xf7 -+#define MI_FillContextFilter 0xf8 -+#define MI_IProcTrapped4 0xf9 -+#define MI_RunSysCntxDma 0xfa -+#define MI_ChainedEventError 0xfb -+#define MI_InputTrappingEOP 0xfc -+#define MI_CheckForRunIfZero 0xfd -+#define MI_TestForBreakOrSuspend 0xfe -+#define MI_SwapForRunable 0xff -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/vmseg.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/vmseg.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/vmseg.h 2005-06-01 23:12:54.732418888 -0400 -@@ -0,0 +1,75 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _VM_SEG_ELAN3_H -+#define _VM_SEG_ELAN3_H -+ -+#ident "$Id: vmseg.h,v 1.20 2003/09/24 13:57:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/vmseg.h,v $*/ -+ -+#include -+ -+/* -+ * This segment maps Elan registers, it is fixed size and has 8K -+ * pages split up as follows -+ * -+ * ---------------------------------------- -+ * | Performance Counters (read-only) | -+ * ---------------------------------------- -+ * | Flag Page (read-only) | -+ * ---------------------------------------- -+ * | Command Port | -+ * ---------------------------------------- -+ */ -+typedef volatile struct elan3_flagstats -+{ -+ u_int CommandFlag; -+ u_int PageFaults; -+ u_int CProcTraps; -+ u_int DProcTraps; -+ u_int TProcTraps; -+ u_int IProcTraps; -+ u_int EopBadAcks; -+ u_int EopResets; -+ u_int DmaNetworkErrors; -+ u_int DmaIdentifyNetworkErrors; -+ u_int ThreadIdentifyNetworkErrors; -+ u_int DmaRetries; -+ u_int ThreadSystemCalls; -+ u_int ThreadElanCalls; -+ u_int LoadVirtualProcess; -+} ELAN3_FLAGSTATS; -+ -+#ifdef DIGITAL_UNIX -+typedef volatile union elan3_flagpage -+{ -+ u_char Padding[8192]; -+ ELAN3_FLAGSTATS Stats; -+} ELAN3_FLAGPAGE; -+ -+typedef volatile struct elan3_vmseg -+{ -+ E3_CommandPort CommandPort; -+ ELAN3_FLAGPAGE FlagPage; -+ E3_User_Regs UserRegs; -+} ELAN3_VMSEG; -+ -+#define SEGELAN3_SIZE (sizeof (ELAN3_VMSEG)) -+ -+#define SEGELAN3_COMMAND_PORT 0 -+#define SEGELAN3_FLAG_PAGE 1 -+#define SEGELAN3_PERF_COUNTERS 2 -+ -+#endif /* DIGITAL_UNIX */ -+ -+#endif /* _VM_SEG_ELAN3_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan3/vpd.h -=================================================================== ---- linux-2.4.21.orig/include/elan3/vpd.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan3/vpd.h 2005-06-01 23:12:54.732418888 -0400 -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: vpd.h,v 1.5 2002/08/09 11:23:34 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan3mod/elan3/elan3/vpd.h,v $*/ -+ -+#ifndef __ELAN3_VPD_H -+#define __ELAN3_VPD_H -+ -+#define LARGE_RESOURCE_BIT 0x80 -+ -+#define SMALL_RESOURCE_COMPATIBLE_DEVICE_ID 0x3 -+#define SMALL_RESOURCE_VENDOR_DEFINED 0xE -+#define SMALL_RESOURCE_END_TAG 0xF -+ -+#define LARGE_RESOURCE_STRING 0x2 -+#define LARGE_RESOURCE_VENDOR_DEFINED 0x4 -+#define LARGE_RESOURCE_VITAL_PRODUCT_DATA 0x10 -+ -+#define VPD_PART_NUMBER "PN" -+#define VPD_FRU_PART_NUMBER "FN" -+#define VPD_EC_LEVEL "EC" -+#define VPD_MANUFACTURE_ID "MN" -+#define VPD_SERIAL_NUMBER "SN" -+ -+#define VPD_LOAD_ID "LI" -+#define VPD_ROM_LEVEL "RL" -+#define VPD_ALTERABLE_ROM_LEVEL "RM" -+#define VPD_NETWORK_ADDRESS "NA" -+#define VPD_DEVICE_DRIVER_LEVEL "DD" -+#define VPD_DIAGNOSTIC_LEVEL "DG" -+#define VPD_LOADABLE_MICROCODE_LEVEL "LL" -+#define VPD_VENDOR_ID "VI" -+#define VPD_FUNCTION_NUMBER "FU" -+#define VPD_SUBSYSTEM_VENDOR_ID "SI" -+ -+#endif /* __ELAN3_VPD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/elan4/commands.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/commands.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/commands.h 2005-06-01 23:12:54.733418736 -0400 -@@ -0,0 +1,247 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_COMMANDS_H -+#define __ELAN4_COMMANDS_H -+ -+#ident "$Id: commands.h,v 1.29 2004/06/16 15:45:02 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/commands.h,v $*/ -+ -+/* -+ * This header file describes the command format for the Elan 4 -+ * See CommandFormat.doc -+ */ -+ -+/* -+ * Number of channels in traced elanlib_trace.c -+ */ -+#define TRACE_MAX_CHANNELS 2 -+ -+/* -+ * Define encoding for the commands issued into the command queues -+ */ -+#define RUN_THREAD_CMD 0x00 -+#define OPEN_STEN_PKT_CMD 0x01 -+#define WRITE_DWORD_CMD 0x02 -+#define ADD_DWORD_CMD 0x03 -+#define COPY64_CMD 0x05 -+#define GUARD_CMD 0x06 -+#define SET_EVENT_CMD 0x07 -+#define SEND_TRANS_CMD 0x09 -+#define INTERRUPT_CMD 0x0d -+#define RUN_DMA_CMD 0x0e -+#define SET_EVENTN_CMD 0x0f -+#define NOP_CMD 0x17 -+#define MAKE_EXT_CLEAN_CMD 0x37 -+#define WAIT_EVENT_CMD 0x1f -+ -+/* -+ * Define the portion of the data word the user is NOT -+ * allowed to use. This varies with Commmand type -+ */ -+#define RUN_THREAD_CMD_MASK 0x03 -+#define OPEN_STEN_PKT_CMD_MASK 0x0f -+#define WRITE_DWORD_CMD_MASK 0x07 -+#define ADD_DWORD_CMD_MASK 0x07 -+#define COPY64_CMD_MASK 0x0f -+#define GUARD_CMD_MASK 0x0f -+#define SET_EVENT_CMD_MASK 0x1f -+#define SEND_TRANS_CMD_MASK 0x1f -+#define INTERRUPT_CMD_MASK 0x0f -+#define RUN_DMA_CMD_MASK 0x0f -+#define SET_EVENTN_CMD_MASK 0x1f -+#define NOP_CMD_MASK 0x3f -+#define MAKE_EXT_CLEAN_MASK 0x3f -+#define WAIT_EVENT_CMD_MASK 0x1f -+ -+#define COPY64_DATA_TYPE_SHIFT 0x4 -+#define COPY64_DTYPE_BYTE (0 << COPY64_DATA_TYPE_SHIFT) -+#define COPY64_DTYPE_SHORT (1 << COPY64_DATA_TYPE_SHIFT) -+#define COPY64_DTYPE_WORD (2 << COPY64_DATA_TYPE_SHIFT) -+#define COPY64_DTYPE_LONG (3 << COPY64_DATA_TYPE_SHIFT) -+ -+/* -+ * SET_EVENTN - word 1 has following form -+ * [63:5] Event Address -+ * [4:0] Part Set Value. -+ */ -+#define SET_EVENT_PART_SET_MASK 0x1f -+ -+/* OPEN_STEN_PKT_CMD -+ * [63:32] Vproc -+ * [31] Use Test -+ * [30:28] unused -+ * [27:21] Test Acceptable PAck code -+ * [20:16] Test Ack Channel Number -+ * [15:9] Acceptable PAck code -+ * [8:4] Ack Channel Number (1 bit on Elan4) -+ * [3:0] Command type -+ */ -+/* Acceptable PAck code */ -+#define PACK_OK (1 << 0) -+#define PACK_TESTFAIL (1 << 1) -+#define PACK_DISCARD (1 << 2) -+#define RESTART_COUNT_ZERO (1 << 3) -+#define PACK_ERROR (1 << 7) -+#define PACK_TIMEOUT (1 << 8) -+ -+/* -+ *#ifndef USE_DIRTY_COMMANDS -+ *#define USE_DIRTY_COMMANDS -+ *#endif -+ */ -+#ifdef USE_DIRTY_COMMANDS -+#define OPEN_PACKET_USED_MASK 0x00000000780f00e0ULL -+#define SEND_TRANS_USED_MASK 0xffffffff0000fff0ULL -+#define COPY64_WRITE_USED_MASK 0x000000000000000fULL -+#define MAIN_INT_USED_MASK 0x0000000000003ff0ULL -+#define GUARD_USED_MASK 0xfffffe007000fde0ULL -+#define DMA_TYPESIZE_USED_MASK 0x000000000000fff0ULL -+#define SETEVENTN_USED_MASK 0xffffffffffffffe0ULL -+#define NOP_USED_MASK 0xffffffffffffffc0ULL -+#define EXT_CLEAN_USED_MASK 0xffffffffffffffc0ULL -+#define WAIT_CNT_TYPE_USED_MASK 0x00000000fffff800ULL -+#else -+#define OPEN_PACKET_USED_MASK 0x0ULL -+#define SEND_TRANS_USED_MASK 0x0ULL -+#define COPY64_WRITE_USED_MASK 0x0ULL -+#define MAIN_INT_USED_MASK 0x0ULL -+#define GUARD_USED_MASK 0x0ULL -+#define DMA_TYPESIZE_USED_MASK 0x0ULL -+#define SETEVENTN_USED_MASK 0x0ULL -+#define NOP_USED_MASK 0x0ULL -+#define EXT_CLEAN_USED_MASK 0x0ULL -+#define WAIT_CNT_TYPE_USED_MASK 0x0ULL -+#endif -+ -+#define OPEN_PACKET(chan, code, vproc) \ -+ ((((chan) & 1) << 4) | (((code) & 0x7f) << 9) | ((E4_uint64)(vproc) << 32) | OPEN_STEN_PKT_CMD) -+ -+#define OPEN_PACKET_TEST(chan, code, vproc, tchan, tcode) \ -+ ((((chan) & 1) << 4) | (((code) & 0x7f) << 9) | ((E4_uint64)(vproc) << 32) | \ -+ (((tchan) & 1) << 16) | (((tcode) & 0x7f) << 21) | (((E4_uint64) 1) << 31) | OPEN_STEN_PKT_CMD) -+ -+/* -+ * GUARD_CMD -+ * [63:41] unused -+ * [40] Reset Restart Fail Count // only performed if the Guard executes the next command. -+ * [39:32] New Restart Fail Count value -+ * [31] Use Test -+ * [30:28] unused -+ * [27:21] Test Acceptable PAck code -+ * [20:16] Test Ack Channel Number -+ * [15:9] unused -+ * [8:4] Ack Channel Number -+ * [3:0] Command type -+ */ -+/* GUARD_CHANNEL(chan) -+ */ -+#define GUARD_ALL_CHANNELS ((1 << 9) | GUARD_CMD) -+#define GUARD_CHANNEL(chan) ((((chan) & 1) << 4) | GUARD_CMD) -+#define GUARD_TEST(chan,code) ((1ull << 31) | (((code) & 0x7f) << 21) | (((chan) & 1) << 16)) -+#define GUARD_RESET(count) ((1ull << 40) | ((((E4_uint64) count) & 0xff) << 32)) -+ -+#define GUARD_CHANNEL_TEST(chan,tchan,tcode) \ -+ ((((chan) & 1) << 4) | (((tchan) & 1) << 16) | (((tcode) & 0x7f) << 21) | \ -+ (((E4_uint64) 1) << 31) | GUARD_CMD) -+ -+/* -+ * SEND_TRANS_CMD -+ * [63:32] unused -+ * [31:16] transaction type -+ * [15:4] unused -+ * [3:0] Command type -+ */ -+#define SEND_TRANS(TransType) (((TransType) << 16) | SEND_TRANS_CMD) -+ -+/* -+ * Command port trace debug levels -+ */ -+#define TRACE_CMD_BUFFER 0x01 -+#define TRACE_CMD_TYPE 0x02 -+#define TRACE_CHANNEL_OPENS 0x04 -+#define TRACE_GUARDED_ATOMICS 0x08 -+#define TRACE_CMD_TIMEOUT 0x10 -+ -+/* -+ * Commands that should be preceeded by a GUARD_CMD. -+ */ -+#define IS_ATOMIC_CMD(cmd) \ -+ ((cmd) == RUN_THREAD_CMD || (cmd) == ADD_DWORD_CMD || (cmd) == INTERRUPT_CMD || \ -+ (cmd) == RUN_DMA_CMD || (cmd) == SET_EVENT_CMD || (cmd) == SET_EVENTN_CMD || \ -+ (cmd) == WAIT_EVENT_CMD) -+ -+#ifndef _ASM -+ -+/* -+ * These structures are used to build event copy command streams. They are intended to be included -+ * in a larger structure to form a self documenting command sequence that can be easily coped and manipulated. -+ */ -+ -+typedef struct e4_runthreadcmd -+{ -+ E4_Addr PC; -+ E4_uint64 r[6]; -+} E4_RunThreadCmd; -+ -+typedef E4_uint64 E4_OpenCmd; -+ -+typedef struct e4_writecmd -+{ -+ E4_Addr WriteAddr; -+ E4_uint64 WriteValue; -+} E4_WriteCmd; -+ -+typedef struct e4_addcmd -+{ -+ E4_Addr AddAddr; -+ E4_uint64 AddValue; -+} E4_AddCmd; -+ -+typedef struct e4_copycmd -+{ -+ E4_Addr SrcAddr; -+ E4_Addr DstAddr; -+} E4_CopyCmd; -+ -+typedef E4_uint64 E4_GaurdCmd; -+typedef E4_uint64 E4_SetEventCmd; -+ -+/* -+ * The data to this command must be declared as a vector after the use of this. -+ */ -+typedef struct e4_sendtranscmd -+{ -+ E4_Addr Type; -+ E4_Addr Addr; -+} E4_SendTransCmd; -+ -+typedef E4_uint64 E4_IntCmd; -+ -+/* The normal Dma struc can be used here. */ -+ -+typedef struct e4_seteventncmd -+{ -+ E4_Addr Event; -+ E4_Addr SetCount; -+} E4_SetEventNCmd; -+ -+typedef E4_uint64 E4_NopCmd; -+typedef E4_uint64 E4_MakeExtCleanCmd; -+ -+typedef struct e4_waitcmd -+{ -+ E4_Addr ev_Event; -+ E4_Addr ev_CountType; -+ E4_Addr ev_Params[2]; -+} E4_WaitCmd; -+ -+#endif /* _ASM */ -+ -+#endif /* __ELAN4_COMMANDS_H */ -+ -Index: linux-2.4.21/include/elan4/debug.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/debug.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/debug.h 2005-06-01 23:12:54.733418736 -0400 -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN4_ELANDEBUG_H -+#define _ELAN4_ELANDEBUG_H -+ -+#ident "$Id: debug.h,v 1.19.6.1 2005/01/18 14:36:10 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/debug.h,v $ */ -+ -+/* values for "type" field - note a "ctxt" is permissible */ -+/* and BUFFER/CONSOLE are for explict calls to elan4_debugf() */ -+#define DBG_DEVICE ((void *) 0) -+#define DBG_USER ((void *) 1) -+ -+#define DBG_BUFFER ((void *) 62) -+#define DBG_CONSOLE ((void *) 63) -+#define DBG_NTYPES 64 -+ -+/* values for "mode" field */ -+#define DBG_CONFIG 0x00000001 -+#define DBG_INTR 0x00000002 -+#define DBG_MAININT 0x00000004 -+#define DBG_SDRAM 0x00000008 -+#define DBG_MMU 0x00000010 -+#define DBG_REGISTER 0x00000020 -+#define DBG_CQ 0x00000040 -+#define DBG_NETWORK_CTX 0x00000080 -+ -+#define DBG_FLUSH 0x00000100 -+#define DBG_FILE 0x00000200 -+#define DBG_CONTROL 0x00000400 -+#define DBG_MEM 0x00000800 -+ -+#define DBG_PERM 0x00001000 -+#define DBG_FAULT 0x00002000 -+#define DBG_SWAP 0x00004000 -+#define DBG_TRAP 0x00008000 -+#define DBG_DDCQ 0x00010000 -+#define DBG_VP 0x00020000 -+#define DBG_RESTART 0x00040000 -+#define DBG_RESUME 0x00080000 -+#define DBG_CPROC 0x00100000 -+#define DBG_DPROC 0x00200000 -+#define DBG_EPROC 0x00400000 -+#define DBG_IPROC 0x00800000 -+#define DBG_TPROC 0x01000000 -+#define DBG_IOPROC 0x02000000 -+#define DBG_ROUTE 0x04000000 -+#define DBG_NETERR 0x08000000 -+ -+#define DBG_ALL 0x7FFFFFFF -+ -+ -+#ifdef DEBUG_PRINTF -+ -+# define PRINTF0(type,m,fmt) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt) : (void)0) -+# define PRINTF1(type,m,fmt,a) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a) : (void)0) -+# define PRINTF2(type,m,fmt,a,b) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b) : (void)0) -+# define PRINTF3(type,m,fmt,a,b,c) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c) : (void)0) -+# define PRINTF4(type,m,fmt,a,b,c,d) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c,d) : (void)0) -+# define PRINTF5(type,m,fmt,a,b,c,d,e) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c,d,e) : (void)0) -+# define PRINTF6(type,m,fmt,a,b,c,d,e,f) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c,d,e,f) : (void)0) -+# define PRINTF7(type,m,fmt,a,b,c,d,e,f,g) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c,d,e,f,g) : (void)0) -+# define PRINTF8(type,m,fmt,a,b,c,d,e,f,g,h) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c,d,e,f,g,h) : (void)0) -+# define PRINTF9(type,m,fmt,a,b,c,d,e,f,g,h,i) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m,fmt,a,b,c,d,e,f,g,h,i): (void)0) -+#ifdef __GNUC__ -+# define PRINTF(type,m,args...) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? elan4_debugf(type,m, ##args) : (void)0) -+#endif -+# define DBGCMD(type,m,cmd) ((elan4_debug&(m) || (type) == DBG_CONSOLE) ? (void) (cmd) : (void) 0) -+ -+#else -+ -+# define PRINTF0(type,m,fmt) (0) -+# define PRINTF1(type,m,fmt,a) (0) -+# define PRINTF2(type,m,fmt,a,b) (0) -+# define PRINTF3(type,m,fmt,a,b,c) (0) -+# define PRINTF4(type,m,fmt,a,b,c,d) (0) -+# define PRINTF5(type,m,fmt,a,b,c,d,e) (0) -+# define PRINTF6(type,m,fmt,a,b,c,d,e,f) (0) -+# define PRINTF7(type,m,fmt,a,b,c,d,e,f,g) (0) -+# define PRINTF8(type,m,fmt,a,b,c,d,e,f,g,h) (0) -+# define PRINTF9(type,m,fmt,a,b,c,d,e,f,g,h,i) (0) -+#ifdef __GNUC__ -+# define PRINTF(type,m,args...) -+#endif -+# define DBGCMD(type,m,cmd) ((void) 0) -+ -+#endif /* DEBUG_PRINTF */ -+ -+extern unsigned elan4_debug; -+extern unsigned elan4_debug_toconsole; -+extern unsigned elan4_debug_tobuffer; -+extern unsigned elan4_debug_display_ctxt; -+extern unsigned elan4_debug_ignore_ctxt; -+extern unsigned elan4_debug_ignore_type; -+ -+extern void elan4_debug_init(void); -+extern void elan4_debug_fini(void); -+extern void elan4_debugf (void *type, int mode, char *fmt, ...); -+extern int elan4_debug_snapshot (caddr_t ubuffer, int len); -+extern int elan4_debug_display (void); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* _ELAN4_ELANDEBUG_H */ -Index: linux-2.4.21/include/elan4/device.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/device.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/device.h 2005-06-01 23:12:54.735418432 -0400 -@@ -0,0 +1,781 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_ELANDEV_H -+#define __ELAN4_ELANDEV_H -+ -+#ident "$Id: device.h,v 1.68.2.1 2004/11/03 14:24:32 duncant Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/device.h,v $ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_MPSAS -+#include -+#endif -+ -+#if defined(LINUX) -+#include -+#elif defined(TRU64UNIX) -+#include -+#elif defined(SOLARIS) -+#include -+#endif -+ -+/* -+ * Network context number allocation. -+ * [0] neterr fixup system context -+ * [1] kernel comms system context -+ * [2048-4095] kernel comms data contexts -+ */ -+#define ELAN4_NETERR_CONTEXT_NUM 0x00 /* network error fixup context number */ -+#define ELAN4_KCOMM_CONTEXT_NUM 0x01 /* kernel comms context number */ -+#define ELAN4_KCOMM_BASE_CONTEXT_NUM 0x800 /* kernel comms data transfer contexts */ -+#define ELAN4_KCOMM_TOP_CONTEXT_NUM 0xfff -+ -+#define ELAN4_SYSTEM_CONTEXT(ctx) ((ctx) >= ELAN4_KCOMM_BASE_CONTEXT_NUM) -+ -+typedef void (ELAN4_HALTFN)(struct elan4_dev *dev, void *arg); -+ -+typedef struct elan4_haltop -+{ -+ struct list_head op_link; /* chain on a list */ -+ E4_uint32 op_mask; /* Interrupt mask to see before calling function */ -+ -+ ELAN4_HALTFN *op_function; /* function to call */ -+ void *op_arg; /* arguement to pass to function */ -+} ELAN4_HALTOP; -+ -+typedef void (ELAN4_DMA_FLUSHFN)(struct elan4_dev *dev, void *arg, int qfull); -+ -+typedef struct elan4_dma_flushop -+{ -+ struct list_head op_link; /* chain on a list */ -+ ELAN4_DMA_FLUSHFN *op_function; /* function to call */ -+ void *op_arg; /* arguement to pass to function */ -+} ELAN4_DMA_FLUSHOP; -+ -+typedef void (ELAN4_INTFN)(struct elan4_dev *dev, void *arg); -+ -+typedef struct elan4_intop -+{ -+ struct list_head op_link; /* chain on a list */ -+ ELAN4_INTFN *op_function; /* function to call */ -+ void *op_arg; /* arguement to pass to function */ -+ E4_uint64 op_cookie; /* and main interrupt cookie */ -+} ELAN4_INTOP; -+ -+#define SDRAM_MIN_BLOCK_SHIFT 10 -+#define SDRAM_NUM_FREE_LISTS 19 /* allows max 256 Mb block */ -+#define SDRAM_MIN_BLOCK_SIZE (1 << SDRAM_MIN_BLOCK_SHIFT) -+#define SDRAM_MAX_BLOCK_SIZE (SDRAM_MIN_BLOCK_SIZE << (SDRAM_NUM_FREE_LISTS-1)) -+ -+#if PAGE_SHIFT < 13 -+#define SDRAM_PAGE_SIZE 8192 -+#define SDRAM_PGOFF_OFFSET 1 -+#define SDRAM_PGOFF_MASK (~SDRAM_PGOFF_OFFSET) -+#else -+#define SDRAM_PAGE_SIZE PAGE_SIZE -+#define SDRAM_PGOFF_OFFSET 0 -+#define SDRAM_PGOFF_MASK (~SDRAM_PGOFF_OFFSET) -+#endif -+ -+typedef struct elan4_sdram -+{ -+ sdramaddr_t b_base; /* offset in sdram bar */ -+ unsigned b_size; /* size of bank */ -+ ioaddr_t b_ioaddr; /* ioaddr where mapped into the kernel */ -+ ELAN4_MAP_HANDLE b_handle; /* and mapping handle */ -+ bitmap_t *b_bitmaps[SDRAM_NUM_FREE_LISTS]; /* buddy allocator bitmaps */ -+} ELAN4_SDRAM_BANK; -+ -+/* command queue */ -+typedef struct elan4_cq -+{ -+ struct elan4_cqa *cq_cqa; /* command queue allocator this belongs to */ -+ unsigned cq_idx; /* and which command queue this is */ -+ -+ sdramaddr_t cq_space; /* sdram backing up command queue */ -+ unsigned cq_size; /* size value */ -+ unsigned cq_perm; /* permissions */ -+ ioaddr_t cq_mapping; /* mapping of command queue page */ -+ ELAN4_MAP_HANDLE cq_handle; /* and mapping handle */ -+} ELAN4_CQ; -+ -+/* cqtype flags to elan4_alloccq() */ -+#define CQ_Priority (1 << 0) -+#define CQ_Reorder (1 << 1) -+ -+/* command queues are allocated in chunks,so that all the -+ * command ports are in a single system page */ -+#define ELAN4_CQ_PER_CQA MAX(1, (PAGESIZE/CQ_CommandMappingSize)) -+ -+/* maximum number of command queues per context */ -+#define ELAN4_MAX_CQA (256 / ELAN4_CQ_PER_CQA) -+ -+typedef struct elan4_cqa -+{ -+ struct list_head cqa_link; /* linked together */ -+ bitmap_t cqa_bitmap[BT_BITOUL(ELAN4_CQ_PER_CQA)]; /* bitmap of which are free */ -+ unsigned int cqa_type; /* allocation type */ -+ unsigned int cqa_cqnum; /* base cq number */ -+ unsigned int cqa_ref; /* "mappings" to a queue */ -+ unsigned int cqa_idx; /* index number */ -+ ELAN4_CQ cqa_cq[ELAN4_CQ_PER_CQA]; /* command queue entries */ -+} ELAN4_CQA; -+ -+#define elan4_cq2num(cq) ((cq)->cq_cqa->cqa_cqnum + (cq)->cq_idx) -+#define elan4_cq2idx(cq) ((cq)->cq_cqa->cqa_idx * ELAN4_CQ_PER_CQA + (cq)->cq_idx) -+ -+typedef struct elan4_ctxt -+{ -+ struct elan4_dev *ctxt_dev; /* device we're associated with */ -+ struct list_head ctxt_link; /* chained on device */ -+ -+ struct elan4_trap_ops *ctxt_ops; /* client specific operations */ -+ -+ signed ctxt_num; /* local context number */ -+ -+ struct list_head ctxt_cqalist; /* link list of command queue allocators */ -+ bitmap_t ctxt_cqamap[BT_BITOUL(ELAN4_MAX_CQA)]; /* bitmap for allocating cqa_idx */ -+ -+ ELAN4_HASH_ENTRY **ctxt_mmuhash[2]; /* software hash tables */ -+ spinlock_t ctxt_mmulock; /* and spinlock. */ -+} ELAN4_CTXT; -+ -+typedef struct elan4_trap_ops -+{ -+ void (*op_eproc_trap) (ELAN4_CTXT *ctxt, E4_uint64 status); -+ void (*op_cproc_trap) (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned cqnum); -+ void (*op_dproc_trap) (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit); -+ void (*op_tproc_trap) (ELAN4_CTXT *ctxt, E4_uint64 status); -+ void (*op_iproc_trap) (ELAN4_CTXT *ctxt, E4_uint64 status, unsigned unit); -+ void (*op_interrupt) (ELAN4_CTXT *ctxt, E4_uint64 cookie); -+ void (*op_neterrmsg) (ELAN4_CTXT *ctxt, ELAN4_NETERR_MSG *msg); -+} ELAN4_TRAP_OPS; -+ -+typedef struct elan4_route_table -+{ -+ spinlock_t tbl_lock; -+ unsigned tbl_size; -+ sdramaddr_t tbl_entries; -+} ELAN4_ROUTE_TABLE; -+ -+#ifdef ELAN4_LARGE_PAGE_SUPPORT -+#define NUM_HASH_TABLES 2 -+#else -+#define NUM_HASH_TABLES 1 -+#endif -+ -+#define DEV_STASH_ROUTE_COUNT 20 -+ -+typedef struct elan4_route_ringbuf { -+ int start; -+ int end; -+ E4_VirtualProcessEntry routes[DEV_STASH_ROUTE_COUNT]; -+} ELAN4_ROUTE_RINGBUF; -+ -+#define elan4_ringbuf_init(ringbuf) memset(&ringbuf, 0, sizeof(ELAN4_ROUTE_RINGBUF)); -+ -+typedef struct elan4_dev -+{ -+ ELAN4_CTXT dev_ctxt; /* context for device operations */ -+ -+ ELAN4_DEV_OSDEP dev_osdep; /* OS specific entries */ -+ -+ int dev_instance; /* device number */ -+ ELAN_DEVINFO dev_devinfo; /* device information (revision etc */ -+ ELAN_POSITION dev_position; /* position connected to switch */ -+ ELAN_DEV_IDX dev_idx; /* device idx registered with elanmod */ -+ -+ kmutex_t dev_lock; /* lock for device state/references */ -+ unsigned dev_state; /* device state */ -+ unsigned dev_references; /* # references */ -+ unsigned dev_features; /* features supported */ -+ -+ ioaddr_t dev_regs; /* Mapping of device registers */ -+ ELAN4_MAP_HANDLE dev_regs_handle; -+ ioaddr_t dev_rom; /* Mapping of rom */ -+ ELAN4_MAP_HANDLE dev_rom_handle; -+ ioaddr_t dev_i2c; /* Mapping of I2C registers */ -+ ELAN4_MAP_HANDLE dev_i2c_handle; -+ -+ E4_uint64 dev_sdram_cfg; /* SDRAM config value (from ROM) */ -+ E4_uint64 dev_sdram_initial_ecc_val; /* power on ECC register value */ -+ int dev_sdram_numbanks; /* # banks of sdram */ -+ ELAN4_SDRAM_BANK dev_sdram_banks[SDRAM_MAX_BANKS]; /* Mapping of sdram banks */ -+ spinlock_t dev_sdram_lock; /* spinlock for buddy allocator */ -+ sdramaddr_t dev_sdram_freelists[SDRAM_NUM_FREE_LISTS]; -+ unsigned dev_sdram_freecounts[SDRAM_NUM_FREE_LISTS]; -+ -+ sdramaddr_t dev_cacheflush_space; /* sdram reserved for cache flush operation */ -+ -+ sdramaddr_t dev_faultarea; /* fault areas for each unit */ -+ sdramaddr_t dev_inputtraparea; /* trap area for trapped transactions */ -+ sdramaddr_t dev_ctxtable; /* context table (E4_ContextControlBlock) */ -+ int dev_ctxtableshift; /* and size (in bits) */ -+ -+ E4_uint32 dev_syscontrol; /* copy of system control register */ -+ spinlock_t dev_syscontrol_lock; /* spinlock to sequentialise modifications */ -+ unsigned dev_direct_map_pci_writes; /* # counts for CONT_DIRECT_MAP_PCI_WRITES */ -+ -+ volatile E4_uint32 dev_intmask; /* copy of interrupt mask register */ -+ spinlock_t dev_intmask_lock; /* spinlock to sequentialise modifications */ -+ -+ /* i2c section */ -+ spinlock_t dev_i2c_lock; /* spinlock for i2c operations */ -+ unsigned int dev_i2c_led_disabled; /* count of reasons led auto update disabled */ -+ -+ /* mmu section */ -+ unsigned dev_pagesizeval[NUM_HASH_TABLES]; /* page size value */ -+ unsigned dev_pageshift[NUM_HASH_TABLES]; /* pageshift in bits. */ -+ unsigned dev_hashsize[NUM_HASH_TABLES]; /* # entries in mmu hash table */ -+ sdramaddr_t dev_hashtable[NUM_HASH_TABLES]; /* mmu hash table */ -+ ELAN4_HASH_ENTRY *dev_mmuhash[NUM_HASH_TABLES]; /* and software shadow */ -+ ELAN4_HASH_ENTRY **dev_mmufree[NUM_HASH_TABLES]; /* and partially free blocks */ -+ ELAN4_HASH_ENTRY *dev_mmufreelist; /* and free blocks */ -+ spinlock_t dev_mmulock; -+ E4_uint16 dev_topaddr[4]; /* top address values */ -+ unsigned char dev_topaddrvalid; -+ unsigned char dev_topaddrmode; -+ unsigned char dev_pteval; /* allow setting of relaxed order/dont snoop attributes */ -+ -+ unsigned dev_rsvd_hashmask[NUM_HASH_TABLES]; -+ unsigned dev_rsvd_hashval[NUM_HASH_TABLES]; -+ -+ /* run queues */ -+ sdramaddr_t dev_comqlowpri; /* CProc low & high pri run queues */ -+ sdramaddr_t dev_comqhighpri; -+ -+ sdramaddr_t dev_dmaqlowpri; /* DProc,TProc,Interrupt queues */ -+ sdramaddr_t dev_dmaqhighpri; -+ sdramaddr_t dev_threadqlowpri; -+ sdramaddr_t dev_threadqhighpri; -+ sdramaddr_t dev_interruptq; -+ -+ E4_uint32 dev_interruptq_nfptr; /* cache next main interrupt fptr */ -+ struct list_head dev_interruptq_list; /* list of operations to call when space in interruptq*/ -+ -+ /* command queue section */ -+ sdramaddr_t dev_cqaddr; /* SDRAM address of command queues */ -+ unsigned dev_cqoffset; /* offset for command queue alignment constraints */ -+ unsigned dev_cqcount; /* number of command queue descriptors */ -+ bitmap_t *dev_cqamap; /* bitmap for allocation */ -+ spinlock_t dev_cqlock; /* spinlock to protect bitmap */ -+#ifdef CONFIG_MTRR -+ unsigned dev_cqreorder; /* offset for first re-ordering queue on revb */ -+#endif -+ -+ /* halt operation section */ -+ struct list_head dev_haltop_list; /* list of operations to call when units halted */ -+ E4_uint32 dev_haltop_mask; /* mask of which ones to halt */ -+ E4_uint32 dev_haltop_active; /* mask of which haltops are executing */ -+ spinlock_t dev_haltop_lock; /* and their spinlock */ -+ -+ struct { -+ struct list_head list; /* list of halt operations for DMAs */ -+ ELAN4_CQ *cq; /* and command queue's */ -+ ELAN4_INTOP intop; /* and main interrupt op */ -+ E4_uint64 status; /* status register (when waiting for intop)*/ -+ } dev_dma_flushop[2]; -+ -+ unsigned dev_halt_all_count; /* count of reasons to halt all units */ -+ unsigned dev_halt_lowpri_count; /* count of reasons to halt lowpri queues */ -+ unsigned dev_halt_cproc_count; /* count of reasons to halt command processor */ -+ unsigned dev_halt_dproc_count; /* count of reasons to halt dma processor */ -+ unsigned dev_halt_tproc_count; /* count of reasons to halt thread processor */ -+ unsigned dev_discard_all_count; /* count of reasons to discard all packets */ -+ unsigned dev_discard_lowpri_count; /* count of reasons to discard non-system packets */ -+ unsigned dev_discard_highpri_count; /* count of reasons to discard system packets */ -+ -+ E4_uint32 dev_schedstatus; /* copy of schedule status register */ -+ -+ /* local context allocation section */ -+ spinlock_t dev_ctxlock; /* spinlock to protect bitmap */ -+ bitmap_t *dev_ctxmap; /* bitmap for local context allocation */ -+ -+ spinlock_t dev_ctxt_lock; /* spinlock to protect context list */ -+ struct list_head dev_ctxt_list; /* linked list of contexts */ -+ -+ /* locks to sequentialise interrupt handling */ -+ spinlock_t dev_trap_lock; /* spinlock while handling a trap */ -+ spinlock_t dev_requeue_lock; /* spinlock sequentialising cproc requeue */ -+ -+ /* error rate interrupt section */ -+ long dev_error_time; /* lbolt at start of sampling period */ -+ unsigned dev_errors_per_period; /* errors so far this sampling period */ -+ timer_fn_t dev_error_timeoutid; /* timeout to re-enable error interrupts */ -+ timer_fn_t dev_linkerr_timeoutid; /* timeout to clear link error led */ -+ -+ /* kernel threads */ -+ unsigned dev_stop_threads:1; /* kernel threads should exit */ -+ -+ /* main interrupt thread */ -+ kcondvar_t dev_mainint_wait; /* place for mainevent interrupt thread to sleep */ -+ spinlock_t dev_mainint_lock; /* and it's spinlock */ -+ unsigned dev_mainint_started:1; -+ unsigned dev_mainint_stopped:1; -+ -+ /* device context - this is used to flush insert cache/instruction cache/dmas & threads */ -+ ELAN4_CPROC_TRAP dev_cproc_trap; /* space to extract cproc trap into */ -+ -+ struct list_head dev_intop_list; /* list of main interrupt operations */ -+ spinlock_t dev_intop_lock; /* and spinlock */ -+ E4_uint64 dev_intop_cookie; /* and next cookie to use */ -+ -+ spinlock_t dev_flush_lock; /* spinlock for flushing */ -+ kcondvar_t dev_flush_wait; /* and place to sleep */ -+ -+ ELAN4_CQ *dev_flush_cq[COMMAND_INSERTER_CACHE_ENTRIES]; /* command queues to flush the insert cache */ -+ ELAN4_INTOP dev_flush_op[COMMAND_INSERTER_CACHE_ENTRIES]; /* and a main interrupt operation for each one */ -+ unsigned dev_flush_finished; /* flush command finished */ -+ -+ ELAN4_HALTOP dev_iflush_haltop; /* halt operation for icache flush */ -+ unsigned dev_iflush_queued:1; /* icache haltop queued */ -+ -+ ELAN4_ROUTE_TABLE *dev_routetable; /* virtual process table (for dma queue flush)*/ -+ sdramaddr_t dev_sdrampages[2]; /* pages of sdram to hold suspend code sequence */ -+ E4_Addr dev_tproc_suspend; /* st8suspend instruction */ -+ E4_Addr dev_tproc_space; /* and target memory */ -+ -+ sdramaddr_t dev_neterr_inputq; /* network error input queue descriptor & event */ -+ sdramaddr_t dev_neterr_slots; /* network error message slots */ -+ ELAN4_CQ *dev_neterr_msgcq; /* command queue for sending messages */ -+ ELAN4_CQ *dev_neterr_intcq; /* command queue for message received interrupt */ -+ ELAN4_INTOP dev_neterr_intop; /* and it's main interrupt operation */ -+ E4_uint64 dev_neterr_queued; /* # message queued in msgcq */ -+ spinlock_t dev_neterr_lock; /* and spinlock .... */ -+ -+ ELAN4_DEV_STATS dev_stats; /* device statistics */ -+ E4_uint64 dev_sdramerrs[30]; /* last few sdram errors for procfs */ -+ -+ spinlock_t dev_error_routes_lock; -+ unsigned int *dev_ack_errors; /* Map of source of dproc ack errors */ -+ ELAN4_ROUTE_RINGBUF dev_ack_error_routes; -+ unsigned int *dev_dproc_timeout; /* Ditto dproc timeout errors */ -+ ELAN4_ROUTE_RINGBUF dev_dproc_timeout_routes; -+ unsigned int *dev_cproc_timeout; /* Ditto cproc timeout errors */ -+ ELAN4_ROUTE_RINGBUF dev_cproc_timeout_routes; -+ -+ struct list_head dev_hc_list; /* list of the allocated hash_chunks */ -+ -+ ELAN4_IPROC_TRAP dev_iproc_trap; /* space for iproc trap */ -+} ELAN4_DEV; -+ -+/* values for dev_state */ -+#define ELAN4_STATE_STOPPED (1 << 0) /* device initialised but not started */ -+#define ELAN4_STATE_STARTING (1 << 1) /* device in process of starting */ -+#define ELAN4_STATE_STARTED (1 << 2) /* device started */ -+#define ELAN4_STATE_STOPPING (1 << 3) /* device in process of stopping */ -+ -+/* values for dev_features */ -+#define ELAN4_FEATURE_NO_WRITE_COMBINE (1 << 0) /* don't allow write combinig at all */ -+#define ELAN4_FEATURE_PCI_MAP (1 << 1) /* must use pci mapping functions */ -+#define ELAN4_FEATURE_NO_DWORD_READ (1 << 2) /* must perform 64 bit PIO reads */ -+ -+extern __inline__ unsigned int -+__elan4_readb (ELAN4_DEV *dev, ioaddr_t addr) -+{ -+ if (dev->dev_features & ELAN4_FEATURE_NO_DWORD_READ) -+ { -+ uint64_t val = readq ((void *) ((unsigned long) addr & ~7)); -+ return ((val >> (((unsigned long) addr & 7) << 3)) & 0xff); -+ } -+ return readb (addr); -+} -+ -+extern __inline__ unsigned int -+__elan4_readw (ELAN4_DEV *dev, ioaddr_t addr) -+{ -+ if (dev->dev_features & ELAN4_FEATURE_NO_DWORD_READ) -+ { -+ uint64_t val = readq ((void *) ((unsigned long) addr & ~7)); -+ return ((val >> (((unsigned long) addr & 7) << 3)) & 0xffff); -+ } -+ return readw (addr); -+} -+ -+extern __inline__ unsigned int -+__elan4_readl (ELAN4_DEV *dev, ioaddr_t addr) -+{ -+ if (dev->dev_features & ELAN4_FEATURE_NO_DWORD_READ) -+ { -+ uint64_t val = readq ((void *) ((unsigned long) addr & ~7)); -+ return ((val >> (((unsigned long) addr & 7) << 3)) & 0xffffffff); -+ } -+ return readl (addr); -+} -+ -+/* macros for accessing dev->dev_regs.Tags. */ -+#define write_tag(dev,what,val) writeq (val, dev->dev_regs + offsetof (E4_Registers, Tags.what)) -+#define read_tag(dev,what) readq (dev->dev_regs + offsetof (E4_Registers, Tags.what)) -+ -+/* macros for accessing dev->dev_regs.Regs. */ -+#define write_reg64(dev,what,val) writeq (val, dev->dev_regs + offsetof (E4_Registers, Regs.what)) -+#define write_reg32(dev,what,val) writel (val, dev->dev_regs + offsetof (E4_Registers, Regs.what)) -+#define read_reg64(dev,what) readq (dev->dev_regs + offsetof (E4_Registers, Regs.what)) -+#define read_reg32(dev,what) __elan4_readl (dev, dev->dev_regs + offsetof (E4_Registers, Regs.what)) -+ -+/* macros for accessing dev->dev_regs.uRegs. */ -+#define write_ureg64(dev,what,val) writeq (val, dev->dev_regs + offsetof (E4_Registers, uRegs.what)) -+#define write_ureg32(dev,what,val) writel (val, dev->dev_regs + offsetof (E4_Registers, uRegs.what)) -+#define read_ureg64(dev,what) readq (dev->dev_regs + offsetof (E4_Registers, uRegs.what)) -+#define read_ureg32(dev,what) __elan4_readl (dev, dev->dev_regs + offsetof (E4_Registers, uRegs.what)) -+ -+/* macros for accessing dev->dev_i2c */ -+#define write_i2c(dev,what,val) writeb (val, dev->dev_i2c + offsetof (E4_I2C, what)) -+#define read_i2c(dev,what) __elan4_readb (dev, dev->dev_i2c + offsetof (E4_I2C, what)) -+ -+/* macros for accessing dev->dev_rom */ -+#define read_ebus_rom(dev,off) __elan4_readb (dev, dev->dev_rom + off) -+ -+/* PIO flush operations - ensure writes to registers/sdram are ordered */ -+#ifdef CONFIG_IA64_SGI_SN2 -+#define pioflush_reg(dev) read_reg32(dev,InterruptReg) -+#define pioflush_sdram(dev) elan4_sdram_readl(dev, 0) -+#else -+#define pioflush_reg(dev) mb() -+#define pioflush_sdram(dev) mb() -+#endif -+ -+/* macros for manipulating the interrupt mask register */ -+#define SET_INT_MASK(dev,value) \ -+do { \ -+ write_reg32(dev, InterruptMask, (dev)->dev_intmask = (value)); \ -+ pioflush_reg(dev);\ -+} while (0) -+ -+#define CHANGE_INT_MASK(dev, value) \ -+do { \ -+ if ((dev)->dev_intmask != (value)) \ -+ {\ -+ write_reg32 (dev, InterruptMask, (dev)->dev_intmask = (value));\ -+ pioflush_reg(dev);\ -+ }\ -+} while (0) -+ -+#define ENABLE_INT_MASK(dev,value) \ -+do { \ -+ unsigned long flags; \ -+ \ -+ spin_lock_irqsave (&(dev)->dev_intmask_lock, flags); \ -+ write_reg32(dev, InterruptMask, (dev)->dev_intmask |= (value)); \ -+ pioflush_reg(dev);\ -+ spin_unlock_irqrestore (&(dev)->dev_intmask_lock, flags); \ -+} while (0) -+ -+#define DISABLE_INT_MASK(dev,value) \ -+do { \ -+ unsigned long flags; \ -+ \ -+ spin_lock_irqsave (&(dev)->dev_intmask_lock, flags); \ -+ write_reg32(dev, InterruptMask, (dev)->dev_intmask &= ~(value)); \ -+ pioflush_reg(dev);\ -+ spin_unlock_irqrestore (&(dev)->dev_intmask_lock, flags); \ -+} while (0) -+ -+#define SET_SYSCONTROL(dev,what,value) \ -+do { \ -+ unsigned long flags; \ -+\ -+ spin_lock_irqsave (&(dev)->dev_syscontrol_lock, flags); \ -+ if ((dev)->what++ == 0) \ -+ write_reg64 (dev, SysControlReg, (dev)->dev_syscontrol |= (value)); \ -+ pioflush_reg(dev);\ -+ spin_unlock_irqrestore (&(dev)->dev_syscontrol_lock, flags); \ -+} while (0) -+ -+#define CLEAR_SYSCONTROL(dev,what,value) \ -+do { \ -+ unsigned long flags; \ -+\ -+ spin_lock_irqsave (&(dev)->dev_syscontrol_lock, flags); \ -+ if (--(dev)->what == 0)\ -+ write_reg64 (dev, SysControlReg, (dev)->dev_syscontrol &= ~(value)); \ -+ pioflush_reg (dev); \ -+ spin_unlock_irqrestore (&(dev)->dev_syscontrol_lock, flags); \ -+} while (0) -+ -+#define PULSE_SYSCONTROL(dev,value) \ -+do { \ -+ unsigned long flags; \ -+\ -+ spin_lock_irqsave (&(dev)->dev_syscontrol_lock, flags); \ -+ write_reg64 (dev, SysControlReg, (dev)->dev_syscontrol | (value)); \ -+ pioflush_reg (dev); \ -+ spin_unlock_irqrestore (&(dev)->dev_syscontrol_lock, flags); \ -+} while (0) -+ -+#define CHANGE_SYSCONTROL(dev,add,sub) \ -+do { \ -+ unsigned long flags; \ -+\ -+ spin_lock_irqsave (&(dev)->dev_syscontrol_lock, flags); \ -+ dev->dev_syscontrol |= (add);\ -+ dev->dev_syscontrol &= ~(sub);\ -+ write_reg64 (dev, SysControlReg, (dev)->dev_syscontrol);\ -+ pioflush_reg (dev); \ -+ spin_unlock_irqrestore (&(dev)->dev_syscontrol_lock, flags); \ -+} while (0) -+ -+#define SET_SCHED_STATUS(dev, value)\ -+do {\ -+ write_reg32 (dev, SchedStatus.Status, (dev)->dev_schedstatus = (value));\ -+ pioflush_reg (dev);\ -+} while (0) -+ -+#define CHANGE_SCHED_STATUS(dev, value)\ -+do {\ -+ if ((dev)->dev_schedstatus != (value))\ -+ {\ -+ write_reg32 (dev, SchedStatus.Status, (dev)->dev_schedstatus = (value));\ -+ pioflush_reg (dev);\ -+ }\ -+} while (0) -+ -+#define PULSE_SCHED_RESTART(dev,value)\ -+do {\ -+ write_reg32 (dev, SchedStatus.Restart, value);\ -+ pioflush_reg (dev);\ -+} while (0) -+ -+/* device context elan address space */ -+#define DEVICE_TPROC_SUSPEND_ADDR (0x1000000000000000ull) -+#define DEVICE_TPROC_SPACE_ADDR (0x1000000000000000ull + SDRAM_PAGE_SIZE) -+#if defined(__LITTLE_ENDIAN__) -+# define DEVICE_TPROC_SUSPEND_INSTR 0xd3f040c0 /* st64suspend %r16, [%r1] */ -+#else -+# define DEVICE_TPROC_SUSPEND_INSTR 0xc040f0d3 /* st64suspend %r16, [%r1] */ -+#endif -+ -+#define DEVICE_NETERR_INPUTQ_ADDR (0x2000000000000000ull) -+#define DEVICE_NETERR_INTCQ_ADDR (0x2000000000000000ull + SDRAM_PAGE_SIZE) -+#define DEVICE_NETERR_SLOTS_ADDR (0x2000000000000000ull + SDRAM_PAGE_SIZE*2) -+ -+/* -+ * Interrupt operation cookie space -+ * [50:48] type -+ * [47:0] value -+ */ -+#define INTOP_PERSISTENT (0x1000000000000ull) -+#define INTOP_ONESHOT (0x2000000000000ull) -+#define INTOP_TYPE_MASK (0x3000000000000ull) -+#define INTOP_VALUE_MASK (0x0ffffffffffffull) -+ -+/* functions for accessing sdram - sdram.c */ -+extern unsigned char elan4_sdram_readb (ELAN4_DEV *dev, sdramaddr_t ptr); -+extern unsigned short elan4_sdram_readw (ELAN4_DEV *dev, sdramaddr_t ptr); -+extern unsigned int elan4_sdram_readl (ELAN4_DEV *dev, sdramaddr_t ptr); -+extern unsigned long long elan4_sdram_readq (ELAN4_DEV *dev, sdramaddr_t ptr); -+extern void elan4_sdram_writeb (ELAN4_DEV *dev, sdramaddr_t ptr, unsigned char val); -+extern void elan4_sdram_writew (ELAN4_DEV *dev, sdramaddr_t ptr, unsigned short val); -+extern void elan4_sdram_writel (ELAN4_DEV *dev, sdramaddr_t ptr, unsigned int val); -+extern void elan4_sdram_writeq (ELAN4_DEV *dev, sdramaddr_t ptr, unsigned long long val); -+ -+extern void elan4_sdram_zerob_sdram (ELAN4_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan4_sdram_zerow_sdram (ELAN4_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan4_sdram_zerol_sdram (ELAN4_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan4_sdram_zeroq_sdram (ELAN4_DEV *dev, sdramaddr_t ptr, int nbytes); -+ -+extern void elan4_sdram_copyb_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan4_sdram_copyw_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan4_sdram_copyl_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan4_sdram_copyq_from_sdram (ELAN4_DEV *dev, sdramaddr_t from, void *to, int nbytes); -+extern void elan4_sdram_copyb_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+extern void elan4_sdram_copyw_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+extern void elan4_sdram_copyl_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+extern void elan4_sdram_copyq_to_sdram (ELAN4_DEV *dev, void *from, sdramaddr_t to, int nbytes); -+ -+/* device.c - configuration */ -+extern unsigned int elan4_hash_0_size_val; -+extern unsigned int elan4_hash_1_size_val; -+extern unsigned int elan4_ctxt_table_shift; -+extern unsigned int elan4_ln2_max_cqs; -+extern unsigned int elan4_dmaq_highpri_size; -+extern unsigned int elan4_threadq_highpri_size; -+extern unsigned int elan4_dmaq_lowpri_size; -+extern unsigned int elan4_threadq_lowpri_size; -+extern unsigned int elan4_interruptq_size; -+ -+extern unsigned int elan4_mainint_punt_loops; -+extern unsigned int elan4_mainint_resched_ticks; -+ -+ -+/* device.c */ -+extern void elan4_set_schedstatus (ELAN4_DEV *dev, E4_uint32 intreg); -+extern void elan4_queue_haltop (ELAN4_DEV *dev, ELAN4_HALTOP *op); -+extern void elan4_queue_intop (ELAN4_DEV *dev, ELAN4_CQ *cq, ELAN4_INTOP *op); -+extern void elan4_register_intop (ELAN4_DEV *dev, ELAN4_INTOP *op); -+extern void elan4_deregister_intop (ELAN4_DEV *dev, ELAN4_INTOP *op); -+extern void elan4_queue_dma_flushop (ELAN4_DEV *dev, ELAN4_DMA_FLUSHOP *op, int hipri); -+extern void elan4_queue_mainintop (ELAN4_DEV *dev, ELAN4_INTOP *op); -+ -+extern int elan4_1msi0 (ELAN4_DEV *dev); -+ -+extern int elan4_insertctxt (ELAN4_DEV *dev, ELAN4_CTXT *ctxt, ELAN4_TRAP_OPS *ops); -+extern void elan4_removectxt (ELAN4_DEV *dev, ELAN4_CTXT *ctxt); -+extern ELAN4_CTXT *elan4_localctxt (ELAN4_DEV *dev, unsigned num); -+extern ELAN4_CTXT *elan4_networkctxt (ELAN4_DEV *dev, unsigned num); -+ -+extern int elan4_attach_filter (ELAN4_CTXT *ctxt, unsigned int ctxnum); -+extern void elan4_detach_filter (ELAN4_CTXT *ctxt, unsigned int ctxnum); -+extern void elan4_set_filter (ELAN4_CTXT *ctxt, unsigned int ctxnum, E4_uint32 state); -+extern void elan4_set_routetable (ELAN4_CTXT *ctxt, ELAN4_ROUTE_TABLE *tbl); -+ -+extern ELAN4_CQA * elan4_getcqa (ELAN4_CTXT *ctxt, unsigned int idx); -+extern void elan4_putcqa (ELAN4_CTXT *ctxt, unsigned int idx); -+extern ELAN4_CQ *elan4_alloccq (ELAN4_CTXT *ctxt, unsigned cqsize, unsigned cqperm, unsigned cqtype); -+extern void elan4_freecq (ELAN4_CTXT *ctxt, ELAN4_CQ *cq); -+extern void elan4_restartcq (ELAN4_DEV *dev, ELAN4_CQ *cq); -+extern void elan4_flushcq (ELAN4_DEV *dev, ELAN4_CQ *cq); -+extern void elan4_updatecq (ELAN4_DEV *dev, ELAN4_CQ *cq, unsigned perm, unsigned restart); -+ -+extern void elan4_flush_icache (ELAN4_CTXT *ctxt); -+extern void elan4_flush_icache_halted (ELAN4_CTXT *ctxt); -+ -+extern int elan4_initialise_device (ELAN4_DEV *dev); -+extern void elan4_finalise_device (ELAN4_DEV *dev); -+extern int elan4_start_device (ELAN4_DEV *dev); -+extern void elan4_stop_device (ELAN4_DEV *dev); -+ -+extern int elan4_compute_position (ELAN_POSITION *pos, unsigned nodeid, unsigned numnodes, unsigned aritiyval); -+extern int elan4_get_position (ELAN4_DEV *dev, ELAN_POSITION *pos); -+extern int elan4_set_position (ELAN4_DEV *dev, ELAN_POSITION *pos); -+extern void elan4_get_params (ELAN4_DEV *dev, ELAN_PARAMS *params, unsigned short *mask); -+extern void elan4_set_params (ELAN4_DEV *dev, ELAN_PARAMS *params, unsigned short mask); -+ -+ -+extern int elan4_read_vpd(ELAN4_DEV *dev, unsigned char *tag, unsigned char *result) ; -+ -+ -+/* device_osdep.c */ -+extern unsigned int elan4_pll_cfg; -+extern int elan4_pll_div; -+extern int elan4_mod45disable; -+ -+extern int elan4_pciinit (ELAN4_DEV *dev); -+extern void elan4_pcifini (ELAN4_DEV *dev); -+extern void elan4_pcierror (ELAN4_DEV *dev); -+ -+extern ELAN4_DEV *elan4_reference_device (int instance, int state); -+extern void elan4_dereference_device (ELAN4_DEV *dev); -+ -+extern ioaddr_t elan4_map_device (ELAN4_DEV *dev, unsigned bar, unsigned off, unsigned size, ELAN4_MAP_HANDLE *handlep); -+extern void elan4_unmap_device (ELAN4_DEV *dev, ioaddr_t ptr, unsigned size, ELAN4_MAP_HANDLE *handlep); -+extern unsigned long elan4_resource_len (ELAN4_DEV *dev, unsigned bar); -+ -+extern void elan4_configure_mtrr (ELAN4_DEV *dev); -+extern void elan4_unconfigure_mtrr (ELAN4_DEV *dev); -+ -+/* i2c.c */ -+extern int i2c_disable_auto_led_update (ELAN4_DEV *dev); -+extern void i2c_enable_auto_led_update (ELAN4_DEV *dev); -+extern int i2c_write (ELAN4_DEV *dev, unsigned int addr, unsigned int count, unsigned char *data); -+extern int i2c_read (ELAN4_DEV *dev, unsigned int addr, unsigned int count, unsigned char *data); -+extern int i2c_writereg (ELAN4_DEV *dev, unsigned int addr, unsigned int reg, unsigned int count, unsigned char *data); -+extern int i2c_readreg (ELAN4_DEV *dev, unsigned int addr, unsigned int reg, unsigned int count, unsigned char *data); -+extern int i2c_read_rom (ELAN4_DEV *dev, unsigned int addr, unsigned int count, unsigned char *data); -+ -+#if defined(__linux__) -+/* procfs_Linux.c */ -+extern void elan4_procfs_device_init (ELAN4_DEV *dev); -+extern void elan4_procfs_device_fini (ELAN4_DEV *dev); -+extern void elan4_procfs_init(void); -+extern void elan4_procfs_fini(void); -+ -+extern struct proc_dir_entry *elan4_procfs_root; -+extern struct proc_dir_entry *elan4_config_root; -+#endif -+ -+/* sdram.c */ -+extern void elan4_sdram_init (ELAN4_DEV *dev); -+extern void elan4_sdram_fini (ELAN4_DEV *dev); -+extern void elan4_sdram_setup_delay_lines (ELAN4_DEV *dev); -+extern int elan4_sdram_init_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank); -+extern void elan4_sdram_fini_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank); -+extern void elan4_sdram_add_bank (ELAN4_DEV *dev, ELAN4_SDRAM_BANK *bank); -+extern sdramaddr_t elan4_sdram_alloc (ELAN4_DEV *dev, int nbytes); -+extern void elan4_sdram_free (ELAN4_DEV *dev, sdramaddr_t ptr, int nbytes); -+extern void elan4_sdram_flushcache (ELAN4_DEV *dev, sdramaddr_t base, int nbytes); -+extern char *elan4_sdramerr2str (ELAN4_DEV *dev, E4_uint64 status, char *str); -+ -+/* traps.c */ -+extern void elan4_display_eproc_trap (void *type, int mode, char *str, ELAN4_EPROC_TRAP *trap); -+extern void elan4_display_cproc_trap (void *type, int mode, char *str, ELAN4_CPROC_TRAP *trap); -+extern void elan4_display_dproc_trap (void *type, int mode, char *str, ELAN4_DPROC_TRAP *trap); -+extern void elan4_display_tproc_trap (void *type, int mode, char *str, ELAN4_TPROC_TRAP *trap); -+extern void elan4_display_iproc_trap (void *type, int mode, char *str, ELAN4_IPROC_TRAP *trap); -+ -+ -+extern void elan4_extract_eproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_EPROC_TRAP *trap, int iswaitevent); -+extern void elan4_extract_cproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_CPROC_TRAP *trap, unsigned cqnum); -+extern void elan4_extract_dproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_DPROC_TRAP *trap, unsigned unit); -+extern void elan4_extract_tproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_TPROC_TRAP *trap); -+extern void elan4_extract_iproc_trap (ELAN4_DEV *dev, E4_uint64 status, ELAN4_IPROC_TRAP *trap, unsigned unit); -+extern void elan4_ringbuf_store(ELAN4_ROUTE_RINGBUF *ringbuf, E4_VirtualProcessEntry *route, ELAN4_DEV *dev); -+extern int cproc_open_extract_vp (ELAN4_DEV *dev, ELAN4_CQ *cq); -+ -+extern void elan4_inspect_iproc_trap (ELAN4_IPROC_TRAP *trap); -+extern E4_uint64 elan4_trapped_open_command (ELAN4_DEV *dev, ELAN4_CQ *cq); -+ -+/* mmu.c */ -+extern void elan4mmu_flush_tlb (ELAN4_DEV *dev); -+extern ELAN4_HASH_ENTRY *elan4mmu_ptealloc (ELAN4_CTXT *ctxt, int tbl, E4_Addr vaddr, unsigned int *tagidxp); -+extern int elan4mmu_pteload (ELAN4_CTXT *ctxt, int tbl, E4_Addr vaddr, E4_uint64 pte); -+extern void elan4mmu_unload_range (ELAN4_CTXT *ctxt, int tbl, E4_Addr start, unsigned long len); -+extern void elan4mmu_invalidate_ctxt (ELAN4_CTXT *ctxt); -+ -+extern ELAN4_HASH_CACHE *elan4mmu_reserve (ELAN4_CTXT *ctxt, int tbl, E4_Addr start, unsigned int npages, int cansleep); -+extern void elan4mmu_release (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc); -+extern void elan4mmu_set_pte (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc, unsigned int idx, E4_uint64 newpte); -+extern E4_uint64 elan4mmu_get_pte (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc, unsigned int idx); -+extern void elan4mmu_clear_pte (ELAN4_CTXT *ctxt, ELAN4_HASH_CACHE *hc, unsigned int idx); -+ -+/* mmu_osdep.c */ -+extern int elan4mmu_categorise_paddr (ELAN4_DEV *dev, physaddr_t *physp); -+extern int elan4mmu_alloc_topaddr (ELAN4_DEV *dev, physaddr_t paddr, unsigned type); -+extern E4_uint64 elan4mmu_phys2pte (ELAN4_DEV *dev, physaddr_t paddr, unsigned perm); -+extern physaddr_t elan4mmu_pte2phys (ELAN4_DEV *dev, E4_uint64 pte); -+ -+/* neterr.c */ -+extern int elan4_neterr_init (ELAN4_DEV *dev); -+extern void elan4_neterr_destroy (ELAN4_DEV *dev); -+extern int elan4_neterr_sendmsg (ELAN4_DEV *dev, unsigned int nodeid, unsigned int retries, ELAN4_NETERR_MSG *msg); -+extern int elan4_neterr_iproc_trap (ELAN4_DEV *dev, ELAN4_IPROC_TRAP *trap); -+ -+/* routetable.c */ -+extern ELAN4_ROUTE_TABLE *elan4_alloc_routetable (ELAN4_DEV *dev, unsigned size); -+extern void elan4_free_routetable (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl); -+extern void elan4_write_route (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl, unsigned vp, E4_VirtualProcessEntry *entry); -+extern void elan4_read_route (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl, unsigned vp, E4_VirtualProcessEntry *entry); -+extern void elan4_invalidate_route (ELAN4_DEV *dev, ELAN4_ROUTE_TABLE *tbl, unsigned vp); -+extern int elan4_generate_route (ELAN_POSITION *pos, E4_VirtualProcessEntry *route, unsigned ctxnum, -+ unsigned lowid, unsigned highid, unsigned options); -+extern int elan4_check_route (ELAN_POSITION *pos, ELAN_LOCATION location, E4_VirtualProcessEntry *route, unsigned flags); -+ -+/* user.c */ -+extern int __categorise_command (E4_uint64 command, int *cmdSize); -+extern int __whole_command (sdramaddr_t *commandPtr, sdramaddr_t insertPtr, unsigned int cqSize, unsigned int cmdSize); -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_ELANDEV_H */ -Index: linux-2.4.21/include/elan4/device_Linux.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/device_Linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/device_Linux.h 2005-06-01 23:12:54.735418432 -0400 -@@ -0,0 +1,97 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_ELANDEV_LINUX_H -+#define __ELAN4_ELANDEV_LINUX_H -+ -+#ident "$Id: device_Linux.h,v 1.19 2004/08/09 14:02:37 daniel Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/device_Linux.h,v $*/ -+ -+#include -+ -+#if defined(MPSAS) -+#include -+#endif -+ -+#if defined(CONFIG_DEVFS_FS) -+#include -+#endif -+ -+#define ELAN4_MAJOR 61 -+#define ELAN4_NAME "elan4" -+#define ELAN4_MAX_CONTROLLER 16 /* limited to 4 bits */ -+ -+/* OS dependant component of ELAN4_DEV struct */ -+typedef struct elan4_dev_osdep -+{ -+ struct pci_dev *pdev; /* PCI config data */ -+ -+ struct proc_dir_entry *procdir; -+ struct proc_dir_entry *configdir; -+ struct proc_dir_entry *statsdir; -+ -+#if defined(CONFIG_DEVFS_FS) -+ devfs_handle_t devfs_control; -+ devfs_handle_t devfs_sdram; -+ devfs_handle_t devfs_user; -+#endif -+ -+#if defined(CONFIG_MTRR) -+ int sdram_mtrr; -+ int regs_mtrr; -+#endif -+} ELAN4_DEV_OSDEP; -+ -+/* /dev/elan/rmsX */ -+ -+/* /dev/elan4/controlX */ -+typedef struct control_private -+{ -+ struct elan4_dev *pr_dev; -+ unsigned pr_boundary_scan; -+} CONTROL_PRIVATE; -+ -+/* /dev/elan4/sdramX */ -+typedef struct mem_page -+{ -+ struct mem_page *pg_next; -+ sdramaddr_t pg_addr; -+ unsigned long pg_pgoff; -+ unsigned pg_ref; -+} MEM_PAGE; -+ -+#define MEM_HASH_SIZE 32 -+#define MEM_HASH(pgoff) ((pgoff) & (MEM_HASH_SIZE-1)) -+ -+typedef struct mem_private -+{ -+ struct elan4_dev *pr_dev; -+ MEM_PAGE *pr_pages[MEM_HASH_SIZE]; -+ spinlock_t pr_lock; -+} MEM_PRIVATE; -+ -+/* /dev/elan4/userX */ -+typedef struct user_private -+{ -+ atomic_t pr_ref; -+ struct user_ctxt *pr_uctx; -+ struct mm_struct *pr_mm; -+ coproc_ops_t pr_coproc; -+} USER_PRIVATE; -+ -+/* No mapping handles on linux */ -+typedef void *ELAN4_MAP_HANDLE; -+ -+#define ELAN4_TASK_HANDLE() ((unsigned long) current->mm) -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_ELANDEV_LINUX_H */ -Index: linux-2.4.21/include/elan4/dma.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/dma.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/dma.h 2005-06-01 23:12:54.736418280 -0400 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_DMA_H -+#define __ELAN4_DMA_H -+ -+#ident "$Id: dma.h,v 1.16 2003/09/04 12:39:17 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/dma.h,v $*/ -+ -+#include -+ -+/* Alignment for a DMA descriptor */ -+#define E4_DMA_ALIGN (64) -+ -+/* Maximum size of a single DMA ((1 << 31)-1) */ -+#define E4_MAX_DMA_SIZE (0x7fffffff) -+ -+/* -+ * dma_typeSize -+ * -+ * [63:32] Size -+ * [31] unused -+ * [30] IsRemote -+ * [29] QueueWrite -+ * [28] ShmemWrite -+ * [27:26] DataType -+ * [25] Broadcast -+ * [24] AlignPackets -+ * [23:16] FailCount -+ * [15:14] unused -+ * [13:0] Context -+ */ -+ -+#define DMA_FailCount(val) (((val) & 0xff) << 16) -+#define DMA_AlignPackets (1 << 24) -+#define DMA_Broadcast (1 << 25) -+#define DMA_ShMemWrite (1 << 28) -+#define DMA_QueueWrite (1 << 29) -+#define DMA_IsRemote (1 << 30) -+#define DMA_Context(val) ((unsigned) (val) & 0x3ff) -+#define DMA_ContextMask 0x3fffull -+#define Dma_TypeSizeMask 0xfffffffffff00000ull -+ -+#define DMA_DataTypeByte (E4_DATATYPE_BYTE << 26) -+#define DMA_DataTypeShort (E4_DATATYPE_SHORT << 26) -+#define DMA_DataTypeWord (E4_DATATYPE_WORD << 26) -+#define DMA_DataTypeLong (E4_DATATYPE_DWORD << 26) -+ -+#define E4_DMA_TYPE_SIZE(size, dataType, flags, failCount) \ -+ ((((E4_uint64)(size)) << 32) | ((dataType) & DMA_DataTypeLong) | \ -+ (flags) | DMA_FailCount(failCount)) -+ -+typedef volatile struct e4_dma -+{ -+ E4_uint64 dma_typeSize; -+ E4_uint64 dma_cookie; -+ E4_uint64 dma_vproc; -+ E4_Addr dma_srcAddr; -+ E4_Addr dma_dstAddr; -+ E4_Addr dma_srcEvent; -+ E4_Addr dma_dstEvent; -+} E4_DMA; -+ -+/* Same as above but padded to 64-bytes */ -+typedef volatile struct e4_dma64 -+{ -+ E4_uint64 dma_typeSize; -+ E4_uint64 dma_cookie; -+ E4_uint64 dma_vproc; -+ E4_Addr dma_srcAddr; -+ E4_Addr dma_dstAddr; -+ E4_Addr dma_srcEvent; -+ E4_Addr dma_dstEvent; -+ E4_Addr dma_pad; -+} E4_DMA64; -+ -+#endif /* __ELAN4_DMA_H */ -Index: linux-2.4.21/include/elan4/events.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/events.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/events.h 2005-06-01 23:12:54.736418280 -0400 -@@ -0,0 +1,179 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_EVENTS_H -+#define __ELAN4_EVENTS_H -+ -+#ident "$Id: events.h,v 1.22 2004/06/23 11:07:18 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/events.h,v $*/ -+ -+#define E4_EVENT_ALIGN 32 -+#define E4_EVENTBLOCK_SIZE 64 -+ -+#ifndef _ASM -+/* -+ * Event locations must be aligned to a 32 byte boundary. It is very much more efficent to place -+ * them in elan local memory but is not essential. -+ */ -+typedef struct _E4_Event -+{ -+ volatile E4_uint64 ev_CountAndType; -+ E4_uint64 ev_Params[2]; -+} E4_Event; -+ -+/* Same as above but padded to correct Event alignment */ -+typedef struct _E4_Event32 -+{ -+ volatile E4_uint64 ev_CountAndType; -+ E4_uint64 ev_Params[2]; -+ E4_uint64 ev_pad; -+} E4_Event32; -+ -+/* -+ * An E4_EVENTBLOCK_SIZE aligned block of Main or Elan memory -+ */ -+typedef union _E4_Event_Blk -+{ -+ /* Padded to 64-bytes in case a cache-line write is more efficient */ -+ volatile E4_uint8 eb_unit8[E4_EVENTBLOCK_SIZE]; -+ volatile E4_uint32 eb_uint32[E4_EVENTBLOCK_SIZE/sizeof(E4_uint32)]; -+ volatile E4_uint64 eb_uint64[E4_EVENTBLOCK_SIZE/sizeof(E4_uint64)]; -+} E4_Event_Blk; -+#define eb_done eb_uint32[14] -+#define eb_done_dword eb_uint64[7] -+ -+#endif /* ! _ASM */ -+ -+/* -+ * ev_CountAndType -+ * [63:31] Count -+ * [10] CopyType -+ * [9:8] DataType -+ * [7:0] CopySize -+ */ -+#define E4_EVENT_TYPE_MASK 0x00000000ffffffffull -+#define E4_EVENT_COUNT_MASK 0xffffffff00000000ull -+#define E4_EVENT_COUNT_SHIFT 32 -+#define E4_EVENT_COPY_TYPE_MASK (1 << 10) -+#define E4_EVENT_DATA_TYPE_MASK (3 << 8) -+#define E4_EVENT_COPY_SIZE_MASK (0xff) -+ -+/* CopyType */ -+#define E4_EVENT_COPY (0 << 10) -+#define E4_EVENT_WRITE (1 << 10) -+ -+/* DataType */ -+#define E4_EVENT_DTYPE_BYTE (0 << 8) -+#define E4_EVENT_DTYPE_SHORT (1 << 8) -+#define E4_EVENT_DTYPE_WORD (2 << 8) -+#define E4_EVENT_DTYPE_LONG (3 << 8) -+ -+#define EVENT_COUNT(EventPtr) ((E4_int32)(elan4_load64 (&(EventPtr)->ev_CountAndType) >> E4_EVENT_COUNT_SHIFT)) -+#define EVENT_TYPE(EventPtr) ((E4_uint32)(elan4_load64 (&(EventPtr)->ev_CountAndType) & E4_EVENT_TYPE_MASK)) -+ -+#define E4_WAITEVENT_COUNT_TYPE_VALUE(Count, EventType, DataType, CopySize) \ -+ (((E4_uint64)(Count) << E4_EVENT_COUNT_SHIFT) | (EventType) | (DataType) | (CopySize)) -+ -+#define E4_EVENT_TYPE_VALUE(EventType, DataType, CopySize) \ -+ ((EventType) | (DataType) | (CopySize)) -+ -+#define E4_EVENT_INIT_VALUE(InitialCount, EventType, DataType, CopySize) \ -+ (((E4_uint64)(InitialCount) << E4_EVENT_COUNT_SHIFT) | E4_EVENT_TYPE_VALUE(EventType, DataType, CopySize)) -+ -+#define ev_CopySource ev_Params[0] -+#define ev_CopyDest ev_Params[1] -+#define ev_WritePtr ev_Params[0] -+#define ev_WriteValue ev_Params[1] -+ -+#define EVENT_BLK_READY(BLK) ((BLK)->eb_done != 0) -+#define EVENT_READY(EVENT) ((E4_uint32)((((volatile E4_Event *) (EVENT))->ev_CountAndType) >> E4_EVENT_COUNT_SHIFT) >= 0) -+ -+#define ELAN_WAIT_EVENT (0) -+#define ELAN_POLL_EVENT (-1) -+ -+#define E4_BLK_PATTERN ((E4_uint32)0xfeedface) -+ -+#define E4_INIT_COPY_EVENT(EVENT, BLK_ELAN, BLK, SIZE) \ -+ do { \ -+ elan4_store64 (E4_EVENT_INIT_VALUE(0, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, SIZE), &(EVENT)->ev_CountAndType); \ -+ elan4_store64 ((BLK_ELAN), &(EVENT)->ev_CopySource); \ -+ elan4_store64 ((BLK), &(EVENT)->ev_CopyDest); \ -+ } while (0) -+ -+#define E4_INIT_WRITE_EVENT(EVENT, DWORD) \ -+ do { \ -+ elan4_store64 (E4_EVENT_INIT_VALUE(0, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0), &(EVENT)->ev_CountAndType); \ -+ elan4_store64 ((DWORD), &(EVENT)->ev_WritePtr); \ -+ elan4_store64 ((E4_Addr) (E4_BLK_PATTERN), &(EVENT)->ev_WriteValue); \ -+ } while (0) -+ -+#define E4_RESET_BLK_EVENT(BLK) \ -+ do { \ -+ (BLK)->eb_done = (0); \ -+ } while (0) -+ -+#define E4_PRIME_BLK_EVENT(EVENT, COUNT) \ -+ do { \ -+ elan4_store64 (E4_EVENT_INIT_VALUE(COUNT, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, 8), &(EVENT)->ev_CountAndType);\ -+ } while (0) -+ -+#define E4_PRIME_COPY_EVENT(EVENT, SIZE, COUNT) \ -+ do { \ -+ elan4_store64 (E4_EVENT_INIT_VALUE(COUNT, E4_EVENT_COPY, E4_EVENT_DTYPE_LONG, (SIZE >> 3)), &(EVENT)->ev_CountAndType);\ -+ } while (0) -+ -+#define E4_PRIME_WRITE_EVENT(EVENT, COUNT) \ -+ do { \ -+ elan4_store64 (E4_EVENT_INIT_VALUE(COUNT, E4_EVENT_WRITE, E4_EVENT_DTYPE_LONG, 0), &(EVENT)->ev_CountAndType);\ -+ } while (0) -+ -+#ifndef _ASM -+ -+#define E4_INPUTQ_ALIGN 32 /* Descriptor must be 32-byte aligned */ -+ -+typedef struct _E4_InputQueue -+{ -+ volatile E4_Addr q_bptr; /* 64 bit aligned ptr to current back item */ -+ E4_Addr q_fptr; /* 64 bit aligned ptr to current front item */ -+ E4_uint64 q_control; /* this defines the last item, item size, and offset back to the first item. */ -+ E4_Addr q_event; /* queue event */ -+} E4_InputQueue; -+ -+#define E4_INPUTQ_LASTITEM_MASK 0x00000000ffffffffULL -+#define E4_INPUTQ_ITEMSIZE_MASK 0x000000ff00000000ULL -+#define E4_INPUTQ_LASTITEM_OFFSET_MASK 0xffffff0000000000ULL -+#define E4_INPUTQ_LASTITEM_SHIFT 0 -+#define E4_INPUTQ_ITEMSIZE_SHIFT 32 -+#define E4_INPUTQ_LASTITEM_OFFSET_SHIFT 40 -+ -+/* -+ * Macro to initialise the InputQueue control word given the FirstItem, LastItem & ItemSize -+ * FirstItem and LastItem are 64 bit double word aligned elan addresses. -+ */ -+#define E4_InputQueueControl(FirstItem, LastItem, ItemSizeInBytes)\ -+ (((((E4_uint64)(LastItem))) & E4_INPUTQ_LASTITEM_MASK) |\ -+ ((((E4_uint64)(ItemSizeInBytes)) << (E4_INPUTQ_ITEMSIZE_SHIFT-3)) & E4_INPUTQ_ITEMSIZE_MASK) |\ -+ ((((E4_uint64)((FirstItem)-(LastItem))) << (E4_INPUTQ_LASTITEM_OFFSET_SHIFT-3)) & E4_INPUTQ_LASTITEM_OFFSET_MASK)) -+ -+/* -+ * LastItemOffset is a sign extended -ve quantity with LastItemOffset[26:3] == q_control[63:40] -+ * we sign extend this by setting LastItemOffset[63:27] to be #one. -+ */ -+#define E4_InputQueueLastItemOffset(control) ((((E4_int64) -1) << (64 - (E4_INPUTQ_LASTITEM_OFFSET_SHIFT-3))) | \ -+ ((E4_int64) (((control) & E4_INPUTQ_LASTITEM_OFFSET_MASK) >> (E4_INPUTQ_LASTITEM_OFFSET_SHIFT-3)))) -+#define E4_InputQueueItemSize(control) (((control) & E4_INPUTQ_ITEMSIZE_MASK) >> (E4_INPUTQ_ITEMSIZE_SHIFT-3)) -+ -+/* -+ * Macro to increment the InputQ front pointer taking into account wrap -+ */ -+#define E4_InputQueueFptrIncrement(Q, FirstItem, LastItem, ItemSizeInBytes) \ -+ ((Q)->q_fptr = ( ((Q)->q_fptr == (LastItem)) ? (FirstItem) : ((Q)->q_fptr + (ItemSizeInBytes))) ) -+ -+#endif /* _ASM */ -+ -+#endif /* __ELAN4_EVENTS_H */ -Index: linux-2.4.21/include/elan4/i2c.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/i2c.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/i2c.h 2005-06-01 23:12:54.736418280 -0400 -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN4_I2C_H -+#define _ELAN4_I2C_H -+ -+#ident "@(#)$Id: i2c.h,v 1.10 2003/12/02 16:11:22 lee Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/elan4hdr/i2c.h,v $*/ -+ -+/* I2C address space - bits[7:1] */ -+#define I2C_LED_I2C_ADDR 0x20 -+#define I2C_TEMP_ADDR 0x48 -+#define I2C_EEPROM_ADDR 0x50 -+ -+#define I2C_WRITE_ADDR(addr) ((addr) << 1 | 0) -+#define I2C_READ_ADDR(addr) ((addr) << 1 | 1) -+ -+/* I2C EEPROM appears as 8 I2C 256 byte devices */ -+#define I2C_24LC16B_BLOCKSIZE (256) -+#define I2C_24LC16B_BLOCKADDR(addr) ((addr) >> 8) -+#define I2C_24LC16B_BLOCKOFFSET(addr) ((addr) & 0xff) -+ -+#define I2C_ELAN_EEPROM_PCI_BASEADDR 0 /* PCI config starts at addr 0 in the EEPROM */ -+#define I2C_ELAN_EEPROM_VPD_BASEADDR 256 /* VPD data start */ -+#define I2C_ELAN_EEPROM_PCI_SIZE 256 /* PCI data max size */ -+#define I2C_ELAN_EEPROM_VPD_SIZE 256 /* VPD data max size */ -+ -+#define I2C_ELAN_EEPROM_SIZE 2048 -+ -+#define I2C_ELAN_EEPROM_DEVICE_ID 0xA0 -+#define I2C_ELAN_EEPROM_FAIL_LIMIT 8 -+ -+#define I2C_ELAN_EEPROM_ADDR_BLOCKSIZE_SHIFT 0x8 -+#define I2C_ELAN_EEPROM_ADDR_BLOCK_MASK 0x7 -+#define I2C_ELAN_EEPROM_ADDR_BLOCK_SHIFT 0x1 -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* _ELAN4_I2C_H */ -Index: linux-2.4.21/include/elan4/intcookie.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/intcookie.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/intcookie.h 2005-06-01 23:12:54.737418128 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: intcookie.h,v 1.10 2004/08/09 14:02:37 daniel Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/intcookie.h,v $*/ -+ -+#ifndef __ELAN4_INTCOOKIE_H -+#define __ELAN4_INTCOOKIE_H -+ -+typedef E4_uint64 ELAN4_INTCOOKIE; -+ -+#ifdef __KERNEL__ -+ -+typedef struct intcookie_entry -+{ -+ struct intcookie_entry *ent_next; -+ struct intcookie_entry *ent_prev; -+ -+ spinlock_t ent_lock; -+ unsigned ent_ref; -+ -+ ELAN4_INTCOOKIE ent_cookie; -+ ELAN4_INTCOOKIE ent_fired; -+ kcondvar_t ent_wait; -+} INTCOOKIE_ENTRY; -+ -+typedef struct intcookie_table -+{ -+ struct intcookie_table *tbl_next; -+ struct intcookie_table *tbl_prev; -+ -+ ELAN_CAPABILITY *tbl_cap; -+ -+ spinlock_t tbl_lock; -+ unsigned tbl_ref; -+ INTCOOKIE_ENTRY *tbl_entries; -+} INTCOOKIE_TABLE; -+ -+extern void intcookie_init(void); -+extern void intcookie_fini(void); -+extern INTCOOKIE_TABLE *intcookie_alloc_table (ELAN_CAPABILITY *cap); -+extern void intcookie_free_table (INTCOOKIE_TABLE *tbl); -+extern int intcookie_alloc (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie); -+extern int intcookie_free (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie); -+extern int intcookie_fire (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie); -+extern int intcookie_fire_cap (ELAN_CAPABILITY *cap, ELAN4_INTCOOKIE cookie); -+extern int intcookie_wait (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie); -+extern int intcookie_arm (INTCOOKIE_TABLE *tbl, ELAN4_INTCOOKIE cookie); -+ -+#endif /* __KERNEL */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_INTCOOKIE_H */ -Index: linux-2.4.21/include/elan4/ioctl.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/ioctl.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/ioctl.h 2005-06-01 23:12:54.738417976 -0400 -@@ -0,0 +1,320 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_IOCTL_H -+#define __ELAN4_IOCTL_H -+ -+#ident "@(#)$Id: ioctl.h,v 1.27.6.2 2005/01/11 12:15:39 duncant Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/ioctl.h,v $*/ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define ELAN4IO_CONTROL_PATHNAME "/dev/elan4/control%d" -+#define ELAN4IO_USER_PATHNAME "/dev/elan4/user%d" -+#define ELAN4IO_SDRAM_PATHNAME "/dev/elan4/sdram%d" -+#define ELAN4IO_MAX_PATHNAMELEN 32 -+ -+/* -+ * NOTE - ioctl values 0->0x1f are defined for -+ * generic/control usage. -+ */ -+ -+/* Macro to generate 'offset' to mmap "control" device */ -+#define OFF_TO_BAR(off) (((off) >> 28) & 0xF) -+#define OFF_TO_OFFSET(off) ((off) & 0x0FFFFFFF) -+#define GEN_OFF(bar,off) (((bar) << 28) | ((off) & 0x0FFFFFFF)) -+ -+/* Definiations for generic ioctls */ -+#define ELAN4IO_GENERIC_BASE 0x00 -+ -+typedef struct elan4io_stats_struct -+{ -+ int which; -+ unsigned long long ptr; /* always pass pointer as 64 bit */ -+} ELAN4IO_STATS_STRUCT; -+ -+#define ELAN4IO_STATS _IOR ('e', ELAN4IO_GENERIC_BASE + 0, ELAN4IO_STATS_STRUCT) -+#define ELAN4IO_DEVINFO _IOR ('e', ELAN4IO_GENERIC_BASE + 1, ELAN_DEVINFO) -+#define ELAN4IO_POSITION _IOR ('e', ELAN4IO_GENERIC_BASE + 2, ELAN_POSITION) -+ -+ -+/* -+ * Definitions for /dev/elan4/controlX -+ */ -+#define ELAN4IO_CONTROL_BASE 0x20 -+ -+#define ELAN4IO_GET_POSITION _IOR ('e', ELAN4IO_CONTROL_BASE + 0, ELAN_POSITION) -+#define ELAN4IO_SET_POSITION _IOW ('e', ELAN4IO_CONTROL_BASE + 1, ELAN_POSITION) -+#define ELAN4IO_DEBUG_SNAPSHOT _IOW ('e', ELAN4IO_CONTROL_BASE + 2, ) -+ -+typedef struct elan4io_params_mask_struct -+{ -+ unsigned short p_mask; -+ ELAN_PARAMS p_params; -+} ELAN4IO_PARAMS_STRUCT; -+#define ELAN4IO_GET_PARAMS _IOR ('e', ELAN4IO_CONTROL_BASE + 3, ELAN4IO_PARAMS_STRUCT) -+#define ELAN4IO_SET_PARAMS _IOW ('e', ELAN4IO_CONTROL_BASE + 4, ELAN4IO_PARAMS_STRUCT) -+ -+/* old versions - implicit p_mask == 3 */ -+#define ELAN4IO_OLD_GET_PARAMS _IOR ('e', ELAN4IO_CONTROL_BASE + 3, ELAN_PARAMS) -+#define ELAN4IO_OLD_SET_PARAMS _IOW ('e', ELAN4IO_CONTROL_BASE + 4, ELAN_PARAMS) -+ -+/* -+ * Definitions for /dev/elan4/userX -+ */ -+#define ELAN4IO_USER_BASE 0x40 -+ -+#define ELAN4IO_FREE _IO ('e', ELAN4IO_USER_BASE + 0) -+#define ELAN4IO_ATTACH _IOWR ('e', ELAN4IO_USER_BASE + 1, ELAN_CAPABILITY) -+#define ELAN4IO_DETACH _IOWR ('e', ELAN4IO_USER_BASE + 2, ELAN_CAPABILITY) -+#define ELAN4IO_BLOCK_INPUTTER _IO ('e', ELAN4IO_USER_BASE + 3) -+ -+typedef struct elan4io_add_p2pvp_struct -+{ -+ unsigned vp_process; -+ ELAN_CAPABILITY vp_capability; -+} ELAN4IO_ADD_P2PVP_STRUCT; -+ -+#define ELAN4IO_ADD_P2PVP _IOW ('e', ELAN4IO_USER_BASE + 4, ELAN4IO_ADD_P2PVP_STRUCT) -+ -+typedef struct elan4io_add_bcastvp_struct -+{ -+ unsigned int vp_process; -+ unsigned int vp_lowvp; -+ unsigned int vp_highvp; -+} ELAN4IO_ADD_BCASTVP_STRUCT; -+ -+#define ELAN4IO_ADD_BCASTVP _IOW ('e', ELAN4IO_USER_BASE + 5, ELAN4IO_ADD_BCASTVP_STRUCT) -+ -+#define ELAN4IO_REMOVEVP _IO ('e', ELAN4IO_USER_BASE + 6) -+ -+typedef struct elan4io_route_struct -+{ -+ unsigned int rt_process; -+ unsigned int rt_error; -+ E4_VirtualProcessEntry rt_route; -+} ELAN4IO_ROUTE_STRUCT; -+ -+#define ELAN4IO_SET_ROUTE _IOW ('e', ELAN4IO_USER_BASE + 7, ELAN4IO_ROUTE_STRUCT) -+#define ELAN4IO_RESET_ROUTE _IOW ('e', ELAN4IO_USER_BASE + 9, ELAN4IO_ROUTE_STRUCT) -+#define ELAN4IO_GET_ROUTE _IOWR ('e', ELAN4IO_USER_BASE + 8, ELAN4IO_ROUTE_STRUCT) -+#define ELAN4IO_CHECK_ROUTE _IOWR ('e', ELAN4IO_USER_BASE + 10, ELAN4IO_ROUTE_STRUCT) -+ -+typedef struct elan4io_alloc_cq_struct -+{ -+ unsigned int cq_size; /* input: size of queue */ -+ unsigned int cq_perm; /* input: requested permissions */ -+ unsigned int cq_type; /* input: queue type */ -+ unsigned int cq_indx; /* output: queue number */ -+} ELAN4IO_ALLOCCQ_STRUCT; -+ -+#define ELAN4IO_ALLOCCQ _IOWR ('e', ELAN4IO_USER_BASE + 11, ELAN4IO_ALLOCCQ_STRUCT) -+#define ELAN4IO_FREECQ _IOWR ('e', ELAN4IO_USER_BASE + 12, unsigned) -+ -+#define ELAN4IO_CQ_TYPE_REORDER 1 /* revb reordering command queue */ -+ -+typedef struct elan4io_perm_struct -+{ -+ E4_Addr ps_eaddr; -+ E4_uint64 ps_len; -+ unsigned long ps_maddr; -+ unsigned int ps_perm; -+} ELAN4IO_PERM_STRUCT; -+ -+typedef struct elan4io_perm_struct32 -+{ -+ E4_Addr ps_eaddr; -+ E4_uint64 ps_len; -+ unsigned int ps_maddr; -+ unsigned int ps_perm; -+} ELAN4IO_PERM_STRUCT32; -+ -+#define ELAN4IO_SETPERM _IOWR ('e', ELAN4IO_USER_BASE + 13, ELAN4IO_PERM_STRUCT) -+#define ELAN4IO_SETPERM32 _IOWR ('e', ELAN4IO_USER_BASE + 13, ELAN4IO_PERM_STRUCT32) -+#define ELAN4IO_CLRPERM _IOWR ('e', ELAN4IO_USER_BASE + 14, ELAN4IO_PERM_STRUCT) -+#define ELAN4IO_CLRPERM32 _IOWR ('e', ELAN4IO_USER_BASE + 14, ELAN4IO_PERM_STRUCT32) -+ -+typedef struct elan4io_trapsig_struct -+{ -+ int ts_signo; -+} ELAN4IO_TRAPSIG_STRUCT; -+#define ELAN4IO_TRAPSIG _IOW ('e', ELAN4IO_USER_BASE + 15, ELAN4IO_TRAPSIG_STRUCT) -+ -+typedef struct elan4io_traphandler_struct -+{ -+ unsigned int th_nticks; /* number of ticks to sleep for next trap */ -+ unsigned int th_proc; /* elan processor involved */ -+ unsigned long th_trapp; /* space to store trap */ -+} ELAN4IO_TRAPHANDLER_STRUCT; -+ -+typedef struct elan4io_traphandler_struct32 -+{ -+ unsigned int th_nticks; /* number of ticks to sleep for next trap */ -+ unsigned int th_proc; /* elan processor involved */ -+ unsigned int th_trapp; /* space to store trap */ -+} ELAN4IO_TRAPHANDLER_STRUCT32; -+ -+#define ELAN4IO_TRAPHANDLER _IOW ('e', ELAN4IO_USER_BASE + 16, ELAN4IO_TRAPHANDLER_STRUCT) -+#define ELAN4IO_TRAPHANDLER32 _IOW ('e', ELAN4IO_USER_BASE + 16, ELAN4IO_TRAPHANDLER_STRUCT32) -+ -+typedef struct elan4io_required_mappings_struct -+{ -+ E4_Addr rm_upage_addr; /* elan address of user page */ -+ E4_Addr rm_trestart_addr; /* elan address of tproc restart trampoline */ -+} ELAN4IO_REQUIRED_MAPPINGS_STRUCT; -+#define ELAN4IO_REQUIRED_MAPPINGS _IOW ('e', ELAN4IO_USER_BASE + 17, ELAN4IO_REQUIRED_MAPPINGS_STRUCT) -+ -+typedef struct elan4io_resume_eproc_trap_struct -+{ -+ E4_Addr rs_addr; -+} ELAN4IO_RESUME_EPROC_TRAP_STRUCT; -+#define ELAN4IO_RESUME_EPROC_TRAP _IOW ('e', ELAN4IO_USER_BASE + 18, ELAN4IO_RESUME_EPROC_TRAP_STRUCT) -+ -+typedef struct elan4io_resume_cproc_trap_struct -+{ -+ unsigned int rs_indx; -+} ELAN4IO_RESUME_CPROC_TRAP_STRUCT; -+#define ELAN4IO_RESUME_CPROC_TRAP _IOW ('e', ELAN4IO_USER_BASE + 19, ELAN4IO_RESUME_CPROC_TRAP_STRUCT) -+ -+typedef struct elan4io_resume_dproc_trap_struct -+{ -+ E4_DMA rs_desc; -+} ELAN4IO_RESUME_DPROC_TRAP_STRUCT; -+#define ELAN4IO_RESUME_DPROC_TRAP _IOW ('e', ELAN4IO_USER_BASE + 20, ELAN4IO_RESUME_DPROC_TRAP_STRUCT) -+ -+typedef struct elan4io_resume_tproc_trap_struct -+{ -+ E4_ThreadRegs rs_regs; -+} ELAN4IO_RESUME_TPROC_TRAP_STRUCT; -+#define ELAN4IO_RESUME_TPROC_TRAP _IOW ('e', ELAN4IO_USER_BASE + 21, ELAN4IO_RESUME_TPROC_TRAP_STRUCT) -+ -+typedef struct elan4io_resume_iproc_trap_struct -+{ -+ unsigned int rs_channel; -+ unsigned int rs_trans; -+ E4_IprocTrapHeader rs_header; -+ E4_IprocTrapData rs_data; -+} ELAN4IO_RESUME_IPROC_TRAP_STRUCT; -+#define ELAN4IO_RESUME_IPROC_TRAP _IOW ('e', ELAN4IO_USER_BASE + 22, ELAN4IO_RESUME_IPROC_TRAP_STRUCT) -+ -+#define ELAN4IO_FLUSH_ICACHE _IO ('e', ELAN4IO_USER_BASE + 23) -+#define ELAN4IO_STOP_CTXT _IO ('e', ELAN4IO_USER_BASE + 24) -+ -+#define ELAN4IO_ALLOC_INTCOOKIE _IOW ('e', ELAN4IO_USER_BASE + 25, ELAN4_INTCOOKIE) -+#define ELAN4IO_FREE_INTCOOKIE _IOW ('e', ELAN4IO_USER_BASE + 26, ELAN4_INTCOOKIE) -+#define ELAN4IO_ARM_INTCOOKIE _IOW ('e', ELAN4IO_USER_BASE + 27, ELAN4_INTCOOKIE) -+#define ELAN4IO_WAIT_INTCOOKIE _IOW ('e', ELAN4IO_USER_BASE + 28, ELAN4_INTCOOKIE) -+ -+typedef struct elan4io_alloc_trap_queues_struct -+{ -+ unsigned int tq_ndproc_traps; -+ unsigned int tq_neproc_traps; -+ unsigned int tq_ntproc_traps; -+ unsigned int tq_nthreads; -+ unsigned int tq_ndmas; -+} ELAN4IO_ALLOC_TRAP_QUEUES_STRUCT; -+#define ELAN4IO_ALLOC_TRAP_QUEUES _IOW ('e', ELAN4IO_USER_BASE + 29, ELAN4IO_ALLOC_TRAP_QUEUES_STRUCT) -+ -+typedef struct elan4io_neterr_msg_struct -+{ -+ unsigned int nm_vp; -+ unsigned int nm_nctx; -+ unsigned int nm_retries; -+ unsigned int nm_pad; -+ ELAN4_NETERR_MSG nm_msg; -+} ELAN4IO_NETERR_MSG_STRUCT; -+#define ELAN4IO_NETERR_MSG _IOW ('e', ELAN4IO_USER_BASE + 30, ELAN4IO_NETERR_MSG_STRUCT) -+ -+typedef struct elan4io_neterr_timer_struct -+{ -+ unsigned int nt_usecs; -+} ELAN4IO_NETERR_TIMER_STUCT; -+ -+#define ELAN4IO_NETERR_TIMER _IO ('e', ELAN4IO_USER_BASE + 31) -+ -+typedef struct elan4io_neterr_fixup_struct -+{ -+ E4_uint64 nf_cookie; -+ unsigned int nf_waitforeop; -+ unsigned int nf_sten; -+ unsigned int nf_vp; -+ unsigned int nf_pad; -+} ELAN4IO_NETERR_FIXUP_STRUCT; -+ -+#define ELAN4IO_NETERR_FIXUP _IOW ('e', ELAN4IO_USER_BASE + 32, ELAN4IO_NETERR_FIXUP_STRUCT) -+ -+typedef struct elan4io_firecap_struct -+{ -+ ELAN_CAPABILITY fc_capability; -+ ELAN4_INTCOOKIE fc_cookie; -+} ELAN4IO_FIRECAP_STRUCT; -+ -+#define ELAN4IO_FIRE_INTCOOKIE _IOW ('e', ELAN4IO_USER_BASE + 33, ELAN4IO_FIRECAP_STRUCT) -+ -+#define ELAN4IO_ALLOC_INTCOOKIE_TABLE _IOW ('e', ELAN4IO_USER_BASE + 34, ELAN_CAPABILITY) -+#define ELAN4IO_FREE_INTCOOKIE_TABLE _IO ('e', ELAN4IO_USER_BASE + 35) -+ -+typedef struct elan4io_translation -+{ -+ E4_Addr tr_addr; -+ unsigned long tr_len; -+ unsigned int tr_access; -+} ELAN4IO_TRANSLATION_STRUCT; -+ -+#define ELAN4IO_LOAD_TRANSLATION _IOW ('e', ELAN4IO_USER_BASE + 36, ELAN4IO_TRANSLATION_STRUCT) -+#define ELAN4IO_UNLOAD_TRANSLATION _IOW ('e', ELAN4IO_USER_BASE + 37, ELAN4IO_TRANSLATION_STRUCT) -+ -+typedef struct elan4io_dumpcq_struct32 -+{ -+ E4_uint64 cq_space; /* output: sdram addr of q, used to decode ptrs */ -+ E4_uint32 cq_size; /* output: The real size of the command queue */ -+ E4_uint32 bufsize; /* input: The size of the buffer to dump to */ -+ E4_uint32 cq_indx; /* input: index of cq to dump */ -+ unsigned int buffer; /* input: user address of rgs->buffer to dump to */ -+} ELAN4IO_DUMPCQ_STRUCT32; -+ -+typedef struct elan4io_dumpcq_struct -+{ -+ E4_uint64 cq_space; /* output: sdram addr of q, used to decode ptrs */ -+ E4_uint32 cq_size; /* output: The real size of the command queue */ -+ E4_uint32 bufsize; /* input: The size of the buffer to dump to */ -+ E4_uint32 cq_indx; /* input: index of cq to dump */ -+ unsigned long buffer; /* input: user address of rgs->buffer to dump to */ -+} ELAN4IO_DUMPCQ_STRUCT; -+ -+#define ELAN4IO_DUMPCQ _IOWR ('e', ELAN4IO_USER_BASE + 38, ELAN4IO_DUMPCQ_STRUCT) -+#define ELAN4IO_DUMPCQ32 _IOWR ('e', ELAN4IO_USER_BASE + 38, ELAN4IO_DUMPCQ_STRUCT32) -+ -+/* mmap offsets - - we define the file offset space as follows: -+ * -+ * page 0 - 4095 - command queues -+ * page 4096 - device user registers -+ * page 4097 - flag page/user stats -+ * page 4098 - device stats -+ * page 4099 - tproc trampoline -+ */ -+ -+#define ELAN4_OFF_COMMAND_QUEUES 0 -+#define ELAN4_OFF_USER_REGS 4096 -+#define ELAN4_OFF_USER_PAGE 4097 -+#define ELAN4_OFF_DEVICE_STATS 4098 -+#define ELAN4_OFF_TPROC_TRAMPOLINE 4099 -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_IOCTL_H */ -Index: linux-2.4.21/include/elan4/mmu.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/mmu.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/mmu.h 2005-06-01 23:12:54.738417976 -0400 -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: mmu.h,v 1.11 2004/04/21 12:04:24 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/mmu.h,v $*/ -+ -+ -+#ifndef __ELAN4_MMU_H -+#define __ELAN4_MMU_H -+ -+typedef struct elan4_hash_entry -+{ -+ struct elan4_hash_entry *he_next; -+ struct elan4_hash_entry *he_prev; -+ -+ sdramaddr_t he_entry; -+ -+ struct elan4_hash_entry *he_chain[2]; -+ E4_uint64 he_tag[2]; -+ E4_uint32 he_pte[2]; -+} ELAN4_HASH_ENTRY; -+ -+#define ELAN4_HENT_CHUNKS 16 /* SDRAM_MIN_BLOCK_SIZE/sizeof (E4_HashTableEntry) */ -+ -+typedef struct elan4_hash_chunk -+{ -+ struct list_head hc_link; -+ ELAN4_HASH_ENTRY hc_hents[ELAN4_HENT_CHUNKS]; -+} ELAN4_HASH_CHUNK; -+ -+typedef struct elan4_hash_cache -+{ -+ E4_Addr hc_start; -+ E4_Addr hc_end; -+ int hc_tbl; -+ -+ ELAN4_HASH_ENTRY *hc_hes[1]; -+} ELAN4_HASH_CACHE; -+ -+/* -+ * he_pte is really 4 bytes of pte "type" one for each pte -+ * entry - however we declare it as an "int" so we can -+ * easily determine that all 4 entries are invalid -+ */ -+#define HE_SET_PTE(he,tagidx,pteidx,val) (((E4_uint8 *) &(he->he_pte[tagidx]))[pteidx] = (val)) -+#define HE_GET_PTE(he,tagidx,pteidx) (((E4_uint8 *) &(he->he_pte[tagidx]))[pteidx]) -+ -+/* -+ * he_tag has the following form : -+ * [63:27] tag -+ * [20:17] pte valid -+ * [16] locked -+ * [15] copy -+ * [14] valid -+ * [13:0] context -+ */ -+ -+#define HE_TAG_VALID (1 << 14) -+#define HE_TAG_COPY (1 << 15) -+#define HE_TAG_LOCKED (1 << 16) -+ -+#define INVALID_CONTEXT 0 -+ -+extern u_char elan4_permtable[]; -+#define ELAN4_INCOMPAT_ACCESS(perm,access) ((elan4_permtable[(perm)] & (1 << (access))) == 0) -+extern u_char elan4_permreadonly[]; -+#define ELAN4_PERM_READONLY(perm) (elan4_permreadonly[(perm)]) -+ -+/* return code from elan4mmu_categorise_paddr */ -+#define ELAN4MMU_PADDR_SDRAM 0 -+#define ELAN4MMU_PADDR_COMMAND 1 -+#define ELAN4MMU_PADDR_LOCALPCI 2 -+#define ELAN4MMU_PADDR_PAGE 3 -+#define ELAN4MMU_PADDR_OTHER 4 -+ -+extern int elan4_debug_mmu; -+ -+#ifdef DEBUG_PRINTF -+# define MPRINTF(ctxt,lvl,args...) (elan4_debug_mmu > (lvl) ? elan4_debugf(ctxt,DBG_MMU, ##args) : (void)0) -+#else -+# define MPRINTF(ctxt,lvl,args...) ((void) 0) -+#endif -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_MMU_H */ -Index: linux-2.4.21/include/elan4/neterr.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/neterr.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/neterr.h 2005-06-01 23:12:54.738417976 -0400 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2004 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_NETERR_H -+#define __ELAN4_NETERR_H -+ -+#ident "@(#)$Id: neterr.h,v 1.1 2004/01/19 14:38:34 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/elan4mod/neterr.h,v $*/ -+ -+typedef struct elan4_neterr_msg -+{ -+ E4_uint8 msg_type; -+ E4_uint8 msg_waitforeop; -+ E4_uint16 msg_context; /* network context # message sent to */ -+ E4_int16 msg_found; /* # cookie found (response) */ -+ -+ ELAN_LOCATION msg_sender; /* nodeid/context # message sent from */ -+ E4_uint32 msg_pad; -+ -+ E4_uint64 msg_cookies[6]; /* 64 bit cookies from identify packets */ -+} ELAN4_NETERR_MSG; -+ -+#define ELAN4_NETERR_MSG_SIZE sizeof (ELAN4_NETERR_MSG) -+#define ELAN4_NETERR_MSG_REQUEST 1 -+#define ELAN4_NETERR_MSG_RESPONSE 2 -+ -+#define ELAN4_NETERR_MAX_COOKIES (sizeof (((ELAN4_NETERR_MSG *) 0)->msg_cookies) / \ -+ sizeof (((ELAN4_NETERR_MSG *) 0)->msg_cookies[0])) -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_NETERR_H */ -Index: linux-2.4.21/include/elan4/pci.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/pci.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/pci.h 2005-06-01 23:12:54.739417824 -0400 -@@ -0,0 +1,227 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_PCI_H -+#define __ELAN4_PCI_H -+ -+#ident "$Id: pci.h,v 1.32 2003/09/04 12:39:17 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/pci.h,v $*/ -+ -+/* Elan has 2 64 bit bars */ -+#define ELAN4_BAR_SDRAM 0 -+#define ELAN4_BAR_REGISTERS 2 -+ -+#define PCI_VENDOR_ID_QUADRICS 0x14fc -+#define PCI_DEVICE_ID_ELAN3 0x0000 -+#define PCI_REVISION_ID_ELAN3_REVA 0x0000 -+#define PCI_REVISION_ID_ELAN3_REVB 0x0001 -+#define PCI_DEVICE_ID_ELAN4 0x0001 -+#define PCI_REVISION_ID_ELAN4_REVA 0x0000 -+#define PCI_REVISION_ID_ELAN4_REVB 0x0001 -+ -+/* support standard pseudo bars */ -+#define ELAN4_PSEUDO_BAR_ROM 8 -+ -+/* Elan PCI control -+ configuration space register. ElanControlRegister */ -+#define PCI_ELAN_PARITY_ADDR_LO 0x40 -+#define PCI_ELAN_PARITY_ADDR_HI 0x44 -+#define PCI_ELAN_PARITY_TYPE 0x48 -+#define PCI_ELAN_CONTROL 0x4c -+#define PCI_ELAN_PLL_CONTROL 0x50 -+#define PCI_ELAN_SPLIT_MESSAGE_ATTR 0x54 -+#define PCI_ELAN_SPLIT_MESSAGE_VALUE 0x54 -+#define PCI_ELAN_RAMBIST_FAILED 0x54 -+#define PCI_ELAN_TOPPHYSADDR(i) (0x58 + ((i)<<1)) -+ -+/* -+ * [31] PciM66EN This is set it the bus is running in PCI2.3 - 66MHz mode. -+ * [30:28] InitPattern This gives the PCI-X startup mode. See "Pci intialisation patterns" below. -+ * [27] notBusIs64Bits If set the bus is running 32 bits wide. If Clear it is a 64 bit bus. -+ * [26:24] RamBistCntl Used to control the Elan4 RAM BIST. Not acitive it zero. -+ * [23] RamBistFinished Only used when performing the RAM BIST test. -+ * [22] SelectSplitMessAttr See ECTRL_SELECT_SPLIT_MESS_ATTR below. -+ * [21] ReceivedSplitCompError See ECTRL_REC_SPLIT_COMP_MESSAGE below -+ * [20:16] WriteHighPriTime Used with ReadHighPriTime to control the ratio of PCI master write to PCI master -+ * read bandwidth under heavy load. The high the value of WriteHighPriTime the longer -+ * the PCI write bursts will be allowed without interruption from a read transfer. -+ * [15] DisableCouplingTest This is only used as part of the RAM BIST test. It effects the testing of the main -+ * cache tag RAMS. -+ * [14:13] Not used Will read as zero. -+ * [12:8] ReadHighPriTime Used with WriteHighPriTime to control the ratio of PCI master write to PCI master -+ * read bandwidth under heavy load. The high the value of ReadHighPriTime the longer -+ * the PCI read bursts will be allowed without interruption from a write transfer. -+ * [7] EnableLatencyCountReset This bit effect the behaviour of disconnects due to the removal of GNT# after the latency -+ * counter has expired. If set it will allow the latency counter to be reset each time the -+ * GNT# is reasserted. If asserted it should provided improved bandwidth on the PCI bus -+ * without increasing the maximum latency another device would have for access to the bus. -+ * It will increase the average latency of other devices. -+ * [6] ExtraMasterAddrBits This bit used to control the physical PCI addresses generated by the MMU. -+ * [5] ReducedPciDecode If set the PCI local memory BAR will decode 256Mbytes of PCI address space. If clear it -+ * will decode 2Gbyte of PCI address space. -+ * [4] ConfigInEBusRom If set the constant values of the Elan4 PCI configuration space will be taken from the -+ * EEPROM. If clear the internal values will be used. -+ * [3] EnableRd2_2Bursts This bit only effects the behaviour of burst reads when the PCI bus is operating in -+ * PCI-2.2 mode. It allows adjacent reads to be merged into longer bursts for higher -+ * performance. -+ * [2] SoftIntReset If set this bit will cause the Elan4 to reset itself with the exception of the PCI -+ * configuation space. All internal state machines will be put into the reset state. -+ * [1] EnableWrBursts This bit allows much longer PCI-X write bursts. If set it will stop the Elan4 from -+ * being completely PCI-X compliant as the Elan4 may request a long PCI-X write burst that -+ * it does not complete. However it should significantly increase the maximum PCI-X write -+ * bandwidth and is unlikely to cause problems with many PCI-X bridge chips. -+ * [0] InvertMSIPriority This bit effect the way MSI interrupts are generated. It provides flexiblity to generate -+ * the MSI interrupts in a different way to allow for different implimentations of MSI -+ * logic and still give the correct priority of Elan4 interrupts. -+ * -+ * {PciM66EN, InitPattern, notBusIs64Bits, RamBistCntl, RamBistFinished, -+ * SelectSplitMessAttr, ReceivedSplitCompError, WriteHighPriTime, -+ * DisableCouplingTest, 2'h0, ReadHighPriTime, -+ * EnableLatencyCountReset, ExtraMasterAddrBits, ReducedPciDecode, ConfigInEBusRom, -+ * EnableRd2_2Bursts, SoftIntReset, EnableWrBursts, InvertMSIPriority} -+ */ -+ -+#define ECTRL_INVERT_MSI_PRIO (1 << 0) -+#define ECTRL_ENABLE_WRITEBURSTS (1 << 1) -+#define ECTRL_SOFTWARE_INTERNAL_RESET (1 << 2) -+#define ECTRL_ENABLE_2_2READBURSTS (1 << 3) -+#define ECTRL_CONFIG_IN_EBUS_ROM (1 << 4) -+#define ECTRL_28_NOT_30_BIT_LOCAL_BAR (1 << 5) -+#define ECTRL_ExtraMasterAddrBits (1 << 6) -+#define ECTRL_ENABLE_LATENCY_RESET (1 << 7) -+#define ECTRL_DISABLE_COUPLING_TEST (1 << 15) -+ -+/* -+ * Ratio of the following two registers set the relative bandwidth given to intputer data -+ * versus other PCI pci traffic when scheduling new PCI master accesses. -+ */ -+#define ECTRL_OTHER_HIGH_PRI_TIME_SHIFT (8) /* Sets top 4 bits of 8 bit counter */ -+#define ECTRL_OTHER_HIGH_PRI_TIME_MASK (0x1f) -+ -+ -+#define ECTRL_IPROC_HIGH_PRI_TIME_SHIFT (16) /* Sets top 4 bits of 8 bit counter */ -+#define ECTRL_IPROC_HIGH_PRI_TIME_MASK (0x1f) -+ -+/* -+ * This is set if a split completion message is received. -+ * This will cause a PCI error interrupt. -+ * This error is cleared by writting a 1 to this bit. -+ */ -+#define ECTRL_REC_SPLIT_COMP_MESSAGE (1 << 21) -+/* -+ * This bit is used to select reading of either the Split message attribute value when -+ * set or the split completion message data value from 0x54 in the config space -+ * if the ECTRL_REC_SPLIT_COMP_MESSAGE bit is set. 0x54 returns the the BistFailed flags -+ * if any of the BIST control bits are set (bits 26 to 24) -+ */ -+#define ECTRL_SELECT_SPLIT_MESS_ATTR (1 << 22) -+ -+// Internal RAM bist control bits. -+// Three bits of state control the RAM BIST (Built in self test). -+// -+// These bits must not be set unless the ECTRL_SOFTWARE_INTERNAL_RESET bit has also been set! -+// -+// For a normal fast ram test assert ECTRL_BIST_FAST_TEST. -+// For a data retention test first write ECTRL_START_RETENTION_TEST then wait the retention period of -+// at least 1ms and preferably much longer then write ECTRL_CONTINUE_RETENTION_TEST then wait -+// again and finallly write ECTRL_FINISH_RETENTION_TEST. -+// -+// The read only bit ECTRL_BIST_FINISHED_TEST can be polled to check that the test has compleated. -+#define ECTRL_BIST_CTRL_SHIFT (24) -+#define ECTRL_BIST_CTRL_MASK (7 << 24) -+ -+#define ECTRL_BIST_FAST_TEST ((7 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) // old scheme -+#define ECTRL_START_RETENTION_TEST ((1 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) -+#define ECTRL_CONTINUE_RETENTION_TEST ((3 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) -+#define ECTRL_FINISH_RETENTION_TEST ((7 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) -+ -+#define ECTRL_BIST_KICK_OFF ((1 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) // new scheme -+#define ECTRL_BIST_MOVE_ON_ODD ((3 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) -+#define ECTRL_BIST_MOVE_ON_EVEN ((5 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) -+#define ECTRL_BIST_SCREAM_THROUGH ((7 << 24) | ECTRL_SOFTWARE_INTERNAL_RESET) -+ -+#define ECTRL_CLEAR_BIST_TEST (0 << 24) -+#define ECTRL_BIST_FINISHED_TEST (1 << 23) -+ -+// Read only current PCI bus type. -+#define ECTRL_RUNNING_32BIT_MODE (1 << 27) -+#define ECTRL_INITIALISATION_MODE (7 << 28) -+#define ECTRL_RUNNING_M66EN_MODE (1 << 31) -+ -+#define ECTRL_INIT_PATTERN_SHIFT (28) -+#define ECTRL_INIT_PATTERN_MASK (0x7) -+ -+// Pci intialisation patterns -+#define Pci2_2 (0 << 28) -+#define PciX50To66MHz (1 << 28) -+#define PciX66to100MHz (2 << 28) -+#define PciX100to133MHz (3 << 28) -+#define PciXReserved1 (4 << 28) -+#define PciXReserved2 (5 << 28) -+#define PciXReserved3 (6 << 28) -+#define PciXReserved4 (7 << 28) -+ -+/* Elan PCI pll and pad control configuration space register. ElanPllControlReg */ -+// This overrides the default PCI pll control settings. -+#define PciPll_FeedForwardISel0 (1 << 0) // Lsi name Z0 -+#define PciPll_FeedForwardISel1 (1 << 1) // Lsi name Z1 -+#define PciPll_ChargePumpISel0 (1 << 2) // Lsi name P0 -+#define PciPll_ChargePumpISel1 (1 << 3) // Lsi name P1 -+#define PciPll_EnableAutoReset (1 << 4) // Lsi name ENARST -+#define PciPll_RSEL200500 (1 << 5) // Lsi name Range Select, 0: 100 - 250MHz, 1: 200 - 500MHz -+#define PciPll_DivideFeedback (1 << 6) // Just used for test - This divides the shortcut feedback to the PCI PLL so that it can lock to the tester clock. -+#define PciPll_CutFeedback (1 << 7) // Just used for test - This disables the shortcut feedback. -+ -+// This overrides the default PCI BZ controler settings. -+#define PciBZ_UPDI (0xf << 8) -+#define PciBZ_WAIT_INT (0xf << 12) -+ -+// This overrides the default Sys and SDRam pll control settings. -+#define SysPll_FeedForwardISel0 (1 << 16) // Lsi name P0 -+#define SysPll_FeedForwardISel1 (1 << 17) // Lsi name P1 -+#define SysPll_ChargePumpISel0 (1 << 18) // Lsi name Z0 -+#define SysPll_ChargePumpISel1 (1 << 19) // Lsi name Z1 -+#define SysPll_EnableAutoReset (1 << 20) // Lsi name ENARST -+#define SysPll_DivPhaseCompInBy2 (1 << 21) // Lsi name NODIV (Should be DIV) -+#define SysPll_PllTestClkSel (1 << 22) // If asserted the master clock source is not taken from the pll. -+ -+#define Pll_ForceEBusADTristate (1 << 23) // Required to enable the testing of EnableAutoReset. Enables use of EBusAD[7] (rev A) -+#define Pll_LinkErrDirectToSDA (1 << 23) // Access to link error flag for triggering (rev B) -+ -+ -+#define ECTRL_SYS_CLOCK_RATIO_SHIFT (24) -+// Config: with 800MHz Speeds are 266 200 160 133. -+// 0 = 133/133 (1:1) 6:6 1 -+// 1 = 160/133 (6:5) 5:6 1.2 -+// 2 = 200/133 (3:2) 4:6 1.5 -+// 3 = 266/133 (2:1) 3:6 2 -+// 4 = 200/200 (1:1) 4:4 1 -+// 5 = 266/200 (4:3) 3:4 1.33 -+ -+// Config: with 600MHz Speeds are 200 150 120 100 -+// 0 = 100/100 (1:1) 6:6 1 -+// 1 = 120/100 (6:5) 5:6 1.2 -+// 2 = 150/100 (3:2) 4:6 1.5 -+// 3 = 200/100 (2:1) 3:6 2 -+// 4 = 150/150 (1:1) 4:4 1 -+// 5 = 200/150 (4:3) 3:4 1.33 -+ -+#define ECTRL_SYS_CLOCK_RATIO_SHIFT (24) -+#define ECTRL_SYS_CLOCK_RATIO_1_1Slow (0 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_6_5 (1 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_3_2 (2 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_2_1 (3 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_1_1Fast (4 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_4_3 (5 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_MAX_NORMAL (6) /* used to generate a valid random value */ -+#define GET_RANDOM_CLOCK_RATIO (Random(ECTRL_SYS_CLOCK_MAX_NORMAL) << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_PLL_TEST (6 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_TEST (7 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+#define ECTRL_SYS_CLOCK_RATIO_MASK (7 << ECTRL_SYS_CLOCK_RATIO_SHIFT) -+ -+#endif /* __ELAN4_PCI_H */ -Index: linux-2.4.21/include/elan4/registers.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/registers.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/registers.h 2005-06-01 23:12:54.742417368 -0400 -@@ -0,0 +1,1588 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN4_REGISTERS_H -+#define _ELAN4_REGISTERS_H -+ -+#ident "$Id: registers.h,v 1.117.2.1 2004/10/04 14:26:18 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/registers.h,v $*/ -+ -+/* -+ * Header file for internal slave mapping of the ELAN4 registers -+ */ -+ -+#define E4_CACHELINE_SIZE (64) -+#define E4_STACK_ALIGN (64) -+ -+#ifndef _ASM -+ -+#include -+#include -+#include -+ -+typedef volatile struct _E4_CacheSets -+{ -+ E4_uint64 Set0[1024]; /* 8k bytes per set */ -+ E4_uint64 Set1[1024]; /* 8k bytes per set */ -+ E4_uint64 Set2[1024]; /* 8k bytes per set */ -+ E4_uint64 Set3[1024]; /* 8k bytes per set */ -+} E4_CacheSets; -+ -+typedef union e4_cache_tag -+{ -+ struct { -+ E4_uint32 pad0; /* Undefined value when read */ -+#if (BYTE_ORDER == LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) -+ E4_uint32 :10; /* 0-9 - reserved */ -+ E4_uint32 LineError:1; /* 10 - line error */ -+ E4_uint32 Modified:1; /* 11 - modified */ -+ E4_uint32 FillPending:1; /* 12 - fill pending */ -+ E4_uint32 AddrTag30to13:18; /* 30-13 - tag */ -+ E4_uint32 :1; /* 31 - */ -+#else -+ E4_uint32 :1; /* 31 - */ -+ E4_uint32 AddrTag30to13:18; /* 30-13 - tag */ -+ E4_uint32 FillPending:1; /* 12 - fill pending */ -+ E4_uint32 Modified:1; /* 11 - modified */ -+ E4_uint32 LineError:1; /* 10 - line error */ -+ E4_uint32 :10; /* 0-9 - reserved */ -+#endif -+ } s; -+ E4_uint64 Value; -+} E4_CacheTag; -+ -+typedef volatile struct _E4_CacheTags -+{ -+ E4_CacheTag Tags[4][128]; /* 8k bytes per set, 64 byte cache line */ -+} E4_CacheTags; -+ -+#define E4_NumCacheSets 4 -+#define E4_NumCacheLines 128 -+#define E4_CacheLineSize 64 -+#define E4_CacheSize (E4_NumCacheSets * E4_NumCacheLines * E4_CacheLineSize) -+#define E4_CacheSetSize (E4_NumCacheLines * E4_CacheLineSize) -+ -+/* -+ * Run Queue pointers -+ * -+ * [62:35] FrontPointer[30:3] -+ * [33:32] Size Value -+ * [30:3] BackPointer[30:3] -+ */ -+#define E4_QueuePtrMask (0x7ffffff8ULL) -+#define E4_QueueSizeMask 3 -+#define E4_QueueEntrySize sizeof (E4_uint64) -+ -+#define E4_Queue8KBytes 0 -+#define E4_Queue64KBytes 1 -+#define E4_Queue512KBytes 2 -+#define E4_Queue4MBytes 3 -+ -+#define E4_QueueFrontValue(val,size) ((val) | (size)) -+#define E4_QueueValue(queue,size) (((E4_uint64) E4_QueueFrontValue(queue,size)) << 32 | ((E4_uint64) (queue))) -+ -+#define E4_QueueFrontPointer(val) /* extract queue front pointer from register */\ -+ (((val) >> 32) & E4_QueuePtrMask) -+#define E4_QueueBackPointer(val) /* extract queue back pointer from register */ \ -+ ((val) & E4_QueuePtrMask) -+#define E4_QueueSizeValue(val) /* extract queue size value from register */ \ -+ (((val) >> 32) & E4_QueueSizeMask) -+#define E4_QueueSize(value) /* queue size in bytes from size value */ \ -+ (1 << (((value)*3) + 13)) -+#define E4_QueueOffsetMask(fptr)\ -+ ((8192 << (((fptr) & E4_QueueSizeMask) << 3)) - 1) -+#define E4_QueueOffset(fptr)\ -+ ((fptr) & E4_QueueOffsetMask(fptr)) -+#define E4_QueueFrontPointerInc(fptr) \ -+ ( ((fptr) & ~E4_QueueOffsetMask(fptr)) | ((E4_QueueOffset(fptr) + 8) & E4_QueueOffsetMask(fptr)) ) -+ -+typedef union _E4_QueuePtr -+{ -+ E4_uint64 Value; -+ struct { -+ E4_uint32 Back; -+ E4_uint32 Front; -+ } s; -+} E4_QueuePtr; -+ -+/* -+ * DMA processor status register. -+ * -+ * [48] FirstSendTrans Set for the first packet of a dma. -+ * [47:46] TimeSliceCount Time left to timeslice. -+ * [45] DmaLastPacket Set for the last packet of a dma. -+ * [44] CurrPrefetchDma Dma descriptor the prefetcher is valid for. -+ * [43:39] PrefetcherState Dma prefetcher's state machines value. -+ * [38:33] PacketAssemblyState Packet assembler's state machines value. -+ * [32:31] PrefetcherWakeupFnt Dma prefetcher's wakeup function. -+ * [30:28] PacketAssWakeupFnt Packet assembler's wakeup function. -+ * [27] AckBufferValid Packet ack is valid. -+ * [26] PrefetchedDataProblem Had either a data read fault or data error. Valid if AckBufferValid. -+ * [25] PrefetcherHalting Prefetch data about to stop for halt. Valid if AckBufferValid. -+ * [24] PacketTimeout Packet timeout. Sent an EopError. Valid if AckBufferValid set. -+ * [23:22] PacketAckValue Packet ack type. Valid if AckBufferValid set. -+ * [21:20] FaultUnitNo Set if the dma prefetcher has faulted. -+ * [19:17] TrapType Packet assembler's trap type. -+ * [16] PrefetcherFault Set if the dma prefetcher has faulted for this DMA unit. -+ * [15] Remote The Dma had been issued remotly -+ * [14] Priority Running at high priority. -+ * [13:0] Context procs current context. -+ */ -+ -+#define DPROC_FirstSendTrans(s) ((unsigned)((s) >> 48) & 1) -+#define DPROC_TimeSliceCount(s) ((unsigned)(((s) >> 46) & 3) -+#define DPROC_DmaLastPacket(s) ((unsigned)((s) >> 45) & 1) -+#define DPROC_CurrPrefetchDma(s) ((unsigned)((s) >> 44) & 1) -+#define DPROC_PrefetcerState(s) ((unsigned)((s) >> 39) & 0x1f) -+#define DPROC_PacketAssemblerState(s) ((unsigned)((s) >> 33) & 0x1f) -+#define DPROC_PrefetcherWakeupFn(s) ((unsigned)((s) >> 31) & 3) -+#define DPROC_PacketAssemblerWakeupFn(s)((unsigned)((s) >> 28) & 3) -+#define DPROC_AckBufferValid(s) ((unsigned)((s) >> 27) & 1) -+#define DPROC_PrefetcherDataProblem(s) ((unsigned)((s) >> 26) & 1) -+#define DPROC_PrefetcherHalting(s) ((unsigned)((s) >> 25) & 1) -+#define DPROC_PacketTimeout(s) ((unsigned)((s) >> 24) & 1) -+#define DPROC_PacketAckValue(s) ((unsigned)((s) >> 22) & 3) -+#define DPROC_FaultUnitNo(s) ((unsigned)((s) >> 20) & 3) -+#define DPROC_TrapType(s) ((unsigned)((s) >> 17) & 7) -+#define DPROC_PrefetcherFault(s) ((unsigned)((s) >> 16) & 1) -+#define DPROC_Remote(s) ((unsigned)((s) >> 15) & 1) -+#define DPROC_Priority(s) ((unsigned)((s) >> 14) & 1) -+#define DPROC_Context(s) ((unsigned)(s) & 0x3fff) -+ -+/* -+ * Command processor status register. -+ * -+ * [26:21] CPState procs current state. -+ * [20] WakeupFnt procs wakeup function. -+ * [19:16] TrapValue procs trap value. -+ * [15] Remote Issued remotely. -+ * [14] Priority Running at high priority. -+ * [13:0] Context procs current context. -+ */ -+ -+#define CPROC_TrapType(s) ((unsigned)((s) >> 16) & 0xf) -+#define CPROC_Remote(s) ((unsigned)((s) >> 15) & 0x1) -+#define CPROC_Priority(s) ((unsigned)((s) >> 14) & 0x1) -+#define CPROC_Context(s) ((unsigned)(s) & 0x3fff) -+ -+/* -+ * Event processor status register. -+ * -+ * [34:30] CPState event procs current state. -+ * [29:28] WakeupFnt event procs wakeup function. -+ * [27:20] EventCopySize This is the number of DWords to still be copied on a copy dword event. -+ * [19] EProcPort1Fault CUN_EventProc1 has taken a translation fault. -+ * [18] EProcPort0Fault CUN_EventProc0 has taken a translation fault. -+ * [17:16] TrapValue event proc's trap value. -+ * [15] Remote Issued remotely. -+ * [14] Priority Running at high priority. -+ * [13:0] Context procs current context. -+ */ -+ -+#define EPROC_CPState(s) ((unsigned)((s) >> 30) & 0x1f) -+#define EPROC_WakeupFunction(s) ((unsigned)((s) >> 28) & 3) -+#define EPROC_CopySize(s) ((unsigned)((s) >> 20) & 0xFF) -+#define EPROC_Port1Fault(s) ((unsigned)((s) >> 19) & 1) -+#define EPROC_Port0Fault(s) ((unsigned)((s) >> 18) & 1) -+#define EPROC_TrapType(s) ((unsigned)((s) >> 16) & 3) -+#define EPROC_Remote(s) ((unsigned)((s) >> 15) & 1) -+#define EPROC_Priority(s) ((unsigned)((s) >> 14) & 1) -+#define EPROC_Context(s) ((unsigned)(s) & 0x3fff) -+ -+/* -+ * Thread processor status register. -+ * -+ * [39:24] MemPortBusy 16 bits of port busy flags for all FFU memory ports. -+ * [23:21] Reads as zero -+ * [20:18] TQState State vector for thread queuing proc. -+ * [17] HighRunQueueFull High priority run queue is full -+ * [16] LowRunQueueFull Low priority run queue is full -+ * [15] ReadyHigh More runable threads at high priority -+ * [14] ReadyLow More runable threads at low priority -+ * [13:0] Context procs current context. -+ */ -+#define TPROC_HighRunQueueFull(s) ((unsigned)((s) >> 17) & 1) -+#define TPROC_LowRunQueueFull(s) ((unsigned)((s) >> 16) & 1) -+#define TPROC_ReadyHigh(s) ((unsigned)((s) >> 15) & 1) -+#define TPROC_ReadyLow(s) ((unsigned)((s) >> 14) & 1) -+#define TPROC_Context(s) ((unsigned)((s) & 0x3fff)) -+ -+/* -+ * Input processor status register -+ * -+ * [55] Last Trans (~EOP) -+ * [54] First Trans (~EOP) -+ * [53] Channel (~EOP) -+ * [52] Bad Length (~EOP) -+ * [51:50] Trans CRC Status (~EOP) -+ * [49:48] EOP type -+ * [47] EOP trap -+ * [46] Trapping priority -+ * [45] Trapping Channel -+ * [44:43] Bad ack sent -+ * [42:41] Good ack sent -+ * [40] Queueing Packet (~EOP) -+ * [39:36] Channel trapped bits -+ * [35:32] IProc Trap Value -+ * [31:16] Network Context (~EOP) -+ * [15:0] Transaction Type (~EOP) -+ */ -+#define IPROC_LastTrans(s) ((unsigned)((s) >> 55) & 0x1) -+#define IPROC_FirstTrans(s) ((unsigned)((s) >> 54) & 0x1) -+#define IPROC_Channel(s) ((unsigned)((s) >> 53) & 0x1) -+#define IPROC_BadLength(s) ((unsigned)((s) >> 52) & 0x1) -+#define IPROC_TransCRCStatus(s) ((unsigned)((s) >> 50) & 0x3) -+#define IPROC_EOPType(s) ((unsigned)((s) >> 48) & 0x3) -+#define IPROC_EOPTrap(s) ((unsigned)((s) >> 47) & 0x1) -+#define IPROC_InputterPri(s) ((unsigned)((s) >> 46) & 0x1) -+#define IPROC_InputterChan(s) ((unsigned)((s) >> 45) & 0x1) -+#define IPROC_BadAckSent(s) ((unsigned)((s) >> 43) & 0x3) -+#define IPROC_GoodAckSent(s) ((unsigned)((s) >> 41) & 0x3) -+#define IPROC_QueueingPacket(s) ((unsigned)((s) >> 40) & 0x1) -+#define IPROC_ChannelTrapped(s) ((unsigned)((s) >> 36) & 0xF) -+#define IPROC_TrapValue(s) ((unsigned)((s) >> 32) & 0xF) -+#define IPROC_NetworkContext(s) ((unsigned)((s) >> 16) & 0xFFFF) -+#define IPROC_TransactionType(s) ((unsigned)(s) & 0xFFFF) -+ -+/* values for IPROC_TransCRCStatus */ -+#define CRC_STATUS_GOOD (0) -+#define CRC_STATUS_DISCARD (1) -+#define CRC_STATUS_ERROR (2) -+#define CRC_STATUS_BAD (3) -+ -+/* values for IPROC_EOPType */ -+#define EOP_GOOD (1) -+#define EOP_BADACK (2) -+#define EOP_ERROR_RESET (3) -+ -+/* -+ * Interrupt register bits -+ * -+ * There are up to four sources of interrupt for the MSI port. -+ * The Elan will request 4 ports but may only get either 2 or 1 port. The Interrupts are assigned -+ * as shown below: -+ * No Of MSI ints Low Prioity High Prioity -+ * 4 Event Ints OtherInts Inputer Ints Hard Error ints. -+ * i.e. Dproc, Tproc, Sten. HighPri and LowPri Link errs, ECC errs, -+ * -+ * 2 Event Ints All other interrupts. -+ * 1 All together. -+ * -+ * It is not safe to change the number of sources of interrupt while there may be outstanding, -+ * unserviced interrupts pending. -+ * There two forms of encoding. This has been provided in case an MSI implimentation assumes either -+ * a high value to have a high priority or a low value to have a high priority. This is controled -+ * by a bit in the Elan Pci Control register. -+ */ -+#define INT_LinkPortKeyFail (1<<18) -+#define INT_PciMemErr (1<<17) -+#define INT_SDRamInt (1<<16) -+#define INT_LinkError (1<<15) -+#define INT_IProcCh1HighPri (1<<14) -+#define INT_IProcCh0HighPri (1<<13) -+#define INT_IProcCh1LowPri (1<<12) -+#define INT_IProcCh0LowPri (1<<11) -+#define INT_DiscardingHighPri (1<<10) -+#define INT_DiscardingLowPri (1<<9) -+#define INT_CProcHalted (1<<8) -+#define INT_TProcHalted (1<<7) -+#define INT_DProcHalted (1<<6) -+#define INT_EProc (1<<5) -+#define INT_TProc (1<<4) -+#define INT_CProc (1<<3) -+#define INT_Dma1Proc (1<<2) -+#define INT_Dma0Proc (1<<1) -+#define INT_MainInterrupt (1<<0) -+ -+#define INT_Units (INT_EProc | INT_TProc | INT_CProc | INT_Dma1Proc | INT_Dma0Proc) -+#define INT_Inputters (INT_IProcCh1HighPri | INT_IProcCh0HighPri | INT_IProcCh1LowPri | INT_IProcCh0LowPri) -+#define INT_Discarding (INT_DiscardingHighPri | INT_DiscardingLowPri) -+#define INT_Halted (INT_CProcHalted | INT_TProcHalted | INT_DProcHalted) -+#define INT_ErrorInterrupts (INT_LinkPortKeyFail | INT_PciMemErr | INT_SDRamInt | INT_LinkError) -+ -+#define INT_MSI0 INT_MainInterrupt -+#define INT_MSI1 (INT_Units | INT_Discarding | INT_Halted) -+#define INT_MSI2 (INT_Inputters) -+#define INT_MSI3 (INT_ErrorInterrupts) -+ -+#define E4_INTERRUPT_REG_SHIFT 32 -+#define E4_INTERRUPT_MASK_MASK (0xffffffffULL) -+ -+/* -+ * Trap type values - see trapvalues.v -+ */ -+ -+#define CommandProcInserterError 0x1 -+#define CommandProcPermissionTrap 0x2 -+#define CommandProcSendTransInvalid 0x3 -+#define CommandProcSendTransExpected 0x4 -+#define CommandProcDmaQueueOverflow 0x5 -+#define CommandProcInterruptQueueOverflow 0x6 -+#define CommandProcMemoryFault 0x7 -+#define CommandProcRouteFetchFault 0x8 -+#define CommandProcFailCountZero 0x9 -+#define CommandProcAddressAlignment 0xa -+#define CommandProcWaitTrap 0xb -+#define CommandProcMultipleGuards 0xc -+#define CommandProcOpenOnGuardedChan 0xd -+#define CommandProcThreadQueueOverflow 0xe -+#define CommandProcBadData 0xf -+ -+#define DmaProcNoFault 0x0 -+#define DmaProcRouteFetchFault 0x1 -+#define DmaProcFailCountError 0x2 -+#define DmaProcPacketAckError 0x3 -+#define DmaProcRunQueueReadFault 0x4 -+#define DmaProcQueueOverflow 0x5 -+ -+#define EventProcNoFault 0x0 -+#define EventProcAddressAlignment 0x1 -+#define EventProcMemoryFault 0x2 -+#define EventProcCountWrapError 0x3 -+ -+#define InputNoFault 0x0 -+#define InputAddressAlignment 0x1 -+#define InputMemoryFault 0x2 -+#define InputInvalidTransType 0x3 -+#define InputDmaQueueOverflow 0x4 -+#define InputEventEngineTrapped 0x5 -+#define InputCrcErrorAfterPAckOk 0x6 -+#define InputEopErrorOnWaitForEop 0x7 -+#define InputEopErrorTrap 0x8 -+#define InputDiscardAfterAckOk 0x9 -+ -+typedef struct _E4_Sched_Status -+{ -+ E4_uint32 Status; -+ E4_uint32 Restart; -+} E4_Sched_Status; -+ -+typedef struct _E4_Input_Ptrs -+{ -+ E4_uint32 ContextFilterTable; -+ E4_uint32 TrapBasePtr; -+} E4_Input_Ptrs; -+ -+#define SCH_StopLowPriQueues (1 << 0) -+#define SCH_DProcHalt (1 << 1) -+#define SCH_TProcHalt (1 << 2) -+#define SCH_CProcHalt (1 << 3) -+ -+#define SCH_CProcTimeout600ns (1 << 4) -+#define SCH_CProcTimeout1p4us (2 << 4) -+#define SCH_CProcTimeout3p0us (3 << 4) -+#define SCH_CProcTimeout6p2us (4 << 4) -+#define SCH_CProcTimeout12p6us (5 << 4) -+#define SCH_CProcTimeout25p4us (6 << 4) -+#define SCH_CProcTimeout51p0us (7 << 4) -+#define SCH_DiscardLowPriInput (1 << 7) -+#define SCH_DiscardHighPriInput (1 << 8) -+ -+#define SCH_DProcTimeslice64us (0 << 9) -+#define SCH_DProcTimeslice128us (1 << 9) -+#define SCH_DProcTimeslice256us (2 << 9) -+#define SCH_DProcTimeslice512us (3 << 9) -+ -+#define SCH_Halt (SCH_StopLowPriQueues | SCH_DProcHalt | SCH_TProcHalt | SCH_CProcHalt) -+#define SCH_Discard (SCH_DiscardLowPriInput | SCH_DiscardHighPriInput) -+ -+#define SCH_RestartCProc (1 << 0) -+#define SCH_RestartTProc (1 << 1) -+#define SCH_RestartEProc (1 << 2) -+#define SCH_RestartDma0Proc (1 << 3) -+#define SCH_RestartDma1Proc (1 << 4) -+#define SCH_RestartDmaPrefetchProc (1 << 5) -+#define SCH_RestartCh0LowPriInput (1 << 6) -+#define SCH_RestartCh1LowPriInput (1 << 7) -+#define SCH_RestartCh0HighPriInput (1 << 8) -+#define SCH_RestartCh1HighPriInput (1 << 9) -+#define SCH_ClearLinkErrorInt (1 << 10) -+#define SCH_ContextFilterFlush (1 << 11) -+ -+/* -+ * Link state bits. -+ */ -+#define LS_LinkNotReady (1 << 0) /* Link is in reset or recovering from an error */ -+#define LS_Locked (1 << 1) /* Linkinput PLL is locked */ -+#define LS_LockError (1 << 2) /* Linkinput PLL was unable to lock onto the input clock. */ -+#define LS_DeskewError (1 << 3) /* Linkinput was unable to Deskew all the inputs. (Broken wire?) */ -+#define LS_PhaseError (1 << 4) /* Linkinput Phase alignment error. */ -+#define LS_DataError (1 << 5) /* Received value was neither good data or a token. */ -+#define LS_FifoOvFlow0 (1 << 6) /* Channel 0 input fifo overflowed. */ -+#define LS_FifoOvFlow1 (1 << 7) /* Channel 1 input fifo overflowed. */ -+#define LS_Mod45Changed (1 << 8) /* Mod45 bit has changed. Error setr to force reset. */ -+#define LS_PAckNotSeenError (1 << 9) /* PAck value not returned for this packet. */ -+ -+/* -+ * Link State Constant defines, used for writing to LinkSetValue -+ */ -+ -+#define LRS_DataDel0 0x0 -+#define LRS_DataDel1 0x1 -+#define LRS_DataDel2 0x2 -+#define LRS_DataDel3 0x3 -+#define LRS_DataDel4 0x4 -+#define LRS_DataDel5 0x5 -+#define LRS_DataDel6 0x6 -+#define LRS_DataDel7 0x7 -+#define LRS_DataDel8 0x8 -+#define LRS_LinkInValue 0x9 -+#define LRS_PllDelValue 0xA -+#define LRS_ClockEven 0xB -+#define LRS_ErrorVal8to0 0xC -+#define LRS_ErrorVal17to9 0xD -+#define LRS_ErrorVal26to18 0xE -+#define LRS_ErrorVal35to27 0xF -+#define LRS_NumLinkDels 0x10 -+ -+#define LRS_Pllfast 0x40 -+ -+typedef struct _E4_CommandControl -+{ -+ volatile E4_uint32 CommandQueueDescsBase; -+ volatile E4_uint32 CommandRequeuePtr; -+} E4_CommandControl; -+ -+#define E4_CommandRequeueBusy 0x80000000 /* Test against read value of CommandRequeuePtr */ -+#define E4_CommandRequeueHighPri 0x1 /* Will requeue onto the high pri queue */ -+#define E4_QueueDescPtrMask 0x7fffffe0 -+ -+typedef struct _E4_CommandQueueDesc -+{ -+ E4_uint64 CQ_QueuePtrs; -+ E4_uint64 CQ_HoldingValue; /* 32 bit value for 32 bit accesses or OutOfOrderMask*/ -+ E4_uint64 CQ_AckBuffers; /* Space for 32 4 bit ack buffer values. */ -+ E4_uint64 CQ_Control; -+} E4_CommandQueueDesc; -+ -+/* -+ * Rev A - CQ_QueuePtrs -+ * [63] Unused Should be set to zero. -+ * [62:51] Unused (reads as top of InsertPtr) -+ * [50:35] CompletedPtr Completed pointer. This is alligned to a byte address. -+ * [34] Trapped Will be set if the command has trapped. -+ * [33:32] Size Size of queue. -+ * [31] Used Will be set if the descriptor has been changed and written back by the elan. -+ * [30:3] InsertPtr Insert pointer. This is alligned to a byte address. -+ * [2] TimedOut Will be set if the queue timedout executing a command. -+ * [1] Priority When set the queue runs at high priority. -+ * [0] Error If this becomes set all new data written to the queue is * discarded. -+ * -+ * Rev B - CQ_QueuePtrs -+ * [63] TimedOut Will be set if the queue timedout executing a command. -+ * [62] Priority When set the queue runs at high priority. -+ * [61] QueueType 1=will accept unordered 64 bit PCI writes. 0=will accept ordered 32 or 64 bit PCI writes. -+ * [60:51] Unused (reads as top of InsertPtr) -+ * [50:35] CompletedPtr Completed pointer. This is alligned to a byte address. -+ * [34] Trapped Will be set if the command has trapped. -+ * [33:32] Size Size of queue. -+ * [31] Used Will be set if the descriptor has been changed and written back by the elan. -+ * [30:3] InsertPtr Insert pointer. This is alligned to a byte address. -+ * [2] OrderControl Holds bit 8 of last PCI accesses. Used by a reordering queue. -+ * [1:0] ErrorType This field has the current error status of the queue. -+ */ -+ -+/* Common between revA and RevB */ -+#define CQ_PtrMask (0x7ffffff8) /* 31 bit sdram address */ -+#define CQ_PtrOffsetMask (0x7fff8) -+#define CQ_PtrBaseMask (0x7ff80000) -+ -+#define CQ_InsertPtrShift (3 - 3) /* InsertPtr is 64 bit aligned */ -+#define CQ_SizeShift (32) -+# define CQ_Size1K 0 -+# define CQ_Size8K 1 -+# define CQ_Size64K 2 -+# define CQ_Size512K 3 -+# define CQ_SizeMask 3 -+ -+#define CQ_CompletedPtrShift (35 - 3) /* CompletedPtr is 64 but aligned */ -+ -+#define CQ_Used (1ull << 31) -+#define CQ_Trapped (1ull << 34) -+ -+#define CQ_QueuePtrsValue(Size,Inserter,Completer) \ -+ (((E4_uint64) (Size) << CQ_SizeShift) | \ -+ ((E4_uint64) (Inserter) << CQ_InsertPtrShift) | \ -+ ((E4_uint64) (Completer) << CQ_CompletedPtrShift)) -+ -+#define CQ_InsertPtr(QueuePtrs) \ -+ (((E4_uint64) QueuePtrs) & CQ_PtrMask) -+ -+#define CQ_CompletedPtr(QueuePtrs) \ -+ (((E4_uint32)((QueuePtrs) >> CQ_CompletedPtrShift) & CQ_PtrOffsetMask) | \ -+ (CQ_InsertPtr(QueuePtrs) & CQ_PtrBaseMask)) -+ -+#define CQ_Size(SizeVal) (1024 * (1 << ((SizeVal)*3))) -+ -+/* Rev A specific */ -+#define CQ_RevA_Error (1 << 0) -+#define CQ_RevA_Priority (1 << 1) -+#define CQ_RevA_TimedOut (1 << 2) -+ -+/* Rev B specific */ -+#define CQ_RevB_ErrorType(QueuePtr) ((QueuePtr) & (3 << 0)) -+# define CQ_RevB_NoError (0ull << 0) -+# define CQ_RevB_Overflowed (1ull << 0) -+# define CQ_RevB_InvalidWriteSize (2ull << 0) -+# define CQ_RevB_InvalidWriteOrder (3ull << 0) -+#define CQ_RevB_OrderControl (1ull << 2) -+ -+#define CQ_RevB_QueueType(QueuePtr) ((QueuePtr) & (1ull << 61)) -+# define CQ_RevB_ReorderingQueue (1ull << 61) -+# define CQ_RevB_32bitWriteQueue (0ull << 61) -+ -+#define CQ_RevB_Priority (1ull << 62) -+#define CQ_RevB_TimedOut (1ull << 62) -+ -+/* -+ * CQ_AckBuffers - Packet Ack Values -+ */ -+#define PackOk (0x0) -+#define PackTestFail (0x1) -+#define PackDiscard (0x2) -+#define PackError (0x7) -+#define PackTimeout (0x8) -+#define PackWaiting (0xF) -+#define PackValue(val,chan) (((val) >> ((chan) * 4)) & 0xf) -+ -+/* -+ * CQ_Control -+ * [63:35] ExtractPtr -+ * [34] Unused -+ * [33:32] ChannelNotCompleted -+ * [31:24] Permissions -+ * [23:16] RestartCount Decremented after each restart. Will trap when zero -+ * [15:14] Unused Should be set to zero -+ * [13:0] Context -+ */ -+#define CQ_Context(Control) ((E4_uint32) ((Control) >> 0) & 0x3fff) -+#define CQ_RestartCount(Control) ((E4_uint32) ((Control) >> 16) & 0x7f) -+#define CQ_ChannelNotCompleted(Control) ((E4_uint32) ((Control) >> 32) & 3) -+#define CQ_ExtractPtr(Control) ((E4_uint32) ((Control) >> 32) & 0xFFFFFFF8) -+ -+#define CQ_RestartCountShift 16 -+ -+#define CQ_SetEventEnableBit (1 << 24) -+#define CQ_WaitEventEnableBit (1 << 25) -+#define CQ_ModifyEnableBit (1 << 26) -+#define CQ_WriteEnableBit (1 << 27) -+#define CQ_ThreadStartEnableBit (1 << 28) -+#define CQ_DmaStartEnableBit (1 << 29) -+#define CQ_STENEnableBit (1 << 30) -+#define CQ_InterruptEnableBit (1 << 31) -+#define CQ_EnableAllBits (0xFF000000) -+#define CQ_PermissionMask (0xFF000000) -+ -+#define CQ_ControlValue(Cntx, RestartCount, Permissions) \ -+ (((Cntx) & 0x3fff) | (((RestartCount) & 0xff) << 16) | ((Permissions) & CQ_PermissionMask)) -+ -+/* -+ * This file describes the slave address map of Elan4. -+ * -+ * Elan4 has two PCI 64 bit base address registers. One is setup for elan -+ * local memory and the other is for the command port, elan registers and ebus. -+ * -+ * This file describes the command port, elan registers and ebus BAR. This is a -+ * 26 bit base address register and is split up as follows: -+ * 1 The ebus requires 21 bits of address. 26'h3e00000 to 26'h3ffffff -+ * 2 The control regsiters requires 16 bits of address. 26'h3df0000 to 26'h3dfffff -+ * 3 The command port has the rest. This give just under 8k command ports or about 123 per -+ * processor of a 64 node SMP. -+ */ -+ -+/* BAR1 contains the command queues followed by the registers and the Ebus - and is 26 bits */ -+/* each command queue has an 8K page associated with it */ -+#define CQ_CommandMappingSize (1 << 13) -+#define CQ_NumCommandDescs ((1 << (26 - 13))) -+#define CQ_CommandDescsAlignment ((1 << (26 - 13)) * sizeof (E4_CommandQueueDesc)) -+ -+/* control reg bits i.e. E4_DataBusMap.SysControlReg */ -+#define CONT_EN_ALL_SETS (1ULL << 0) /* enable cache */ -+#define CONT_MMU_ENABLE (1ULL << 1) /* bit 0 enables mmu */ -+#define CONT_CACHE_HASH_TABLE (1ULL << 2) /* cache up hash table entries */ -+#define CONT_CACHE_CHAINS (1ULL << 3) /* cache up chain entries */ -+#define CONT_CACHE_ROOT_CNTX (1ULL << 4) /* cache root context table for routes and filters. */ -+#define CONT_CACHE_STEN_ROUTES (1ULL << 5) /* cache up sten packet routes */ -+#define CONT_CACHE_DMA_ROUTES (1ULL << 6) /* cache up dma packet routes */ -+ -+#define CONT_CACHE_NONE 0ULL -+#define CONT_CACHE_ALL (CONT_CACHE_HASH_TABLE | CONT_CACHE_CHAINS | CONT_CACHE_ROOT_CNTX | \ -+ CONT_CACHE_STEN_ROUTES | CONT_CACHE_DMA_ROUTES) -+ -+/* This controls the format size and position of the MMU hash tables. */ -+#define CONT_INHIBIT_MAX_CHAIN_ITEMS (1ULL << 7) /* Prevents the MaxChainItems value of 1024 from forcing a translation miss */ -+#define CONT_TABLE0_MASK_SIZE_SHIFT 8 /* Defines the size of hash table 0 */ -+#define CONT_TABLE0_PAGE_SIZE_SHIFT 13 /* Set the page size for hash table 0 */ -+#define CONT_TABLE1_MASK_SIZE_SHIFT 16 /* Defines the size of hash table 1 */ -+#define CONT_TABLE1_PAGE_SIZE_SHIFT 21 /* Set the page size for hash table 1 */ -+#define CONT_TWO_HASH_TABLES (1ULL << 24) /* Sets the MMU to use two hash tables. If not set only 0 used. */ -+#define CONT_2K_NOT_1K_DMA_PACKETS (1ULL << 25) /* Used to select the default DMA packet size. */ -+#define CONT_ALIGN_ALL_DMA_PACKETS (1ULL << 26) /* Will force all dma packets to be aligned to a page.*/ -+#define CONT_DIRECT_MAP_PCI_WRITES (1ULL << 27) /* Will force pci writes to write and flush the dcache.*/ -+#define CONT_TLB_FLUSH (1ULL << 28) /* Invalidates the TLB and indicates when flushed */ -+#define CONT_CLEAR_WALK_WROTE_TABLES (1ULL << 29) /* Used to guarantee that the elan is using new PTE values. */ -+#define CONT_ROUTE_FLUSH (1ULL << 30) /* Invalidates all route cache entries. */ -+#define CONT_CLEAR_LINKPORT_INT (1ULL << 31) /* Clears the Linkport key fail interrupt. Reads as 0. */ -+#define CONT_CLEAR_SDRAM_ERROR (1ULL << 32) /* Clears an EEC error interrupt. Reads as 0. */ -+ -+/* -+ * These are extra control bits used for testing the DLLs of the SDRAM interface. Most of the Sdram -+ * control bits are defined in xsdram.h -+ */ -+#define SDRAM_FIXED_DLL_DELAY_SHIFT 47 -+#define SDRAM_FIXED_DLL_DELAY_BITS 5 -+#define SDRAM_FIXED_DLL_DELAY_MASK ((1ULL << SDRAM_FIXED_DLL_DELAY_BITS) - 1ULL) -+#define SDRAM_FIXED_DLL_DELAY(Value) ((SDRAM_FIXED_DLL_DELAY_MASK & (Value)) << SDRAM_FIXED_DLL_DELAY_SHIFT) -+#define SDRAM_FIXED_DELAY_ENABLE (1ULL << 52) -+#define SDRAM_GET_DLL_DELAY(Value) (((Value) >> SDRAM_FIXED_DLL_DELAY_SHIFT) & SDRAM_FIXED_DLL_DELAY_MASK) -+ -+#define SDRAM_DLL_CORRECTION_FACTOR 3 /* This is to allow for SSO and ringing on the DQ lines */ -+ -+#define PAGE_SIZE_4K 0x0 -+#define PAGE_SIZE_8K 0x1 -+#define PAGE_SIZE_64K 0x2 -+#define PAGE_SIZE_512K 0x3 -+#define PAGE_SIZE_2M 0x4 -+#define PAGE_SIZE_4M 0x5 -+#define PAGE_SIZE_64M 0x6 -+#define PAGE_SIZE_512M 0x7 -+ -+#define PAGE_SIZE_MASK 0x7 -+#define PAGE_MASK_MASK 0x1f -+ -+/* control reg bits i.e. E4_DataBusMap.LinkControlReg */ -+#define LCONT_REVA_GREEN_LED (1 << 0) -+#define LCONT_REVA_YELLOW_LED (1 << 1) -+#define LCONT_REVA_RED_LED (1 << 2) -+#define LCONT_REVA_ENABLE_LED_DRIVE (1 << 3) /* Enable manual setting of the Leds to the bits set above. */ -+ -+#define LCONT_REVB_DISABLE_TLB_PREFETCH (1 << 0) -+#define LCONT_REVB_DISABLE_CRC_ERROR_CHECKING (1 << 1) -+ -+ -+#define LCONT_EN_SYS_WRITES (1 << 4) /* Enable linkport writes to sys registers. i.e. all of E4_DataBusMap. */ -+#define LCONT_EN_SYS_READS (1 << 5) /* Enable linkport reads from sys registers. i.e. all of E4_DataBusMap. */ -+#define LCONT_EN_USER_WRITES (1 << 6) /* Enable linkport writes to user registers. i.e. all of E4_User_Regs. */ -+#define LCONT_EN_USER_READS (1 << 7) /* Enable linkport reads from user registers. i.e. all of E4_User_Regs. */ -+ -+#define LCONT_TEST_VALUE_MASK 0x3ff /* Value used for test writes and link boundary scan. */ -+#define LCONT_TEST_VALUE_SHIFT 8 -+#define LCONT_TEST_VALUE(Value) ((LCONT_LINK_STATE_MASK & (Value)) << LCONT_TEST_VALUE_SHIFT) -+ -+/* -+ * State read from LINK_STATE when TEST_VALUE is set to the following values. -+ * TEST_VALUE LINK_STATE read TEST_VALUE LINK_STATE read -+ * 000 - Data delay count 0 008 - Data delay count 8 -+ * 001 - Data delay count 1 009 - Link in value -+ * 002 - Data delay count 2 00a - PLL delay -+ * 003 - Data delay count 3 00b - Clock Delay -+ * 004 - Data delay count 4 00c ? ErrorVal8to0 -+ * 005 - Data delay count 5 00d ? ErrorVal17to9 -+ * 006 - Data delay count 6 00e ? ErrorVal26to18 -+ * 007 - Data delay count 7 00f ? ErrorVal35to27 -+ */ -+ -+#define LCONT_TEST_CONTROL_MASK 0x3 /* Selects and controls the action of the LINK_STATE value. */ -+#define LCONT_TEST_CONTROL_SHIFT 18 -+ -+#define LCONT_READ_ERRORS 0 /* {Mod45RequestChanged, FifoOverflowError, DataError, PhaseError, -+ * DeskewError, LockError, Locked, LinkNotReady} */ -+#define LCONT_READ_STATE 1 /* Read valus addressed by TEST_CONTROL value */ -+#define LCONT_FIX_LINK_DELAYS 2 /* Sets delays to TEST_CONTROL value */ -+#define LCONT_BOUNDARY_SCAN 3 /* Puts link into boundary scan. Outputs TEST_CONTROL value to link, -+ * reads LINK_STATE from link. */ -+ -+#define LCONT_LINK_STATE_MASK 0x3ff /* Read only */ -+#define LCONT_LINK_STATE_SHIFT 20 /* Read only */ -+#define LCONT_LINK_STATE(ControlRegValue) (LCONT_LINK_STATE_MASK & ((ControlRegValue) >> LCONT_LINK_STATE_SHIFT)) -+ -+/* control reg bits i.e. E4_DataBusMap.LinkContSettings */ -+#define LCONT_MOD45_DISABLE (1 << 0) /* is set the link will try to run in TNB mode. */ -+#define LCONT_CONFIG_PHASE_MASK 0x7 /* This set the delay through the phase alignment buffer. */ -+#define LCONT_CONFIG_PHASE_SHIFT 1 -+ -+#define LCONT_PLL_REF_VAL_BITS_MASK 0x7f /* This is the divide value on the LinkIn clock to form the comms PLL */ -+#define LCONT_PLL_REF_VAL_BITS_SHIFT 4 /* reference clock. Div value is (n - 2). e.g. to Divide by 7 set to 5. */ -+ -+#define LCONT_FORCE_COMMSCLK_LOCAL (1 << 11) /* This must be set at one end of a back to back Elan configuration. */ -+#define LCONT_LVDS_VOLTAGE_BITS_MASK 0x3 /* This is used to set the voltage swing on the LVDS link output pads. */ -+#define LCONT_LVDS_VOLTAGE_BITS_SHIFT 12 /* reference clock. Div value is (n - 2). e.g. to Divide by 7 set to 5. */ -+ -+#define LCONT_VOD_170 0 /* Approximate differential voltage swing in mV of link outputs into */ -+#define LCONT_VOD_360 1 /* a 100 ohm diferential load. */ -+#define LCONT_VOD_460 2 -+#define LCONT_VOD_550 3 -+ -+#define LCONT_LVDS_TERMINATION_MASK 0x3 /* This set the resistor values of the internal single ended termation */ -+#define LCONT_LVDS_TERMINATION_SHIFT 14 /* resistors of the link input and comms input clcok. */ -+ -+#define LCONT_TERM_55_OHM 0 /* Resistor values for internal termination of LVDS pads. */ -+#define LCONT_TERM_50_OHM 1 -+#define LCONT_TERM_AUTO_OHM 2 /* Should normally be set to auto. */ -+#define LCONT_TERM_45_OHM 3 -+ -+#define LCONT_LVDS_EN_TERM_UPDATE (1 << 47) /* This should be asserted and deasserted if LCONT_LVDS_TERMINATION is changed. */ -+ -+/* Macros used to access and construct MMU hash table and chain entries. */ -+/* -+ * Each hash entry is made up of a 64 byte block. Each entry hash two tags where each -+ * tag has 4 PTE's. PTE's 0 to 2 use the bottom 48 bits of a 64 bit word and PTE 3 -+ * uses the top 16 bits of 3 64 bit words. -+ * -+ * These macros can be used to build a single PTE. PTE3 needs to be built into a 48 bit -+ * object before they can be used. -+ */ -+#define PTE_ENTRY_MASK 0x0000ffffffffffffULL -+#define PTE_TYPE_MASK 0x000000000000000fULL -+#define PTE_PERM_MASK 0x00000000000000f0ULL -+#define PTE_PERM_TYPE_MASK 0x00000000000000ffULL -+#define PTE_REF_MASK 0x0000000000000100ULL -+#define PTE_PPN_MASK 0x00007ffffffffe00ULL -+#define PTE_MOD_MASK 0x0000800000000000ULL -+#define PTE_TOPADDR_MASK 0x0000600000000000ULL -+ -+#define PTE_MOD_SHIFT 47 -+#define PTE_PPN_SHIFT 9 -+#define PTE_REF_SHIFT 8 -+#define PTE_PERM_SHIFT 4 -+#define PTE_TYPE_SHIFT 0 -+ -+#define PTE_PADDR_SHIFT (12 - 9) /* Physical addresses are shifted down 3 this to go into the PTE */ -+ -+ -+/* Values required for tag 3 */ -+#define PTE_REF_3 0x0100000000000000ULL -+#define PTE_MOD_3 0x8000000000000000ULL -+#define PTE_ENTRY_MASK_3 0xffff000000000000ULL -+#define PTE_PERM_TYPE_MASK_3 0x00ff000000000000ULL -+#define PTE_ENTRY_3_FOR_0(NewPte) ((NewPte << (48)) & PTE_ENTRY_MASK_3) -+#define PTE_ENTRY_3_FOR_1(NewPte) ((NewPte << (32)) & PTE_ENTRY_MASK_3) -+#define PTE_ENTRY_3_FOR_2(NewPte) ((NewPte << (16)) & PTE_ENTRY_MASK_3) -+ -+/* Values required for the tags */ -+#define TAG_CONTEXT_MASK 0x0000000000003fffULL -+#define TAG_ADDRESS_MASK 0xfffffffff8000000ULL -+#define TAG_CHAINPTR_18TO6_MASK 0x0000000007ffc000ULL -+#define TAG_CHAINPTR_LOW_SHIFT (14 - 6) -+#define TAG_CHAINPTR_30TO19_MASK 0x0000000003ffc000ULL -+#define TAG_CHAINPTR_HIGH_SHIFT (19 - 14) -+#define TAG_COPY_BIT 0x0000000004000000ULL -+ -+/* -+ * This takes number loaded into the control register and returns the page size as a power of two. -+ */ -+ -+#define E4_PAGE_SIZE_TABLE E4_uint32 const PageSizeTable[] = {12, 13, 16, 19, 21, 22, 26, 29} -+#define E4_PAGE_SIZE_TABLE_SIZE (sizeof(PageSizeTable)/sizeof(PageSizeTable[0])) -+ -+/* -+ * This macro generates a hash block index. -+ * -+ * Cntx This is the 14 bit context. It should not be larger than 14 bits. -+ * VAddr This is the 64 bit virtual address. It does not require any masking and can be a byte address. -+ * PageSize This is the value loaded into the control register for this hash table. -+ * HashTableMask This should be set mask out upper bits past the end of the hash table. -+ */ -+#define E4MMU_SHIFT_ADDR(VAddr, Shift) \ -+ ((((E4_uint32)(VAddr)) >> (Shift)) | (((E4_uint32)((VAddr) >> 32)) << (32 - (Shift)))) -+ -+#define E4MMU_CONTEXT_SCRAMBLE(Cntx) \ -+ ((((Cntx) << 8) | ((Cntx) >> 6)) ^ (((Cntx) << 15) | ((Cntx) << 1))) -+ -+#define E4MMU_HASH_INDEX(Cntx, VAddr, PageShift, HashTableMask) \ -+ ((E4MMU_SHIFT_ADDR(VAddr, (PageShift) + 2) ^ E4MMU_CONTEXT_SCRAMBLE(Cntx)) & (HashTableMask)) -+ -+#define E4MMU_TAG(vaddr,ctx) (((vaddr) & TAG_ADDRESS_MASK) | ((ctx) & TAG_CONTEXT_MASK)) -+ -+#define E4MMU_TAG2VADDR(tag,hashidx,PageShift,HashTableMask) \ -+ (((tag) & TAG_ADDRESS_MASK) | ((((hashidx) ^ E4MMU_CONTEXT_SCRAMBLE((tag) & TAG_CONTEXT_MASK)) & (HashTableMask)) << ((PageShift + 2)))) -+ -+/* -+ * Detailed bit descriptions for the tags and PTE's are better done with the macros -+ * defined above. -+ */ -+typedef struct _E4_HashTableEntry -+{ -+ E4_uint64 Tag[2]; -+ E4_uint64 TagPTE[2][3]; -+} E4_HashTableEntry; -+ -+#define E4MMU_TAG_OFFSET(tag) ((tag) << 3) -+#define E4MMU_PTE_LOW_OFFSET(tag,pte) ((((tag)*3 + (pte) + 2) << 3)) -+#define E4MMU_PTE_HIGH_OFFSET(tag,pte) ((((tag)*3 + (pte) + 2) << 3) + 4) -+#define E4MMU_PTE3_WORD0_OFFSET(tag) ((((tag)*3 + 2) << 3) + 6) -+#define E4MMU_PTE3_WORD1_OFFSET(tag) ((((tag)*3 + 3) << 3) + 6) -+#define E4MMU_PTE3_WORD2_OFFSET(tag) ((((tag)*3 + 4) << 3) + 6) -+ -+ -+/* -+ * Hash0AddrBits is the size of the hash table in bytes as a power of 2. -+ * e.g. 11 would give 32 hash entries where each entry is 64 bytes. -+ */ -+#define SETUP_HASH_TABLES(Hash0PageSize, Hash0AddrBits, Hash1PageSize, Hash1AddrBits) \ -+ (((Hash0PageSize) << CONT_TABLE0_PAGE_SIZE_SHIFT) | \ -+ ((Hash0AddrBits) << CONT_TABLE0_MASK_SIZE_SHIFT) | \ -+ ((Hash1PageSize) << CONT_TABLE1_PAGE_SIZE_SHIFT) | \ -+ ((Hash1AddrBits) << CONT_TABLE1_MASK_SIZE_SHIFT)) -+ -+/* ECC status register */ -+#define ECC_Addr(s) ((s) & 0x7ffffff8ULL) -+#define ECC_Syndrome(s) (((s) >> 32) & 0xffffULL) -+#define ECC_RisingDQSSyndrome(s) (((s) >> 32) & 0xffULL) -+#define ECC_FallingDQSSyndrome(s) (((s) >> 40) & 0xffULL) -+#define ECC_UncorrectableErr(s) (((s) >> 48) & 1ULL) -+#define ECC_MultUncorrectErrs(s) (((s) >> 49) & 1ULL) -+#define ECC_CorrectableErr(s) (((s) >> 50) & 1ULL) -+#define ECC_MultCorrectErrs(s) (((s) >> 51) & 1ULL) -+ -+/* Permission type saved in a PTE. This is a four bit field */ -+#define PERM_Disabled 0x0 -+#define PERM_Unused 0x1 -+#define PERM_LocDataRead 0x2 -+#define PERM_LocDataWrite 0x3 -+#define PERM_LocRead 0x4 -+#define PERM_LocExecute 0x5 -+#define PERM_ReadOnly 0x6 -+#define PERM_LocWrite 0x7 -+#define PERM_LocEventOnly 0x8 -+#define PERM_LocEventWrite 0x9 -+#define PERM_RemoteEvent 0xa -+#define PERM_RemoteAll 0xb -+#define PERM_RemoteReadOnly 0xc -+#define PERM_RemoteWriteLocRead 0xd -+#define PERM_DataReadWrite 0xe -+#define PERM_NoFault 0xf -+ -+#define PERM_Mask 0xf -+ -+/* Permission type hints to device driver */ -+#define PERM_Preload 0x10 -+ -+#define PTE_SetPerm(Perm) (((Perm) & PERM_Mask) << 4) -+ -+/* Control info saved in the lookup field of the TLB */ -+#define PTE_PciNotLocal (1ULL << 0) /* Directs the access to the PCI interface */ -+#define PTE_BigEndian (1ULL << 1) /* Valid for PCI entries only */ -+#define PTE_RelaxedOrder (1ULL << 2) /* Valid for PCI entries only */ -+#define PTE_DontSnoop (1ULL << 3) /* Valid for PCI entries only */ -+ -+#define PTE_UseFixedSet (1ULL << 1) /* Value for non PCI entries only */ -+#define PTE_CommandQueue (1ULL << 2) /* Value for non PCI entries only */ -+#define PTE_SetFixedSetNo(Set) ((((Set) & 3) << 2) | PTE_UseFixedSet) -+ -+#define PTE_TypeBitsMask (0xfULL) -+#define PTE_PermissionTypeMask (0xfULL << 4) -+#define PTE_Referenced (1ULL << 8) -+#define PTE_PhysicalPageNoMask (0x7ffffffffe00ULL) -+#define PTE_Modified (1ULL << 47) -+ -+#define PTE_PhysicalAddrShiftIntoPTE (12 - 9) -+ -+/* define page table entry bit fields */ -+#define TLB_PageSizeBits (3 << 0) -+#define TLB_ACCBits (7 << 2) -+#define TLB_LocalBit (1 << 5) -+#define TLB_PCI64BitTargetBit (1 << 6) -+#define TLB_PCIBigEndianBit (1 << 7) -+ -+#define TLB_ModifiedBit (1 << 55) -+#define TLB_ReferencedBit (1 << 63) -+ -+/* Used to read values from the tlb. */ -+#define TLB_TlbReadCntBitsSh 56 -+#define TLB_UseSelAddrSh (1ULL << 60) -+#define TLB_WriteTlbLine (1ULL << 61) -+ -+#define TLB_SEL_LINE(LineNo) (TLB_UseSelAddrSh | \ -+ ((E4_uint64)((LineNo) & 0xf) << TLB_TlbReadCntBitsSh)) -+ -+#define TLB_NUM_ENTRIES 16 -+/* -+ * The following macros are used with the test access port (TlbLineValue) for the TLBs. -+ */ -+#define TLV_DoPciAccess (1ULL << 0) -+#define TLV_CommandAccess (1ULL << 1) -+#define TLV_DoCacheAccess (1ULL << 2) -+#define TLV_notStartTLBWalk (1ULL << 3) -+#define TLV_UseFixedSet (1ULL << 4) -+#define TLV_BigEndian (1ULL << 4) -+#define TLV_RelaxedOrder (1ULL << 5) -+#define TLV_DontSnoop (1ULL << 6) -+#define TLV_FixedSetNo_MASK (3ULL << 5) -+#define TLV_PciTypeBits_MASK (7ULL << 4) -+#define TLV_LookupBits_MASK (0x7fULL) -+#define TLV_MissErr (1ULL << 7) -+#define TLV_TypeBits (0xffULL) -+ -+#define TLV_PhysicalAddr_MASK (0x3fffffffff000ULL) -+ -+#define TLV_TlbTesting (1ULL << 51) -+#define TLV_SelectUnitsTlbRead (1ULL << 52) -+#define TLV_SelectTProcTlbRead (1ULL << 53) -+ -+#define TLV_TlbLineSelect_MASK (0xf) -+#define TLV_UnitsTlbLineSelect_SHIFT (54) -+#define TLV_TProcTlbLineSelect_SHIFT (59) -+#define TLV_EnableUnitsTlbRead (1ULL << 58) -+#define TLV_EnableTProcTlbRead (1ULL << 63) -+ -+/* -+ * Use this macro to enable direct testing of the Units TLB. -+ * When Line is in the range 0 to 15 a TLB line is selected for reading or writing. -+ * When Line is set to -1 the tlb will be activated to perform a match. -+ */ -+#define TLV_UnitsTlbLineSel(Line) (((Line) == -1) ? 0ULL : \ -+ (TLV_EnableUnitsTlbRead | ((E4_uint64)((Line) & TLV_TlbLineSelect_MASK) << TLV_UnitsTlbLineSelect_SHIFT))) -+#define TLV_TProcTlbLineSel(Line) (((Line) == -1) ? 0ULL : \ -+ (TLV_EnableTProcTlbRead | ((E4_uint64)((Line) & TLV_TlbLineSelect_MASK) << TLV_TProcTlbLineSelect_SHIFT))) -+ -+/* -+ * Thread_Trap_State -+ * see f_RegFileControl.v TProcStatus -+ */ -+#define TS_HaltThread (1 << 0) -+#define TS_TrapForTooManyInstructions (1 << 1) -+#define TS_InstAccessException (1 << 2) -+#define TS_Unimplemented (1 << 3) -+#define TS_DataAccessException (1 << 4) -+#define TS_DataAlignmentError (1 << 5) -+#define TS_TrapForUsingBadData (1 << 6) -+#define TS_TrapTypeMask (0x7f) -+#define TS_DataPortNo(ts) (((ts) >> 7) & 7) -+#define TS_TrappedFlag (1 << 10) -+#define TS_MemLock (1 << 11) -+#define TS_XCCshift 12 -+#define TS_XCCmask 0xff -+#define TS_ICC(ts) (((ts) >> 12) & 15) -+#define TS_XCC(ts) (((ts) >> 16) & 15) -+#define TS_InstValid_F (1 << 20) -+#define TS_InstValid_R (1 << 21) -+#define TS_InstValid_E (1 << 22) -+#define TS_InstValid_W (1 << 23) -+#define TS_HighPriority (1 << 24) -+#define TS_RemoteThread (1 << 25) -+#define TS_TProcTranslationInProgress (1 << 26) -+#define TS_MemLock_E (1 << 27) -+ -+/* Thread run queue entries */ -+typedef struct E4_ThreadRegs -+{ -+ E4_uint64 Registers[7]; -+} E4_ThreadRegs; -+ -+typedef struct E4_TProcQueueEntry -+{ -+ E4_ThreadRegs Regs; /* XXXX: jon check this */ -+ E4_uint64 Context; /* XXXX: jon check this */ -+} E4_TProcQueueEntry; -+ -+typedef struct E4_DProcQueueEntry -+{ -+ E4_DMA Desc; -+ E4_uint64 Pad; -+} E4_DProcQueueEntry; -+ -+/* -+ * Packet acknowledge values. -+ */ -+#define E4_PAckOk 0 -+#define E4_PAckTestFail 1 -+#define E4_PAckDiscard 2 -+#define E4_PAckError 3 -+ -+/* -+ * return values from breaktest instruction. -+ */ -+#define ICC_CARRY_BIT (0x1ULL << 0) /* Breaktest: Load pending */ -+#define ICC_ZERO_BIT (0x1ULL << 1) /* Breaktest: Time to break */ -+#define ICC_SIGNED_BIT (0x1ULL << 2) /* Breaktest: Another thread ready */ -+#define ICC_TPROC_RDY_LOW_PRI (0x1ULL << 3) -+#define ICC_TPROC_RDY_HIGH_PRI (0x1ULL << 4) -+#define ICC_RUNNING_HIGH_PRI (0x1ULL << 5) -+#define ICC_RUNNING_AS_REMOTE (0x1ULL << 6) -+#define ICC_TIME_TO_BREAK (0x1ULL << 7) -+#define ICC_RS1LOAD_PENDING (0x1ULL << 8) -+#define ICC_TPROC_HALT (0x1ULL << 9) -+ -+/* -+ * Main Interrupt cookies -+ * [63:14] user cookie -+ * [13:0] context -+ */ -+#define E4_MAIN_INT_SHIFT 14 -+#define E4_MAIN_INT_COOKIE(cookie) ((cookie) >> E4_MAIN_INT_SHIFT) -+#define E4_MAIN_INT_CTX(cookie) ((cookie) & 0x3FFF) -+ -+typedef E4_uint64 E4_MainIntEntry; -+ -+#define E4_MainIntEntrySize sizeof (E4_MainIntEntry) -+ -+/* -+ * The internal databus is 64 bits wide. -+ * All writes to the internal registers MUST be made with 64 bit write operations. -+ * These can be made up of pairs 32 bit writes on the PCI bus. The writes will be -+ * treated as nops if they are performed with two separate 32 bit writes. -+ */ -+typedef volatile struct _E4_DataBusMap -+{ -+ E4_uint64 InputTrans[4][16]; /* 0x000 */ -+ -+ E4_uint64 Dma0TransAddr; /* 0x200 */ -+ E4_DMA Dma0Desc; /* Current Dma0 registers */ /* 0x208 */ -+ -+ E4_uint64 Dma1TransAddr; /* 0x240 */ -+ E4_DMA Dma1Desc; /* Current Dma1 registers */ /* 0x248 */ -+ -+ E4_uint64 Dma0LastPacketSize; /* 0x280 */ -+ E4_uint64 Dma0ThisPacketSize; /* 0x288 */ -+ E4_uint64 Dma0DescSizeInProg; /* 0x290 */ -+ E4_uint64 Dma0BytesToPrefetch; /* 0x298 */ -+ E4_uint64 Dma0PrefetchAddr; /* 0x2a0 */ -+ E4_uint64 EventCountAndType; /* 0x2a8 */ -+ E4_uint64 EventParameters[2]; /* 0x2b0 */ -+ -+ E4_uint64 Dma1LastPacketSize; /* 0x2c0 */ -+ E4_uint64 Dma1ThisPacketSize; /* 0x2c8 */ -+ E4_uint64 Dma1DescSizeInProg; /* 0x2d0 */ -+ E4_uint64 Dma1BytesToPrefetch; /* 0x2d8 */ -+ E4_uint64 Dma1PrefetchAddr; /* 0x2e0 */ -+ E4_Input_Ptrs InputTrapAndFilter; /* 0x2e8 */ -+ E4_uint64 EventAddress; /* 0x2f0 */ -+ E4_QueuePtr MainIntQueuePtrs; /* 0x2f8 */ -+ -+ E4_uint64 Event_Copy[16]; /* 0x300 */ -+ -+ E4_uint64 CommandCopy[7]; /* 0x380 */ -+ E4_uint64 CommandHold; /* 0x3b8 */ -+ -+ E4_uint64 InputQueueDesc[4]; /* 0x3c0 */ -+ -+ /* Run queue Pointers */ -+ E4_uint64 DProcLowPriPtrs; /* 0x3e0 */ -+ E4_uint64 DProcHighPriPtrs; /* 0x3e8 */ -+ E4_uint64 TProcLowPriPtrs; /* 0x3f0 */ -+ E4_uint64 TProcHighPriPtrs; /* 0x3f8 */ -+ -+ E4_uint64 CProcStatus; /* 0x400 */ -+ E4_uint64 TProcStatus; /* 0x408 */ -+ E4_uint64 IProcStatus; /* 0x410 */ -+ E4_uint64 EProcStatus; /* 0x418 */ -+ E4_uint64 DProc0Status; /* 0x420 */ -+ E4_uint64 DProc1Status; /* 0x428 */ -+ E4_Sched_Status SchedStatus; /* 0x430 */ -+ -+ E4_uint64 LoadIProcCntxFilter; /* Will load one of 4 cntx filter regs. Write only */ /* 0x438 */ -+ -+ E4_CommandControl CommandControl; /* 0x440 */ -+ E4_uint64 CommandCacheTestPort; /* 0x448 */ -+ E4_uint64 CommandLowPriRunPtrs; /* 0x450 */ -+ E4_uint64 CommandHighPriRunPtrs; /* 0x458 */ -+ E4_uint64 CommandSchedDataPort[4]; /* 0x460 */ -+ -+ E4_uint64 DmaRouteBuffer[2][2]; /* Write only. Should not be written to. */ /* 0x480 */ -+ E4_uint64 StenRouteBuffer[2]; /* Write only. Should not be written to. */ /* 0x4a0 */ -+ E4_uint64 pad4[0x098 - 0x096]; /* 0x4b0 */ -+ -+ E4_uint64 DmaAlignmentPort[8]; /* Write only. Should only be written to clear the prev reg. */ /* 0x4c0 */ -+ -+ E4_uint64 MmuBlockEntry[8]; /* Used for hash table and chain fetches */ /* 0x500 */ -+ E4_uint64 WriteUnitsTlbLine[3]; /* 0x550 */ -+ E4_uint64 pad5; /* 0x540 */ -+ E4_uint64 WriteTProcTlbLine[3]; /* 0x568 */ -+ E4_uint64 pad6; /* 0x540 */ -+ -+ E4_uint64 MmuTableBasePtrs; /* Both tables packed into a single 64 bit value */ /* 0x580 */ -+ E4_uint64 MmuFaultAndRootCntxPtr; /* Both packed into a single 64 bit value */ /* 0x588 */ -+ E4_uint64 UnitsVAddr; /* 0x590 */ -+ E4_uint64 TProcVAddr; /* 0x598 */ -+ E4_uint64 UnitsCntx; /* 0x5a0 */ -+ E4_uint64 TProcCntx; /* Read only. Writes access VProcCacheWritePort */ /* 0x5a8 */ -+ E4_uint64 FaultAddrReg; /* 0x5b0 */ -+ E4_uint64 FaultTypeAndContextReg; /* 0x5b8 */ -+ -+ E4_uint32 SysControlReg; /* 0x5c0 */ -+ E4_uint32 CacheTagValue; /* 0x5c4 */ -+ E4_uint64 TlbLineValue; /* 0x5c8 */ -+ E4_uint64 SDRamConfigReg; /* 0x5d0 */ -+ E4_uint32 InterruptMask; /* 0x5d8 */ -+ E4_uint32 InterruptReg; /* 0x5dc */ -+ E4_uint64 SDRamECCStatus; /* 0x5e0 */ -+ E4_uint32 LinkControlReg; /* 0x5e8 */ -+ E4_uint32 LinkContSettings; /* 0x5ec */ -+ E4_uint64 LinkPortKey; /* 0x5f0 */ -+ E4_uint64 LinkPortLock; /* 0x5f8 */ -+ -+ E4_uint64 SDRamWriteBuffer[4][8]; /* 0x600 */ -+ E4_uint64 SDRamReadBuffer[4][8]; /* 0x700 */ -+ -+ E4_uint64 TProcRegs[64]; /* 0x800 */ -+ E4_uint64 TProcStartUp[8]; /* Not to be used except by the elan itself */ /* 0xa00 */ -+ -+ E4_uint64 LoadPending; /* 0xa40 */ -+ E4_uint64 StortPending; /* 0xa48 */ -+ E4_uint64 DirtyBits; /* 0xa50 */ -+ E4_uint64 BadBits; /* 0xa58 */ -+ -+ E4_uint64 ICachePort_Cntl_Addr; /* 0xa60 */ -+ E4_uint64 Thread_Trap_State; /* 0xa68 */ -+ -+/* Instruction buffer (4 * 32 bit words) */ -+ E4_uint64 nPC_W; /* 0xa70 */ -+ E4_uint64 PC_W; /* 0xa78 */ -+ -+ E4_uint64 ICacheFillData[8]; /* 0xa80 */ -+ E4_uint64 ICachePort[8]; /* 0xac0 */ -+ -+ E4_uint64 PciDataBufs[4][8]; /* 0xb00 */ -+ -+ E4_uint64 CommandQueueBuffer[128]; /* 0xc00 */ -+} E4_DataBusMap; -+ -+#define LINK_PORT_LOCK_VALUE 0x123456789abcdef0ULL -+ -+/* -+ * These macros are used to setup the thread pcoessors ICache. -+ */ -+#define E4_ICacheTagAddrShift 6 -+#define E4_AccessICacheRams 1 -+#define E4_InvalidTagValue 0xffffffffffffffffULL -+#define E4_ICacheSizeInBytes (1024*16) -+#define E4_ICacheLineSizeInBytes (64) -+#define E4_ICacheLines (E4_ICacheSizeInBytes/E4_ICacheLineSizeInBytes) -+#define E4_ICachePortSize ( (sizeof((E4_DataBusMap *) 0)->ICachePort) / \ -+ (sizeof((E4_DataBusMap *) 0)->ICachePort[0])) -+ -+#define E4_ICacheFixupInsn 0xc0b02f95ull /* st1 [%r0 + 0xf95] */ -+#define E4_ICacheFixupAddr 0xf95ull -+#define E4_ICacheFixupOffset 0xfc0 -+ -+/* -+ * Event interrupt -+ */ -+typedef volatile union _E4_EventInt -+{ -+ E4_uint64 ForceAlign; -+ struct { -+ E4_uint32 IntCookie; -+ E4_uint32 EventContext; /* Bits 16 to 28 */ -+ } s; -+} E4_EventInt; -+ -+/* -+ * The following are used to interpret a fault status register. -+ */ -+ -+/* -+ * FSR[14:0] - AccessType -+ * -+ * T = Type bit -+ * S = size bit. Size is in units of 64 bits or 8 bytes. -+ * E = Byte end pointer. Used to define the last written byte of the last 64 bits written. -+ * D = Data type bit. Used for endian conversion in the PCI interface. -+ * C = Used by the cache to decide if this access should allocate a cache line. -+ * d = Set if dma read or write data data. This is used to guarantee order at the PCI interface. -+ * A = Access type used to check permissions by the MMU in a virtual access. -+ * P = Part Write. If set some byte enables may be used. Effects the action of a cache miss. -+ */ -+ -+/* FSR[7:0] */ -+/* bit 7 => virtual write */ -+#define AT_VirtualWriteAccBit (1 << 7) /* AAADDdC1EEESSSS = Virtual Write */ -+#define AT_VirtualWriteSizeMask 0xf /* size of write access (0 => 128 bytes) */ -+#define AT_VirtualWriteEndPtrShift 4 /* end byte pointer for part write block */ -+#define AT_VirtualWriteEndPtrMask 0x7 -+ -+/* else bit 6 => virtual read */ -+#define AT_VirtualReadAccBit (1 << 6) /* AAADDdC01SSSSSS = Virtual Read */ -+#define AT_VirtualReadSizeMask 0x3f /* size of read access (0 => 512 bytes) */ -+ -+/* else => special access */ -+#define AT_SelBitsMask 0xf /* Bits to select the type of acces from */ -+#define AT_SelBitsShift 0x4 -+#define AT_SpecialRd (0x0 << 4) /* AAADDdC0000TTTT = Special read Access */ -+#define AT_SpecialWr (0x1 << 4) /* AAADDdC0001TTTT = Special write Access */ -+#define AT_PhysicalRd (0x2 << 4) /* AAADDdC00100SSS = Physical Read */ -+#define AT_PhysicalWr (0x3 << 4) /* AAADDdC0011PSSS = Physical write */ -+ -+#define AT_OtherSizeMask 0xf /* Size bits used by all other accesses. 0=128 bytes */ -+#define AT_SpecialBitsMask 0xf /* Bits used to define the special access types */ -+#define AT_CacheSizeBitsMask 0x7 /* Size bits used for local accesses. 0=64 */ -+#define AT_CachePhysPartWriteBit 0x8 /* This bit is set if the access is a part write to the cache */ -+ -+/* Special memory access operations */ -+#define AT_RegAccess 0x0 -+#define AT_GetCntxFilter 0xe /* Only used by special reads */ -+#define AT_RouteFetch 0xf /* Only used by special reads */ -+ -+/* FSR[9:8] */ -+#define AT_NonAlloc (1 << 8) /* 1=Do not fill cache with this data */ -+#define AT_DmaData (1 << 9) /* This is a DMA read access. Required to guarantee dma read order. */ -+ -+/* FSR[11:10] - Data Type - defines data type for endian conversion in PCI interface*/ -+#define AT_BlkDataTyMask 0x3 -+#define AT_BlkDataTyShift 10 -+ -+#define AT_BlkDataType(FSR) (((FSR) >> AT_BlkDataTyShift) & AT_BlkDataTyMask) -+#define AT_TypeByte 0x0 -+#define AT_TypeHWord 0x1 -+#define AT_TypeWord 0x2 -+#define AT_TypeDWord 0x3 -+ -+/* FSR[14:12] - Access Permissions */ -+#define AT_PermBitsMask 0x7 -+#define AT_PermBitsShift 12 -+ -+#define AT_Perm(FSR) (((FSR) >> AT_PermBitsShift) & AT_PermBitsMask) -+#define AT_PermLocalDataRead 0x0 -+#define AT_PermLocalDataWrite 0x1 -+#define AT_PermRemoteRead 0x2 -+#define AT_PermRemoteWrite 0x3 -+#define AT_PermExecute 0x4 -+#define AT_PermLocalEvent 0x5 -+#define AT_PermRemoteEvent 0x7 -+ -+/* FSR[22:15] - reason for fault */ -+ -+#define FSR_WalkForThread (1 << 15) /* The thread processor caused the fault */ -+#define FSR_Walking (1 << 16) /* The fault was caused during a hash table access */ -+#define FSR_NoTranslationsFound (1 << 17) /* The hash table did not contain a matching tag */ -+#define FSR_WalkingProtectionFault (1 << 18) /* A protection fault was detected while walking */ -+#define FSR_HashTable1 (1 << 19) /* Was accessing hash table 1 not 0 */ -+#define FSR_RouteVProcErr (1 << 20) /* This is an invalid vproc for a route fetch */ -+#define FSR_FaultForBadData (1 << 21) /* Bad data (double bit ECC error) while performing a walk access */ -+#define FSR_FaultForMaxChainCount (1 << 22) /* The Elan4 has walked a chain of 1024 items. */ -+ -+typedef volatile struct _E4_FaultSave -+{ -+ E4_uint64 FSRAndFaultContext; /* Bits 0-31 : FaultContext. Bits 32-63 : FaultStatus Register */ -+ E4_uint64 FaultAddress; -+} E4_FaultSave; -+ -+#define FaultSaveContext(FSRAndFaultContext) ((E4_uint32) ((FSRAndFaultContext) & 0xFFFFFFFF)) -+#define FaultSaveFSR(FSRAndFaultContext) ((E4_uint32) ((FSRAndFaultContext) >> 32)) -+ -+typedef union E4_TrTypeCntx -+{ -+ E4_uint32 TypeContext; -+ struct -+ { -+#if (BYTE_ORDER == LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) -+ E4_uint32 Type:16; /* Transaction type field */ -+ E4_uint32 Context:13; /* Transaction context */ -+ E4_uint32 TypeCntxInvalid:1; /* Bit 29 */ -+ E4_uint32 StatusRegValid:1; /* Bit 30 */ -+ E4_uint32 LastTrappedTrans:1; /* Bit 31 */ -+#else -+ E4_uint32 LastTrappedTrans:1; /* Bit 31 */ -+ E4_uint32 StatusRegValid:1; /* Bit 30 */ -+ E4_uint32 TypeCntxInvalid:1; /* Bit 29 */ -+ E4_uint32 Context:13; /* Transaction context */ -+ E4_uint32 Type:16; /* Transaction type field */ -+#endif -+ } s; -+} E4_TrTypeCntx; -+ -+#define MAX_TRAPPED_TRANS 28 -+#define TRANS_DATA_DWORDS 16 -+#define TRANS_DATA_BYTES 128 -+#define NO_OF_INPUT_CHANNELS 4 -+ -+#define CH0_LOW_PRI_CHAN 0 -+#define CH1_LOW_PRI_CHAN 1 -+#define CH0_HIGH_PRI_CHAN 2 -+#define CH1_HIGH_PRI_CHAN 3 -+ -+/* Words have been swapped for big endian access when fetched with dword access from elan.*/ -+typedef struct _E4_IprocTrapHeader -+{ -+ E4_uint64 TrAddr; -+ E4_uint64 IProcStatusCntxAndTrType; -+} E4_IprocTrapHeader; -+ -+typedef struct _E4_IprocTrapData -+{ -+ E4_uint64 Data[TRANS_DATA_DWORDS]; -+} E4_IprocTrapData; -+ -+/* -+ * This struct defines the trap state for the inputers. It requires a contiguous 16K byte block of local memory. -+ * The channel bits have been grouped to the low end of the address to force all Identify cookies to use the -+ * same cache line. -+ */ -+typedef struct _E4_IprocTrapState -+{ -+ E4_IprocTrapData TrData[MAX_TRAPPED_TRANS][NO_OF_INPUT_CHANNELS]; -+ E4_IprocTrapHeader TrHeader[MAX_TRAPPED_TRANS][NO_OF_INPUT_CHANNELS]; -+ E4_uint64 pad[8*NO_OF_INPUT_CHANNELS]; -+} E4_IprocTrapState; -+ -+/* -+ * 64 kbytes of elan local memory. Must be aligned on a 64k boundary -+ */ -+#define E4_LowPriQueueSize 0x400 -+#define E4_HighPriQueueSize 0x100 -+ -+typedef struct _E4_FaultSaveArea -+{ -+ E4_FaultSave TProcData[8]; -+ E4_FaultSave TProcInst; -+ E4_FaultSave Dummy[7]; -+ E4_FaultSave SchedProc; -+ E4_FaultSave DProc; -+ E4_FaultSave EventProc; -+ E4_FaultSave IProc; -+ E4_FaultSave DProcData[4]; -+ E4_FaultSave QReadData[8]; -+} E4_FaultSaveArea; -+ -+/* Macros to manipulate event queue pointers */ -+/* generate index in EventIntQueue */ -+#define E4_EVENT_INTQ_INDEX(fptr) (((fptr) & 0x1fff) >> 3) -+/* generate next fptr */ -+#define E4_EVENT_INTQ_NEXT(fptr) ((((fptr) + 8) & ~0x4000) | 0x2000) -+ -+typedef struct _E4_CommandPort -+{ -+ volatile E4_uint64 Command[1024]; /* a whole 8k page */ -+} E4_CommandPort; -+ -+/* -+ * This is the allocation of unit numbers within the ELAN. It is used to extract the fault address -+ * and fault type after a unit has trapped on a memory fetch. Only units that can generate traps -+ * have been included. -+ */ -+#define CUN_TProcData0 0x00 -+#define CUN_TProcData1 0x01 -+#define CUN_TProcData2 0x02 -+#define CUN_TProcData3 0x03 -+#define CUN_TProcData4 0x04 -+#define CUN_TProcData5 0x05 -+#define CUN_TProcData6 0x06 -+#define CUN_TProcData7 0x07 -+#define CUN_TProcInst 0x08 -+ -+/* memory current unit numbers -+ * TProc data bus */ -+#define CUN_DProcPA0 0x10 -+#define CUN_DProcPA1 0x11 -+#define CUN_DProcPrefetch 0x12 -+#define CUN_CommandProc 0x13 -+#define CUN_DProcData0 0x14 /* Dma prefetch reads. */ -+#define CUN_DProcData1 0x15 /* Dma prefetch reads. */ -+#define CUN_DProcData2 0x16 /* Dma prefetch reads. */ -+#define CUN_DProcData3 0x17 /* Dma prefetch reads. */ -+ -+#define CUN_IProcLowPri 0x18 -+#define CUN_IProcHighPri 0x19 -+#define CUN_Spare0 0x1A -+#define CUN_Spare1 0x1B -+#define CUN_Spare2 0x1C -+#define CUN_ThreadQueue 0x1D -+#define CUN_EventProc0 0x1e -+#define CUN_EventProc1 0x1f -+ -+#define CUN_Entries 0x20 -+ -+typedef struct E4_Registers -+{ -+ E4_CacheTags Tags; /* 4k bytes c000 -> cfff */ -+ E4_DataBusMap Regs; /* 4k bytes d000 -> dfff */ -+ E4_User_Regs uRegs; /* 8k bytes e000 -> ffff */ -+} E4_Registers; -+ -+#define I2cCntl_I2cPortWrite (0 << 0) -+#define I2cCntl_I2cPortRead (1 << 0) -+#define I2cCntl_I2cPortGenStopBit (1 << 1) -+#define I2cCntl_I2cPortGenRestartBit (1 << 2) -+#define I2cCntl_I2cPortAccFailed (1 << 3) -+#define I2cCntl_I2cStopped (1 << 4) -+#define I2cCntl_I2cWakeupFailed (1 << 5) -+#define I2cCntl_I2cFastMode (1 << 6) -+#define I2cCntl_I2cPortBusy (1 << 7) -+ -+#define I2cCntl_LedI2cRegBase_Mask 0x7f -+#define I2cCntl_I2cUpdatingLedReg (1 << 7) -+ -+#define I2cCntl_InvertLedValues (1 << 0) /* read/write */ -+#define I2cCntl_LedRegWriteFailed (1 << 1) /* read only */ -+#define I2cCntl_EEPromLoadFailed (1 << 2) /* read only */ -+#define I2cCntl_InhibitI2CRom (1 << 3) /* read only */ -+#define I2cCntl_BadRomCrc (1 << 4) /* read only */ -+#define I2cCntl_MapInI2cConfigData (1 << 5) /* read/write */ -+#define I2cCntl_SampleNewLedValues (1 << 6) /* read/write */ -+#define I2cCntl_ClearLinkError (1 << 7) /* write only */ -+ -+typedef struct E4_I2C -+{ -+ volatile E4_uint8 I2cWrData; -+ volatile E4_uint8 I2cRdData; -+ volatile E4_uint8 I2cPortControl; -+ volatile E4_uint8 I2cLedBase; -+ volatile E4_uint8 I2cStatus; -+ volatile E4_uint8 I2cLedsValue; -+ volatile E4_uint16 I2cPad; -+ -+ E4_uint8 pad[256 - sizeof(E4_uint64)]; -+ -+ E4_uint8 UnchangedElan4ConfigRegs[256]; -+ E4_uint8 I2cRomConfigShadowValues[256]; -+ E4_uint8 ChangedElan4ConfigRegs[256]; -+} E4_I2C; -+ -+typedef struct _E4_ContextControlBlock -+{ -+ E4_uint32 Filter; /* Use a Network context to index for this value */ -+ E4_uint32 VirtualProcessTable; /* Use a local context to index for this value */ -+} E4_ContextControlBlock; -+ -+/* -+ * Filter -+ * [13:0] Context -+ * [14] DiscardAll -+ * [15] AckAll -+ * [16] HighPri -+ * [17] CountStats -+ * [31:18] Unused -+ */ -+#define E4_FILTER_STATS (1 << 17) -+#define E4_FILTER_HIGH_PRI (1 << 16) -+#define E4_FILTER_ACKOK_ALL (1 << 15) -+#define E4_FILTER_DISCARD_ALL (1 << 14) -+#define E4_FILTER_CONTEXT_MASK (0x3FFF) -+ -+/* -+ * VirtualProcessTable -+ * [8:0] Unused -+ * [12:9] Size num vp entries = 512 << Size -+ * [30:13] Pointer -+ * [31] Valid -+ */ -+#define E4_VPT_MIN_ENTRIES 512 -+#define E4_VPT_VALID ((unsigned)1 << 31) -+#define E4_VPT_PTR_SHIFT 0 -+#define E4_VPT_SIZE_SHIFT 9 -+#define E4_VPT_SIZE_MASK 0xf -+#define E4_VPT_NUM_VP(vpt_val) (E4_VPT_MIN_ENTRIES << (((vpt_val) >> E4_VPT_SIZE_SHIFT) & E4_VPT_SIZE_MASK)) -+#define E4_VPT_VALUE(ptr,size) (((ptr) << E4_VPT_PTR_SHIFT) | ((size) << E4_VPT_SIZE_SHIFT)) -+ -+ -+/* Virtual Process Table */ -+typedef struct _E4_VirtualProcessEntry -+{ -+ E4_uint64 Values[2]; -+} E4_VirtualProcessEntry; -+ -+/* -+ * Entries have the following format - rtX is a packed route -+ * -+ * |rt11|rt10|rt9 |rt8 |rt7 |rt6 |rt5 |rt4 |rt3 |rt2 |rt2 |rt0 |PAAADD RRRRRR| -+ * |output context |rt23|rt22|rt21|rt20|rt19|rt18|rt17|rt16|rt15|rt14|rt13|rt12| -+ */ -+ -+#define ROUTE_CTXT_SHIFT 48 -+#define ROUTE_CTXT_MASK (~((1ull << ROUTE_CTXT_SHIFT)-1)) -+#define ROUTE_CTXT_VALUE(ctx) (((E4_uint64) ctx) << ROUTE_CTXT_SHIFT) -+ -+#define ROUTE_PACKED_OFFSET 16 -+#define ROUTE_NUM_PACKED 24 -+ -+/* defines for first flit of a route */ -+#define FIRST_TIMEOUT(Val) ((Val) << 14) /* [15:14] */ -+#define FIRST_SYSTEM_PACKET (1 << 13) /* [13] */ -+#define FIRST_FLOOD_PACKET (1 << 12) /* [12] */ -+#define FIRST_HIGH_PRI (1 << 11) /* [11] */ -+#define FIRST_AGE(Val) ((Val) << 7) /* [10:7] */ -+#define FIRST_OPTIONS_MASK (0xFF80) -+ -+/* [6:0] unpacked 1st route value */ -+#define FIRST_INVALID (0) -+#define FIRST_ROUTE(Val) (0x08 | (Val)) -+#define FIRST_ADAPTIVE (0x30) -+#define FIRST_BCAST_TREE (0x20) -+#define FIRST_MYLINK (0x10) -+#define FIRST_BCAST(Top, Bot) (0x40 | ((Top) << 3) | (Bot)) -+ -+/* defines for 3 bit packed entries for subsequent flits */ -+#define PACKED_INVALID (0) -+#define PACKED_ROUTE(Val) (8 | (Val)) -+#define PACKED_ADAPTIVE (3) -+#define PACKED_BCAST_TREE (2) -+#define PACKED_MYLINK (1) -+#define PACKED_BCAST0(Top,Bot) (4 | (Bot & 3)) -+#define PACKED_BCAST1(Top,Bot) ((Top << 1) | (Bot >> 2)) -+ -+#endif /* _ASM */ -+/* The MMU root context pointer has a mask to bounds check -+ * it - this is computed as follows. -+ */ -+#define E4_CONTEXT_MASK(num) (((num) >= 0x2000) ? 0x00 : \ -+ ((num) >= 0x1000) ? 0x80 : \ -+ ((num) >= 0x0800) ? 0xc0 : \ -+ ((num) >= 0x0400) ? 0xe0 : \ -+ ((num) >= 0x0200) ? 0xf0 : \ -+ ((num) >= 0x0100) ? 0xf8 : \ -+ ((num) >= 0x0080) ? 0xfc : \ -+ ((num) >= 0x0040) ? 0xfe : 0xff) -+/* -+ * This generates the size field for a virtual process table. -+ * Size defined as 2^n no of 8K pages. -+ * Single cycle route fetches are possible if the minimum vproc table size is 8k. -+ */ -+#define E4_GEN_VPT_SIZE(Size) (((Size) & E4_VPT_SIZE_MASK) << E4_VPT_SIZE_SHIFT) -+ -+#define COMMAND_RUN_QUEUE_BITS (13 + 2) /* 8K entries of 4 bytes. This is fixed in hardware. */ -+#define COMMAND_DESCS_SPACE_BITS (13 + 5) /* 8K entries of 32 bytes. This is fixed in hardware. */ -+#define COMMAND_INSERTER_CACHE_ENTRIES 16 -+ -+#define COM_TEST_PORT_ADDR_MASK 0xfULL -+#define COM_TEST_PORT_ADDR_SH 0 -+ -+/* -+ * The flush register is accessed through the CommandControl register. -+ * The address is naturally alligned. It also positions the command descriptors in memory. -+ * When no command queues need flushing it should be or with COM_FLUSH_INVALID. This sets -+ * it to the top command queue descriptor. This cannot be accessed from the PCI. -+ */ -+#define COM_ENABLE_DEQUEUE (1 << 4) -+#define COM_FLUSH_DESCRIPTOR_MASK 0x7fffffe0ULL -+#define COM_FLUSH_INVALID 0x0003ffe0ULL -+ -+ -+/* -+ * Elan4 BAR1 is split up as follows : -+ * -+ * RevA -+ * 0x3f00000 EBUS other -+ * 0x3e00000 EBUS ROM -+ * 0x3dfc000 registers -+ * 0x0000000 command ports -+ * -+ * RevB -+ * 0x3ffc000 registers -+ * 0x3ff8000 padding -+ * 0x3ff6000 i2c registers -+ * 0x0000000 command ports -+ */ -+#define ELAN4_BAR1_SIZE (1 << 26) /* 64M */ -+#define ELAN4_REG_SIZE (1 << 14) /* 16K */ -+ -+#define ELAN4_REVA_EBUS_SIZE (1 << 21) /* 2M */ -+#define ELAN4_REVA_EBUS_OFFSET (ELAN4_BAR1_SIZE - ELAN4_REVA_EBUS_SIZE) -+#define ELAN4_REVA_REG_OFFSET (ELAN4_REVA_EBUS_OFFSET - ELAN4_REG_SIZE) -+#define ELAN4_REVA_NUM_COMMAND_QUEUES (ELAN4_REVA_REG_OFFSET >> 13) -+ -+#define ELAN4_REVA_EBUS_ROM_SIZE (1 << 20) /* 1M */ -+#define ELAN4_REVA_EBUS_ROM_OFFSET 0 -+ -+#define ELAN4_REVB_I2C_PADDING (1 << 14) /* 16K */ -+#define ELAN4_REVB_I2C_SIZE (1 << 13) /* 8k */ -+#define ELAN4_REVB_REG_OFFSET (ELAN4_BAR1_SIZE - ELAN4_REG_SIZE) -+#define ELAN4_REVB_I2C_OFFSET (ELAN4_REVB_REG_OFFSET - ELAN4_REVB_I2C_PADDING - ELAN4_REVB_I2C_SIZE) -+#define ELAN4_REVB_NUM_COMMAND_QUEUES (ELAN4_REVB_I2C_OFFSET >> 13) -+ -+#endif /* notdef _ELAN4_REGISTERS_H */ -Index: linux-2.4.21/include/elan4/sdram.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/sdram.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/sdram.h 2005-06-01 23:12:54.743417216 -0400 -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_SDRAM_H -+#define __ELAN4_SDRAM_H -+ -+#ident "$Id: sdram.h,v 1.8 2003/09/24 13:55:55 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/sdram.h,v $*/ -+ -+/* Include header file generated by sdram configuration program */ -+#include -+ -+/* SDRAM bank shift definitions */ -+#define SDRAM_0_CS_SHIFT 25 -+#define SDRAM_1_CS_SHIFT 27 -+#define SDRAM_2_CS_SHIFT 28 -+#define SDRAM_3_CS_SHIFT 29 -+ -+#define SDRAM_BANK_SHIFT(cfg) \ -+ (((cfg >> SDRAM_RamSize_SH) & 3) == 0 ? SDRAM_0_CS_SHIFT : \ -+ ((cfg >> SDRAM_RamSize_SH) & 3) == 1 ? SDRAM_1_CS_SHIFT : \ -+ ((cfg >> SDRAM_RamSize_SH) & 3) == 2 ? SDRAM_2_CS_SHIFT : SDRAM_3_CS_SHIFT) -+ -+#define SDRAM_BANK_SIZE(cfg) (1ULL << SDRAM_BANK_SHIFT(cfg)) -+#define SDRAM_BANK_OFFSET(cfg,bank) ((unsigned long long)(bank) << SDRAM_BANK_SHIFT(cfg)) -+#define SDRAM_NUM_BANKS(cfg) (4) -+#define SDRAM_MAX_BANKS 4 -+ -+/* When the elan access sdram it passes eaddr[12] as sdramaddr[12] when -+ * running with a 4k page size, however PCI accesses pass paddr[12], so -+ * we must ensure that sdram pages are allocated such that eaddr[12] is the -+ * same as paddr[12] - the easiest way is to allocate sdram in 8k chunks and -+ * ensure that maddr[12] == eaddr[12] == pgoff[0] */ -+#define SDRAM_MIN_PAGE_SIZE (8192) -+ -+#endif /* __ELAN4_SDRAM_H */ -Index: linux-2.4.21/include/elan4/stats.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/stats.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/stats.h 2005-06-01 23:12:54.743417216 -0400 -@@ -0,0 +1,83 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: stats.h,v 1.10.12.1 2004/10/06 11:09:12 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/stats.h,v $*/ -+ -+#ifndef __ELAN4_STATS_H -+#define __ELAN4_STATS_H -+ -+#define ELAN4_DEV_STATS_BUCKETS 8 -+ -+ -+typedef struct elan4_dev_stats -+{ -+ unsigned long s_interrupts; -+ -+ unsigned long s_mainints[ELAN4_DEV_STATS_BUCKETS]; -+ unsigned long s_mainint_punts; -+ unsigned long s_mainint_rescheds; -+ -+ unsigned long s_haltints; -+ -+ unsigned long s_cproc_traps; -+ unsigned long s_dproc_traps; -+ unsigned long s_eproc_traps; -+ unsigned long s_iproc_traps; -+ unsigned long s_tproc_traps; -+ -+ unsigned long s_cproc_trap_types[0x10]; -+ unsigned long s_dproc_trap_types[6]; -+ unsigned long s_eproc_trap_types[4]; -+ unsigned long s_iproc_trap_types[0xa]; -+ unsigned long s_tproc_trap_types[7]; -+ -+ unsigned long s_correctable_errors; -+ unsigned long s_multiple_errors; -+ -+ unsigned long s_link_errors; -+ unsigned long s_lock_errors; -+ unsigned long s_deskew_errors; -+ unsigned long s_phase_errors; -+ unsigned long s_data_errors; -+ unsigned long s_fifo_overflow0; -+ unsigned long s_fifo_overflow1; -+ unsigned long s_mod45changed; -+ unsigned long s_pack_not_seen; -+ unsigned long s_linkport_keyfail; -+ -+ unsigned long s_eop_reset; -+ unsigned long s_bad_length; -+ unsigned long s_crc_bad; -+ unsigned long s_crc_error; -+ -+ unsigned long s_cproc_timeout; -+ unsigned long s_dproc_timeout; -+ -+ unsigned long s_sdram_bytes_free; -+} ELAN4_DEV_STATS; -+ -+#define MainIntBuckets ((int[ELAN4_DEV_STATS_BUCKETS-1]) {1, 2, 3, 4, 8, 16, 32}) -+ -+#define BumpDevStat(dev,stat) ((dev)->dev_stats.stat++) -+#define BucketDevStat(dev,stat,n,bucket) ((n) <= (bucket)[0] ? (dev)->dev_stats.stat[0]++ : \ -+ (n) <= (bucket)[1] ? (dev)->dev_stats.stat[1]++ : \ -+ (n) <= (bucket)[2] ? (dev)->dev_stats.stat[2]++ : \ -+ (n) <= (bucket)[3] ? (dev)->dev_stats.stat[3]++ : \ -+ (n) <= (bucket)[4] ? (dev)->dev_stats.stat[4]++ : \ -+ (n) <= (bucket)[5] ? (dev)->dev_stats.stat[5]++ : \ -+ (n) <= (bucket)[6] ? (dev)->dev_stats.stat[6]++ : \ -+ (dev)->dev_stats.stat[7]++) -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /*__ELAN4_STATS_H */ -Index: linux-2.4.21/include/elan4/tprintf.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/tprintf.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/tprintf.h 2005-06-01 23:12:54.743417216 -0400 -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_TPRINTF_H -+#define __ELAN4_TPRINTF_H -+ -+#ident "$Id: tprintf.h,v 1.6 2003/09/04 12:39:17 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/tprintf.h,v $*/ -+ -+ -+#ifdef _ASM -+#define TPRINTF0(string) add %r0, __LINE__, %r0 -+#define TPRINTF1(string,reg) add reg, __LINE__, %r0 -+#else -+#define TPRINTF0(string) asm volatile ("add %%r0, %0, %%r0" : : "i" (__LINE__)) -+#define TPRINTF1(string, value) asm volatile ("add %0, %1, %%r0" : : "r" (value), "i" (__LINE__)) -+#endif /* _ASM */ -+ -+#endif /* __ELAN4_TPRINTF_H */ -Index: linux-2.4.21/include/elan4/trap.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/trap.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/trap.h 2005-06-01 23:12:54.743417216 -0400 -@@ -0,0 +1,95 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: trap.h,v 1.10 2003/10/07 12:11:10 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/trap.h,v $*/ -+ -+#ifndef __ELAN4_TRAP_H -+#define __ELAN4_TRAP_H -+ -+/* -+ * If the EProc Faults whilst performing an action (e.g. Read/Write on the data src or dest Addr) -+ * the Eproc increments the Addr(s) by a block size (64 bytes): -+ * 1: Fault on Read: -+ * Src EventAddr = Read Addr + block -+ * 2: Fault on Write: -+ * Src EventAddr = Read Addr + block -+ * Dst EventAddr = Read Addr + block -+ * Size = Size - block ndwords -+ * We must rewind the addr correctly to completely the transfer successfully -+ */ -+#define EVENT_COPY_NDWORDS 0x8 -+#define EVENT_COPY_BLOCK_SIZE 0x40 -+ -+typedef struct elan4_eproc_trap -+{ -+ E4_uint64 tr_status; -+ E4_FaultSave tr_faultarea; -+ E4_Event tr_event; -+ E4_Addr tr_eventaddr; -+} ELAN4_EPROC_TRAP; -+ -+typedef struct elan4_cproc_trap -+{ -+ E4_uint64 tr_status; /* cproc status register */ -+ E4_uint64 tr_command; /* cproc command */ -+ E4_CommandQueueDesc tr_qdesc; /* copy of command queue descriptor */ -+ E4_FaultSave tr_faultarea; /* fault area for mmu traps */ -+ ELAN4_EPROC_TRAP tr_eventtrap; /* associated event trap (waitevent) */ -+} ELAN4_CPROC_TRAP; -+ -+typedef struct elan4_dproc_trap -+{ -+ E4_DMA tr_desc; -+ E4_FaultSave tr_packAssemFault; -+ E4_FaultSave tr_prefetchFault; -+ E4_uint64 tr_status; -+} ELAN4_DPROC_TRAP; -+ -+typedef struct elan4_tproc_trap -+{ -+ E4_uint64 tr_regs[64]; -+ E4_FaultSave tr_dataFault; -+ E4_FaultSave tr_instFault; -+ E4_uint64 tr_status; -+ E4_uint64 tr_state; -+ E4_Addr tr_pc; -+ E4_Addr tr_npc; -+ E4_uint64 tr_dirty; -+ E4_uint64 tr_bad; -+} ELAN4_TPROC_TRAP; -+ -+typedef struct elan4_iproc_trap -+{ -+ E4_uint32 tr_numTransactions; -+ E4_uint32 tr_flags; -+ E4_uint32 tr_trappedTrans; -+ E4_uint32 tr_waitForEopTrans; -+ E4_uint32 tr_identifyTrans; -+ E4_uint32 tr_pad; -+ -+ E4_FaultSave tr_faultarea; -+ E4_IprocTrapHeader tr_transactions[MAX_TRAPPED_TRANS]; -+ E4_IprocTrapData tr_dataBuffers[MAX_TRAPPED_TRANS]; -+} ELAN4_IPROC_TRAP; -+ -+#define TR_FLAG_ACK_SENT (1 << 0) -+#define TR_FLAG_EOP_ERROR (1 << 1) -+#define TR_FLAG_BAD_TRANS (1 << 2) -+#define TR_FLAG_DMA_PACKET (1 << 3) -+#define TR_FLAG_EOP_BAD (1 << 4) -+#define TR_FLAG_TOOMANY_TRANS (1 << 5) -+ -+#define TR_TRANS_INVALID (0xffffffff) -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_TRAP_H */ -Index: linux-2.4.21/include/elan4/trtype.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/trtype.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/trtype.h 2005-06-01 23:12:54.744417064 -0400 -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _ELAN4_TRTYPE_H -+#define _ELAN4_TRTYPE_H -+ -+#ident "$Id: trtype.h,v 1.20 2004/02/06 10:38:21 mike Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/trtype.h,v $*/ -+ -+/*<15:11> Size field is used to give the number of additional 64 bit data values. -+ A value from 0 to 16 inclusive is valid. */ -+ -+#include -+ -+#define TR_SIZE_SHIFT (11) -+#define TR_SIZE_MASK (0x1f << TR_SIZE_SHIFT) -+#define SET_TR_SIZE(Size) (((Size) << TR_SIZE_SHIFT) & TR_SIZE_MASK) -+ -+/* <10:9> Last Transaction and AckNow bits, marks the last transaction and -+ enables a PACK_OK to be sent. */ -+#define TR_LAST_AND_SEND_ACK (3 << 9) -+ -+ -+/* <8> Only valid on the last transaction. Delays execution until an EOP_GOOD is received. -+ * Any other EOP type will abort execution of this transaction. */ -+#define TR_WAIT_FOR_EOP (1 << 8) -+ -+/* -+ * Data type. This is used by transactions of variable data type. It controls any endian -+ * converion required if the destiantion host processor has a big endian memory format. -+ */ -+/* WriteBlock <8:7> Data type -+ <6:0> Part write size */ -+#define TR_DATATYPE_SHIFT (6) -+#define TR_DATATYPE_MASK ((1 << 2) - 1) -+ -+#define TR_DATATYPE_BYTE E4_DATATYPE_BYTE -+#define TR_DATATYPE_SHORT E4_DATATYPE_SHORT -+#define TR_DATATYPE_WORD E4_DATATYPE_WORD -+#define TR_DATATYPE_DWORD E4_DATATYPE_DWORD -+ -+/* <5:0> Transaction Type -+ * For Writeblock <5:3> 000 => Write, 0001 => Read -+ * <2:0> End Byte Addr */ -+#define TR_OPCODE_MASK 0x3F -+#define TR_BLOCK_OPCODE_MASK 0x38 -+ -+#define TR_WRITEBLOCK 0x0 -+#define TR_ENDBYTE_MASK 0x7 -+#define TR_WRITE(Size, EndByte, DataType) \ -+ (0x0 | SET_TR_SIZE(Size) | ((EndByte) & TR_ENDBYTE_MASK) | \ -+ (((DataType) & TR_DATATYPE_MASK) << TR_DATATYPE_SHIFT)) -+ -+#define TR_NOP_TRANS (0x10 | SET_TR_SIZE(0)) -+#define TR_SETEVENT 0x10 -+#define TR_SETEVENT_NOIDENT (TR_SETEVENT | SET_TR_SIZE(0) | TR_LAST_AND_SEND_ACK) -+#define TR_SETEVENT_IDENTIFY (TR_SETEVENT | SET_TR_SIZE(1) | TR_LAST_AND_SEND_ACK) -+#define TR_REMOTEDMA (0x11 | SET_TR_SIZE(7) | TR_LAST_AND_SEND_ACK) -+#define TR_SENDDISCARD (0x12 | SET_TR_SIZE(0)) -+ -+/* -+ * Conditional transactions that might return PAckTestFail. -+ * All will allow further exection of the packet if ([Address] operator DataValue) is true. -+ * e.g. for TR_GTE further execution if ([Address] >= DataValue) is true. -+ * These should be used where a definite TRUE/FALSE answer is required. -+ */ -+#define TR_GTE (0x14 | SET_TR_SIZE(1)) -+#define TR_LT (0x15 | SET_TR_SIZE(1)) -+#define TR_EQ (0x16 | SET_TR_SIZE(1)) -+#define TR_NEQ (0x17 | SET_TR_SIZE(1)) -+ -+/* -+ * Conditional transactions that might return PAckDiscard. -+ * All will allow further exection of the packet if ([Address] operator DataValue) is true. -+ * e.g. for TR_GTE further execution if ([Address] >= DataValue) is true. -+ * These should be used where eventually a TRUE answer is expected but the node might not be ready yet. -+ * These can be mixed with the normal conditionals to allow a single packet to test for readyness and -+ * a TRUE/FALSE answer. -+ */ -+#define TR_GTE_DISCARD (0x34 | SET_TR_SIZE(1)) -+#define TR_LT_DISCARD (0x35 | SET_TR_SIZE(1)) -+#define TR_EQ_DISCARD (0x36 | SET_TR_SIZE(1)) -+#define TR_NEQ_DISCARD (0x37 | SET_TR_SIZE(1)) -+ -+#define TR_TRACEROUTE_TRANS 0x18 -+#define TR_TRACEROUTE(Size) (TR_TRACEROUTE_TRANS | (TR_DATATYPE_WORD << TR_DATATYPE_SHIFT) |SET_TR_SIZE(Size)) -+#define TR_IDENTIFY (0x19 | SET_TR_SIZE(0)) -+ -+#define TR_ADDWORD (0x1c | SET_TR_SIZE(2) | TR_LAST_AND_SEND_ACK) -+#define TR_INPUT_Q_COMMIT (0x1d | SET_TR_SIZE(1) | TR_LAST_AND_SEND_ACK) -+#define TR_TESTANDWRITE (0x1e | SET_TR_SIZE(3) | TR_LAST_AND_SEND_ACK) -+#define TR_INPUT_Q_GETINDEX (0x1f | SET_TR_SIZE(0)) -+ -+ -+ -+/* TraceRoute formate */ -+#define TR_TRACEROUTE0_CHANID(val) ((val) & 1) /* 0 Chan Id */ -+#define TR_TRACEROUTE0_LINKID(val) (((val) >> 1) & 7) /* 1:3 Link Id */ -+#define TR_TRACEROUTE0_REVID(val) (((val) >> 4) & 7) /* 4:6 Revision Id */ -+#define TR_TRACEROUTE0_BCAST_PIN(val) (((val) >> 7) & 1) /* 7 Bcast Top Pin */ -+#define TR_TRACEROUTE0_LNR(val) (((val) >> 8) & 0xFF) /* 8:15 Global Link Not Ready */ -+ -+#define TR_TRACEROUTE1_ROUTES_SELECTED(val) ((val & 0xFF)) /* 0:7 Routes Selected */ -+#define TR_TRACEROUTE1_BCAST_TOP(val) (((val) >> 8) & 7) /* 8:10 Broadcast Top */ -+#define TR_TRACEROUTE1_BCAST_BOTTOM(val) (((val) >> 12) & 7) /* 12:14 Broadcast Bottom */ -+ -+#endif /* _ELAN4_TRANSACTIONTYPE_H */ -Index: linux-2.4.21/include/elan4/types.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/types.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/types.h 2005-06-01 23:12:54.744417064 -0400 -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_TYPES_H -+#define __ELAN4_TYPES_H -+ -+#ident "@(#)$Id: types.h,v 1.9 2003/09/04 12:39:17 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/types.h,v $*/ -+ -+#include -+/* -+ * "flip" values for correctly indexing into -+ * block data which was copied from the Elan -+ * using 64 bit accesses. -+ */ -+#if defined(__LITTLE_ENDIAN__) -+# define ByteEndianFlip 0 -+# define ShortEndianFlip 0 -+# define WordEndianFlip 0 -+#else -+# define ByteEndianFlip 7 -+# define ShortEndianFlip 3 -+# define WordEndianFlip 1 -+#endif -+ -+ -+#ifndef _ASM -+ -+typedef signed int E4_int; -+typedef unsigned int E4_uint; -+ -+typedef signed char E4_int8; -+typedef unsigned char E4_uint8; -+ -+typedef signed short E4_int16; -+typedef unsigned short E4_uint16; -+ -+typedef signed int E4_int32; -+typedef unsigned int E4_uint32; -+ -+#ifdef _LP64 -+typedef signed long E4_int64; -+typedef unsigned long E4_uint64; -+#else -+typedef signed long long E4_int64; -+typedef unsigned long long E4_uint64; -+#endif -+ -+/* 64-bit Elan4 */ -+typedef E4_uint64 E4_Addr; -+typedef E4_uint32 E4_LocPhysAddr; /* Really 31 bits */ -+ -+#define OneK (1024) -+#define EightK (8*OneK) -+ -+#define E4_DATATYPE_BYTE 0 -+#define E4_DATATYPE_SHORT 1 -+#define E4_DATATYPE_WORD 2 -+#define E4_DATATYPE_DWORD 3 -+ -+#endif /* _ASM */ -+ -+#endif /* __ELAN4_TYPES_H */ -+ -Index: linux-2.4.21/include/elan4/user.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/user.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/user.h 2005-06-01 23:12:54.745416912 -0400 -@@ -0,0 +1,344 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: user.h,v 1.37.2.2 2004/11/18 17:54:17 duncant Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/user.h,v $*/ -+ -+#ifndef __ELAN4_USER_H -+#define __ELAN4_USER_H -+ -+#include -+#include -+#include -+ -+typedef struct trap_queue -+{ -+ unsigned q_back; /* Next free space */ -+ unsigned q_front; /* First object to remove */ -+ unsigned q_size; /* Size of queue */ -+ unsigned q_count; /* Current number of entries */ -+ unsigned q_slop; /* FULL <=> (count+slop) == size */ -+} RING_QUEUE; -+ -+#define RING_QUEUE_INIT(q,num,slop) ((q).q_size = (num), (q).q_slop = (slop), (q).q_front = (q).q_back = 0, (q).q_count = 0) -+#define RING_QUEUE_FULL(q) ((q).q_count >= ((q).q_size - (q).q_slop)) -+#define RING_QUEUE_REALLY_FULL(q) ((q).q_count == (q).q_size) -+#define RING_QUEUE_EMPTY(q) ((q).q_count == 0) -+#define RING_QUEUE_NEXT(q,indx) ((indx) = (((indx)+1) % (q).q_size)) -+#define RING_QUEUE_PREV(q,indx) ((indx) = (((indx)+(q).q_size-1) % (q).q_size)) -+#define RING_QUEUE_ADD(q) (RING_QUEUE_NEXT(q ,(q).q_back), (++(q).q_count) >= ((q).q_size - (q).q_slop)) -+#define RING_QUEUE_REMOVE(q) (RING_QUEUE_NEXT(q, (q).q_front), (--(q).q_count) == 0) -+#define RING_QUEUE_ADD_FRONT(q) (RING_QUEUE_PREV(q, (q).q_front), (++(q).q_count) >= ((q).q_size - (q).q_slop)) -+#define RING_QUEUE_ENTRY(qArea,indx) (&(qArea)[(indx)]) -+#define RING_QUEUE_FRONT(q,qArea) RING_QUEUE_ENTRY(qArea, (q).q_front) -+#define RING_QUEUE_BACK(q,qArea) RING_QUEUE_ENTRY(qArea, (q).q_back) -+#define RING_QUEUE_ITERATE(q,idx) for (idx = (q).q_front; idx != (q).q_back; idx = (((idx) + 1) % (q).q_size)) -+ -+typedef struct user_rgn -+{ -+ struct user_rgn *rgn_mnext; /* Doubly linked list of regions */ -+ struct user_rgn *rgn_mprev; /* sorted on main address */ -+ virtaddr_t rgn_mbase; /* main address of base of region */ -+ -+ struct user_rgn *rgn_enext; /* Doubly linked list of regions */ -+ struct user_rgn *rgn_eprev; /* sorted on elan address */ -+ E4_Addr rgn_ebase; /* elan address of base of region */ -+ -+ unsigned long rgn_len; /* length of region */ -+ unsigned rgn_perm; /* elan access permission */ -+} USER_RGN; -+ -+typedef struct user_vpseg -+{ -+ struct list_head vps_link; -+ -+ unsigned short vps_process; /* virtual process number */ -+ unsigned short vps_entries; /* and # virtual processes */ -+ -+ unsigned vps_type; -+ union -+ { -+ struct { -+ ELAN_CAPABILITY *cap; -+ E4_VirtualProcessEntry *routes; -+ } p2p; -+#define vps_p2p_cap vps_u.p2p.cap -+#define vps_p2p_routes vps_u.p2p.routes -+ -+ struct { -+ unsigned short lowvp; -+ unsigned short highvp; -+ } bcast; -+#define vps_bcast_lowvp vps_u.bcast.lowvp -+#define vps_bcast_highvp vps_u.bcast.highvp -+ } vps_u; -+} USER_VPSEG; -+ -+/* values for vps_type */ -+#define USER_VPSEG_P2P 0 -+#define USER_VPSEG_BCAST 1 -+ -+typedef struct user_cq -+{ -+ struct list_head ucq_link; -+ -+ ELAN4_CQ *ucq_cq; /* the real command queue */ -+ -+ unsigned char ucq_state; /* command queue state */ -+ unsigned char ucq_errored; /* command queue has errored */ -+ unsigned char ucq_flags; /* flags */ -+ ELAN4_CPROC_TRAP ucq_trap; /* trap state */ -+ -+ atomic_t ucq_ref; /* # references to this cq (mmaps) */ -+} USER_CQ; -+ -+/* values for ucq_state */ -+#define UCQ_RUNNING 0 /* command queue is running */ -+#define UCQ_TRAPPED 1 /* command queue has trapped */ -+#define UCQ_NEEDS_RESTART 2 /* command queue has trapped, and needs restarting */ -+#define UCQ_STOPPED 3 /* command queue has trapped, and delivered to user */ -+ -+/* values for ucq_flags */ -+#define UCQ_SYSTEM (1 << 0) -+#define UCQ_REORDER (1 << 1) -+ -+extern int num_fault_save; -+extern int min_fault_pages; -+extern int max_fault_pages; -+ -+typedef struct fault_save -+{ -+ struct fault_save *next; -+ E4_Addr addr; -+ E4_uint32 count; -+} FAULT_SAVE; -+ -+typedef struct user_iproc_trap -+{ -+ unsigned char ut_state; -+ ELAN4_IPROC_TRAP ut_trap; -+} USER_IPROC_TRAP; -+ -+/* values for ut_state */ -+#define UTS_IPROC_RUNNING 0 -+#define UTS_IPROC_TRAPPED 1 -+#define UTS_IPROC_RESOLVING 2 -+#define UTS_IPROC_EXECUTE_PACKET 3 -+#define UTS_IPROC_EXECUTING 4 -+#define UTS_IPROC_NETWORK_ERROR 5 -+#define UTS_IPROC_STOPPED 6 -+ -+typedef struct user_ctxt_entry -+{ -+ struct list_head cent_link; /* entry chained on context */ -+ ELAN_CAPABILITY *cent_cap; /* capability we attached with */ -+} USER_CTXT_ENTRY; -+ -+typedef struct user_ctxt -+{ -+ ELAN4_CTXT uctx_ctxt; /* is also an elan context */ -+ -+ spinlock_t uctx_spinlock; /* spinlock for items used with interrupt handler */ -+ kcondvar_t uctx_wait; /* place to sleep (traphandler/swapout/swapin/neterr fixup) */ -+ -+ unsigned uctx_status; /* status (uctx_spinlock) */ -+ -+ pid_t uctx_trap_pid; /* pid to deliver signals to on trap */ -+ int uctx_trap_signo; /* signal number to deliver */ -+ unsigned uctx_trap_state; /* state of trap handling code */ -+ unsigned uctx_trap_count; /* count of "thread" in user_trap_handler() */ -+ -+ unsigned uctx_int_count; /* # interrupts since last zeroed */ -+ unsigned long uctx_int_start; /* tick when int_count last zeroed */ -+ unsigned long uctx_int_delay; /* # ticks to delay next wakeup */ -+ struct timer_list uctx_int_timer; /* and timer to use to delay signal */ -+ -+ struct timer_list uctx_neterr_timer; /* network error timer */ -+ -+ struct list_head uctx_vpseg_list; /* list of vp segments we've got */ -+ kmutex_t uctx_vpseg_lock; /* and lock to protect it. */ -+ ELAN4_ROUTE_TABLE *uctx_routetable; /* our virtual process table */ -+ ELAN_POSITION uctx_position; /* position in network */ -+ -+ struct list_head uctx_cent_list; /* list of attached network contexts */ -+ -+ USER_CQ *uctx_ddcq; /* command queue for re-issueing traps */ -+ E4_uint64 uctx_ddcq_insertcnt; /* # dwords inserted into command queue */ -+ E4_uint64 uctx_ddcq_completed; /* last "completed" write was here */ -+ int uctx_ddcq_intr; /* count of outstanding ddcq interrupts */ -+ -+ ELAN4_HALTOP uctx_haltop; /* halt operation for flushing */ -+ ELAN4_DMA_FLUSHOP uctx_dma_flushop; /* flush operation for flushing dma runqueue */ -+ -+ INTCOOKIE_TABLE *uctx_intcookie_table; /* table of interrupt cookies (shared with other uctxs for this task) */ -+ -+ kmutex_t uctx_cqlock; /* lock for create/destory cqs */ -+ struct list_head uctx_cqlist; /* list of command queues (uctx_cqlock,uctx_spinlock) */ -+ -+ ELAN4_DPROC_TRAP *uctx_dprocTraps; /* queue of dproc traps to resolve/reissue */ -+ RING_QUEUE uctx_dprocTrapQ; -+ -+ ELAN4_TPROC_TRAP *uctx_tprocTraps; /* queue of tproc traps to resolve/reissue */ -+ RING_QUEUE uctx_tprocTrapQ; -+ -+ ELAN4_EPROC_TRAP *uctx_eprocTraps; /* queue of eproc traps to resolve */ -+ RING_QUEUE uctx_eprocTrapQ; -+ -+ USER_IPROC_TRAP uctx_iprocTrap[2]; /* input trap state, 1 per virtual channel */ -+ -+ E4_DMA *uctx_dmas; /* queue of dmas to restart */ -+ RING_QUEUE uctx_dmaQ; -+ -+ E4_ThreadRegs *uctx_threads; /* queue of threads to restart */ -+ RING_QUEUE uctx_threadQ; -+ -+ ELAN4_NETERR_MSG *uctx_msgs; /* queue of neterr messages */ -+ RING_QUEUE uctx_msgQ; -+ kmutex_t uctx_rgnmutex; /* lock for create/destroy regions */ -+ spinlock_t uctx_rgnlock; /* spinlock to protect linked lists */ -+ USER_RGN *uctx_mrgns; /* Doubly linked list of memory regions (uctx_rgnlock) */ -+ USER_RGN *uctx_mtail; /* Last memory region on list (uctx_rgnlock) */ -+ USER_RGN *uctx_mrgnlast; /* Last region 'hit' (uctx_rgnlock) */ -+ -+ USER_RGN *uctx_ergns; /* Doubly linked list of memory regions (uctx_rgnlock) */ -+ USER_RGN *uctx_etail; /* Last memory region on list (uctx_rgnlock) */ -+ USER_RGN *uctx_ergnlast; /* Last region 'hit' (uctx_rgnlock) */ -+ -+ ELAN4_USER_PAGE *uctx_upage; /* kernel page shared with user */ -+ sdramaddr_t uctx_trampoline; /* sdram page for tproc trampoline */ -+ -+ E4_Addr uctx_upage_addr; /* elan addr page mapped into */ -+ E4_Addr uctx_trestart_addr; /* address of thread restart code */ -+ FAULT_SAVE *uctx_faults; -+ FAULT_SAVE *uctx_fault_list; -+ int uctx_num_fault_save; -+ spinlock_t uctx_fault_lock; -+} USER_CTXT; -+ -+/* bit values for uctx_status */ -+#define UCTX_EXITING (1 << 0) /* context is exiting. */ -+#define UCTX_USER_FILTERING (1 << 1) /* user requested context filter */ -+#define UCTX_USER_STOPPED (1 << 2) /* user requested stop */ -+ -+#define UCTX_SWAPPING (1 << 3) /* context is swapping out */ -+#define UCTX_SWAPPED (1 << 4) /* context is swapped out */ -+ -+#define UCTX_STOPPING (1 << 5) /* stopping elan from running this context */ -+#define UCTX_STOPPED (1 << 6) /* elan no longer running this context */ -+ -+#define UCTX_EPROC_QUEUE_FULL (1 << 7) /* reasons for stopping running */ -+#define UCTX_DPROC_QUEUE_FULL (1 << 8) -+#define UCTX_TPROC_QUEUE_FULL (1 << 9) -+#define UCTX_IPROC_CH0_TRAPPED (1 << 10) -+#define UCTX_IPROC_CH1_TRAPPED (1 << 11) -+ -+#define UCTX_NETERR_TIMER (1 << 12) -+#define UCTX_NETERR_FIXUP (1 << 13) -+ -+#define UCTX_EPROC_QUEUE_OVERFLOW (1 << 14) -+#define UCTX_DPROC_QUEUE_OVERFLOW (1 << 15) -+#define UCTX_TPROC_QUEUE_OVERFLOW (1 << 16) -+ -+#define UCTX_EPROC_QUEUE_ERROR (1 << 17) -+#define UCTX_DPROC_QUEUE_ERROR (1 << 18) -+#define UCTX_TPROC_QUEUE_ERROR (1 << 19) -+ -+#define UCTX_STOPPED_REASONS (UCTX_EPROC_QUEUE_FULL | UCTX_DPROC_QUEUE_FULL | UCTX_TPROC_QUEUE_FULL) -+#define UCTX_SWAPPED_REASONS (UCTX_EXITING | UCTX_USER_STOPPED | UCTX_NETERR_FIXUP) -+#define UCTX_NACKING_REASONS (UCTX_USER_FILTERING | UCTX_IPROC_CH0_TRAPPED | UCTX_IPROC_CH1_TRAPPED) -+ -+#define UCTX_OVERFLOW_REASONS (UCTX_EPROC_QUEUE_OVERFLOW | UCTX_DPROC_QUEUE_OVERFLOW | UCTX_TPROC_QUEUE_OVERFLOW) -+#define UCTX_ERROR_REASONS (UCTX_EPROC_QUEUE_ERROR | UCTX_DPROC_QUEUE_ERROR | UCTX_TPROC_QUEUE_ERROR) -+ -+#define UCTX_RUNNABLE(uctx) (((uctx)->uctx_status & (UCTX_SWAPPED_REASONS | UCTX_STOPPED_REASONS)) == 0) -+#define UCTX_NACKING(uctx) (((uctx)->uctx_status & (UCTX_SWAPPED_REASONS | UCTX_STOPPED_REASONS | UCTX_NACKING_REASONS)) != 0) -+ -+/* values for uctx_trap_signalled */ -+#define UCTX_TRAP_IDLE 0 -+#define UCTX_TRAP_SLEEPING 1 -+#define UCTX_TRAP_SIGNALLED 2 -+#define UCTX_TRAP_ACTIVE 3 -+ -+extern int user_p2p_route_options; -+extern int user_bcast_route_options; -+extern int user_dproc_retry_count; -+extern int user_cproc_retry_count; -+ -+extern USER_CTXT *user_alloc (ELAN4_DEV *dev); -+extern void user_free (USER_CTXT *uctx); -+extern void user_swapout (USER_CTXT *uctx, unsigned reason); -+extern void user_swapin (USER_CTXT *uctx, unsigned reason); -+extern int user_attach (USER_CTXT *uctx, ELAN_CAPABILITY *cap); -+extern void user_detach (USER_CTXT *uctx, ELAN_CAPABILITY *cap); -+extern void user_block_inputter (USER_CTXT *uctx, unsigned blocked); -+extern int user_alloc_trap_queues (USER_CTXT *uctx, unsigned ndproc_traps, unsigned neproc_traps, -+ unsigned ntproc_traps, unsigned nthreads, unsigned ndmas); -+ -+extern int user_add_p2pvp (USER_CTXT *uctx, unsigned process, ELAN_CAPABILITY *cap); -+extern int user_add_bcastvp (USER_CTXT *uctx, unsigned process, unsigned lowvp, unsigned highvp); -+extern int user_removevp (USER_CTXT *uctx, unsigned process); -+ -+extern int user_set_route (USER_CTXT *uctx, unsigned process, E4_VirtualProcessEntry *route); -+extern int user_reset_route (USER_CTXT *uctx, unsigned process); -+extern int user_get_route (USER_CTXT *uctx, unsigned process, E4_VirtualProcessEntry *route); -+extern int user_check_route (USER_CTXT *uctx, unsigned process, E4_VirtualProcessEntry *route, unsigned *error); -+extern int user_send_neterr_msg (USER_CTXT *uctx, unsigned int vp, unsigned int nctx, unsigned int retries, ELAN4_NETERR_MSG *msg); -+extern int user_neterr_sten (USER_CTXT *uctx, unsigned int vp, E4_uint64 cookie, int waitforeop); -+extern int user_neterr_dma (USER_CTXT *uctx, unsigned int vp, E4_uint64 cookie, int waitforeop); -+ -+extern int user_resume_eproc_trap (USER_CTXT *uctx, E4_Addr addr); -+extern int user_resume_cproc_trap (USER_CTXT *uctx, unsigned indx); -+extern int user_resume_dproc_trap (USER_CTXT *uctx, E4_DMA *dma); -+extern int user_resume_tproc_trap (USER_CTXT *uctx, E4_ThreadRegs *regs); -+extern int user_resume_iproc_trap (USER_CTXT *uctx, unsigned channel, unsigned trans, -+ E4_IprocTrapHeader *hdrp, E4_IprocTrapData *datap); -+ -+extern int user_trap_handler (USER_CTXT *uctx, ELAN4_USER_TRAP *utrapp, int nticks); -+extern USER_CQ *user_findcq (USER_CTXT *uctx, unsigned num); -+extern USER_CQ *user_alloccq (USER_CTXT *uctx, unsigned size, unsigned perm, unsigned flags); -+extern void user_freecq (USER_CTXT *uctx, USER_CQ *cq); -+extern void user_dropcq (USER_CTXT *uctx, USER_CQ *cq); -+ -+/* user_osdep.c */ -+extern int user_load_range (USER_CTXT *uctx, E4_Addr addr, unsigned long nbytes, E4_uint32 fsr); -+extern void user_update_main (USER_CTXT *uctx, struct mm_struct *mm, unsigned long start, unsigned long len); -+extern void user_unload_main (USER_CTXT *uctx, unsigned long start, unsigned long len); -+ -+ -+/* regions.c */ -+extern USER_RGN *user_findrgn_elan (USER_CTXT *uctx, E4_Addr addr, int tail); -+extern USER_RGN *user_findrgn_main (USER_CTXT *uctx, virtaddr_t addr, int tail); -+extern USER_RGN *user_rgnat_elan (USER_CTXT *uctx, E4_Addr addr); -+extern USER_RGN *user_rgnat_main (USER_CTXT *uctx, virtaddr_t addr); -+extern int user_setperm (USER_CTXT *uctx, virtaddr_t maddr, E4_Addr eaddr, unsigned long len, unsigned perm); -+extern void user_clrperm (USER_CTXT *uctx, E4_Addr addr, unsigned long len); -+extern int user_checkperm (USER_CTXT *uctx, E4_Addr raddr, unsigned long rsize, unsigned access); -+extern virtaddr_t user_elan2main (USER_CTXT *uctx, E4_Addr addr); -+extern E4_Addr user_main2elan (USER_CTXT *uctx, virtaddr_t addr); -+extern void user_preload_main (USER_CTXT *uctx, virtaddr_t addr, unsigned long len); -+extern void user_freergns (USER_CTXT *uctx); -+ -+/* user_ddcq.c */ -+extern int user_ddcq_check (USER_CTXT *uctx, unsigned num); -+extern int user_ddcq_flush (USER_CTXT *uctx); -+extern void user_ddcq_intr (USER_CTXT *uctx); -+extern void user_ddcq_write_dword (USER_CTXT *uctx, E4_Addr addr, E4_uint64 value); -+extern void user_ddcq_interrupt (USER_CTXT *uctx, E4_uint64 cookie); -+extern void user_ddcq_run_dma (USER_CTXT *uctx, E4_DMA *dma); -+extern void user_ddcq_run_thread (USER_CTXT *uctx, E4_ThreadRegs *regs); -+extern void user_ddcq_setevent (USER_CTXT *uctx, E4_Addr addr); -+extern void user_ddcq_seteventn (USER_CTXT *uctx, E4_Addr addr, E4_uint32 count); -+extern void user_ddcq_waitevent (USER_CTXT *uctx, E4_Addr addr, E4_uint64 CountAndType, E4_uint64 Param0, E4_uint64 Param1); -+ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_USER_H */ -Index: linux-2.4.21/include/elan4/userregs.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/userregs.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/userregs.h 2005-06-01 23:12:54.746416760 -0400 -@@ -0,0 +1,383 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_USERREGS_H -+#define __ELAN4_USERREGS_H -+ -+#ident "$Id: userregs.h,v 1.14.2.1 2004/10/07 10:57:40 addy Exp $" -+/* $Source: /cvs/master/quadrics/elan4hdr/userregs.h,v $*/ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* -+ * Statistic control reg values -+ * Each 4-bit nibble of the control word specifies what statistic -+ * is to be recorded in each of the 8 statistic counters -+ */ -+#define COUNT_REG0_SHIFT 32ull -+#define COUNT_REG1_SHIFT 36ull -+#define COUNT_REG2_SHIFT 40ull -+#define COUNT_REG3_SHIFT 44ull -+#define COUNT_REG4_SHIFT 48ull -+#define COUNT_REG5_SHIFT 52ull -+#define COUNT_REG6_SHIFT 56ull -+#define COUNT_REG7_SHIFT 60ull -+ -+ -+/* Count reg 0 */ -+#define STC_INPUT_NON_WRITE_BLOCKS (0x0ull << COUNT_REG0_SHIFT) -+#define STP_DMA_EOP_WAIT_ACK (0x1ull << COUNT_REG0_SHIFT) -+#define STP_TPROC_RUNNING (0x2ull << COUNT_REG0_SHIFT) -+#define STC_STEN_PKTS_OPEN (0x3ull << COUNT_REG0_SHIFT) -+#define STP_CPROC_HOLDS_FFU_DP (0x4ull << COUNT_REG0_SHIFT) -+#define STC_TLB_TABLE_WALKS (0x5ull << COUNT_REG0_SHIFT) -+#define STC_CACHE_HITS (0x6ull << COUNT_REG0_SHIFT) -+#define STC_PCI_SLAVE_READS (0x7ull << COUNT_REG0_SHIFT) -+#define STP_PCI_WAITING_FOR_GNT (0x8ull << COUNT_REG0_SHIFT) -+#define STP_SYS_CLOCK_RATE0 (0xfull << COUNT_REG0_SHIFT) -+ -+#define STATS_REG0_NAMES { \ -+ "STC_INPUT_NON_WRITE_BLOCKS", \ -+ "STP_DMA_EOP_WAIT_ACK", \ -+ "STP_TPROC_RUNNING", \ -+ "STC_STEN_PKTS_OPEN", \ -+ "STP_CPROC_HOLDS_FFU_DP", \ -+ "STC_TLB_TABLE_WALKS", \ -+ "STC_CACHE_HITS", \ -+ "STC_PCI_SLAVE_READS", \ -+ "STP_PCI_WAITING_FOR_GNT", \ -+ "STP_SYS_CLOCK_RATE0" \ -+} -+ -+/* Count reg 1 */ -+#define STC_INPUT_WRITE_BLOCKS (0x0ull << COUNT_REG1_SHIFT) -+#define STP_DMA_DATA_TRANSMITTING (0x1ull << COUNT_REG1_SHIFT) -+#define STC_CPROC_VALUES_EXE (0x2ull << COUNT_REG1_SHIFT) -+#define STC_STEN_TRANS_SENT (0x3ull << COUNT_REG1_SHIFT) -+#define STP_TPROC_DQ_HOLDS_FFU_DP (0x4ull << COUNT_REG1_SHIFT) -+#define STC_TPROC_TLB_HITS (0x5ull << COUNT_REG1_SHIFT) -+#define STC_CACHE_ALLOC_MISSES (0x6ull << COUNT_REG1_SHIFT) -+#define STP_PCI_MASTER_READ_WAITING (0x7ull << COUNT_REG1_SHIFT) -+#define STP_PCI_WAITING_FOR_DEVSEL (0x8ull << COUNT_REG1_SHIFT) -+#define STP_SYS_CLOCK_RATE1 (0xfull << COUNT_REG1_SHIFT) -+ -+#define STATS_REG1_NAMES { \ -+ "STC_INPUT_WRITE_BLOCKS", \ -+ "STP_DMA_DATA_TRANSMITTING", \ -+ "STC_CPROC_VALUES_EXE", \ -+ "STC_STEN_TRANS_SENT", \ -+ "STP_TPROC_DQ_HOLDS_FFU_DP", \ -+ "STC_TPROC_TLB_HITS", \ -+ "STC_CACHE_ALLOC_MISSES", \ -+ "STP_PCI_MASTER_READ_WAITING", \ -+ "STP_PCI_WAITING_FOR_DEVSEL", \ -+ "STP_SYS_CLOCK_RATE1" \ -+} -+ -+/* Count reg 2 */ -+#define STC_INPUT_PKTS (0x0ull << COUNT_REG2_SHIFT) -+#define STP_DMA_WAITING_MEM (0x1ull << COUNT_REG2_SHIFT) -+#define STC_CPROC_TRANSFERS (0x2ull << COUNT_REG2_SHIFT) -+#define STP_STEN_WAIT_NETWORK_BUSY (0x3ull << COUNT_REG2_SHIFT) -+#define STP_IPROC_HOLDS_FFU_DP (0x4ull << COUNT_REG2_SHIFT) -+#define STC_UNITS_TLB_HITS (0x5ull << COUNT_REG2_SHIFT) -+#define STC_CACHE_NON_ALLOC_MISSES (0x6ull << COUNT_REG2_SHIFT) -+#define STP_PCI_MASTER_WRITE_WAITING (0x7ull << COUNT_REG2_SHIFT) -+#define STC_PCI_OUT_OF_ORDER_SPLIT_COMP (0x8ull << COUNT_REG2_SHIFT) -+#define STP_SYS_CLOCK_RATE2 (0xfull << COUNT_REG2_SHIFT) -+ -+#define STATS_REG2_NAMES { \ -+ "STC_INPUT_PKTS", \ -+ "STP_DMA_WAITING_MEM", \ -+ "STC_CPROC_TRANSFERS", \ -+ "STP_STEN_WAIT_NETWORK_BUSY", \ -+ "STP_IPROC_HOLDS_FFU_DP", \ -+ "STC_UNITS_TLB_HITS", \ -+ "STC_CACHE_NON_ALLOC_MISSES", \ -+ "STP_PCI_MASTER_WRITE_WAITING", \ -+ "STC_PCI_OUT_OF_ORDER_SPLIT_COMP", \ -+ "STP_SYS_CLOCK_RATE2" \ -+} -+ -+/* Count reg 3 */ -+#define STC_INPUT_PKTS_REJECTED (0x0ull << COUNT_REG3_SHIFT) -+#define STP_DMA_WAIT_NETWORK_BUSY (0x1ull << COUNT_REG3_SHIFT) -+#define STC_CPROC_PREFETCH_SDRAM (0x2ull << COUNT_REG3_SHIFT) -+#define STP_STEN_BLOCKED_ACKS_OR_VC (0x3ull << COUNT_REG3_SHIFT) -+#define STP_EPROC_HOLDS_FFU_DP (0x4ull << COUNT_REG3_SHIFT) -+#define STP_TPROC_BLOCKED_MEMSYS (0x5ull << COUNT_REG3_SHIFT) -+#define STC_CACHE_WRITE_BACKS (0x6ull << COUNT_REG3_SHIFT) -+#define STP_PCI_SLAVE_READ_WAITING (0x7ull << COUNT_REG3_SHIFT) -+#define STP_PCI_IDLE_CYCLES (0x8ull << COUNT_REG3_SHIFT) -+#define STP_SYS_CLOCK_RATE3 (0xfull << COUNT_REG3_SHIFT) -+ -+#define STATS_REG3_NAMES { \ -+ "STC_INPUT_PKTS_REJECTED", \ -+ "STP_DMA_WAIT_NETWORK_BUSY", \ -+ "STC_CPROC_PREFETCH_SDRAM", \ -+ "STP_STEN_BLOCKED_ACKS_OR_VC", \ -+ "STP_EPROC_HOLDS_FFU_DP", \ -+ "STP_TPROC_BLOCKED_MEMSYS", \ -+ "STC_CACHE_WRITE_BACKS", \ -+ "STP_PCI_SLAVE_READ_WAITING", \ -+ "STP_PCI_IDLE_CYCLES", \ -+ "STP_SYS_CLOCK_RATE3" \ -+} -+ -+/* Count reg 4 */ -+#define STP_INPUT_DATA_TRANSMITTING (0x0ull << COUNT_REG4_SHIFT) -+#define STC_DMA_PKTS_ACCEPTED (0x1ull << COUNT_REG4_SHIFT) -+#define STC_CPROC_FLUSH_REQ_SDRAM (0x2ull << COUNT_REG4_SHIFT) -+#define STP_STEN_EOP_WAIT_ACK (0x3ull << COUNT_REG4_SHIFT) -+#define STP_DMA_HOLDS_FFU_DP (0x4ull << COUNT_REG4_SHIFT) -+#define STP_UNIT_BLOCKED_MEMSYS (0x5ull << COUNT_REG4_SHIFT) -+#define STC_PCI_MASTER_READS (0x6ull << COUNT_REG4_SHIFT) -+#define STP_PCI_SLAVE_WRITE_WAITING (0x7ull << COUNT_REG4_SHIFT) -+#define STC_INPUT_PACKETS_DISCARDED (0x8ull << COUNT_REG4_SHIFT) -+#define STP_SYS_CLOCK_RATE4 (0xfull << COUNT_REG4_SHIFT) -+ -+#define STATS_REG4_NAMES { \ -+ "STP_INPUT_DATA_TRANSMITTING", \ -+ "STC_DMA_PKTS_ACCEPTED", \ -+ "STC_CPROC_FLUSH_REQ_SDRAM", \ -+ "STP_STEN_EOP_WAIT_ACK", \ -+ "STP_DMA_HOLDS_FFU_DP", \ -+ "STP_UNIT_BLOCKED_MEMSYS", \ -+ "STC_PCI_MASTER_READS", \ -+ "STP_PCI_SLAVE_WRITE_WAITING", \ -+ "STC_INPUT_PACKETS_DISCARDED", \ -+ "STP_SYS_CLOCK_RATE4" \ -+} -+ -+/* Count reg 5 */ -+#define STP_INPUT_WAITING_NETWORK_DATA (0x0ull << COUNT_REG5_SHIFT) -+#define STC_DMA_PKTS_REJECTED (0x1ull << COUNT_REG5_SHIFT) -+#define STC_CPROC_INSERT_CACHE_MISSES (0x2ull << COUNT_REG5_SHIFT) -+#define STP_STEN_TRANSMITTING_DATA (0x3ull << COUNT_REG5_SHIFT) -+#define FFU_BLOCKED_DIFF_FFU_PROC (0x4ull << COUNT_REG5_SHIFT) -+#define STP_TABLE_WALKS_BLOCKED_MEMSYS (0x5ull << COUNT_REG5_SHIFT) -+#define STC_PCI_MASTER_WRITES (0x6ull << COUNT_REG5_SHIFT) -+#define STP_PCI_MASTER_HOLDS_BUS (0x7ull << COUNT_REG5_SHIFT) -+#define STC_PCI_NO_SPLIT_COMPS (0x8ull << COUNT_REG5_SHIFT) -+#define STP_SYS_CLOCK_RATE5 (0xfull << COUNT_REG5_SHIFT) -+ -+#define STATS_REG5_NAMES { \ -+ "STP_INPUT_WAITING_NETWORK_DATA", \ -+ "STC_DMA_PKTS_REJECTED", \ -+ "STC_CPROC_INSERT_CACHE_MISSES", \ -+ "STP_STEN_TRANSMITTING_DATA", \ -+ "FFU_BLOCKED_DIFF_FFU_PROC", \ -+ "STP_TABLE_WALKS_BLOCKED_MEMSYS", \ -+ "STC_PCI_MASTER_WRITES", \ -+ "STP_PCI_MASTER_HOLDS_BUS", \ -+ "STC_PCI_NO_SPLIT_COMPS", \ -+ "STP_SYS_CLOCK_RATE5" \ -+} -+ -+/* Count reg 6 */ -+#define STP_INPUT_BLOCKED_WAITING_TRANS (0x0ull << COUNT_REG6_SHIFT) -+#define STP_TPROC_INST_STALL (0x1ull << COUNT_REG6_SHIFT) -+#define STP_CPROC_WAITING_DESCHED (0x2ull << COUNT_REG6_SHIFT) -+#define STP_STEN_PKT_OPEN_WAITING_DATA (0x3ull << COUNT_REG6_SHIFT) -+#define STP_TLB_HASH_TABLE_ACCESSES (0x4ull << COUNT_REG6_SHIFT) -+#define STP_PCI_SLAVE_BLOCKED_MEMSYS (0x5ull << COUNT_REG6_SHIFT) -+#define STP_PCI_TRANSFERRING_DATA (0x6ull << COUNT_REG6_SHIFT) -+#define STP_PCI_MASTER_WAITING_BUS (0x7ull << COUNT_REG6_SHIFT) -+#define STP_PCI_READ_LATENCY (0x8ull << COUNT_REG6_SHIFT) -+#define STP_SYS_CLOCK_RATE6 (0xfull << COUNT_REG6_SHIFT) -+ -+#define STATS_REG6_NAMES { \ -+ "STP_INPUT_BLOCKED_WAITING_TRANS", \ -+ "STP_TPROC_INST_STALL", \ -+ "STP_CPROC_WAITING_DESCHED", \ -+ "STP_STEN_PKT_OPEN_WAITING_DATA", \ -+ "STP_TLB_HASH_TABLE_ACCESSES", \ -+ "STP_PCI_SLAVE_BLOCKED_MEMSYS", \ -+ "STP_PCI_TRANSFERRING_DATA", \ -+ "STP_PCI_MASTER_WAITING_BUS", \ -+ "STP_PCI_READ_LATENCY", \ -+ "STP_SYS_CLOCK_RATE6" \ -+} -+ -+/* Count reg 7 */ -+#define STC_INPUT_CTX_FILTER_FILL (0x0ull << COUNT_REG7_SHIFT) -+#define STP_TPROC_LOAD_STORE_STALL (0x1ull << COUNT_REG7_SHIFT) -+#define STC_CPROC_TIMEOUTS (0x2ull << COUNT_REG7_SHIFT) -+#define STP_STEN_BLOCKED_NETWORK (0x3ull << COUNT_REG7_SHIFT) -+#define STP_TLB_CHAIN_ACCESSES (0x4ull << COUNT_REG7_SHIFT) -+#define STP_CPROC_SCHED_BLOCKED_MEMSYS (0x5ull << COUNT_REG7_SHIFT) -+#define STC_PCI_SLAVE_WRITES (0x6ull << COUNT_REG7_SHIFT) -+#define STC_PCI_DISCONNECTS_RETRIES (0x7ull << COUNT_REG7_SHIFT) -+#define STC_RING_OSCILLATOR (0x8ull << COUNT_REG7_SHIFT) -+#define STP_SYS_CLOCK_RATE7 (0xfull << COUNT_REG7_SHIFT) -+ -+#define STATS_REG7_NAMES { \ -+ "STC_INPUT_CTX_FILTER_FILL", \ -+ "STP_TPROC_LOAD_STORE_STALL", \ -+ "STC_CPROC_TIMEOUTS", \ -+ "STP_STEN_BLOCKED_NETWORK", \ -+ "STP_TLB_CHAIN_ACCESSES", \ -+ "STP_CPROC_SCHED_BLOCKED_MEMSYS", \ -+ "STC_PCI_SLAVE_WRITES", \ -+ "STC_PCI_DISCONNECTS_RETRIES", \ -+ "STC_RING_OSCILLATOR", \ -+ "STP_SYS_CLOCK_RATE7" \ -+} -+ -+#define STATS_REG_NAMES { \ -+ STATS_REG0_NAMES, \ -+ STATS_REG1_NAMES, \ -+ STATS_REG2_NAMES, \ -+ STATS_REG3_NAMES, \ -+ STATS_REG4_NAMES, \ -+ STATS_REG5_NAMES, \ -+ STATS_REG6_NAMES, \ -+ STATS_REG7_NAMES, \ -+} -+ -+ -+#define INPUT_PERF_STATS (STC_INPUT_NON_WRITE_BLOCKS | STC_INPUT_WRITE_BLOCKS | \ -+ STC_INPUT_PKTS | STC_INPUT_PKTS_REJECTED | \ -+ STC_INPUT_CTX_FILTER_FILL | STP_INPUT_DATA_TRANSMITTING | \ -+ STP_INPUT_WAITING_NETWORK_DATA | STP_INPUT_BLOCKED_WAITING_TRANS | STC_INPUT_PACKETS_DISCARDED) -+ -+#define DMA_PERF_STATS (STC_DMA_PKTS_ACCEPTED | STC_DMA_PKTS_REJECTED | \ -+ STP_DMA_EOP_WAIT_ACK | STP_DMA_DATA_TRANSMITTING | \ -+ STP_DMA_WAITING_MEM | STP_DMA_WAIT_NETWORK_BUSY) -+ -+ -+#define TPROC_PERF_STATS (STP_TPROC_RUNNING | STP_TPROC_INST_STALL | \ -+ STP_TPROC_LOAD_STORE_STALL) -+ -+#define CPROC_PERF_STATS (STC_CPROC_VALUES_EXE | STC_CPROC_TRANSFERS | \ -+ STC_CPROC_PREFETCH_SDRAM | STC_CPROC_FLUSH_REQ_SDRAM | \ -+ STC_CPROC_INSERT_CACHE_MISSES | STP_CPROC_WAITING_DESCHED | \ -+ STC_CPROC_TIMEOUTS) -+ -+#define STEN_PERF_STATS (STC_STEN_PKTS_OPEN | STC_STEN_TRANS_SENT | \ -+ STP_STEN_WAIT_NETWORK_BUSY | STP_STEN_BLOCKED_ACKS_OR_VC | \ -+ STP_STEN_EOP_WAIT_ACK | STP_STEN_TRANSMITTING_DATA | \ -+ STP_STEN_PKT_OPEN_WAITING_DATA | STP_STEN_BLOCKED_NETWORK) -+ -+#define FFU_PREF_STATS (STP_CPROC_HOLDS_FFU_DP | STP_TPROC_DQ_HOLDS_FFU_DP | \ -+ STP_IPROC_HOLDS_FFU_DP | STP_EPROC_HOLDS_FFU_DP | \ -+ STP_DMA_HOLDS_FFU_DP | FFU_BLOCKED_DIFF_FFU_PROC) -+ -+#define TABLE_WALK_PERF_STATS (STC_TPROC_TLB_HITS | STC_UNITS_TLB_HITS | \ -+ STP_TLB_HASH_TABLE_ACCESSES | STP_TLB_CHAIN_ACCESSES | \ -+ STC_TLB_TABLE_WALKS) -+ -+#define ADDRESS_ARB_PERF_STATS (STP_UNIT_BLOCKED_MEMSYS | STP_TPROC_BLOCKED_MEMSYS | \ -+ STP_TABLE_WALKS_BLOCKED_MEMSYS | STP_CPROC_SCHED_BLOCKED_MEMSYS | \ -+ STP_PCI_SLAVE_BLOCKED_MEMSYS) -+ -+#define CACHE_PERF_STATS (STC_CACHE_HITS | STC_CACHE_ALLOC_MISSES | \ -+ STC_CACHE_NON_ALLOC_MISSES | STC_CACHE_WRITE_BACKS) -+ -+ -+#define PCI_PERF_STATS (STC_PCI_SLAVE_READS | STP_PCI_MASTER_READ_WAITING | \ -+ STP_PCI_MASTER_WRITE_WAITING | STP_PCI_SLAVE_READ_WAITING | \ -+ STP_PCI_SLAVE_WRITE_WAITING | STC_PCI_MASTER_WRITES | \ -+ STP_PCI_TRANSFERRING_DATA | STC_PCI_SLAVE_WRITES) -+ -+#define PCIBUS_PERF_STATS (STP_PCI_WAITING_FOR_GNT | STP_PCI_WAITING_FOR_DEVSEL | \ -+ STC_PCI_OUT_OF_ORDER_SPLIT_COMP | STP_PCI_IDLE_CYCLES | \ -+ STC_PCI_MASTER_READS | STP_PCI_MASTER_HOLDS_BUS | \ -+ STP_PCI_MASTER_WAITING_BUS | STC_PCI_DISCONNECTS_RETRIES) -+ -+ -+ extern const char *elan_stats_names[8][10]; -+ -+#define ELAN_STATS_NAME(COUNT, CONTROL) (elan_stats_names[(COUNT)][(CONTROL) & 7]) -+ -+ typedef volatile union e4_StatsControl -+ { -+ E4_uint64 StatsControl; -+ struct -+ { -+#if (BYTE_ORDER == LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) -+ E4_uint32 StatCont0:4; -+ E4_uint32 StatCont1:4; -+ E4_uint32 StatCont2:4; -+ E4_uint32 StatCont3:4; -+ E4_uint32 StatCont4:4; -+ E4_uint32 StatCont5:4; -+ E4_uint32 StatCont6:4; -+ E4_uint32 StatCont7:4; -+#else -+ E4_uint32 StatCont7:4; -+ E4_uint32 StatCont6:4; -+ E4_uint32 StatCont5:4; -+ -+ E4_uint32 StatCont4:4; -+ E4_uint32 StatCont3:4; -+ E4_uint32 StatCont2:4; -+ E4_uint32 StatCont1:4; -+ E4_uint32 StatCont0:4; -+#endif -+ E4_uint32 pad; -+ } s; -+ } E4_StatsControl; -+ -+typedef volatile union e4_StatsCount -+{ -+ E4_uint64 ClockStat; -+ struct -+ { -+ E4_uint32 ClockLSW; /* read only */ -+ E4_uint32 StatsCount; -+ } s; -+} E4_StatsCount; -+ -+typedef volatile union e4_clock -+{ -+ E4_uint64 NanoSecClock; -+ struct -+ { -+ E4_uint32 ClockLSW; -+ E4_uint32 ClockMSW; -+ } s; -+} E4_Clock; -+#define E4_TIME( X ) ((X).NanoSecClock) -+ -+#define ELAN4_COMMS_CLOCK_FREQUENCY 660 /* In Mhz. This is half the bit rate. */ -+#define ELAN4_CLOCK_ADD_VALUE 200 /* For 200ns increment rate */ -+#define ELAN4_CLOCK_COMMS_DIV_VALUE (((ELAN4_COMMS_CLOCK_FREQUENCY * ELAN4_CLOCK_ADD_VALUE) / (1000 * 4)) - 1) -+#define ELAN4_CLOCK_TICK_RATE ((ELAN4_CLOCK_ADD_VALUE << 8) + ELAN4_CLOCK_COMMS_DIV_VALUE) -+ -+typedef volatile union e4_clocktickrate -+{ -+ E4_uint64 NanoSecClock; -+ struct -+ { -+ E4_uint32 pad1; -+ E4_uint32 TickRates; -+ } s; -+} E4_ClockTickRate; -+ -+/* -+ * This is made into an 8k byte object. -+ */ -+typedef volatile struct _E4_User_Regs -+{ -+ E4_StatsCount StatCounts[8]; -+ E4_StatsCount InstCount; -+ E4_Clock Clock; -+ E4_StatsControl StatCont; -+ E4_ClockTickRate ClockTickRate; -+ E4_uint8 pad1[EightK - ((sizeof(E4_StatsCount)*9)+sizeof(E4_StatsControl)+ -+ sizeof(E4_Clock)+sizeof(E4_ClockTickRate))]; -+} E4_User_Regs; -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __ELAN4_USERREGS_H */ -Index: linux-2.4.21/include/elan4/usertrap.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/usertrap.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/usertrap.h 2005-06-01 23:12:54.746416760 -0400 -@@ -0,0 +1,114 @@ -+/* -+ * Copyright (c) 2001-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: usertrap.h,v 1.17 2004/05/05 09:08:35 david Exp $" -+/* $Source: /cvs/master/quadrics/elan4mod/usertrap.h,v $*/ -+ -+#ifndef __ELAN4_USERTRAP_H -+#define __ELAN4_USERTRAP_H -+ -+#ifndef _ASM -+typedef struct elan4_user_page -+{ -+ E4_uint64 upage_ddcq_completed; -+} ELAN4_USER_PAGE; -+ -+typedef struct elan4_user_trap -+{ -+ int ut_type; -+ unsigned ut_proc; -+ unsigned ut_args[4]; -+ -+ union { -+ ELAN4_EPROC_TRAP eproc; -+ ELAN4_CPROC_TRAP cproc; -+ ELAN4_DPROC_TRAP dproc; -+ ELAN4_IPROC_TRAP iproc; -+ ELAN4_TPROC_TRAP tproc; -+ ELAN4_NETERR_MSG msg; -+ } ut_trap; -+} ELAN4_USER_TRAP; -+ -+#endif /* _ASM */ -+ -+ -+/* value for ut_type */ -+#define UTS_FINISHED 0 /* all pending traps have been handled */ -+#define UTS_RESCHEDULE 1 /* must return to user mode and re-enter */ -+#define UTS_UNIMP_INSTR 2 /* unimplemented thread instruction */ -+#define UTS_EXECUTE_PACKET 3 /* iproc trap needs packet executing */ -+#define UTS_NETWORK_ERROR_TRAP 4 /* network error on this trap */ -+#define UTS_NETWORK_ERROR_MSG 5 /* network error message */ -+#define UTS_NETWORK_ERROR_TIMER 6 /* network error timer expired */ -+ -+#define UTS_EFAULT -1 /* failed to copyout trap */ -+#define UTS_INVALID_ADDR -2 /* all -ve codes mean trap could not be resolved. */ -+#define UTS_INVALID_VPROC -3 -+#define UTS_INVALID_COMMAND -4 -+#define UTS_BAD_TRAP -5 -+#define UTS_ALIGNMENT_ERROR -6 -+#define UTS_QUEUE_OVERFLOW -7 -+#define UTS_QUEUE_ERROR -8 -+#define UTS_INVALID_TRANS -9 -+#define UTS_PERMISSION_DENIED -10 -+#define UTS_CPROC_ERROR -11 -+#define UTS_INVALID_COOKIE -12 -+#define UTS_NETERR_ERROR -13 -+ -+/* "special" values for registering handlers */ -+#define UTS_ALL_TRAPS -9999 -+ -+/* value for ut_proc */ -+#define UTS_NOPROC 0 -+#define UTS_EPROC 1 -+#define UTS_CPROC 2 -+#define UTS_DPROC 3 -+#define UTS_TPROC 4 -+#define UTS_IPROC 5 -+#define UTS_NETERR_MSG 6 -+ -+/* unimplemented trap numbers for thread processor */ -+#define ELAN4_T_TRAP_INSTR(t) (0x80202000 | ((t) & 0xFF)) -+ -+#define ELAN4_T_SYSCALL_TRAP 1 -+# define ELAN4_T_OPEN 0 -+# define ELAN4_T_WRITE 1 -+# define ELAN4_T_READ 2 -+# define ELAN4_T_IOCTL 3 -+# define ELAN4_T_LSEEK 4 -+# define ELAN4_T_POLL 5 -+# define ELAN4_T_CLOSE 6 -+# define ELAN4_T_KILL 7 -+# define ELAN4_T_MMAP 8 -+# define ELAN4_T_MUNMAP 9 -+# define ELAN4_T_ABORT 100 -+# define ELAN4_T_DEBUG 101 -+# define ELAN4_T_REGDUMP 102 -+ -+#define ELAN4_T_REGDUMP_TRAP 2 -+ -+#define ELAN4_T_LIBELAN_TRAP 3 -+# define ELAN4_T_TPORT_NEWBUF 0 -+# define ELAN4_T_TPORT_GC 1 -+# define ELAN4_T_TPORT_DEBUG 2 -+ -+#define ELAN4_T_ALLOC_TRAP 4 -+# define ELAN4_T_ALLOC_ELAN 0 -+# define ELAN4_T_ALLOC_MAIN 1 -+# define ELAN4_T_FREE_ELAN 2 -+# define ELAN4_T_FREE_MAIN 3 -+ -+/* reserved main interrupt cookies */ -+#define ELAN4_INT_COOKIE_DDCQ 0 -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -+#endif /* __ELAN4_USERTRAP_H */ -Index: linux-2.4.21/include/elan4/xsdram.h -=================================================================== ---- linux-2.4.21.orig/include/elan4/xsdram.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/elan4/xsdram.h 2005-06-01 23:12:54.747416608 -0400 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2003 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __ELAN4_XSDRAM_H -+#define __ELAN4_XSDRAM_H -+ -+#ident "@(#)$Id: xsdram.h,v 1.13 2004/03/05 12:32:04 jon Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/elan4hdr/xsdram.h,v $*/ -+ -+/* SAMSUNG K4H281638D-TCB3 */ -+ -+#define SDRAM_tRCF_1_SH 0 -+#define SDRAM_tRP_1_SH 4 -+#define SDRAM_tRCD_SH 8 -+#define SDRAM_tRRD_SH 12 -+#define SDRAM_tEndWr_SH 16 -+#define SDRAM_tEndRd_SH 20 -+#define SDRAM_Burst_SH 24 -+#define SDRAM_CL_SH 28 -+#define SDRAM_DsblBypass (1ULL << 31) -+#define SDRAM_RefreshRate_SH 32 -+#define SDRAM_RamSize_SH 34 -+#define SDRAM_ReadLtncy_1_SH 36 -+#define SDRAM_RdOffset_SH 40 -+#define SDRAM_FlightDelay_SH 42 -+ -+#define SDRAM_ENABLE_ECC (1ULL << 44) // Enables error detecting on the ECC. -+#define SDRAM_SDRAM_TESTING (1ULL << 45) // Switches to test mode for checking EEC data bits -+#define SDRAM_SETUP (1ULL << 46) // Writes SDram control reg when set. Also starts -+ -+#define SDRAM_CS_MODE0 0ULL // 64Mbit, 128Mbit, 256Mbit, 512Mbit or 1Gbit (16-bit output) -+#define SDRAM_CS_MODE1 1ULL // 64Mbit, 128Mbit, 256Mbit or 512Mbit (8-bit output) -+#define SDRAM_CS_MODE2 2ULL // 2Gbit (16-bit output) or 1Gbit (8-bit output) -+#define SDRAM_CS_MODE3 3ULL // 4Gbit (16-bit output) or 2Gbit (8-bit output) -+ -+#if defined(LINUX) && !defined(CONFIG_MPSAS) -+#define SDRAM_STARTUP_VALUE ((0xbULL << SDRAM_tRCF_1_SH) | (0x2ULL << SDRAM_tRP_1_SH) | \ -+ (0x3ULL << SDRAM_tRCD_SH) | (0x2ULL << SDRAM_tRRD_SH) | \ -+ (0xaULL << SDRAM_tEndWr_SH) | (0x6ULL << SDRAM_tEndRd_SH) | \ -+ (0x8ULL << SDRAM_Burst_SH) | (0x6ULL << SDRAM_CL_SH) | \ -+ (0x2ULL << SDRAM_RefreshRate_SH) | (0x3ULL << SDRAM_RamSize_SH) | \ -+ (0x1ULL << SDRAM_RdOffset_SH) | (0x1ULL << SDRAM_FlightDelay_SH) | \ -+ (0x4ULL << SDRAM_ReadLtncy_1_SH)) -+#else -+#define SDRAM_STARTUP_VALUE ((0xbULL << SDRAM_tRCF_1_SH) | (0x2ULL << SDRAM_tRP_1_SH) | \ -+ (0x3ULL << SDRAM_tRCD_SH) | (0x2ULL << SDRAM_tRRD_SH) | \ -+ (0xaULL << SDRAM_tEndWr_SH) | (0x6ULL << SDRAM_tEndRd_SH) | \ -+ (0x8ULL << SDRAM_Burst_SH) | (0x6ULL << SDRAM_CL_SH) | \ -+ (0x0ULL << SDRAM_RefreshRate_SH) | (0x0ULL << SDRAM_RamSize_SH) | \ -+ (0x1ULL << SDRAM_RdOffset_SH) | (0x1ULL << SDRAM_FlightDelay_SH) | \ -+ (0x4ULL << SDRAM_ReadLtncy_1_SH) | SDRAM_ENABLE_ECC | SDRAM_SETUP) -+#endif -+ -+#endif /* __ELAN4_XSDRAM_H */ -Index: linux-2.4.21/include/jtag/jtagio.h -=================================================================== ---- linux-2.4.21.orig/include/jtag/jtagio.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/jtag/jtagio.h 2005-06-01 23:12:54.747416608 -0400 -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "$Id: jtagio.h,v 1.7.8.1 2005/01/27 15:21:47 lee Exp $" -+/* $Source: /cvs/master/quadrics/jtagmod/jtagio.h,v $*/ -+ -+ -+#ifndef __SYS_JTAGMOD_H -+#define __SYS_JTAGMOD_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define JTAG_MAX_CHIPS 8 -+#define JTAG_MAX_INSTR_LEN 8 -+#define JTAG_MAX_BITS (JTAG_MAX_CHIPS * JTAG_MAX_INSTR_LEN) -+#define JTAG_MAX_DATA_LEN 1024 -+ -+#define JTAG_BYPASS 0xFF -+ -+#define I2C_ADDR_LEN 7 /* 7 bits of address */ -+#define I2C_DATA_LEN 8 /* 8 bits of data */ -+#define I2C_MAX_DATA_LEN 9 /* and upto 9 bytes worth */ -+ -+#define BITS_PER_BYTE 8 -+#define JTAG_NBYTES(nbits) (((nbits)+BITS_PER_BYTE-1)/BITS_PER_BYTE) -+#define JTAG_BIT(v, num) (((v)[(num) / BITS_PER_BYTE] >> ((num) % BITS_PER_BYTE)) & 1) -+#define JTAG_SET_BIT(v, num) ((v)[(num) / BITS_PER_BYTE] |= (1 << ((num) % BITS_PER_BYTE))) -+#define JTAG_CLR_BIT(v, num) ((v)[(num) / BITS_PER_BYTE] &= ~(1 << ((num) % BITS_PER_BYTE))) -+ -+#define RING_CLOCK_CARD (0x3D) -+#define RING_CLOCK_SHIFT (0x3E) -+#define RING_JTAG_LOOPBACK (0x3F) -+#define RING_MAX (0x40) -+ -+#define RING_QUAD_BIT (0x40) -+#define RING_I2C_BIT (0x80) -+ -+#define VALID_JTAG_RING(ring) ((ring) < 0x20 || (ring) == RING_JTAG_LOOPBACK) -+#define VALID_I2C_RING(ring) ((ring) < 0x20 || (ring) == RING_CLOCK_CARD) -+ -+ -+typedef struct jtag_value -+{ -+ u_char bytes[JTAG_NBYTES(JTAG_MAX_DATA_LEN)]; -+} JTAG_VALUE; -+ -+/* arguements to JTAG_SHIFT_IR/JTAG_SHIFT_DR */ -+typedef struct jtag_reset_args -+{ -+ u_int ring; -+} JTAG_RESET_ARGS; -+ -+typedef struct jtag_shift_args -+{ -+ u_int ring; -+ u_int nbits; -+ u_char *value; -+} JTAG_SHIFT_ARGS; -+ -+typedef struct i2c_args -+{ -+ u_int ring; -+ u_int device; -+ u_int reg; -+ u_int count; -+ u_int ok; -+ u_char data[I2C_MAX_DATA_LEN]; -+} I2C_ARGS; -+ -+/* values for 'ok' - the return value from i2c_xx functions */ -+#define I2C_OP_SUCCESS 0 -+#define I2C_OP_ERROR 1 -+#define I2C_OP_NOT_IDLE 2 -+#define I2C_OP_NO_DEVICE 3 -+#define I2C_OP_WRITE_TO_BIG 4 -+#define I2C_OP_BAD_RESOURCE 5 -+ -+typedef struct i2c_clock_shift_args -+{ -+ u_int t; -+ u_int n; -+ u_int m; -+} I2C_CLOCK_SHIFT_ARGS; -+ -+#define JTAG_RESET _IOWR('j', '0', JTAG_RESET_ARGS) -+#define JTAG_SHIFT_IR _IOWR('j', '1', JTAG_SHIFT_ARGS) -+#define JTAG_SHIFT_DR _IOWR('j', '2', JTAG_SHIFT_ARGS) -+ -+#define I2C_CLOCK_SHIFT _IOWR('j', '4', I2C_CLOCK_SHIFT_ARGS) -+#define I2C_WRITE _IOWR('j', '5', I2C_ARGS) -+#define I2C_READ _IOWR('j', '6', I2C_ARGS) -+#define I2C_WRITEREG _IOWR('j', '7', I2C_ARGS) -+#define I2C_READREG _IOWR('j', '8', I2C_ARGS) -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __SYS_JTAGMOD_H */ -Index: linux-2.4.21/include/linux/coproc.h -=================================================================== ---- linux-2.4.21.orig/include/linux/coproc.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/linux/coproc.h 2005-06-01 23:12:54.748416456 -0400 -@@ -0,0 +1,206 @@ -+/* -+ * Copyright (C) 2002, 2003 Quadrics Ltd. -+ * -+ * 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 -+ * -+ * -+ */ -+ -+/* -+ * Callbacks for coprocessor page table updates. -+ */ -+ -+#ifndef __LINUX_COPROC_H__ -+#define __LINUX_COPROC_H__ -+ -+#include -+#include -+#include -+#include /* kmalloc */ -+ -+typedef struct coproc_ops_struct { -+ struct list_head list; -+ void *arg; -+ -+ void (*release)(void *arg, struct mm_struct *mm); -+ void (*sync_range)(void *arg, struct mm_struct *mm, unsigned long start, unsigned long end); -+ void (*invalidate_range)(void *arg, struct mm_struct *mm, unsigned long start, unsigned long end); -+ void (*update_range)(void *arg, struct mm_struct *mm, unsigned long start, unsigned long end); -+ -+ void (*change_protection)(void *arg, struct mm_struct *mm, unsigned long start, unsigned long end, pgprot_t newprot); -+ -+ void (*sync_page)(void *arg, struct vm_area_struct *vma, unsigned long address); -+ void (*invalidate_page)(void *arg, struct vm_area_struct *vma, unsigned long address); -+ void (*update_page)(void *arg, struct vm_area_struct *vma, unsigned long address); -+ -+} coproc_ops_t; -+ -+extern __inline__ void -+register_coproc_ops(struct mm_struct *mm, coproc_ops_t *cp) -+{ -+ if (mm->coproc_ops == NULL) { -+ mm->coproc_ops = (struct list_head *) -+ kmalloc(sizeof(struct list_head), GFP_KERNEL); -+ INIT_LIST_HEAD(mm->coproc_ops); -+ } -+ list_add(&cp->list, mm->coproc_ops); -+} -+ -+extern __inline__ void -+unregister_coproc_ops(struct mm_struct *mm, coproc_ops_t *cp) -+{ -+ list_del(&cp->list); -+ if (list_empty(mm->coproc_ops)) { -+ kfree(mm->coproc_ops); -+ mm->coproc_ops = NULL; -+ } -+} -+ -+extern __inline__ void -+coproc_release(struct mm_struct *mm) -+{ -+ struct list_head *head = mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ while (! list_empty(head)) { -+ lp = head->next; -+ cp = list_entry(lp, coproc_ops_t, list); -+ -+ list_del (&cp->list); -+ -+ if (cp->release) -+ cp->release(cp->arg, mm); -+ } -+ kfree(head); -+ mm->coproc_ops = NULL; -+ } -+} -+ -+extern __inline__ void -+coproc_sync_range(struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ struct list_head *head = mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->sync_range) -+ cp->sync_range(cp->arg, mm, start, end); -+ } -+ } -+} -+ -+extern __inline__ void -+coproc_invalidate_range(struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ struct list_head *head = mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->invalidate_range) -+ cp->invalidate_range(cp->arg, mm, start, end); -+ } -+ } -+} -+ -+extern __inline__ void -+coproc_update_range(struct mm_struct *mm, unsigned long start, unsigned long end) -+{ -+ struct list_head *head = mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->update_range) -+ cp->update_range(cp->arg, mm, start, end); -+ } -+ } -+} -+ -+extern __inline__ void -+coproc_change_protection (struct mm_struct *mm, unsigned long start, unsigned long end, pgprot_t newprot) -+{ -+ struct list_head *head = mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->change_protection) -+ cp->change_protection(cp->arg, mm, start, end, newprot); -+ } -+ } -+} -+ -+extern __inline__ void -+coproc_sync_page(struct vm_area_struct *vma, unsigned long addr) -+{ -+ struct list_head *head = vma->vm_mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->sync_page) -+ cp->sync_page(cp->arg, vma, addr); -+ } -+ } -+} -+ -+extern __inline__ void -+coproc_invalidate_page(struct vm_area_struct *vma, unsigned long addr) -+{ -+ struct list_head *head = vma->vm_mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->invalidate_page) -+ cp->invalidate_page(cp->arg, vma, addr); -+ } -+ } -+} -+ -+extern __inline__ void -+coproc_update_page(struct vm_area_struct *vma, unsigned long addr) -+{ -+ struct list_head *head = vma->vm_mm->coproc_ops; -+ struct list_head *lp; -+ coproc_ops_t *cp; -+ -+ if (head) { -+ for (lp = head->next; lp != head; lp = lp->next) { -+ cp = list_entry(lp, coproc_ops_t, list); -+ if (cp->update_page) -+ cp->update_page(cp->arg, vma, addr); -+ } -+ } -+} -+ -+ -+#endif /* __LINUX_COPROC_H__ */ -Index: linux-2.4.21/include/linux/ptrack.h -=================================================================== ---- linux-2.4.21.orig/include/linux/ptrack.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/linux/ptrack.h 2005-06-01 23:12:54.748416456 -0400 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2000 Regents of the University of California -+ * -+ * 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 -+ * -+ * Derived from exit_actn.c by -+ * Copyright (C) 2003 Quadrics Ltd. -+ * -+ */ -+#ifndef __LINUX_PTRACK_H -+#define __LINUX_PTRACK_H -+ -+/* -+ * Process tracking - this allows a module to keep track of processes -+ * in order that it can manage all tasks derived from a single process. -+ */ -+ -+#define PTRACK_PHASE_CLONE 1 -+#define PTRACK_PHASE_CLONE_FAIL 2 -+#define PTRACK_PHASE_EXEC 3 -+#define PTRACK_PHASE_EXIT 4 -+ -+typedef int (*ptrack_callback_t)(void *arg, int phase, struct task_struct *child); -+ -+#define PTRACK_FINISHED 0 -+#define PTRACK_INNHERIT 1 -+#define PTRACK_DENIED 2 -+ -+struct ptrack_desc { -+ struct list_head link; -+ ptrack_callback_t callback; -+ void *arg; -+}; -+ -+extern int ptrack_register (ptrack_callback_t callback, void *arg); -+extern void ptrack_deregister (ptrack_callback_t callback, void *arg); -+extern int ptrack_registered (ptrack_callback_t callback, void *arg); -+ -+extern int ptrack_call_callbacks (int phase, struct task_struct *child); -+ -+#endif /* __LINUX_PTRACK_H */ -Index: linux-2.4.21/include/linux/sched.h -=================================================================== ---- linux-2.4.21.orig/include/linux/sched.h 2005-06-01 22:52:05.000000000 -0400 -+++ linux-2.4.21/include/linux/sched.h 2005-06-01 23:12:54.749416304 -0400 -@@ -30,6 +30,8 @@ - #include - #include - -+#include -+ - struct exec_domain; - extern int exec_shield; - extern int exec_shield_randomize; -@@ -322,6 +324,9 @@ - #endif - /* Architecture-specific MM context */ - mm_context_t context; -+ -+ /* Support page table updates on adapter cards with on-board MMU */ -+ struct list_head *coproc_ops; - - /* coredumping support */ - int core_waiters; -@@ -342,6 +347,7 @@ - mmap_sem: __RWSEM_INITIALIZER(name.mmap_sem), \ - page_table_lock: SPIN_LOCK_UNLOCKED, \ - mmlist: LIST_HEAD_INIT(name.mmlist), \ -+ coproc_ops: NULL, \ - rlimit_rss: RLIM_INFINITY, \ - } - -@@ -572,6 +578,9 @@ - /* context-switch lock */ - spinlock_t switch_lock; - -+/* process tracking callbacks */ -+ struct list_head ptrack_list; -+ - /* journalling filesystem info */ - void *journal_info; - -@@ -740,6 +749,7 @@ - blocked: {{0}}, \ - alloc_lock: SPIN_LOCK_UNLOCKED, \ - switch_lock: SPIN_LOCK_UNLOCKED, \ -+ ptrack_list: LIST_HEAD_INIT(tsk.ptrack_list), \ - journal_info: NULL, \ - real_stack: &tsk, \ - } -Index: linux-2.4.21/include/qsnet/autoconf.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/autoconf.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/autoconf.h 2005-06-01 23:12:54.750416152 -0400 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (c) 2004 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ * NOTE: This file has been automatically generated: -+ * node : milano -+ * kernel : /src/linux/qsnet/linux-2.4.21 -+ * date : Wed May 4 18:24:23 EDT 2005 -+ * -+ */ -+ -+#include -+#undef NO_RMAP -+#define AC -+#undef NO_O1_SCHED -+#undef NO_NPTL -+#define NO_ABI -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -+#define PROCESS_ACCT -+#endif -+#undef RSS_ATOMIC -+#undef NO_COPROC -+#define NO_IOPROC -+#undef NO_PTRACK -+#define NO_PANIC_NOTIFIER -+#undef NO_SHM_CLEANUP -+#undef NO_PDE -+ -+ -+#define CONFIG_EIP -+#define CONFIG_ELAN -+#define CONFIG_ELAN3 -+#define CONFIG_ELAN4 -+#define CONFIG_EP -+#define CONFIG_JTAG -+#define CONFIG_QSNET -+#define CONFIG_RMS -Index: linux-2.4.21/include/qsnet/condvar.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/condvar.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/condvar.h 2005-06-01 23:12:54.750416152 -0400 -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2000 Regents of the University of California -+ * -+ * 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 -+ * -+ */ -+ -+#if !defined(_LINUX_CONDVAR_H) -+#define _LINUX_CONDVAR_H -+ -+#if defined(__KERNEL__) -+ -+#include -+#include -+ -+#define CV_RET_SIGPENDING 0 -+#define CV_RET_TIMEOUT (-1) -+#define CV_RET_NORMAL 1 -+ -+struct kcondvar_task { -+ struct task_struct *task; /* need to wrap task in this */ -+ struct list_head list; /* to thread as a list */ -+ int blocked; -+}; -+ -+typedef struct { -+ struct list_head task_list; /* list of kcondvar_task's */ -+} kcondvar_t; -+ -+#define kcondvar_wait(c,l,fl) debug_kcondvar_wait(c, l, fl, 0, TASK_UNINTERRUPTIBLE) -+#define kcondvar_waitsig(c,l,fl) debug_kcondvar_wait(c, l, fl, 0, TASK_INTERRUPTIBLE) -+#define kcondvar_timedwait(c,l,fl,to) debug_kcondvar_wait(c, l, fl, to, TASK_UNINTERRUPTIBLE) -+#define kcondvar_timedwaitsig(c,l,fl,to) debug_kcondvar_wait(c, l, fl, to, TASK_INTERRUPTIBLE) -+#define kcondvar_wakeupone(c,l) kcondvar_wakeup(c, l, 0) -+#define kcondvar_wakeupall(c,l) kcondvar_wakeup(c, l, 1) -+ -+extern __inline__ void -+kcondvar_init(kcondvar_t *c) -+{ -+ INIT_LIST_HEAD(&c->task_list); -+} -+ -+extern __inline__ void -+kcondvar_destroy(kcondvar_t *c) -+{ -+ ASSERT(list_empty(&c->task_list)); -+} -+ -+/* -+ * We thread a struct kcondvar_task, allocated on the stack, onto the kcondvar_t's -+ * task_list, and take it off again when we wake up. -+ */ -+extern __inline__ int -+debug_kcondvar_wait(kcondvar_t *c, spinlock_t *l, unsigned long *fl, long tmo, int state) -+{ -+ struct kcondvar_task cvt; -+ int ret = CV_RET_NORMAL; -+ -+ ASSERT(!in_interrupt()); /* we can block */ -+ ASSERT(SPINLOCK_HELD(l)); /* enter holding lock */ -+ -+ cvt.task = current; -+ cvt.blocked = 1; -+ list_add(&cvt.list, &c->task_list); -+ do { -+ /* Note: we avoid using TASK_UNINTERRUPTIBLE here because avenrun() -+ * (linux/kernel/timer.c:calc_load()) -+ * computation treats it like TASK_RUNNABLE hence creates false high -+ * load averages when we create kernel threads. -+ * The cvt.blocked flag distinguishes a signal wakeup from a kcondvar_wakeup. -+ * -+ * However, if we do take a signal we could end up busily spinning here, if -+ * we ignore it (state == TASK_UNINTERRUPTIBLE) so once we see a signal -+ * pending we do sleep TASK_UNINTERRUPTIBLE to stop a busy spin. -+ * I have now blocked all signals for kernel threads to prevent this -+ * happening but other users of kcondvar_wait may still hit this spin. -+ */ -+ set_current_state (signal_pending(current) ? state : TASK_INTERRUPTIBLE); -+ -+ if (fl) -+ spin_unlock_irqrestore(l, *fl); -+ else -+ spin_unlock(l); -+ if (tmo) { -+ if (tmo <= jiffies || !schedule_timeout(tmo - jiffies)) -+ ret = CV_RET_TIMEOUT; -+ } else -+ schedule(); -+ if (fl) -+ spin_lock_irqsave (l, *fl); -+ else -+ spin_lock(l); -+ -+ /* signal_pending - Only exit the loop if the user was waiting TASK_INTERRUPTIBLE */ -+ if ((state == TASK_INTERRUPTIBLE) && signal_pending(current)) -+ ret = CV_RET_SIGPENDING; -+ -+ } while (cvt.blocked && ret == CV_RET_NORMAL); -+ list_del(&cvt.list); -+ -+ /* Reset task state in case we didn't sleep above */ -+ set_current_state (TASK_RUNNING); -+ -+ return ret; /* return holding lock */ -+} -+ -+extern __inline__ void -+kcondvar_wakeup(kcondvar_t *c, spinlock_t *l, int wakeall) -+{ -+ struct list_head *lp; -+ struct kcondvar_task *cvtp; -+ -+ ASSERT(SPINLOCK_HELD(l)); /* already holding lock */ -+ for (lp = c->task_list.next; lp != &c->task_list; lp = lp->next) { -+ cvtp = list_entry(lp, struct kcondvar_task, list); -+ if (cvtp->blocked) { -+ cvtp->blocked = 0; -+ /* wake_up_process added to kernel/ksyms.c */ -+ wake_up_process(cvtp->task); -+ if (!wakeall) -+ break; -+ } -+ } -+} /* return still holding lock */ -+ -+ -+#endif /* __KERNEL__ */ -+#endif /* _LINUX_CONDVAR_H */ -Index: linux-2.4.21/include/qsnet/config.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/config.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/config.h 2005-06-01 23:12:54.751416000 -0400 -@@ -0,0 +1,195 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _QSNET_CONFIG_H -+#define _QSNET_CONFIG_H -+ -+#ident "$Id: config.h,v 1.23 2003/07/24 21:31:19 robin Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/config.h,v $*/ -+ -+ -+/* -+ * QSNET standard defines : -+ * -+ * Target operating system defines -+ * SOLARIS -+ * TRU64UNIX/DIGITAL_UNIX -+ * LINUX -+ * -+ * Target processor defines -+ * SPARC -+ * ALPHA -+ * I386 -+ * IA64 -+ * X86_64 -+ * -+ * Byte order defines -+ * __LITTLE_ENDIAN__ -+ * __BIG_ENDIAN__ -+ * -+ * Data size defines -+ * _LP64 - LP64 - long/pointer is 64 bits -+ * _ILP32 - LP32 - long/pointer is 32 bits -+ * -+ * Elan defines for main processor -+ * __MAIN_LITTLE_ENDIAN__ - main byte order (for thread code) -+ * __MAIN_BIG_ENDIAN__ -+ * _MAIN_LP64 - main long size (for thread code) -+ * _MAIN_ILP32 -+ * -+ * Compiling for kernel (defined in makefile) -+ * _KERNEL -+ * -+ */ -+ -+#if defined(__LP64__) && !defined(_LP64) -+# define _LP64 -+#endif -+ -+#if defined(__arch64__) && !defined(_LP64) && !defined(_ILP32) -+# define _LP64 -+#endif -+ -+#if defined(__alpha__) && !defined(_LP64) && !defined(_ILP32) -+# define _LP64 -+#endif -+ -+#if !defined(__arch64__) && !defined(_ILP32) && !defined(_LP64) -+# define _ILP32 -+#endif -+ -+#if defined(__ELAN__) || defined(__ELAN3__) -+ -+#define __LITTLE_ENDIAN__ -+ -+#if defined(__host_solaris) && defined(__host_sparc) -+#define SOLARIS -+#define SPARC -+#define SOLARIS_SPARC -+#define _MAIN_ILP32 -+#define __MAIN_BIG_ENDIAN__ -+ -+#elif defined(__host_osf) -+#define TRU64UNIX -+#define DIGITAL_UNIX -+#define ALPHA -+#define _MAIN_LP64 -+#define __MAIN_LITTLE_ENDIAN__ -+ -+#elif defined(__host_linux) && defined(__host_alpha) -+#define LINUX -+#define ALPHA -+#define LINUX_ALPHA -+#define _MAIN_LP64 -+#define __MAIN_LITTLE_ENDIAN__ -+ -+#elif defined(__host_linux) && defined(__host_sparc) -+#define LINUX -+#define SPARC -+#define LINUX_SPARC -+#define __MAIN_BIG_ENDIAN__ -+#ifdef __KERNEL__ -+# define _MAIN_LP64 -+#else -+# define _MAIN_ILP32 -+#endif -+ -+#elif defined(__host_linux) && defined(__host_i386) -+#define LINUX -+#define I386 -+#define LINUX_I386 -+#define _MAIN_ILP32 -+#define __MAIN_LITTLE_ENDIAN__ -+ -+#elif defined(__host_linux) && defined(__host_ia64) -+#define LINUX -+#define IA64 -+#define LINUX_IA64 -+#define _MAIN_LP64 -+#define __MAIN_LITTLE_ENDIAN__ -+ -+#elif defined(__host_linux) && defined(__host_x86_64) -+#define LINUX -+#define X86_64 -+#define LINUX_X86_64 -+#define _MAIN_LP64 -+#define __MAIN_LITTLE_ENDIAN__ -+ -+#else -+#error Cannot determine operating system/processor architecture. -+#endif -+ -+#else /* !defined(__ELAN3__) */ -+ -+#if (defined(sun) || defined(__sun)) && defined(sparc) && !defined(__sparcv9) /* Sun Solaris 5.6 */ -+#define SOLARIS -+#define SPARC -+#define SOLARIS_SPARC -+#ifndef __BIG_ENDIAN__ -+#define __BIG_ENDIAN__ -+#endif -+ -+#elif (defined(sun) || defined(__sun)) && defined(sparc) && defined(__sparcv9) /* Sun Solaris 5.7 */ -+#define SOLARIS -+#define SPARC -+#define SOLARIS_SPARC -+#define __BIG_ENDIAN__ -+ -+#elif defined(__osf__) && defined(__alpha) /* Digital Unix */ -+#define TRU64UNIX -+#define DIGITAL_UNIX -+#define ALPHA -+#define __LITTLE_ENDIAN__ -+ -+#elif (defined(linux) || defined(__linux__)) && defined(__alpha) /* Linux Alpha */ -+ -+#define LINUX -+#define ALPHA -+#define LINUX_ALPHA -+#define __LITTLE_ENDIAN__ -+ -+#elif (defined(linux) || defined(__linux__)) && defined(__sparc) /* Linux Sparc */ -+ -+#define LINUX -+#define SPARC -+#define LINUX_SPARC -+#define __BIG_ENDIAN__ -+ -+#elif (defined(linux) || defined(__linux__)) && defined(__i386) /* Linux i386 */ -+ -+#define LINUX -+#define I386 -+#define LINUX_I386 -+#define __LITTLE_ENDIAN__ -+ -+#elif (defined(linux) || defined(__linux__)) && defined(__ia64) /* Linux ia64 */ -+ -+#define LINUX -+#define IA64 -+#define LINUX_IA64 -+#define __LITTLE_ENDIAN__ -+ -+#elif (defined(linux) || defined(__linux__)) && defined(__x86_64) /* Linux x86_64 */ -+ -+#define LINUX -+#define X86_64 -+#define LINUX_X86_64 -+#define __LITTLE_ENDIAN__ -+ -+#elif defined(__QNXNTO__) -+#define QNX -+#define I386 -+#define __LITTLE_ENDIAN__ -+#else -+#error Cannot determine operating system/processor architecture. -+#endif -+ -+#endif -+ -+#include -+ -+#endif /* _QSNET_CONFIG_H */ -Index: linux-2.4.21/include/qsnet/crwlock.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/crwlock.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/crwlock.h 2005-06-01 23:12:54.751416000 -0400 -@@ -0,0 +1,207 @@ -+/* -+ * Copyright (C) 2000 Regents of the University of California -+ * -+ * 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 -+ * -+ */ -+ -+/* -+ * Complex - Reader/Writer locks -+ * Ref: "UNIX Systems for Modern Architectures", by Curt Schimmel, -+ * sec 11.6.3. -+ * -+ * This implementation is based on semaphores and may not be called from -+ * interrupt handlers. -+ * -+ */ -+ -+#if !defined(_LINUX_RWLOCK_H) -+#define _LINUX_RWLOCK_H -+ -+#if defined(__KERNEL__) -+ -+typedef enum { RD, WRT, ANY } crwlock_type_t; -+ -+#define crwlock_write_held(l) debug_crwlock_held(l, WRT, __BASE_FILE__,__LINE__) -+#define crwlock_read_held(l) debug_crwlock_held(l, RD, __BASE_FILE__, __LINE__) -+#define crwlock_held(l) debug_crwlock_held(l, ANY, __BASE_FILE__, __LINE__) -+ -+#define crwlock_read(l) debug_crwlock_read(l, __BASE_FILE__, __LINE__) -+#define crwlock_write(l) debug_crwlock_write(l, __BASE_FILE__, __LINE__) -+#define crwlock_done(l) debug_crwlock_done(l, __BASE_FILE__, __LINE__) -+ -+#if defined(DEBUG_RWLOCK) && defined(__alpha__) && !defined(DEBUG_SPINLOCK) -+#define DEBUG_SPINLOCK -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#if !defined(DEBUG_SPINLOCK) -+#define debug_spin_lock(lock, file, line) spin_lock(lock) -+#endif -+ -+typedef struct { -+ spinlock_t m_lock; /* protects cnt fields below */ -+ int m_rdcnt; /* # of rdrs in crit section */ -+ int m_wrcnt; /* # of wrtrs in crit section */ -+ int m_rdwcnt; /* # of waiting readers */ -+ int m_wrwcnt; /* # of waiting writers */ -+ struct semaphore m_rdwait; /* sema where readers wait */ -+ struct semaphore m_wrwait; /* sema where writers wait */ -+ pid_t m_wrholder; /* task holding write lock */ -+} crwlock_t; -+ -+extern __inline__ void -+crwlock_init(crwlock_t *l) -+{ -+ l->m_lock = SPIN_LOCK_UNLOCKED; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -+ l->m_rdwait = MUTEX_LOCKED; -+ l->m_wrwait = MUTEX_LOCKED; -+#else -+ sema_init(&l->m_rdwait,0); -+ sema_init(&l->m_wrwait,0); -+#endif -+ l->m_rdcnt = l->m_wrcnt = l->m_rdwcnt = l->m_wrwcnt = 0; -+ l->m_wrholder = PID_NONE; -+} -+ -+extern __inline__ void -+crwlock_destroy(crwlock_t *l) -+{ -+ ASSERT(l->m_rdcnt == 0 && l->m_wrcnt == 0); -+} -+ -+/* -+ * If a writer has the lock presently or there are writers waiting, -+ * then we have to wait. -+ */ -+extern __inline__ void -+debug_crwlock_read(crwlock_t *l, char *file, int line) -+{ -+ ASSERT(!in_interrupt()); -+ spin_lock(&l->m_lock); -+ if (l->m_wrcnt || l->m_wrwcnt) { -+ l->m_rdwcnt++; -+ spin_unlock(&l->m_lock); -+ down(&l->m_rdwait); /* P */ -+ } else { -+ l->m_rdcnt++; -+ spin_unlock(&l->m_lock); -+ } -+} -+ -+/* -+ * If we're the last reader, and a writer is waiting, -+ * then let the writer go now. -+ */ -+/* private */ -+extern __inline__ void -+debug_crwlock_read_done(crwlock_t *l, char *file, int line) -+{ -+ spin_lock(&l->m_lock); -+ l->m_rdcnt--; -+ if (l->m_wrwcnt && l->m_rdcnt == 0) { -+ l->m_wrcnt = 1; -+ l->m_wrwcnt--; -+ spin_unlock(&l->m_lock); -+ up(&l->m_wrwait); /* V */ -+ return; -+ } -+ spin_unlock(&l->m_lock); -+} -+ -+extern __inline__ void -+debug_crwlock_write(crwlock_t *l, char *file, int line) -+{ -+ ASSERT(!in_interrupt()); -+ spin_lock(&l->m_lock); -+ if (l->m_wrcnt || l->m_rdcnt) { /* block if lock is in use */ -+ l->m_wrwcnt++; -+ spin_unlock(&l->m_lock); -+ down(&l->m_wrwait); /* P */ -+ } else { /* lock is not in use */ -+ l->m_wrcnt = 1; -+ spin_unlock(&l->m_lock); -+ } -+ l->m_wrholder = current->pid; -+} -+ -+/* private */ -+extern __inline__ void -+debug_crwlock_write_done(crwlock_t *l, char *file, int line) -+{ -+ int rdrs; -+ -+ spin_lock(&l->m_lock); -+ l->m_wrholder = PID_NONE; -+ if (l->m_rdwcnt) { /* let any readers go first */ -+ l->m_wrcnt = 0; -+ rdrs = l->m_rdwcnt; -+ l->m_rdcnt = rdrs; -+ l->m_rdwcnt = 0; -+ spin_unlock(&l->m_lock); -+ while (rdrs--) -+ up(&l->m_rdwait); /* V */ -+ } else if (l->m_wrwcnt) { /* or let any writer go */ -+ l->m_wrwcnt--; -+ spin_unlock(&l->m_lock); -+ up(&l->m_wrwait); /* V */ -+ } else { /* nobody waiting, unlock */ -+ l->m_wrcnt = 0; -+ spin_unlock(&l->m_lock); -+ } -+} -+ -+extern __inline__ void -+debug_crwlock_done(crwlock_t *l, char *file, int line) -+{ -+ if (l->m_wrholder == current->pid) -+ debug_crwlock_write_done(l, file, line); -+ else -+ debug_crwlock_read_done(l, file, line); -+} -+ -+/* -+ * Return nonzero if lock is held -+ */ -+extern __inline__ int -+debug_crwlock_held(crwlock_t *l, crwlock_type_t t, char *file, int line) -+{ -+ int res; -+ -+ spin_lock(&l->m_lock); -+ switch(t) { -+ case RD: -+ res = l->m_rdcnt; -+ break; -+ case WRT: -+ res = l->m_wrcnt; -+ break; -+ case ANY: -+ res = l->m_wrcnt + l->m_rdcnt; -+ break; -+ } -+ spin_unlock(&l->m_lock); -+ -+ return res; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* _LINUX_RWLOCK_H */ -Index: linux-2.4.21/include/qsnet/ctrl_linux.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/ctrl_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/ctrl_linux.h 2005-06-01 23:12:54.751416000 -0400 -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_CTRL_LINUX_H -+#define __QSNET_CTRL_LINUX_H -+ -+#ident "$Id: ctrl_linux.h,v 1.3 2003/03/26 09:32:03 mike Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/ctrl_linux.h,v $*/ -+ -+#define QSNETIO_USER_BASE 0x40 -+ -+#define QSNETIO_DEBUG_DUMP _IO ('e', QSNETIO_USER_BASE + 0) -+ -+typedef struct qsnetio_debug_buffer_struct -+{ -+ caddr_t addr; -+ size_t len; -+} QSNETIO_DEBUG_BUFFER_STRUCT; -+#define QSNETIO_DEBUG_BUFFER _IOWR ('e', QSNETIO_USER_BASE + 1, QSNETIO_DEBUG_BUFFER_STRUCT) -+ -+typedef struct qsnetio_debug_kmem_struct -+{ -+ void *handle; -+} QSNETIO_DEBUG_KMEM_STRUCT; -+#define QSNETIO_DEBUG_KMEM _IOWR ('e', QSNETIO_USER_BASE + 2, QSNETIO_DEBUG_KMEM_STRUCT) -+ -+#endif /* __QSNET_CTRL_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/debug.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/debug.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/debug.h 2005-06-01 23:12:54.752415848 -0400 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2000 Regents of the University of California -+ * -+ * 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 _QSNET_DEBUG_H -+#define _QSNET_DEBUG_H -+ -+#if defined(DIGITAL_UNIX) -+#include -+#elif defined(LINUX) -+extern int qsnet_assfail (char *ex, const char *func, char *file, int line); -+ -+#define ASSERT(EX) do { \ -+ if (!(EX) && qsnet_assfail (#EX, __FUNCTION__, __BASE_FILE__, __LINE__)) { \ -+ BUG(); \ -+ } \ -+} while (0) -+#endif /* DIGITAL_UNIX */ -+ -+/* debug.c */ -+extern void qsnet_debug_init(void); -+extern void qsnet_debug_fini(void); -+extern void qsnet_debug_disable(int); -+extern void qsnet_debug_alloc(void); -+ -+#define QSNET_DEBUG_BUFFER ((unsigned int)(0x01)) -+#define QSNET_DEBUG_CONSOLE ((unsigned int)(0x02)) -+#define QSNET_DEBUG_BUF_CON ( QSNET_DEBUG_BUFFER | QSNET_DEBUG_CONSOLE ) -+ -+#ifdef __GNUC__ -+extern void qsnet_debugf (unsigned int mode, char *fmt, ...) -+ __attribute__ ((format (printf,2,3))); -+extern void kqsnet_debugf (char *fmt, ...) -+ __attribute__ ((format (printf,1,2))); -+#else -+extern void qsnet_debugf (unsigned int mode, char *fmt, ...); -+extern void kqsnet_debugf (char *fmt, ...); -+#endif -+extern void qsnet_vdebugf (unsigned int mode, char * prefix, char *fmt, va_list ap); -+extern int qsnet_debug_buffer(caddr_t ubuffer, int len); -+extern int qsnet_debug_dump (void); -+extern int qsnet_debug_kmem (void *handle); -+ -+extern void qsnet_debug_buffer_on(void); -+extern void qsnet_debug_buffer_clear(void); -+extern void qsnet_debug_buffer_mark(char *str); -+ -+#endif /* _QSNET_DEBUG_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/fence.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/fence.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/fence.h 2005-06-01 23:12:54.752415848 -0400 -@@ -0,0 +1,178 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* $Id: fence.h,v 1.21.6.4 2004/11/23 14:34:45 addy Exp $ */ -+/* $Source: /cvs/master/quadrics/qsnet/fence.h,v $*/ -+ -+#ifndef _CONFIG_FENCE_H -+#define _CONFIG_FENCE_H -+ -+#ident "$Id: fence.h,v 1.21.6.4 2004/11/23 14:34:45 addy Exp $" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#if defined(__ELAN__) || defined(__ELAN3__) -+ -+/* no memory barriers required on elan3/elan4 */ -+ -+#elif defined QSNET_MEMBARS_ASSERT -+ -+#include -+#define MEMBAR_MEMISSUE() assert(0); -+#define MEMBAR_SYNC() assert(0); -+#define MEMBAR_STORELOAD() assert(0); -+#define MEMBAR_LOADSTORE() assert(0); -+#define MEMBAR_STORESTORE() assert(0); -+#define MEMBAR_LOADLOAD() assert(0); -+#define MEMBAR_VISIBLE() assert(0); -+#define MEMBAR_DRAIN() assert(0); -+ -+#elif defined(__alpha) -+ -+/* Memory barrier instructions */ -+#if defined(__DECC) || defined(__DECXX) -+long asm( const char *,...); -+#pragma intrinsic( asm ) -+#define MEMBAR_MEMISSUE() asm("mb") -+#define MEMBAR_SYNC() asm("mb") -+#define MEMBAR_STORELOAD() asm("wmb") -+#define MEMBAR_LOADSTORE() asm("mb") -+#define MEMBAR_STORESTORE() asm("wmb") -+#define MEMBAR_LOADLOAD() asm("mb") -+#define MEMBAR_VISIBLE() asm("") -+#define MEMBAR_DRAIN() asm("wmb") -+ -+#else -+/* Assume gcc */ -+#define MEMBAR_MEMISSUE() asm volatile ("mb"::) -+#define MEMBAR_SYNC() asm volatile ("mb"::) -+#define MEMBAR_STORELOAD() asm volatile ("wmb"::) -+#define MEMBAR_LOADSTORE() asm volatile ("mb"::) -+#define MEMBAR_STORESTORE() asm volatile ("wmb"::) -+#define MEMBAR_LOADLOAD() asm volatile ("mb"::) -+#define MEMBAR_VISIBLE() asm volatile ("" ::: "memory") -+#define MEMBAR_DRAIN() asm volatile ("wmb"::: "memory") -+ -+#endif /* __DECC */ -+ -+#elif defined(__sparc) -+ -+/* UltraSPARC with WRITE MERGING enabled */ -+#define MEMBAR_MEMISSUE() asm volatile ("membar #MemIssue"); -+#define MEMBAR_SYNC() asm volatile ("membar #Sync"); -+#define MEMBAR_STORELOAD() asm volatile ("membar #StoreLoad"); -+#define MEMBAR_LOADSTORE() asm volatile ("membar #LoadStore"); -+#define MEMBAR_STORESTORE() asm volatile ("membar #StoreStore"); -+#define MEMBAR_LOADLOAD() asm volatile ("membar #LoadLoad"); -+#define MEMBAR_VISIBLE() asm volatile (""::: "memory") -+#define MEMBAR_DRAIN() asm volatile (""::: "memory") -+ -+#elif defined(__linux__) -+ -+#if defined(__INTEL_COMPILER) -+ -+/* NB: Intel compiler version 8.0 now also defines __GNUC__ unless you set the -no-gcc cmdline option -+ * I've moved the check for __INTEL_COMPILER to be first to get around this -+ */ -+#ifdef __ECC -+ -+#include -+ -+#define MEMBAR_MEMISSUE() __mf() -+#define MEMBAR_SYNC() __mf() -+#define MEMBAR_STORELOAD() __mf() -+#define MEMBAR_LOADSTORE() __mf() -+#define MEMBAR_STORESTORE() __mf() -+#define MEMBAR_LOADLOAD() __mf() -+#define MEMBAR_VISIBLE() __mf() -+#define MEMBAR_DRAIN() __mf() -+ -+#else -+ -+#warning Membars not implemented with this compiler. -+#define MEMBAR_MEMISSUE() ; -+#define MEMBAR_SYNC() ; -+#define MEMBAR_STORELOAD() ; -+#define MEMBAR_LOADSTORE() ; -+#define MEMBAR_STORESTORE() ; -+#define MEMBAR_LOADLOAD() ; -+#define MEMBAR_VISIBLE() ; -+#define MEMBAR_DRAIN() ; -+ -+#endif /* __ECC */ -+ -+#elif defined(__GNUC__) -+ -+#ifndef __ia64 -+ -+/* These are needed by on AMD64 */ -+#include -+#include -+ -+#ifndef __cplusplus -+/* this header file has a parameter called "new" - great huh */ -+#include -+#endif -+ -+#else -+# define mb() __asm__ __volatile__ ("mf" ::: "memory") -+# define rmb() mb() -+# define wmb() mb() -+#endif /* !__ia64 */ -+ -+#if defined(__x86_64) || defined(__i386) -+/* For some reason the AMD64 definition (glibc-devel 2.3.X) of this -+ * is not useful (compiler only directive) so we overload it here -+ */ -+/* I don't trust the IA32 header files either as with mtrr enabled -+ * we really need a membar and not a compiler directive -+ * NB: sfence is only available with X86_FEATURE_XMM CPUs -+ */ -+#undef wmb -+#define wmb() asm volatile("sfence":::"memory"); -+#endif /* __x86_64 */ -+ -+#define MEMBAR_MEMISSUE() mb() -+#define MEMBAR_SYNC() mb() -+#define MEMBAR_STORELOAD() wmb() -+#define MEMBAR_LOADSTORE() mb() -+#define MEMBAR_STORESTORE() wmb() -+#define MEMBAR_LOADLOAD() mb() -+ -+#ifdef __ia64 -+#define MEMBAR_VISIBLE() asm volatile ("mf.a;;mf;;"::: "memory") -+#define MEMBAR_DRAIN() asm volatile ("mf;"::: "memory") -+#else -+#define MEMBAR_VISIBLE() asm volatile (""::: "memory") -+#define MEMBAR_DRAIN() wmb() -+#endif -+ -+#else /* elif __GNUC__ */ -+ -+#error Membars not implemented for this architecture/compiler. -+ -+#endif /* __INTEL_COMPILER */ -+ -+#else /* elif __linux__ */ -+ -+#error Membars not implemented for this architecture/compiler. -+ -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _CONFIG_FENCE_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/kernel.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/kernel.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/kernel.h 2005-06-01 23:12:54.752415848 -0400 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_KERNEL_H -+#define __QSNET_KERNEL_H -+ -+#ident "$Id: kernel.h,v 1.8 2003/03/14 10:18:22 mike Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/kernel.h,v $*/ -+ -+#include -+#include -+ -+#if defined(SOLARIS) -+#include -+#endif -+ -+#if defined(DIGITAL_UNIX) -+#include -+#endif -+ -+#if defined(LINUX) -+#include -+#endif -+ -+#include -+ -+#endif /* __QSNET_KERNEL_H */ -+ -+ -+ -+ -+ -+ -+ -Index: linux-2.4.21/include/qsnet/kernel_linux.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/kernel_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/kernel_linux.h 2005-06-01 23:12:54.753415696 -0400 -@@ -0,0 +1,354 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_KERNEL_LINUX_H -+#define __QSNET_KERNEL_LINUX_H -+ -+#ident "$Id: kernel_linux.h,v 1.62.6.5 2005/01/18 14:37:22 david Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/kernel_linux.h,v $*/ -+ -+#if defined(MODVERSIONS) -+#include -+#endif -+ -+#include -+#include -+ -+ -+/* ASSERT(spin_is_locked(l)) would always fail on UP kernels */ -+#if defined(CONFIG_SMP) -+#define SPINLOCK_HELD(l) spin_is_locked(l) -+#else -+#define SPINLOCK_HELD(l) (1) -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include /* Quadrics added */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#if defined(LINUX_ALPHA) -+# include /* for TSUNAMI_MEM */ -+#endif -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) -+# undef MOD_INC_USE_COUNT -+# undef MOD_DEC_USE_COUNT -+# define MOD_INC_USE_COUNT -+# define MOD_DEC_USE_COUNT -+#endif -+ -+#define MIN(a,b) ((a) > (b) ? (b) : (a)) -+#define MAX(a,b) ((a) > (b) ? (a) : (b)) -+ -+/* stray types */ -+typedef u64 u_longlong_t; -+typedef unsigned long uintptr_t; -+typedef int bool_t; -+ -+typedef unsigned long virtaddr_t; /* virtual address */ -+typedef unsigned long ioaddr_t; /* io address */ -+typedef unsigned long sdramaddr_t; /* elan sdram offset */ -+ -+/* 386 kernel can be compiled with PAE enabled to use a 44 bit physical address */ -+#if defined(CONFIG_X86_PAE) -+typedef unsigned long long physaddr_t; -+#else -+typedef unsigned long physaddr_t; -+#endif -+ -+/* ticks since reboot, and tick freq */ -+#define lbolt jiffies -+#define hz HZ -+ -+/* System page size and friends */ -+#define PAGESIZE PAGE_SIZE -+#define PAGESHIFT PAGE_SHIFT -+#define PAGEOFFSET (PAGE_SIZE - 1) -+#define PAGEMASK PAGE_MASK -+ -+#define PAGE_ALIGNED(a) (((a) & PAGE_MASK) == a) -+ -+/* convert between bytes and pages */ -+#define btop(b) ((unsigned long)(b) >> PAGE_SHIFT) /* rnd down */ -+#define btopr(b) btop(PAGE_ALIGN((unsigned long) b)) /* rnd up */ -+#define ptob(p) ((unsigned long)(p) << PAGE_SHIFT) -+ -+/* round up sz to the nearest multiple of blk */ -+#define roundup(sz,blk) ((blk) * ((sz) / (blk) + ((sz) % (blk) ? 1 : 0))) -+ -+/* send a signal to a process */ -+#define psignal(pr,sig) send_sig(sig,pr,0) -+ -+/* microsecond delay */ -+#define DELAY(us) udelay(us) -+ -+/* macro macros */ -+#define MACRO_BEGIN do { -+#define MACRO_END } while (0) -+ -+/* D-Unix compatable errno values */ -+#define ESUCCESS 0 -+#define EFAIL 255 -+ -+/* ASSERT(NO_LOCKS_HELD) will be a no-op */ -+#define NO_LOCKS_HELD 1 -+ -+/* misc */ -+typedef int label_t; -+#define on_fault(ljp) ((ljp) == NULL) -+#define _NOTE(X) -+#define no_fault() ((void) 0) -+#define panicstr 0 -+ -+/* return from system call is -EXXX on linux */ -+#define set_errno(e) (-(e)) -+ -+/* -+ * BSD-style byte ops -+ */ -+ -+#define bcmp(src1,src2,len) memcmp(src1,src2,len) -+#define bzero(dst,len) memset(dst,0,len) -+#define bcopy(src,dst,len) memcpy(dst,src,len) -+ -+#define preemptable_start do { long must_yield_at = lbolt + (hz/10); -+#define preemptable_end } while (0) -+#define preemptable_check() do {\ -+ if ((lbolt - must_yield_at) > 0)\ -+ {\ -+ preemptable_yield() ; \ -+ must_yield_at = lbolt + (hz/10);\ -+ }\ -+ } while (0) -+ -+#define preemptable_yield() schedule() -+ -+#define CURPROC() current -+#define CURTHREAD() current -+#define SUSER() suser() -+ -+/* 64 bit IO operations on 32 bit intel cpus using MMX */ -+#if defined(LINUX_I386) -+extern u64 qsnet_readq (volatile u64 *ptr); -+extern void qsnet_writeq (u64 value, volatile u64 *ptr); -+ -+#define readq(ptr) qsnet_readq((void *) ptr) -+#define writeq(val,ptr) qsnet_writeq(val, (void *)ptr) -+#endif -+ -+/* -+ * Memory barriers -+ */ -+#ifndef mmiob -+# define mmiob() mb() -+#endif -+ -+/* -+ * Exit handlers -+ */ -+#define HANDLER_REGISTER(func,arg,flags) xa_handler_register(func,arg,flags) -+#define HANDLER_UNREGISTER(func,arg,flags) xa_handler_unregister(func,arg,flags) -+ -+/* -+ * KMEM_GETPAGES and KMEM_ALLOC both call kmem_alloc, which -+ * translates the call to kmalloc if < PAGE_SIZE, or vmalloc -+ * if >= PAGE_SIZE. vmalloc will always return a page-aligned -+ * region rounded up to the nearest page, while kmalloc will -+ * return bits and pieces of a page. -+ */ -+ -+#ifdef KMEM_DEBUG -+extern void *qsnet_kmem_alloc_debug(int len, int sleep, int zerofill, char *file, int line); -+extern void qsnet_kmem_free_debug(void *ptr, int len, char *file, int line); -+#define KMEM_ALLOC(ptr,type,len,sleep) \ -+ { KMEM_ASSERT(sleep); (ptr)=(type)qsnet_kmem_alloc_debug(len,sleep,0,__FILE__,__LINE__); } -+#define KMEM_ZALLOC(ptr,type,len,sleep) \ -+ { KMEM_ASSERT(sleep); (ptr)=(type)qsnet_kmem_alloc_debug(len,sleep,1,__FILE__,__LINE__); } -+ -+#define KMEM_FREE(ptr,len) qsnet_kmem_free_debug((void *)ptr,len,__FILE__,__LINE__) -+ -+#else -+ -+extern void *qsnet_kmem_alloc(int len, int sleep, int zerofill); -+extern void qsnet_kmem_free(void *ptr, int len); -+ -+#define KMEM_ALLOC(ptr,type,len,sleep) \ -+ { KMEM_ASSERT(sleep); (ptr)=(type)qsnet_kmem_alloc(len,sleep,0); } -+#define KMEM_ZALLOC(ptr,type,len,sleep) \ -+ { KMEM_ASSERT(sleep); (ptr)=(type)qsnet_kmem_alloc(len,sleep,1); } -+ -+#define KMEM_FREE(ptr,len) qsnet_kmem_free((void *)ptr,len) -+ -+#endif -+extern void qsnet_kmem_display(void *handle); -+extern physaddr_t kmem_to_phys(void *ptr); -+ -+#define KMEM_ASSERT(sleep) ASSERT(!(in_interrupt() && sleep)) -+ -+ -+#define KMEM_GETPAGES(ptr,type,pgs,sleep) KMEM_ZALLOC(ptr,type,ptob(pgs),sleep) -+#define KMEM_FREEPAGES(ptr,pgs) KMEM_FREE(ptr,ptob(pgs)); -+ -+/* -+ * Copying from user space -> kernel space (perms checked) -+ */ -+#define copyin(up,kp,size) copy_from_user(kp,up,size) -+#define copyin_noerr(up,kp,size) copy_from_user(kp,up,size) -+ -+/* get_user() gets xfer width right */ -+#define fulinux(ret, up) (get_user(ret, (up)) == 0 ? ret : -1) -+#define fulinuxp(ret, up) (get_user(ret, (up)) == 0 ? ret : NULL) -+ -+extern __inline__ int fubyte (u8 *up) { u8 ret; return fulinux(ret, up);} -+extern __inline__ int fusword (u16 *up) { u16 ret; return fulinux(ret, up);} -+extern __inline__ int fuword (u32 *up) { u32 ret; return fulinux(ret, up);} -+#if BITS_PER_LONG > 32 -+extern __inline__ u64 fulonglong(u64 *up) { u64 ret; return fulinux(ret, up);} -+#else -+extern __inline__ u64 fulonglong(u64 *up) { return ((u64) fuword((u32 *)up) | (((u64) fuword(((u32 *)up)+1))<<32)); } -+#endif -+extern __inline__ void *fuptr (void **up) { void *ret; return fulinuxp(ret,up);} -+ -+#define fubyte_noerr(up) fubyte(up) -+#define fusword_noerr(up) fusword(up) -+#define fuword_noerr(up) fuword(up) -+#define fulonglong_noerr(up) fulonglong(up) -+#define fuptr_noerr(up) fuptr(up) -+ -+extern __inline__ int copyinstr(char *up, char *kp, int max, int *size) -+{ -+ for (*size = 1; *size <= max; (*size)++) { -+ if (get_user(*kp, up++) != 0) -+ return EFAULT; /* bad user space addr */ -+ if (*kp++ == '\0') -+ return 0; /* success */ -+ } -+ *size = max; -+ return ENAMETOOLONG; /* runaway string */ -+} -+ -+/* -+ * Copying from kernel space -> user space (perms checked) -+ */ -+ -+#define copyout(kp,up,size) copy_to_user(up,kp,size) -+#define copyout_noerr(kp,up,size) copy_to_user(up,kp,size) -+ -+/* put_user() gets xfer width right */ -+#define sulinux(val, up) (put_user(val, (up)) == 0 ? 0 : -1) -+ -+extern __inline__ int subyte (u8 *up, u8 val) { return sulinux(val, up); } -+extern __inline__ int susword (u16 *up, u16 val) { return sulinux(val, up); } -+extern __inline__ int suword (u32 *up, u32 val) { return sulinux(val, up); } -+#if BITS_PER_LONG > 32 -+extern __inline__ int sulonglong(u64 *up, u64 val) { return sulinux(val, up); } -+#else -+extern __inline__ int sulonglong(u64 *up, u64 val) { return (suword((u32 *) up, (u32) val) == 0 ? -+ suword(((u32 *) up)+1, (u32) (val >> 32)) : -1); } -+#endif -+extern __inline__ int suptr (void **up,void *val){ return sulinux(val, up); } -+ -+#define subyte_noerr(up,val) subyte(up,val) -+#define susword_noerr(up,val) susword(up,val) -+#define suword_noerr(up,val) suword(up,val) -+#define sulonglong_noerr(up,val) sulonglong(up,val) -+#define suptr_noerr(up,val) suptr(up,val) -+ -+/* -+ * /proc/qsnet interface -+ */ -+extern inline int -+str_append(char *buf, char *add, int size) -+{ -+#define TRUNC_MSG "[Output truncated]\n" -+ int full = 0; -+ int max = size - strlen(TRUNC_MSG) - strlen(add) - 1; -+ -+ if (strlen(buf) > max) { -+ strcat(buf, TRUNC_MSG); -+ full = 1; -+ } else -+ strcat(buf, add); -+ return full; -+} -+ -+/* Spinlocks */ -+#define spin_lock_destroy(l) ((void) 0) -+ -+/* Complex - Reader/Writer locks - we added */ -+typedef crwlock_t krwlock_t; -+#define krwlock_init(l) crwlock_init(l) -+#define krwlock_destroy(l) crwlock_destroy(l) -+#define krwlock_write(l) crwlock_write(l) -+#define krwlock_read(l) crwlock_read(l) -+#define krwlock_done(l) crwlock_done(l) -+#define krwlock_is_locked(l) crwlock_held(l) -+#define krwlock_is_write_locked(l) crwlock_write_held(l) -+#define krwlock_is_read_locked(l) crwlock_read_held(l) -+ -+/* -+ * Timeouts - Solaris style. -+ */ -+typedef struct timer_list timer_fn_t; -+ -+extern inline void -+schedule_timer_fn(timer_fn_t *timer, void (*fun)(void *), void *arg, long hz_delay) -+{ -+ init_timer(timer); -+ -+ timer->function = (void (*)(unsigned long)) fun; -+ timer->data = (unsigned long) arg; -+ timer->expires = jiffies + hz_delay; -+ -+ add_timer(timer); -+} -+ -+/* returns 1 if timer_fn was cancelled */ -+extern inline int -+cancel_timer_fn(timer_fn_t *timer) -+{ -+ return (del_timer_sync(timer)); -+} -+ -+extern inline int -+timer_fn_queued(timer_fn_t *timer) -+{ -+ return (timer_pending (timer)); -+} -+/* -+ * Hold/release CPU's. -+ */ -+ -+extern void cpu_hold_all(void); -+extern void cpu_release_all(void); -+#define CAPTURE_CPUS() cpu_hold_all() -+#define RELEASE_CPUS() cpu_release_all() -+ -+#define IASSERT ASSERT -+ -+#endif /* __QSNET_KERNEL_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/kpte.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/kpte.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/kpte.h 2005-06-01 23:12:54.753415696 -0400 -@@ -0,0 +1,107 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2004 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_KPTE_H -+#define __QSNET_KPTE_H -+ -+#ident "@(#)$Id: kpte.h,v 1.1.2.1 2004/11/02 10:45:29 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/qsnet/kpte.h,v $*/ -+ -+#include -+ -+#ifdef NO_RMAP -+# define pte_offset_kernel pte_offset -+# define pte_offset_map pte_offset -+# define pte_unmap(A) do { ; } while (0) -+#endif -+ -+/* -+ * Pte stuff -+ */ -+static __inline__ struct mm_struct * -+get_kern_mm(void) -+{ -+ return &init_mm; -+} -+ -+static __inline__ pte_t * -+find_pte_map(struct mm_struct *mm, unsigned long vaddr) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *ptep; -+ -+/* XXXX - handle hugh tlb code */ -+ pgd = pgd_offset(mm, vaddr); -+ if (pgd_none(*pgd) || pgd_bad(*pgd)) -+ goto out; -+ -+ pmd = pmd_offset(pgd, vaddr); -+ if (pmd_none(*pmd) || pmd_bad (*pmd)) -+ goto out; -+ -+ ptep = pte_offset_map (pmd, vaddr); -+ if (! ptep) -+ goto out; -+ -+ if (pte_present (*ptep)) -+ return ptep; -+ -+ pte_unmap (ptep); -+out: -+ return NULL; -+} -+ -+static __inline__ pte_t * -+find_pte_kernel(unsigned long vaddr) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ -+ pgd = pgd_offset_k(vaddr); -+ if (pgd && !pgd_none(*pgd)) { -+ pmd = pmd_offset(pgd, vaddr); -+ if (pmd && pmd_present(*pmd)) { -+ pte = pte_offset_kernel(pmd, vaddr); -+ if (pte && pte_present(*pte)) -+ return (pte); -+ } -+ } -+ return (NULL); -+} -+ -+static __inline__ physaddr_t -+pte_phys(pte_t pte) -+{ -+#if defined(LINUX_ALPHA) -+ /* RedHat 7.1 2.4.3-12 -+ * They have now enabled Monster windows on Tsunami -+ * and so can use the Main's phys pte value -+ */ -+ return (pte_val(pte) >> (32-PAGE_SHIFT)); -+#elif defined(LINUX_I386) -+ return (pte_val(pte) & ~((1 << PAGE_SHIFT)-1)); -+#elif defined(LINUX_SPARC) -+ return (pte_val(pte) & _PAGE_PADDR); -+#elif defined(LINUX_IA64) -+ return (pte_val(pte) & _PFN_MASK); -+#elif defined(LINUX_X86_64) -+ return (pte_val(pte) & ~((1 << PAGE_SHIFT)-1) & ~_PAGE_NX); -+#else -+#error Unknown architecture -+#endif -+} -+ -+#endif /* __QSNET_KPTE_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/kthread.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/kthread.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/kthread.h 2005-06-01 23:12:54.754415544 -0400 -@@ -0,0 +1,71 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * Copyright (c) 2002-2004 by Quadrics Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_KTHREAD_H -+#define __QSNET_KTHREAD_H -+ -+#ident "@(#)$Id: kthread.h,v 1.1 2004/10/28 11:50:29 david Exp $ $Name: QSNETMODULES-4-30_20050128 $" -+/* $Source: /cvs/master/quadrics/qsnet/kthread.h,v $*/ -+ -+#include -+ -+/* -+ * kernel threads -+ */ -+extern __inline__ void -+kernel_thread_init(char *comm) -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) -+#ifndef NO_NPTL -+# define sigmask_lock sighand->siglock -+#endif -+ lock_kernel(); -+ daemonize(); -+ reparent_to_init(); -+ -+ /* avoid getting signals */ -+ spin_lock_irq(¤t->sigmask_lock); -+ flush_signals(current); -+ sigfillset(¤t->blocked); -+ -+#ifdef NO_NPTL -+ recalc_sigpending(current); -+#else -+ recalc_sigpending(); -+#endif -+ -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ /* set our name for identification purposes */ -+ strncpy(current->comm, comm, sizeof(current->comm)); -+ -+ unlock_kernel(); -+#else -+ daemonize(comm); -+#endif -+} -+ -+extern __inline__ void * -+kernel_thread_wrap(caddr_t stk, int stksize, void (*proc)(void *), void *arg) -+{ -+ ASSERT(stk == NULL && stksize == 0); -+ kernel_thread((int (*)(void *))proc, arg, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); -+ return (void *)1; /* non-null value */ -+} -+ -+#define kernel_thread_create(proc,arg) kernel_thread_wrap(NULL,0,(void (*)(void *))proc,arg) -+#define kernel_thread_exit() ((void) 0) -+#define kernel_thread_become_highpri() ((void) 0) -+ -+#endif /* __QSNET_KTHREAD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/list.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/list.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/list.h 2005-06-01 23:12:54.754415544 -0400 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Limited. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: list.h,v 1.5 2003/10/27 13:55:33 david Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/list.h,v $*/ -+ -+#ifndef __QSNET_LIST_H -+#define __QSNET_LIST_H -+ -+/* Implementation of doubly linked lists - compatible with linux */ -+struct list_head -+{ -+ struct list_head *next; -+ struct list_head *prev; -+}; -+ -+#if !defined(LINUX) -+#if ! defined( offsetof ) -+#define offsetof(T,F) ((int )&(((T *)0)->F)) -+#endif -+ -+#define LIST_HEAD_INIT(name) { &(name), &(name) } -+ -+#define LIST_HEAD(name) \ -+ struct list_head name = LIST_HEAD_INIT(name) -+#endif -+ -+#define list_entry(ptr, type, off) \ -+ ((type *) ((unsigned long)(ptr) - offsetof (type,off))) -+ -+#define INIT_LIST_HEAD(list) \ -+MACRO_BEGIN \ -+ (list)->next = (list)->prev = (list); \ -+MACRO_END -+ -+#define list_add(new, list) \ -+MACRO_BEGIN \ -+ (list)->next->prev = (new); \ -+ (new)->next = (list)->next; \ -+ (new)->prev = (list); \ -+ (list)->next = (new); \ -+MACRO_END -+ -+#define list_add_tail(new, list) \ -+MACRO_BEGIN \ -+ (list)->prev->next = new; \ -+ (new)->prev = (list)->prev; \ -+ (new)->next = (list); \ -+ (list)->prev = (new); \ -+MACRO_END -+ -+#define list_del(entry) \ -+MACRO_BEGIN \ -+ (entry)->prev->next = (entry)->next; \ -+ (entry)->next->prev = (entry)->prev; \ -+MACRO_END -+ -+#define list_del_init(entry) \ -+MACRO_BEGIN \ -+ (entry)->prev->next = (entry)->next; \ -+ (entry)->next->prev = (entry)->prev; \ -+ (entry)->next = (entry)->prev = (entry); \ -+MACRO_END -+ -+#define list_empty(list) \ -+ ((list)->next == (list)) -+ -+#define list_for_each(pos,list) \ -+ for (pos = (list)->next; pos != (list); \ -+ pos = (pos)->next) -+ -+#define list_for_each_safe(pos,n,list) \ -+ for (pos = (list)->next, n = (pos)->next; pos != (list); \ -+ pos = n, n = (pos)->next) -+ -+#endif /* __QSNET_LIST_H */ -Index: linux-2.4.21/include/qsnet/mutex.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/mutex.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/mutex.h 2005-06-01 23:12:54.754415544 -0400 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2000 Regents of the University of California -+ * -+ * 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 -+ * -+ */ -+ -+#if !defined(_LINUX_MUTEX_H) -+#define _LINUX_MUTEX_H -+#if defined(__KERNEL__) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define PID_NONE 0 -+ -+typedef struct -+{ -+ struct semaphore sem; -+ pid_t holder; -+} kmutex_t; -+ -+extern __inline__ void -+kmutex_init (kmutex_t *l) -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -+ l->sem = MUTEX; -+#else -+ init_MUTEX(&l->sem); -+#endif -+ l->holder = PID_NONE; -+} -+ -+extern __inline__ void -+kmutex_destroy (kmutex_t *l) -+{ -+ ASSERT (l->holder == PID_NONE); -+} -+ -+extern __inline__ void -+kmutex_lock (kmutex_t *l) -+{ -+ ASSERT(l->holder != current->pid); -+ down (&l->sem); -+ l->holder = current->pid; -+} -+ -+extern __inline__ void -+kmutex_unlock (kmutex_t *l) -+{ -+ ASSERT(l->holder == current->pid); -+ -+ l->holder = PID_NONE; -+ up (&l->sem); -+} -+ -+extern __inline__ int -+kmutex_trylock (kmutex_t *l) -+{ -+ if (down_trylock (&l->sem) == 0) -+ { -+ l->holder = current->pid; -+ return (1); -+ } -+ return (0); -+} -+ -+extern __inline__ int -+kmutex_is_locked (kmutex_t *l) -+{ -+ return (l->holder == current->pid); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* _LINUX_MUTEX_H */ -Index: linux-2.4.21/include/qsnet/procfs_linux.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/procfs_linux.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/procfs_linux.h 2005-06-01 23:12:54.755415392 -0400 -@@ -0,0 +1,234 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __PROCFS_LINUX_H -+#define __PROCFS_LINUX_H -+ -+#ident "$Id: procfs_linux.h,v 1.6.2.6 2004/12/06 17:36:24 robin Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/procfs_linux.h,v $ */ -+ -+#if defined(__KERNEL__) -+ -+#include -+#include -+#include -+ -+extern gid_t qsnet_procfs_gid; -+ -+/* borrowed from fs/proc/proc_misc - helper for proc_read_int */ -+static inline int -+qsnet_proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) -+{ -+ if (len <= off+count) *eof = 1; -+ *start = page + off; -+ len -= off; -+ if (len>count) len = count; -+ if (len<0) len = 0; -+ return len; -+} -+ -+static inline int -+qsnet_proc_write_int(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ char tmpbuf[16]; -+ int res = count; -+ -+ if (count > sizeof(tmpbuf) - 1) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ if (copy_from_user(tmpbuf, buf, count)) -+ res = -EFAULT; -+ else -+ { -+ tmpbuf[count] = '\0'; -+ *(int *)data = simple_strtoul(tmpbuf, NULL, 0); -+ } -+ MOD_DEC_USE_COUNT; -+ -+ return (res); -+} -+ -+static inline int -+qsnet_proc_read_int(char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ int len, res; -+ -+ MOD_INC_USE_COUNT; -+ -+ len = sprintf(page, "%d\n", *(int *)data); -+ res = qsnet_proc_calc_metrics(page, start, off, count, eof, len); -+ -+ MOD_DEC_USE_COUNT; -+ return (res); -+} -+ -+static inline struct proc_dir_entry * -+qsnet_proc_register_int(struct proc_dir_entry *dir, char *path, int *var, int read_only) -+{ -+ struct proc_dir_entry *p; -+ -+ p = create_proc_entry(path, read_only ? S_IRUGO : S_IRUGO|S_IWUSR|S_IWGRP, dir); -+ if (p) { -+ if (! read_only) -+ p->write_proc = qsnet_proc_write_int; -+ p->read_proc = qsnet_proc_read_int; -+ p->data = var; -+ p->owner = THIS_MODULE; -+ p->gid = qsnet_procfs_gid; -+ } -+ return p; -+} -+ -+static inline int -+qsnet_proc_write_hex(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ char tmpbuf[16]; -+ int res = count; -+ -+ if (count > sizeof(tmpbuf) - 1) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ if (copy_from_user(tmpbuf, buf, count)) -+ res = -EFAULT; -+ else -+ { -+ tmpbuf[count] = '\0'; -+ *(int *)data = simple_strtoul(tmpbuf, NULL, 0); -+ } -+ MOD_DEC_USE_COUNT; -+ -+ return (res); -+} -+ -+static inline int -+qsnet_proc_read_hex(char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ int len, res; -+ -+ MOD_INC_USE_COUNT; -+ -+ len = sprintf(page, "0x%x\n", *(int *)data); -+ res = qsnet_proc_calc_metrics(page, start, off, count, eof, len); -+ -+ MOD_DEC_USE_COUNT; -+ return (res); -+} -+ -+static inline struct proc_dir_entry * -+qsnet_proc_register_hex(struct proc_dir_entry *dir, char *path, int *var, int read_only) -+{ -+ struct proc_dir_entry *p; -+ -+ p = create_proc_entry(path, read_only ? S_IRUGO : S_IRUGO|S_IWUSR|S_IWGRP, dir); -+ if (p) { -+ if (! read_only) -+ p->write_proc = qsnet_proc_write_hex; -+ p->read_proc = qsnet_proc_read_hex; -+ p->data = var; -+ p->owner = THIS_MODULE; -+ p->gid = qsnet_procfs_gid; -+ } -+ return p; -+} -+ -+#define QSNET_PROC_STR_LEN_MAX ((int)256) -+ -+static inline int -+qsnet_proc_write_str(struct file *file, const char *buf, unsigned long count, void *data) -+{ -+ int res = count; -+ -+ if (count > (QSNET_PROC_STR_LEN_MAX - 1)) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ if (copy_from_user((char *)data, buf, count)) -+ res = -EFAULT; -+ else -+ { -+ ((char *)data)[count] = '\0'; -+ /* remove linefeed */ -+ if ( (count) && (((char *)data)[count -1] == '\n')) -+ ((char *)data)[count -1] = '\0'; -+ } -+ MOD_DEC_USE_COUNT; -+ -+ return (res); -+} -+ -+static inline int -+qsnet_proc_read_str(char *page, char **start, off_t off, int count, int *eof, void *data) -+{ -+ int len, res; -+ -+ if ( strlen(data) > (count + 1)) -+ return (-EINVAL); -+ -+ MOD_INC_USE_COUNT; -+ -+ /* cant output too much */ -+ if ( strlen(data) > (count + 1)) -+ { -+ MOD_DEC_USE_COUNT; -+ return (-EINVAL); -+ } -+ -+ -+ len = sprintf(page, "%s\n", (char *)data); -+ if (len > count) -+ { -+ MOD_DEC_USE_COUNT; -+ return (-EINVAL); -+ } -+ -+ res = qsnet_proc_calc_metrics(page, start, off, count, eof, len); -+ -+ MOD_DEC_USE_COUNT; -+ return (res); -+} -+ -+static inline struct proc_dir_entry * -+qsnet_proc_register_str(struct proc_dir_entry *dir, char *path, char *var, int read_only) -+{ -+ struct proc_dir_entry *p; -+ -+ p = create_proc_entry(path, read_only ? S_IRUGO : S_IRUGO|S_IWUSR|S_IWGRP, dir); -+ if (p) { -+ if (! read_only) -+ p->write_proc = qsnet_proc_write_str; -+ p->read_proc = qsnet_proc_read_str; -+ p->data = var; -+ p->owner = THIS_MODULE; -+ p->gid = qsnet_procfs_gid; -+ } -+ return p; -+} -+ -+extern struct proc_dir_entry *qsnet_procfs_root; -+extern struct proc_dir_entry *qsnet_procfs_config; -+ -+#ifdef NO_PDE -+static inline struct proc_dir_entry *PDE(const struct inode *inode) -+{ -+ return inode->u.generic_ip; -+} -+#endif -+#endif /* __KERNEL__ */ -+ -+#define QSNET_PROCFS_IOCTL "/proc/qsnet/ioctl" -+#define QSNET_PROCFS_KMEM_DEBUG "/proc/qsnet/kmem_debug" -+#define QSNET_PROCFS_VERSION "/proc/qsnet/version" -+ -+#endif /* __PROCFS_LINUX_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/pthread.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/pthread.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/pthread.h 2005-06-01 23:12:54.755415392 -0400 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (c) 2003 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+/* $Id: pthread.h,v 1.5 2004/06/07 10:47:06 addy Exp $ */ -+/* $Source: /cvs/master/quadrics/qsnet/pthread.h,v $*/ -+ -+#ifndef _CONFIG_PTHREAD_H -+#define _CONFIG_PTHREAD_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#if defined(__ELAN__) -+ -+/* No pthread support on Elan co-processor */ -+ -+#define MUTEX unsigned long long -+#define MUTEX_INIT(X) ; -+#define MUTEX_LOCK(X) ; -+#define MUTEX_UNLOCK(X) ; -+ -+#else -+#if defined(DIGITAL_UNIX) -+#include -+#define MUTEX pthread_mutex_t -+#define MUTEX_INIT(X) tis_mutex_init(X) -+#define MUTEX_LOCK(X) tis_mutex_lock(X) -+#define MUTEX_UNLOCK(X) tis_mutex_unlock(X) -+#define MUTEX_TRYLOCK(X) (tis_mutex_trylock(X) == 0) -+ -+#else /* Linux... */ -+ -+/* Use standard pthread calls */ -+#include -+#define MUTEX pthread_mutex_t -+#define MUTEX_INIT(X) pthread_mutex_init(X, NULL) -+#define MUTEX_LOCK(X) pthread_mutex_lock(X) -+#define MUTEX_UNLOCK(X) pthread_mutex_unlock(X) -+#define MUTEX_TRYLOCK(X) (pthread_mutex_trylock(X) == 0) -+ -+#endif /* DIGITAL_UNIX */ -+#endif /* __ELAN__ */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _CONFIG_PTHREAD_H */ -+ -+/* -+ * Local variables: -+ * c-file-style: "stroustrup" -+ * End: -+ */ -Index: linux-2.4.21/include/qsnet/statsformat.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/statsformat.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/statsformat.h 2005-06-01 23:12:54.756415240 -0400 -@@ -0,0 +1,25 @@ -+#ifndef _QSNET_STATSFORMAT_H -+#define _QSNET_STATSFORMAT_H -+ -+#ident "$Id: statsformat.h,v 1.2 2003/05/22 19:37:14 addy Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/statsformat.h,v $*/ -+ -+#include -+ -+/* -+ * format of an Elan stats record -+ * -+ * type char(8), type of statistic, e.g. FPAGE, ELAN3, TPORT -+ * time uint64, 10 digits, time in millisecs since counters initialised -+ * device uint, 2 digits, Elan device id -+ * name char(32), name of the statistic -+ * value uint64, current value of statistic -+ */ -+ -+#ifdef _ILP32 -+#define ELAN_STATSFORMAT "%-8s %10llu %2d %-32s %llu\n" -+#else -+#define ELAN_STATSFORMAT "%-8s %10lu %2d %-32s %lu\n" -+#endif -+ -+#endif -Index: linux-2.4.21/include/qsnet/types.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/types.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/types.h 2005-06-01 23:12:54.756415240 -0400 -@@ -0,0 +1,90 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef __QSNET_TYPES_H -+#define __QSNET_TYPES_H -+ -+#ident "$Id: types.h,v 1.16 2003/08/01 16:21:38 addy Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/types.h,v $*/ -+ -+/* -+ * Include typedefs for ISO/IEC 9899:1990 standard types -+ * -+ * -+ * The following integer typedefs are used: -+ * -+ * int8_t, int16_t, int32_t, int64_t, intptr_t -+ * uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t -+ * uchar_t, ushort_t, uint_t, ulong_t -+ * -+ * also defines the following: -+ * u_char, u_short, u_int, u_long, caddr_t -+ */ -+ -+#include -+ -+#if defined(SOLARIS) && defined(__KERNEL__) -+# include -+#endif -+ -+#if defined(SOLARIS) && !defined(__KERNEL__) -+# include -+# include -+#endif -+ -+#if defined(DIGITAL_UNIX) && defined(__KERNEL__) -+# include -+#endif -+ -+#if defined(DIGITAL_UNIX) && !defined(__KERNEL__) -+# include -+# include -+#endif -+ -+#if defined(LINUX) && defined(__KERNEL__) -+# include -+#endif -+ -+#if defined(LINUX) && !defined(__KERNEL__) -+# include -+# include -+# include -+ -+typedef unsigned char uchar_t; -+typedef unsigned short ushort_t; -+typedef unsigned int uint_t; -+typedef unsigned long ulong_t; -+#endif -+ -+#if defined(QNX) -+# include -+# include -+#endif -+ -+/* Define a type that will represent a Main CPU pointer -+ * on both the Main and the Elan -+ */ -+#ifdef __ELAN__ -+ -+#if defined(_MAIN_LP64) -+#define QSNET_MAIN_PTR uint64_t -+#else -+#define QSNET_MAIN_PTR uint32_t -+#endif -+ -+#else -+ -+#ifdef _LP64 -+#define QSNET_MAIN_PTR uint64_t -+#else -+#define QSNET_MAIN_PTR uint32_t -+#endif -+ -+#endif -+ -+ -+#endif /* __QSNET_TYPES_H */ -Index: linux-2.4.21/include/qsnet/workarounds.h -=================================================================== ---- linux-2.4.21.orig/include/qsnet/workarounds.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/qsnet/workarounds.h 2005-06-01 23:12:54.756415240 -0400 -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ifndef _QSNET_WORKAROUNDS_H -+#define _QSNET_WORKAROUNDS_H -+ -+#ident "$Id: workarounds.h,v 1.11 2002/08/09 11:15:55 addy Exp $" -+/* $Source: /cvs/master/quadrics/qsnet/workarounds.h,v $ */ -+ -+/* Elan workarounds */ -+#undef ELAN_REVA_SUPPORTED /* rev a elans no longer supported. */ -+#undef ELITE_REVA_SUPPORTED /* removed since RMS disables broadcast on rev A elites. */ -+#define ELAN_REVB_BUG_1 -+/* WORKAROUND for GNAT hw-elan3/3263 */ -+#define ELAN_REVB_BUG_2 -+ -+/* WORKAROUND for GNATs ic-elan3/3637 & ic-elan3/3550 */ -+#define ELAN_REVB_BUG_3 -+ -+#endif /* _QSNET_WORKAROUNDS_H */ -Index: linux-2.4.21/include/rms/rmscall.h -=================================================================== ---- linux-2.4.21.orig/include/rms/rmscall.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/rms/rmscall.h 2005-06-01 23:12:54.757415088 -0400 -@@ -0,0 +1,144 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ * rmscall.h: user interface to rms kernel module -+ * -+ * $Id: rmscall.h,v 1.25 2004/05/14 08:55:57 duncan Exp $ -+ * $Source: /cvs/master/quadrics/rmsmod/rmscall.h,v $ -+ * -+ */ -+ -+#ifndef RMSCALL_H_INCLUDED -+#define RMSCALL_H_INCLUDED 1 -+ -+#ident "$Id: rmscall.h,v 1.25 2004/05/14 08:55:57 duncan Exp $" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* -+ * flags for rms_fork_register -+ * -+ * RMS_IOF is not in a public header file -+ */ -+#define RMS_IOF 1 /* inherit on fork */ -+ -+#ifndef __KERNEL__ -+#include -+#endif -+ -+#include -+#include -+ -+#define MAXCOREPATHLEN 32 -+ -+#if defined(SOLARIS) -+typedef long long rmstime_t; -+#else /* DIGITAL_UNIX */ -+typedef long rmstime_t; -+#endif -+ -+typedef enum { -+ -+ PRG_RUNNING = 0x01, /* program is running */ -+ PRG_ZOMBIE = 0x02, /* last process on a node has exited */ -+ PRG_NODE = 0x04, /* stats are complete for this node */ -+ PRG_KILLED = 0x08, /* program was killed */ -+ PRG_SUSPEND = 0x10 /* program is suspended */ -+ -+} PRGSTATUS_FLAGS; -+ -+/* -+ * program time statistics extended in version 5 of the kernel module -+ */ -+typedef struct { -+ rmstime_t etime; /* elapsed cpu time (milli-secs) */ -+ rmstime_t atime; /* allocated cpu time (cpu milli-secs) */ -+ rmstime_t utime; /* user cpu time (cpu milli-secs) */ -+ rmstime_t stime; /* system cpu time (cpu milli-secs) */ -+ int ncpus; /* number of cpus allocated */ -+ int flags; /* program status flags */ -+ int mem; /* max memory size in MBytes */ -+ int pageflts; /* number of page faults */ -+ rmstime_t memint; /* memory integral */ -+} prgstats_old_t; -+ -+typedef struct { -+ uint64_t etime; /* elapsed cpu time (milli-secs) */ -+ uint64_t atime; /* allocated cpu time (cpu milli-secs) */ -+ uint64_t utime; /* user cpu time (cpu milli-secs) */ -+ uint64_t stime; /* system cpu time (cpu milli-secs) */ -+ uint64_t pageflts; /* number of page faults */ -+ uint64_t memint; /* memory integral */ -+ uint64_t ebytes; /* data transferred by the Elan(s) */ -+ uint64_t exfers; /* number of Elan data transfers */ -+ uint64_t spare64[4]; /* expansion space */ -+ int ncpus; /* number of cpus allocated */ -+ int flags; /* program status flags */ -+ int mem; /* max memory size in MBytes */ -+ int spare32[5]; /* expansion space */ -+} prgstats_t; -+ -+int rmsmod_init(void); -+void rmsmod_fini(void); -+ -+int rms_setcorepath(caddr_t path); -+int rms_getcorepath(pid_t pid, caddr_t path, int maxlen); -+int rms_prgcreate(int id, uid_t uid, int cpus); -+int rms_prgdestroy(int id); -+int rms_prgids(int maxids, int *prgids, int *nprgs); -+int rms_prginfo(int id, int maxpids, pid_t *pids, int *nprocs); -+int rms_prgaddcap(int id, int index, ELAN_CAPABILITY *cap); -+ -+int rms_prgsuspend(int id); -+int rms_prgresume(int id); -+int rms_prgsignal(int id, int signo); -+ -+int rms_getprgid(pid_t pid, int *id); -+int rms_ncaps(int *ncaps); -+int rms_getcap(int index, ELAN_CAPABILITY *cap); -+int rms_mycap(int *index); -+int rms_setcap(int index, int ctx); -+int rms_prefcap(int nprocess, int *index); -+ -+int rms_prggetstats(int id, prgstats_t *stats); -+void rms_accumulatestats(prgstats_t *total, prgstats_t *stats); -+char *rms_statsreport(prgstats_t *stats, char *buf); -+ -+int rms_elaninitdone(int vp); -+int rms_prgelanpids(int id, int maxpids, int *vps, pid_t *pids, int *npids); -+int rms_setelanstats(int id, uint64_t ebytes, uint64_t exfers); -+ -+int rms_setpset(int psid); -+int rms_getpset(int id, int *psid); -+int rms_modversion(); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+ -+#if defined(__KERNEL__) -+ -+int rms_init(void); -+int rms_fini(void); -+int rms_reconfigure(void); -+ -+extern int rms_debug; -+ -+#if 1 -+#define DBG(x) do if (rms_debug) x ; while (0) -+#else -+#define DBG(x) -+#endif -+ -+#endif -+ -+#endif /* RMSCALL_H_INCLUDED */ -+ -+ -+ -+ -Index: linux-2.4.21/include/rms/rmsio.h -=================================================================== ---- linux-2.4.21.orig/include/rms/rmsio.h 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/include/rms/rmsio.h 2005-06-01 23:12:54.757415088 -0400 -@@ -0,0 +1,185 @@ -+/* -+ * Copyright (c) 1996-2002 by Quadrics Supercomputers World Ltd. -+ * -+ * For licensing information please see the supplied COPYING file -+ * -+ */ -+ -+#ident "@(#)$Id: rmsio.h,v 1.6 2004/05/14 08:55:57 duncan Exp $" -+/* $Source: /cvs/master/quadrics/rmsmod/rmsio.h,v $*/ -+ -+ -+#ifndef __RMSMOD_RMSIO_H -+#define __RMSMOD_RMSIO_H -+ -+/* arg is corepath string */ -+#define RMSIO_SETCOREPATH _IOW ('r', 1, char) -+ -+typedef struct rmsio_getcorepath_struct -+{ -+ pid_t pid; -+ char *corepath; -+ int maxlen; -+} RMSIO_GETCOREPATH_STRUCT; -+#define RMSIO_GETCOREPATH _IOW ('r', 2, RMSIO_GETCOREPATH_STRUCT) -+ -+typedef struct rmsio_prgcreate_struct -+{ -+ int id; -+ uid_t uid; -+ int cpus; -+} RMSIO_PRGCREATE_STRUCT; -+#define RMSIO_PRGCREATE _IOW ('r', 3, RMSIO_PRGCREATE_STRUCT) -+ -+typedef struct rmsio_prginfo_struct -+{ -+ int id; -+ int maxpids; -+ pid_t *pids; -+ int *nprocs; -+} RMSIO_PRGINFO_STRUCT; -+#define RMSIO_PRGINFO _IOW ('r', 4, RMSIO_PRGINFO_STRUCT) -+ -+typedef struct rmsio_prgsignal_struct -+{ -+ int id; -+ int signo; -+} RMSIO_PRGSIGNAL_STRUCT; -+#define RMSIO_PRGSIGNAL _IOW ('r', 5, RMSIO_PRGSIGNAL_STRUCT) -+ -+typedef struct rmsio_prgaddcap_struct -+{ -+ int id; -+ int index; -+ ELAN_CAPABILITY *cap; -+} RMSIO_PRGADDCAP_STRUCT; -+#define RMSIO_PRGADDCAP _IOW ('r', 6, RMSIO_PRGADDCAP_STRUCT) -+typedef struct rmsio_setcap_struct -+{ -+ int index; -+ int ctx; -+} RMSIO_SETCAP_STRUCT; -+#define RMSIO_SETCAP _IOW ('r', 7, RMSIO_SETCAP_STRUCT) -+ -+typedef struct rmsio_getcap_struct -+{ -+ int index; -+ ELAN_CAPABILITY *cap; -+} RMSIO_GETCAP_STRUCT; -+#define RMSIO_GETCAP _IOW ('r', 8, RMSIO_GETCAP_STRUCT) -+ -+typedef struct rmsio_getcap_struct32 -+{ -+ int index; -+ unsigned int capptr; -+} RMSIO_GETCAP_STRUCT32; -+#define RMSIO_GETCAP32 _IOW ('r', 8, RMSIO_GETCAP_STRUCT32) -+ -+/* arg is pointer to ncaps */ -+#define RMSIO_NCAPS _IOW ('r', 9, int) -+ -+typedef struct rmsio_prggetstats_struct -+{ -+ int id; -+ prgstats_old_t *stats; -+} RMSIO_PRGGETSTATS_STRUCT; -+#define RMSIO_PRGGETSTATS _IOW ('r', 10, RMSIO_PRGGETSTATS_STRUCT) -+ -+/* arg is program id */ -+#define RMSIO_PRGSUSPEND _IOW ('r', 11, int) -+#define RMSIO_PRGRESUME _IOW ('r', 12, int) -+#define RMSIO_PRGDESTROY _IOW ('r', 13, int) -+ -+typedef struct rmsio_getprgid_struct -+{ -+ pid_t pid; -+ int *id; -+} RMSIO_GETPRGID_STRUCT; -+#define RMSIO_GETPRGID _IOW ('r', 14, RMSIO_GETPRGID_STRUCT) -+ -+typedef struct rmsio_getprgid_struct32 -+{ -+ pid_t pid; -+ unsigned int idptr; -+} RMSIO_GETPRGID_STRUCT32; -+#define RMSIO_GETPRGID32 _IOW ('r', 14, RMSIO_GETPRGID_STRUCT32) -+ -+/* arg is pointer to index */ -+#define RMSIO_GETMYCAP _IOW ('r', 15, int) -+ -+typedef struct rmsio_prgids_struct -+{ -+ int maxids; -+ int *prgids; -+ int *nprgs; -+} RMSIO_PRGIDS_STRUCT; -+#define RMSIO_PRGIDS _IOW ('r', 16, RMSIO_PRGIDS_STRUCT) -+ -+/* arg is pointer to vp */ -+#define RMSIO_ELANINITDONE _IOW ('r', 17, int) -+ -+typedef struct rmsio_prgelanpids_struct -+{ -+ int id; -+ int maxpids; -+ int *vps; -+ int *pids; -+ int *npids; -+} RMSIO_PRGELANPIDS_STRUCT; -+#define RMSIO_PRGELANPIDS _IOW ('r', 18, RMSIO_PRGELANPIDS_STRUCT) -+ -+typedef struct rmsio_setpset_struct -+{ -+ int id; -+ int psid; -+} RMSIO_SETPSET_STRUCT; -+#define RMSIO_SETPSET _IOW ('r', 19, RMSIO_SETPSET_STRUCT) -+ -+typedef struct rmsio_getpset_struct -+{ -+ int id; -+ int *psid; -+} RMSIO_GETPSET_STRUCT; -+#define RMSIO_GETPSET _IOW ('r', 20, RMSIO_GETPSET_STRUCT) -+ -+/* -+ * have to pass a pointer to the stats, the switch -+ * statement goes wrong in the module of the size -+ * is too large -+ */ -+typedef struct { -+ uint64_t ebytes; -+ uint64_t exfers; -+} elanstats_t; -+ -+typedef struct rmsio_setelanstats_struct -+{ -+ int id; -+ elanstats_t *estats; -+} RMSIO_SETELANSTATS_STRUCT; -+#define RMSIO_SETELANSTATS _IOW ('r', 21, RMSIO_SETELANSTATS_STRUCT) -+ -+typedef struct rmsio_prggetstats2_struct -+{ -+ int id; -+ prgstats_t *stats; -+} RMSIO_PRGGETSTATS2_STRUCT; -+#define RMSIO_PRGGETSTATS2 _IOW ('r', 22, RMSIO_PRGGETSTATS2_STRUCT) -+ -+typedef struct rmsio_modversion_struct -+{ -+ int *version; -+} RMSIO_MODVERSION_STRUCT; -+#define RMSIO_MODVERSION _IOW ('r', 23, RMSIO_MODVERSION_STRUCT) -+ -+ -+#endif /* __RMSMOD_RMSIO_H */ -+ -+ -+ -+ -+ -+ -+ -+ -+ -Index: linux-2.4.21/ipc/shm.c -=================================================================== ---- linux-2.4.21.orig/ipc/shm.c 2005-06-01 22:51:50.000000000 -0400 -+++ linux-2.4.21/ipc/shm.c 2005-06-01 23:12:54.758414936 -0400 -@@ -723,6 +723,44 @@ - return retval; - } - -+/* -+ * Mark all segments created by this process for destruction -+ */ -+asmlinkage int shm_cleanup () -+{ -+ int i; -+ -+ down(&shm_ids.sem); -+ -+ for(i = 0; i <= shm_ids.max_id; i++) { -+ struct shmid_kernel* shp; -+ -+ shp = shm_lock(i); -+ if(shp!=NULL) { -+ -+ /* Mark this segment for destruction if we created it */ -+ if (current->pid == shp->shm_cprid) -+ { -+ /* Copy of IPC_RMID code */ -+ if (shp->shm_nattch){ -+ shp->shm_flags |= SHM_DEST; -+ /* Do not find it any more */ -+ shp->shm_perm.key = IPC_PRIVATE; -+ } else { -+ shm_destroy(shp); -+ continue; -+ } -+ } -+ -+ shm_unlock(i); -+ } -+ } -+ -+ up(&shm_ids.sem); -+ -+ return 0; -+} -+ - #ifdef CONFIG_PROC_FS - static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data) - { -Index: linux-2.4.21/kernel/exit.c -=================================================================== ---- linux-2.4.21.orig/kernel/exit.c 2005-06-01 22:58:09.055062312 -0400 -+++ linux-2.4.21/kernel/exit.c 2005-06-01 23:12:54.759414784 -0400 -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -705,6 +706,10 @@ - if (current->tux_info) - current->tux_exit(); - acct_process(code); -+ -+ /* Notify any ptrack callbacks of the process exit */ -+ ptrack_call_callbacks(PTRACK_PHASE_EXIT, NULL); -+ - if (isaudit(tsk)) - audit_exit(tsk, code); - __exit_mm(tsk); -Index: linux-2.4.21/kernel/fork.c -=================================================================== ---- linux-2.4.21.orig/kernel/fork.c 2005-06-01 22:58:09.055062312 -0400 -+++ linux-2.4.21/kernel/fork.c 2005-06-01 23:12:54.760414632 -0400 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -308,6 +309,7 @@ - /* unlimited stack is larger than TASK_SIZE */ - mm->non_executable_cache = NON_EXECUTABLE_CACHE(current); - mm->pgd = pgd_alloc(mm); -+ mm->coproc_ops = NULL; - mm->def_flags = 0; - if (mm->pgd) - return mm; -@@ -1110,6 +1112,12 @@ - p->vfork_done = &vfork; - init_completion(&vfork); - } -+ -+ if (ptrack_call_callbacks (PTRACK_PHASE_CLONE, p)) { -+ /* start up with an immediate SIGKILL. */ -+ sigaddset (&p->pending.signal, SIGKILL); -+ p->sigpending = 1; -+ } - - if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) { - /* -Index: linux-2.4.21/kernel/ksyms.c -=================================================================== ---- linux-2.4.21.orig/kernel/ksyms.c 2005-06-01 23:12:40.911519984 -0400 -+++ linux-2.4.21/kernel/ksyms.c 2005-06-01 23:12:54.760414632 -0400 -@@ -43,6 +43,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -104,6 +105,10 @@ - - #endif - -+EXPORT_SYMBOL_GPL(ptrack_register); -+EXPORT_SYMBOL_GPL(ptrack_deregister); -+EXPORT_SYMBOL_GPL(ptrack_registered); -+ - /* process memory management */ - EXPORT_SYMBOL(do_mmap_pgoff); - EXPORT_SYMBOL(do_munmap); -@@ -113,6 +118,7 @@ - EXPORT_SYMBOL(exit_files); - EXPORT_SYMBOL(exit_fs); - EXPORT_SYMBOL(exit_sighand); -+EXPORT_SYMBOL(make_pages_present); - EXPORT_SYMBOL(unshare_files); - EXPORT_SYMBOL(mmput); - -@@ -589,6 +595,10 @@ - EXPORT_SYMBOL(kernel_read); - EXPORT_SYMBOL(open_exec); - -+/* QSW Shared-memory cleanup hook for rmsmod */ -+extern int shm_cleanup(); -+EXPORT_SYMBOL_GPL(shm_cleanup); -+ - /* Miscellaneous access points */ - EXPORT_SYMBOL(si_meminfo); - -Index: linux-2.4.21/kernel/Makefile -=================================================================== ---- linux-2.4.21.orig/kernel/Makefile 2005-06-01 22:51:53.000000000 -0400 -+++ linux-2.4.21/kernel/Makefile 2005-06-01 23:12:54.760414632 -0400 -@@ -18,6 +18,10 @@ - signal.o sys.o kmod.o context.o \ - futex.o pid.o kksymoops.o - -+# Quadrics additions -+export-objs += ptrack.o -+obj-y += ptrack.o -+ - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += ksyms.o - obj-$(CONFIG_COMPAT) += compat.o -Index: linux-2.4.21/kernel/ptrack.c -=================================================================== ---- linux-2.4.21.orig/kernel/ptrack.c 2004-02-23 16:02:56.000000000 -0500 -+++ linux-2.4.21/kernel/ptrack.c 2005-06-01 23:12:54.761414480 -0400 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2000 Regents of the University of California -+ * -+ * 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 -+ * -+ * Derived from exit_actn.c by -+ * Copyright (C) 2003 Quadrics Ltd. -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+ -+int -+ptrack_register (ptrack_callback_t callback, void *arg) -+{ -+ struct ptrack_desc *desc = kmalloc (sizeof (struct ptrack_desc), GFP_KERNEL); -+ -+ if (desc == NULL) -+ return -ENOMEM; -+ -+ desc->callback = callback; -+ desc->arg = arg; -+ -+ list_add_tail (&desc->link, ¤t->ptrack_list); -+ -+ return 0; -+} -+ -+void -+ptrack_deregister (ptrack_callback_t callback, void *arg) -+{ -+ struct list_head *el, *nel; -+ -+ list_for_each_safe (el, nel, ¤t->ptrack_list) { -+ struct ptrack_desc *desc = list_entry (el, struct ptrack_desc, link); -+ -+ if (desc->callback == callback && desc->arg == arg) { -+ list_del (&desc->link); -+ kfree (desc); -+ } -+ } -+} -+ -+int -+ptrack_registered (ptrack_callback_t callback, void *arg) -+{ -+ struct list_head *el; -+ -+ list_for_each (el, ¤t->ptrack_list) { -+ struct ptrack_desc *desc = list_entry (el, struct ptrack_desc, link); -+ -+ if (desc->callback == callback && desc->arg == arg) -+ return 1; -+ } -+ return 0; -+} -+ -+int -+ptrack_call_callbacks (int phase, struct task_struct *child) -+{ -+ struct list_head *el, *nel; -+ struct ptrack_desc *new; -+ int res; -+ -+ if (phase == PTRACK_PHASE_CLONE) -+ INIT_LIST_HEAD (&child->ptrack_list); -+ -+ /* if init process, ignore */ -+ if (current->pid == 0) -+ return 0; -+ -+ list_for_each_safe (el, nel, ¤t->ptrack_list) { -+ struct ptrack_desc *desc = list_entry (el, struct ptrack_desc, link); -+ -+ res = desc->callback (desc->arg, phase, child); -+ -+ switch (phase) -+ { -+ case PTRACK_PHASE_EXIT: -+ list_del (&desc->link); -+ kfree (desc); -+ break; -+ -+ case PTRACK_PHASE_CLONE: -+ switch (res) -+ { -+ case PTRACK_FINISHED: -+ break; -+ -+ case PTRACK_INNHERIT: -+ if ((new = kmalloc (sizeof (struct ptrack_desc), GFP_ATOMIC)) == NULL) -+ { -+ /* allocation failed - notify that this process is not going -+ * to be started by signalling clone failure. -+ */ -+ desc->callback (desc->arg, PTRACK_PHASE_CLONE_FAIL, child); -+ -+ goto failed; -+ } -+ -+ new->callback = desc->callback; -+ new->arg = desc->arg; -+ -+ list_add_tail (&new->link, &child->ptrack_list); -+ break; -+ -+ case PTRACK_DENIED: -+ goto failed; -+ } -+ break; -+ } -+ } -+ -+ return 0; -+ -+ failed: -+ while (! list_empty (&child->ptrack_list)) -+ { -+ struct ptrack_desc *desc = list_entry (child->ptrack_list.next, struct ptrack_desc, link); -+ -+ desc->callback (desc->arg, PTRACK_PHASE_CLONE_FAIL, child); -+ -+ list_del (&desc->link); -+ kfree (desc); -+ } -+ return 1; -+} -Index: linux-2.4.21/mm/filemap.c -=================================================================== ---- linux-2.4.21.orig/mm/filemap.c 2005-06-01 23:12:41.100491256 -0400 -+++ linux-2.4.21/mm/filemap.c 2005-06-01 23:12:54.763414176 -0400 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2468,6 +2469,7 @@ - flush_cache_range(vma, end - size, end); - if (address >= end) - BUG(); -+ coproc_sync_range (vma->vm_mm, address, end); - do { - error |= filemap_sync_pmd_range(dir, address, end - address, vma, flags); - address = (address + PGDIR_SIZE) & PGDIR_MASK; -Index: linux-2.4.21/mm/memory.c -=================================================================== ---- linux-2.4.21.orig/mm/memory.c 2005-06-01 22:52:04.000000000 -0400 -+++ linux-2.4.21/mm/memory.c 2005-06-01 23:13:59.371592240 -0400 -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -632,6 +633,7 @@ - BUG_ON(address >= end); - - spin_lock(&mm->page_table_lock); -+ coproc_invalidate_range (mm, address, end); - flush_cache_range(vma, start, end); - tlb = tlb_gather_mmu(vma); - -@@ -1302,6 +1304,7 @@ - BUG(); - - spin_lock(&mm->page_table_lock); -+ coproc_invalidate_range (mm, beg, end); - do { - pmd_t *pmd = pmd_alloc(mm, dir, address); - error = -ENOMEM; -@@ -1313,6 +1316,7 @@ - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); -+ coproc_update_range(mm, beg, end); - spin_unlock(&mm->page_table_lock); - flush_tlb_range(vma, beg, end); - return error; -@@ -1391,6 +1395,7 @@ - BUG(); - - spin_lock(&mm->page_table_lock); -+ coproc_invalidate_range(mm, beg, end); - do { - pmd_t *pmd = pmd_alloc(mm, dir, from); - error = -ENOMEM; -@@ -1402,6 +1407,7 @@ - from = (from + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (from && (from < end)); -+ coproc_update_range(mm, beg, end); - spin_unlock(&mm->page_table_lock); - flush_tlb_range(vma, beg, end); - return error; -@@ -1497,8 +1503,10 @@ - unlock_page(old_page); - flush_cache_page(vma, address); - entry = maybe_mkwrite(pte_mkyoung(pte_mkdirty(pte)), vma); -+ coproc_invalidate_page(vma, address); - establish_pte(vma, address, page_table, entry); - pte_unmap(page_table); -+ coproc_update_page(vma, address); - spin_unlock(&mm->page_table_lock); - return 1; /* Minor fault */ - } -@@ -1528,6 +1536,7 @@ - if (PageReserved(old_page)) - ++mm->rss; - page_remove_rmap(old_page, page_table); -+ coproc_invalidate_page(vma, address); - break_cow(vma, new_page, address, page_table); - pte_chain = page_add_rmap(new_page, page_table, pte_chain); - lru_cache_add(new_page); -@@ -1536,6 +1545,7 @@ - new_page = old_page; - } - pte_unmap(page_table); -+ coproc_update_page(vma, address); - spin_unlock(&mm->page_table_lock); - if (old_page_locked) - unlock_page(old_page); -@@ -1748,6 +1758,7 @@ - /* No need to invalidate - it was non-present before */ - update_mmu_cache(vma, address, pte); - pte_unmap(page_table); -+ coproc_update_page(vma, address); - spin_unlock(&mm->page_table_lock); - pte_chain_free(pte_chain); - return ret; -@@ -1804,6 +1815,7 @@ - /* No need to invalidate - it was non-present before */ - update_mmu_cache(vma, addr, entry); - pte_unmap(page_table); -+ coproc_update_page(vma, addr); - spin_unlock(&mm->page_table_lock); - ret = 1; /* Minor fault */ - goto out; -@@ -1902,6 +1914,7 @@ - - /* no need to invalidate: a not-present page shouldn't be cached */ - update_mmu_cache(vma, address, entry); -+ coproc_update_page(vma, address); - spin_unlock(&mm->page_table_lock); - pte_chain_free(pte_chain); - return 2; /* Major fault */ -@@ -1958,8 +1971,10 @@ - entry = pte_mkdirty(entry); - } - entry = pte_mkyoung(entry); -+ coproc_invalidate_page(vma, address); - establish_pte(vma, address, pte, entry); - pte_unmap(pte); -+ coproc_update_page(vma, address); - spin_unlock(&mm->page_table_lock); - return 1; - } -Index: linux-2.4.21/mm/mmap.c -=================================================================== ---- linux-2.4.21.orig/mm/mmap.c 2005-06-01 22:51:50.000000000 -0400 -+++ linux-2.4.21/mm/mmap.c 2005-06-01 23:12:54.767413568 -0400 -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1450,6 +1451,7 @@ - release_segments(mm); - - spin_lock(&mm->page_table_lock); -+ coproc_release(mm); - mpnt = mm->mmap; - mm->mmap = mm->mmap_cache = NULL; - mm->mm_rb = RB_ROOT; -Index: linux-2.4.21/mm/mprotect.c -=================================================================== ---- linux-2.4.21.orig/mm/mprotect.c 2005-06-01 22:51:50.000000000 -0400 -+++ linux-2.4.21/mm/mprotect.c 2005-06-01 23:12:54.767413568 -0400 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -106,6 +107,7 @@ - if (start >= end) - BUG(); - spin_lock(¤t->mm->page_table_lock); -+ coproc_change_protection (current->mm, start, end, newprot); - do { - change_pmd_range(vma, dir, start, end - start, newprot); - start = (start + PGDIR_SIZE) & PGDIR_MASK; -Index: linux-2.4.21/mm/mremap.c -=================================================================== ---- linux-2.4.21.orig/mm/mremap.c 2005-06-01 22:51:50.000000000 -0400 -+++ linux-2.4.21/mm/mremap.c 2005-06-01 23:12:54.768413416 -0400 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -160,7 +161,10 @@ - unsigned long new_addr, unsigned long old_addr, unsigned long len) - { - unsigned long offset = len; -+ struct mm_struct *mm = vma->vm_mm; - -+ coproc_invalidate_range(mm, old_addr, old_addr+len); -+ coproc_invalidate_range(mm, new_addr, new_addr+len); - flush_cache_range(vma, old_addr, old_addr + len); - - /* -Index: linux-2.4.21/mm/rmap.c -=================================================================== ---- linux-2.4.21.orig/mm/rmap.c 2005-06-01 22:51:50.000000000 -0400 -+++ linux-2.4.21/mm/rmap.c 2005-06-01 23:12:54.768413416 -0400 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -449,6 +450,7 @@ - } - - /* Nuke the page table entry. */ -+ coproc_invalidate_page(vma, address); - pte = vm_ptep_get_and_clear(vma, address, ptep); - flush_tlb_page(vma, address); - flush_cache_page(vma, address); diff --git a/lustre/kernel_patches/patches/remove-suid-2.4-rhel.patch b/lustre/kernel_patches/patches/remove-suid-2.4-rhel.patch deleted file mode 100644 index 4f9fe49..0000000 --- a/lustre/kernel_patches/patches/remove-suid-2.4-rhel.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- uml-2.4.24/mm/filemap.c.orig 2005-02-18 22:27:31.000000000 +0200 -+++ uml-2.4.24/mm/filemap.c 2005-02-18 22:49:02.960952568 +0200 -@@ -2993,7 +2993,20 @@ inline void remove_suid(struct inode *in - /* was any of the uid bits set? */ - mode &= inode->i_mode; - if (mode && !capable(CAP_FSETID)) { -+ struct inode_operations *op = inode->i_op; - inode->i_mode &= ~mode; -+ -+ if (op && op->setattr_raw) { -+ struct iattr newattrs; -+ int result; -+ newattrs.ia_mode = inode->i_mode; -+ -+ newattrs.ia_valid = ATTR_FORCE | ATTR_MODE; -+ result = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (result != -EOPNOTSUPP) -+ return; /* No way to return status. Whoops! */ -+ } - mark_inode_dirty(inode); - } - } diff --git a/lustre/kernel_patches/patches/removepage-2.4.20.patch b/lustre/kernel_patches/patches/removepage-2.4.20.patch deleted file mode 100644 index cc721e1..0000000 --- a/lustre/kernel_patches/patches/removepage-2.4.20.patch +++ /dev/null @@ -1,28 +0,0 @@ - include/linux/fs.h | 1 + - mm/filemap.c | 3 +++ - 2 files changed, 4 insertions(+) - ---- linux-2.4.20-b_llpmd-l24/include/linux/fs.h~removepage-2.4.20 2003-09-05 11:45:42.000000000 -0700 -+++ linux-2.4.20-b_llpmd-l24-zab/include/linux/fs.h 2003-09-05 11:46:25.000000000 -0700 -@@ -402,6 +402,7 @@ struct address_space_operations { - int (*releasepage) (struct page *, int); - #define KERNEL_HAS_O_DIRECT /* this is for modules out of the kernel */ - int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); -+ void (*removepage)(struct page *); /* called when page gets removed from the inode */ - }; - - struct address_space { ---- linux-2.4.20-b_llpmd-l24/mm/filemap.c~removepage-2.4.20 2003-09-05 11:45:42.000000000 -0700 -+++ linux-2.4.20-b_llpmd-l24-zab/mm/filemap.c 2003-09-05 11:46:25.000000000 -0700 -@@ -95,6 +95,9 @@ static inline void remove_page_from_inod - { - struct address_space * mapping = page->mapping; - -+ if (mapping->a_ops->removepage) -+ mapping->a_ops->removepage(page); -+ - mapping->nrpages--; - list_del(&page->list); - page->mapping = NULL; - -_ diff --git a/lustre/kernel_patches/patches/sd_iostats-2.4.21-chaos.patch b/lustre/kernel_patches/patches/sd_iostats-2.4.21-chaos.patch deleted file mode 100644 index ba97b76..0000000 --- a/lustre/kernel_patches/patches/sd_iostats-2.4.21-chaos.patch +++ /dev/null @@ -1,471 +0,0 @@ -diff -urp RH_2_4_21_47_0_1.orig/Documentation/Configure.help RH_2_4_21_47_0_1/Documentation/Configure.help ---- RH_2_4_21_47_0_1.orig/Documentation/Configure.help 2006-11-20 16:59:49.000000000 +0200 -+++ RH_2_4_21_47_0_1/Documentation/Configure.help 2007-05-21 19:13:23.000000000 +0300 -@@ -7620,6 +7620,11 @@ CONFIG_SCSI_LOGGING - there should be no noticeable performance impact as long as you have - logging turned off. - -+SCSI disk I/O stats -+CONFIG_SD_IOSTATS -+ This enables SCSI disk I/O stats collection. You must also enable -+ /proc file system support if you want this feature. -+ - QDIO base support for IBM S/390 and zSeries - CONFIG_QDIO - This driver provides the Queued Direct I/O base support for the -diff -urp RH_2_4_21_47_0_1.orig/drivers/scsi/Config.in RH_2_4_21_47_0_1/drivers/scsi/Config.in ---- RH_2_4_21_47_0_1.orig/drivers/scsi/Config.in 2006-11-20 16:59:49.000000000 +0200 -+++ RH_2_4_21_47_0_1/drivers/scsi/Config.in 2007-05-21 19:13:23.000000000 +0300 -@@ -4,6 +4,7 @@ dep_tristate ' SCSI disk support' CONFI - - if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then - int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 -+ bool 'SCSI disk I/O stats' CONFIG_SD_IOSTATS y - fi - if [ "$CONFIG_BLK_DEV_SD" != "n" -a "$CONFIG_DISKDUMP" != "n" ]; then - dep_tristate ' SCSI dump support' CONFIG_SCSI_DUMP $CONFIG_SCSI -diff -urp RH_2_4_21_47_0_1.orig/drivers/scsi/sd.c RH_2_4_21_47_0_1/drivers/scsi/sd.c ---- RH_2_4_21_47_0_1.orig/drivers/scsi/sd.c 2006-11-20 16:59:45.000000000 +0200 -+++ RH_2_4_21_47_0_1/drivers/scsi/sd.c 2007-05-21 19:14:27.000000000 +0300 -@@ -65,6 +65,40 @@ - * static const char RCSid[] = "$Header:"; - */ - -+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS)) -+#include -+#include -+ -+typedef struct -+{ -+ unsigned long long iostat_size; -+ unsigned long long iostat_count; -+} iostat_counter_t; -+ -+#define IOSTAT_NCOUNTERS 16 -+typedef struct -+{ -+ iostat_counter_t iostat_read_histogram[IOSTAT_NCOUNTERS]; -+ iostat_counter_t iostat_write_histogram[IOSTAT_NCOUNTERS]; -+ struct timeval iostat_timeval; -+} iostat_stats_t; -+ -+iostat_stats_t **sd_iostats; -+spinlock_t sd_iostats_lock; -+struct proc_dir_entry *sd_iostats_procdir; -+char sd_iostats_procdir_name[] = "sd_iostats"; -+ -+extern void sd_iostats_init(void); -+extern void sd_iostats_init_disk(int disk); -+extern void sd_iostats_fini(void); -+extern void sd_iostats_bump(int disk, unsigned int nsect, int iswrite); -+#else -+static inline void sd_iostats_init(void) {} -+static inline void sd_iostats_init_disk(int disk) {} -+static inline void sd_iostats_fini(void) {} -+static inline void sd_iostats_bump(int dev, unsigned int nsect, int iswrite) {} -+#endif -+ - /* device number --> sd_gendisks index */ - #define SD_MAJOR_IDX(i) ( ((MAJOR(i) & 0x80) >> 4) + (MAJOR(i) & 7) ) - /* sd_gendisks index --> system major */ -@@ -372,6 +406,8 @@ static int sd_init_command(Scsi_Cmnd * S - SCSI_LOG_HLQUEUE(2, printk("%s : real dev = /dev/%d, block = %d\n", - nbuff, dev, block)); - -+ sd_iostats_bump(dev, this_count, SCpnt->request.cmd == WRITE); -+ - /* - * If we have a 1K hardware sectorsize, prevent access to single - * 512 byte sectors. In theory we could handle this - in fact -@@ -575,7 +611,7 @@ static int sd_open(struct inode *inode, - if (scsi_block_when_processing_errors(SDev)) - scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL); - -- -+ sd_iostats_init_disk(target); - return 0; - - error_out: -@@ -593,18 +629,31 @@ static int sd_release(struct inode *inod - { - int target; - Scsi_Device * SDev; -+ char nbuff[6]; - - target = DEVICE_NR(inode->i_rdev); - SDev = rscsi_disks[target].device; - if (!SDev) - return -ENODEV; - -- SDev->access_count--; -- -- if (SDev->removable) { -- if (!SDev->access_count) -+ if (!--SDev->access_count) { -+ /* -+ * Remove sd_iostats information about this disk -+ */ -+ if (sd_iostats_procdir != NULL) { -+ sd_devname(target, nbuff); -+ remove_proc_entry(nbuff, sd_iostats_procdir); -+ } -+ if (sd_iostats != NULL) { -+ if (sd_iostats[target] != NULL) { -+ kfree (sd_iostats[target]); -+ sd_iostats[target] = NULL; -+ } -+ } -+ if (SDev->removable) { - if (scsi_block_when_processing_errors(SDev)) - scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL); -+ } - } - if (SDev->host->hostt->module) - __MOD_DEC_USE_COUNT(SDev->host->hostt->module); -@@ -1260,6 +1309,8 @@ static int sd_init() - - memset(sd_varyio, 0, (sd_template.dev_max << 4)); - -+ sd_iostats_init(); -+ - for (i = 0; i < sd_template.dev_max << 4; i++) { - sd_blocksizes[i] = 1024; - sd_hardsizes[i] = 512; -@@ -1324,6 +1375,7 @@ cleanup_gendisks_de_arr: - kfree(sd_gendisks); - sd_gendisks = NULL; - cleanup_sd_gendisks: -+ sd_iostats_fini(); - kfree(sd_varyio); - cleanup_varyio: - kfree(sd_max_sectors); -@@ -1547,6 +1599,321 @@ static void sd_detach(Scsi_Device * SDp) - return; - } - -+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS)) -+static int -+sd_iostats_seq_show(struct seq_file *seq, void *v) -+{ -+ struct timeval now; -+ unsigned long index = (unsigned long)(seq->private); -+ iostat_stats_t *stats; -+ unsigned long long read_len; -+ unsigned long long read_len_tot; -+ unsigned long read_num; -+ unsigned long read_num_tot; -+ unsigned long long write_len; -+ unsigned long long write_len_tot; -+ unsigned long write_num; -+ unsigned long write_num_tot; -+ int i; -+ int maxi; -+ -+ if (seq == NULL || sd_iostats == NULL) { -+ printk(KERN_ERR "sd_iostats_seq_show: NULL stats array\n"); -+ BUG(); -+ } -+ -+ if (index >= sd_template.dev_max || !rscsi_disks[index].device) -+ return -ENXIO; /* No such device */ -+ -+ stats = sd_iostats[index]; -+ if (stats == NULL) { -+ seq_printf(seq, "sd_iostats_seq_show: sd_iostats " -+ "entry %d does not exist\n", -+ index); -+ return 0; -+ } -+ -+ do_gettimeofday(&now); -+ now.tv_sec -= stats->iostat_timeval.tv_sec; -+ now.tv_usec -= stats->iostat_timeval.tv_usec; -+ if (now.tv_usec < 0) { -+ now.tv_usec += 1000000; -+ now.tv_sec--; -+ } -+ -+ /* this sampling races with updates */ -+ seq_printf(seq, "index: %lu snapshot_time: %lu.%06lu\n", -+ index, now.tv_sec, now.tv_usec); -+ -+ for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--) -+ if (stats->iostat_read_histogram[i].iostat_count != 0 || -+ stats->iostat_write_histogram[i].iostat_count != 0) -+ break; -+ maxi = i; -+ -+ seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size", -+ "reads", "total", "writes", "total"); -+ -+ read_len_tot = write_len_tot = 0; -+ read_num_tot = write_num_tot = 0; -+ for (i = 0; i <= maxi; i++) { -+ read_len = stats->iostat_read_histogram[i].iostat_size; -+ read_len_tot += read_len; -+ read_num = stats->iostat_read_histogram[i].iostat_count; -+ read_num_tot += read_num; -+ -+ write_len = stats->iostat_write_histogram[i].iostat_size; -+ write_len_tot += write_len; -+ write_num = stats->iostat_write_histogram[i].iostat_count; -+ write_num_tot += write_num; -+ -+ seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n", -+ 512<private_data)->private = PDE(inode)->data; -+ return 0; -+} -+ -+static int -+sd_iostats_seq_write(struct file *file, const char *buffer, -+ size_t len, loff_t *off) -+{ -+ struct seq_file *seq = file->private_data; -+ unsigned long index = (unsigned long)seq->private; -+ iostat_stats_t *stats = sd_iostats[index]; -+ unsigned long flags; -+ -+ -+ spin_lock_irqsave (&sd_iostats_lock, flags); -+ memset (stats, 0, sizeof(*stats)); -+ do_gettimeofday(&stats->iostat_timeval); -+ spin_unlock_irqrestore (&sd_iostats_lock, flags); -+ -+ return len; -+} -+ -+static struct file_operations sd_iostats_proc_fops = { -+ .owner = THIS_MODULE, -+ .open = sd_iostats_seq_open, -+ .read = seq_read, -+ .write = sd_iostats_seq_write, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+ -+void -+sd_iostats_init(void) -+{ -+ int maxdevs = sd_template.dev_max; -+ int i; -+ -+ spin_lock_init(&sd_iostats_lock); -+ -+ sd_iostats = kmalloc(maxdevs * sizeof(iostat_stats_t *), GFP_KERNEL); -+ if (sd_iostats == NULL) { -+ printk(KERN_WARNING "Can't keep sd iostats: " -+ "ENOMEM allocating stats array size %d\n", -+ sd_template.dev_max * sizeof(iostat_stats_t *)); -+ return; -+ } -+ -+ for (i = 0; i < maxdevs; i++) -+ sd_iostats[i] = NULL; -+ -+ if (proc_scsi == NULL) { -+ printk(KERN_WARNING "No access to sd iostats: " -+ "proc_scsi is NULL\n"); -+ return; -+ } -+ -+ sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name, -+ S_IFDIR | S_IRUGO | S_IXUGO, -+ proc_scsi); -+ if (sd_iostats_procdir == NULL) { -+ printk(KERN_WARNING "No access to sd iostats: " -+ "can't create /proc/scsi/%s\n", sd_iostats_procdir_name); -+ return; -+ } -+} -+ -+void -+sd_iostats_init_disk(int disk) -+{ -+ char name[6]; -+ struct proc_dir_entry *pde; -+ int i; -+ unsigned long flags; -+ iostat_stats_t *stats; -+ int maxdevs = sd_template.dev_max; -+ -+ if (sd_iostats == NULL || -+ sd_iostats_procdir == NULL) -+ return; -+ -+ if (disk > sd_template.dev_max) { -+ printk(KERN_ERR "sd_iostats_init_disk: " -+ "unexpected disk index %d(%d)\n", -+ disk, sd_template.dev_max); -+ BUG(); -+ } -+ -+ if (sd_iostats[disk] != NULL) -+ return; -+ -+ sd_devname(disk, name); -+ stats = kmalloc(sizeof(*stats), GFP_KERNEL); -+ if (stats == NULL) { -+ printk(KERN_WARNING "Can't keep %s iostats: " -+ "ENOMEM allocating stats size %d\n", -+ name, sizeof(*stats)); -+ return; -+ } -+ -+ memset (stats, 0, sizeof(*stats)); -+ do_gettimeofday(&stats->iostat_timeval); -+ -+ spin_lock_irqsave(&sd_iostats_lock, flags); -+ -+ if (sd_iostats[disk] != NULL) { -+ spin_unlock_irqrestore(&sd_iostats_lock, flags); -+ kfree (stats); -+ return; -+ } -+ -+ sd_iostats[disk] = stats; -+ -+ spin_unlock_irqrestore(&sd_iostats_lock, flags); -+ -+ pde = create_proc_entry(name, S_IRUGO | S_IWUSR, -+ sd_iostats_procdir); -+ if (pde == NULL) { -+ printk(KERN_WARNING "Can't create /proc/scsi/%s/%s\n", -+ sd_iostats_procdir_name, name); -+ } else { -+ pde->proc_fops = &sd_iostats_proc_fops; -+ pde->data = (void *)((long)disk); -+ } -+} -+ -+void -+sd_iostats_fini(void) -+{ -+ char name[6]; -+ int i; -+ int maxdevs = sd_template.dev_max; -+ -+ if (sd_iostats_procdir != NULL) { -+ for (i = 0; i < maxdevs; i++) { -+ sd_devname(i, name); -+ remove_proc_entry(name, sd_iostats_procdir); -+ } -+ -+ if (proc_scsi == NULL) { -+ printk(KERN_ERR "sd_iostats_fini: proc_scsi NULL\n"); -+ BUG(); -+ } -+ remove_proc_entry(sd_iostats_procdir_name, -+ proc_scsi); -+ -+ sd_iostats_procdir = NULL; -+ } -+ -+ if (sd_iostats != NULL) { -+ for (i = 0; i < maxdevs; i++) { -+ if (sd_iostats[i] != NULL) -+ kfree (sd_iostats[i]); -+ } -+ -+ kfree(sd_iostats); -+ sd_iostats = NULL; -+ } -+} -+ -+void -+sd_iostats_bump(int disk, unsigned int nsect, int iswrite) -+{ -+ iostat_stats_t *stats; -+ iostat_counter_t *counter; -+ int bucket; -+ int tmp; -+ unsigned long irqflags; -+ -+ if (sd_iostats == NULL) -+ return; -+ -+ if (disk < 0 || disk >= sd_template.dev_max) { -+ printk(KERN_ERR "sd_iostats_bump: unexpected disk index %d([0-%d])\n", -+ disk, sd_template.dev_max); -+ BUG(); -+ } -+ -+ for (bucket = 0, tmp = nsect; tmp > 1; bucket++) -+ tmp /= 2; -+ -+ if (bucket >= IOSTAT_NCOUNTERS) { -+ printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect); -+ BUG(); -+ } -+ -+ spin_lock_irqsave(&sd_iostats_lock, irqflags); -+ -+ stats = sd_iostats[disk]; -+ if (stats != NULL) { -+ counter = iswrite ? -+ &stats->iostat_write_histogram[bucket] : -+ &stats->iostat_read_histogram[bucket]; -+ -+ counter->iostat_size += nsect; -+ counter->iostat_count++; -+ } -+ -+ spin_unlock_irqrestore(&sd_iostats_lock, irqflags); -+} -+#endif -+ - static int __init init_sd(void) - { - sd_template.module = THIS_MODULE; -@@ -1569,6 +1936,7 @@ static void __exit exit_sd(void) - kfree(sd_blocksizes); - kfree(sd_hardsizes); - kfree(sd_varyio); -+ sd_iostats_fini(); - for (i = 0; i < N_USED_SD_MAJORS; i++) { - kfree(sd_gendisks[i].de_arr); - kfree(sd_gendisks[i].flags); diff --git a/lustre/kernel_patches/patches/slab-use-after-free-debug-2.4.24.patch b/lustre/kernel_patches/patches/slab-use-after-free-debug-2.4.24.patch deleted file mode 100644 index 05c0209..0000000 --- a/lustre/kernel_patches/patches/slab-use-after-free-debug-2.4.24.patch +++ /dev/null @@ -1,748 +0,0 @@ -%patch -Index: linux-2.4.24/mm/slab.c -=================================================================== ---- linux-2.4.24.orig/mm/slab.c 2004-02-06 11:15:22.000000000 +0300 -+++ linux-2.4.24/mm/slab.c 2004-02-07 00:42:38.000000000 +0300 -@@ -97,6 +97,8 @@ - #define FORCED_DEBUG 0 - #endif - -+#include -+ - /* - * Parameters for kmem_cache_reap - */ -@@ -825,6 +827,12 @@ - return cachep; - } - -+#ifdef CONFIG_DEBUG_UAF -+void * uaf_alloc(kmem_cache_t *, int gfp_mask); -+int uaf_cache_free(kmem_cache_t *, void *addr); -+int uaf_free(void *addr); -+struct page *uaf_vaddr_to_page(void *obj); -+#endif - - #if DEBUG - /* -@@ -1342,6 +1350,20 @@ - unsigned long save_flags; - void* objp; - -+#ifdef CONFIG_DEBUG_UAF -+ /* try to use uaf-allocator first */ -+ objp = uaf_alloc(cachep, flags); -+ if (objp) { -+ if (cachep->ctor) { -+ unsigned long ctor_flags; -+ ctor_flags = SLAB_CTOR_CONSTRUCTOR; -+ if (!(flags & __GFP_WAIT)) -+ ctor_flags |= SLAB_CTOR_ATOMIC; -+ cachep->ctor(objp, cachep, ctor_flags); -+ } -+ return objp; -+ } -+#endif - kmem_cache_alloc_head(cachep, flags); - try_again: - local_irq_save(save_flags); -@@ -1436,13 +1458,17 @@ - - if (cachep->flags & SLAB_RED_ZONE) { - objp -= BYTES_PER_WORD; -- if (xchg((unsigned long *)objp, RED_MAGIC1) != RED_MAGIC2) -+ if (xchg((unsigned long *)objp, RED_MAGIC1) != RED_MAGIC2) { - /* Either write before start, or a double free. */ -+ printk("inconsistency at start of %s\n", cachep->name); - BUG(); -+ } - if (xchg((unsigned long *)(objp+cachep->objsize - -- BYTES_PER_WORD), RED_MAGIC1) != RED_MAGIC2) -+ BYTES_PER_WORD), RED_MAGIC1) != RED_MAGIC2) { - /* Either write past end, or a double free. */ -+ printk("inconsistency at end of %s\n", cachep->name); - BUG(); -+ } - } - if (cachep->flags & SLAB_POISON) - kmem_poison_obj(cachep, objp); -@@ -1578,6 +1604,10 @@ - void kmem_cache_free (kmem_cache_t *cachep, void *objp) - { - unsigned long flags; -+#ifdef CONFIG_DEBUG_UAF -+ if (uaf_cache_free(cachep, objp)) -+ return; -+#endif - #if DEBUG - CHECK_PAGE(virt_to_page(objp)); - if (cachep != GET_PAGE_CACHE(virt_to_page(objp))) -@@ -1603,6 +1633,10 @@ - - if (!objp) - return; -+#ifdef CONFIG_DEBUG_UAF -+ if (uaf_free((void *) objp)) -+ return; -+#endif - local_irq_save(flags); - CHECK_PAGE(virt_to_page(objp)); - c = GET_PAGE_CACHE(virt_to_page(objp)); -@@ -2078,3 +2112,471 @@ - #endif - } - #endif -+ -+ -+ -+#ifdef CONFIG_DEBUG_UAF -+ -+#define MAX_UAF_OBJ_SIZE 8 /* in pages */ -+#define UAF_ASSERT(xxx) if (!(xxx)) BUG(); -+#define UAF_DEBUG__ -+#ifdef UAF_DEBUG -+#define uaf_printk(fmt,a...) printk(fmt, ##a) -+#else -+#define uaf_printk(a,...) -+#endif -+ -+struct uaf_stats { -+ atomic_t uaf_allocated; -+ atomic_t uaf_allocations; -+ atomic_t uaf_failed; -+}; -+ -+static int uaf_max = 32768; -+static void *uaf_bitmap = NULL; -+static spinlock_t uaf_lock; -+static int uaf_last_found = 0; -+static int uaf_used = 0; -+static struct vm_struct *uaf_area = NULL; -+static struct uaf_stats uaf_stats[MAX_UAF_OBJ_SIZE + 1]; -+ -+static int __init uaf_setup(char *str) -+{ -+ uaf_max = simple_strtoul(str, NULL, 0); -+ return 1; -+} -+ -+__setup("uaf=", uaf_setup); -+ -+ -+void uaf_init(void) -+{ -+ int size; -+ -+ printk("UAF: total vmalloc-space - %lu\n", -+ VMALLOC_END - VMALLOC_START); -+ -+ uaf_area = get_vm_area(PAGE_SIZE * uaf_max, VM_ALLOC); -+ if (!uaf_area) { -+ printk(KERN_ALERT "UAF: can't reserve %lu bytes in KVA\n", -+ PAGE_SIZE * uaf_max); -+ return; -+ } -+ -+ printk("UAF: reserved %lu bytes in KVA at 0x%p\n", -+ PAGE_SIZE * uaf_max, uaf_area->addr); -+ -+ /* how many bytes we need to track space usage? */ -+ size = uaf_max / 8 + 8; -+ -+ uaf_bitmap = vmalloc(size); -+ if (!uaf_bitmap) { -+ printk(KERN_ALERT -+ "UAF: can't allocate %d bytes for bitmap\n", size); -+ return; -+ } -+ memset(uaf_bitmap, 0, size); -+ spin_lock_init(&uaf_lock); -+ memset(uaf_stats, 0, sizeof(uaf_stats)); -+ -+ printk("UAF: allocated %d for bitmap\n", size); -+} -+ -+static int uaf_find(int len) -+{ -+ int new_last_found = -1; -+ int loop = 0; -+ int i, j; -+ -+ j = uaf_last_found; -+ -+ do { -+ i = find_next_zero_bit(uaf_bitmap, uaf_max, j); -+ if (i >= uaf_max) { -+ /* repeat from 0 */ -+ if (++loop > 1) { -+ /* this is 2nd loop and it's useless */ -+ return -1; -+ } -+ -+ i = find_next_zero_bit(uaf_bitmap, uaf_max, 0); -+ if (i >= uaf_max) -+ return -1; -+ -+ /* save found num for subsequent searches */ -+ if (new_last_found == -1) -+ new_last_found = uaf_last_found = i; -+ UAF_ASSERT(new_last_found < uaf_max); -+ } -+ -+ /* -+ * OK. found first zero bit. -+ * now, try to find requested cont. zero-space -+ */ -+ -+ /* FIXME: implmement multipage allocation! */ -+ break; -+ -+ /* -+ j = find_next_bit(uaf_bitmap, uaf_max, i); -+ if (++loop2 > 10000) { -+ printk("ALERT: loop2=%d\n", loop2); -+ return -1; -+ } -+ */ -+ } while (j - i < len); -+ -+ /* found! */ -+ if (new_last_found == -1) -+ uaf_last_found = i + 1; -+ if (uaf_last_found >= uaf_max) -+ uaf_last_found = 0; -+ return i; -+} -+ -+extern int __vmalloc_area_pages (unsigned long address, unsigned long size, -+ int gfp_mask, pgprot_t prot, -+ struct page ***pages); -+void * uaf_alloc(kmem_cache_t *cachep, int gfp_mask) -+{ -+ struct page *ptrs[MAX_UAF_OBJ_SIZE]; -+ int size = cachep->objsize; -+ struct page **pages; -+ unsigned long flags; -+ unsigned long addr; -+ int i, j, err = -2000; -+ -+ if (uaf_bitmap == NULL) -+ return NULL; -+ -+ if (!(cachep->flags & SLAB_USE_UAF)) -+ return NULL; -+ -+ pages = (struct page **) ptrs; -+ size = (size + (PAGE_SIZE - 1)) / PAGE_SIZE; -+ /* FIXME: implement multipage allocation! */ -+ if (size > 1) -+ return NULL; -+ if (size > MAX_UAF_OBJ_SIZE) { -+ printk(KERN_ALERT "size is too big: %d\n", size); -+ return NULL; -+ } -+ -+ if (uaf_used == uaf_max) { -+ uaf_printk("UAF: space exhausted!\n"); -+ atomic_inc(&uaf_stats[size].uaf_failed); -+ return NULL; -+ } -+ -+ -+ spin_lock_irqsave(&uaf_lock, flags); -+ i = uaf_find(size); -+ if (i < 0) { -+ spin_unlock_irqrestore(&uaf_lock, flags); -+ atomic_inc(&uaf_stats[size].uaf_failed); -+ return NULL; -+ } -+ for (j = 0; j < size; j++) { -+ UAF_ASSERT(!test_bit(i + j, uaf_bitmap)); -+ set_bit(i + j, uaf_bitmap); -+ uaf_used++; -+ } -+ spin_unlock_irqrestore(&uaf_lock, flags); -+ -+ addr = ((unsigned long) uaf_area->addr) + (PAGE_SIZE * i); -+ uaf_printk("UAF: found %d/%d, base 0x%p, map at 0x%lx: ", i, -+ size, uaf_area->addr, addr); -+ -+ /* OK. we've found free space, let's allocate pages */ -+ memset(pages, 0, sizeof(struct page *) * MAX_UAF_OBJ_SIZE); -+ for (j = 0; j < size; j++) { -+ pages[j] = alloc_page(gfp_mask); -+ if (pages[j] == NULL) -+ goto nomem; -+ uaf_printk("0x%p ", pages[j]); -+ } -+ -+ /* time to map just allocated pages */ -+ err = __vmalloc_area_pages(addr, PAGE_SIZE * size, gfp_mask, -+ PAGE_KERNEL, &pages); -+ pages = (struct page **) ptrs; -+ if (err == 0) { -+ /* put slab cache pointer in first page */ -+ ptrs[0]->list.next = (void *) cachep; -+ uaf_printk(" -> 0x%lx\n", addr); -+ atomic_inc(&uaf_stats[size].uaf_allocated); -+ atomic_inc(&uaf_stats[size].uaf_allocations); -+ if (!in_interrupt() && !in_softirq()) -+ flush_tlb_all(); -+ else -+ local_flush_tlb(); -+ size = cachep->objsize; -+ if (size < PAGE_SIZE) -+ memset((char *) addr + size, 0xa7, PAGE_SIZE - size); -+ return (void *) addr; -+ } -+ -+nomem: -+ printk(KERN_ALERT "can't map pages: %d\n", err); -+ for (j = 0; j < size; j++) -+ if (pages[j]) -+ __free_page(pages[j]); -+ -+ /* can't find free pages */ -+ spin_lock_irqsave(&uaf_lock, flags); -+ for (j = 0; j < size; j++) { -+ clear_bit(i + j, uaf_bitmap); -+ uaf_used--; -+ } -+ spin_unlock_irqrestore(&uaf_lock, flags); -+ atomic_inc(&uaf_stats[size].uaf_failed); -+ -+ return NULL; -+} -+ -+extern void free_area_pmd(pgd_t *dir, unsigned long address, -+ unsigned long size); -+static void uaf_unmap(unsigned long address, unsigned long size) -+{ -+ unsigned long end = (address + size); -+ pgd_t *dir; -+ -+ dir = pgd_offset_k(address); -+ flush_cache_all(); -+ do { -+ free_area_pmd(dir, address, end - address); -+ address = (address + PGDIR_SIZE) & PGDIR_MASK; -+ dir++; -+ } while (address && (address < end)); -+ -+ /* -+ * we must not call smp_call_function() with interrtups disabled -+ * otherwise we can get into deadlock -+ */ -+ if (!in_interrupt() && !in_softirq()) -+ flush_tlb_all(); -+ else -+ local_flush_tlb(); -+} -+ -+/* -+ * returns 1 if free was successfull -+ */ -+int uaf_cache_free(kmem_cache_t *cachep, void *addr) -+{ -+ struct page *pages[MAX_UAF_OBJ_SIZE]; -+ int size = cachep->objsize; -+ unsigned long flags; -+ int i, j; -+ -+ uaf_printk("UAF: to free 0x%p/%d\n", addr, size); -+ -+ size = (size + (PAGE_SIZE - 1)) / PAGE_SIZE; -+ if (size > MAX_UAF_OBJ_SIZE) -+ return 0; -+ -+ if (uaf_bitmap == NULL) -+ return 0; -+ -+ /* first, check is address is in UAF space */ -+ if ((unsigned) addr < (unsigned) uaf_area->addr || -+ (unsigned) addr >= (unsigned) uaf_area->addr + uaf_area->size) -+ return 0; -+ -+ if (cachep->objsize < PAGE_SIZE) { -+ unsigned char *a = (void *) addr; -+ for (i = 0; i < PAGE_SIZE - cachep->objsize; i++) -+ if (a[cachep->objsize + i] != 0xa7) { -+ printk("corruption(0x%x) at %u in %s/0x%p\n", -+ (unsigned) a[cachep->objsize + i], -+ cachep->objsize + i, cachep->name, addr); -+ BUG(); -+ } -+ } -+ UAF_ASSERT(((unsigned long) addr & ~PAGE_MASK) == 0UL); -+ -+ /* calculate placement in bitmap */ -+ i = (unsigned) addr - (unsigned) uaf_area->addr; -+ UAF_ASSERT(i >= 0); -+ i = i / PAGE_SIZE; -+ -+ /* collect all the pages */ -+ uaf_printk("free/unmap %d pages: ", size); -+ /* NOTE: we need not page_table_lock here. bits in bitmap -+ * protect those pte's from to be reused */ -+ for (j = 0; j < size; j++) { -+ unsigned long address; -+ address = ((unsigned long) addr) + (PAGE_SIZE * j); -+ pages[j] = vmalloc_to_page((void *) address); -+ uaf_printk("0x%lx->0x%p ", address, pages[j]); -+ } -+ uaf_printk("\n"); -+ -+ uaf_unmap((unsigned long) addr, PAGE_SIZE * size); -+ /* free all the pages */ -+ for (j = 0; j < size; j++) -+ __free_page(pages[j]); -+ -+ spin_lock_irqsave(&uaf_lock, flags); -+ for (j = 0; j < size; j++) { -+ /* now check is correspondend bit set */ -+ UAF_ASSERT(i+j >= 0 && i+j < uaf_max); -+ UAF_ASSERT(test_bit(i+j, uaf_bitmap)); -+ -+ /* now free space in UAF */ -+ clear_bit(i+j, uaf_bitmap); -+ uaf_used--; -+ } -+ spin_unlock_irqrestore(&uaf_lock, flags); -+ -+ atomic_dec(&uaf_stats[size].uaf_allocated); -+ -+ uaf_printk("UAF: freed %d/%d at 0x%p\n", i, size, addr); -+ //printk("UAF: freed %d/%d at 0x%p\n", i, size, addr); -+ -+ return 1; -+} -+ -+struct page *uaf_vaddr_to_page(void *obj) -+{ -+ if (uaf_bitmap == NULL) -+ return NULL; -+ -+ /* first, check is address is in UAF space */ -+ if ((unsigned) obj < (unsigned) uaf_area->addr || -+ (unsigned) obj >= (unsigned) uaf_area->addr + uaf_area->size) -+ return NULL; -+ -+ return vmalloc_to_page(obj); -+} -+ -+int uaf_free(void *obj) -+{ -+ struct page *page = uaf_vaddr_to_page((void *) obj); -+ kmem_cache_t *c; -+ -+ if (!page) -+ return 0; -+ -+ c = GET_PAGE_CACHE(page); -+ return uaf_cache_free(c, (void *) obj); -+} -+ -+int uaf_is_allocated(void *obj) -+{ -+ unsigned long addr = (unsigned long) obj; -+ int i; -+ -+ if (uaf_bitmap == NULL) -+ return 0; -+ -+ addr &= PAGE_MASK; -+ /* first, check is address is in UAF space */ -+ if (addr < (unsigned long) uaf_area->addr || -+ addr >= (unsigned long) uaf_area->addr + uaf_area->size) -+ return 0; -+ -+ /* calculate placement in bitmap */ -+ i = (unsigned) addr - (unsigned) uaf_area->addr; -+ i = i / PAGE_SIZE; -+ return test_bit(i, uaf_bitmap); -+} -+ -+static void *uaf_s_start(struct seq_file *m, loff_t *pos) -+{ -+ loff_t n = *pos; -+ -+ if (!n) -+ seq_printf(m, "size(pgs) allocated failed allocations. " -+ "%d reserved, %d in use, %d last\n", -+ uaf_max, uaf_used, uaf_last_found); -+ else if (n > MAX_UAF_OBJ_SIZE) -+ return NULL; -+ -+ *pos = 1; -+ return (void *) 1; -+} -+ -+static void *uaf_s_next(struct seq_file *m, void *p, loff_t *pos) -+{ -+ unsigned long n = *pos; -+ ++*pos; -+ if (n + 1 > MAX_UAF_OBJ_SIZE) -+ return NULL; -+ return (void *) (n + 1); -+} -+ -+static void uaf_s_stop(struct seq_file *m, void *p) -+{ -+} -+ -+static int uaf_s_show(struct seq_file *m, void *p) -+{ -+ int n = (int) p; -+ -+ if (n > MAX_UAF_OBJ_SIZE) -+ return 0; -+ seq_printf(m, "%d %d %d %d\n", n, -+ atomic_read(&uaf_stats[n].uaf_allocated), -+ atomic_read(&uaf_stats[n].uaf_failed), -+ atomic_read(&uaf_stats[n].uaf_allocations)); -+ return 0; -+} -+ -+struct seq_operations uafinfo_op = { -+ .start = uaf_s_start, -+ .next = uaf_s_next, -+ .stop = uaf_s_stop, -+ .show = uaf_s_show, -+}; -+ -+ssize_t uafinfo_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ char kbuf[MAX_SLABINFO_WRITE+1], *tmp; -+ char *key, *name; -+ int res; -+ struct list_head *p; -+ -+ if (count > MAX_SLABINFO_WRITE) -+ return -EINVAL; -+ if (copy_from_user(&kbuf, buffer, count)) -+ return -EFAULT; -+ kbuf[MAX_SLABINFO_WRITE] = '\0'; -+ -+ tmp = kbuf; -+ key = strsep(&tmp, " \t\n"); -+ if (!key) -+ return -EINVAL; -+ if (!strcmp(key, "on")) -+ res = 1; -+ else if (!strcmp(key, "off")) -+ res = 0; -+ else -+ return -EINVAL; -+ -+ name = strsep(&tmp, " \t\n"); -+ if (!name) -+ return -EINVAL; -+ -+ /* Find the cache in the chain of caches. */ -+ down(&cache_chain_sem); -+ list_for_each(p,&cache_chain) { -+ kmem_cache_t *cachep = list_entry(p, kmem_cache_t, next); -+ -+ if (!strcmp(cachep->name, name)) { -+ if (res) { -+ printk("UAF: use on %s\n", cachep->name); -+ cachep->flags |= SLAB_USE_UAF; -+ } else { -+ printk("UAF: dont use on %s\n", cachep->name); -+ cachep->flags &= ~SLAB_USE_UAF; -+ } -+ break; -+ } -+ } -+ up(&cache_chain_sem); -+ return count; -+} -+#endif -+ -Index: linux-2.4.24/mm/vmalloc.c -=================================================================== ---- linux-2.4.24.orig/mm/vmalloc.c 2004-01-10 17:05:20.000000000 +0300 -+++ linux-2.4.24/mm/vmalloc.c 2004-02-06 11:17:09.000000000 +0300 -@@ -53,7 +53,7 @@ - } while (address < end); - } - --static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned long size) -+void free_area_pmd(pgd_t * dir, unsigned long address, unsigned long size) - { - pmd_t * pmd; - unsigned long end; -@@ -152,7 +152,7 @@ - return 0; - } - --static inline int __vmalloc_area_pages (unsigned long address, -+int __vmalloc_area_pages (unsigned long address, - unsigned long size, - int gfp_mask, - pgprot_t prot, -Index: linux-2.4.24/init/main.c -=================================================================== ---- linux-2.4.24.orig/init/main.c 2004-01-10 17:05:59.000000000 +0300 -+++ linux-2.4.24/init/main.c 2004-02-06 11:17:43.000000000 +0300 -@@ -437,6 +437,9 @@ - #if defined(CONFIG_SYSVIPC) - ipc_init(); - #endif -+#ifdef CONFIG_DEBUG_UAF -+ uaf_init(); -+#endif - rest_init(); - } - -Index: linux-2.4.24/fs/proc/proc_misc.c -=================================================================== ---- linux-2.4.24.orig/fs/proc/proc_misc.c 2004-01-10 17:05:55.000000000 +0300 -+++ linux-2.4.24/fs/proc/proc_misc.c 2004-02-06 11:35:27.000000000 +0300 -@@ -303,6 +303,22 @@ - release: seq_release, - }; - -+#ifdef CONFIG_DEBUG_UAF -+extern struct seq_operations uafinfo_op; -+extern ssize_t uafinfo_write(struct file *, const char *, size_t, loff_t *); -+static int uafinfo_open(struct inode *inode, struct file *file) -+{ -+ return seq_open(file, &uafinfo_op); -+} -+static struct file_operations proc_uafinfo_operations = { -+ .open = uafinfo_open, -+ .read = seq_read, -+ .write = uafinfo_write, -+ .llseek = seq_lseek, -+ .release = seq_release, -+}; -+#endif -+ - static int kstat_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) - { -@@ -640,6 +656,9 @@ - create_seq_entry("iomem", 0, &proc_iomem_operations); - create_seq_entry("partitions", 0, &proc_partitions_operations); - create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); -+#ifdef CONFIG_DEBUG_UAF -+ create_seq_entry("uafinfo",S_IWUSR|S_IRUGO,&proc_uafinfo_operations); -+#endif - #ifdef CONFIG_MODULES - create_seq_entry("ksyms", 0, &proc_ksyms_operations); - #endif -Index: linux-2.4.24/include/linux/slab.h -=================================================================== ---- linux-2.4.24.orig/include/linux/slab.h 2004-01-29 15:01:10.000000000 +0300 -+++ linux-2.4.24/include/linux/slab.h 2004-02-06 11:18:26.000000000 +0300 -@@ -40,6 +40,7 @@ - #define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */ - #define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */ - #define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */ -+#define SLAB_USE_UAF 0x00040000UL /* use UAF allocator */ - - /* flags passed to a constructor func */ - #define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */ -Index: linux-2.4.24/include/asm-i386/io.h -=================================================================== ---- linux-2.4.24.orig/include/asm-i386/io.h 2004-01-29 15:01:10.000000000 +0300 -+++ linux-2.4.24/include/asm-i386/io.h 2004-02-06 11:18:26.000000000 +0300 -@@ -75,6 +75,16 @@ - - static inline unsigned long virt_to_phys(volatile void * address) - { -+#ifdef CONFIG_DEBUG_UAF -+ unsigned long addr = (unsigned long) address; -+ if (vmlist && addr >= VMALLOC_START && addr < VMALLOC_END) { -+ struct page *page = vmalloc_to_page((void *) address); -+ if (page) { -+ unsigned long offset = addr & ~PAGE_MASK; -+ address = page_address(page) + offset; -+ } -+ } -+#endif - return __pa(address); - } - -Index: linux-2.4.24/include/asm-i386/page.h -=================================================================== ---- linux-2.4.24.orig/include/asm-i386/page.h 2004-01-14 02:58:46.000000000 +0300 -+++ linux-2.4.24/include/asm-i386/page.h 2004-02-06 11:17:09.000000000 +0300 -@@ -131,9 +131,49 @@ - #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE) - #define __MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE) - #define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)) -+ -+#ifndef CONFIG_DEBUG_UAF - #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) - #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) - #define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) -+#else -+#define __pa(x) ({ \ -+ unsigned long __pn, __fr; \ -+ __pn = (unsigned long)(x)-PAGE_OFFSET; \ -+ __fr = __pn >> PAGE_SHIFT; \ -+ if (jiffies > HZ*3 && __fr >= max_mapnr) { \ -+ printk("invalid arg __pa(0x%x)" \ -+ " at %s:%d\n", (unsigned) (x), \ -+ __FILE__, __LINE__); \ -+ dump_stack(); \ -+ } \ -+ __pn; \ -+ }) -+ -+#define __va(x) ({ \ -+ unsigned long __pn; \ -+ __pn = (unsigned long) (x) >> PAGE_SHIFT; \ -+ if (jiffies > HZ*3 && __pn >= max_mapnr) { \ -+ printk("invalid arg __va(0x%x)" \ -+ " at %s:%d\n", (unsigned) (x), \ -+ __FILE__, __LINE__); \ -+ dump_stack(); \ -+ } \ -+ ((void *)((unsigned long)(x) + PAGE_OFFSET)); \ -+ }) -+ -+#define virt_to_page(ka) ({ \ -+ struct page *_p; \ -+ if ((unsigned long)(ka) >= VMALLOC_START) { \ -+ _p = vmalloc_to_page((void *)(ka)); \ -+ BUG_ON(!_p); \ -+ } else \ -+ _p = mem_map+(__pa(ka) >> PAGE_SHIFT); \ -+ (_p); \ -+ }) -+#endif -+ -+ - #define VALID_PAGE(page) ((page - mem_map) < max_mapnr) - - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ -Index: linux-2.4.24/arch/i386/config.in -=================================================================== ---- linux-2.4.24.orig/arch/i386/config.in 2004-01-14 02:58:46.000000000 +0300 -+++ linux-2.4.24/arch/i386/config.in 2004-02-06 11:17:09.000000000 +0300 -@@ -508,6 +508,9 @@ - bool ' Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW - bool ' Debug high memory support' CONFIG_DEBUG_HIGHMEM - bool ' Debug memory allocations' CONFIG_DEBUG_SLAB -+ if [ "$CONFIG_DEBUG_SLAB" != "n" ]; then -+ bool ' Debug memory allocations (use-after-free via vmalloced space)' CONFIG_DEBUG_UAF -+ fi - bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT - bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ - bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK - -%diffstat - arch/i386/config.in | 3 - fs/proc/proc_misc.c | 19 + - include/asm-i386/io.h | 10 - include/asm-i386/page.h | 40 +++ - include/linux/slab.h | 1 - init/main.c | 3 - mm/slab.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++- - mm/vmalloc.c | 4 - 8 files changed, 582 insertions(+), 4 deletions(-) - diff --git a/lustre/kernel_patches/patches/socket-exports-vanilla.patch b/lustre/kernel_patches/patches/socket-exports-vanilla.patch deleted file mode 100644 index 9dd5008..0000000 --- a/lustre/kernel_patches/patches/socket-exports-vanilla.patch +++ /dev/null @@ -1,42 +0,0 @@ - include/linux/socket.h | 4 ++++ - net/netsyms.c | 2 ++ - net/socket.c | 2 +- - 3 files changed, 7 insertions(+), 1 deletion(-) - ---- linux-2.4.20-l18/include/linux/socket.h~socket-exports-vanilla Fri Aug 22 15:43:58 2003 -+++ linux-2.4.20-l18-phil/include/linux/socket.h Fri Aug 22 16:26:37 2003 -@@ -260,6 +260,10 @@ extern void memcpy_tokerneliovec(struct - extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen); - extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr); - extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); -+struct socket; -+extern int sock_map_fd(struct socket *sock); -+extern struct socket *sockfd_lookup(int fd, int *err); -+ - #endif - #endif /* not kernel and not glibc */ - #endif /* _LINUX_SOCKET_H */ ---- linux-2.4.20-l18/net/netsyms.c~socket-exports-vanilla Fri Aug 22 15:43:58 2003 -+++ linux-2.4.20-l18-phil/net/netsyms.c Fri Aug 22 16:25:04 2003 -@@ -159,6 +159,8 @@ EXPORT_SYMBOL(datagram_poll); - EXPORT_SYMBOL(put_cmsg); - EXPORT_SYMBOL(sock_kmalloc); - EXPORT_SYMBOL(sock_kfree_s); -+EXPORT_SYMBOL(sockfd_lookup); -+EXPORT_SYMBOL(sock_map_fd); - - #ifdef CONFIG_FILTER - EXPORT_SYMBOL(sk_run_filter); ---- linux-2.4.20-l18/net/socket.c~socket-exports-vanilla Fri Aug 22 15:43:58 2003 -+++ linux-2.4.20-l18-phil/net/socket.c Fri Aug 22 16:25:04 2003 -@@ -325,7 +325,7 @@ static struct dentry_operations sockfs_d - * but we take care of internal coherence yet. - */ - --static int sock_map_fd(struct socket *sock) -+int sock_map_fd(struct socket *sock) - { - int fd; - struct qstr this; - -_ diff --git a/lustre/kernel_patches/patches/statfs64-cast-unsigned-2.4-rhel.patch b/lustre/kernel_patches/patches/statfs64-cast-unsigned-2.4-rhel.patch deleted file mode 100644 index a1063ae..0000000 --- a/lustre/kernel_patches/patches/statfs64-cast-unsigned-2.4-rhel.patch +++ /dev/null @@ -1,28 +0,0 @@ -Index: linux-2.4.21/fs/open.c -=================================================================== ---- linux-2.4.21.orig/fs/open.c 2005-05-04 16:09:11.702098704 -0400 -+++ linux-2.4.21/fs/open.c 2005-05-04 16:17:31.597103112 -0400 -@@ -92,15 +92,15 @@ - if (retval) - return retval; - /* Stuff the 32 bit values into the 64 bit struct */ -- buf->f_type = st.f_type; -- buf->f_bsize = st.f_bsize; -- buf->f_blocks = st.f_blocks; -- buf->f_bfree = st.f_bfree; -- buf->f_bavail = st.f_bavail; -- buf->f_files = st.f_files; -- buf->f_ffree = st.f_ffree; -+ buf->f_type = (unsigned long) st.f_type; -+ buf->f_bsize = (unsigned long) st.f_bsize; -+ buf->f_blocks = (unsigned long) st.f_blocks; -+ buf->f_bfree = (unsigned long) st.f_bfree; -+ buf->f_bavail = (unsigned long) st.f_bavail; -+ buf->f_files = (unsigned long) st.f_files; -+ buf->f_ffree = (unsigned long) st.f_ffree; - buf->f_fsid = st.f_fsid; -- buf->f_namelen = st.f_namelen; -+ buf->f_namelen = (unsigned long) st.f_namelen; - memset(buf->f_spare, 0, sizeof(buf->f_spare)); - } - return 0; diff --git a/lustre/kernel_patches/patches/uml-2.4.20-do_mmap_pgoff-fix.patch b/lustre/kernel_patches/patches/uml-2.4.20-do_mmap_pgoff-fix.patch deleted file mode 100644 index 844d735..0000000 --- a/lustre/kernel_patches/patches/uml-2.4.20-do_mmap_pgoff-fix.patch +++ /dev/null @@ -1,16 +0,0 @@ - arch/i386/kernel/sys_i386.c | 2 +- - 1 files changed, 1 insertion(+), 1 deletion(-) - ---- linux-2.4.20-vanilla/arch/i386/kernel/sys_i386.c~uml-2.4.20-do_mmap_pgoff-fix 2001-03-19 23:35:09.000000000 +0300 -+++ linux-2.4.20-vanilla-alexey/arch/i386/kernel/sys_i386.c 2003-09-15 10:26:19.000000000 +0400 -@@ -56,7 +56,7 @@ static inline long do_mmap2( - } - - down_write(¤t->mm->mmap_sem); -- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); -+ error = do_mmap_pgoff(current->mm, file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - -_ diff --git a/lustre/kernel_patches/patches/uml-patch-2.4.24-1.patch b/lustre/kernel_patches/patches/uml-patch-2.4.24-1.patch deleted file mode 100644 index e74862c..0000000 --- a/lustre/kernel_patches/patches/uml-patch-2.4.24-1.patch +++ /dev/null @@ -1,41972 +0,0 @@ -diff -Naur -X ../exclude-files orig/arch/um/common.ld.in um/arch/um/common.ld.in ---- orig/arch/um/common.ld.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/common.ld.in 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,53 @@ -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ .unprotected : { *(.unprotected) } -+ . = ALIGN(4096); -+ PROVIDE (_unprotected_end = .); -+ -+ . = ALIGN(4096); -+ __uml_setup_start = .; -+ .uml.setup.init : { *(.uml.setup.init) } -+ __uml_setup_end = .; -+ __uml_help_start = .; -+ .uml.help.init : { *(.uml.help.init) } -+ __uml_help_end = .; -+ __uml_postsetup_start = .; -+ .uml.postsetup.init : { *(.uml.postsetup.init) } -+ __uml_postsetup_end = .; -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ __uml_initcall_start = .; -+ .uml.initcall.init : { *(.uml.initcall.init) } -+ __uml_initcall_end = .; -+ __init_end = .; -+ __exitcall_begin = .; -+ .exitcall : { *(.exitcall.exit) } -+ __exitcall_end = .; -+ __uml_exitcall_begin = .; -+ .uml.exitcall : { *(.uml.exitcall.exit) } -+ __uml_exitcall_end = .; -+ -+ __preinit_array_start = .; -+ .preinit_array : { *(.preinit_array) } -+ __preinit_array_end = .; -+ __init_array_start = .; -+ .init_array : { *(.init_array) } -+ __init_array_end = .; -+ __fini_array_start = .; -+ .fini_array : { *(.fini_array) } -+ __fini_array_end = .; -+ -+ .data.init : { *(.data.init) } -diff -Naur -X ../exclude-files orig/arch/um/config_block.in um/arch/um/config_block.in ---- orig/arch/um/config_block.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/config_block.in 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,22 @@ -+mainmenu_option next_comment -+comment 'Block Devices' -+ -+bool 'Virtual block device' CONFIG_BLK_DEV_UBD -+dep_bool ' Always do synchronous disk IO for UBD' CONFIG_BLK_DEV_UBD_SYNC $CONFIG_BLK_DEV_UBD -+bool 'COW device' CONFIG_COW -+ -+if [ "$CONFIG_BLK_DEV_UBD" = "y" -o "$CONFIG_COW" = "y" ] ; then -+ define_bool CONFIG_COW_COMMON y -+fi -+ -+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET -+tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -+if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then -+ int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 -+fi -+dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM -+ -+tristate 'Example IO memory driver' CONFIG_MMAPPER -+ -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config_char.in um/arch/um/config_char.in ---- orig/arch/um/config_char.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/config_char.in 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,37 @@ -+mainmenu_option next_comment -+comment 'Character Devices' -+ -+define_bool CONFIG_STDIO_CONSOLE y -+ -+bool 'Virtual serial line' CONFIG_SSL -+ -+bool 'file descriptor channel support' CONFIG_FD_CHAN -+bool 'null channel support' CONFIG_NULL_CHAN -+bool 'port channel support' CONFIG_PORT_CHAN -+bool 'pty channel support' CONFIG_PTY_CHAN -+bool 'tty channel support' CONFIG_TTY_CHAN -+bool 'xterm channel support' CONFIG_XTERM_CHAN -+string 'Default main console channel initialization' CONFIG_CON_ZERO_CHAN \ -+ "fd:0,fd:1" -+string 'Default console channel initialization' CONFIG_CON_CHAN "xterm" -+string 'Default serial line channel initialization' CONFIG_SSL_CHAN "pty" -+ -+ -+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS -+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then -+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 -+fi -+ -+bool 'Watchdog Timer Support' CONFIG_WATCHDOG -+dep_bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT \ -+ $CONFIG_WATCHDOG -+dep_tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG $CONFIG_WATCHDOG -+dep_tristate ' UML watchdog' CONFIG_UML_WATCHDOG $CONFIG_WATCHDOG -+ -+tristate 'Sound support' CONFIG_UML_SOUND -+define_tristate CONFIG_SOUND $CONFIG_UML_SOUND -+define_tristate CONFIG_HOSTAUDIO $CONFIG_UML_SOUND -+ -+bool 'Enable tty logging' CONFIG_TTY_LOG -+ -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config.in um/arch/um/config.in ---- orig/arch/um/config.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/config.in 2003-12-14 11:34:02.000000000 -0500 -@@ -0,0 +1,105 @@ -+define_bool CONFIG_USERMODE y -+ -+mainmenu_name "Linux/Usermode Kernel Configuration" -+ -+define_bool CONFIG_ISA n -+define_bool CONFIG_SBUS n -+define_bool CONFIG_PCI n -+ -+define_bool CONFIG_UID16 y -+ -+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y -+ -+mainmenu_option next_comment -+comment 'Code maturity level options' -+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL -+endmenu -+ -+mainmenu_option next_comment -+comment 'General Setup' -+ -+bool 'Separate kernel address space support' CONFIG_MODE_SKAS -+ -+# This is to ensure that at least one of the modes is enabled. When neither -+# is present in defconfig, they default to N, which is bad. -+if [ "$CONFIG_MODE_SKAS" != "y" ]; then -+ define_bool CONFIG_MODE_TT y -+fi -+ -+bool 'Tracing thread support' CONFIG_MODE_TT -+if [ "$CONFIG_MODE_TT" != "y" ]; then -+ bool 'Statically linked binary when CONFIG_MODE_TT is disabled' CONFIG_STATIC_LINK -+fi -+bool 'Networking support' CONFIG_NET -+bool 'System V IPC' CONFIG_SYSVIPC -+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT -+bool 'Sysctl support' CONFIG_SYSCTL -+tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF -+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -+tristate 'Host filesystem' CONFIG_HOSTFS -+tristate 'Honeypot proc filesystem' CONFIG_HPPFS -+bool 'Management console' CONFIG_MCONSOLE -+dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE -+bool '2G/2G host address space split' CONFIG_HOST_2G_2G -+bool 'Symmetric multi-processing support' CONFIG_UML_SMP -+define_bool CONFIG_SMP $CONFIG_UML_SMP -+int 'Nesting level' CONFIG_NEST_LEVEL 0 -+int 'Kernel address space size (in .5G units)' CONFIG_KERNEL_HALF_GIGS 1 -+bool 'Highmem support' CONFIG_HIGHMEM -+bool '/proc/mm' CONFIG_PROC_MM -+int 'Kernel stack size order' CONFIG_KERNEL_STACK_ORDER 2 -+bool 'Real-time Clock' CONFIG_UML_REAL_TIME_CLOCK -+endmenu -+ -+mainmenu_option next_comment -+comment 'Loadable module support' -+bool 'Enable loadable module support' CONFIG_MODULES -+if [ "$CONFIG_MODULES" = "y" ]; then -+# MODVERSIONS does not yet work in this architecture -+# bool ' Set version information on all module symbols' CONFIG_MODVERSIONS -+ bool ' Kernel module loader' CONFIG_KMOD -+fi -+endmenu -+ -+source arch/um/config_char.in -+ -+source arch/um/config_block.in -+ -+define_bool CONFIG_NETDEVICES $CONFIG_NET -+ -+if [ "$CONFIG_NET" = "y" ]; then -+ source arch/um/config_net.in -+ source net/Config.in -+fi -+ -+source fs/Config.in -+ -+mainmenu_option next_comment -+comment 'SCSI support' -+ -+tristate 'SCSI support' CONFIG_SCSI -+ -+if [ "$CONFIG_SCSI" != "n" ]; then -+ source arch/um/config_scsi.in -+fi -+endmenu -+ -+source drivers/md/Config.in -+ -+source drivers/mtd/Config.in -+ -+source lib/Config.in -+ -+mainmenu_option next_comment -+comment 'Kernel hacking' -+bool 'Debug memory allocations' CONFIG_DEBUG_SLAB -+bool 'Enable kernel debugging symbols' CONFIG_DEBUGSYM -+if [ "$CONFIG_XTERM_CHAN" = "y" ]; then -+ dep_bool 'Enable ptrace proxy' CONFIG_PT_PROXY $CONFIG_DEBUGSYM -+else -+ define_bool CONFIG_PT_PROXY n -+fi -+dep_bool 'Enable gprof support' CONFIG_GPROF $CONFIG_DEBUGSYM -+dep_bool 'Enable gcov support' CONFIG_GCOV $CONFIG_DEBUGSYM -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config_net.in um/arch/um/config_net.in ---- orig/arch/um/config_net.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/config_net.in 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,47 @@ -+mainmenu_option next_comment -+comment 'Network Devices' -+ -+# UML virtual driver -+bool 'Virtual network device' CONFIG_UML_NET -+ -+dep_bool ' Ethertap transport' CONFIG_UML_NET_ETHERTAP $CONFIG_UML_NET -+dep_bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP $CONFIG_UML_NET -+dep_bool ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET -+dep_bool ' SLiRP transport' CONFIG_UML_NET_SLIRP $CONFIG_UML_NET -+dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $CONFIG_UML_NET -+dep_bool ' Multicast transport' CONFIG_UML_NET_MCAST $CONFIG_UML_NET -+dep_bool ' pcap transport' CONFIG_UML_NET_PCAP $CONFIG_UML_NET -+ -+# Below are hardware-independent drivers mirrored from -+# drivers/net/Config.in. It would be nice if Linux -+# had HW independent drivers separated from the other -+# but it does not. Until then each non-ISA/PCI arch -+# needs to provide it's own menu of network drivers -+ -+tristate 'Dummy net driver support' CONFIG_DUMMY -+tristate 'Bonding driver support' CONFIG_BONDING -+tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER -+tristate 'Universal TUN/TAP device driver support' CONFIG_TUN -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ if [ "$CONFIG_NETLINK" = "y" ]; then -+ tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP -+ fi -+fi -+ -+tristate 'PPP (point-to-point protocol) support' CONFIG_PPP -+if [ ! "$CONFIG_PPP" = "n" ]; then -+ dep_bool ' PPP multilink support (EXPERIMENTAL)' CONFIG_PPP_MULTILINK $CONFIG_EXPERIMENTAL -+ dep_bool ' PPP filtering' CONFIG_PPP_FILTER $CONFIG_FILTER -+ dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP -+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP -+ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP -+ dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP -+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL -+fi -+ -+tristate 'SLIP (serial line) support' CONFIG_SLIP -+dep_bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED $CONFIG_SLIP -+dep_bool ' Keepalive and linefill' CONFIG_SLIP_SMART $CONFIG_SLIP -+dep_bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 $CONFIG_SLIP -+ -+endmenu -diff -Naur -X ../exclude-files orig/arch/um/config.release um/arch/um/config.release ---- orig/arch/um/config.release 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/config.release 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,302 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_USERMODE=y -+# CONFIG_ISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_PCI is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+ -+# -+# General Setup -+# -+CONFIG_NET=y -+CONFIG_SYSVIPC=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_SYSCTL=y -+CONFIG_BINFMT_AOUT=y -+CONFIG_BINFMT_ELF=y -+CONFIG_BINFMT_MISC=y -+CONFIG_HOSTFS=y -+# CONFIG_HPPFS is not set -+CONFIG_MCONSOLE=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_HOST_2G_2G is not set -+# CONFIG_UML_SMP is not set -+# CONFIG_SMP is not set -+CONFIG_NEST_LEVEL=0 -+CONFIG_KERNEL_HALF_GIGS=1 -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+CONFIG_KMOD=y -+ -+# -+# Character Devices -+# -+CONFIG_STDIO_CONSOLE=y -+CONFIG_SSL=y -+CONFIG_FD_CHAN=y -+# CONFIG_NULL_CHAN is not set -+CONFIG_PORT_CHAN=y -+CONFIG_PTY_CHAN=y -+CONFIG_TTY_CHAN=y -+CONFIG_XTERM_CHAN=y -+CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -+CONFIG_CON_CHAN="xterm" -+CONFIG_SSL_CHAN="pty" -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=256 -+# CONFIG_WATCHDOG is not set -+CONFIG_UML_SOUND=y -+CONFIG_SOUND=y -+CONFIG_HOSTAUDIO=y -+# CONFIG_TTY_LOG is not set -+ -+# -+# Block Devices -+# -+CONFIG_BLK_DEV_UBD=y -+# CONFIG_BLK_DEV_UBD_SYNC is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_NBD=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_MMAPPER is not set -+CONFIG_NETDEVICES=y -+ -+# -+# Network Devices -+# -+CONFIG_UML_NET=y -+CONFIG_UML_NET_ETHERTAP=y -+CONFIG_UML_NET_TUNTAP=y -+CONFIG_UML_NET_SLIP=y -+CONFIG_UML_NET_DAEMON=y -+CONFIG_UML_NET_MCAST=y -+CONFIG_DUMMY=y -+CONFIG_BONDING=m -+CONFIG_EQUALIZER=m -+CONFIG_TUN=y -+CONFIG_PPP=m -+CONFIG_PPP_MULTILINK=y -+# CONFIG_PPP_ASYNC is not set -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPPOE=m -+CONFIG_SLIP=m -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+CONFIG_PACKET_MMAP=y -+# CONFIG_NETLINK_DEV is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_FILTER is not set -+CONFIG_UNIX=y -+CONFIG_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_PNP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+# CONFIG_ATM is not set -+# CONFIG_VLAN_8021Q is not set -+ -+# -+# -+# -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DECNET is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# File systems -+# -+CONFIG_QUOTA=y -+CONFIG_AUTOFS_FS=m -+CONFIG_AUTOFS4_FS=m -+CONFIG_REISERFS_FS=m -+# CONFIG_REISERFS_CHECK is not set -+# CONFIG_REISERFS_PROC_INFO is not set -+CONFIG_ADFS_FS=m -+# CONFIG_ADFS_FS_RW is not set -+CONFIG_AFFS_FS=m -+CONFIG_HFS_FS=m -+CONFIG_BFS_FS=m -+CONFIG_EXT3_FS=y -+CONFIG_JBD=y -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_UMSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_EFS_FS=m -+CONFIG_CRAMFS=m -+CONFIG_TMPFS=y -+CONFIG_RAMFS=y -+CONFIG_ISO9660_FS=y -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+CONFIG_MINIX_FS=m -+CONFIG_VXFS_FS=m -+# CONFIG_NTFS_FS is not set -+CONFIG_HPFS_FS=m -+CONFIG_PROC_FS=y -+CONFIG_DEVFS_FS=y -+CONFIG_DEVFS_MOUNT=y -+# CONFIG_DEVFS_DEBUG is not set -+CONFIG_DEVPTS_FS=y -+CONFIG_QNX4FS_FS=m -+# CONFIG_QNX4FS_RW is not set -+CONFIG_ROMFS_FS=m -+CONFIG_EXT2_FS=y -+CONFIG_SYSV_FS=m -+CONFIG_UDF_FS=m -+# CONFIG_UDF_RW is not set -+CONFIG_UFS_FS=m -+# CONFIG_UFS_FS_WRITE is not set -+ -+# -+# Network File Systems -+# -+# CONFIG_CODA_FS is not set -+# CONFIG_INTERMEZZO_FS is not set -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3=y -+CONFIG_NFSD=y -+CONFIG_NFSD_V3=y -+CONFIG_SUNRPC=y -+CONFIG_LOCKD=y -+CONFIG_LOCKD_V4=y -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_ZISOFS_FS is not set -+CONFIG_ZLIB_FS_INFLATE=m -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+# CONFIG_NLS_CODEPAGE_437 is not set -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ISO8859_1 is not set -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=y -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+# CONFIG_BLK_DEV_SD is not set -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+CONFIG_SCSI_DEBUG=m -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+# CONFIG_MTD is not set -+ -+# -+# Kernel hacking -+# -+# CONFIG_DEBUG_SLAB is not set -+# CONFIG_DEBUGSYM is not set -diff -Naur -X ../exclude-files orig/arch/um/config_scsi.in um/arch/um/config_scsi.in ---- orig/arch/um/config_scsi.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/config_scsi.in 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,30 @@ -+comment 'SCSI support type (disk, tape, CD-ROM)' -+ -+dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI -+ -+if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then -+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 -+fi -+ -+dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI -+ -+dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI -+ -+if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then -+ bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR -+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 -+fi -+dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI -+ -+comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' -+ -+#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ bool ' Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES -+#fi -+ -+bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN -+ -+bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS -+bool ' SCSI logging facility' CONFIG_SCSI_LOGGING -+ -+dep_tristate 'SCSI debugging host simulator (EXPERIMENTAL)' CONFIG_SCSI_DEBUG $CONFIG_SCSI -diff -Naur -X ../exclude-files orig/arch/um/defconfig um/arch/um/defconfig ---- orig/arch/um/defconfig 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/defconfig 2003-12-17 02:15:39.000000000 -0500 -@@ -0,0 +1,423 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_USERMODE=y -+# CONFIG_ISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_PCI is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+ -+# -+# General Setup -+# -+CONFIG_MODE_SKAS=y -+CONFIG_MODE_TT=y -+CONFIG_NET=y -+CONFIG_SYSVIPC=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_SYSCTL=y -+CONFIG_BINFMT_AOUT=y -+CONFIG_BINFMT_ELF=y -+CONFIG_BINFMT_MISC=y -+CONFIG_HOSTFS=y -+CONFIG_HPPFS=y -+CONFIG_MCONSOLE=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_HOST_2G_2G is not set -+# CONFIG_UML_SMP is not set -+# CONFIG_SMP is not set -+CONFIG_NEST_LEVEL=0 -+CONFIG_KERNEL_HALF_GIGS=1 -+# CONFIG_HIGHMEM is not set -+CONFIG_PROC_MM=y -+CONFIG_KERNEL_STACK_ORDER=2 -+CONFIG_UML_REAL_TIME_CLOCK=y -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+# CONFIG_KMOD is not set -+ -+# -+# Character Devices -+# -+CONFIG_STDIO_CONSOLE=y -+CONFIG_SSL=y -+CONFIG_FD_CHAN=y -+CONFIG_NULL_CHAN=y -+CONFIG_PORT_CHAN=y -+CONFIG_PTY_CHAN=y -+CONFIG_TTY_CHAN=y -+CONFIG_XTERM_CHAN=y -+CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -+CONFIG_CON_CHAN="xterm" -+CONFIG_SSL_CHAN="pty" -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=256 -+# CONFIG_WATCHDOG is not set -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+# CONFIG_SOFT_WATCHDOG is not set -+# CONFIG_UML_WATCHDOG is not set -+CONFIG_UML_SOUND=y -+CONFIG_SOUND=y -+CONFIG_HOSTAUDIO=y -+# CONFIG_TTY_LOG is not set -+ -+# -+# Block Devices -+# -+CONFIG_BLK_DEV_UBD=y -+# CONFIG_BLK_DEV_UBD_SYNC is not set -+# CONFIG_COW is not set -+CONFIG_COW_COMMON=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_NBD=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_MMAPPER is not set -+CONFIG_NETDEVICES=y -+ -+# -+# Network Devices -+# -+CONFIG_UML_NET=y -+CONFIG_UML_NET_ETHERTAP=y -+CONFIG_UML_NET_TUNTAP=y -+CONFIG_UML_NET_SLIP=y -+CONFIG_UML_NET_SLIRP=y -+CONFIG_UML_NET_DAEMON=y -+CONFIG_UML_NET_MCAST=y -+# CONFIG_UML_NET_PCAP is not set -+CONFIG_DUMMY=y -+# CONFIG_BONDING is not set -+# CONFIG_EQUALIZER is not set -+CONFIG_TUN=y -+CONFIG_PPP=y -+# CONFIG_PPP_MULTILINK is not set -+# CONFIG_PPP_FILTER is not set -+# CONFIG_PPP_ASYNC is not set -+# CONFIG_PPP_SYNC_TTY is not set -+# CONFIG_PPP_DEFLATE is not set -+# CONFIG_PPP_BSDCOMP is not set -+# CONFIG_PPPOE is not set -+CONFIG_SLIP=y -+# CONFIG_SLIP_COMPRESSED is not set -+# CONFIG_SLIP_SMART is not set -+# CONFIG_SLIP_MODE_SLIP6 is not set -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+CONFIG_PACKET_MMAP=y -+# CONFIG_NETLINK_DEV is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_FILTER is not set -+CONFIG_UNIX=y -+CONFIG_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_PNP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+ -+# -+# SCTP Configuration (EXPERIMENTAL) -+# -+CONFIG_IPV6_SCTP__=y -+# CONFIG_IP_SCTP is not set -+# CONFIG_ATM is not set -+# CONFIG_VLAN_8021Q is not set -+ -+# -+# -+# -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DEV_APPLETALK is not set -+# CONFIG_DECNET is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# File systems -+# -+CONFIG_QUOTA=y -+# CONFIG_QFMT_V2 is not set -+CONFIG_AUTOFS_FS=y -+CONFIG_AUTOFS4_FS=y -+CONFIG_REISERFS_FS=y -+# CONFIG_REISERFS_CHECK is not set -+# CONFIG_REISERFS_PROC_INFO is not set -+# CONFIG_ADFS_FS is not set -+# CONFIG_ADFS_FS_RW is not set -+# CONFIG_AFFS_FS is not set -+# CONFIG_HFS_FS is not set -+# CONFIG_HFSPLUS_FS is not set -+# CONFIG_BEFS_FS is not set -+# CONFIG_BEFS_DEBUG is not set -+# CONFIG_BFS_FS is not set -+# CONFIG_EXT3_FS is not set -+# CONFIG_JBD is not set -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_UMSDOS_FS=y -+CONFIG_VFAT_FS=y -+# CONFIG_EFS_FS is not set -+CONFIG_JFFS_FS=y -+CONFIG_JFFS_FS_VERBOSE=0 -+CONFIG_JFFS_PROC_FS=y -+CONFIG_JFFS2_FS=y -+CONFIG_JFFS2_FS_DEBUG=0 -+# CONFIG_CRAMFS is not set -+# CONFIG_TMPFS is not set -+CONFIG_RAMFS=y -+CONFIG_ISO9660_FS=y -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+# CONFIG_JFS_FS is not set -+# CONFIG_JFS_DEBUG is not set -+# CONFIG_JFS_STATISTICS is not set -+CONFIG_MINIX_FS=y -+# CONFIG_VXFS_FS is not set -+# CONFIG_NTFS_FS is not set -+# CONFIG_NTFS_RW is not set -+# CONFIG_HPFS_FS is not set -+CONFIG_PROC_FS=y -+CONFIG_DEVFS_FS=y -+CONFIG_DEVFS_MOUNT=y -+# CONFIG_DEVFS_DEBUG is not set -+CONFIG_DEVPTS_FS=y -+# CONFIG_QNX4FS_FS is not set -+# CONFIG_QNX4FS_RW is not set -+# CONFIG_ROMFS_FS is not set -+CONFIG_EXT2_FS=y -+# CONFIG_SYSV_FS is not set -+# CONFIG_UDF_FS is not set -+# CONFIG_UDF_RW is not set -+# CONFIG_UFS_FS is not set -+# CONFIG_UFS_FS_WRITE is not set -+ -+# -+# Network File Systems -+# -+# CONFIG_CODA_FS is not set -+# CONFIG_INTERMEZZO_FS is not set -+# CONFIG_NFS_FS is not set -+# CONFIG_NFS_V3 is not set -+# CONFIG_NFS_DIRECTIO is not set -+# CONFIG_ROOT_NFS is not set -+# CONFIG_NFSD is not set -+# CONFIG_NFSD_V3 is not set -+# CONFIG_NFSD_TCP is not set -+# CONFIG_SUNRPC is not set -+# CONFIG_LOCKD is not set -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_NCPFS_PACKET_SIGNING is not set -+# CONFIG_NCPFS_IOCTL_LOCKING is not set -+# CONFIG_NCPFS_STRONG is not set -+# CONFIG_NCPFS_NFS_NS is not set -+# CONFIG_NCPFS_OS2_NS is not set -+# CONFIG_NCPFS_SMALLDOS is not set -+# CONFIG_NCPFS_NLS is not set -+# CONFIG_NCPFS_EXTRAS is not set -+# CONFIG_ZISOFS_FS is not set -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+# CONFIG_NLS_CODEPAGE_437 is not set -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ISO8859_1 is not set -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=y -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+# CONFIG_BLK_DEV_SD is not set -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+CONFIG_SCSI_DEBUG=y -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+# CONFIG_BLK_DEV_MD is not set -+# CONFIG_MD_LINEAR is not set -+# CONFIG_MD_RAID0 is not set -+# CONFIG_MD_RAID1 is not set -+# CONFIG_MD_RAID5 is not set -+# CONFIG_MD_MULTIPATH is not set -+# CONFIG_BLK_DEV_LVM is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+CONFIG_MTD=y -+# CONFIG_MTD_DEBUG is not set -+# CONFIG_MTD_PARTITIONS is not set -+# CONFIG_MTD_CONCAT is not set -+# CONFIG_MTD_REDBOOT_PARTS is not set -+# CONFIG_MTD_CMDLINE_PARTS is not set -+ -+# -+# User Modules And Translation Layers -+# -+CONFIG_MTD_CHAR=y -+CONFIG_MTD_BLOCK=y -+# CONFIG_FTL is not set -+# CONFIG_NFTL is not set -+ -+# -+# RAM/ROM/Flash chip drivers -+# -+# CONFIG_MTD_CFI is not set -+# CONFIG_MTD_JEDECPROBE is not set -+# CONFIG_MTD_GEN_PROBE is not set -+# CONFIG_MTD_CFI_INTELEXT is not set -+# CONFIG_MTD_CFI_AMDSTD is not set -+# CONFIG_MTD_CFI_STAA is not set -+# CONFIG_MTD_RAM is not set -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_ABSENT is not set -+# CONFIG_MTD_OBSOLETE_CHIPS is not set -+# CONFIG_MTD_AMDSTD is not set -+# CONFIG_MTD_SHARP is not set -+# CONFIG_MTD_JEDEC is not set -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_PHYSMAP is not set -+# CONFIG_MTD_PCI is not set -+# CONFIG_MTD_PCMCIA is not set -+ -+# -+# Self-contained MTD device drivers -+# -+# CONFIG_MTD_PMC551 is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_MTDRAM is not set -+CONFIG_MTD_BLKMTD=y -+ -+# -+# Disk-On-Chip Device Drivers -+# -+# CONFIG_MTD_DOC1000 is not set -+# CONFIG_MTD_DOC2000 is not set -+# CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOCPROBE is not set -+ -+# -+# NAND Flash Device Drivers -+# -+# CONFIG_MTD_NAND is not set -+ -+# -+# Library routines -+# -+# CONFIG_CRC32 is not set -+CONFIG_ZLIB_INFLATE=y -+CONFIG_ZLIB_DEFLATE=y -+ -+# -+# Kernel hacking -+# -+# CONFIG_DEBUG_SLAB is not set -+CONFIG_DEBUGSYM=y -+CONFIG_PT_PROXY=y -+# CONFIG_GPROF is not set -+# CONFIG_GCOV is not set -diff -Naur -X ../exclude-files orig/arch/um/drivers/chan_kern.c um/arch/um/drivers/chan_kern.c ---- orig/arch/um/drivers/chan_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/chan_kern.c 2003-11-07 07:25:34.000000000 -0500 -@@ -0,0 +1,519 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "sigio.h" -+#include "line.h" -+ -+static void *not_configged_init(char *str, int device, struct chan_opts *opts) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(NULL); -+} -+ -+static int not_configged_open(int input, int output, int primary, void *data, -+ char **dev_out) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-ENODEV); -+} -+ -+static void not_configged_close(int fd, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+} -+ -+static int not_configged_read(int fd, char *c_out, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_write(int fd, const char *buf, int len, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_console_write(int fd, const char *buf, int len, -+ void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_window_size(int fd, void *data, unsigned short *rows, -+ unsigned short *cols) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-ENODEV); -+} -+ -+static void not_configged_free(void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+} -+ -+static struct chan_ops not_configged_ops = { -+ .init = not_configged_init, -+ .open = not_configged_open, -+ .close = not_configged_close, -+ .read = not_configged_read, -+ .write = not_configged_write, -+ .console_write = not_configged_console_write, -+ .window_size = not_configged_window_size, -+ .free = not_configged_free, -+ .winch = 0, -+}; -+ -+static void tty_receive_char(struct tty_struct *tty, char ch) -+{ -+ if(tty == NULL) return; -+ -+ if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { -+ if(ch == STOP_CHAR(tty)){ -+ stop_tty(tty); -+ return; -+ } -+ else if(ch == START_CHAR(tty)){ -+ start_tty(tty); -+ return; -+ } -+ } -+ -+ if((tty->flip.flag_buf_ptr == NULL) || -+ (tty->flip.char_buf_ptr == NULL)) -+ return; -+ tty_insert_flip_char(tty, ch, TTY_NORMAL); -+} -+ -+static int open_one_chan(struct chan *chan, int input, int output, int primary) -+{ -+ int fd; -+ -+ if(chan->opened) return(0); -+ if(chan->ops->open == NULL) fd = 0; -+ else fd = (*chan->ops->open)(input, output, primary, chan->data, -+ &chan->dev); -+ if(fd < 0) return(fd); -+ chan->fd = fd; -+ -+ chan->opened = 1; -+ return(0); -+} -+ -+int open_chan(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int ret, err = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ ret = open_one_chan(chan, chan->input, chan->output, -+ chan->primary); -+ if(chan->primary) err = ret; -+ } -+ return(err); -+} -+ -+void chan_enable_winch(struct list_head *chans, void *line) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary && chan->output && chan->ops->winch){ -+ register_winch(chan->fd, line); -+ return; -+ } -+ } -+} -+ -+void enable_chan(struct list_head *chans, void *data) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->opened) continue; -+ -+ line_setup_irq(chan->fd, chan->input, chan->output, data); -+ } -+} -+ -+void close_chan(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ /* Close in reverse order as open in case more than one of them -+ * refers to the same device and they save and restore that device's -+ * state. Then, the first one opened will have the original state, -+ * so it must be the last closed. -+ */ -+ for(ele = chans->prev; ele != chans; ele = ele->prev){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->opened) continue; -+ if(chan->ops->close != NULL) -+ (*chan->ops->close)(chan->fd, chan->data); -+ chan->opened = 0; -+ chan->fd = -1; -+ } -+} -+ -+int write_chan(struct list_head *chans, const char *buf, int len, -+ int write_irq) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int n, ret = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->output || (chan->ops->write == NULL)) continue; -+ n = chan->ops->write(chan->fd, buf, len, chan->data); -+ if(chan->primary){ -+ ret = n; -+ if((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){ -+ reactivate_fd(chan->fd, write_irq); -+ if(ret == -EAGAIN) ret = 0; -+ } -+ } -+ } -+ return(ret); -+} -+ -+int console_write_chan(struct list_head *chans, const char *buf, int len) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int n, ret = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->output || (chan->ops->console_write == NULL)) -+ continue; -+ n = chan->ops->console_write(chan->fd, buf, len, chan->data); -+ if(chan->primary) ret = n; -+ } -+ return(ret); -+} -+ -+int chan_window_size(struct list_head *chans, unsigned short *rows_out, -+ unsigned short *cols_out) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary){ -+ if(chan->ops->window_size == NULL) return(0); -+ return(chan->ops->window_size(chan->fd, chan->data, -+ rows_out, cols_out)); -+ } -+ } -+ return(0); -+} -+ -+void free_one_chan(struct chan *chan) -+{ -+ list_del(&chan->list); -+ if(chan->ops->free != NULL) -+ (*chan->ops->free)(chan->data); -+ free_irq_by_fd(chan->fd); -+ if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); -+ kfree(chan); -+} -+ -+void free_chan(struct list_head *chans) -+{ -+ struct list_head *ele, *next; -+ struct chan *chan; -+ -+ list_for_each_safe(ele, next, chans){ -+ chan = list_entry(ele, struct chan, list); -+ free_one_chan(chan); -+ } -+} -+ -+static int one_chan_config_string(struct chan *chan, char *str, int size, -+ char **error_out) -+{ -+ int n = 0; -+ -+ if(chan == NULL){ -+ CONFIG_CHUNK(str, size, n, "none", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, chan->ops->type, 0); -+ -+ if(chan->dev == NULL){ -+ CONFIG_CHUNK(str, size, n, "", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, ":", 0); -+ CONFIG_CHUNK(str, size, n, chan->dev, 0); -+ -+ return(n); -+} -+ -+static int chan_pair_config_string(struct chan *in, struct chan *out, -+ char *str, int size, char **error_out) -+{ -+ int n; -+ -+ n = one_chan_config_string(in, str, size, error_out); -+ str += n; -+ size -= n; -+ -+ if(in == out){ -+ CONFIG_CHUNK(str, size, n, "", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, ",", 1); -+ n = one_chan_config_string(out, str, size, error_out); -+ str += n; -+ size -= n; -+ CONFIG_CHUNK(str, size, n, "", 1); -+ -+ return(n); -+} -+ -+int chan_config_string(struct list_head *chans, char *str, int size, -+ char **error_out) -+{ -+ struct list_head *ele; -+ struct chan *chan, *in = NULL, *out = NULL; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->primary) -+ continue; -+ if(chan->input) -+ in = chan; -+ if(chan->output) -+ out = chan; -+ } -+ -+ return(chan_pair_config_string(in, out, str, size, error_out)); -+} -+ -+struct chan_type { -+ char *key; -+ struct chan_ops *ops; -+}; -+ -+struct chan_type chan_table[] = { -+#ifdef CONFIG_FD_CHAN -+ { "fd", &fd_ops }, -+#else -+ { "fd", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_NULL_CHAN -+ { "null", &null_ops }, -+#else -+ { "null", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_PORT_CHAN -+ { "port", &port_ops }, -+#else -+ { "port", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_PTY_CHAN -+ { "pty", &pty_ops }, -+ { "pts", &pts_ops }, -+#else -+ { "pty", ¬_configged_ops }, -+ { "pts", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_TTY_CHAN -+ { "tty", &tty_ops }, -+#else -+ { "tty", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_XTERM_CHAN -+ { "xterm", &xterm_ops }, -+#else -+ { "xterm", ¬_configged_ops }, -+#endif -+}; -+ -+static struct chan *parse_chan(char *str, int pri, int device, -+ struct chan_opts *opts) -+{ -+ struct chan_type *entry; -+ struct chan_ops *ops; -+ struct chan *chan; -+ void *data; -+ int i; -+ -+ ops = NULL; -+ data = NULL; -+ for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){ -+ entry = &chan_table[i]; -+ if(!strncmp(str, entry->key, strlen(entry->key))){ -+ ops = entry->ops; -+ str += strlen(entry->key); -+ break; -+ } -+ } -+ if(ops == NULL){ -+ printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n", -+ str); -+ return(NULL); -+ } -+ if(ops->init == NULL) return(NULL); -+ data = (*ops->init)(str, device, opts); -+ if(data == NULL) return(NULL); -+ -+ chan = kmalloc(sizeof(*chan), GFP_KERNEL); -+ if(chan == NULL) return(NULL); -+ *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), -+ .primary = 1, -+ .input = 0, -+ .output = 0, -+ .opened = 0, -+ .fd = -1, -+ .pri = pri, -+ .ops = ops, -+ .data = data }); -+ return(chan); -+} -+ -+int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, -+ struct chan_opts *opts) -+{ -+ struct chan *new, *chan; -+ char *in, *out; -+ -+ if(!list_empty(chans)){ -+ chan = list_entry(chans->next, struct chan, list); -+ if(chan->pri >= pri) return(0); -+ free_chan(chans); -+ INIT_LIST_HEAD(chans); -+ } -+ -+ out = strchr(str, ','); -+ if(out != NULL){ -+ in = str; -+ *out = '\0'; -+ out++; -+ new = parse_chan(in, pri, device, opts); -+ if(new == NULL) return(-1); -+ new->input = 1; -+ list_add(&new->list, chans); -+ -+ new = parse_chan(out, pri, device, opts); -+ if(new == NULL) return(-1); -+ list_add(&new->list, chans); -+ new->output = 1; -+ } -+ else { -+ new = parse_chan(str, pri, device, opts); -+ if(new == NULL) return(-1); -+ list_add(&new->list, chans); -+ new->input = 1; -+ new->output = 1; -+ } -+ return(0); -+} -+ -+int chan_out_fd(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary && chan->output) -+ return(chan->fd); -+ } -+ return(-1); -+} -+ -+void chan_interrupt(struct list_head *chans, struct tq_struct *task, -+ struct tty_struct *tty, int irq, void *dev) -+{ -+ struct list_head *ele, *next; -+ struct chan *chan; -+ int err; -+ char c; -+ -+ list_for_each_safe(ele, next, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->input || (chan->ops->read == NULL)) continue; -+ do { -+ if((tty != NULL) && -+ (tty->flip.count >= TTY_FLIPBUF_SIZE)){ -+ queue_task(task, &tq_timer); -+ goto out; -+ } -+ err = chan->ops->read(chan->fd, &c, chan->data); -+ if(err > 0) -+ tty_receive_char(tty, c); -+ } while(err > 0); -+ -+ if(err == 0) reactivate_fd(chan->fd, irq); -+ if(err == -EIO){ -+ if(chan->primary){ -+ if(tty != NULL) -+ tty_hangup(tty); -+ line_disable(dev, irq); -+ close_chan(chans); -+ free_chan(chans); -+ return; -+ } -+ else { -+ if(chan->ops->close != NULL) -+ chan->ops->close(chan->fd, chan->data); -+ free_one_chan(chan); -+ } -+ } -+ } -+ out: -+ if(tty) tty_flip_buffer_push(tty); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/chan_user.c um/arch/um/drivers/chan_user.c ---- orig/arch/um/drivers/chan_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/chan_user.c 2003-11-07 07:23:45.000000000 -0500 -@@ -0,0 +1,217 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "kern_util.h" -+#include "user_util.h" -+#include "chan_user.h" -+#include "user.h" -+#include "helper.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+void generic_close(int fd, void *unused) -+{ -+ os_close_file(fd); -+} -+ -+int generic_read(int fd, char *c_out, void *unused) -+{ -+ int n; -+ -+ n = os_read_file(fd, c_out, sizeof(*c_out)); -+ -+ if(n == -EAGAIN) -+ return(0); -+ else if(n == 0) -+ return(-EIO); -+ return(n); -+} -+ -+/* XXX Trivial wrapper around os_write_file */ -+ -+int generic_write(int fd, const char *buf, int n, void *unused) -+{ -+ return(os_write_file(fd, buf, n)); -+} -+ -+int generic_console_write(int fd, const char *buf, int n, void *unused) -+{ -+ struct termios save, new; -+ int err; -+ -+ if(isatty(fd)){ -+ tcgetattr(fd, &save); -+ new = save; -+ new.c_oflag |= OPOST; -+ tcsetattr(fd, TCSAFLUSH, &new); -+ } -+ err = generic_write(fd, buf, n, NULL); -+ if(isatty(fd)) tcsetattr(fd, TCSAFLUSH, &save); -+ return(err); -+} -+ -+int generic_window_size(int fd, void *unused, unsigned short *rows_out, -+ unsigned short *cols_out) -+{ -+ int rows, cols; -+ int ret; -+ -+ ret = os_window_size(fd, &rows, &cols); -+ if(ret < 0) -+ return(ret); -+ -+ ret = ((*rows_out != rows) || (*cols_out != cols)); -+ -+ *rows_out = rows; -+ *cols_out = cols; -+ -+ return(ret); -+} -+ -+void generic_free(void *data) -+{ -+ kfree(data); -+} -+ -+static void winch_handler(int sig) -+{ -+} -+ -+struct winch_data { -+ int pty_fd; -+ int pipe_fd; -+ int close_me; -+}; -+ -+static int winch_thread(void *arg) -+{ -+ struct winch_data *data = arg; -+ sigset_t sigs; -+ int pty_fd, pipe_fd; -+ int count, err; -+ char c = 1; -+ -+ os_close_file(data->close_me); -+ pty_fd = data->pty_fd; -+ pipe_fd = data->pipe_fd; -+ count = os_write_file(pipe_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("winch_thread : failed to write synchronization " -+ "byte, err = %d\n", -count); -+ -+ signal(SIGWINCH, winch_handler); -+ sigfillset(&sigs); -+ sigdelset(&sigs, SIGWINCH); -+ if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){ -+ printk("winch_thread : sigprocmask failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ if(setsid() < 0){ -+ printk("winch_thread : setsid failed, errno = %d\n", errno); -+ exit(1); -+ } -+ -+ err = os_new_tty_pgrp(pty_fd, os_getpid()); -+ if(err < 0){ -+ printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err); -+ exit(1); -+ } -+ -+ count = os_read_file(pipe_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("winch_thread : failed to read synchronization byte, " -+ "err = %d\n", -count); -+ -+ while(1){ -+ pause(); -+ -+ count = os_write_file(pipe_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("winch_thread : write failed, err = %d\n", -+ -count); -+ } -+} -+ -+static int winch_tramp(int fd, void *device_data, int *fd_out) -+{ -+ struct winch_data data; -+ unsigned long stack; -+ int fds[2], pid, n, err; -+ char c; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err < 0){ -+ printk("winch_tramp : os_pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ -+ data = ((struct winch_data) { .pty_fd = fd, -+ .pipe_fd = fds[1], -+ .close_me = fds[0] } ); -+ pid = run_helper_thread(winch_thread, &data, 0, &stack, 0); -+ if(pid < 0){ -+ printk("fork of winch_thread failed - errno = %d\n", errno); -+ return(pid); -+ } -+ -+ os_close_file(fds[1]); -+ *fd_out = fds[0]; -+ n = os_read_file(fds[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("winch_tramp : failed to read synchronization byte\n"); -+ printk("read failed, err = %d\n", -n); -+ printk("fd %d will not support SIGWINCH\n", fd); -+ *fd_out = -1; -+ } -+ return(pid); -+} -+ -+void register_winch(int fd, void *device_data) -+{ -+ int pid, thread, thread_fd; -+ int count; -+ char c = 1; -+ -+ if(!isatty(fd)) -+ return; -+ -+ pid = tcgetpgrp(fd); -+ if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, -+ device_data) && (pid == -1)){ -+ thread = winch_tramp(fd, device_data, &thread_fd); -+ if(fd != -1){ -+ register_winch_irq(thread_fd, fd, thread, device_data); -+ -+ count = os_write_file(thread_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("register_winch : failed to write " -+ "synchronization byte, err = %d\n", -+ -count); -+ } -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/cow.h um/arch/um/drivers/cow.h ---- orig/arch/um/drivers/cow.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/cow.h 2004-01-16 03:45:20.000000000 -0500 -@@ -0,0 +1,41 @@ -+#ifndef __COW_H__ -+#define __COW_H__ -+ -+#include -+ -+#if __BYTE_ORDER == __BIG_ENDIAN -+# define ntohll(x) (x) -+# define htonll(x) (x) -+#elif __BYTE_ORDER == __LITTLE_ENDIAN -+# define ntohll(x) bswap_64(x) -+# define htonll(x) bswap_64(x) -+#else -+#error "__BYTE_ORDER not defined" -+#endif -+ -+extern int init_cow_file(int fd, char *cow_file, char *backing_file, -+ int sectorsize, int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out); -+ -+extern int file_reader(__u64 offset, char *buf, int len, void *arg); -+extern int read_cow_header(int (*reader)(__u64, char *, int, void *), -+ void *arg, __u32 *version_out, -+ char **backing_file_out, time_t *mtime_out, -+ __u64 *size_out, int *sectorsize_out, -+ __u32 *align_out, int *bitmap_offset_out); -+ -+extern int write_cow_header(char *cow_file, int fd, char *backing_file, -+ int sectorsize, int alignment, long long *size); -+ -+extern void cow_sizes(int version, __u64 size, int sectorsize, int align, -+ int bitmap_offset, unsigned long *bitmap_len_out, -+ int *data_offset_out); -+ -+#endif -+ -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/cow_kern.c um/arch/um/drivers/cow_kern.c ---- orig/arch/um/drivers/cow_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/cow_kern.c 2004-01-10 05:55:04.000000000 -0500 -@@ -0,0 +1,630 @@ -+#define COW_MAJOR 60 -+#define MAJOR_NR COW_MAJOR -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "2_5compat.h" -+#include "cow.h" -+#include "ubd_user.h" -+ -+#define COW_SHIFT 4 -+ -+struct cow { -+ int count; -+ char *cow_path; -+ dev_t cow_dev; -+ struct block_device *cow_bdev; -+ char *backing_path; -+ dev_t backing_dev; -+ struct block_device *backing_bdev; -+ int sectorsize; -+ unsigned long *bitmap; -+ unsigned long bitmap_len; -+ int bitmap_offset; -+ int data_offset; -+ devfs_handle_t devfs; -+ struct semaphore sem; -+ struct semaphore io_sem; -+ atomic_t working; -+ spinlock_t io_lock; -+ struct buffer_head *bh; -+ struct buffer_head *bhtail; -+ void *end_io; -+}; -+ -+#define DEFAULT_COW { \ -+ .count = 0, \ -+ .cow_path = NULL, \ -+ .cow_dev = 0, \ -+ .backing_path = NULL, \ -+ .backing_dev = 0, \ -+ .bitmap = NULL, \ -+ .bitmap_len = 0, \ -+ .bitmap_offset = 0, \ -+ .data_offset = 0, \ -+ .devfs = NULL, \ -+ .working = ATOMIC_INIT(0), \ -+ .io_lock = SPIN_LOCK_UNLOCKED, \ -+} -+ -+#define MAX_DEV (8) -+#define MAX_MINOR (MAX_DEV << COW_SHIFT) -+ -+struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW }; -+ -+/* Not modified by this driver */ -+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE }; -+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 }; -+ -+/* Protected by cow_lock */ -+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 }; -+ -+static struct hd_struct cow_part[MAX_MINOR] = -+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } }; -+ -+/* Protected by io_request_lock */ -+static request_queue_t *cow_queue; -+ -+static int cow_open(struct inode *inode, struct file *filp); -+static int cow_release(struct inode * inode, struct file * file); -+static int cow_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg); -+static int cow_revalidate(kdev_t rdev); -+ -+static struct block_device_operations cow_blops = { -+ .open = cow_open, -+ .release = cow_release, -+ .ioctl = cow_ioctl, -+ .revalidate = cow_revalidate, -+}; -+ -+/* Initialized in an initcall, and unchanged thereafter */ -+devfs_handle_t cow_dir_handle; -+ -+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \ -+{ \ -+ .major = maj, \ -+ .major_name = name, \ -+ .minor_shift = shift, \ -+ .max_p = 1 << shift, \ -+ .part = parts, \ -+ .sizes = bsizes, \ -+ .nr_real = max, \ -+ .real_devices = NULL, \ -+ .next = NULL, \ -+ .fops = blops, \ -+ .de_arr = NULL, \ -+ .flags = 0 \ -+} -+ -+static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED; -+ -+static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part, -+ COW_SHIFT, sizes, MAX_DEV, -+ &cow_blops); -+ -+static int cow_add(int n) -+{ -+ struct cow *dev = &cow_dev[n]; -+ char name[sizeof("nnnnnn\0")]; -+ int err = -ENODEV; -+ -+ if(dev->cow_path == NULL) -+ goto out; -+ -+ sprintf(name, "%d", n); -+ dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE, -+ MAJOR_NR, n << COW_SHIFT, S_IFBLK | -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, -+ &cow_blops, NULL); -+ -+ init_MUTEX_LOCKED(&dev->sem); -+ init_MUTEX(&dev->io_sem); -+ -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+/* -+ * Add buffer_head to back of pending list -+ */ -+static void cow_add_bh(struct cow *cow, struct buffer_head *bh) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&cow->io_lock, flags); -+ if(cow->bhtail != NULL){ -+ cow->bhtail->b_reqnext = bh; -+ cow->bhtail = bh; -+ } -+ else { -+ cow->bh = bh; -+ cow->bhtail = bh; -+ } -+ spin_unlock_irqrestore(&cow->io_lock, flags); -+} -+ -+/* -+ * Grab first pending buffer -+ */ -+static struct buffer_head *cow_get_bh(struct cow *cow) -+{ -+ struct buffer_head *bh; -+ -+ spin_lock_irq(&cow->io_lock); -+ bh = cow->bh; -+ if(bh != NULL){ -+ if(bh == cow->bhtail) -+ cow->bhtail = NULL; -+ cow->bh = bh->b_reqnext; -+ bh->b_reqnext = NULL; -+ } -+ spin_unlock_irq(&cow->io_lock); -+ -+ return(bh); -+} -+ -+static void cow_handle_bh(struct cow *cow, struct buffer_head *bh, -+ struct buffer_head **cow_bh, int ncow_bh) -+{ -+ int i; -+ -+ if(ncow_bh > 0) -+ ll_rw_block(WRITE, ncow_bh, cow_bh); -+ -+ for(i = 0; i < ncow_bh ; i++){ -+ wait_on_buffer(cow_bh[i]); -+ brelse(cow_bh[i]); -+ } -+ -+ ll_rw_block(WRITE, 1, &bh); -+ brelse(bh); -+} -+ -+static struct buffer_head *cow_new_bh(struct cow *dev, int sector) -+{ -+ struct buffer_head *bh; -+ -+ sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize; -+ bh = getblk(dev->cow_dev, sector, dev->sectorsize); -+ memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])), -+ dev->sectorsize); -+ return(bh); -+} -+ -+/* Copied from loop.c, needed to avoid deadlocking in make_request. */ -+ -+static int cow_thread(void *data) -+{ -+ struct cow *dev = data; -+ struct buffer_head *bh; -+ -+ daemonize(); -+ exit_files(current); -+ -+ sprintf(current->comm, "cow%d", dev - cow_dev); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ sigfillset(¤t->blocked); -+ flush_signals(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ atomic_inc(&dev->working); -+ -+ current->policy = SCHED_OTHER; -+ current->nice = -20; -+ -+ current->flags |= PF_NOIO; -+ -+ /* -+ * up sem, we are running -+ */ -+ up(&dev->sem); -+ -+ for(;;){ -+ int start, len, nbh, i, update_bitmap = 0; -+ struct buffer_head *cow_bh[2]; -+ -+ down_interruptible(&dev->io_sem); -+ /* -+ * could be upped because of tear-down, not because of -+ * pending work -+ */ -+ if(!atomic_read(&dev->working)) -+ break; -+ -+ bh = cow_get_bh(dev); -+ if(bh == NULL){ -+ printk(KERN_ERR "cow: missing bh\n"); -+ continue; -+ } -+ -+ start = bh->b_blocknr * bh->b_size / dev->sectorsize; -+ len = bh->b_size / dev->sectorsize; -+ for(i = 0; i < len ; i++){ -+ if(ubd_test_bit(start + i, -+ (unsigned char *) dev->bitmap)) -+ continue; -+ -+ update_bitmap = 1; -+ ubd_set_bit(start + i, (unsigned char *) dev->bitmap); -+ } -+ -+ cow_bh[0] = NULL; -+ cow_bh[1] = NULL; -+ nbh = 0; -+ if(update_bitmap){ -+ cow_bh[0] = cow_new_bh(dev, start); -+ nbh++; -+ if(start / dev->sectorsize != -+ (start + len) / dev->sectorsize){ -+ cow_bh[1] = cow_new_bh(dev, start + len); -+ nbh++; -+ } -+ } -+ -+ bh->b_dev = dev->cow_dev; -+ bh->b_blocknr += dev->data_offset / dev->sectorsize; -+ -+ cow_handle_bh(dev, bh, cow_bh, nbh); -+ -+ /* -+ * upped both for pending work and tear-down, lo_pending -+ * will hit zero then -+ */ -+ if(atomic_dec_and_test(&dev->working)) -+ break; -+ } -+ -+ up(&dev->sem); -+ return(0); -+} -+ -+static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh) -+{ -+ struct cow *dev; -+ int n, minor; -+ -+ minor = MINOR(bh->b_rdev); -+ n = minor >> COW_SHIFT; -+ dev = &cow_dev[n]; -+ -+ dev->end_io = NULL; -+ if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){ -+ bh->b_rdev = dev->cow_dev; -+ bh->b_rsector += dev->data_offset / dev->sectorsize; -+ } -+ else if(rw == WRITE){ -+ bh->b_dev = dev->cow_dev; -+ bh->b_blocknr += dev->data_offset / dev->sectorsize; -+ -+ cow_add_bh(dev, bh); -+ up(&dev->io_sem); -+ return(0); -+ } -+ else { -+ bh->b_rdev = dev->backing_dev; -+ } -+ -+ return(1); -+} -+ -+int cow_init(void) -+{ -+ int i; -+ -+ cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL); -+ if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) { -+ printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR); -+ return -1; -+ } -+ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[MAJOR_NR] = blk_sizes; -+ blk_size[MAJOR_NR] = sizes; -+ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes); -+ -+ cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); -+ blk_init_queue(cow_queue, NULL); -+ INIT_ELV(cow_queue, &cow_queue->elevator); -+ blk_queue_make_request(cow_queue, cow_make_request); -+ -+ add_gendisk(&cow_gendisk); -+ -+ for(i=0;i 0){ -+ n = (left > blocksize) ? blocksize : left; -+ -+ bh = bread(dev, block, (n < 512) ? 512 : n); -+ if(bh == NULL) -+ return(-EIO); -+ -+ n -= offset; -+ memcpy(&buf[cur], bh->b_data + offset, n); -+ block++; -+ left -= n; -+ cur += n; -+ offset = 0; -+ brelse(bh); -+ } -+ -+ return(count); -+} -+ -+static int cow_open(struct inode *inode, struct file *filp) -+{ -+ int (*dev_ioctl)(struct inode *, struct file *, unsigned int, -+ unsigned long); -+ mm_segment_t fs; -+ struct cow *dev; -+ __u64 size; -+ __u32 version, align; -+ time_t mtime; -+ char *backing_file; -+ int n, offset, err = 0; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ if(n >= MAX_DEV) -+ return(-ENODEV); -+ dev = &cow_dev[n]; -+ offset = n << COW_SHIFT; -+ -+ spin_lock(&cow_lock); -+ -+ if(dev->count == 0){ -+ dev->cow_dev = name_to_kdev_t(dev->cow_path); -+ if(dev->cow_dev == 0){ -+ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") " -+ "failed\n", dev->cow_path); -+ err = -ENODEV; -+ } -+ -+ dev->backing_dev = name_to_kdev_t(dev->backing_path); -+ if(dev->backing_dev == 0){ -+ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") " -+ "failed\n", dev->backing_path); -+ err = -ENODEV; -+ } -+ -+ if(err) -+ goto out; -+ -+ dev->cow_bdev = bdget(dev->cow_dev); -+ if(dev->cow_bdev == NULL){ -+ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", -+ dev->cow_path); -+ err = -ENOMEM; -+ } -+ dev->backing_bdev = bdget(dev->backing_dev); -+ if(dev->backing_bdev == NULL){ -+ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", -+ dev->backing_path); -+ err = -ENOMEM; -+ } -+ -+ if(err) -+ goto out; -+ -+ err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0, -+ BDEV_RAW); -+ if(err){ -+ printk("cow_open - blkdev_get of COW device failed, " -+ "error = %d\n", err); -+ goto out; -+ } -+ -+ err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW); -+ if(err){ -+ printk("cow_open - blkdev_get of backing device " -+ "failed, error = %d\n", err); -+ goto out; -+ } -+ -+ err = read_cow_header(reader, &dev->cow_dev, &version, -+ &backing_file, &mtime, &size, -+ &dev->sectorsize, &align, -+ &dev->bitmap_offset); -+ if(err){ -+ printk(KERN_ERR "cow_open - read_cow_header failed, " -+ "err = %d\n", err); -+ goto out; -+ } -+ -+ cow_sizes(version, size, dev->sectorsize, align, -+ dev->bitmap_offset, &dev->bitmap_len, -+ &dev->data_offset); -+ dev->bitmap = (void *) vmalloc(dev->bitmap_len); -+ if(dev->bitmap == NULL){ -+ err = -ENOMEM; -+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); -+ goto out; -+ } -+ flush_tlb_kernel_vm(); -+ -+ err = reader(dev->bitmap_offset, (char *) dev->bitmap, -+ dev->bitmap_len, &dev->cow_dev); -+ if(err < 0){ -+ printk(KERN_ERR "Failed to read COW bitmap\n"); -+ vfree(dev->bitmap); -+ goto out; -+ } -+ -+ dev_ioctl = dev->backing_bdev->bd_op->ioctl; -+ fs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = (*dev_ioctl)(inode, filp, BLKGETSIZE, -+ (unsigned long) &sizes[offset]); -+ set_fs(fs); -+ if(err){ -+ printk(KERN_ERR "cow_open - BLKGETSIZE failed, " -+ "error = %d\n", err); -+ goto out; -+ } -+ -+ kernel_thread(cow_thread, dev, -+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND); -+ down(&dev->sem); -+ } -+ dev->count++; -+ out: -+ spin_unlock(&cow_lock); -+ return(err); -+} -+ -+static int cow_release(struct inode * inode, struct file * file) -+{ -+ struct cow *dev; -+ int n, err; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ if(n >= MAX_DEV) -+ return(-ENODEV); -+ dev = &cow_dev[n]; -+ -+ spin_lock(&cow_lock); -+ -+ if(--dev->count > 0) -+ goto out; -+ -+ err = blkdev_put(dev->cow_bdev, BDEV_RAW); -+ if(err) -+ printk("cow_release - blkdev_put of cow device failed, " -+ "error = %d\n", err); -+ bdput(dev->cow_bdev); -+ dev->cow_bdev = 0; -+ -+ err = blkdev_put(dev->backing_bdev, BDEV_RAW); -+ if(err) -+ printk("cow_release - blkdev_put of backing device failed, " -+ "error = %d\n", err); -+ bdput(dev->backing_bdev); -+ dev->backing_bdev = 0; -+ -+ out: -+ spin_unlock(&cow_lock); -+ return(0); -+} -+ -+static int cow_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct cow *dev; -+ int (*dev_ioctl)(struct inode *, struct file *, unsigned int, -+ unsigned long); -+ int n; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ if(n >= MAX_DEV) -+ return(-ENODEV); -+ dev = &cow_dev[n]; -+ -+ dev_ioctl = dev->backing_bdev->bd_op->ioctl; -+ return((*dev_ioctl)(inode, file, cmd, arg)); -+} -+ -+static int cow_revalidate(kdev_t rdev) -+{ -+ printk(KERN_ERR "Need to implement cow_revalidate\n"); -+ return(0); -+} -+ -+static int parse_unit(char **ptr) -+{ -+ char *str = *ptr, *end; -+ int n = -1; -+ -+ if(isdigit(*str)) { -+ n = simple_strtoul(str, &end, 0); -+ if(end == str) -+ return(-1); -+ *ptr = end; -+ } -+ else if (('a' <= *str) && (*str <= 'h')) { -+ n = *str - 'a'; -+ str++; -+ *ptr = str; -+ } -+ return(n); -+} -+ -+static int cow_setup(char *str) -+{ -+ struct cow *dev; -+ char *cow_name, *backing_name; -+ int unit; -+ -+ unit = parse_unit(&str); -+ if(unit < 0){ -+ printk(KERN_ERR "cow_setup - Couldn't parse unit number\n"); -+ return(1); -+ } -+ -+ if(*str != '='){ -+ printk(KERN_ERR "cow_setup - Missing '=' after unit " -+ "number\n"); -+ return(1); -+ } -+ str++; -+ -+ cow_name = str; -+ backing_name = strchr(str, ','); -+ if(backing_name == NULL){ -+ printk(KERN_ERR "cow_setup - missing backing device name\n"); -+ return(0); -+ } -+ *backing_name = '\0'; -+ backing_name++; -+ -+ spin_lock(&cow_lock); -+ -+ dev = &cow_dev[unit]; -+ dev->cow_path = cow_name; -+ dev->backing_path = backing_name; -+ -+ spin_unlock(&cow_lock); -+ return(0); -+} -+ -+__setup("cow", cow_setup); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/cow_sys.h um/arch/um/drivers/cow_sys.h ---- orig/arch/um/drivers/cow_sys.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/cow_sys.h 2003-12-17 10:53:03.000000000 -0500 -@@ -0,0 +1,48 @@ -+#ifndef __COW_SYS_H__ -+#define __COW_SYS_H__ -+ -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "user.h" -+ -+static inline void *cow_malloc(int size) -+{ -+ return(um_kmalloc(size)); -+} -+ -+static inline void cow_free(void *ptr) -+{ -+ kfree(ptr); -+} -+ -+#define cow_printf printk -+ -+static inline char *cow_strdup(char *str) -+{ -+ return(uml_strdup(str)); -+} -+ -+static inline int cow_seek_file(int fd, __u64 offset) -+{ -+ return(os_seek_file(fd, offset)); -+} -+ -+static inline int cow_file_size(char *file, __u64 *size_out) -+{ -+ return(os_file_size(file, size_out)); -+} -+ -+static inline int cow_write_file(int fd, char *buf, int size) -+{ -+ return(os_write_file(fd, buf, size)); -+} -+ -+#endif -+ -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/cow_user.c um/arch/um/drivers/cow_user.c ---- orig/arch/um/drivers/cow_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/cow_user.c 2004-01-10 05:56:22.000000000 -0500 -@@ -0,0 +1,375 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "os.h" -+ -+#include "cow.h" -+#include "cow_sys.h" -+ -+#define PATH_LEN_V1 256 -+ -+struct cow_header_v1 { -+ int magic; -+ int version; -+ char backing_file[PATH_LEN_V1]; -+ time_t mtime; -+ __u64 size; -+ int sectorsize; -+}; -+ -+#define PATH_LEN_V2 MAXPATHLEN -+ -+struct cow_header_v2 { -+ unsigned long magic; -+ unsigned long version; -+ char backing_file[PATH_LEN_V2]; -+ time_t mtime; -+ __u64 size; -+ int sectorsize; -+}; -+ -+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in -+ * case other systems have different values for MAXPATHLEN -+ */ -+#define PATH_LEN_V3 4096 -+ -+/* Changes from V2 - -+ * PATH_LEN_V3 as described above -+ * Explicitly specify field bit lengths for systems with different -+ * lengths for the usual C types. Not sure whether char or -+ * time_t should be changed, this can be changed later without -+ * breaking compatibility -+ * Add alignment field so that different alignments can be used for the -+ * bitmap and data -+ * Add cow_format field to allow for the possibility of different ways -+ * of specifying the COW blocks. For now, the only value is 0, -+ * for the traditional COW bitmap. -+ * Move the backing_file field to the end of the header. This allows -+ * for the possibility of expanding it into the padding required -+ * by the bitmap alignment. -+ * The bitmap and data portions of the file will be aligned as specified -+ * by the alignment field. This is to allow COW files to be -+ * put on devices with restrictions on access alignments, such as -+ * /dev/raw, with a 512 byte alignment restriction. This also -+ * allows the data to be more aligned more strictly than on -+ * sector boundaries. This is needed for ubd-mmap, which needs -+ * the data to be page aligned. -+ * Fixed (finally!) the rounding bug -+ */ -+ -+struct cow_header_v3 { -+ __u32 magic; -+ __u32 version; -+ time_t mtime; -+ __u64 size; -+ __u32 sectorsize; -+ __u32 alignment; -+ __u32 cow_format; -+ char backing_file[PATH_LEN_V3]; -+}; -+ -+/* COW format definitions - for now, we have only the usual COW bitmap */ -+#define COW_BITMAP 0 -+ -+union cow_header { -+ struct cow_header_v1 v1; -+ struct cow_header_v2 v2; -+ struct cow_header_v3 v3; -+}; -+ -+#define COW_MAGIC 0x4f4f4f4d /* MOOO */ -+#define COW_VERSION 3 -+ -+#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) -+#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) -+ -+void cow_sizes(int version, __u64 size, int sectorsize, int align, -+ int bitmap_offset, unsigned long *bitmap_len_out, -+ int *data_offset_out) -+{ -+ if(version < 3){ -+ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); -+ -+ *data_offset_out = bitmap_offset + *bitmap_len_out; -+ *data_offset_out = (*data_offset_out + sectorsize - 1) / -+ sectorsize; -+ *data_offset_out *= sectorsize; -+ } -+ else { -+ *bitmap_len_out = DIV_ROUND(size, sectorsize); -+ *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8); -+ -+ *data_offset_out = bitmap_offset + *bitmap_len_out; -+ *data_offset_out = ROUND_UP(*data_offset_out, align); -+ } -+} -+ -+static int absolutize(char *to, int size, char *from) -+{ -+ char save_cwd[256], *slash; -+ int remaining; -+ -+ if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { -+ cow_printf("absolutize : unable to get cwd - errno = %d\n", -+ errno); -+ return(-1); -+ } -+ slash = strrchr(from, '/'); -+ if(slash != NULL){ -+ *slash = '\0'; -+ if(chdir(from)){ -+ *slash = '/'; -+ cow_printf("absolutize : Can't cd to '%s' - " -+ "errno = %d\n", from, errno); -+ return(-1); -+ } -+ *slash = '/'; -+ if(getcwd(to, size) == NULL){ -+ cow_printf("absolutize : unable to get cwd of '%s' - " -+ "errno = %d\n", from, errno); -+ return(-1); -+ } -+ remaining = size - strlen(to); -+ if(strlen(slash) + 1 > remaining){ -+ cow_printf("absolutize : unable to fit '%s' into %d " -+ "chars\n", from, size); -+ return(-1); -+ } -+ strcat(to, slash); -+ } -+ else { -+ if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ -+ cow_printf("absolutize : unable to fit '%s' into %d " -+ "chars\n", from, size); -+ return(-1); -+ } -+ strcpy(to, save_cwd); -+ strcat(to, "/"); -+ strcat(to, from); -+ } -+ chdir(save_cwd); -+ return(0); -+} -+ -+int write_cow_header(char *cow_file, int fd, char *backing_file, -+ int sectorsize, int alignment, long long *size) -+{ -+ struct cow_header_v3 *header; -+ unsigned long modtime; -+ int err; -+ -+ err = cow_seek_file(fd, 0); -+ if(err < 0){ -+ cow_printf("write_cow_header - lseek failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ header = cow_malloc(sizeof(*header)); -+ if(header == NULL){ -+ cow_printf("Failed to allocate COW V3 header\n"); -+ goto out; -+ } -+ header->magic = htonl(COW_MAGIC); -+ header->version = htonl(COW_VERSION); -+ -+ err = -EINVAL; -+ if(strlen(backing_file) > sizeof(header->backing_file) - 1){ -+ cow_printf("Backing file name \"%s\" is too long - names are " -+ "limited to %d characters\n", backing_file, -+ sizeof(header->backing_file) - 1); -+ goto out_free; -+ } -+ -+ if(absolutize(header->backing_file, sizeof(header->backing_file), -+ backing_file)) -+ goto out_free; -+ -+ err = os_file_modtime(header->backing_file, &modtime); -+ if(err < 0){ -+ cow_printf("Backing file '%s' mtime request failed, " -+ "err = %d\n", header->backing_file, -err); -+ goto out_free; -+ } -+ -+ err = cow_file_size(header->backing_file, size); -+ if(err < 0){ -+ cow_printf("Couldn't get size of backing file '%s', " -+ "err = %d\n", header->backing_file, -err); -+ goto out_free; -+ } -+ -+ header->mtime = htonl(modtime); -+ header->size = htonll(*size); -+ header->sectorsize = htonl(sectorsize); -+ header->alignment = htonl(alignment); -+ header->cow_format = COW_BITMAP; -+ -+ err = os_write_file(fd, header, sizeof(*header)); -+ if(err != sizeof(*header)){ -+ cow_printf("Write of header to new COW file '%s' failed, " -+ "err = %d\n", cow_file, -err); -+ goto out_free; -+ } -+ err = 0; -+ out_free: -+ cow_free(header); -+ out: -+ return(err); -+} -+ -+int file_reader(__u64 offset, char *buf, int len, void *arg) -+{ -+ int fd = *((int *) arg); -+ -+ return(pread(fd, buf, len, offset)); -+} -+ -+/* XXX Need to sanity-check the values read from the header */ -+ -+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, -+ __u32 *version_out, char **backing_file_out, -+ time_t *mtime_out, __u64 *size_out, -+ int *sectorsize_out, __u32 *align_out, -+ int *bitmap_offset_out) -+{ -+ union cow_header *header; -+ char *file; -+ int err, n; -+ unsigned long version, magic; -+ -+ header = cow_malloc(sizeof(*header)); -+ if(header == NULL){ -+ cow_printf("read_cow_header - Failed to allocate header\n"); -+ return(-ENOMEM); -+ } -+ err = -EINVAL; -+ n = (*reader)(0, (char *) header, sizeof(*header), arg); -+ if(n < offsetof(typeof(header->v1), backing_file)){ -+ cow_printf("read_cow_header - short header\n"); -+ goto out; -+ } -+ -+ magic = header->v1.magic; -+ if(magic == COW_MAGIC) { -+ version = header->v1.version; -+ } -+ else if(magic == ntohl(COW_MAGIC)){ -+ version = ntohl(header->v1.version); -+ } -+ /* No error printed because the non-COW case comes through here */ -+ else goto out; -+ -+ *version_out = version; -+ -+ if(version == 1){ -+ if(n < sizeof(header->v1)){ -+ cow_printf("read_cow_header - failed to read V1 " -+ "header\n"); -+ goto out; -+ } -+ *mtime_out = header->v1.mtime; -+ *size_out = header->v1.size; -+ *sectorsize_out = header->v1.sectorsize; -+ *bitmap_offset_out = sizeof(header->v1); -+ *align_out = *sectorsize_out; -+ file = header->v1.backing_file; -+ } -+ else if(version == 2){ -+ if(n < sizeof(header->v2)){ -+ cow_printf("read_cow_header - failed to read V2 " -+ "header\n"); -+ goto out; -+ } -+ *mtime_out = ntohl(header->v2.mtime); -+ *size_out = ntohll(header->v2.size); -+ *sectorsize_out = ntohl(header->v2.sectorsize); -+ *bitmap_offset_out = sizeof(header->v2); -+ *align_out = *sectorsize_out; -+ file = header->v2.backing_file; -+ } -+ else if(version == 3){ -+ if(n < sizeof(header->v3)){ -+ cow_printf("read_cow_header - failed to read V2 " -+ "header\n"); -+ goto out; -+ } -+ *mtime_out = ntohl(header->v3.mtime); -+ *size_out = ntohll(header->v3.size); -+ *sectorsize_out = ntohl(header->v3.sectorsize); -+ *align_out = ntohl(header->v3.alignment); -+ *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); -+ file = header->v3.backing_file; -+ } -+ else { -+ cow_printf("read_cow_header - invalid COW version\n"); -+ goto out; -+ } -+ err = -ENOMEM; -+ *backing_file_out = cow_strdup(file); -+ if(*backing_file_out == NULL){ -+ cow_printf("read_cow_header - failed to allocate backing " -+ "file\n"); -+ goto out; -+ } -+ err = 0; -+ out: -+ cow_free(header); -+ return(err); -+} -+ -+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, -+ int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out) -+{ -+ __u64 size, offset; -+ char zero = 0; -+ int err; -+ -+ err = write_cow_header(cow_file, fd, backing_file, sectorsize, -+ alignment, &size); -+ if(err) -+ goto out; -+ -+ *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); -+ cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, -+ bitmap_len_out, data_offset_out); -+ -+ offset = *data_offset_out + size - sizeof(zero); -+ err = cow_seek_file(fd, offset); -+ if(err < 0){ -+ cow_printf("cow bitmap lseek failed : err = %d\n", -err); -+ goto out; -+ } -+ -+ /* does not really matter how much we write it is just to set EOF -+ * this also sets the entire COW bitmap -+ * to zero without having to allocate it -+ */ -+ err = cow_write_file(fd, &zero, sizeof(zero)); -+ if(err != sizeof(zero)){ -+ cow_printf("Write of bitmap to new COW file '%s' failed, " -+ "err = %d\n", cow_file, -err); -+ err = -EINVAL; -+ goto out; -+ } -+ -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/daemon.h um/arch/um/drivers/daemon.h ---- orig/arch/um/drivers/daemon.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/daemon.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+#define SWITCH_VERSION 3 -+ -+struct daemon_data { -+ char *sock_type; -+ char *ctl_sock; -+ void *ctl_addr; -+ void *data_addr; -+ void *local_addr; -+ int fd; -+ int control; -+ void *dev; -+}; -+ -+extern struct net_user_info daemon_user_info; -+ -+extern int daemon_user_write(int fd, void *buf, int len, -+ struct daemon_data *pri); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/daemon_kern.c um/arch/um/drivers/daemon_kern.c ---- orig/arch/um/drivers/daemon_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/daemon_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "daemon.h" -+ -+struct daemon_init { -+ char *sock_type; -+ char *ctl_sock; -+}; -+ -+void daemon_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct daemon_data *dpri; -+ struct daemon_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ dpri = (struct daemon_data *) pri->user; -+ *dpri = ((struct daemon_data) -+ { .sock_type = init->sock_type, -+ .ctl_sock = init->ctl_sock, -+ .ctl_addr = NULL, -+ .data_addr = NULL, -+ .local_addr = NULL, -+ .fd = -1, -+ .control = -1, -+ .dev = dev }); -+ -+ printk("daemon backend (uml_switch version %d) - %s:%s", -+ SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); -+ printk("\n"); -+} -+ -+static int daemon_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int daemon_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(daemon_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct daemon_data *) &lp->user)); -+} -+ -+static struct net_kern_info daemon_kern_info = { -+ .init = daemon_init, -+ .protocol = eth_protocol, -+ .read = daemon_read, -+ .write = daemon_write, -+}; -+ -+int daemon_setup(char *str, char **mac_out, void *data) -+{ -+ struct daemon_init *init = data; -+ char *remain; -+ -+ *init = ((struct daemon_init) -+ { .sock_type = "unix", -+ .ctl_sock = "/tmp/uml.ctl" }); -+ -+ remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, -+ NULL); -+ if(remain != NULL) -+ printk(KERN_WARNING "daemon_setup : Ignoring data socket " -+ "specification\n"); -+ -+ return(1); -+} -+ -+static struct transport daemon_transport = { -+ .list = LIST_HEAD_INIT(daemon_transport.list), -+ .name = "daemon", -+ .setup = daemon_setup, -+ .user = &daemon_user_info, -+ .kern = &daemon_kern_info, -+ .private_size = sizeof(struct daemon_data), -+ .setup_size = sizeof(struct daemon_init), -+}; -+ -+static int register_daemon(void) -+{ -+ register_transport(&daemon_transport); -+ return(1); -+} -+ -+__initcall(register_daemon); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/daemon_user.c um/arch/um/drivers/daemon_user.c ---- orig/arch/um/drivers/daemon_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/daemon_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,197 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "net_user.h" -+#include "daemon.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+enum request_type { REQ_NEW_CONTROL }; -+ -+#define SWITCH_MAGIC 0xfeedface -+ -+struct request_v3 { -+ uint32_t magic; -+ uint32_t version; -+ enum request_type type; -+ struct sockaddr_un sock; -+}; -+ -+static struct sockaddr_un *new_addr(void *name, int len) -+{ -+ struct sockaddr_un *sun; -+ -+ sun = um_kmalloc(sizeof(struct sockaddr_un)); -+ if(sun == NULL){ -+ printk("new_addr: allocation of sockaddr_un failed\n"); -+ return(NULL); -+ } -+ sun->sun_family = AF_UNIX; -+ memcpy(sun->sun_path, name, len); -+ return(sun); -+} -+ -+static int connect_to_switch(struct daemon_data *pri) -+{ -+ struct sockaddr_un *ctl_addr = pri->ctl_addr; -+ struct sockaddr_un *local_addr = pri->local_addr; -+ struct sockaddr_un *sun; -+ struct request_v3 req; -+ int fd, n, err; -+ -+ pri->control = socket(AF_UNIX, SOCK_STREAM, 0); -+ if(pri->control < 0){ -+ printk("daemon_open : control socket failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ if(connect(pri->control, (struct sockaddr *) ctl_addr, -+ sizeof(*ctl_addr)) < 0){ -+ printk("daemon_open : control connect failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out; -+ } -+ -+ fd = socket(AF_UNIX, SOCK_DGRAM, 0); -+ if(fd < 0){ -+ printk("daemon_open : data socket failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out; -+ } -+ if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ -+ printk("daemon_open : data bind failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out_close; -+ } -+ -+ sun = um_kmalloc(sizeof(struct sockaddr_un)); -+ if(sun == NULL){ -+ printk("new_addr: allocation of sockaddr_un failed\n"); -+ err = -ENOMEM; -+ goto out_close; -+ } -+ -+ req.magic = SWITCH_MAGIC; -+ req.version = SWITCH_VERSION; -+ req.type = REQ_NEW_CONTROL; -+ req.sock = *local_addr; -+ n = os_write_file(pri->control, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ printk("daemon_open : control setup request failed, err = %d\n", -+ -n); -+ err = -ENOTCONN; -+ goto out; -+ } -+ -+ n = os_read_file(pri->control, sun, sizeof(*sun)); -+ if(n != sizeof(*sun)){ -+ printk("daemon_open : read of data socket failed, err = %d\n", -+ -n); -+ err = -ENOTCONN; -+ goto out_close; -+ } -+ -+ pri->data_addr = sun; -+ return(fd); -+ -+ out_close: -+ os_close_file(fd); -+ out: -+ os_close_file(pri->control); -+ return(err); -+} -+ -+static void daemon_user_init(void *data, void *dev) -+{ -+ struct daemon_data *pri = data; -+ struct timeval tv; -+ struct { -+ char zero; -+ int pid; -+ int usecs; -+ } name; -+ -+ if(!strcmp(pri->sock_type, "unix")) -+ pri->ctl_addr = new_addr(pri->ctl_sock, -+ strlen(pri->ctl_sock) + 1); -+ name.zero = 0; -+ name.pid = os_getpid(); -+ gettimeofday(&tv, NULL); -+ name.usecs = tv.tv_usec; -+ pri->local_addr = new_addr(&name, sizeof(name)); -+ pri->dev = dev; -+ pri->fd = connect_to_switch(pri); -+ if(pri->fd < 0){ -+ kfree(pri->local_addr); -+ pri->local_addr = NULL; -+ } -+} -+ -+static int daemon_open(void *data) -+{ -+ struct daemon_data *pri = data; -+ return(pri->fd); -+} -+ -+static void daemon_remove(void *data) -+{ -+ struct daemon_data *pri = data; -+ -+ os_close_file(pri->fd); -+ os_close_file(pri->control); -+ if(pri->data_addr != NULL) kfree(pri->data_addr); -+ if(pri->ctl_addr != NULL) kfree(pri->ctl_addr); -+ if(pri->local_addr != NULL) kfree(pri->local_addr); -+} -+ -+int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) -+{ -+ struct sockaddr_un *data_addr = pri->data_addr; -+ -+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); -+} -+ -+static int daemon_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info daemon_user_info = { -+ .init = daemon_user_init, -+ .open = daemon_open, -+ .close = NULL, -+ .remove = daemon_remove, -+ .set_mtu = daemon_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/fd.c um/arch/um/drivers/fd.c ---- orig/arch/um/drivers/fd.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/fd.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,97 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include "user.h" -+#include "user_util.h" -+#include "chan_user.h" -+ -+struct fd_chan { -+ int fd; -+ int raw; -+ struct termios tt; -+ char str[sizeof("1234567890\0")]; -+}; -+ -+void *fd_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct fd_chan *data; -+ char *end; -+ int n; -+ -+ if(*str != ':'){ -+ printk("fd_init : channel type 'fd' must specify a file " -+ "descriptor\n"); -+ return(NULL); -+ } -+ str++; -+ n = strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk("fd_init : couldn't parse file descriptor '%s'\n", str); -+ return(NULL); -+ } -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) return(NULL); -+ *data = ((struct fd_chan) { .fd = n, -+ .raw = opts->raw }); -+ return(data); -+} -+ -+int fd_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct fd_chan *data = d; -+ -+ if(data->raw && isatty(data->fd)){ -+ tcgetattr(data->fd, &data->tt); -+ raw(data->fd, 0); -+ } -+ sprintf(data->str, "%d", data->fd); -+ *dev_out = data->str; -+ return(data->fd); -+} -+ -+void fd_close(int fd, void *d) -+{ -+ struct fd_chan *data = d; -+ -+ if(data->raw && isatty(fd)){ -+ tcsetattr(fd, TCSAFLUSH, &data->tt); -+ data->raw = 0; -+ } -+} -+ -+int fd_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct fd_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops fd_ops = { -+ .type = "fd", -+ .init = fd_init, -+ .open = fd_open, -+ .close = fd_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = fd_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 1, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/harddog_kern.c um/arch/um/drivers/harddog_kern.c ---- orig/arch/um/drivers/harddog_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/harddog_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,194 @@ -+/* UML hardware watchdog, shamelessly stolen from: -+ * -+ * SoftDog 0.05: A Software Watchdog Device -+ * -+ * (c) Copyright 1996 Alan Cox , All Rights Reserved. -+ * http://www.redhat.com -+ * -+ * 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. -+ * -+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide -+ * warranty for any of this software. This material is provided -+ * "AS-IS" and at no charge. -+ * -+ * (c) Copyright 1995 Alan Cox -+ * -+ * Software only watchdog driver. Unlike its big brother the WDT501P -+ * driver this won't always recover a failed machine. -+ * -+ * 03/96: Angelo Haritsis : -+ * Modularised. -+ * Added soft_margin; use upon insmod to change the timer delay. -+ * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate -+ * minors. -+ * -+ * 19980911 Alan Cox -+ * Made SMP safe for 2.3.x -+ * -+ * 20011127 Joel Becker (jlbec@evilplan.org> -+ * Added soft_noboot; Allows testing the softdog trigger without -+ * requiring a recompile. -+ * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "helper.h" -+#include "mconsole.h" -+ -+MODULE_LICENSE("GPL"); -+ -+/* Locked by the BKL in harddog_open and harddog_release */ -+static int timer_alive; -+static int harddog_in_fd = -1; -+static int harddog_out_fd = -1; -+ -+/* -+ * Allow only one person to hold it open -+ */ -+ -+extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); -+ -+static int harddog_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ char *sock = NULL; -+ -+ lock_kernel(); -+ if(timer_alive) -+ return -EBUSY; -+#ifdef CONFIG_HARDDOG_NOWAYOUT -+ MOD_INC_USE_COUNT; -+#endif -+ -+#ifdef CONFIG_MCONSOLE -+ sock = mconsole_notify_socket(); -+#endif -+ err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock); -+ if(err) return(err); -+ -+ timer_alive = 1; -+ unlock_kernel(); -+ return 0; -+} -+ -+extern void stop_watchdog(int in_fd, int out_fd); -+ -+static int harddog_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * Shut off the timer. -+ */ -+ lock_kernel(); -+ -+ stop_watchdog(harddog_in_fd, harddog_out_fd); -+ harddog_in_fd = -1; -+ harddog_out_fd = -1; -+ -+ timer_alive=0; -+ unlock_kernel(); -+ return 0; -+} -+ -+extern int ping_watchdog(int fd); -+ -+static ssize_t harddog_write(struct file *file, const char *data, size_t len, -+ loff_t *ppos) -+{ -+ /* Can't seek (pwrite) on this device */ -+ if (ppos != &file->f_pos) -+ return -ESPIPE; -+ -+ /* -+ * Refresh the timer. -+ */ -+ if(len) -+ return(ping_watchdog(harddog_out_fd)); -+ return 0; -+} -+ -+static int harddog_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ static struct watchdog_info ident = { -+ WDIOF_SETTIMEOUT, -+ 0, -+ "UML Hardware Watchdog" -+ }; -+ switch (cmd) { -+ default: -+ return -ENOTTY; -+ case WDIOC_GETSUPPORT: -+ if(copy_to_user((struct harddog_info *)arg, &ident, -+ sizeof(ident))) -+ return -EFAULT; -+ return 0; -+ case WDIOC_GETSTATUS: -+ case WDIOC_GETBOOTSTATUS: -+ return put_user(0,(int *)arg); -+ case WDIOC_KEEPALIVE: -+ return(ping_watchdog(harddog_out_fd)); -+ } -+} -+ -+static struct file_operations harddog_fops = { -+ .owner = THIS_MODULE, -+ .write = harddog_write, -+ .ioctl = harddog_ioctl, -+ .open = harddog_open, -+ .release = harddog_release, -+}; -+ -+static struct miscdevice harddog_miscdev = { -+ .minor = WATCHDOG_MINOR, -+ .name = "watchdog", -+ .fops = &harddog_fops, -+}; -+ -+static char banner[] __initdata = KERN_INFO "UML Watchdog Timer\n"; -+ -+static int __init harddog_init(void) -+{ -+ int ret; -+ -+ ret = misc_register(&harddog_miscdev); -+ -+ if (ret) -+ return ret; -+ -+ printk(banner); -+ -+ return(0); -+} -+ -+static void __exit harddog_exit(void) -+{ -+ misc_deregister(&harddog_miscdev); -+} -+ -+module_init(harddog_init); -+module_exit(harddog_exit); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/harddog_user.c um/arch/um/drivers/harddog_user.c ---- orig/arch/um/drivers/harddog_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/harddog_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include "user_util.h" -+#include "user.h" -+#include "helper.h" -+#include "mconsole.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+struct dog_data { -+ int stdin; -+ int stdout; -+ int close_me[2]; -+}; -+ -+static void pre_exec(void *d) -+{ -+ struct dog_data *data = d; -+ -+ dup2(data->stdin, 0); -+ dup2(data->stdout, 1); -+ dup2(data->stdout, 2); -+ os_close_file(data->stdin); -+ os_close_file(data->stdout); -+ os_close_file(data->close_me[0]); -+ os_close_file(data->close_me[1]); -+} -+ -+int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) -+{ -+ struct dog_data data; -+ int in_fds[2], out_fds[2], pid, n, err; -+ char pid_buf[sizeof("nnnnn\0")], c; -+ char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; -+ char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, -+ NULL }; -+ char **args = NULL; -+ -+ err = os_pipe(in_fds, 1, 0); -+ if(err < 0){ -+ printk("harddog_open - os_pipe failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ err = os_pipe(out_fds, 1, 0); -+ if(err < 0){ -+ printk("harddog_open - os_pipe failed, err = %d\n", -err); -+ goto out_close_in; -+ } -+ -+ data.stdin = out_fds[0]; -+ data.stdout = in_fds[1]; -+ data.close_me[0] = out_fds[1]; -+ data.close_me[1] = in_fds[0]; -+ -+ if(sock != NULL){ -+ mconsole_args[2] = sock; -+ args = mconsole_args; -+ } -+ else { -+ /* XXX The os_getpid() is not SMP correct */ -+ sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); -+ args = pid_args; -+ } -+ -+ pid = run_helper(pre_exec, &data, args, NULL); -+ -+ os_close_file(out_fds[0]); -+ os_close_file(in_fds[1]); -+ -+ if(pid < 0){ -+ err = -pid; -+ printk("harddog_open - run_helper failed, errno = %d\n", -err); -+ goto out_close_out; -+ } -+ -+ n = os_read_file(in_fds[0], &c, sizeof(c)); -+ if(n == 0){ -+ printk("harddog_open - EOF on watchdog pipe\n"); -+ helper_wait(pid); -+ err = -EIO; -+ goto out_close_out; -+ } -+ else if(n < 0){ -+ printk("harddog_open - read of watchdog pipe failed, " -+ "err = %d\n", -n); -+ helper_wait(pid); -+ err = n; -+ goto out_close_out; -+ } -+ *in_fd_ret = in_fds[0]; -+ *out_fd_ret = out_fds[1]; -+ return(0); -+ -+ out_close_in: -+ os_close_file(in_fds[0]); -+ os_close_file(in_fds[1]); -+ out_close_out: -+ os_close_file(out_fds[0]); -+ os_close_file(out_fds[1]); -+ out: -+ return(err); -+} -+ -+void stop_watchdog(int in_fd, int out_fd) -+{ -+ os_close_file(in_fd); -+ os_close_file(out_fd); -+} -+ -+int ping_watchdog(int fd) -+{ -+ int n; -+ char c = '\n'; -+ -+ n = os_write_file(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("ping_watchdog - write failed, err = %d\n", -n); -+ if(n < 0) -+ return(n); -+ return(-EIO); -+ } -+ return 1; -+ -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/hostaudio_kern.c um/arch/um/drivers/hostaudio_kern.c ---- orig/arch/um/drivers/hostaudio_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/hostaudio_kern.c 2004-02-12 05:46:22.000000000 -0500 -@@ -0,0 +1,352 @@ -+/* -+ * Copyright (C) 2002 Steve Schmidtke -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/slab.h" -+#include "linux/fs.h" -+#include "linux/sound.h" -+#include "linux/soundcard.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+#include "init.h" -+#include "os.h" -+ -+struct hostaudio_state { -+ int fd; -+}; -+ -+struct hostmixer_state { -+ int fd; -+}; -+ -+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" -+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" -+ -+/* Only changed from linux_main at boot time */ -+char *dsp = HOSTAUDIO_DEV_DSP; -+char *mixer = HOSTAUDIO_DEV_MIXER; -+ -+#define DSP_HELP \ -+" This is used to specify the host dsp device to the hostaudio driver.\n" \ -+" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" -+ -+#define MIXER_HELP \ -+" This is used to specify the host mixer device to the hostaudio driver.\n" \ -+" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" -+ -+#ifndef MODULE -+static int set_dsp(char *name, int *add) -+{ -+ dsp = name; -+ return(0); -+} -+ -+__uml_setup("dsp=", set_dsp, "dsp=\n" DSP_HELP); -+ -+static int set_mixer(char *name, int *add) -+{ -+ mixer = name; -+ return(0); -+} -+ -+__uml_setup("mixer=", set_mixer, "mixer=\n" MIXER_HELP); -+ -+#else /*MODULE*/ -+ -+MODULE_PARM(dsp, "s"); -+MODULE_PARM_DESC(dsp, DSP_HELP); -+ -+MODULE_PARM(mixer, "s"); -+MODULE_PARM_DESC(mixer, MIXER_HELP); -+ -+#endif -+ -+/* /dev/dsp file operations */ -+ -+static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ struct hostaudio_state *state = file->private_data; -+ void *kbuf; -+ int err; -+ -+#ifdef DEBUG -+ printk("hostaudio: read called, count = %d\n", count); -+#endif -+ -+ kbuf = kmalloc(count, GFP_KERNEL); -+ if(kbuf == NULL) -+ return(-ENOMEM); -+ -+ err = os_read_file(state->fd, kbuf, count); -+ if(err < 0) -+ goto out; -+ -+ if(copy_to_user(buffer, kbuf, err)) -+ err = -EFAULT; -+ -+ out: -+ kfree(kbuf); -+ return(err); -+} -+ -+static ssize_t hostaudio_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct hostaudio_state *state = file->private_data; -+ void *kbuf; -+ int err; -+ -+#ifdef DEBUG -+ printk("hostaudio: write called, count = %d\n", count); -+#endif -+ -+ kbuf = kmalloc(count, GFP_KERNEL); -+ if(kbuf == NULL) -+ return(-ENOMEM); -+ -+ err = -EFAULT; -+ if(copy_from_user(kbuf, buffer, count)) -+ goto out; -+ -+ err = os_write_file(state->fd, kbuf, count); -+ if(err < 0) -+ goto out; -+ *ppos += err; -+ -+ out: -+ kfree(kbuf); -+ return(err); -+} -+ -+static unsigned int hostaudio_poll(struct file *file, -+ struct poll_table_struct *wait) -+{ -+ unsigned int mask = 0; -+ -+#ifdef DEBUG -+ printk("hostaudio: poll called (unimplemented)\n"); -+#endif -+ -+ return(mask); -+} -+ -+static int hostaudio_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hostaudio_state *state = file->private_data; -+ unsigned long data = 0; -+ int err; -+ -+#ifdef DEBUG -+ printk("hostaudio: ioctl called, cmd = %u\n", cmd); -+#endif -+ switch(cmd){ -+ case SNDCTL_DSP_SPEED: -+ case SNDCTL_DSP_STEREO: -+ case SNDCTL_DSP_GETBLKSIZE: -+ case SNDCTL_DSP_CHANNELS: -+ case SNDCTL_DSP_SUBDIVIDE: -+ case SNDCTL_DSP_SETFRAGMENT: -+ if(get_user(data, (int *) arg)) -+ return(-EFAULT); -+ break; -+ default: -+ break; -+ } -+ -+ err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data); -+ -+ switch(cmd){ -+ case SNDCTL_DSP_SPEED: -+ case SNDCTL_DSP_STEREO: -+ case SNDCTL_DSP_GETBLKSIZE: -+ case SNDCTL_DSP_CHANNELS: -+ case SNDCTL_DSP_SUBDIVIDE: -+ case SNDCTL_DSP_SETFRAGMENT: -+ if(put_user(data, (int *) arg)) -+ return(-EFAULT); -+ break; -+ default: -+ break; -+ } -+ -+ return(err); -+} -+ -+static int hostaudio_open(struct inode *inode, struct file *file) -+{ -+ struct hostaudio_state *state; -+ int r = 0, w = 0; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostaudio: open called (host: %s)\n", dsp); -+#endif -+ -+ state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); -+ if(state == NULL) -+ return(-ENOMEM); -+ -+ if(file->f_mode & FMODE_READ) r = 1; -+ if(file->f_mode & FMODE_WRITE) w = 1; -+ -+ ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); -+ if(ret < 0){ -+ kfree(state); -+ return(ret); -+ } -+ -+ state->fd = ret; -+ file->private_data = state; -+ return(0); -+} -+ -+static int hostaudio_release(struct inode *inode, struct file *file) -+{ -+ struct hostaudio_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostaudio: release called\n"); -+#endif -+ -+ os_close_file(state->fd); -+ kfree(state); -+ -+ return(0); -+} -+ -+/* /dev/mixer file operations */ -+ -+static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hostmixer_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostmixer: ioctl called\n"); -+#endif -+ -+ return(os_ioctl_generic(state->fd, cmd, arg)); -+} -+ -+static int hostmixer_open_mixdev(struct inode *inode, struct file *file) -+{ -+ struct hostmixer_state *state; -+ int r = 0, w = 0; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostmixer: open called (host: %s)\n", mixer); -+#endif -+ -+ state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); -+ if(state == NULL) return(-ENOMEM); -+ -+ if(file->f_mode & FMODE_READ) r = 1; -+ if(file->f_mode & FMODE_WRITE) w = 1; -+ -+ ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); -+ -+ if(ret < 0){ -+ printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", -+ dsp, -ret); -+ kfree(state); -+ return(ret); -+ } -+ -+ file->private_data = state; -+ return(0); -+} -+ -+static int hostmixer_release(struct inode *inode, struct file *file) -+{ -+ struct hostmixer_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostmixer: release called\n"); -+#endif -+ -+ os_close_file(state->fd); -+ kfree(state); -+ -+ return(0); -+} -+ -+ -+/* kernel module operations */ -+ -+static struct file_operations hostaudio_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = hostaudio_read, -+ .write = hostaudio_write, -+ .poll = hostaudio_poll, -+ .ioctl = hostaudio_ioctl, -+ .mmap = NULL, -+ .open = hostaudio_open, -+ .release = hostaudio_release, -+}; -+ -+static struct file_operations hostmixer_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .ioctl = hostmixer_ioctl_mixdev, -+ .open = hostmixer_open_mixdev, -+ .release = hostmixer_release, -+}; -+ -+struct { -+ int dev_audio; -+ int dev_mixer; -+} module_data; -+ -+MODULE_AUTHOR("Steve Schmidtke"); -+MODULE_DESCRIPTION("UML Audio Relay"); -+MODULE_LICENSE("GPL"); -+ -+static int __init hostaudio_init_module(void) -+{ -+ printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", -+ dsp, mixer); -+ -+ module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); -+ if(module_data.dev_audio < 0){ -+ printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); -+ return -ENODEV; -+ } -+ -+ module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); -+ if(module_data.dev_mixer < 0){ -+ printk(KERN_ERR "hostmixer: couldn't register mixer " -+ "device!\n"); -+ unregister_sound_dsp(module_data.dev_audio); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit hostaudio_cleanup_module (void) -+{ -+ unregister_sound_mixer(module_data.dev_mixer); -+ unregister_sound_dsp(module_data.dev_audio); -+} -+ -+module_init(hostaudio_init_module); -+module_exit(hostaudio_cleanup_module); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/line.c um/arch/um/drivers/line.c ---- orig/arch/um/drivers/line.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/line.c 2003-11-07 03:03:57.000000000 -0500 -@@ -0,0 +1,610 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "linux/list.h" -+#include "linux/devfs_fs_kernel.h" -+#include "asm/irq.h" -+#include "asm/uaccess.h" -+#include "chan_kern.h" -+#include "irq_user.h" -+#include "line.h" -+#include "kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "os.h" -+#include "irq_kern.h" -+ -+#define LINE_BUFSIZE 4096 -+ -+static void line_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct line *dev = data; -+ -+ if(dev->count > 0) -+ chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, -+ dev); -+} -+ -+static void line_timer_cb(void *arg) -+{ -+ struct line *dev = arg; -+ -+ line_interrupt(dev->driver->read_irq, dev, NULL); -+} -+ -+static int write_room(struct line *dev) -+{ -+ int n; -+ -+ if(dev->buffer == NULL) return(LINE_BUFSIZE - 1); -+ -+ n = dev->head - dev->tail; -+ if(n <= 0) n = LINE_BUFSIZE + n; -+ return(n - 1); -+} -+ -+static int buffer_data(struct line *line, const char *buf, int len) -+{ -+ int end, room; -+ -+ if(line->buffer == NULL){ -+ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); -+ if(line->buffer == NULL){ -+ printk("buffer_data - atomic allocation failed\n"); -+ return(0); -+ } -+ line->head = line->buffer; -+ line->tail = line->buffer; -+ } -+ -+ room = write_room(line); -+ len = (len > room) ? room : len; -+ -+ end = line->buffer + LINE_BUFSIZE - line->tail; -+ if(len < end){ -+ memcpy(line->tail, buf, len); -+ line->tail += len; -+ } -+ else { -+ memcpy(line->tail, buf, end); -+ buf += end; -+ len -= end; -+ memcpy(line->buffer, buf, len); -+ line->tail = line->buffer + len; -+ } -+ -+ return(len); -+} -+ -+static int flush_buffer(struct line *line) -+{ -+ int n, count; -+ -+ if((line->buffer == NULL) || (line->head == line->tail)) return(1); -+ -+ if(line->tail < line->head){ -+ count = line->buffer + LINE_BUFSIZE - line->head; -+ n = write_chan(&line->chan_list, line->head, count, -+ line->driver->write_irq); -+ if(n < 0) return(n); -+ if(n == count) line->head = line->buffer; -+ else { -+ line->head += n; -+ return(0); -+ } -+ } -+ -+ count = line->tail - line->head; -+ n = write_chan(&line->chan_list, line->head, count, -+ line->driver->write_irq); -+ if(n < 0) return(n); -+ -+ line->head += n; -+ return(line->head == line->tail); -+} -+ -+int line_write(struct line *lines, struct tty_struct *tty, int from_user, -+ const char *buf, int len) -+{ -+ struct line *line; -+ char *new; -+ unsigned long flags; -+ int n, err, i, ret = 0; -+ -+ if(tty->stopped) return 0; -+ -+ if(from_user){ -+ new = kmalloc(len, GFP_KERNEL); -+ if(new == NULL) -+ return(0); -+ n = copy_from_user(new, buf, len); -+ buf = new; -+ if(n == len){ -+ len = -EFAULT; -+ goto out_free; -+ } -+ -+ len -= n; -+ } -+ -+ i = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[i]; -+ -+ down(&line->sem); -+ if(line->head != line->tail){ -+ local_irq_save(flags); -+ ret += buffer_data(line, buf, len); -+ err = flush_buffer(line); -+ local_irq_restore(flags); -+ if(err <= 0) -+ goto out_up; -+ } -+ else { -+ n = write_chan(&line->chan_list, buf, len, -+ line->driver->write_irq); -+ if(n < 0){ -+ ret = n; -+ goto out_up; -+ } -+ -+ len -= n; -+ ret += n; -+ if(len > 0) -+ ret += buffer_data(line, buf + n, len); -+ } -+ out_up: -+ up(&line->sem); -+ -+ out_free: -+ if(from_user) -+ kfree(buf); -+ return(ret); -+} -+ -+static void line_write_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct line *dev = data; -+ struct tty_struct *tty = dev->tty; -+ int err; -+ -+ err = flush_buffer(dev); -+ if(err == 0) return; -+ else if(err < 0){ -+ dev->head = dev->buffer; -+ dev->tail = dev->buffer; -+ } -+ -+ if(tty == NULL) return; -+ -+ if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && -+ (tty->ldisc.write_wakeup != NULL)) -+ (tty->ldisc.write_wakeup)(tty); -+ -+ /* BLOCKING mode -+ * In blocking mode, everything sleeps on tty->write_wait. -+ * Sleeping in the console driver would break non-blocking -+ * writes. -+ */ -+ -+ if (waitqueue_active(&tty->write_wait)) -+ wake_up_interruptible(&tty->write_wait); -+ -+} -+ -+int line_setup_irq(int fd, int input, int output, void *data) -+{ -+ struct line *line = data; -+ struct line_driver *driver = line->driver; -+ int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; -+ -+ if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, -+ line_interrupt, flags, -+ driver->read_irq_name, line); -+ if(err) return(err); -+ if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, -+ line_write_interrupt, flags, -+ driver->write_irq_name, line); -+ line->have_irq = 1; -+ return(err); -+} -+ -+void line_disable(struct line *line, int current_irq) -+{ -+ if(!line->have_irq) return; -+ -+ if(line->driver->read_irq == current_irq) -+ free_irq_later(line->driver->read_irq, line); -+ else -+ free_irq(line->driver->read_irq, line); -+ -+ if(line->driver->write_irq == current_irq) -+ free_irq_later(line->driver->write_irq, line); -+ else -+ free_irq(line->driver->write_irq, line); -+ -+ line->have_irq = 0; -+} -+ -+int line_open(struct line *lines, struct tty_struct *tty, -+ struct chan_opts *opts) -+{ -+ struct line *line; -+ int n, err = 0; -+ -+ if(tty == NULL) n = 0; -+ else n = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[n]; -+ -+ down(&line->sem); -+ if(line->count == 0){ -+ if(!line->valid){ -+ err = -ENODEV; -+ goto out; -+ } -+ if(list_empty(&line->chan_list)){ -+ err = parse_chan_pair(line->init_str, &line->chan_list, -+ line->init_pri, n, opts); -+ if(err) goto out; -+ err = open_chan(&line->chan_list); -+ if(err) goto out; -+ } -+ enable_chan(&line->chan_list, line); -+ INIT_TQUEUE(&line->task, line_timer_cb, line); -+ } -+ -+ if(!line->sigio){ -+ chan_enable_winch(&line->chan_list, line); -+ line->sigio = 1; -+ } -+ -+ /* This is outside the if because the initial console is opened -+ * with tty == NULL -+ */ -+ line->tty = tty; -+ -+ if(tty != NULL){ -+ tty->driver_data = line; -+ chan_window_size(&line->chan_list, &tty->winsize.ws_row, -+ &tty->winsize.ws_col); -+ } -+ -+ line->count++; -+ out: -+ up(&line->sem); -+ return(err); -+} -+ -+void line_close(struct line *lines, struct tty_struct *tty) -+{ -+ struct line *line; -+ int n; -+ -+ if(tty == NULL) n = 0; -+ else n = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[n]; -+ -+ down(&line->sem); -+ line->count--; -+ -+ /* I don't like this, but I can't think of anything better. What's -+ * going on is that the tty is in the process of being closed for -+ * the last time. Its count hasn't been dropped yet, so it's still -+ * at 1. This may happen when line->count != 0 because of the initial -+ * console open (without a tty) bumping it up to 1. -+ */ -+ if((line->tty != NULL) && (line->tty->count == 1)) -+ line->tty = NULL; -+ if(line->count == 0) -+ line_disable(line, -1); -+ up(&line->sem); -+} -+ -+void close_lines(struct line *lines, int nlines) -+{ -+ int i; -+ -+ for(i = 0; i < nlines; i++) -+ close_chan(&lines[i].chan_list); -+} -+ -+int line_setup(struct line *lines, int num, char *init, int all_allowed) -+{ -+ int i, n; -+ char *end; -+ -+ if(*init == '=') n = -1; -+ else { -+ n = simple_strtoul(init, &end, 0); -+ if(*end != '='){ -+ printk(KERN_ERR "line_setup failed to parse \"%s\"\n", -+ init); -+ return(0); -+ } -+ init = end; -+ } -+ init++; -+ if((n >= 0) && (n >= num)){ -+ printk("line_setup - %d out of range ((0 ... %d) allowed)\n", -+ n, num); -+ return(0); -+ } -+ else if(n >= 0){ -+ if(lines[n].count > 0){ -+ printk("line_setup - device %d is open\n", n); -+ return(0); -+ } -+ if(lines[n].init_pri <= INIT_ONE){ -+ lines[n].init_pri = INIT_ONE; -+ if(!strcmp(init, "none")) lines[n].valid = 0; -+ else { -+ lines[n].init_str = init; -+ lines[n].valid = 1; -+ } -+ } -+ } -+ else if(!all_allowed){ -+ printk("line_setup - can't configure all devices from " -+ "mconsole\n"); -+ return(0); -+ } -+ else { -+ for(i = 0; i < num; i++){ -+ if(lines[i].init_pri <= INIT_ALL){ -+ lines[i].init_pri = INIT_ALL; -+ if(!strcmp(init, "none")) lines[i].valid = 0; -+ else { -+ lines[i].init_str = init; -+ lines[i].valid = 1; -+ } -+ } -+ } -+ } -+ return(1); -+} -+ -+int line_config(struct line *lines, int num, char *str) -+{ -+ char *new = uml_strdup(str); -+ -+ if(new == NULL){ -+ printk("line_config - uml_strdup failed\n"); -+ return(-ENOMEM); -+ } -+ return(!line_setup(lines, num, new, 0)); -+} -+ -+int line_get_config(char *name, struct line *lines, int num, char *str, -+ int size, char **error_out) -+{ -+ struct line *line; -+ char *end; -+ int dev, n = 0; -+ -+ dev = simple_strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ *error_out = "line_get_config failed to parse device number"; -+ return(0); -+ } -+ -+ if((dev < 0) || (dev >= num)){ -+ *error_out = "device number of of range"; -+ return(0); -+ } -+ -+ line = &lines[dev]; -+ -+ down(&line->sem); -+ if(!line->valid) -+ CONFIG_CHUNK(str, size, n, "none", 1); -+ else if(line->count == 0) -+ CONFIG_CHUNK(str, size, n, line->init_str, 1); -+ else n = chan_config_string(&line->chan_list, str, size, error_out); -+ up(&line->sem); -+ -+ return(n); -+} -+ -+int line_remove(struct line *lines, int num, char *str) -+{ -+ char config[sizeof("conxxxx=none\0")]; -+ -+ sprintf(config, "%s=none", str); -+ return(!line_setup(lines, num, config, 0)); -+} -+ -+static int line_write_room(struct tty_struct *tty) -+{ -+ struct line *dev = tty->driver_data; -+ -+ return(write_room(dev)); -+} -+ -+void line_register_devfs(struct lines *set, struct line_driver *line_driver, -+ struct tty_driver *driver, struct line *lines, -+ int nlines) -+{ -+ int err, i, n; -+ char *from, *to; -+ -+ driver->driver_name = line_driver->name; -+ driver->name = line_driver->devfs_name; -+ driver->major = line_driver->major; -+ driver->minor_start = line_driver->minor_start; -+ driver->type = line_driver->type; -+ driver->subtype = line_driver->subtype; -+ driver->magic = TTY_DRIVER_MAGIC; -+ driver->flags = TTY_DRIVER_REAL_RAW; -+ -+ n = set->num; -+ driver->num = n; -+ driver->table = kmalloc(n * sizeof(driver->table[0]), GFP_KERNEL); -+ driver->termios = kmalloc(n * sizeof(driver->termios[0]), GFP_KERNEL); -+ driver->termios_locked = kmalloc(n * sizeof(driver->termios_locked[0]), -+ GFP_KERNEL); -+ if((driver->table == NULL) || (driver->termios == NULL) || -+ (driver->termios_locked == NULL)) -+ panic("Failed to allocate driver table"); -+ -+ memset(driver->table, 0, n * sizeof(driver->table[0])); -+ memset(driver->termios, 0, n * sizeof(driver->termios[0])); -+ memset(driver->termios_locked, 0, -+ n * sizeof(driver->termios_locked[0])); -+ -+ driver->write_room = line_write_room; -+ driver->init_termios = tty_std_termios; -+ -+ if (tty_register_driver(driver)) -+ panic("line_register_devfs : Couldn't register driver\n"); -+ -+ from = line_driver->symlink_from; -+ to = line_driver->symlink_to; -+ err = devfs_mk_symlink(NULL, from, 0, to, NULL, NULL); -+ if(err) printk("Symlink creation from /dev/%s to /dev/%s " -+ "returned %d\n", from, to, err); -+ -+ for(i = 0; i < nlines; i++){ -+ if(!lines[i].valid) -+ tty_unregister_devfs(driver, driver->minor_start + i); -+ } -+ -+ mconsole_register_dev(&line_driver->mc); -+} -+ -+void lines_init(struct line *lines, int nlines) -+{ -+ struct line *line; -+ int i; -+ -+ for(i = 0; i < nlines; i++){ -+ line = &lines[i]; -+ INIT_LIST_HEAD(&line->chan_list); -+ sema_init(&line->sem, 1); -+ if(line->init_str != NULL){ -+ line->init_str = uml_strdup(line->init_str); -+ if(line->init_str == NULL) -+ printk("lines_init - uml_strdup returned " -+ "NULL\n"); -+ } -+ } -+} -+ -+struct winch { -+ struct list_head list; -+ int fd; -+ int tty_fd; -+ int pid; -+ struct line *line; -+}; -+ -+void winch_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct winch *winch = data; -+ struct tty_struct *tty; -+ int err; -+ char c; -+ -+ if(winch->fd != -1){ -+ err = generic_read(winch->fd, &c, NULL); -+ if(err < 0){ -+ if(err != -EAGAIN){ -+ printk("winch_interrupt : read failed, " -+ "errno = %d\n", -err); -+ printk("fd %d is losing SIGWINCH support\n", -+ winch->tty_fd); -+ return; -+ } -+ goto out; -+ } -+ } -+ tty = winch->line->tty; -+ if(tty != NULL){ -+ chan_window_size(&winch->line->chan_list, -+ &tty->winsize.ws_row, -+ &tty->winsize.ws_col); -+ kill_pg(tty->pgrp, SIGWINCH, 1); -+ } -+ out: -+ if(winch->fd != -1) -+ reactivate_fd(winch->fd, WINCH_IRQ); -+} -+ -+DECLARE_MUTEX(winch_handler_sem); -+LIST_HEAD(winch_handlers); -+ -+void register_winch_irq(int fd, int tty_fd, int pid, void *line) -+{ -+ struct winch *winch; -+ -+ down(&winch_handler_sem); -+ winch = kmalloc(sizeof(*winch), GFP_KERNEL); -+ if(winch == NULL){ -+ printk("register_winch_irq - kmalloc failed\n"); -+ goto out; -+ } -+ *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), -+ .fd = fd, -+ .tty_fd = tty_fd, -+ .pid = pid, -+ .line = line }); -+ list_add(&winch->list, &winch_handlers); -+ if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "winch", winch) < 0) -+ printk("register_winch_irq - failed to register IRQ\n"); -+ out: -+ up(&winch_handler_sem); -+} -+ -+static void winch_cleanup(void) -+{ -+ struct list_head *ele; -+ struct winch *winch; -+ -+ list_for_each(ele, &winch_handlers){ -+ winch = list_entry(ele, struct winch, list); -+ if(winch->fd != -1){ -+ deactivate_fd(winch->fd, WINCH_IRQ); -+ os_close_file(winch->fd); -+ } -+ if(winch->pid != -1) -+ os_kill_process(winch->pid, 1); -+ } -+} -+ -+__uml_exitcall(winch_cleanup); -+ -+char *add_xterm_umid(char *base) -+{ -+ char *umid, *title; -+ int len; -+ -+ umid = get_umid(1); -+ if(umid == NULL) return(base); -+ -+ len = strlen(base) + strlen(" ()") + strlen(umid) + 1; -+ title = kmalloc(len, GFP_KERNEL); -+ if(title == NULL){ -+ printk("Failed to allocate buffer for xterm title\n"); -+ return(base); -+ } -+ -+ strncpy(title, base, len); -+ len -= strlen(title); -+ snprintf(&title[strlen(title)], len, " (%s)", umid); -+ return(title); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/Makefile um/arch/um/drivers/Makefile ---- orig/arch/um/drivers/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/Makefile 2004-02-12 03:55:08.000000000 -0500 -@@ -0,0 +1,97 @@ -+# -+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := built-in.o -+ -+CHAN_OBJS := chan_kern.o chan_user.o line.o -+ -+list-multi := slip.o slirp.o daemon.o mcast.o mconsole.o net.o ubd.o \ -+ hostaudio.o pcap.o port.o harddog.o -+ -+slip-objs := slip_kern.o slip_user.o -+slirp-objs := slirp_kern.o slirp_user.o -+daemon-objs := daemon_kern.o daemon_user.o -+mcast-objs := mcast_kern.o mcast_user.o -+pcap-objs := pcap_kern.o pcap_user.o -+pcap-libs := -lpcap -L/usr/lib -+net-objs := net_kern.o net_user.o -+mconsole-objs := mconsole_kern.o mconsole_user.o -+hostaudio-objs := hostaudio_kern.o -+ubd-objs := ubd_kern.o ubd_user.o -+port-objs := port_kern.o port_user.o -+harddog-objs := harddog_kern.o harddog_user.o -+ -+export-objs := mconsole_kern.o -+ -+obj-y = -+obj-$(CONFIG_SSL) += ssl.o -+obj-$(CONFIG_UML_NET_SLIP) += slip.o -+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o -+obj-$(CONFIG_UML_NET_DAEMON) += daemon.o -+obj-$(CONFIG_UML_NET_MCAST) += mcast.o -+obj-$(CONFIG_UML_NET_PCAP) += pcap.o -+obj-$(CONFIG_UML_NET) += net.o -+obj-$(CONFIG_MCONSOLE) += mconsole.o -+obj-$(CONFIG_MMAPPER) += mmapper_kern.o -+obj-$(CONFIG_BLK_DEV_UBD) += ubd.o -+obj-$(CONFIG_HOSTAUDIO) += hostaudio.o -+obj-$(CONFIG_FD_CHAN) += fd.o -+obj-$(CONFIG_NULL_CHAN) += null.o -+obj-$(CONFIG_PORT_CHAN) += port.o -+obj-$(CONFIG_PTY_CHAN) += pty.o -+obj-$(CONFIG_TTY_CHAN) += tty.o -+obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o -+obj-$(CONFIG_UML_WATCHDOG) += harddog.o -+obj-$(CONFIG_COW) += cow_kern.o -+obj-$(CONFIG_COW_COMMON) += cow_user.o -+ -+CFLAGS_pcap_user.o = -I/usr/include/pcap -+ -+obj-y += stdio_console.o $(CHAN_OBJS) -+ -+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \ -+ null.o pty.o tty.o xterm.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean: -+ -+modules: -+ -+fastdep: -+ -+dep: -+ -+archmrproper: -+ -+daemon.o : $(daemon-objs) -+ -+slip.o : $(slip-objs) -+ -+slirp.o : $(slirp-objs) -+ -+mcast.o : $(mcast-objs) -+ -+pcap.o : $(pcap-objs) -+ -+mconsole.o : $(mconsole-objs) -+ -+net.o : $(net-objs) -+ -+hostaudio.o : $(hostaudio-objs) -+ -+ubd.o : $(ubd-objs) -+ -+port.o : $(port-objs) -+ -+harddog.o : $(harddog-objs) -+ -+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)' -+ $(LD) -r -o $@ $($(patsubst %.o,%,$@)-objs) $($(patsubst %.o,%,$@)-libs) -diff -Naur -X ../exclude-files orig/arch/um/drivers/mcast.h um/arch/um/drivers/mcast.h ---- orig/arch/um/drivers/mcast.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/mcast.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct mcast_data { -+ char *addr; -+ unsigned short port; -+ void *mcast_addr; -+ int ttl; -+ void *dev; -+}; -+ -+extern struct net_user_info mcast_user_info; -+ -+extern int mcast_user_write(int fd, void *buf, int len, -+ struct mcast_data *pri); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/mcast_kern.c um/arch/um/drivers/mcast_kern.c ---- orig/arch/um/drivers/mcast_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/mcast_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,145 @@ -+/* -+ * user-mode-linux networking multicast transport -+ * Copyright (C) 2001 by Harald Welte -+ * -+ * based on the existing uml-networking code, which is -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/in.h" -+#include "linux/inet.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "mcast.h" -+ -+struct mcast_init { -+ char *addr; -+ int port; -+ int ttl; -+}; -+ -+void mcast_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct mcast_data *dpri; -+ struct mcast_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ dpri = (struct mcast_data *) pri->user; -+ *dpri = ((struct mcast_data) -+ { .addr = init->addr, -+ .port = init->port, -+ .ttl = init->ttl, -+ .mcast_addr = NULL, -+ .dev = dev }); -+ printk("mcast backend "); -+ printk("multicast adddress: %s:%u, TTL:%u ", -+ dpri->addr, dpri->port, dpri->ttl); -+ -+ printk("\n"); -+} -+ -+static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int mcast_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return mcast_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct mcast_data *) &lp->user); -+} -+ -+static struct net_kern_info mcast_kern_info = { -+ .init = mcast_init, -+ .protocol = eth_protocol, -+ .read = mcast_read, -+ .write = mcast_write, -+}; -+ -+int mcast_setup(char *str, char **mac_out, void *data) -+{ -+ struct mcast_init *init = data; -+ char *port_str = NULL, *ttl_str = NULL, *remain; -+ char *last; -+ int n; -+ -+ *init = ((struct mcast_init) -+ { .addr = "239.192.168.1", -+ .port = 1102, -+ .ttl = 1 }); -+ -+ remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, -+ NULL); -+ if(remain != NULL){ -+ printk(KERN_ERR "mcast_setup - Extra garbage on " -+ "specification : '%s'\n", remain); -+ return(0); -+ } -+ -+ if(port_str != NULL){ -+ n = simple_strtoul(port_str, &last, 10); -+ if((*last != '\0') || (last == port_str)){ -+ printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", -+ port_str); -+ return(0); -+ } -+ init->port = htons(n); -+ } -+ -+ if(ttl_str != NULL){ -+ init->ttl = simple_strtoul(ttl_str, &last, 10); -+ if((*last != '\0') || (last == ttl_str)){ -+ printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", -+ ttl_str); -+ return(0); -+ } -+ } -+ -+ printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, -+ init->port, init->ttl); -+ -+ return(1); -+} -+ -+static struct transport mcast_transport = { -+ .list = LIST_HEAD_INIT(mcast_transport.list), -+ .name = "mcast", -+ .setup = mcast_setup, -+ .user = &mcast_user_info, -+ .kern = &mcast_kern_info, -+ .private_size = sizeof(struct mcast_data), -+ .setup_size = sizeof(struct mcast_init), -+}; -+ -+static int register_mcast(void) -+{ -+ register_transport(&mcast_transport); -+ return(1); -+} -+ -+__initcall(register_mcast); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/mcast_user.c um/arch/um/drivers/mcast_user.c ---- orig/arch/um/drivers/mcast_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/mcast_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,177 @@ -+/* -+ * user-mode-linux networking multicast transport -+ * Copyright (C) 2001 by Harald Welte -+ * -+ * based on the existing uml-networking code, which is -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * -+ * Licensed under the GPL. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "net_user.h" -+#include "mcast.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+static struct sockaddr_in *new_addr(char *addr, unsigned short port) -+{ -+ struct sockaddr_in *sin; -+ -+ sin = um_kmalloc(sizeof(struct sockaddr_in)); -+ if(sin == NULL){ -+ printk("new_addr: allocation of sockaddr_in failed\n"); -+ return(NULL); -+ } -+ sin->sin_family = AF_INET; -+ sin->sin_addr.s_addr = in_aton(addr); -+ sin->sin_port = port; -+ return(sin); -+} -+ -+static void mcast_user_init(void *data, void *dev) -+{ -+ struct mcast_data *pri = data; -+ -+ pri->mcast_addr = new_addr(pri->addr, pri->port); -+ pri->dev = dev; -+} -+ -+static int mcast_open(void *data) -+{ -+ struct mcast_data *pri = data; -+ struct sockaddr_in *sin = pri->mcast_addr; -+ struct ip_mreq mreq; -+ int fd, yes = 1; -+ -+ -+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) { -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ fd = socket(AF_INET, SOCK_DGRAM, 0); -+ if (fd < 0){ -+ printk("mcast_open : data socket failed, errno = %d\n", -+ errno); -+ fd = -ENOMEM; -+ goto out; -+ } -+ -+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { -+ printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", -+ errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* set ttl according to config */ -+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, -+ sizeof(pri->ttl)) < 0) { -+ printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", -+ errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* set LOOP, so data does get fed back to local sockets */ -+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { -+ printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", -+ errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* bind socket to mcast address */ -+ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { -+ printk("mcast_open : data bind failed, errno = %d\n", errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* subscribe to the multicast group */ -+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; -+ mreq.imr_interface.s_addr = 0; -+ if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, -+ &mreq, sizeof(mreq)) < 0) { -+ printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", -+ errno); -+ printk("There appears not to be a multicast-capable network " -+ "interface on the host.\n"); -+ printk("eth0 should be configured in order to use the " -+ "multicast transport.\n"); -+ os_close_file(fd); -+ fd = -EINVAL; -+ } -+ -+ out: -+ return(fd); -+} -+ -+static void mcast_close(int fd, void *data) -+{ -+ struct ip_mreq mreq; -+ struct mcast_data *pri = data; -+ struct sockaddr_in *sin = pri->mcast_addr; -+ -+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; -+ mreq.imr_interface.s_addr = 0; -+ if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, -+ &mreq, sizeof(mreq)) < 0) { -+ printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n", -+ errno); -+ } -+ -+ os_close_file(fd); -+} -+ -+int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) -+{ -+ struct sockaddr_in *data_addr = pri->mcast_addr; -+ -+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); -+} -+ -+static int mcast_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info mcast_user_info = { -+ .init = mcast_user_init, -+ .open = mcast_open, -+ .close = mcast_close, -+ .remove = NULL, -+ .set_mtu = mcast_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/mconsole_kern.c um/arch/um/drivers/mconsole_kern.c ---- orig/arch/um/drivers/mconsole_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/mconsole_kern.c 2004-02-12 03:09:12.000000000 -0500 -@@ -0,0 +1,560 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/slab.h" -+#include "linux/init.h" -+#include "linux/notifier.h" -+#include "linux/reboot.h" -+#include "linux/utsname.h" -+#include "linux/ctype.h" -+#include "linux/interrupt.h" -+#include "linux/sysrq.h" -+#include "linux/tqueue.h" -+#include "linux/module.h" -+#include "linux/file.h" -+#include "linux/fs.h" -+#include "linux/proc_fs.h" -+#include "asm/irq.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mconsole.h" -+#include "mconsole_kern.h" -+#include "irq_user.h" -+#include "init.h" -+#include "os.h" -+#include "umid.h" -+#include "irq_kern.h" -+ -+static int do_unlink_socket(struct notifier_block *notifier, -+ unsigned long what, void *data) -+{ -+ return(mconsole_unlink_socket()); -+} -+ -+ -+static struct notifier_block reboot_notifier = { -+ .notifier_call = do_unlink_socket, -+ .priority = 0, -+}; -+ -+/* Safe without explicit locking for now. Tasklets provide their own -+ * locking, and the interrupt handler is safe because it can't interrupt -+ * itself and it can only happen on CPU 0. -+ */ -+ -+LIST_HEAD(mc_requests); -+ -+void mc_task_proc(void *unused) -+{ -+ struct mconsole_entry *req; -+ unsigned long flags; -+ int done; -+ -+ do { -+ save_flags(flags); -+ req = list_entry(mc_requests.next, struct mconsole_entry, -+ list); -+ list_del(&req->list); -+ done = list_empty(&mc_requests); -+ restore_flags(flags); -+ req->request.cmd->handler(&req->request); -+ kfree(req); -+ } while(!done); -+} -+ -+struct tq_struct mconsole_task = { -+ .routine = mc_task_proc, -+ .data = NULL -+}; -+ -+void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ int fd; -+ struct mconsole_entry *new; -+ struct mc_request req; -+ -+ fd = (int) dev_id; -+ while (mconsole_get_request(fd, &req)){ -+ if(req.cmd->context == MCONSOLE_INTR) -+ (*req.cmd->handler)(&req); -+ else { -+ new = kmalloc(sizeof(*new), GFP_ATOMIC); -+ if(new == NULL) -+ mconsole_reply(&req, "Out of memory", 1, 0); -+ else { -+ new->request = req; -+ list_add(&new->list, &mc_requests); -+ } -+ } -+ } -+ if(!list_empty(&mc_requests)) schedule_task(&mconsole_task); -+ reactivate_fd(fd, MCONSOLE_IRQ); -+} -+ -+void mconsole_version(struct mc_request *req) -+{ -+ char version[256]; -+ -+ sprintf(version, "%s %s %s %s %s", system_utsname.sysname, -+ system_utsname.nodename, system_utsname.release, -+ system_utsname.version, system_utsname.machine); -+ mconsole_reply(req, version, 0, 0); -+} -+ -+void mconsole_log(struct mc_request *req) -+{ -+ int len; -+ char *ptr = req->request.data; -+ -+ ptr += strlen("log "); -+ -+ len = req->len - (ptr - req->request.data); -+ printk("%.*s", len, ptr); -+ mconsole_reply(req, "", 0, 0); -+} -+ -+void mconsole_proc(struct mc_request *req) -+{ -+ struct nameidata nd; -+ struct file_system_type *proc; -+ struct super_block *super; -+ struct file *file; -+ int n, err; -+ char *ptr = req->request.data, *buf; -+ -+ ptr += strlen("proc"); -+ while(isspace(*ptr)) ptr++; -+ -+ proc = get_fs_type("proc"); -+ if(proc == NULL){ -+ mconsole_reply(req, "procfs not registered", 1, 0); -+ goto out; -+ } -+ -+ super = get_anon_super(proc, NULL, NULL); -+ if(super == NULL){ -+ mconsole_reply(req, "Failed to get procfs superblock", 1, 0); -+ goto out_put; -+ } -+ -+ if(super->s_root == NULL){ -+ super = (*proc->read_super)(super, NULL, 0); -+ if(super == NULL){ -+ mconsole_reply(req, "Failed to read superblock", 1, 0); -+ goto out_put; -+ } -+ } -+ up_write(&super->s_umount); -+ -+ nd.dentry = super->s_root; -+ nd.mnt = NULL; -+ nd.flags = O_RDONLY + 1; -+ nd.last_type = LAST_ROOT; -+ -+ err = link_path_walk(ptr, &nd); -+ if(err){ -+ mconsole_reply(req, "Failed to look up file", 1, 0); -+ goto out_kill; -+ } -+ -+ file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ if(IS_ERR(file)){ -+ mconsole_reply(req, "Failed to open file", 1, 0); -+ goto out_kill; -+ } -+ -+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ if(buf == NULL){ -+ mconsole_reply(req, "Failed to allocate buffer", 1, 0); -+ goto out_fput; -+ } -+ -+ if((file->f_op != NULL) && (file->f_op->read != NULL)){ -+ do { -+ n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, -+ &file->f_pos); -+ if(n >= 0){ -+ buf[n] = '\0'; -+ mconsole_reply(req, buf, 0, (n > 0)); -+ } -+ else { -+ mconsole_reply(req, "Read of file failed", -+ 1, 0); -+ goto out_free; -+ } -+ } while(n > 0); -+ } -+ else mconsole_reply(req, "", 0, 0); -+ -+ out_free: -+ kfree(buf); -+ out_fput: -+ fput(file); -+ out_kill: -+ kill_super(super); -+ out_put: -+ /* put_filesystem(proc); */ -+ out: ; -+} -+ -+#define UML_MCONSOLE_HELPTEXT \ -+"Commands: \n\ -+ version - Get kernel version \n\ -+ help - Print this message \n\ -+ halt - Halt UML \n\ -+ reboot - Reboot UML \n\ -+ config = - Add a new device to UML; \n\ -+ same syntax as command line \n\ -+ config - Query the configuration of a device \n\ -+ remove - Remove a device from UML \n\ -+ sysrq - Performs the SysRq action controlled by the letter \n\ -+ cad - invoke the Ctl-Alt-Del handler \n\ -+ stop - pause the UML; it will do nothing until it receives a 'go' \n\ -+ go - continue the UML after a 'stop' \n\ -+ log - make UML enter into the kernel log\n\ -+ proc - returns the contents of the UML's /proc/\n\ -+" -+ -+void mconsole_help(struct mc_request *req) -+{ -+ mconsole_reply(req, UML_MCONSOLE_HELPTEXT, 0, 0); -+} -+ -+void mconsole_halt(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ machine_halt(); -+} -+ -+void mconsole_reboot(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ machine_restart(NULL); -+} -+ -+extern void ctrl_alt_del(void); -+ -+void mconsole_cad(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ ctrl_alt_del(); -+} -+ -+void mconsole_go(struct mc_request *req) -+{ -+ mconsole_reply(req, "Not stopped", 1, 0); -+} -+ -+void mconsole_stop(struct mc_request *req) -+{ -+ deactivate_fd(req->originating_fd, MCONSOLE_IRQ); -+ os_set_fd_block(req->originating_fd, 1); -+ mconsole_reply(req, "", 0, 0); -+ while(mconsole_get_request(req->originating_fd, req)){ -+ if(req->cmd->handler == mconsole_go) break; -+ (*req->cmd->handler)(req); -+ } -+ os_set_fd_block(req->originating_fd, 0); -+ reactivate_fd(req->originating_fd, MCONSOLE_IRQ); -+ mconsole_reply(req, "", 0, 0); -+} -+ -+/* This list is populated by __initcall routines. */ -+ -+LIST_HEAD(mconsole_devices); -+ -+void mconsole_register_dev(struct mc_device *new) -+{ -+ list_add(&new->list, &mconsole_devices); -+} -+ -+static struct mc_device *mconsole_find_dev(char *name) -+{ -+ struct list_head *ele; -+ struct mc_device *dev; -+ -+ list_for_each(ele, &mconsole_devices){ -+ dev = list_entry(ele, struct mc_device, list); -+ if(!strncmp(name, dev->name, strlen(dev->name))) -+ return(dev); -+ } -+ return(NULL); -+} -+ -+#define CONFIG_BUF_SIZE 64 -+ -+static void mconsole_get_config(int (*get_config)(char *, char *, int, -+ char **), -+ struct mc_request *req, char *name) -+{ -+ char default_buf[CONFIG_BUF_SIZE], *error, *buf; -+ int n, size; -+ -+ if(get_config == NULL){ -+ mconsole_reply(req, "No get_config routine defined", 1, 0); -+ return; -+ } -+ -+ error = NULL; -+ size = sizeof(default_buf)/sizeof(default_buf[0]); -+ buf = default_buf; -+ -+ while(1){ -+ n = (*get_config)(name, buf, size, &error); -+ if(error != NULL){ -+ mconsole_reply(req, error, 1, 0); -+ goto out; -+ } -+ -+ if(n <= size){ -+ mconsole_reply(req, buf, 0, 0); -+ goto out; -+ } -+ -+ if(buf != default_buf) -+ kfree(buf); -+ -+ size = n; -+ buf = kmalloc(size, GFP_KERNEL); -+ if(buf == NULL){ -+ mconsole_reply(req, "Failed to allocate buffer", 1, 0); -+ return; -+ } -+ } -+ out: -+ if(buf != default_buf) -+ kfree(buf); -+ -+} -+ -+void mconsole_config(struct mc_request *req) -+{ -+ struct mc_device *dev; -+ char *ptr = req->request.data, *name; -+ int err; -+ -+ ptr += strlen("config"); -+ while(isspace(*ptr)) ptr++; -+ dev = mconsole_find_dev(ptr); -+ if(dev == NULL){ -+ mconsole_reply(req, "Bad configuration option", 1, 0); -+ return; -+ } -+ -+ name = &ptr[strlen(dev->name)]; -+ ptr = name; -+ while((*ptr != '=') && (*ptr != '\0')) -+ ptr++; -+ -+ if(*ptr == '='){ -+ err = (*dev->config)(name); -+ mconsole_reply(req, "", err, 0); -+ } -+ else mconsole_get_config(dev->get_config, req, name); -+} -+ -+void mconsole_remove(struct mc_request *req) -+{ -+ struct mc_device *dev; -+ char *ptr = req->request.data; -+ int err; -+ -+ ptr += strlen("remove"); -+ while(isspace(*ptr)) ptr++; -+ dev = mconsole_find_dev(ptr); -+ if(dev == NULL){ -+ mconsole_reply(req, "Bad remove option", 1, 0); -+ return; -+ } -+ err = (*dev->remove)(&ptr[strlen(dev->name)]); -+ mconsole_reply(req, "", err, 0); -+} -+ -+#ifdef CONFIG_MAGIC_SYSRQ -+void mconsole_sysrq(struct mc_request *req) -+{ -+ char *ptr = req->request.data; -+ -+ ptr += strlen("sysrq"); -+ while(isspace(*ptr)) ptr++; -+ -+ mconsole_reply(req, "", 0, 0); -+ handle_sysrq(*ptr, ¤t->thread.regs, NULL, NULL); -+} -+#else -+void mconsole_sysrq(struct mc_request *req) -+{ -+ mconsole_reply(req, "Sysrq not compiled in", 1, 0); -+} -+#endif -+ -+/* Changed by mconsole_setup, which is __setup, and called before SMP is -+ * active. -+ */ -+static char *notify_socket = NULL; -+ -+int mconsole_init(void) -+{ -+ int err, sock; -+ char file[256]; -+ -+ if(umid_file_name("mconsole", file, sizeof(file))) return(-1); -+ snprintf(mconsole_socket_name, sizeof(file), "%s", file); -+ -+ sock = os_create_unix_socket(file, sizeof(file), 1); -+ if (sock < 0){ -+ printk("Failed to initialize management console\n"); -+ return(1); -+ } -+ -+ register_reboot_notifier(&reboot_notifier); -+ -+ err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "mconsole", (void *)sock); -+ if (err){ -+ printk("Failed to get IRQ for management console\n"); -+ return(1); -+ } -+ -+ if(notify_socket != NULL){ -+ notify_socket = uml_strdup(notify_socket); -+ if(notify_socket != NULL) -+ mconsole_notify(notify_socket, MCONSOLE_SOCKET, -+ mconsole_socket_name, -+ strlen(mconsole_socket_name) + 1); -+ else printk(KERN_ERR "mconsole_setup failed to strdup " -+ "string\n"); -+ } -+ -+ printk("mconsole (version %d) initialized on %s\n", -+ MCONSOLE_VERSION, mconsole_socket_name); -+ return(0); -+} -+ -+__initcall(mconsole_init); -+ -+static int write_proc_mconsole(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char *buf; -+ -+ buf = kmalloc(count + 1, GFP_KERNEL); -+ if(buf == NULL) -+ return(-ENOMEM); -+ -+ if(copy_from_user(buf, buffer, count)){ -+ count = -EFAULT; -+ goto out; -+ } -+ -+ buf[count] = '\0'; -+ -+ mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); -+ out: -+ kfree(buf); -+ return(count); -+} -+ -+static int create_proc_mconsole(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ if(notify_socket == NULL) return(0); -+ -+ ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); -+ if(ent == NULL){ -+ printk("create_proc_mconsole : create_proc_entry failed\n"); -+ return(0); -+ } -+ -+ ent->read_proc = NULL; -+ ent->write_proc = write_proc_mconsole; -+ return(0); -+} -+ -+static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED; -+ -+void lock_notify(void) -+{ -+ spin_lock(¬ify_spinlock); -+} -+ -+void unlock_notify(void) -+{ -+ spin_unlock(¬ify_spinlock); -+} -+ -+__initcall(create_proc_mconsole); -+ -+#define NOTIFY "=notify:" -+ -+static int mconsole_setup(char *str) -+{ -+ if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ -+ str += strlen(NOTIFY); -+ notify_socket = str; -+ } -+ else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); -+ return(1); -+} -+ -+__setup("mconsole", mconsole_setup); -+ -+__uml_help(mconsole_setup, -+"mconsole=notify:\n" -+" Requests that the mconsole driver send a message to the named Unix\n" -+" socket containing the name of the mconsole socket. This also serves\n" -+" to notify outside processes when UML has booted far enough to respond\n" -+" to mconsole requests.\n\n" -+); -+ -+static int notify_panic(struct notifier_block *self, unsigned long unused1, -+ void *ptr) -+{ -+ char *message = ptr; -+ -+ if(notify_socket == NULL) return(0); -+ -+ mconsole_notify(notify_socket, MCONSOLE_PANIC, message, -+ strlen(message) + 1); -+ return(0); -+} -+ -+static struct notifier_block panic_exit_notifier = { -+ .notifier_call = notify_panic, -+ .next = NULL, -+ .priority = 1 -+}; -+ -+static int add_notifier(void) -+{ -+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); -+ return(0); -+} -+ -+__initcall(add_notifier); -+ -+char *mconsole_notify_socket(void) -+{ -+ return(notify_socket); -+} -+ -+EXPORT_SYMBOL(mconsole_notify_socket); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/mconsole_user.c um/arch/um/drivers/mconsole_user.c ---- orig/arch/um/drivers/mconsole_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/mconsole_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,215 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user.h" -+#include "mconsole.h" -+#include "umid.h" -+ -+static struct mconsole_command commands[] = { -+ { "version", mconsole_version, MCONSOLE_INTR }, -+ { "halt", mconsole_halt, MCONSOLE_PROC }, -+ { "reboot", mconsole_reboot, MCONSOLE_PROC }, -+ { "config", mconsole_config, MCONSOLE_PROC }, -+ { "remove", mconsole_remove, MCONSOLE_PROC }, -+ { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, -+ { "help", mconsole_help, MCONSOLE_INTR }, -+ { "cad", mconsole_cad, MCONSOLE_INTR }, -+ { "stop", mconsole_stop, MCONSOLE_PROC }, -+ { "go", mconsole_go, MCONSOLE_INTR }, -+ { "log", mconsole_log, MCONSOLE_INTR }, -+ { "proc", mconsole_proc, MCONSOLE_PROC }, -+}; -+ -+/* Initialized in mconsole_init, which is an initcall */ -+char mconsole_socket_name[256]; -+ -+int mconsole_reply_v0(struct mc_request *req, char *reply) -+{ -+ struct iovec iov; -+ struct msghdr msg; -+ -+ iov.iov_base = reply; -+ iov.iov_len = strlen(reply); -+ -+ msg.msg_name = &(req->origin); -+ msg.msg_namelen = req->originlen; -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ -+ return sendmsg(req->originating_fd, &msg, 0); -+} -+ -+static struct mconsole_command *mconsole_parse(struct mc_request *req) -+{ -+ struct mconsole_command *cmd; -+ int i; -+ -+ for(i=0;irequest.data, cmd->command, -+ strlen(cmd->command))){ -+ return(cmd); -+ } -+ } -+ return(NULL); -+} -+ -+#define MIN(a,b) ((a)<(b) ? (a):(b)) -+ -+#define STRINGX(x) #x -+#define STRING(x) STRINGX(x) -+ -+int mconsole_get_request(int fd, struct mc_request *req) -+{ -+ int len; -+ -+ req->originlen = sizeof(req->origin); -+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0, -+ (struct sockaddr *) req->origin, &req->originlen); -+ if (req->len < 0) -+ return 0; -+ -+ req->originating_fd = fd; -+ -+ if(req->request.magic != MCONSOLE_MAGIC){ -+ /* Unversioned request */ -+ len = MIN(sizeof(req->request.data) - 1, -+ strlen((char *) &req->request)); -+ memmove(req->request.data, &req->request, len); -+ req->request.data[len] = '\0'; -+ -+ req->request.magic = MCONSOLE_MAGIC; -+ req->request.version = 0; -+ req->request.len = len; -+ -+ mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " -+ "not supported by this driver"); -+ return(0); -+ } -+ -+ if(req->request.len >= MCONSOLE_MAX_DATA){ -+ mconsole_reply(req, "Request too large", 1, 0); -+ return(0); -+ } -+ if(req->request.version != MCONSOLE_VERSION){ -+ mconsole_reply(req, "This driver only supports version " -+ STRING(MCONSOLE_VERSION) " clients", 1, 0); -+ } -+ -+ req->request.data[req->request.len] = '\0'; -+ req->cmd = mconsole_parse(req); -+ if(req->cmd == NULL){ -+ mconsole_reply(req, "Unknown command", 1, 0); -+ return(0); -+ } -+ -+ return(1); -+} -+ -+int mconsole_reply(struct mc_request *req, char *str, int err, int more) -+{ -+ struct mconsole_reply reply; -+ int total, len, n; -+ -+ total = strlen(str); -+ do { -+ reply.err = err; -+ -+ /* err can only be true on the first packet */ -+ err = 0; -+ -+ len = MIN(total, MCONSOLE_MAX_DATA - 1); -+ -+ if(len == total) reply.more = more; -+ else reply.more = 1; -+ -+ memcpy(reply.data, str, len); -+ reply.data[len] = '\0'; -+ total -= len; -+ str += len; -+ reply.len = len + 1; -+ -+ len = sizeof(reply) + reply.len - sizeof(reply.data); -+ -+ n = sendto(req->originating_fd, &reply, len, 0, -+ (struct sockaddr *) req->origin, req->originlen); -+ -+ if(n < 0) return(-errno); -+ } while(total > 0); -+ return(0); -+} -+ -+int mconsole_unlink_socket(void) -+{ -+ unlink(mconsole_socket_name); -+ return 0; -+} -+ -+static int notify_sock = -1; -+ -+int mconsole_notify(char *sock_name, int type, const void *data, int len) -+{ -+ struct sockaddr_un target; -+ struct mconsole_notify packet; -+ int n, err = 0; -+ -+ lock_notify(); -+ if(notify_sock < 0){ -+ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); -+ if(notify_sock < 0){ -+ printk("mconsole_notify - socket failed, errno = %d\n", -+ errno); -+ err = -errno; -+ } -+ } -+ unlock_notify(); -+ -+ if(err) -+ return(err); -+ -+ target.sun_family = AF_UNIX; -+ strcpy(target.sun_path, sock_name); -+ -+ packet.magic = MCONSOLE_MAGIC; -+ packet.version = MCONSOLE_VERSION; -+ packet.type = type; -+ len = (len > sizeof(packet.data)) ? sizeof(packet.data) : len; -+ packet.len = len; -+ memcpy(packet.data, data, len); -+ -+ err = 0; -+ len = sizeof(packet) + packet.len - sizeof(packet.data); -+ n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, -+ sizeof(target)); -+ if(n < 0){ -+ printk("mconsole_notify - sendto failed, errno = %d\n", errno); -+ err = -errno; -+ } -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/mmapper_kern.c um/arch/um/drivers/mmapper_kern.c ---- orig/arch/um/drivers/mmapper_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/mmapper_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,151 @@ -+/* -+ * arch/um/drivers/mmapper_kern.c -+ * -+ * BRIEF MODULE DESCRIPTION -+ * -+ * Copyright (C) 2000 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mem_user.h" -+#include "user_util.h" -+ -+/* These are set in mmapper_init, which is called at boot time */ -+static unsigned long mmapper_size; -+static unsigned long p_buf = 0; -+static char *v_buf = NULL; -+ -+static ssize_t -+mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ if(*ppos > mmapper_size) -+ return -EINVAL; -+ -+ if(count + *ppos > mmapper_size) -+ count = count + *ppos - mmapper_size; -+ -+ if(count < 0) -+ return -EINVAL; -+ -+ copy_to_user(buf,&v_buf[*ppos],count); -+ -+ return count; -+} -+ -+static ssize_t -+mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -+{ -+ if(*ppos > mmapper_size) -+ return -EINVAL; -+ -+ if(count + *ppos > mmapper_size) -+ count = count + *ppos - mmapper_size; -+ -+ if(count < 0) -+ return -EINVAL; -+ -+ copy_from_user(&v_buf[*ppos],buf,count); -+ -+ return count; -+} -+ -+static int -+mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return(-ENOIOCTLCMD); -+} -+ -+static int -+mmapper_mmap(struct file *file, struct vm_area_struct * vma) -+{ -+ int ret = -EINVAL; -+ int size; -+ -+ lock_kernel(); -+ if (vma->vm_pgoff != 0) -+ goto out; -+ -+ size = vma->vm_end - vma->vm_start; -+ if(size > mmapper_size) return(-EFAULT); -+ -+ /* XXX A comment above remap_page_range says it should only be -+ * called when the mm semaphore is held -+ */ -+ if (remap_page_range(vma->vm_start, p_buf, size, vma->vm_page_prot)) -+ goto out; -+ ret = 0; -+out: -+ unlock_kernel(); -+ return ret; -+} -+ -+static int -+mmapper_open(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static int -+mmapper_release(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static struct file_operations mmapper_fops = { -+ .owner = THIS_MODULE, -+ .read = mmapper_read, -+ .write = mmapper_write, -+ .ioctl = mmapper_ioctl, -+ .mmap = mmapper_mmap, -+ .open = mmapper_open, -+ .release = mmapper_release, -+}; -+ -+static int __init mmapper_init(void) -+{ -+ printk(KERN_INFO "Mapper v0.1\n"); -+ -+ v_buf = (char *) find_iomem("mmapper", &mmapper_size); -+ if(mmapper_size == 0){ -+ printk(KERN_ERR "mmapper_init - find_iomem failed\n"); -+ return(0); -+ } -+ -+ p_buf = __pa(v_buf); -+ -+ devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, -+ 30, 0, S_IFCHR | S_IRUGO | S_IWUGO, -+ &mmapper_fops, NULL); -+ devfs_mk_symlink(NULL, "mmapper0", DEVFS_FL_DEFAULT, "mmapper", -+ NULL, NULL); -+ return(0); -+} -+ -+static void mmapper_exit(void) -+{ -+} -+ -+module_init(mmapper_init); -+module_exit(mmapper_exit); -+ -+MODULE_AUTHOR("Greg Lonnon "); -+MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/net_kern.c um/arch/um/drivers/net_kern.c ---- orig/arch/um/drivers/net_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/net_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,872 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/netdevice.h" -+#include "linux/rtnetlink.h" -+#include "linux/skbuff.h" -+#include "linux/socket.h" -+#include "linux/spinlock.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/etherdevice.h" -+#include "linux/list.h" -+#include "linux/inetdevice.h" -+#include "linux/ctype.h" -+#include "linux/bootmem.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+ -+static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED; -+LIST_HEAD(opened); -+ -+static int uml_net_rx(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ int pkt_len; -+ struct sk_buff *skb; -+ -+ /* If we can't allocate memory, try again next round. */ -+ skb = dev_alloc_skb(dev->mtu); -+ if (skb == NULL) { -+ lp->stats.rx_dropped++; -+ return 0; -+ } -+ -+ skb->dev = dev; -+ skb_put(skb, dev->mtu); -+ skb->mac.raw = skb->data; -+ pkt_len = (*lp->read)(lp->fd, &skb, lp); -+ -+ if (pkt_len > 0) { -+ skb_trim(skb, pkt_len); -+ skb->protocol = (*lp->protocol)(skb); -+ netif_rx(skb); -+ -+ lp->stats.rx_bytes += skb->len; -+ lp->stats.rx_packets++; -+ return pkt_len; -+ } -+ -+ kfree_skb(skb); -+ return pkt_len; -+} -+ -+void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ struct net_device *dev = dev_id; -+ struct uml_net_private *lp = dev->priv; -+ int err; -+ -+ if(!netif_running(dev)) -+ return; -+ -+ spin_lock(&lp->lock); -+ while((err = uml_net_rx(dev)) > 0) ; -+ if(err < 0) { -+ printk(KERN_ERR -+ "Device '%s' read returned %d, shutting it down\n", -+ dev->name, err); -+ dev_close(dev); -+ goto out; -+ } -+ reactivate_fd(lp->fd, UM_ETH_IRQ); -+ -+ out: -+ spin_unlock(&lp->lock); -+} -+ -+static int uml_net_open(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ char addr[sizeof("255.255.255.255\0")]; -+ int err; -+ -+ spin_lock(&lp->lock); -+ -+ if(lp->fd >= 0){ -+ err = -ENXIO; -+ goto out; -+ } -+ -+ if(!lp->have_mac){ -+ dev_ip_addr(dev, addr, &lp->mac[2]); -+ set_ether_mac(dev, lp->mac); -+ } -+ -+ lp->fd = (*lp->open)(&lp->user); -+ if(lp->fd < 0){ -+ err = lp->fd; -+ goto out; -+ } -+ -+ err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, -+ SA_INTERRUPT | SA_SHIRQ, dev->name, dev); -+ if(err != 0){ -+ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ lp->fd = -1; -+ err = -ENETUNREACH; -+ } -+ -+ lp->tl.data = (unsigned long) &lp->user; -+ netif_start_queue(dev); -+ -+ spin_lock(&opened_lock); -+ list_add(&lp->list, &opened); -+ spin_unlock(&opened_lock); -+ MOD_INC_USE_COUNT; -+ out: -+ spin_unlock(&lp->lock); -+ return(err); -+} -+ -+static int uml_net_close(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ -+ netif_stop_queue(dev); -+ spin_lock(&lp->lock); -+ -+ free_irq(dev->irq, dev); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ lp->fd = -1; -+ spin_lock(&opened_lock); -+ list_del(&lp->list); -+ spin_unlock(&opened_lock); -+ -+ MOD_DEC_USE_COUNT; -+ spin_unlock(&lp->lock); -+ return 0; -+} -+ -+static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ unsigned long flags; -+ int len; -+ -+ netif_stop_queue(dev); -+ -+ spin_lock_irqsave(&lp->lock, flags); -+ -+ len = (*lp->write)(lp->fd, &skb, lp); -+ -+ if(len == skb->len) { -+ lp->stats.tx_packets++; -+ lp->stats.tx_bytes += skb->len; -+ dev->trans_start = jiffies; -+ netif_start_queue(dev); -+ -+ /* this is normally done in the interrupt when tx finishes */ -+ netif_wake_queue(dev); -+ } -+ else if(len == 0){ -+ netif_start_queue(dev); -+ lp->stats.tx_dropped++; -+ } -+ else { -+ netif_start_queue(dev); -+ printk(KERN_ERR "uml_net_start_xmit: failed(%d)\n", len); -+ } -+ -+ spin_unlock_irqrestore(&lp->lock, flags); -+ -+ dev_kfree_skb(skb); -+ -+ return 0; -+} -+ -+static struct net_device_stats *uml_net_get_stats(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ return &lp->stats; -+} -+ -+static void uml_net_set_multicast_list(struct net_device *dev) -+{ -+ if (dev->flags & IFF_PROMISC) return; -+ else if (dev->mc_count) dev->flags |= IFF_ALLMULTI; -+ else dev->flags &= ~IFF_ALLMULTI; -+} -+ -+static void uml_net_tx_timeout(struct net_device *dev) -+{ -+ dev->trans_start = jiffies; -+ netif_wake_queue(dev); -+} -+ -+static int uml_net_set_mac(struct net_device *dev, void *addr) -+{ -+ struct uml_net_private *lp = dev->priv; -+ struct sockaddr *hwaddr = addr; -+ -+ spin_lock(&lp->lock); -+ memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); -+ spin_unlock(&lp->lock); -+ -+ return(0); -+} -+ -+static int uml_net_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ struct uml_net_private *lp = dev->priv; -+ int err = 0; -+ -+ spin_lock(&lp->lock); -+ -+ new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); -+ if(new_mtu < 0){ -+ err = new_mtu; -+ goto out; -+ } -+ -+ dev->mtu = new_mtu; -+ -+ out: -+ spin_unlock(&lp->lock); -+ return err; -+} -+ -+static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ return(-EINVAL); -+} -+ -+void uml_net_user_timer_expire(unsigned long _conn) -+{ -+#ifdef undef -+ struct connection *conn = (struct connection *)_conn; -+ -+ dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn); -+ do_connect(conn); -+#endif -+} -+ -+/* -+ * default do nothing hard header packet routines for struct net_device init. -+ * real ethernet transports will overwrite with real routines. -+ */ -+static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev, -+ unsigned short type, void *daddr, void *saddr, unsigned len) -+{ -+ return(0); /* no change */ -+} -+ -+static int uml_net_rebuild_header(struct sk_buff *skb) -+{ -+ return(0); /* ignore */ -+} -+ -+static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh) -+{ -+ return(-1); /* fail */ -+} -+ -+static void uml_net_header_cache_update(struct hh_cache *hh, -+ struct net_device *dev, unsigned char * haddr) -+{ -+ /* ignore */ -+} -+ -+static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr) -+{ -+ return(0); /* nothing */ -+} -+ -+static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED; -+static struct list_head devices = LIST_HEAD_INIT(devices); -+ -+static int eth_configure(int n, void *init, char *mac, -+ struct transport *transport) -+{ -+ struct uml_net *device; -+ struct net_device *dev; -+ struct uml_net_private *lp; -+ int save, err, size; -+ -+ size = transport->private_size + sizeof(struct uml_net_private) + -+ sizeof(((struct uml_net_private *) 0)->user); -+ -+ device = kmalloc(sizeof(*device), GFP_KERNEL); -+ if(device == NULL){ -+ printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); -+ return(1); -+ } -+ -+ *device = ((struct uml_net) { .list = LIST_HEAD_INIT(device->list), -+ .dev = NULL, -+ .index = n, -+ .mac = { [ 0 ... 5 ] = 0 }, -+ .have_mac = 0 }); -+ -+ spin_lock(&devices_lock); -+ list_add(&device->list, &devices); -+ spin_unlock(&devices_lock); -+ -+ if(setup_etheraddr(mac, device->mac)) -+ device->have_mac = 1; -+ -+ printk(KERN_INFO "Netdevice %d ", n); -+ if(device->have_mac) printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", -+ device->mac[0], device->mac[1], -+ device->mac[2], device->mac[3], -+ device->mac[4], device->mac[5]); -+ printk(": "); -+ dev = kmalloc(sizeof(*dev) + size, GFP_KERNEL); -+ if(dev == NULL){ -+ printk(KERN_ERR "eth_configure: failed to allocate device\n"); -+ return(1); -+ } -+ memset(dev, 0, sizeof(*dev) + size); -+ -+ snprintf(dev->name, sizeof(dev->name), "eth%d", n); -+ dev->priv = (void *) &dev[1]; -+ device->dev = dev; -+ -+ dev->hard_header = uml_net_hard_header; -+ dev->rebuild_header = uml_net_rebuild_header; -+ dev->hard_header_cache = uml_net_header_cache; -+ dev->header_cache_update= uml_net_header_cache_update; -+ dev->hard_header_parse = uml_net_header_parse; -+ -+ (*transport->kern->init)(dev, init); -+ -+ dev->mtu = transport->user->max_packet; -+ dev->open = uml_net_open; -+ dev->hard_start_xmit = uml_net_start_xmit; -+ dev->stop = uml_net_close; -+ dev->get_stats = uml_net_get_stats; -+ dev->set_multicast_list = uml_net_set_multicast_list; -+ dev->tx_timeout = uml_net_tx_timeout; -+ dev->set_mac_address = uml_net_set_mac; -+ dev->change_mtu = uml_net_change_mtu; -+ dev->do_ioctl = uml_net_ioctl; -+ dev->watchdog_timeo = (HZ >> 1); -+ dev->irq = UM_ETH_IRQ; -+ -+ rtnl_lock(); -+ err = register_netdevice(dev); -+ rtnl_unlock(); -+ if(err) -+ return(1); -+ lp = dev->priv; -+ -+ /* lp.user is the first four bytes of the transport data, which -+ * has already been initialized. This structure assignment will -+ * overwrite that, so we make sure that .user gets overwritten with -+ * what it already has. -+ */ -+ save = lp->user[0]; -+ *lp = ((struct uml_net_private) -+ { .list = LIST_HEAD_INIT(lp->list), -+ .lock = SPIN_LOCK_UNLOCKED, -+ .dev = dev, -+ .fd = -1, -+ .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, -+ .have_mac = device->have_mac, -+ .protocol = transport->kern->protocol, -+ .open = transport->user->open, -+ .close = transport->user->close, -+ .remove = transport->user->remove, -+ .read = transport->kern->read, -+ .write = transport->kern->write, -+ .add_address = transport->user->add_address, -+ .delete_address = transport->user->delete_address, -+ .set_mtu = transport->user->set_mtu, -+ .user = { save } }); -+ init_timer(&lp->tl); -+ lp->tl.function = uml_net_user_timer_expire; -+ memset(&lp->stats, 0, sizeof(lp->stats)); -+ if(lp->have_mac) memcpy(lp->mac, device->mac, sizeof(lp->mac)); -+ -+ if(transport->user->init) -+ (*transport->user->init)(&lp->user, dev); -+ -+ if(device->have_mac) -+ set_ether_mac(dev, device->mac); -+ return(0); -+} -+ -+static struct uml_net *find_device(int n) -+{ -+ struct uml_net *device; -+ struct list_head *ele; -+ -+ spin_lock(&devices_lock); -+ list_for_each(ele, &devices){ -+ device = list_entry(ele, struct uml_net, list); -+ if(device->index == n) -+ goto out; -+ } -+ device = NULL; -+ out: -+ spin_unlock(&devices_lock); -+ return(device); -+} -+ -+static int eth_parse(char *str, int *index_out, char **str_out) -+{ -+ char *end; -+ int n; -+ -+ n = simple_strtoul(str, &end, 0); -+ if(end == str){ -+ printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); -+ return(1); -+ } -+ if(n < 0){ -+ printk(KERN_ERR "eth_setup: device %d is negative\n", n); -+ return(1); -+ } -+ str = end; -+ if(*str != '='){ -+ printk(KERN_ERR -+ "eth_setup: expected '=' after device number\n"); -+ return(1); -+ } -+ str++; -+ if(find_device(n)){ -+ printk(KERN_ERR "eth_setup: Device %d already configured\n", -+ n); -+ return(1); -+ } -+ if(index_out) *index_out = n; -+ *str_out = str; -+ return(0); -+} -+ -+struct eth_init { -+ struct list_head list; -+ char *init; -+ int index; -+}; -+ -+/* Filled in at boot time. Will need locking if the transports become -+ * modular. -+ */ -+struct list_head transports = LIST_HEAD_INIT(transports); -+ -+/* Filled in during early boot */ -+struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); -+ -+static int check_transport(struct transport *transport, char *eth, int n, -+ void **init_out, char **mac_out) -+{ -+ int len; -+ -+ len = strlen(transport->name); -+ if(strncmp(eth, transport->name, len)) -+ return(0); -+ -+ eth += len; -+ if(*eth == ',') -+ eth++; -+ else if(*eth != '\0') -+ return(0); -+ -+ *init_out = kmalloc(transport->setup_size, GFP_KERNEL); -+ if(*init_out == NULL) -+ return(1); -+ -+ if(!transport->setup(eth, mac_out, *init_out)){ -+ kfree(*init_out); -+ *init_out = NULL; -+ } -+ return(1); -+} -+ -+void register_transport(struct transport *new) -+{ -+ struct list_head *ele, *next; -+ struct eth_init *eth; -+ void *init; -+ char *mac = NULL; -+ int match; -+ -+ list_add(&new->list, &transports); -+ -+ list_for_each_safe(ele, next, ð_cmd_line){ -+ eth = list_entry(ele, struct eth_init, list); -+ match = check_transport(new, eth->init, eth->index, &init, -+ &mac); -+ if(!match) -+ continue; -+ else if(init != NULL){ -+ eth_configure(eth->index, init, mac, new); -+ kfree(init); -+ } -+ list_del(ð->list); -+ } -+} -+ -+static int eth_setup_common(char *str, int index) -+{ -+ struct list_head *ele; -+ struct transport *transport; -+ void *init; -+ char *mac = NULL; -+ -+ list_for_each(ele, &transports){ -+ transport = list_entry(ele, struct transport, list); -+ if(!check_transport(transport, str, index, &init, &mac)) -+ continue; -+ if(init != NULL){ -+ eth_configure(index, init, mac, transport); -+ kfree(init); -+ } -+ return(1); -+ } -+ return(0); -+} -+ -+static int eth_setup(char *str) -+{ -+ struct eth_init *new; -+ int n, err; -+ -+ err = eth_parse(str, &n, &str); -+ if(err) return(1); -+ -+ new = alloc_bootmem(sizeof(new)); -+ if(new == NULL){ -+ printk("eth_init : alloc_bootmem failed\n"); -+ return(1); -+ } -+ *new = ((struct eth_init) { .list = LIST_HEAD_INIT(new->list), -+ .index = n, -+ .init = str }); -+ list_add_tail(&new->list, ð_cmd_line); -+ return(1); -+} -+ -+__setup("eth", eth_setup); -+__uml_help(eth_setup, -+"eth[0-9]+=,\n" -+" Configure a network device.\n\n" -+); -+ -+static int eth_init(void) -+{ -+ struct list_head *ele, *next; -+ struct eth_init *eth; -+ -+ list_for_each_safe(ele, next, ð_cmd_line){ -+ eth = list_entry(ele, struct eth_init, list); -+ -+ if(eth_setup_common(eth->init, eth->index)) -+ list_del(ð->list); -+ } -+ -+ return(1); -+} -+ -+__initcall(eth_init); -+ -+static int net_config(char *str) -+{ -+ int n, err; -+ -+ err = eth_parse(str, &n, &str); -+ if(err) return(err); -+ -+ str = uml_strdup(str); -+ if(str == NULL){ -+ printk(KERN_ERR "net_config failed to strdup string\n"); -+ return(-1); -+ } -+ err = !eth_setup_common(str, n); -+ if(err) -+ kfree(str); -+ return(err); -+} -+ -+static int net_remove(char *str) -+{ -+ struct uml_net *device; -+ struct net_device *dev; -+ struct uml_net_private *lp; -+ char *end; -+ int n; -+ -+ n = simple_strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)) -+ return(-1); -+ -+ device = find_device(n); -+ if(device == NULL) -+ return(0); -+ -+ dev = device->dev; -+ lp = dev->priv; -+ if(lp->fd > 0) return(-1); -+ if(lp->remove != NULL) (*lp->remove)(&lp->user); -+ unregister_netdev(dev); -+ -+ list_del(&device->list); -+ kfree(device); -+ return(0); -+} -+ -+static struct mc_device net_mc = { -+ .name = "eth", -+ .config = net_config, -+ .get_config = NULL, -+ .remove = net_remove, -+}; -+ -+static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, -+ void *ptr) -+{ -+ struct in_ifaddr *ifa = ptr; -+ u32 addr = ifa->ifa_address; -+ u32 netmask = ifa->ifa_mask; -+ struct net_device *dev = ifa->ifa_dev->dev; -+ struct uml_net_private *lp; -+ void (*proc)(unsigned char *, unsigned char *, void *); -+ unsigned char addr_buf[4], netmask_buf[4]; -+ -+ if(dev->open != uml_net_open) return(NOTIFY_DONE); -+ -+ lp = dev->priv; -+ -+ proc = NULL; -+ switch (event){ -+ case NETDEV_UP: -+ proc = lp->add_address; -+ break; -+ case NETDEV_DOWN: -+ proc = lp->delete_address; -+ break; -+ } -+ if(proc != NULL){ -+ addr_buf[0] = addr & 0xff; -+ addr_buf[1] = (addr >> 8) & 0xff; -+ addr_buf[2] = (addr >> 16) & 0xff; -+ addr_buf[3] = addr >> 24; -+ netmask_buf[0] = netmask & 0xff; -+ netmask_buf[1] = (netmask >> 8) & 0xff; -+ netmask_buf[2] = (netmask >> 16) & 0xff; -+ netmask_buf[3] = netmask >> 24; -+ (*proc)(addr_buf, netmask_buf, &lp->user); -+ } -+ return(NOTIFY_DONE); -+} -+ -+struct notifier_block uml_inetaddr_notifier = { -+ .notifier_call = uml_inetaddr_event, -+}; -+ -+static int uml_net_init(void) -+{ -+ struct list_head *ele; -+ struct uml_net_private *lp; -+ struct in_device *ip; -+ struct in_ifaddr *in; -+ -+ mconsole_register_dev(&net_mc); -+ register_inetaddr_notifier(¨_inetaddr_notifier); -+ -+ /* Devices may have been opened already, so the uml_inetaddr_notifier -+ * didn't get a chance to run for them. This fakes it so that -+ * addresses which have already been set up get handled properly. -+ */ -+ list_for_each(ele, &opened){ -+ lp = list_entry(ele, struct uml_net_private, list); -+ ip = lp->dev->ip_ptr; -+ if(ip == NULL) continue; -+ in = ip->ifa_list; -+ while(in != NULL){ -+ uml_inetaddr_event(NULL, NETDEV_UP, in); -+ in = in->ifa_next; -+ } -+ } -+ -+ return(0); -+} -+ -+__initcall(uml_net_init); -+ -+static void close_devices(void) -+{ -+ struct list_head *ele; -+ struct uml_net_private *lp; -+ -+ list_for_each(ele, &opened){ -+ lp = list_entry(ele, struct uml_net_private, list); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ if(lp->remove != NULL) (*lp->remove)(&lp->user); -+ } -+} -+ -+__uml_exitcall(close_devices); -+ -+int setup_etheraddr(char *str, unsigned char *addr) -+{ -+ char *end; -+ int i; -+ -+ if(str == NULL) -+ return(0); -+ for(i=0;i<6;i++){ -+ addr[i] = simple_strtoul(str, &end, 16); -+ if((end == str) || -+ ((*end != ':') && (*end != ',') && (*end != '\0'))){ -+ printk(KERN_ERR -+ "setup_etheraddr: failed to parse '%s' " -+ "as an ethernet address\n", str); -+ return(0); -+ } -+ str = end + 1; -+ } -+ if(addr[0] & 1){ -+ printk(KERN_ERR -+ "Attempt to assign a broadcast ethernet address to a " -+ "device disallowed\n"); -+ return(0); -+ } -+ return(1); -+} -+ -+void dev_ip_addr(void *d, char *buf, char *bin_buf) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ u32 addr; -+ -+ if((ip == NULL) || ((in = ip->ifa_list) == NULL)){ -+ printk(KERN_WARNING "dev_ip_addr - device not assigned an " -+ "IP address\n"); -+ return; -+ } -+ addr = in->ifa_address; -+ sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, -+ (addr >> 16) & 0xff, addr >> 24); -+ if(bin_buf){ -+ bin_buf[0] = addr & 0xff; -+ bin_buf[1] = (addr >> 8) & 0xff; -+ bin_buf[2] = (addr >> 16) & 0xff; -+ bin_buf[3] = addr >> 24; -+ } -+} -+ -+void set_ether_mac(void *d, unsigned char *addr) -+{ -+ struct net_device *dev = d; -+ -+ memcpy(dev->dev_addr, addr, ETH_ALEN); -+} -+ -+struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) -+{ -+ if((skb != NULL) && (skb_tailroom(skb) < extra)){ -+ struct sk_buff *skb2; -+ -+ skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); -+ dev_kfree_skb(skb); -+ skb = skb2; -+ } -+ if(skb != NULL) skb_put(skb, extra); -+ return(skb); -+} -+ -+void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, -+ void *), -+ void *arg) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ unsigned char address[4], netmask[4]; -+ -+ if(ip == NULL) return; -+ in = ip->ifa_list; -+ while(in != NULL){ -+ address[0] = in->ifa_address & 0xff; -+ address[1] = (in->ifa_address >> 8) & 0xff; -+ address[2] = (in->ifa_address >> 16) & 0xff; -+ address[3] = in->ifa_address >> 24; -+ netmask[0] = in->ifa_mask & 0xff; -+ netmask[1] = (in->ifa_mask >> 8) & 0xff; -+ netmask[2] = (in->ifa_mask >> 16) & 0xff; -+ netmask[3] = in->ifa_mask >> 24; -+ (*cb)(address, netmask, arg); -+ in = in->ifa_next; -+ } -+} -+ -+int dev_netmask(void *d, void *m) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ __u32 *mask_out = m; -+ -+ if(ip == NULL) -+ return(1); -+ -+ in = ip->ifa_list; -+ if(in == NULL) -+ return(1); -+ -+ *mask_out = in->ifa_mask; -+ return(0); -+} -+ -+void *get_output_buffer(int *len_out) -+{ -+ void *ret; -+ -+ ret = (void *) __get_free_pages(GFP_KERNEL, 0); -+ if(ret) *len_out = PAGE_SIZE; -+ else *len_out = 0; -+ return(ret); -+} -+ -+void free_output_buffer(void *buffer) -+{ -+ free_pages((unsigned long) buffer, 0); -+} -+ -+int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, -+ char **gate_addr) -+{ -+ char *remain; -+ -+ remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); -+ if(remain != NULL){ -+ printk("tap_setup_common - Extra garbage on specification : " -+ "'%s'\n", remain); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+unsigned short eth_protocol(struct sk_buff *skb) -+{ -+ return(eth_type_trans(skb, skb->dev)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/net_user.c um/arch/um/drivers/net_user.c ---- orig/arch/um/drivers/net_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/net_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,252 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "net_user.h" -+#include "helper.h" -+#include "os.h" -+ -+int tap_open_common(void *dev, char *gate_addr) -+{ -+ int tap_addr[4]; -+ -+ if(gate_addr == NULL) return(0); -+ if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], -+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ -+ printk("Invalid tap IP address - '%s'\n", gate_addr); -+ return(-EINVAL); -+ } -+ return(0); -+} -+ -+void tap_check_ips(char *gate_addr, char *eth_addr) -+{ -+ int tap_addr[4]; -+ -+ if((gate_addr != NULL) && -+ (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], -+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && -+ (eth_addr[0] == tap_addr[0]) && -+ (eth_addr[1] == tap_addr[1]) && -+ (eth_addr[2] == tap_addr[2]) && -+ (eth_addr[3] == tap_addr[3])){ -+ printk("The tap IP address and the UML eth IP address" -+ " must be different\n"); -+ } -+} -+ -+void read_output(int fd, char *output, int len) -+{ -+ int remain, n, actual; -+ char c; -+ -+ if(output == NULL){ -+ output = &c; -+ len = sizeof(c); -+ } -+ -+ *output = '\0'; -+ n = os_read_file(fd, &remain, sizeof(remain)); -+ if(n != sizeof(remain)){ -+ printk("read_output - read of length failed, err = %d\n", -n); -+ return; -+ } -+ -+ while(remain != 0){ -+ n = (remain < len) ? remain : len; -+ actual = os_read_file(fd, output, n); -+ if(actual != n){ -+ printk("read_output - read of data failed, " -+ "err = %d\n", -actual); -+ return; -+ } -+ remain -= actual; -+ } -+ return; -+} -+ -+int net_read(int fd, void *buf, int len) -+{ -+ int n; -+ -+ n = os_read_file(fd, buf, len); -+ -+ if(n == -EAGAIN) -+ return(0); -+ else if(n == 0) -+ return(-ENOTCONN); -+ return(n); -+} -+ -+int net_recvfrom(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) && -+ (errno == EINTR)) ; -+ -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+int net_write(int fd, void *buf, int len) -+{ -+ int n; -+ -+ n = os_write_file(fd, buf, len); -+ -+ if(n == -EAGAIN) -+ return(0); -+ else if(n == 0) -+ return(-ENOTCONN); -+ return(n); -+} -+ -+int net_send(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ; -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+int net_sendto(int fd, void *buf, int len, void *to, int sock_len) -+{ -+ int n; -+ -+ while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to, -+ sock_len)) < 0) && (errno == EINTR)) ; -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+struct change_pre_exec_data { -+ int close_me; -+ int stdout; -+}; -+ -+static void change_pre_exec(void *arg) -+{ -+ struct change_pre_exec_data *data = arg; -+ -+ os_close_file(data->close_me); -+ dup2(data->stdout, 1); -+} -+ -+static int change_tramp(char **argv, char *output, int output_len) -+{ -+ int pid, fds[2], err; -+ struct change_pre_exec_data pe_data; -+ -+ err = os_pipe(fds, 1, 0); -+ if(err < 0){ -+ printk("change_tramp - pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ pe_data.close_me = fds[0]; -+ pe_data.stdout = fds[1]; -+ pid = run_helper(change_pre_exec, &pe_data, argv, NULL); -+ -+ os_close_file(fds[1]); -+ read_output(fds[0], output, output_len); -+ waitpid(pid, NULL, 0); -+ return(pid); -+} -+ -+static void change(char *dev, char *what, unsigned char *addr, -+ unsigned char *netmask) -+{ -+ char addr_buf[sizeof("255.255.255.255\0")]; -+ char netmask_buf[sizeof("255.255.255.255\0")]; -+ char version[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version, what, dev, addr_buf, -+ netmask_buf, NULL }; -+ char *output; -+ int output_len, pid; -+ -+ sprintf(version, "%d", UML_NET_VERSION); -+ sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); -+ sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], -+ netmask[2], netmask[3]); -+ -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ if(output == NULL) -+ printk("change : failed to allocate output buffer\n"); -+ -+ pid = change_tramp(argv, output, output_len); -+ if(pid < 0) return; -+ -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+} -+ -+void open_addr(unsigned char *addr, unsigned char *netmask, void *arg) -+{ -+ change(arg, "add", addr, netmask); -+} -+ -+void close_addr(unsigned char *addr, unsigned char *netmask, void *arg) -+{ -+ change(arg, "del", addr, netmask); -+} -+ -+char *split_if_spec(char *str, ...) -+{ -+ char **arg, *end; -+ va_list ap; -+ -+ va_start(ap, str); -+ while((arg = va_arg(ap, char **)) != NULL){ -+ if(*str == '\0') -+ return(NULL); -+ end = strchr(str, ','); -+ if(end != str) -+ *arg = str; -+ if(end == NULL) -+ return(NULL); -+ *end++ = '\0'; -+ str = end; -+ } -+ va_end(ap); -+ return(str); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/null.c um/arch/um/drivers/null.c ---- orig/arch/um/drivers/null.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/null.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include "chan_user.h" -+#include "os.h" -+ -+static int null_chan; -+ -+void *null_init(char *str, int device, struct chan_opts *opts) -+{ -+ return(&null_chan); -+} -+ -+int null_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ *dev_out = NULL; -+ return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); -+} -+ -+int null_read(int fd, char *c_out, void *unused) -+{ -+ return(-ENODEV); -+} -+ -+void null_free(void *data) -+{ -+} -+ -+struct chan_ops null_ops = { -+ .type = "null", -+ .init = null_init, -+ .open = null_open, -+ .close = generic_close, -+ .read = null_read, -+ .write = generic_write, -+ .console_write = generic_console_write, -+ .window_size = generic_window_size, -+ .free = null_free, -+ .winch = 0, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/pcap_kern.c um/arch/um/drivers/pcap_kern.c ---- orig/arch/um/drivers/pcap_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/pcap_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "pcap_user.h" -+ -+struct pcap_init { -+ char *host_if; -+ int promisc; -+ int optimize; -+ char *filter; -+}; -+ -+void pcap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct pcap_data *ppri; -+ struct pcap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ ppri = (struct pcap_data *) pri->user; -+ *ppri = ((struct pcap_data) -+ { .host_if = init->host_if, -+ .promisc = init->promisc, -+ .optimize = init->optimize, -+ .filter = init->filter, -+ .compiled = NULL, -+ .pcap = NULL }); -+} -+ -+static int pcap_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(pcap_user_read(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER, -+ (struct pcap_data *) &lp->user)); -+} -+ -+static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ return(-EPERM); -+} -+ -+static struct net_kern_info pcap_kern_info = { -+ .init = pcap_init, -+ .protocol = eth_protocol, -+ .read = pcap_read, -+ .write = pcap_write, -+}; -+ -+int pcap_setup(char *str, char **mac_out, void *data) -+{ -+ struct pcap_init *init = data; -+ char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; -+ int i; -+ -+ *init = ((struct pcap_init) -+ { .host_if = "eth0", -+ .promisc = 1, -+ .optimize = 0, -+ .filter = NULL }); -+ -+ remain = split_if_spec(str, &host_if, &init->filter, -+ &options[0], &options[1], NULL); -+ if(remain != NULL){ -+ printk(KERN_ERR "pcap_setup - Extra garbage on " -+ "specification : '%s'\n", remain); -+ return(0); -+ } -+ -+ if(host_if != NULL) -+ init->host_if = host_if; -+ -+ for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){ -+ if(options[i] == NULL) -+ continue; -+ if(!strcmp(options[i], "promisc")) -+ init->promisc = 1; -+ else if(!strcmp(options[i], "nopromisc")) -+ init->promisc = 0; -+ else if(!strcmp(options[i], "optimize")) -+ init->optimize = 1; -+ else if(!strcmp(options[i], "nooptimize")) -+ init->optimize = 0; -+ else printk("pcap_setup : bad option - '%s'\n", options[i]); -+ } -+ -+ return(1); -+} -+ -+static struct transport pcap_transport = { -+ .list = LIST_HEAD_INIT(pcap_transport.list), -+ .name = "pcap", -+ .setup = pcap_setup, -+ .user = &pcap_user_info, -+ .kern = &pcap_kern_info, -+ .private_size = sizeof(struct pcap_data), -+ .setup_size = sizeof(struct pcap_init), -+}; -+ -+static int register_pcap(void) -+{ -+ register_transport(&pcap_transport); -+ return(1); -+} -+ -+__initcall(register_pcap); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/pcap_user.c um/arch/um/drivers/pcap_user.c ---- orig/arch/um/drivers/pcap_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/pcap_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike -+ * Licensed under the GPL. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "net_user.h" -+#include "pcap_user.h" -+#include "user.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+#define PCAP_FD(p) (*(int *)(p)) -+ -+static void pcap_user_init(void *data, void *dev) -+{ -+ struct pcap_data *pri = data; -+ pcap_t *p; -+ char errors[PCAP_ERRBUF_SIZE]; -+ -+ p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); -+ if(p == NULL){ -+ printk("pcap_user_init : pcap_open_live failed - '%s'\n", -+ errors); -+ return; -+ } -+ -+ pri->dev = dev; -+ pri->pcap = p; -+} -+ -+static int pcap_open(void *data) -+{ -+ struct pcap_data *pri = data; -+ __u32 netmask; -+ int err; -+ -+ if(pri->pcap == NULL) -+ return(-ENODEV); -+ -+ if(pri->filter != NULL){ -+ err = dev_netmask(pri->dev, &netmask); -+ if(err < 0){ -+ printk("pcap_open : dev_netmask failed\n"); -+ return(-EIO); -+ } -+ -+ pri->compiled = um_kmalloc(sizeof(struct bpf_program)); -+ if(pri->compiled == NULL){ -+ printk("pcap_open : kmalloc failed\n"); -+ return(-ENOMEM); -+ } -+ -+ err = pcap_compile(pri->pcap, -+ (struct bpf_program *) pri->compiled, -+ pri->filter, pri->optimize, netmask); -+ if(err < 0){ -+ printk("pcap_open : pcap_compile failed - '%s'\n", -+ pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ -+ err = pcap_setfilter(pri->pcap, pri->compiled); -+ if(err < 0){ -+ printk("pcap_open : pcap_setfilter failed - '%s'\n", -+ pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ } -+ -+ return(PCAP_FD(pri->pcap)); -+} -+ -+static void pcap_remove(void *data) -+{ -+ struct pcap_data *pri = data; -+ -+ if(pri->compiled != NULL) -+ pcap_freecode(pri->compiled); -+ -+ pcap_close(pri->pcap); -+} -+ -+struct pcap_handler_data { -+ char *buffer; -+ int len; -+}; -+ -+static void handler(u_char *data, const struct pcap_pkthdr *header, -+ const u_char *packet) -+{ -+ int len; -+ -+ struct pcap_handler_data *hdata = (struct pcap_handler_data *) data; -+ -+ len = hdata->len < header->caplen ? hdata->len : header->caplen; -+ memcpy(hdata->buffer, packet, len); -+ hdata->len = len; -+} -+ -+int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) -+{ -+ struct pcap_handler_data hdata = ((struct pcap_handler_data) -+ { .buffer = buffer, -+ .len = len }); -+ int n; -+ -+ n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); -+ if(n < 0){ -+ printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ else if(n == 0) -+ return(0); -+ return(hdata.len); -+} -+ -+struct net_user_info pcap_user_info = { -+ .init = pcap_user_init, -+ .open = pcap_open, -+ .close = NULL, -+ .remove = pcap_remove, -+ .set_mtu = NULL, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/pcap_user.h um/arch/um/drivers/pcap_user.h ---- orig/arch/um/drivers/pcap_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/pcap_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct pcap_data { -+ char *host_if; -+ int promisc; -+ int optimize; -+ char *filter; -+ void *compiled; -+ void *pcap; -+ void *dev; -+}; -+ -+extern struct net_user_info pcap_user_info; -+ -+extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/port.h um/arch/um/drivers/port.h ---- orig/arch/um/drivers/port.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/port.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PORT_H__ -+#define __PORT_H__ -+ -+extern void *port_data(int port); -+extern int port_wait(void *data); -+extern void port_kern_close(void *d); -+extern int port_connection(int fd, int *socket_out, int *pid_out); -+extern int port_listen_fd(int port); -+extern void port_read(int fd, void *data); -+extern void port_kern_free(void *d); -+extern int port_rcv_fd(int fd); -+extern void port_remove_dev(void *d); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/port_kern.c um/arch/um/drivers/port_kern.c ---- orig/arch/um/drivers/port_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/port_kern.c 2004-01-10 06:18:49.000000000 -0500 -@@ -0,0 +1,303 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/list.h" -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "linux/irq.h" -+#include "linux/spinlock.h" -+#include "linux/errno.h" -+#include "asm/semaphore.h" -+#include "asm/errno.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "port.h" -+#include "init.h" -+#include "os.h" -+ -+struct port_list { -+ struct list_head list; -+ int has_connection; -+ struct semaphore sem; -+ int port; -+ int fd; -+ spinlock_t lock; -+ struct list_head pending; -+ struct list_head connections; -+}; -+ -+struct port_dev { -+ struct port_list *port; -+ int helper_pid; -+ int telnetd_pid; -+}; -+ -+struct connection { -+ struct list_head list; -+ int fd; -+ int helper_pid; -+ int socket[2]; -+ int telnetd_pid; -+ struct port_list *port; -+}; -+ -+static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct connection *conn = data; -+ int fd; -+ -+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); -+ if(fd < 0){ -+ if(fd == -EAGAIN) -+ return; -+ -+ printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -+ -fd); -+ os_close_file(conn->fd); -+ } -+ -+ list_del(&conn->list); -+ -+ conn->fd = fd; -+ list_add(&conn->list, &conn->port->connections); -+ -+ up(&conn->port->sem); -+} -+ -+static int port_accept(struct port_list *port) -+{ -+ struct connection *conn; -+ int fd, socket[2], pid, ret = 0; -+ -+ fd = port_connection(port->fd, socket, &pid); -+ if(fd < 0){ -+ if(fd != -EAGAIN) -+ printk(KERN_ERR "port_accept : port_connection " -+ "returned %d\n", -fd); -+ goto out; -+ } -+ -+ conn = kmalloc(sizeof(*conn), GFP_ATOMIC); -+ if(conn == NULL){ -+ printk(KERN_ERR "port_accept : failed to allocate " -+ "connection\n"); -+ goto out_close; -+ } -+ *conn = ((struct connection) -+ { .list = LIST_HEAD_INIT(conn->list), -+ .fd = fd, -+ .socket = { socket[0], socket[1] }, -+ .telnetd_pid = pid, -+ .port = port }); -+ -+ if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "telnetd", conn)){ -+ printk(KERN_ERR "port_accept : failed to get IRQ for " -+ "telnetd\n"); -+ goto out_free; -+ } -+ -+ list_add(&conn->list, &port->pending); -+ return(1); -+ -+ out_free: -+ kfree(conn); -+ out_close: -+ os_close_file(fd); -+ if(pid != -1) -+ os_kill_process(pid, 1); -+ out: -+ return(ret); -+} -+ -+DECLARE_MUTEX(ports_sem); -+struct list_head ports = LIST_HEAD_INIT(ports); -+ -+void port_task_proc(void *unused) -+{ -+ struct port_list *port; -+ struct list_head *ele; -+ unsigned long flags; -+ -+ save_flags(flags); -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ if(!port->has_connection) -+ continue; -+ reactivate_fd(port->fd, ACCEPT_IRQ); -+ while(port_accept(port)) ; -+ port->has_connection = 0; -+ } -+ restore_flags(flags); -+} -+ -+struct tq_struct port_task = { -+ .routine = port_task_proc, -+ .data = NULL -+}; -+ -+static void port_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct port_list *port = data; -+ -+ port->has_connection = 1; -+ schedule_task(&port_task); -+} -+ -+void *port_data(int port_num) -+{ -+ struct list_head *ele; -+ struct port_list *port; -+ struct port_dev *dev = NULL; -+ int fd; -+ -+ down(&ports_sem); -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ if(port->port == port_num) goto found; -+ } -+ port = kmalloc(sizeof(struct port_list), GFP_KERNEL); -+ if(port == NULL){ -+ printk(KERN_ERR "Allocation of port list failed\n"); -+ goto out; -+ } -+ -+ fd = port_listen_fd(port_num); -+ if(fd < 0){ -+ printk(KERN_ERR "binding to port %d failed, errno = %d\n", -+ port_num, -fd); -+ goto out_free; -+ } -+ if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port", -+ port)){ -+ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); -+ goto out_close; -+ } -+ -+ *port = ((struct port_list) -+ { .list = LIST_HEAD_INIT(port->list), -+ .has_connection = 0, -+ .sem = __SEMAPHORE_INITIALIZER(port->sem, -+ 0), -+ .lock = SPIN_LOCK_UNLOCKED, -+ .port = port_num, -+ .fd = fd, -+ .pending = LIST_HEAD_INIT(port->pending), -+ .connections = LIST_HEAD_INIT(port->connections) }); -+ list_add(&port->list, &ports); -+ -+ found: -+ dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); -+ if(dev == NULL){ -+ printk(KERN_ERR "Allocation of port device entry failed\n"); -+ goto out; -+ } -+ -+ *dev = ((struct port_dev) { .port = port, -+ .helper_pid = -1, -+ .telnetd_pid = -1 }); -+ goto out; -+ -+ out_free: -+ kfree(port); -+ out_close: -+ os_close_file(fd); -+ out: -+ up(&ports_sem); -+ return(dev); -+} -+ -+int port_wait(void *data) -+{ -+ struct port_dev *dev = data; -+ struct connection *conn; -+ struct port_list *port = dev->port; -+ int fd; -+ -+ while(1){ -+ if(down_interruptible(&port->sem)) -+ return(-ERESTARTSYS); -+ -+ spin_lock(&port->lock); -+ -+ conn = list_entry(port->connections.next, struct connection, -+ list); -+ list_del(&conn->list); -+ spin_unlock(&port->lock); -+ -+ os_shutdown_socket(conn->socket[0], 1, 1); -+ os_close_file(conn->socket[0]); -+ os_shutdown_socket(conn->socket[1], 1, 1); -+ os_close_file(conn->socket[1]); -+ -+ /* This is done here because freeing an IRQ can't be done -+ * within the IRQ handler. So, pipe_interrupt always ups -+ * the semaphore regardless of whether it got a successful -+ * connection. Then we loop here throwing out failed -+ * connections until a good one is found. -+ */ -+ free_irq(TELNETD_IRQ, conn); -+ -+ if(conn->fd >= 0) break; -+ os_close_file(conn->fd); -+ kfree(conn); -+ } -+ -+ fd = conn->fd; -+ dev->helper_pid = conn->helper_pid; -+ dev->telnetd_pid = conn->telnetd_pid; -+ kfree(conn); -+ -+ return(fd); -+} -+ -+void port_remove_dev(void *d) -+{ -+ struct port_dev *dev = d; -+ -+ if(dev->helper_pid != -1) -+ os_kill_process(dev->helper_pid, 0); -+ if(dev->telnetd_pid != -1) -+ os_kill_process(dev->telnetd_pid, 1); -+ dev->helper_pid = -1; -+ dev->telnetd_pid = -1; -+} -+ -+void port_kern_free(void *d) -+{ -+ struct port_dev *dev = d; -+ -+ port_remove_dev(dev); -+ kfree(dev); -+} -+ -+static void free_port(void) -+{ -+ struct list_head *ele; -+ struct port_list *port; -+ -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ free_irq_by_fd(port->fd); -+ os_close_file(port->fd); -+ } -+} -+ -+__uml_exitcall(free_port); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/port_user.c um/arch/um/drivers/port_user.c ---- orig/arch/um/drivers/port_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/port_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "chan_user.h" -+#include "port.h" -+#include "helper.h" -+#include "os.h" -+ -+struct port_chan { -+ int raw; -+ struct termios tt; -+ void *kernel_data; -+ char dev[sizeof("32768\0")]; -+}; -+ -+void *port_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct port_chan *data; -+ void *kern_data; -+ char *end; -+ int port; -+ -+ if(*str != ':'){ -+ printk("port_init : channel type 'port' must specify a " -+ "port number\n"); -+ return(NULL); -+ } -+ str++; -+ port = strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk("port_init : couldn't parse port '%s'\n", str); -+ return(NULL); -+ } -+ -+ kern_data = port_data(port); -+ if(kern_data == NULL) -+ return(NULL); -+ -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) -+ goto err; -+ -+ *data = ((struct port_chan) { .raw = opts->raw, -+ .kernel_data = kern_data }); -+ sprintf(data->dev, "%d", port); -+ -+ return(data); -+ err: -+ port_kern_free(kern_data); -+ return(NULL); -+} -+ -+void port_free(void *d) -+{ -+ struct port_chan *data = d; -+ -+ port_kern_free(data->kernel_data); -+ kfree(data); -+} -+ -+int port_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct port_chan *data = d; -+ int fd; -+ -+ fd = port_wait(data->kernel_data); -+ if((fd >= 0) && data->raw){ -+ tcgetattr(fd, &data->tt); -+ raw(fd, 0); -+ } -+ *dev_out = data->dev; -+ return(fd); -+} -+ -+void port_close(int fd, void *d) -+{ -+ struct port_chan *data = d; -+ -+ port_remove_dev(data->kernel_data); -+ os_close_file(fd); -+} -+ -+int port_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct port_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops port_ops = { -+ .type = "port", -+ .init = port_init, -+ .open = port_open, -+ .close = port_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = port_console_write, -+ .window_size = generic_window_size, -+ .free = port_free, -+ .winch = 1, -+}; -+ -+int port_listen_fd(int port) -+{ -+ struct sockaddr_in addr; -+ int fd, err; -+ -+ fd = socket(PF_INET, SOCK_STREAM, 0); -+ if(fd == -1) -+ return(-errno); -+ -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = htonl(INADDR_ANY); -+ if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ -+ err = -errno; -+ goto out; -+ } -+ -+ if(listen(fd, 1) < 0){ -+ err = -errno; -+ goto out; -+ } -+ -+ err = os_set_fd_block(fd, 0); -+ if(err < 0) -+ goto out; -+ -+ return(fd); -+ out: -+ os_close_file(fd); -+ return(err); -+} -+ -+struct port_pre_exec_data { -+ int sock_fd; -+ int pipe_fd; -+}; -+ -+void port_pre_exec(void *arg) -+{ -+ struct port_pre_exec_data *data = arg; -+ -+ dup2(data->sock_fd, 0); -+ dup2(data->sock_fd, 1); -+ dup2(data->sock_fd, 2); -+ os_close_file(data->sock_fd); -+ dup2(data->pipe_fd, 3); -+ os_shutdown_socket(3, 1, 0); -+ os_close_file(data->pipe_fd); -+} -+ -+int port_connection(int fd, int *socket, int *pid_out) -+{ -+ int new, err; -+ char *argv[] = { "/usr/sbin/in.telnetd", "-L", -+ "/usr/lib/uml/port-helper", NULL }; -+ struct port_pre_exec_data data; -+ -+ new = os_accept_connection(fd); -+ if(new < 0) -+ return(new); -+ -+ err = os_pipe(socket, 0, 0); -+ if(err < 0) -+ goto out_close; -+ -+ data = ((struct port_pre_exec_data) -+ { .sock_fd = new, -+ .pipe_fd = socket[1] }); -+ -+ err = run_helper(port_pre_exec, &data, argv, NULL); -+ if(err < 0) -+ goto out_shutdown; -+ -+ *pid_out = err; -+ return(new); -+ -+ out_shutdown: -+ os_shutdown_socket(socket[0], 1, 1); -+ os_close_file(socket[0]); -+ os_shutdown_socket(socket[1], 1, 1); -+ os_close_file(socket[1]); -+ out_close: -+ os_close_file(new); -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/pty.c um/arch/um/drivers/pty.c ---- orig/arch/um/drivers/pty.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/pty.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,148 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "chan_user.h" -+#include "user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "os.h" -+ -+struct pty_chan { -+ void (*announce)(char *dev_name, int dev); -+ int dev; -+ int raw; -+ struct termios tt; -+ char dev_name[sizeof("/dev/pts/0123456\0")]; -+}; -+ -+void *pty_chan_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct pty_chan *data; -+ -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) return(NULL); -+ *data = ((struct pty_chan) { .announce = opts->announce, -+ .dev = device, -+ .raw = opts->raw }); -+ return(data); -+} -+ -+int pts_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct pty_chan *data = d; -+ char *dev; -+ int fd; -+ -+ fd = get_pty(); -+ if(fd < 0){ -+ printk("open_pts : Failed to open pts\n"); -+ return(-errno); -+ } -+ if(data->raw){ -+ tcgetattr(fd, &data->tt); -+ raw(fd, 0); -+ } -+ -+ dev = ptsname(fd); -+ sprintf(data->dev_name, "%s", dev); -+ *dev_out = data->dev_name; -+ if(data->announce) (*data->announce)(dev, data->dev); -+ return(fd); -+} -+ -+int getmaster(char *line) -+{ -+ char *pty, *bank, *cp; -+ int master, err; -+ -+ pty = &line[strlen("/dev/ptyp")]; -+ for (bank = "pqrs"; *bank; bank++) { -+ line[strlen("/dev/pty")] = *bank; -+ *pty = '0'; -+ if (os_stat_file(line, NULL) < 0) -+ break; -+ for (cp = "0123456789abcdef"; *cp; cp++) { -+ *pty = *cp; -+ master = os_open_file(line, of_rdwr(OPENFLAGS()), 0); -+ if (master >= 0) { -+ char *tp = &line[strlen("/dev/")]; -+ -+ /* verify slave side is usable */ -+ *tp = 't'; -+ err = os_access(line, OS_ACC_RW_OK); -+ *tp = 'p'; -+ if(err == 0) return(master); -+ (void) os_close_file(master); -+ } -+ } -+ } -+ return(-1); -+} -+ -+int pty_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct pty_chan *data = d; -+ int fd; -+ char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx"; -+ -+ fd = getmaster(dev); -+ if(fd < 0) return(-errno); -+ -+ if(data->raw) raw(fd, 0); -+ if(data->announce) (*data->announce)(dev, data->dev); -+ -+ sprintf(data->dev_name, "%s", dev); -+ *dev_out = data->dev_name; -+ return(fd); -+} -+ -+int pty_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct pty_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops pty_ops = { -+ .type = "pty", -+ .init = pty_chan_init, -+ .open = pty_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = pty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+struct chan_ops pts_ops = { -+ .type = "pts", -+ .init = pty_chan_init, -+ .open = pts_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = pty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slip.h um/arch/um/drivers/slip.h ---- orig/arch/um/drivers/slip.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slip.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,39 @@ -+#ifndef __UM_SLIP_H -+#define __UM_SLIP_H -+ -+#define BUF_SIZE 1500 -+ /* two bytes each for a (pathological) max packet of escaped chars + * -+ * terminating END char + initial END char */ -+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2) -+ -+struct slip_data { -+ void *dev; -+ char name[sizeof("slnnnnn\0")]; -+ char *addr; -+ char *gate_addr; -+ int slave; -+ char ibuf[ENC_BUF_SIZE]; -+ char obuf[ENC_BUF_SIZE]; -+ int more; /* more data: do not read fd until ibuf has been drained */ -+ int pos; -+ int esc; -+}; -+ -+extern struct net_user_info slip_user_info; -+ -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); -+extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slip_kern.c um/arch/um/drivers/slip_kern.c ---- orig/arch/um/drivers/slip_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slip_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,109 @@ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/stddef.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/if_arp.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "kern.h" -+#include "slip.h" -+ -+struct slip_init { -+ char *gate_addr; -+}; -+ -+void slip_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *private; -+ struct slip_data *spri; -+ struct slip_init *init = data; -+ -+ private = dev->priv; -+ spri = (struct slip_data *) private->user; -+ *spri = ((struct slip_data) -+ { .name = { '\0' }, -+ .addr = NULL, -+ .gate_addr = init->gate_addr, -+ .slave = -1, -+ .ibuf = { '\0' }, -+ .obuf = { '\0' }, -+ .pos = 0, -+ .esc = 0, -+ .dev = dev }); -+ -+ dev->init = NULL; -+ dev->hard_header_len = 0; -+ dev->addr_len = 4; -+ dev->type = ARPHRD_ETHER; -+ dev->tx_queue_len = 256; -+ dev->flags = IFF_NOARP; -+ printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr); -+} -+ -+static unsigned short slip_protocol(struct sk_buff *skbuff) -+{ -+ return(htons(ETH_P_IP)); -+} -+ -+static int slip_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slip_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, -+ (struct slip_data *) &lp->user)); -+} -+ -+static int slip_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slip_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct slip_data *) &lp->user)); -+} -+ -+struct net_kern_info slip_kern_info = { -+ .init = slip_init, -+ .protocol = slip_protocol, -+ .read = slip_read, -+ .write = slip_write, -+}; -+ -+static int slip_setup(char *str, char **mac_out, void *data) -+{ -+ struct slip_init *init = data; -+ -+ *init = ((struct slip_init) -+ { .gate_addr = NULL }); -+ -+ if(str[0] != '\0') -+ init->gate_addr = str; -+ return(1); -+} -+ -+static struct transport slip_transport = { -+ .list = LIST_HEAD_INIT(slip_transport.list), -+ .name = "slip", -+ .setup = slip_setup, -+ .user = &slip_user_info, -+ .kern = &slip_kern_info, -+ .private_size = sizeof(struct slip_data), -+ .setup_size = sizeof(struct slip_init), -+}; -+ -+static int register_slip(void) -+{ -+ register_transport(&slip_transport); -+ return(1); -+} -+ -+__initcall(register_slip); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slip_proto.h um/arch/um/drivers/slip_proto.h ---- orig/arch/um/drivers/slip_proto.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slip_proto.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,93 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SLIP_PROTO_H__ -+#define __UM_SLIP_PROTO_H__ -+ -+/* SLIP protocol characters. */ -+#define SLIP_END 0300 /* indicates end of frame */ -+#define SLIP_ESC 0333 /* indicates byte stuffing */ -+#define SLIP_ESC_END 0334 /* ESC ESC_END means END 'data' */ -+#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */ -+ -+static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc) -+{ -+ int ret; -+ -+ switch(c){ -+ case SLIP_END: -+ *esc = 0; -+ ret=*pos; -+ *pos=0; -+ return(ret); -+ case SLIP_ESC: -+ *esc = 1; -+ return(0); -+ case SLIP_ESC_ESC: -+ if(*esc){ -+ *esc = 0; -+ c = SLIP_ESC; -+ } -+ break; -+ case SLIP_ESC_END: -+ if(*esc){ -+ *esc = 0; -+ c = SLIP_END; -+ } -+ break; -+ } -+ buf[(*pos)++] = c; -+ return(0); -+} -+ -+static inline int slip_esc(unsigned char *s, unsigned char *d, int len) -+{ -+ unsigned char *ptr = d; -+ unsigned char c; -+ -+ /* -+ * Send an initial END character to flush out any -+ * data that may have accumulated in the receiver -+ * due to line noise. -+ */ -+ -+ *ptr++ = SLIP_END; -+ -+ /* -+ * For each byte in the packet, send the appropriate -+ * character sequence, according to the SLIP protocol. -+ */ -+ -+ while (len-- > 0) { -+ switch(c = *s++) { -+ case SLIP_END: -+ *ptr++ = SLIP_ESC; -+ *ptr++ = SLIP_ESC_END; -+ break; -+ case SLIP_ESC: -+ *ptr++ = SLIP_ESC; -+ *ptr++ = SLIP_ESC_ESC; -+ break; -+ default: -+ *ptr++ = c; -+ break; -+ } -+ } -+ *ptr++ = SLIP_END; -+ return (ptr - d); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slip_user.c um/arch/um/drivers/slip_user.c ---- orig/arch/um/drivers/slip_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slip_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,274 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "net_user.h" -+#include "slip.h" -+#include "slip_proto.h" -+#include "helper.h" -+#include "os.h" -+ -+void slip_user_init(void *data, void *dev) -+{ -+ struct slip_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+static int set_up_tty(int fd) -+{ -+ int i; -+ struct termios tios; -+ -+ if (tcgetattr(fd, &tios) < 0) { -+ printk("could not get initial terminal attributes\n"); -+ return(-1); -+ } -+ -+ tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; -+ tios.c_iflag = IGNBRK | IGNPAR; -+ tios.c_oflag = 0; -+ tios.c_lflag = 0; -+ for (i = 0; i < NCCS; i++) -+ tios.c_cc[i] = 0; -+ tios.c_cc[VMIN] = 1; -+ tios.c_cc[VTIME] = 0; -+ -+ cfsetospeed(&tios, B38400); -+ cfsetispeed(&tios, B38400); -+ -+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { -+ printk("failed to set terminal attributes\n"); -+ return(-1); -+ } -+ return(0); -+} -+ -+struct slip_pre_exec_data { -+ int stdin; -+ int stdout; -+ int close_me; -+}; -+ -+static void slip_pre_exec(void *arg) -+{ -+ struct slip_pre_exec_data *data = arg; -+ -+ if(data->stdin >= 0) dup2(data->stdin, 0); -+ dup2(data->stdout, 1); -+ if(data->close_me >= 0) os_close_file(data->close_me); -+} -+ -+static int slip_tramp(char **argv, int fd) -+{ -+ struct slip_pre_exec_data pe_data; -+ char *output; -+ int status, pid, fds[2], err, output_len; -+ -+ err = os_pipe(fds, 1, 0); -+ if(err < 0){ -+ printk("slip_tramp : pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ -+ err = 0; -+ pe_data.stdin = fd; -+ pe_data.stdout = fds[1]; -+ pe_data.close_me = fds[0]; -+ pid = run_helper(slip_pre_exec, &pe_data, argv, NULL); -+ -+ if(pid < 0) err = pid; -+ else { -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ if(output == NULL) -+ printk("slip_tramp : failed to allocate output " -+ "buffer\n"); -+ -+ os_close_file(fds[1]); -+ read_output(fds[0], output, output_len); -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+ if(waitpid(pid, &status, 0) < 0) err = errno; -+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ -+ printk("'%s' didn't exit with status 0\n", argv[0]); -+ err = -EINVAL; -+ } -+ } -+ return(err); -+} -+ -+static int slip_open(void *data) -+{ -+ struct slip_data *pri = data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, -+ NULL }; -+ int sfd, mfd, err; -+ -+ mfd = get_pty(); -+ if(mfd < 0){ -+ printk("umn : Failed to open pty, err = %d\n", -mfd); -+ return(mfd); -+ } -+ sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); -+ if(sfd < 0){ -+ printk("Couldn't open tty for slip line, err = %d\n", -sfd); -+ return(sfd); -+ } -+ if(set_up_tty(sfd)) return(-1); -+ pri->slave = sfd; -+ pri->pos = 0; -+ pri->esc = 0; -+ if(pri->gate_addr != NULL){ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ strcpy(gate_buf, pri->gate_addr); -+ -+ err = slip_tramp(argv, sfd); -+ -+ if(err < 0){ -+ printk("slip_tramp failed - err = %d\n", -err); -+ return(err); -+ } -+ err = os_get_ifname(pri->slave, pri->name); -+ if(err < 0){ -+ printk("get_ifname failed, err = %d\n", -err); -+ return(err); -+ } -+ iter_addresses(pri->dev, open_addr, pri->name); -+ } -+ else { -+ err = os_set_slip(sfd); -+ if(err < 0){ -+ printk("Failed to set slip discipline encapsulation - " -+ "err = %d\n", -err); -+ return(err); -+ } -+ } -+ return(mfd); -+} -+ -+static void slip_close(int fd, void *data) -+{ -+ struct slip_data *pri = data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, -+ NULL }; -+ int err; -+ -+ if(pri->gate_addr != NULL) -+ iter_addresses(pri->dev, close_addr, pri->name); -+ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ -+ err = slip_tramp(argv, -1); -+ -+ if(err != 0) -+ printk("slip_tramp failed - errno = %d\n", -err); -+ os_close_file(fd); -+ os_close_file(pri->slave); -+ pri->slave = -1; -+} -+ -+int slip_user_read(int fd, void *buf, int len, struct slip_data *pri) -+{ -+ int i, n, size, start; -+ -+ if(pri->more>0) { -+ i = 0; -+ while(i < pri->more) { -+ size = slip_unesc(pri->ibuf[i++], -+ pri->ibuf, &pri->pos, &pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); -+ pri->more=pri->more-i; -+ return(size); -+ } -+ } -+ pri->more=0; -+ } -+ -+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); -+ if(n <= 0) return(n); -+ -+ start = pri->pos; -+ for(i = 0; i < n; i++){ -+ size = slip_unesc(pri->ibuf[start + i], -+ pri->ibuf, &pri->pos, &pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); -+ pri->more=n-(i+1); -+ return(size); -+ } -+ } -+ return(0); -+} -+ -+int slip_user_write(int fd, void *buf, int len, struct slip_data *pri) -+{ -+ int actual, n; -+ -+ actual = slip_esc(buf, pri->obuf, len); -+ n = net_write(fd, pri->obuf, actual); -+ if(n < 0) return(n); -+ else return(len); -+} -+ -+static int slip_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+static void slip_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct slip_data *pri = data; -+ -+ if(pri->slave < 0) return; -+ open_addr(addr, netmask, pri->name); -+} -+ -+static void slip_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct slip_data *pri = data; -+ -+ if(pri->slave < 0) return; -+ close_addr(addr, netmask, pri->name); -+} -+ -+struct net_user_info slip_user_info = { -+ .init = slip_user_init, -+ .open = slip_open, -+ .close = slip_close, -+ .remove = NULL, -+ .set_mtu = slip_set_mtu, -+ .add_address = slip_add_addr, -+ .delete_address = slip_del_addr, -+ .max_packet = BUF_SIZE -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slirp.h um/arch/um/drivers/slirp.h ---- orig/arch/um/drivers/slirp.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slirp.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,51 @@ -+#ifndef __UM_SLIRP_H -+#define __UM_SLIRP_H -+ -+#define BUF_SIZE 1500 -+ /* two bytes each for a (pathological) max packet of escaped chars + * -+ * terminating END char + initial END char */ -+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2) -+ -+#define SLIRP_MAX_ARGS 100 -+/* -+ * XXX this next definition is here because I don't understand why this -+ * initializer doesn't work in slirp_kern.c: -+ * -+ * argv : { init->argv[ 0 ... SLIRP_MAX_ARGS-1 ] }, -+ * -+ * or why I can't typecast like this: -+ * -+ * argv : (char* [SLIRP_MAX_ARGS])(init->argv), -+ */ -+struct arg_list_dummy_wrapper { char *argv[SLIRP_MAX_ARGS]; }; -+ -+struct slirp_data { -+ void *dev; -+ struct arg_list_dummy_wrapper argw; -+ int pid; -+ int slave; -+ char ibuf[ENC_BUF_SIZE]; -+ char obuf[ENC_BUF_SIZE]; -+ int more; /* more data: do not read fd until ibuf has been drained */ -+ int pos; -+ int esc; -+}; -+ -+extern struct net_user_info slirp_user_info; -+ -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); -+extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slirp_kern.c um/arch/um/drivers/slirp_kern.c ---- orig/arch/um/drivers/slirp_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slirp_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,132 @@ -+#include "linux/kernel.h" -+#include "linux/stddef.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/if_arp.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "kern.h" -+#include "slirp.h" -+ -+struct slirp_init { -+ struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */ -+}; -+ -+void slirp_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *private; -+ struct slirp_data *spri; -+ struct slirp_init *init = data; -+ int i; -+ -+ private = dev->priv; -+ spri = (struct slirp_data *) private->user; -+ *spri = ((struct slirp_data) -+ { .argw = init->argw, -+ .pid = -1, -+ .slave = -1, -+ .ibuf = { '\0' }, -+ .obuf = { '\0' }, -+ .pos = 0, -+ .esc = 0, -+ .dev = dev }); -+ -+ dev->init = NULL; -+ dev->hard_header_len = 0; -+ dev->addr_len = 4; -+ dev->type = ARPHRD_ETHER; -+ dev->tx_queue_len = 256; -+ dev->flags = IFF_NOARP; -+ printk("SLIRP backend - command line:"); -+ for(i=0;spri->argw.argv[i]!=NULL;i++) { -+ printk(" '%s'",spri->argw.argv[i]); -+ } -+ printk("\n"); -+} -+ -+static unsigned short slirp_protocol(struct sk_buff *skbuff) -+{ -+ return(htons(ETH_P_IP)); -+} -+ -+static int slirp_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, -+ (struct slirp_data *) &lp->user)); -+} -+ -+static int slirp_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slirp_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct slirp_data *) &lp->user)); -+} -+ -+struct net_kern_info slirp_kern_info = { -+ .init = slirp_init, -+ .protocol = slirp_protocol, -+ .read = slirp_read, -+ .write = slirp_write, -+}; -+ -+static int slirp_setup(char *str, char **mac_out, void *data) -+{ -+ struct slirp_init *init = data; -+ int i=0; -+ -+ *init = ((struct slirp_init) -+ { argw : { { "slirp", NULL } } }); -+ -+ str = split_if_spec(str, mac_out, NULL); -+ -+ if(str == NULL) { /* no command line given after MAC addr */ -+ return(1); -+ } -+ -+ do { -+ if(i>=SLIRP_MAX_ARGS-1) { -+ printk("slirp_setup: truncating slirp arguments\n"); -+ break; -+ } -+ init->argw.argv[i++] = str; -+ while(*str && *str!=',') { -+ if(*str=='_') *str=' '; -+ str++; -+ } -+ if(*str!=',') -+ break; -+ *str++='\0'; -+ } while(1); -+ init->argw.argv[i]=NULL; -+ return(1); -+} -+ -+static struct transport slirp_transport = { -+ .list = LIST_HEAD_INIT(slirp_transport.list), -+ .name = "slirp", -+ .setup = slirp_setup, -+ .user = &slirp_user_info, -+ .kern = &slirp_kern_info, -+ .private_size = sizeof(struct slirp_data), -+ .setup_size = sizeof(struct slirp_init), -+}; -+ -+static int register_slirp(void) -+{ -+ register_transport(&slirp_transport); -+ return(1); -+} -+ -+__initcall(register_slirp); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/slirp_user.c um/arch/um/drivers/slirp_user.c ---- orig/arch/um/drivers/slirp_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/slirp_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,201 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "net_user.h" -+#include "slirp.h" -+#include "slip_proto.h" -+#include "helper.h" -+#include "os.h" -+ -+void slirp_user_init(void *data, void *dev) -+{ -+ struct slirp_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+struct slirp_pre_exec_data { -+ int stdin; -+ int stdout; -+}; -+ -+static void slirp_pre_exec(void *arg) -+{ -+ struct slirp_pre_exec_data *data = arg; -+ -+ if(data->stdin != -1) dup2(data->stdin, 0); -+ if(data->stdout != -1) dup2(data->stdout, 1); -+} -+ -+static int slirp_tramp(char **argv, int fd) -+{ -+ struct slirp_pre_exec_data pe_data; -+ int pid; -+ -+ pe_data.stdin = fd; -+ pe_data.stdout = fd; -+ pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL); -+ -+ return(pid); -+} -+ -+/* XXX This is just a trivial wrapper around os_pipe */ -+static int slirp_datachan(int *mfd, int *sfd) -+{ -+ int fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err < 0){ -+ printk("slirp_datachan: Failed to open pipe, err = %d\n", -err); -+ return(err); -+ } -+ -+ *mfd = fds[0]; -+ *sfd = fds[1]; -+ return(0); -+} -+ -+static int slirp_open(void *data) -+{ -+ struct slirp_data *pri = data; -+ int sfd, mfd, pid, err; -+ -+ err = slirp_datachan(&mfd, &sfd); -+ if(err) -+ return(err); -+ -+ pid = slirp_tramp(pri->argw.argv, sfd); -+ -+ if(pid < 0){ -+ printk("slirp_tramp failed - errno = %d\n", -pid); -+ os_close_file(sfd); -+ os_close_file(mfd); -+ return(pid); -+ } -+ -+ pri->slave = sfd; -+ pri->pos = 0; -+ pri->esc = 0; -+ -+ pri->pid = pid; -+ -+ return(mfd); -+} -+ -+static void slirp_close(int fd, void *data) -+{ -+ struct slirp_data *pri = data; -+ int status,err; -+ -+ os_close_file(fd); -+ os_close_file(pri->slave); -+ -+ pri->slave = -1; -+ -+ if(pri->pid<1) { -+ printk("slirp_close: no child process to shut down\n"); -+ return; -+ } -+ -+#if 0 -+ if(kill(pri->pid, SIGHUP)<0) { -+ printk("slirp_close: sending hangup to %d failed (%d)\n", -+ pri->pid, errno); -+ } -+#endif -+ -+ err = waitpid(pri->pid, &status, WNOHANG); -+ if(err<0) { -+ printk("slirp_close: waitpid returned %d\n", errno); -+ return; -+ } -+ -+ if(err==0) { -+ printk("slirp_close: process %d has not exited\n"); -+ return; -+ } -+ -+ pri->pid = -1; -+} -+ -+int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) -+{ -+ int i, n, size, start; -+ -+ if(pri->more>0) { -+ i = 0; -+ while(i < pri->more) { -+ size = slip_unesc(pri->ibuf[i++], -+ pri->ibuf,&pri->pos,&pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); -+ pri->more=pri->more-i; -+ return(size); -+ } -+ } -+ pri->more=0; -+ } -+ -+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); -+ if(n <= 0) return(n); -+ -+ start = pri->pos; -+ for(i = 0; i < n; i++){ -+ size = slip_unesc(pri->ibuf[start + i], -+ pri->ibuf,&pri->pos,&pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); -+ pri->more=n-(i+1); -+ return(size); -+ } -+ } -+ return(0); -+} -+ -+int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) -+{ -+ int actual, n; -+ -+ actual = slip_esc(buf, pri->obuf, len); -+ n = net_write(fd, pri->obuf, actual); -+ if(n < 0) return(n); -+ else return(len); -+} -+ -+static int slirp_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info slirp_user_info = { -+ .init = slirp_user_init, -+ .open = slirp_open, -+ .close = slirp_close, -+ .remove = NULL, -+ .set_mtu = slirp_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = BUF_SIZE -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/ssl.c um/arch/um/drivers/ssl.c ---- orig/arch/um/drivers/ssl.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/ssl.c 2004-01-10 06:20:17.000000000 -0500 -@@ -0,0 +1,300 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/fs.h" -+#include "linux/tty.h" -+#include "linux/tty_driver.h" -+#include "linux/major.h" -+#include "linux/mm.h" -+#include "linux/init.h" -+#include "linux/console.h" -+#include "asm/termbits.h" -+#include "asm/irq.h" -+#include "line.h" -+#include "ssl.h" -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "mconsole_kern.h" -+#include "2_5compat.h" -+ -+static int ssl_version = 1; -+ -+/* Referenced only by tty_driver below - presumably it's locked correctly -+ * by the tty driver. -+ */ -+static int ssl_refcount = 0; -+ -+static struct tty_driver ssl_driver; -+ -+#define NR_PORTS 64 -+ -+void ssl_announce(char *dev_name, int dev) -+{ -+ printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev, -+ dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = ssl_announce, -+ .xterm_title = "Serial Line #%d", -+ .raw = 1, -+ .tramp_stack = 0, -+ .in_kernel = 1, -+}; -+ -+static int ssl_config(char *str); -+static int ssl_get_config(char *dev, char *str, int size, char **error_out); -+static int ssl_remove(char *str); -+ -+static struct line_driver driver = { -+ .name = "UML serial line", -+ .devfs_name = "tts/%d", -+ .major = TTY_MAJOR, -+ .minor_start = 64, -+ .type = TTY_DRIVER_TYPE_SERIAL, -+ .subtype = 0, -+ .read_irq = SSL_IRQ, -+ .read_irq_name = "ssl", -+ .write_irq = SSL_WRITE_IRQ, -+ .write_irq_name = "ssl-write", -+ .symlink_from = "serial", -+ .symlink_to = "tts", -+ .mc = { -+ .name = "ssl", -+ .config = ssl_config, -+ .get_config = ssl_get_config, -+ .remove = ssl_remove, -+ }, -+}; -+ -+/* The array is initialized by line_init, which is an initcall. The -+ * individual elements are protected by individual semaphores. -+ */ -+static struct line serial_lines[NR_PORTS] = -+ { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; -+ -+static struct lines lines = LINES_INIT(NR_PORTS); -+ -+static int ssl_config(char *str) -+{ -+ return(line_config(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), str)); -+} -+ -+static int ssl_get_config(char *dev, char *str, int size, char **error_out) -+{ -+ return(line_get_config(dev, serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), -+ str, size, error_out)); -+} -+ -+static int ssl_remove(char *str) -+{ -+ return(line_remove(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), str)); -+} -+ -+int ssl_open(struct tty_struct *tty, struct file *filp) -+{ -+ return(line_open(serial_lines, tty, &opts)); -+} -+ -+static void ssl_close(struct tty_struct *tty, struct file * filp) -+{ -+ line_close(serial_lines, tty); -+} -+ -+static int ssl_write(struct tty_struct * tty, int from_user, -+ const unsigned char *buf, int count) -+{ -+ return(line_write(serial_lines, tty, from_user, buf, count)); -+} -+ -+static void ssl_put_char(struct tty_struct *tty, unsigned char ch) -+{ -+ line_write(serial_lines, tty, 0, &ch, sizeof(ch)); -+} -+ -+static void ssl_flush_chars(struct tty_struct *tty) -+{ -+ return; -+} -+ -+static int ssl_chars_in_buffer(struct tty_struct *tty) -+{ -+ return(0); -+} -+ -+static void ssl_flush_buffer(struct tty_struct *tty) -+{ -+ return; -+} -+ -+static int ssl_ioctl(struct tty_struct *tty, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ -+ ret = 0; -+ switch(cmd){ -+ case TCGETS: -+ case TCSETS: -+ case TCFLSH: -+ case TCSETSF: -+ case TCSETSW: -+ case TCGETA: -+ case TIOCMGET: -+ case TCSBRK: -+ case TCSBRKP: -+ case TIOCMSET: -+ ret = -ENOIOCTLCMD; -+ break; -+ default: -+ printk(KERN_ERR -+ "Unimplemented ioctl in ssl_ioctl : 0x%x\n", cmd); -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return(ret); -+} -+ -+static void ssl_throttle(struct tty_struct * tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_throttle\n"); -+} -+ -+static void ssl_unthrottle(struct tty_struct * tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_unthrottle\n"); -+} -+ -+static void ssl_set_termios(struct tty_struct *tty, -+ struct termios *old_termios) -+{ -+} -+ -+static void ssl_stop(struct tty_struct *tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_stop\n"); -+} -+ -+static void ssl_start(struct tty_struct *tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_start\n"); -+} -+ -+void ssl_hangup(struct tty_struct *tty) -+{ -+} -+ -+static struct tty_driver ssl_driver = { -+ .refcount = &ssl_refcount, -+ .open = ssl_open, -+ .close = ssl_close, -+ .write = ssl_write, -+ .put_char = ssl_put_char, -+ .flush_chars = ssl_flush_chars, -+ .chars_in_buffer = ssl_chars_in_buffer, -+ .flush_buffer = ssl_flush_buffer, -+ .ioctl = ssl_ioctl, -+ .throttle = ssl_throttle, -+ .unthrottle = ssl_unthrottle, -+ .set_termios = ssl_set_termios, -+ .stop = ssl_stop, -+ .start = ssl_start, -+ .hangup = ssl_hangup -+}; -+ -+/* Changed by ssl_init and referenced by ssl_exit, which are both serialized -+ * by being an initcall and exitcall, respectively. -+ */ -+static int ssl_init_done = 0; -+ -+static void ssl_console_write(struct console *c, const char *string, -+ unsigned len) -+{ -+ struct line *line = &serial_lines[c->index]; -+ if(ssl_init_done) -+ down(&line->sem); -+ console_write_chan(&line->chan_list, string, len); -+ if(ssl_init_done) -+ up(&line->sem); -+} -+ -+static kdev_t ssl_console_device(struct console *c) -+{ -+ return mk_kdev(TTY_MAJOR, c->index); -+} -+ -+static int ssl_console_setup(struct console *co, char *options) -+{ -+ return(0); -+} -+ -+static struct console ssl_cons = { -+ name: "ttyS", -+ write: ssl_console_write, -+ device: ssl_console_device, -+ setup: ssl_console_setup, -+ flags: CON_PRINTBUFFER, -+ index: -1, -+}; -+ -+int ssl_init(void) -+{ -+ char *new_title; -+ -+ printk(KERN_INFO "Initializing software serial port version %d\n", -+ ssl_version); -+ -+ line_register_devfs(&lines, &driver, &ssl_driver, serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0])); -+ -+ lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); -+ -+ new_title = add_xterm_umid(opts.xterm_title); -+ if(new_title != NULL) opts.xterm_title = new_title; -+ -+ register_console(&ssl_cons); -+ ssl_init_done = 1; -+ return(0); -+} -+ -+__initcall(ssl_init); -+ -+static int ssl_chan_setup(char *str) -+{ -+ return(line_setup(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), -+ str, 1)); -+} -+ -+__setup("ssl", ssl_chan_setup); -+__channel_help(ssl_chan_setup, "ssl"); -+ -+static void ssl_exit(void) -+{ -+ if(!ssl_init_done) return; -+ close_lines(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0])); -+} -+ -+__uml_exitcall(ssl_exit); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/ssl.h um/arch/um/drivers/ssl.h ---- orig/arch/um/drivers/ssl.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/ssl.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SSL_H__ -+#define __SSL_H__ -+ -+extern int ssl_read(int fd, int line); -+extern void ssl_receive_char(int line, char ch); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/stdio_console.c um/arch/um/drivers/stdio_console.c ---- orig/arch/um/drivers/stdio_console.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/stdio_console.c 2003-11-07 03:03:03.000000000 -0500 -@@ -0,0 +1,258 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/posix_types.h" -+#include "linux/tty.h" -+#include "linux/tty_flip.h" -+#include "linux/types.h" -+#include "linux/major.h" -+#include "linux/kdev_t.h" -+#include "linux/console.h" -+#include "linux/string.h" -+#include "linux/sched.h" -+#include "linux/list.h" -+#include "linux/init.h" -+#include "linux/interrupt.h" -+#include "linux/slab.h" -+#include "asm/current.h" -+#include "asm/softirq.h" -+#include "asm/hardirq.h" -+#include "asm/irq.h" -+#include "stdio_console.h" -+#include "line.h" -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "2_5compat.h" -+ -+#define MAX_TTYS (8) -+ -+/* Referenced only by tty_driver below - presumably it's locked correctly -+ * by the tty driver. -+ */ -+ -+static struct tty_driver console_driver; -+ -+static int console_refcount = 0; -+ -+static struct chan_ops init_console_ops = { -+ .type = "you shouldn't see this", -+ .init = NULL, -+ .open = NULL, -+ .close = NULL, -+ .read = NULL, -+ .write = NULL, -+ .console_write = generic_write, -+ .window_size = NULL, -+ .free = NULL, -+ .winch = 0, -+}; -+ -+static struct chan init_console_chan = { -+ .list = { }, -+ .primary = 1, -+ .input = 0, -+ .output = 1, -+ .opened = 1, -+ .fd = 1, -+ .pri = INIT_STATIC, -+ .ops = &init_console_ops, -+ .data = NULL -+}; -+ -+void stdio_announce(char *dev_name, int dev) -+{ -+ printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, -+ dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = stdio_announce, -+ .xterm_title = "Virtual Console #%d", -+ .raw = 1, -+ .tramp_stack = 0, -+ .in_kernel = 1, -+}; -+ -+static int con_config(char *str); -+static int con_get_config(char *dev, char *str, int size, char **error_out); -+static int con_remove(char *str); -+ -+static struct line_driver driver = { -+ .name = "UML console", -+ .devfs_name = "vc/%d", -+ .major = TTY_MAJOR, -+ .minor_start = 0, -+ .type = TTY_DRIVER_TYPE_CONSOLE, -+ .subtype = SYSTEM_TYPE_CONSOLE, -+ .read_irq = CONSOLE_IRQ, -+ .read_irq_name = "console", -+ .write_irq = CONSOLE_WRITE_IRQ, -+ .write_irq_name = "console-write", -+ .symlink_from = "ttys", -+ .symlink_to = "vc", -+ .mc = { -+ .name = "con", -+ .config = con_config, -+ .get_config = con_get_config, -+ .remove = con_remove, -+ }, -+}; -+ -+static struct lines console_lines = LINES_INIT(MAX_TTYS); -+ -+/* The array is initialized by line_init, which is an initcall. The -+ * individual elements are protected by individual semaphores. -+ */ -+struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), -+ [ 1 ... MAX_TTYS - 1 ] = -+ LINE_INIT(CONFIG_CON_CHAN, &driver) }; -+ -+static int con_config(char *str) -+{ -+ return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); -+} -+ -+static int con_get_config(char *dev, char *str, int size, char **error_out) -+{ -+ return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, -+ size, error_out)); -+} -+ -+static int con_remove(char *str) -+{ -+ return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str)); -+} -+ -+static int open_console(struct tty_struct *tty) -+{ -+ return(line_open(vts, tty, &opts)); -+} -+ -+static int con_open(struct tty_struct *tty, struct file *filp) -+{ -+ return(open_console(tty)); -+} -+ -+static void con_close(struct tty_struct *tty, struct file *filp) -+{ -+ line_close(vts, tty); -+} -+ -+static int con_write(struct tty_struct *tty, int from_user, -+ const unsigned char *buf, int count) -+{ -+ return(line_write(vts, tty, from_user, buf, count)); -+} -+ -+static void set_termios(struct tty_struct *tty, struct termios * old) -+{ -+} -+ -+static int chars_in_buffer(struct tty_struct *tty) -+{ -+ return(0); -+} -+ -+static int con_init_done = 0; -+ -+int stdio_init(void) -+{ -+ char *new_title; -+ -+ printk(KERN_INFO "Initializing stdio console driver\n"); -+ -+ line_register_devfs(&console_lines, &driver, &console_driver, vts, -+ sizeof(vts)/sizeof(vts[0])); -+ -+ lines_init(vts, sizeof(vts)/sizeof(vts[0])); -+ -+ new_title = add_xterm_umid(opts.xterm_title); -+ if(new_title != NULL) opts.xterm_title = new_title; -+ -+ open_console(NULL); -+ con_init_done = 1; -+ return(0); -+} -+ -+__initcall(stdio_init); -+ -+static void console_write(struct console *console, const char *string, -+ unsigned len) -+{ -+ struct line *line = &vts[console->index]; -+ -+ if(con_init_done) -+ down(&line->sem); -+ console_write_chan(&line->chan_list, string, len); -+ if(con_init_done) -+ up(&line->sem); -+} -+ -+static struct tty_driver console_driver = { -+ .refcount = &console_refcount, -+ .open = con_open, -+ .close = con_close, -+ .write = con_write, -+ .chars_in_buffer = chars_in_buffer, -+ .set_termios = set_termios -+}; -+ -+static kdev_t console_device(struct console *c) -+{ -+ return mk_kdev(TTY_MAJOR, c->index); -+} -+ -+static int console_setup(struct console *co, char *options) -+{ -+ return(0); -+} -+ -+static struct console stdiocons = { -+ name: "tty", -+ write: console_write, -+ device: console_device, -+ setup: console_setup, -+ flags: CON_PRINTBUFFER, -+ index: -1, -+}; -+ -+void stdio_console_init(void) -+{ -+ INIT_LIST_HEAD(&vts[0].chan_list); -+ list_add(&init_console_chan.list, &vts[0].chan_list); -+ register_console(&stdiocons); -+} -+ -+static int console_chan_setup(char *str) -+{ -+ return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); -+} -+ -+__setup("con", console_chan_setup); -+__channel_help(console_chan_setup, "con"); -+ -+static void console_exit(void) -+{ -+ if(!con_init_done) return; -+ close_lines(vts, sizeof(vts)/sizeof(vts[0])); -+} -+ -+__uml_exitcall(console_exit); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/stdio_console.h um/arch/um/drivers/stdio_console.h ---- orig/arch/um/drivers/stdio_console.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/stdio_console.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __STDIO_CONSOLE_H -+#define __STDIO_CONSOLE_H -+ -+extern void save_console_flags(void); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/tty.c um/arch/um/drivers/tty.c ---- orig/arch/um/drivers/tty.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/tty.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include "chan_user.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+struct tty_chan { -+ char *dev; -+ int raw; -+ struct termios tt; -+}; -+ -+void *tty_chan_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct tty_chan *data; -+ -+ if(*str != ':'){ -+ printk("tty_init : channel type 'tty' must specify " -+ "a device\n"); -+ return(NULL); -+ } -+ str++; -+ -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) -+ return(NULL); -+ *data = ((struct tty_chan) { .dev = str, -+ .raw = opts->raw }); -+ -+ return(data); -+} -+ -+int tty_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct tty_chan *data = d; -+ int fd; -+ -+ fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); -+ if(fd < 0) return(fd); -+ if(data->raw){ -+ tcgetattr(fd, &data->tt); -+ raw(fd, 0); -+ } -+ -+ *dev_out = data->dev; -+ return(fd); -+} -+ -+int tty_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct tty_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops tty_ops = { -+ .type = "tty", -+ .init = tty_chan_init, -+ .open = tty_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = tty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/ubd_kern.c um/arch/um/drivers/ubd_kern.c ---- orig/arch/um/drivers/ubd_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/ubd_kern.c 2004-01-21 01:28:43.000000000 -0500 -@@ -0,0 +1,1396 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+/* 2001-09-28...2002-04-17 -+ * Partition stuff by James_McMechan@hotmail.com -+ * old style ubd by setting UBD_SHIFT to 0 -+ */ -+ -+#define MAJOR_NR UBD_MAJOR -+#define UBD_SHIFT 4 -+ -+#include "linux/config.h" -+#include "linux/blk.h" -+#include "linux/blkdev.h" -+#include "linux/hdreg.h" -+#include "linux/init.h" -+#include "linux/devfs_fs_kernel.h" -+#include "linux/cdrom.h" -+#include "linux/proc_fs.h" -+#include "linux/ctype.h" -+#include "linux/capability.h" -+#include "linux/mm.h" -+#include "linux/vmalloc.h" -+#include "linux/blkpg.h" -+#include "linux/genhd.h" -+#include "linux/spinlock.h" -+#include "asm/segment.h" -+#include "asm/uaccess.h" -+#include "asm/irq.h" -+#include "asm/types.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "ubd_user.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "mem.h" -+#include "mem_kern.h" -+ -+static int ubd_open(struct inode * inode, struct file * filp); -+static int ubd_release(struct inode * inode, struct file * file); -+static int ubd_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg); -+static int ubd_revalidate(kdev_t rdev); -+static int ubd_revalidate1(kdev_t rdev); -+ -+#define MAX_DEV (8) -+#define MAX_MINOR (MAX_DEV << UBD_SHIFT) -+ -+/* Changed in early boot */ -+static int ubd_do_mmap = 0; -+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE -+ -+/* Not modified by this driver */ -+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE }; -+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 }; -+ -+/* Protected by ubd_lock */ -+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 }; -+ -+static struct block_device_operations ubd_blops = { -+ .open = ubd_open, -+ .release = ubd_release, -+ .ioctl = ubd_ioctl, -+ .revalidate = ubd_revalidate, -+}; -+ -+/* Protected by ubd_lock, except in prepare_request and ubd_ioctl because -+ * the block layer should ensure that the device is idle before closing it. -+ */ -+static struct hd_struct ubd_part[MAX_MINOR] = -+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } }; -+ -+/* Protected by io_request_lock */ -+static request_queue_t *ubd_queue; -+ -+/* Protected by ubd_lock */ -+static int fake_major = MAJOR_NR; -+ -+static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED; -+ -+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \ -+{ \ -+ .major = maj, \ -+ .major_name = name, \ -+ .minor_shift = shift, \ -+ .max_p = 1 << shift, \ -+ .part = parts, \ -+ .sizes = bsizes, \ -+ .nr_real = max, \ -+ .real_devices = NULL, \ -+ .next = NULL, \ -+ .fops = blops, \ -+ .de_arr = NULL, \ -+ .flags = 0 \ -+} -+ -+static struct gendisk ubd_gendisk = INIT_GENDISK(MAJOR_NR, "ubd", ubd_part, -+ UBD_SHIFT, sizes, MAX_DEV, -+ &ubd_blops); -+static struct gendisk fake_gendisk = INIT_GENDISK(0, "ubd", ubd_part, -+ UBD_SHIFT, sizes, MAX_DEV, -+ &ubd_blops); -+ -+#ifdef CONFIG_BLK_DEV_UBD_SYNC -+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \ -+ .cl = 1 }) -+#else -+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \ -+ .cl = 1 }) -+#endif -+ -+/* Not protected - changed only in ubd_setup_common and then only to -+ * to enable O_SYNC. -+ */ -+static struct openflags global_openflags = OPEN_FLAGS; -+ -+struct cow { -+ char *file; -+ int fd; -+ unsigned long *bitmap; -+ unsigned long bitmap_len; -+ int bitmap_offset; -+ int data_offset; -+}; -+ -+struct ubd { -+ char *file; -+ int count; -+ int fd; -+ __u64 size; -+ struct openflags boot_openflags; -+ struct openflags openflags; -+ devfs_handle_t devfs; -+ int no_cow; -+ struct cow cow; -+ -+ int map_writes; -+ int map_reads; -+ int nomap_writes; -+ int nomap_reads; -+ int write_maps; -+}; -+ -+#define DEFAULT_COW { \ -+ .file = NULL, \ -+ .fd = -1, \ -+ .bitmap = NULL, \ -+ .bitmap_offset = 0, \ -+ .data_offset = 0, \ -+} -+ -+#define DEFAULT_UBD { \ -+ .file = NULL, \ -+ .count = 0, \ -+ .fd = -1, \ -+ .size = -1, \ -+ .boot_openflags = OPEN_FLAGS, \ -+ .openflags = OPEN_FLAGS, \ -+ .devfs = NULL, \ -+ .no_cow = 0, \ -+ .cow = DEFAULT_COW, \ -+ .map_writes = 0, \ -+ .map_reads = 0, \ -+ .nomap_writes = 0, \ -+ .nomap_reads = 0, \ -+ .write_maps = 0, \ -+} -+ -+struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; -+ -+static int ubd0_init(void) -+{ -+ struct ubd *dev = &ubd_dev[0]; -+ -+ if(dev->file == NULL) -+ dev->file = "root_fs"; -+ return(0); -+} -+ -+__initcall(ubd0_init); -+ -+/* Only changed by fake_ide_setup which is a setup */ -+static int fake_ide = 0; -+static struct proc_dir_entry *proc_ide_root = NULL; -+static struct proc_dir_entry *proc_ide = NULL; -+ -+static void make_proc_ide(void) -+{ -+ proc_ide_root = proc_mkdir("ide", 0); -+ proc_ide = proc_mkdir("ide0", proc_ide_root); -+} -+ -+static int proc_ide_read_media(char *page, char **start, off_t off, int count, -+ int *eof, void *data) -+{ -+ int len; -+ -+ strcpy(page, "disk\n"); -+ len = strlen("disk\n"); -+ len -= off; -+ if (len < count){ -+ *eof = 1; -+ if (len <= 0) return 0; -+ } -+ else len = count; -+ *start = page + off; -+ return len; -+} -+ -+static void make_ide_entries(char *dev_name) -+{ -+ struct proc_dir_entry *dir, *ent; -+ char name[64]; -+ -+ if(!fake_ide) return; -+ -+ /* Without locking this could race if a UML was booted with no -+ * disks and then two mconsole requests which add disks came in -+ * at the same time. -+ */ -+ spin_lock(&ubd_lock); -+ if(proc_ide_root == NULL) make_proc_ide(); -+ spin_unlock(&ubd_lock); -+ -+ dir = proc_mkdir(dev_name, proc_ide); -+ if(!dir) return; -+ -+ ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); -+ if(!ent) return; -+ ent->nlink = 1; -+ ent->data = NULL; -+ ent->read_proc = proc_ide_read_media; -+ ent->write_proc = NULL; -+ sprintf(name,"ide0/%s", dev_name); -+ proc_symlink(dev_name, proc_ide_root, name); -+} -+ -+static int fake_ide_setup(char *str) -+{ -+ fake_ide = 1; -+ return(1); -+} -+ -+__setup("fake_ide", fake_ide_setup); -+ -+__uml_help(fake_ide_setup, -+"fake_ide\n" -+" Create ide0 entries that map onto ubd devices.\n\n" -+); -+ -+static int parse_unit(char **ptr) -+{ -+ char *str = *ptr, *end; -+ int n = -1; -+ -+ if(isdigit(*str)) { -+ n = simple_strtoul(str, &end, 0); -+ if(end == str) -+ return(-1); -+ *ptr = end; -+ } -+ else if (('a' <= *str) && (*str <= 'h')) { -+ n = *str - 'a'; -+ str++; -+ *ptr = str; -+ } -+ return(n); -+} -+ -+static int ubd_setup_common(char *str, int *index_out) -+{ -+ struct openflags flags = global_openflags; -+ struct ubd *dev; -+ char *backing_file; -+ int n, err; -+ -+ if(index_out) *index_out = -1; -+ n = *str; -+ if(n == '='){ -+ char *end; -+ int major; -+ -+ str++; -+ if(!strcmp(str, "mmap")){ -+ CHOOSE_MODE(printk("mmap not supported by the ubd " -+ "driver in tt mode\n"), -+ ubd_do_mmap = 1); -+ return(0); -+ } -+ -+ if(!strcmp(str, "sync")){ -+ global_openflags.s = 1; -+ return(0); -+ } -+ major = simple_strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk(KERN_ERR -+ "ubd_setup : didn't parse major number\n"); -+ return(1); -+ } -+ -+ err = 1; -+ spin_lock(&ubd_lock); -+ if(fake_major != MAJOR_NR){ -+ printk(KERN_ERR "Can't assign a fake major twice\n"); -+ goto out1; -+ } -+ -+ fake_gendisk.major = major; -+ fake_major = major; -+ -+ printk(KERN_INFO "Setting extra ubd major number to %d\n", -+ major); -+ err = 0; -+ out1: -+ spin_unlock(&ubd_lock); -+ return(err); -+ } -+ -+ n = parse_unit(&str); -+ if(n < 0){ -+ printk(KERN_ERR "ubd_setup : couldn't parse unit number " -+ "'%s'\n", str); -+ return(1); -+ } -+ -+ if(n >= MAX_DEV){ -+ printk(KERN_ERR "ubd_setup : index %d out of range " -+ "(%d devices)\n", n, MAX_DEV); -+ return(1); -+ } -+ -+ err = 1; -+ spin_lock(&ubd_lock); -+ -+ dev = &ubd_dev[n]; -+ if(dev->file != NULL){ -+ printk(KERN_ERR "ubd_setup : device already configured\n"); -+ goto out2; -+ } -+ -+ if(index_out) *index_out = n; -+ -+ if(*str == 'r'){ -+ flags.w = 0; -+ str++; -+ } -+ if(*str == 's'){ -+ flags.s = 1; -+ str++; -+ } -+ if(*str == 'd'){ -+ dev->no_cow = 1; -+ str++; -+ } -+ -+ if(*str++ != '='){ -+ printk(KERN_ERR "ubd_setup : Expected '='\n"); -+ goto out2; -+ } -+ -+ err = 0; -+ backing_file = strchr(str, ','); -+ if(backing_file){ -+ if(dev->no_cow) -+ printk(KERN_ERR "Can't specify both 'd' and a " -+ "cow file\n"); -+ else { -+ *backing_file = '\0'; -+ backing_file++; -+ } -+ } -+ dev->file = str; -+ dev->cow.file = backing_file; -+ dev->boot_openflags = flags; -+ out2: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_setup(char *str) -+{ -+ ubd_setup_common(str, NULL); -+ return(1); -+} -+ -+__setup("ubd", ubd_setup); -+__uml_help(ubd_setup, -+"ubd=\n" -+" This is used to associate a device with a file in the underlying\n" -+" filesystem. Usually, there is a filesystem in the file, but \n" -+" that's not required. Swap devices containing swap files can be\n" -+" specified like this. Also, a file which doesn't contain a\n" -+" filesystem can have its contents read in the virtual \n" -+" machine by running dd on the device. n must be in the range\n" -+" 0 to 7. Appending an 'r' to the number will cause that device\n" -+" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n" -+" an 's' (has to be _after_ 'r', if there is one) will cause data\n" -+" to be written to disk on the host immediately.\n\n" -+); -+ -+static int fakehd(char *str) -+{ -+ printk(KERN_INFO -+ "fakehd : Changing ubd_gendisk.major_name to \"hd\".\n"); -+ ubd_gendisk.major_name = "hd"; -+ return(1); -+} -+ -+__setup("fakehd", fakehd); -+__uml_help(fakehd, -+"fakehd\n" -+" Change the ubd device name to \"hd\".\n\n" -+); -+ -+static void do_ubd_request(request_queue_t * q); -+ -+/* Only changed by ubd_init, which is an initcall. */ -+int thread_fd = -1; -+ -+/* Changed by ubd_handler, which is serialized because interrupts only -+ * happen on CPU 0. -+ */ -+int intr_count = 0; -+ -+static void ubd_finish(int error) -+{ -+ int nsect; -+ -+ if(error){ -+ end_request(0); -+ return; -+ } -+ nsect = CURRENT->current_nr_sectors; -+ CURRENT->sector += nsect; -+ CURRENT->buffer += nsect << 9; -+ CURRENT->errors = 0; -+ CURRENT->nr_sectors -= nsect; -+ CURRENT->current_nr_sectors = 0; -+ end_request(1); -+} -+ -+static void ubd_handler(void) -+{ -+ struct io_thread_req req; -+ int n, err; -+ -+ DEVICE_INTR = NULL; -+ intr_count++; -+ n = read_ubd_fs(thread_fd, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " -+ "err = %d\n", os_getpid(), -n); -+ spin_lock(&io_request_lock); -+ end_request(0); -+ spin_unlock(&io_request_lock); -+ return; -+ } -+ -+ if((req.op != UBD_MMAP) && -+ ((req.offset != ((__u64) (CURRENT->sector)) << 9) || -+ (req.length != (CURRENT->current_nr_sectors) << 9))) -+ panic("I/O op mismatch"); -+ -+ if(req.map_fd != -1){ -+ err = physmem_subst_mapping(req.buffer, req.map_fd, -+ req.map_offset, 1); -+ if(err) -+ printk("ubd_handler - physmem_subst_mapping failed, " -+ "err = %d\n", -err); -+ } -+ -+ spin_lock(&io_request_lock); -+ ubd_finish(req.error); -+ reactivate_fd(thread_fd, UBD_IRQ); -+ do_ubd_request(ubd_queue); -+ spin_unlock(&io_request_lock); -+} -+ -+static void ubd_intr(int irq, void *dev, struct pt_regs *unused) -+{ -+ ubd_handler(); -+} -+ -+/* Only changed by ubd_init, which is an initcall. */ -+static int io_pid = -1; -+ -+void kill_io_thread(void) -+{ -+ if(io_pid != -1) -+ os_kill_process(io_pid, 1); -+} -+ -+__uml_exitcall(kill_io_thread); -+ -+/* Initialized in an initcall, and unchanged thereafter */ -+devfs_handle_t ubd_dir_handle; -+ -+static int ubd_add(int n) -+{ -+ struct ubd *dev = &ubd_dev[n]; -+ char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")]; -+ int err = -EISDIR; -+ -+ if(dev->file == NULL) -+ goto out; -+ -+ err = ubd_revalidate1(MKDEV(MAJOR_NR, n << UBD_SHIFT)); -+ if(err) -+ goto out; -+ -+ if(dev->cow.file == NULL) -+ blk_sizes[n] = UBD_MMAP_BLOCK_SIZE; -+ -+ sprintf(name, "%d", n); -+ dev->devfs = devfs_register(ubd_dir_handle, name, DEVFS_FL_REMOVABLE, -+ MAJOR_NR, n << UBD_SHIFT, S_IFBLK | -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, -+ &ubd_blops, NULL); -+ -+#if 0 /* 2.5 ... */ -+ sprintf(disk->disk_name, "ubd%c", 'a' + unit); -+#endif -+ -+ sprintf(dev_name, "%s%c", ubd_gendisk.major_name, -+ n + 'a'); -+ -+ make_ide_entries(dev_name); -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+static int ubd_config(char *str) -+{ -+ int n, err; -+ -+ str = uml_strdup(str); -+ if(str == NULL){ -+ printk(KERN_ERR "ubd_config failed to strdup string\n"); -+ return(1); -+ } -+ err = ubd_setup_common(str, &n); -+ if(err){ -+ kfree(str); -+ return(-1); -+ } -+ if(n == -1) return(0); -+ -+ spin_lock(&ubd_lock); -+ err = ubd_add(n); -+ if(err) -+ ubd_dev[n].file = NULL; -+ spin_unlock(&ubd_lock); -+ -+ return(err); -+} -+ -+static int ubd_get_config(char *name, char *str, int size, char **error_out) -+{ -+ struct ubd *dev; -+ char *end; -+ int n, len = 0; -+ -+ n = simple_strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ *error_out = "ubd_get_config : didn't parse device number"; -+ return(-1); -+ } -+ -+ if((n >= MAX_DEV) || (n < 0)){ -+ *error_out = "ubd_get_config : device number out of range"; -+ return(-1); -+ } -+ -+ dev = &ubd_dev[n]; -+ spin_lock(&ubd_lock); -+ -+ if(dev->file == NULL){ -+ CONFIG_CHUNK(str, size, len, "", 1); -+ goto out; -+ } -+ -+ CONFIG_CHUNK(str, size, len, dev->file, 0); -+ -+ if(dev->cow.file != NULL){ -+ CONFIG_CHUNK(str, size, len, ",", 0); -+ CONFIG_CHUNK(str, size, len, dev->cow.file, 1); -+ } -+ else CONFIG_CHUNK(str, size, len, "", 1); -+ -+ out: -+ spin_unlock(&ubd_lock); -+ return(len); -+} -+ -+static int ubd_remove(char *str) -+{ -+ struct ubd *dev; -+ int n, err = -ENODEV; -+ -+ if(isdigit(*str)){ -+ char *end; -+ n = simple_strtoul(str, &end, 0); -+ if ((*end != '\0') || (end == str)) -+ return(err); -+ } -+ else if (('a' <= *str) && (*str <= 'h')) -+ n = *str - 'a'; -+ else -+ return(err); /* it should be a number 0-7/a-h */ -+ -+ if((n < 0) || (n >= MAX_DEV)) -+ return(err); -+ -+ dev = &ubd_dev[n]; -+ -+ spin_lock(&ubd_lock); -+ err = 0; -+ if(dev->file == NULL) -+ goto out; -+ err = -1; -+ if(dev->count > 0) -+ goto out; -+ if(dev->devfs != NULL) -+ devfs_unregister(dev->devfs); -+ -+ *dev = ((struct ubd) DEFAULT_UBD); -+ err = 0; -+ out: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static struct mc_device ubd_mc = { -+ .name = "ubd", -+ .config = ubd_config, -+ .get_config = ubd_get_config, -+ .remove = ubd_remove, -+}; -+ -+static int ubd_mc_init(void) -+{ -+ mconsole_register_dev(&ubd_mc); -+ return(0); -+} -+ -+__initcall(ubd_mc_init); -+ -+static request_queue_t *ubd_get_queue(kdev_t device) -+{ -+ return(ubd_queue); -+} -+ -+int ubd_init(void) -+{ -+ unsigned long stack; -+ int i, err; -+ -+ ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); -+ if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) { -+ printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR); -+ return -1; -+ } -+ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[MAJOR_NR] = blk_sizes; -+ blk_size[MAJOR_NR] = sizes; -+ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes); -+ -+ ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); -+ blk_init_queue(ubd_queue, DEVICE_REQUEST); -+ INIT_ELV(ubd_queue, &ubd_queue->elevator); -+ -+ add_gendisk(&ubd_gendisk); -+ if (fake_major != MAJOR_NR){ -+ /* major number 0 is used to auto select */ -+ err = devfs_register_blkdev(fake_major, "fake", &ubd_blops); -+ if(fake_major == 0){ -+ /* auto device number case */ -+ fake_major = err; -+ if(err == 0) -+ return(-ENODEV); -+ } -+ else if (err){ -+ /* not auto so normal error */ -+ printk(KERN_ERR "ubd: error %d getting major %d\n", -+ -err, fake_major); -+ return(-ENODEV); -+ } -+ -+ blk_dev[fake_major].queue = ubd_get_queue; -+ read_ahead[fake_major] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[fake_major] = blk_sizes; -+ blk_size[fake_major] = sizes; -+ INIT_HARDSECT(hardsect_size, fake_major, hardsect_sizes); -+ add_gendisk(&fake_gendisk); -+ } -+ -+ for(i=0;ifd); -+ os_close_file(dev->fd); -+ if(dev->cow.file != NULL) -+ return; -+ -+ if(ubd_do_mmap) -+ physmem_forget_descriptor(dev->cow.fd); -+ os_close_file(dev->cow.fd); -+ vfree(dev->cow.bitmap); -+ dev->cow.bitmap = NULL; -+} -+ -+static int ubd_open_dev(struct ubd *dev) -+{ -+ struct openflags flags; -+ char **back_ptr; -+ int err, create_cow, *create_ptr; -+ -+ dev->openflags = dev->boot_openflags; -+ create_cow = 0; -+ create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; -+ back_ptr = dev->no_cow ? NULL : &dev->cow.file; -+ dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr, -+ &dev->cow.bitmap_offset, &dev->cow.bitmap_len, -+ &dev->cow.data_offset, create_ptr); -+ -+ if((dev->fd == -ENOENT) && create_cow){ -+ dev->fd = create_cow_file(dev->file, dev->cow.file, -+ dev->openflags, 1 << 9, PAGE_SIZE, -+ &dev->cow.bitmap_offset, -+ &dev->cow.bitmap_len, -+ &dev->cow.data_offset); -+ if(dev->fd >= 0){ -+ printk(KERN_INFO "Creating \"%s\" as COW file for " -+ "\"%s\"\n", dev->file, dev->cow.file); -+ } -+ } -+ -+ if(dev->fd < 0) return(dev->fd); -+ -+ if(dev->cow.file != NULL){ -+ err = -ENOMEM; -+ dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); -+ if(dev->cow.bitmap == NULL){ -+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); -+ goto error; -+ } -+ flush_tlb_kernel_vm(); -+ -+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap, -+ dev->cow.bitmap_offset, -+ dev->cow.bitmap_len); -+ if(err < 0) -+ goto error; -+ -+ flags = dev->openflags; -+ flags.w = 0; -+ err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, -+ NULL, NULL); -+ if(err < 0) goto error; -+ dev->cow.fd = err; -+ } -+ return(0); -+ error: -+ os_close_file(dev->fd); -+ return(err); -+} -+ -+static int ubd_file_size(struct ubd *dev, __u64 *size_out) -+{ -+ char *file; -+ -+ file = dev->cow.file ? dev->cow.file : dev->file; -+ return(os_file_size(file, size_out)); -+} -+ -+static int ubd_open(struct inode *inode, struct file *filp) -+{ -+ struct ubd *dev; -+ int n, offset, err = 0; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ dev = &ubd_dev[n]; -+ if(n >= MAX_DEV) -+ return -ENODEV; -+ -+ spin_lock(&ubd_lock); -+ offset = n << UBD_SHIFT; -+ -+ if(dev->count == 0){ -+ err = ubd_open_dev(dev); -+ if(err){ -+ printk(KERN_ERR "ubd%d: Can't open \"%s\": " -+ "errno = %d\n", n, dev->file, -err); -+ goto out; -+ } -+ err = ubd_file_size(dev, &dev->size); -+ if(err < 0) -+ goto out; -+ sizes[offset] = dev->size / BLOCK_SIZE; -+ ubd_part[offset].nr_sects = dev->size / hardsect_sizes[offset]; -+ } -+ dev->count++; -+ if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ -+ if(--dev->count == 0) ubd_close(dev); -+ err = -EROFS; -+ } -+ out: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_release(struct inode * inode, struct file * file) -+{ -+ int n, offset; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ offset = n << UBD_SHIFT; -+ if(n >= MAX_DEV) -+ return -ENODEV; -+ -+ spin_lock(&ubd_lock); -+ if(--ubd_dev[n].count == 0) -+ ubd_close(&ubd_dev[n]); -+ spin_unlock(&ubd_lock); -+ -+ return(0); -+} -+ -+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, -+ __u64 *cow_offset, unsigned long *bitmap, -+ __u64 bitmap_offset, unsigned long *bitmap_words, -+ __u64 bitmap_len) -+{ -+ __u64 sector = io_offset >> 9; -+ int i, update_bitmap = 0; -+ -+ for(i = 0; i < length >> 9; i++){ -+ if(cow_mask != NULL) -+ ubd_set_bit(i, (unsigned char *) cow_mask); -+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) -+ continue; -+ -+ update_bitmap = 1; -+ ubd_set_bit(sector + i, (unsigned char *) bitmap); -+ } -+ -+ if(!update_bitmap) -+ return; -+ -+ *cow_offset = sector / (sizeof(unsigned long) * 8); -+ -+ /* This takes care of the case where we're exactly at the end of the -+ * device, and *cow_offset + 1 is off the end. So, just back it up -+ * by one word. Thanks to Lynn Kerby for the fix and James McMechan -+ * for the original diagnosis. -+ */ -+ if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / -+ sizeof(unsigned long) - 1)) -+ (*cow_offset)--; -+ -+ bitmap_words[0] = bitmap[*cow_offset]; -+ bitmap_words[1] = bitmap[*cow_offset + 1]; -+ -+ *cow_offset *= sizeof(unsigned long); -+ *cow_offset += bitmap_offset; -+} -+ -+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, -+ __u64 bitmap_offset, __u64 bitmap_len) -+{ -+ __u64 sector = req->offset >> 9; -+ int i; -+ -+ if(req->length > (sizeof(req->sector_mask) * 8) << 9) -+ panic("Operation too long"); -+ -+ if(req->op == UBD_READ) { -+ for(i = 0; i < req->length >> 9; i++){ -+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap)){ -+ ubd_set_bit(i, (unsigned char *) -+ &req->sector_mask); -+ } -+ } -+ } -+ else cowify_bitmap(req->offset, req->length, &req->sector_mask, -+ &req->cow_offset, bitmap, bitmap_offset, -+ req->bitmap_words, bitmap_len); -+} -+ -+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset) -+{ -+ __u64 sector; -+ unsigned char *bitmap; -+ int bit, i; -+ -+ /* mmap must have been requested on the command line */ -+ if(!ubd_do_mmap) -+ return(-1); -+ -+ /* The buffer must be page aligned */ -+ if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0) -+ return(-1); -+ -+ /* The request must be a page long */ -+ if((req->current_nr_sectors << 9) != PAGE_SIZE) -+ return(-1); -+ -+ if(dev->cow.file == NULL) -+ return(dev->fd); -+ -+ sector = offset >> 9; -+ bitmap = (unsigned char *) dev->cow.bitmap; -+ bit = ubd_test_bit(sector, bitmap); -+ -+ for(i = 1; i < req->current_nr_sectors; i++){ -+ if(ubd_test_bit(sector + i, bitmap) != bit) -+ return(-1); -+ } -+ -+ if(bit || (req->cmd == WRITE)) -+ offset += dev->cow.data_offset; -+ -+ /* The data on disk must be page aligned */ -+ if((offset % UBD_MMAP_BLOCK_SIZE) != 0) -+ return(-1); -+ -+ return(bit ? dev->fd : dev->cow.fd); -+} -+ -+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset, -+ struct request *req, -+ struct io_thread_req *io_req) -+{ -+ int err; -+ -+ if(req->cmd == WRITE){ -+ /* Writes are almost no-ops since the new data is already in the -+ * host page cache -+ */ -+ dev->map_writes++; -+ if(dev->cow.file != NULL) -+ cowify_bitmap(io_req->offset, io_req->length, -+ &io_req->sector_mask, &io_req->cow_offset, -+ dev->cow.bitmap, dev->cow.bitmap_offset, -+ io_req->bitmap_words, -+ dev->cow.bitmap_len); -+ } -+ else { -+ int w; -+ -+ if((dev->cow.file != NULL) && (fd == dev->cow.fd)) -+ w = 0; -+ else w = dev->openflags.w; -+ -+ if((dev->cow.file != NULL) && (fd == dev->fd)) -+ offset += dev->cow.data_offset; -+ -+ err = physmem_subst_mapping(req->buffer, fd, offset, w); -+ if(err){ -+ printk("physmem_subst_mapping failed, err = %d\n", -+ -err); -+ return(1); -+ } -+ dev->map_reads++; -+ } -+ io_req->op = UBD_MMAP; -+ io_req->buffer = req->buffer; -+ return(0); -+} -+ -+static int prepare_request(struct request *req, struct io_thread_req *io_req) -+{ -+ struct ubd *dev; -+ __u64 offset; -+ int minor, n, len, fd; -+ -+ if(req->rq_status == RQ_INACTIVE) return(1); -+ -+ minor = MINOR(req->rq_dev); -+ n = minor >> UBD_SHIFT; -+ dev = &ubd_dev[n]; -+ -+ if(IS_WRITE(req) && !dev->openflags.w){ -+ printk("Write attempted on readonly ubd device %d\n", n); -+ end_request(0); -+ return(1); -+ } -+ -+ req->sector += ubd_part[minor].start_sect; -+ offset = ((__u64) req->sector) << 9; -+ len = req->current_nr_sectors << 9; -+ -+ io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; -+ io_req->fds[1] = dev->fd; -+ io_req->map_fd = -1; -+ io_req->cow_offset = -1; -+ io_req->offset = offset; -+ io_req->length = len; -+ io_req->error = 0; -+ io_req->sector_mask = 0; -+ -+ fd = mmap_fd(req, dev, io_req->offset); -+ if(fd > 0){ -+ /* If mmapping is otherwise OK, but the first access to the -+ * page is a write, then it's not mapped in yet. So we have -+ * to write the data to disk first, then we can map the disk -+ * page in and continue normally from there. -+ */ -+ if((req->cmd == WRITE) && !is_remapped(req->buffer)){ -+ io_req->map_fd = dev->fd; -+ io_req->map_offset = io_req->offset + -+ dev->cow.data_offset; -+ dev->write_maps++; -+ } -+ else return(prepare_mmap_request(dev, fd, io_req->offset, req, -+ io_req)); -+ } -+ -+ if(req->cmd == READ) -+ dev->nomap_reads++; -+ else dev->nomap_writes++; -+ -+ io_req->op = (req->cmd == READ) ? UBD_READ : UBD_WRITE; -+ io_req->offsets[0] = 0; -+ io_req->offsets[1] = dev->cow.data_offset; -+ io_req->buffer = req->buffer; -+ io_req->sectorsize = 1 << 9; -+ -+ if(dev->cow.file != NULL) -+ cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, -+ dev->cow.bitmap_len); -+ return(0); -+} -+ -+static void do_ubd_request(request_queue_t *q) -+{ -+ struct io_thread_req io_req; -+ struct request *req; -+ int err, n; -+ -+ if(thread_fd == -1){ -+ while(!list_empty(&q->queue_head)){ -+ req = blkdev_entry_next_request(&q->queue_head); -+ err = prepare_request(req, &io_req); -+ if(!err){ -+ do_io(&io_req); -+ ubd_finish(io_req.error); -+ } -+ } -+ } -+ else { -+ if(DEVICE_INTR || list_empty(&q->queue_head)) return; -+ req = blkdev_entry_next_request(&q->queue_head); -+ err = prepare_request(req, &io_req); -+ if(!err){ -+ SET_INTR(ubd_handler); -+ n = write_ubd_fs(thread_fd, (char *) &io_req, -+ sizeof(io_req)); -+ if(n != sizeof(io_req)) -+ printk("write to io thread failed, " -+ "errno = %d\n", -n); -+ } -+ } -+} -+ -+static int ubd_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hd_geometry *loc = (struct hd_geometry *) arg; -+ struct ubd *dev; -+ int n, minor, err; -+ struct hd_driveid ubd_id = { -+ .cyls = 0, -+ .heads = 128, -+ .sectors = 32, -+ }; -+ -+ if(!inode) return(-EINVAL); -+ minor = MINOR(inode->i_rdev); -+ n = minor >> UBD_SHIFT; -+ if(n >= MAX_DEV) -+ return(-EINVAL); -+ dev = &ubd_dev[n]; -+ switch (cmd) { -+ struct hd_geometry g; -+ struct cdrom_volctrl volume; -+ case HDIO_GETGEO: -+ if(!loc) return(-EINVAL); -+ g.heads = 128; -+ g.sectors = 32; -+ g.cylinders = dev->size / (128 * 32 * hardsect_sizes[minor]); -+ g.start = ubd_part[minor].start_sect; -+ return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0); -+ case BLKGETSIZE: /* Return device size */ -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ put_user(ubd_part[minor].nr_sects, (long *) arg); -+ return(0); -+ case BLKRRPART: /* Re-read partition tables */ -+ return(ubd_revalidate(inode->i_rdev)); -+ -+ case HDIO_SET_UNMASKINTR: -+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES); -+ if((arg > 1) || (minor & 0x3F)) return(-EINVAL); -+ return(0); -+ -+ case HDIO_GET_UNMASKINTR: -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ return(0); -+ -+ case HDIO_GET_MULTCOUNT: -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ return(0); -+ -+ case HDIO_SET_MULTCOUNT: -+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES); -+ if(MINOR(inode->i_rdev) & 0x3F) return(-EINVAL); -+ return(0); -+ -+ case HDIO_GET_IDENTITY: -+ ubd_id.cyls = dev->size / (128 * 32 * hardsect_sizes[minor]); -+ if(copy_to_user((char *) arg, (char *) &ubd_id, -+ sizeof(ubd_id))) -+ return(-EFAULT); -+ return(0); -+ -+ case CDROMVOLREAD: -+ if(copy_from_user(&volume, (char *) arg, sizeof(volume))) -+ return(-EFAULT); -+ volume.channel0 = 255; -+ volume.channel1 = 255; -+ volume.channel2 = 255; -+ volume.channel3 = 255; -+ if(copy_to_user((char *) arg, &volume, sizeof(volume))) -+ return(-EFAULT); -+ return(0); -+ -+ default: -+ return blk_ioctl(inode->i_rdev, cmd, arg); -+ } -+} -+ -+static int ubd_revalidate1(kdev_t rdev) -+{ -+ int i, n, offset, err = 0, pcount = 1 << UBD_SHIFT; -+ struct ubd *dev; -+ struct hd_struct *part; -+ -+ n = DEVICE_NR(rdev); -+ offset = n << UBD_SHIFT; -+ dev = &ubd_dev[n]; -+ -+ part = &ubd_part[offset]; -+ -+ /* clear all old partition counts */ -+ for(i = 1; i < pcount; i++) { -+ part[i].start_sect = 0; -+ part[i].nr_sects = 0; -+ } -+ -+ /* If it already has been opened we can check the partitions -+ * directly -+ */ -+ if(dev->count){ -+ part->start_sect = 0; -+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount, -+ &ubd_blops, part->nr_sects); -+ } -+ else if(dev->file){ -+ err = ubd_open_dev(dev); -+ if(err){ -+ printk(KERN_ERR "unable to open %s for validation\n", -+ dev->file); -+ goto out; -+ } -+ -+ /* have to recompute sizes since we opened it */ -+ err = ubd_file_size(dev, &dev->size); -+ if(err < 0) { -+ ubd_close(dev); -+ goto out; -+ } -+ part->start_sect = 0; -+ part->nr_sects = dev->size / hardsect_sizes[offset]; -+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount, -+ &ubd_blops, part->nr_sects); -+ -+ /* we are done so close it */ -+ ubd_close(dev); -+ } -+ else err = -ENODEV; -+ out: -+ return(err); -+} -+ -+static int ubd_revalidate(kdev_t rdev) -+{ -+ int err; -+ -+ spin_lock(&ubd_lock); -+ err = ubd_revalidate1(rdev); -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_check_remapped(int fd, unsigned long address, int is_write, -+ __u64 offset) -+{ -+ __u64 bitmap_offset; -+ unsigned long new_bitmap[2]; -+ int i, err, n; -+ -+ /* If it's not a write access, we can't do anything about it */ -+ if(!is_write) -+ return(0); -+ -+ /* We have a write */ -+ for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){ -+ struct ubd *dev = &ubd_dev[i]; -+ -+ if((dev->fd != fd) && (dev->cow.fd != fd)) -+ continue; -+ -+ /* It's a write to a ubd device */ -+ -+ if(!dev->openflags.w){ -+ /* It's a write access on a read-only device - probably -+ * shouldn't happen. If the kernel is trying to change -+ * something with no intention of writing it back out, -+ * then this message will clue us in that this needs -+ * fixing -+ */ -+ printk("Write access to mapped page from readonly ubd " -+ "device %d\n", i); -+ return(0); -+ } -+ -+ /* It's a write to a writeable ubd device - it must be COWed -+ * because, otherwise, the page would have been mapped in -+ * writeable -+ */ -+ -+ if(!dev->cow.file) -+ panic("Write fault on writeable non-COW ubd device %d", -+ i); -+ -+ /* It should also be an access to the backing file since the -+ * COW pages should be mapped in read-write -+ */ -+ -+ if(fd == dev->fd) -+ panic("Write fault on a backing page of ubd " -+ "device %d\n", i); -+ -+ /* So, we do the write, copying the backing data to the COW -+ * file... -+ */ -+ -+ err = os_seek_file(dev->fd, offset + dev->cow.data_offset); -+ if(err < 0) -+ panic("Couldn't seek to %lld in COW file of ubd " -+ "device %d, err = %d", -+ offset + dev->cow.data_offset, i, -err); -+ -+ n = os_write_file(dev->fd, (void *) address, PAGE_SIZE); -+ if(n != PAGE_SIZE) -+ panic("Couldn't copy data to COW file of ubd " -+ "device %d, err = %d", i, -n); -+ -+ /* ... updating the COW bitmap... */ -+ -+ cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset, -+ dev->cow.bitmap, dev->cow.bitmap_offset, -+ new_bitmap, dev->cow.bitmap_len); -+ -+ err = os_seek_file(dev->fd, bitmap_offset); -+ if(err < 0) -+ panic("Couldn't seek to %lld in COW file of ubd " -+ "device %d, err = %d", bitmap_offset, i, -err); -+ -+ n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap)); -+ if(n != sizeof(new_bitmap)) -+ panic("Couldn't update bitmap of ubd device %d, " -+ "err = %d", i, -n); -+ -+ /* Maybe we can map the COW page in, and maybe we can't. If -+ * it is a pre-V3 COW file, we can't, since the alignment will -+ * be wrong. If it is a V3 or later COW file which has been -+ * moved to a system with a larger page size, then maybe we -+ * can't, depending on the exact location of the page. -+ */ -+ -+ offset += dev->cow.data_offset; -+ -+ /* Remove the remapping, putting the original anonymous page -+ * back. If the COW file can be mapped in, that is done. -+ * Otherwise, the COW page is read in. -+ */ -+ -+ if(!physmem_remove_mapping((void *) address)) -+ panic("Address 0x%lx not remapped by ubd device %d", -+ address, i); -+ if((offset % UBD_MMAP_BLOCK_SIZE) == 0) -+ physmem_subst_mapping((void *) address, dev->fd, -+ offset, 1); -+ else { -+ err = os_seek_file(dev->fd, offset); -+ if(err < 0) -+ panic("Couldn't seek to %lld in COW file of " -+ "ubd device %d, err = %d", offset, i, -+ -err); -+ -+ n = os_read_file(dev->fd, (void *) address, PAGE_SIZE); -+ if(n != PAGE_SIZE) -+ panic("Failed to read page from offset %llx of " -+ "COW file of ubd device %d, err = %d", -+ offset, i, -n); -+ } -+ -+ return(1); -+ } -+ -+ /* It's not a write on a ubd device */ -+ return(0); -+} -+ -+static struct remapper ubd_remapper = { -+ .list = LIST_HEAD_INIT(ubd_remapper.list), -+ .proc = ubd_check_remapped, -+}; -+ -+static int ubd_remapper_setup(void) -+{ -+ if(ubd_do_mmap) -+ register_remapper(&ubd_remapper); -+ -+ return(0); -+} -+ -+__initcall(ubd_remapper_setup); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/ubd_user.c um/arch/um/drivers/ubd_user.c ---- orig/arch/um/drivers/ubd_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/ubd_user.c 2004-01-10 06:24:52.000000000 -0500 -@@ -0,0 +1,377 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "asm/types.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "ubd_user.h" -+#include "os.h" -+#include "cow.h" -+ -+#include -+#include -+ -+static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) -+{ -+ struct uml_stat buf1, buf2; -+ int err; -+ -+ if(from_cmdline == NULL) return(1); -+ if(!strcmp(from_cmdline, from_cow)) return(1); -+ -+ err = os_stat_file(from_cmdline, &buf1); -+ if(err < 0){ -+ printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); -+ return(1); -+ } -+ err = os_stat_file(from_cow, &buf2); -+ if(err < 0){ -+ printk("Couldn't stat '%s', err = %d\n", from_cow, -err); -+ return(1); -+ } -+ if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) -+ return(1); -+ -+ printk("Backing file mismatch - \"%s\" requested,\n" -+ "\"%s\" specified in COW header of \"%s\"\n", -+ from_cmdline, from_cow, cow); -+ return(0); -+} -+ -+static int backing_file_mismatch(char *file, __u64 size, time_t mtime) -+{ -+ unsigned long modtime; -+ long long actual; -+ int err; -+ -+ err = os_file_modtime(file, &modtime); -+ if(err < 0){ -+ printk("Failed to get modification time of backing file " -+ "\"%s\", err = %d\n", file, -err); -+ return(err); -+ } -+ -+ err = os_file_size(file, &actual); -+ if(err < 0){ -+ printk("Failed to get size of backing file \"%s\", " -+ "err = %d\n", file, -err); -+ return(err); -+ } -+ -+ if(actual != size){ -+ printk("Size mismatch (%ld vs %ld) of COW header vs backing " -+ "file\n", size, actual); -+ return(-EINVAL); -+ } -+ if(modtime != mtime){ -+ printk("mtime mismatch (%ld vs %ld) of COW header vs backing " -+ "file\n", mtime, modtime); -+ return(-EINVAL); -+ } -+ return(0); -+} -+ -+int read_cow_bitmap(int fd, void *buf, int offset, int len) -+{ -+ int err; -+ -+ err = os_seek_file(fd, offset); -+ if(err < 0) -+ return(err); -+ -+ err = os_read_file(fd, buf, len); -+ if(err < 0) -+ return(err); -+ -+ return(0); -+} -+ -+int open_ubd_file(char *file, struct openflags *openflags, -+ char **backing_file_out, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out, -+ int *create_cow_out) -+{ -+ time_t mtime; -+ __u64 size; -+ __u32 version, align; -+ char *backing_file; -+ int fd, err, sectorsize, same, mode = 0644; -+ -+ fd = os_open_file(file, *openflags, mode); -+ if(fd < 0){ -+ if((fd == -ENOENT) && (create_cow_out != NULL)) -+ *create_cow_out = 1; -+ if(!openflags->w || -+ ((errno != EROFS) && (errno != EACCES))) return(-errno); -+ openflags->w = 0; -+ fd = os_open_file(file, *openflags, mode); -+ if(fd < 0) -+ return(fd); -+ } -+ -+ err = os_lock_file(fd, openflags->w); -+ if(err < 0){ -+ printk("Failed to lock '%s', err = %d\n", file, -err); -+ goto out_close; -+ } -+ -+ if(backing_file_out == NULL) return(fd); -+ -+ err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, -+ &size, §orsize, &align, bitmap_offset_out); -+ if(err && (*backing_file_out != NULL)){ -+ printk("Failed to read COW header from COW file \"%s\", " -+ "errno = %d\n", file, -err); -+ goto out_close; -+ } -+ if(err) return(fd); -+ -+ if(backing_file_out == NULL) return(fd); -+ -+ same = same_backing_files(*backing_file_out, backing_file, file); -+ -+ if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ -+ printk("Switching backing file to '%s'\n", *backing_file_out); -+ err = write_cow_header(file, fd, *backing_file_out, -+ sectorsize, align, &size); -+ if(err){ -+ printk("Switch failed, errno = %d\n", -err); -+ return(err); -+ } -+ } -+ else { -+ *backing_file_out = backing_file; -+ err = backing_file_mismatch(*backing_file_out, size, mtime); -+ if(err) goto out_close; -+ } -+ -+ cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, -+ bitmap_len_out, data_offset_out); -+ -+ return(fd); -+ out_close: -+ os_close_file(fd); -+ return(err); -+} -+ -+int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, -+ int sectorsize, int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out) -+{ -+ int err, fd; -+ -+ flags.c = 1; -+ fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL); -+ if(fd < 0){ -+ err = fd; -+ printk("Open of COW file '%s' failed, errno = %d\n", cow_file, -+ -err); -+ goto out; -+ } -+ -+ err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment, -+ bitmap_offset_out, bitmap_len_out, -+ data_offset_out); -+ if(!err) -+ return(fd); -+ -+ os_close_file(fd); -+ out: -+ return(err); -+} -+ -+/* XXX Just trivial wrappers around os_read_file and os_write_file */ -+int read_ubd_fs(int fd, void *buffer, int len) -+{ -+ return(os_read_file(fd, buffer, len)); -+} -+ -+int write_ubd_fs(int fd, char *buffer, int len) -+{ -+ return(os_write_file(fd, buffer, len)); -+} -+ -+static int update_bitmap(struct io_thread_req *req) -+{ -+ int n; -+ -+ if(req->cow_offset == -1) -+ return(0); -+ -+ n = os_seek_file(req->fds[1], req->cow_offset); -+ if(n < 0){ -+ printk("do_io - bitmap lseek failed : err = %d\n", -n); -+ return(1); -+ } -+ -+ n = os_write_file(req->fds[1], &req->bitmap_words, -+ sizeof(req->bitmap_words)); -+ if(n != sizeof(req->bitmap_words)){ -+ printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, -+ req->fds[1]); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+void do_io(struct io_thread_req *req) -+{ -+ char *buf; -+ unsigned long len; -+ int n, nsectors, start, end, bit; -+ int err; -+ __u64 off; -+ -+ if(req->op == UBD_MMAP){ -+ /* Touch the page to force the host to do any necessary IO to -+ * get it into memory -+ */ -+ n = *((volatile int *) req->buffer); -+ req->error = update_bitmap(req); -+ return; -+ } -+ -+ nsectors = req->length / req->sectorsize; -+ start = 0; -+ do { -+ bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask); -+ end = start; -+ while((end < nsectors) && -+ (ubd_test_bit(end, (unsigned char *) -+ &req->sector_mask) == bit)) -+ end++; -+ -+ off = req->offset + req->offsets[bit] + -+ start * req->sectorsize; -+ len = (end - start) * req->sectorsize; -+ buf = &req->buffer[start * req->sectorsize]; -+ -+ err = os_seek_file(req->fds[bit], off); -+ if(err < 0){ -+ printk("do_io - lseek failed : err = %d\n", -err); -+ req->error = 1; -+ return; -+ } -+ if(req->op == UBD_READ){ -+ n = 0; -+ do { -+ buf = &buf[n]; -+ len -= n; -+ n = os_read_file(req->fds[bit], buf, len); -+ if (n < 0) { -+ printk("do_io - read failed, err = %d " -+ "fd = %d\n", -n, req->fds[bit]); -+ req->error = 1; -+ return; -+ } -+ } while((n < len) && (n != 0)); -+ if (n < len) memset(&buf[n], 0, len - n); -+ } -+ else { -+ n = os_write_file(req->fds[bit], buf, len); -+ if(n != len){ -+ printk("do_io - write failed err = %d " -+ "fd = %d\n", -n, req->fds[bit]); -+ req->error = 1; -+ return; -+ } -+ } -+ -+ start = end; -+ } while(start < nsectors); -+ -+ req->error = update_bitmap(req); -+} -+ -+/* Changed in start_io_thread, which is serialized by being called only -+ * from ubd_init, which is an initcall. -+ */ -+int kernel_fd = -1; -+ -+/* Only changed by the io thread */ -+int io_count = 0; -+ -+int io_thread(void *arg) -+{ -+ struct io_thread_req req; -+ int n; -+ -+ signal(SIGWINCH, SIG_IGN); -+ while(1){ -+ n = os_read_file(kernel_fd, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ if(n < 0) -+ printk("io_thread - read failed, fd = %d, " -+ "err = %d\n", kernel_fd, -n); -+ else { -+ printk("io_thread - short read, fd = %d, " -+ "length = %d\n", kernel_fd, n); -+ } -+ continue; -+ } -+ io_count++; -+ do_io(&req); -+ n = os_write_file(kernel_fd, &req, sizeof(req)); -+ if(n != sizeof(req)) -+ printk("io_thread - write failed, fd = %d, err = %d\n", -+ kernel_fd, -n); -+ } -+} -+ -+int start_io_thread(unsigned long sp, int *fd_out) -+{ -+ int pid, fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err < 0){ -+ printk("start_io_thread - os_pipe failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ kernel_fd = fds[0]; -+ *fd_out = fds[1]; -+ -+ pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, -+ NULL); -+ if(pid < 0){ -+ printk("start_io_thread - clone failed : errno = %d\n", errno); -+ goto out_close; -+ } -+ -+ return(pid); -+ -+ out_close: -+ os_close_file(fds[0]); -+ os_close_file(fds[1]); -+ kernel_fd = -1; -+ *fd_out = -1; -+ out: -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/xterm.c um/arch/um/drivers/xterm.c ---- orig/arch/um/drivers/xterm.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/xterm.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,201 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "kern_util.h" -+#include "chan_user.h" -+#include "helper.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+#include "xterm.h" -+ -+struct xterm_chan { -+ int pid; -+ int helper_pid; -+ char *title; -+ int device; -+ int raw; -+ struct termios tt; -+ unsigned long stack; -+ int direct_rcv; -+}; -+ -+void *xterm_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct xterm_chan *data; -+ -+ data = malloc(sizeof(*data)); -+ if(data == NULL) return(NULL); -+ *data = ((struct xterm_chan) { .pid = -1, -+ .helper_pid = -1, -+ .device = device, -+ .title = opts->xterm_title, -+ .raw = opts->raw, -+ .stack = opts->tramp_stack, -+ .direct_rcv = !opts->in_kernel } ); -+ return(data); -+} -+ -+/* Only changed by xterm_setup, which is a setup */ -+static char *terminal_emulator = "xterm"; -+static char *title_switch = "-T"; -+static char *exec_switch = "-e"; -+ -+static int __init xterm_setup(char *line, int *add) -+{ -+ *add = 0; -+ terminal_emulator = line; -+ -+ line = strchr(line, ','); -+ if(line == NULL) return(0); -+ *line++ = '\0'; -+ if(*line) title_switch = line; -+ -+ line = strchr(line, ','); -+ if(line == NULL) return(0); -+ *line++ = '\0'; -+ if(*line) exec_switch = line; -+ -+ return(0); -+} -+ -+__uml_setup("xterm=", xterm_setup, -+"xterm=,,<exec switch>\n" -+" Specifies an alternate terminal emulator to use for the debugger,\n" -+" consoles, and serial lines when they are attached to the xterm channel.\n" -+" The values are the terminal emulator binary, the switch it uses to set\n" -+" its title, and the switch it uses to execute a subprocess,\n" -+" respectively. The title switch must have the form '<switch> title',\n" -+" not '<switch>=title'. Similarly, the exec switch must have the form\n" -+" '<switch> command arg1 arg2 ...'.\n" -+" The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n" -+" are 'xterm=gnome-terminal,-t,-x'.\n\n" -+); -+ -+int xterm_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct xterm_chan *data = d; -+ unsigned long stack; -+ int pid, fd, new, err; -+ char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; -+ char *argv[] = { terminal_emulator, title_switch, title, exec_switch, -+ "/usr/lib/uml/port-helper", "-uml-socket", -+ file, NULL }; -+ -+ if(os_access(argv[4], OS_ACC_X_OK) < 0) -+ argv[4] = "port-helper"; -+ -+ fd = mkstemp(file); -+ if(fd < 0){ -+ printk("xterm_open : mkstemp failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(unlink(file)){ -+ printk("xterm_open : unlink failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ os_close_file(fd); -+ -+ fd = os_create_unix_socket(file, sizeof(file), 1); -+ if(fd < 0){ -+ printk("xterm_open : create_unix_socket failed, errno = %d\n", -+ -fd); -+ return(fd); -+ } -+ -+ sprintf(title, data->title, data->device); -+ stack = data->stack; -+ pid = run_helper(NULL, NULL, argv, &stack); -+ if(pid < 0){ -+ printk("xterm_open : run_helper failed, errno = %d\n", -pid); -+ return(pid); -+ } -+ -+ if(data->stack == 0) free_stack(stack, 0); -+ -+ if(data->direct_rcv) -+ new = os_rcv_fd(fd, &data->helper_pid); -+ else { -+ err = os_set_fd_block(fd, 0); -+ if(err < 0){ -+ printk("xterm_open : failed to set descriptor " -+ "non-blocking, err = %d\n", -err); -+ return(err); -+ } -+ new = xterm_fd(fd, &data->helper_pid); -+ } -+ if(new < 0){ -+ printk("xterm_open : os_rcv_fd failed, err = %d\n", -new); -+ goto out; -+ } -+ -+ tcgetattr(new, &data->tt); -+ if(data->raw) raw(new, 0); -+ -+ data->pid = pid; -+ *dev_out = NULL; -+ out: -+ unlink(file); -+ return(new); -+} -+ -+void xterm_close(int fd, void *d) -+{ -+ struct xterm_chan *data = d; -+ -+ if(data->pid != -1) -+ os_kill_process(data->pid, 1); -+ data->pid = -1; -+ if(data->helper_pid != -1) -+ os_kill_process(data->helper_pid, 0); -+ data->helper_pid = -1; -+ os_close_file(fd); -+} -+ -+void xterm_free(void *d) -+{ -+ free(d); -+} -+ -+int xterm_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct xterm_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops xterm_ops = { -+ .type = "xterm", -+ .init = xterm_init, -+ .open = xterm_open, -+ .close = xterm_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = xterm_console_write, -+ .window_size = generic_window_size, -+ .free = xterm_free, -+ .winch = 1, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/xterm.h um/arch/um/drivers/xterm.h ---- orig/arch/um/drivers/xterm.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/xterm.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __XTERM_H__ -+#define __XTERM_H__ -+ -+extern int xterm_fd(int socket, int *pid_out); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/drivers/xterm_kern.c um/arch/um/drivers/xterm_kern.c ---- orig/arch/um/drivers/xterm_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/drivers/xterm_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/errno.h" -+#include "linux/slab.h" -+#include "asm/semaphore.h" -+#include "asm/irq.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "kern_util.h" -+#include "os.h" -+#include "xterm.h" -+ -+struct xterm_wait { -+ struct semaphore sem; -+ int fd; -+ int pid; -+ int new_fd; -+}; -+ -+static void xterm_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct xterm_wait *xterm = data; -+ int fd; -+ -+ fd = os_rcv_fd(xterm->fd, &xterm->pid); -+ if(fd == -EAGAIN) -+ return; -+ -+ xterm->new_fd = fd; -+ up(&xterm->sem); -+} -+ -+int xterm_fd(int socket, int *pid_out) -+{ -+ struct xterm_wait *data; -+ int err, ret; -+ -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL){ -+ printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n"); -+ return(-ENOMEM); -+ } -+ *data = ((struct xterm_wait) -+ { .sem = __SEMAPHORE_INITIALIZER(data->sem, 0), -+ .fd = socket, -+ .pid = -1, -+ .new_fd = -1 }); -+ -+ err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "xterm", data); -+ if(err){ -+ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " -+ "err = %d\n", err); -+ ret = err; -+ goto out; -+ } -+ down(&data->sem); -+ -+ free_irq(XTERM_IRQ, data); -+ -+ ret = data->new_fd; -+ *pid_out = data->pid; -+ out: -+ kfree(data); -+ -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/dyn_link.ld.in um/arch/um/dyn_link.ld.in ---- orig/arch/um/dyn_link.ld.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/dyn_link.ld.in 2004-01-10 04:28:44.000000000 -0500 -@@ -0,0 +1,171 @@ -+OUTPUT_FORMAT("ELF_FORMAT") -+OUTPUT_ARCH(ELF_ARCH) -+ENTRY(_start) -+SEARCH_DIR("/usr/local/i686-pc-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); -+/* Do we need any of these for elf? -+ __DYNAMIC = 0; */ -+SECTIONS -+{ -+ . = START() + SIZEOF_HEADERS; -+ .interp : { *(.interp) } -+ __binary_start = .; -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ -+ . = ALIGN(4096); -+ -+ /* Read-only sections, merged into text segment: */ -+ .hash : { *(.hash) } -+ .dynsym : { *(.dynsym) } -+ .dynstr : { *(.dynstr) } -+ .gnu.version : { *(.gnu.version) } -+ .gnu.version_d : { *(.gnu.version_d) } -+ .gnu.version_r : { *(.gnu.version_r) } -+ .rel.init : { *(.rel.init) } -+ .rela.init : { *(.rela.init) } -+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } -+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } -+ .rel.fini : { *(.rel.fini) } -+ .rela.fini : { *(.rela.fini) } -+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } -+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } -+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } -+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } -+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } -+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } -+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } -+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } -+ .rel.ctors : { *(.rel.ctors) } -+ .rela.ctors : { *(.rela.ctors) } -+ .rel.dtors : { *(.rel.dtors) } -+ .rela.dtors : { *(.rela.dtors) } -+ .rel.got : { *(.rel.got) } -+ .rela.got : { *(.rela.got) } -+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } -+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } -+ .rel.plt : { *(.rel.plt) } -+ .rela.plt : { *(.rela.plt) } -+ .init : { -+ KEEP (*(.init)) -+ } =0x90909090 -+ .plt : { *(.plt) } -+ .text : { -+ *(.text .stub .text.* .gnu.linkonce.t.*) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ } =0x90909090 -+ .fini : { -+ KEEP (*(.fini)) -+ } =0x90909090 -+ -+ PROVIDE (__etext = .); -+ PROVIDE (_etext = .); -+ PROVIDE (etext = .); -+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } -+ .rodata1 : { *(.rodata1) } -+ .eh_frame_hdr : { *(.eh_frame_hdr) } -+ -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+include(`arch/um/common.ld.in') -+ -+ /* Ensure the __preinit_array_start label is properly aligned. We -+ could instead move the label definition inside the section, but -+ the linker would then create the section even if it turns out to -+ be empty, which isn't pretty. */ -+ . = ALIGN(32 / 8); -+ .preinit_array : { *(.preinit_array) } -+ .init_array : { *(.init_array) } -+ .fini_array : { *(.fini_array) } -+ .data : { -+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ -+ *(.data.init_task) -+ *(.data .data.* .gnu.linkonce.d.*) -+ SORT(CONSTRUCTORS) -+ } -+ .data1 : { *(.data1) } -+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } -+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } -+ .eh_frame : { KEEP (*(.eh_frame)) } -+ .gcc_except_table : { *(.gcc_except_table) } -+ .dynamic : { *(.dynamic) } -+ .ctors : { -+ /* gcc uses crtbegin.o to find the start of -+ the constructors, so we make sure it is -+ first. Because this is a wildcard, it -+ doesn't matter if the user does not -+ actually link against crtbegin.o; the -+ linker won't look for a file to match a -+ wildcard. The wildcard also means that it -+ doesn't matter which directory crtbegin.o -+ is in. */ -+ KEEP (*crtbegin.o(.ctors)) -+ /* We don't want to include the .ctor section from -+ from the crtend.o file until after the sorted ctors. -+ The .ctor section from the crtend file contains the -+ end of ctors marker and it must be last */ -+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) -+ KEEP (*(SORT(.ctors.*))) -+ KEEP (*(.ctors)) -+ } -+ .dtors : { -+ KEEP (*crtbegin.o(.dtors)) -+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) -+ KEEP (*(SORT(.dtors.*))) -+ KEEP (*(.dtors)) -+ } -+ .jcr : { KEEP (*(.jcr)) } -+ .got : { *(.got.plt) *(.got) } -+ _edata = .; -+ PROVIDE (edata = .); -+ __bss_start = .; -+ .bss : { -+ *(.dynbss) -+ *(.bss .bss.* .gnu.linkonce.b.*) -+ *(COMMON) -+ /* Align here to ensure that the .bss section occupies space up to -+ _end. Align after .bss to ensure correct alignment even if the -+ .bss section disappears because there are no input sections. */ -+ . = ALIGN(32 / 8); -+ . = ALIGN(32 / 8); -+ } -+ _end = .; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+ /* DWARF debug sections. -+ Symbols in the DWARF debugging sections are relative to the beginning -+ of the section so we begin them at 0. */ -+ /* DWARF 1 */ -+ .debug 0 : { *(.debug) } -+ .line 0 : { *(.line) } -+ /* GNU DWARF 1 extensions */ -+ .debug_srcinfo 0 : { *(.debug_srcinfo) } -+ .debug_sfnames 0 : { *(.debug_sfnames) } -+ /* DWARF 1.1 and DWARF 2 */ -+ .debug_aranges 0 : { *(.debug_aranges) } -+ .debug_pubnames 0 : { *(.debug_pubnames) } -+ /* DWARF 2 */ -+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } -+ .debug_abbrev 0 : { *(.debug_abbrev) } -+ .debug_line 0 : { *(.debug_line) } -+ .debug_frame 0 : { *(.debug_frame) } -+ .debug_str 0 : { *(.debug_str) } -+ .debug_loc 0 : { *(.debug_loc) } -+ .debug_macinfo 0 : { *(.debug_macinfo) } -+ /* SGI/MIPS DWARF 2 extensions */ -+ .debug_weaknames 0 : { *(.debug_weaknames) } -+ .debug_funcnames 0 : { *(.debug_funcnames) } -+ .debug_typenames 0 : { *(.debug_typenames) } -+ .debug_varnames 0 : { *(.debug_varnames) } -+} -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs.h um/arch/um/fs/hostfs/hostfs.h ---- orig/arch/um/fs/hostfs/hostfs.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/hostfs/hostfs.h 2003-12-17 10:52:50.000000000 -0500 -@@ -0,0 +1,69 @@ -+#ifndef __UM_FS_HOSTFS -+#define __UM_FS_HOSTFS -+ -+#include "os.h" -+ -+/* These are exactly the same definitions as in fs.h, but the names are -+ * changed so that this file can be included in both kernel and user files. -+ */ -+ -+#define HOSTFS_ATTR_MODE 1 -+#define HOSTFS_ATTR_UID 2 -+#define HOSTFS_ATTR_GID 4 -+#define HOSTFS_ATTR_SIZE 8 -+#define HOSTFS_ATTR_ATIME 16 -+#define HOSTFS_ATTR_MTIME 32 -+#define HOSTFS_ATTR_CTIME 64 -+#define HOSTFS_ATTR_ATIME_SET 128 -+#define HOSTFS_ATTR_MTIME_SET 256 -+#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */ -+#define HOSTFS_ATTR_ATTR_FLAG 1024 -+ -+struct hostfs_iattr { -+ unsigned int ia_valid; -+ mode_t ia_mode; -+ uid_t ia_uid; -+ gid_t ia_gid; -+ loff_t ia_size; -+ time_t ia_atime; -+ time_t ia_mtime; -+ time_t ia_ctime; -+ unsigned int ia_attr_flags; -+}; -+ -+extern int stat_file(const char *path, int *dev_out, -+ unsigned long long *inode_out, int *mode_out, -+ int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, unsigned long *atime_out, -+ unsigned long *mtime_out, unsigned long *ctime_out, -+ int *blksize_out, unsigned long long *blocks_out); -+extern int access_file(char *path, int r, int w, int x); -+extern int open_file(char *path, int r, int w, int append); -+extern int file_type(const char *path, int *rdev); -+extern void *open_dir(char *path, int *err_out); -+extern char *read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out); -+extern void close_file(void *stream); -+extern void close_dir(void *stream); -+extern int read_file(int fd, unsigned long long *offset, char *buf, int len); -+extern int write_file(int fd, unsigned long long *offset, const char *buf, -+ int len); -+extern int lseek_file(int fd, long long offset, int whence); -+extern int file_create(char *name, int ur, int uw, int ux, int gr, -+ int gw, int gx, int or, int ow, int ox); -+extern int set_attr(const char *file, struct hostfs_iattr *attrs); -+extern int make_symlink(const char *from, const char *to); -+extern int unlink_file(const char *file); -+extern int do_mkdir(const char *file, int mode); -+extern int do_rmdir(const char *file); -+extern int do_mknod(const char *file, int mode, int dev); -+extern int link_file(const char *from, const char *to); -+extern int do_readlink(char *file, char *buf, int size); -+extern int rename_file(char *from, char *to); -+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, -+ void *fsid_out, int fsid_size, long *namelen_out, -+ long *spare_out); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs_kern.c um/arch/um/fs/hostfs/hostfs_kern.c ---- orig/arch/um/fs/hostfs/hostfs_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/hostfs/hostfs_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,965 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/stddef.h> -+#include <linux/fs.h> -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/pagemap.h> -+#include <linux/blkdev.h> -+#include <asm/uaccess.h> -+#include "hostfs.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "user_util.h" -+#include "2_5compat.h" -+#include "init.h" -+ -+#define file_hostfs_i(file) (&(file)->f_dentry->d_inode->u.hostfs_i) -+ -+int hostfs_d_delete(struct dentry *dentry) -+{ -+ return(1); -+} -+ -+struct dentry_operations hostfs_dentry_ops = { -+ .d_delete = hostfs_d_delete, -+}; -+ -+#define DEFAULT_ROOT "/" -+ -+/* Changed in hostfs_args before the kernel starts running */ -+static char *jail_dir = NULL; -+static int append = 0; -+ -+#define HOSTFS_SUPER_MAGIC 0x00c0ffee -+ -+static struct inode_operations hostfs_iops; -+static struct inode_operations hostfs_dir_iops; -+static struct address_space_operations hostfs_link_aops; -+ -+static int __init hostfs_args(char *options, int *add) -+{ -+ char *ptr; -+ -+ ptr = strchr(options, ','); -+ if(ptr != NULL) -+ *ptr++ = '\0'; -+ if(*options != '\0') -+ jail_dir = options; -+ -+ options = ptr; -+ while(options){ -+ ptr = strchr(options, ','); -+ if(ptr != NULL) -+ *ptr++ = '\0'; -+ if(*options != '\0'){ -+ if(!strcmp(options, "append")) -+ append = 1; -+ else printf("hostfs_args - unsupported option - %s\n", -+ options); -+ } -+ options = ptr; -+ } -+ return(0); -+} -+ -+__uml_setup("hostfs=", hostfs_args, -+"hostfs=<root dir>,<flags>,...\n" -+" This is used to set hostfs parameters. The root directory argument\n" -+" is used to confine all hostfs mounts to within the specified directory\n" -+" tree on the host. If this isn't specified, then a user inside UML can\n" -+" mount anything on the host that's accessible to the user that's running\n" -+" it.\n" -+" The only flag currently supported is 'append', which specifies that all\n" -+" files opened by hostfs will be opened in append mode.\n\n" -+); -+ -+static char *dentry_name(struct dentry *dentry, int extra) -+{ -+ struct dentry *parent; -+ char *root, *name; -+ int len; -+ -+ len = 0; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ len += parent->d_name.len + 1; -+ parent = parent->d_parent; -+ } -+ -+ root = parent->d_inode->u.hostfs_i.host_filename; -+ len += strlen(root); -+ name = kmalloc(len + extra + 1, GFP_KERNEL); -+ if(name == NULL) return(NULL); -+ -+ name[len] = '\0'; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ len -= parent->d_name.len + 1; -+ name[len] = '/'; -+ strncpy(&name[len + 1], parent->d_name.name, -+ parent->d_name.len); -+ parent = parent->d_parent; -+ } -+ strncpy(name, root, strlen(root)); -+ return(name); -+} -+ -+static char *inode_name(struct inode *ino, int extra) -+{ -+ struct dentry *dentry; -+ -+ dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias); -+ return(dentry_name(dentry, extra)); -+} -+ -+static int read_name(struct inode *ino, char *name) -+{ -+ /* The non-int inode fields are copied into ints by stat_file and -+ * then copied into the inode because passing the actual pointers -+ * in and having them treated as int * breaks on big-endian machines -+ */ -+ int err; -+ int i_dev, i_mode, i_nlink, i_blksize; -+ unsigned long long i_size; -+ unsigned long long i_ino; -+ unsigned long long i_blocks; -+ err = stat_file(name, &i_dev, &i_ino, &i_mode, &i_nlink, -+ &ino->i_uid, &ino->i_gid, &i_size, &ino->i_atime, -+ &ino->i_mtime, &ino->i_ctime, &i_blksize, &i_blocks); -+ if(err) return(err); -+ ino->i_ino = i_ino; -+ ino->i_dev = i_dev; -+ ino->i_mode = i_mode; -+ ino->i_nlink = i_nlink; -+ ino->i_size = i_size; -+ ino->i_blksize = i_blksize; -+ ino->i_blocks = i_blocks; -+ if(kdev_same(ino->i_sb->s_dev, ROOT_DEV) && (ino->i_uid == getuid())) -+ ino->i_uid = 0; -+ return(0); -+} -+ -+static char *follow_link(char *link) -+{ -+ int len, n; -+ char *name, *resolved, *end; -+ -+ len = 64; -+ while(1){ -+ n = -ENOMEM; -+ name = kmalloc(len, GFP_KERNEL); -+ if(name == NULL) -+ goto out; -+ -+ n = do_readlink(link, name, len); -+ if(n < len) -+ break; -+ len *= 2; -+ kfree(name); -+ } -+ if(n < 0) -+ goto out_free; -+ -+ if(*name == '/') -+ return(name); -+ -+ end = strrchr(link, '/'); -+ if(end == NULL) -+ return(name); -+ -+ *(end + 1) = '\0'; -+ len = strlen(link) + strlen(name) + 1; -+ -+ resolved = kmalloc(len, GFP_KERNEL); -+ if(resolved == NULL){ -+ n = -ENOMEM; -+ goto out_free; -+ } -+ -+ sprintf(resolved, "%s%s", link, name); -+ kfree(name); -+ kfree(link); -+ return(resolved); -+ -+ out_free: -+ kfree(name); -+ out: -+ return(ERR_PTR(n)); -+} -+ -+static int read_inode(struct inode *ino) -+{ -+ char *name; -+ int err; -+ -+ err = -ENOMEM; -+ name = inode_name(ino, 0); -+ if(name == NULL) -+ goto out; -+ -+ if(file_type(name, NULL) == OS_TYPE_SYMLINK){ -+ name = follow_link(name); -+ if(IS_ERR(name)){ -+ err = PTR_ERR(name); -+ goto out; -+ } -+ } -+ -+ err = read_name(ino, name); -+ kfree(name); -+ out: -+ return(err); -+} -+ -+void hostfs_delete_inode(struct inode *ino) -+{ -+ if(ino->u.hostfs_i.host_filename) -+ kfree(ino->u.hostfs_i.host_filename); -+ ino->u.hostfs_i.host_filename = NULL; -+ -+ if(ino->u.hostfs_i.fd != -1) -+ close_file(&ino->u.hostfs_i.fd); -+ -+ ino->u.hostfs_i.mode = 0; -+ clear_inode(ino); -+} -+ -+int hostfs_statfs(struct super_block *sb, struct statfs *sf) -+{ -+ /* do_statfs uses struct statfs64 internally, but the linux kernel -+ * struct statfs still has 32-bit versions for most of these fields, -+ * so we convert them here -+ */ -+ int err; -+ long long f_blocks; -+ long long f_bfree; -+ long long f_bavail; -+ long long f_files; -+ long long f_ffree; -+ -+ err = do_statfs(sb->s_root->d_inode->u.hostfs_i.host_filename, -+ &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, -+ &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), -+ &sf->f_namelen, sf->f_spare); -+ if(err) return(err); -+ sf->f_blocks = f_blocks; -+ sf->f_bfree = f_bfree; -+ sf->f_bavail = f_bavail; -+ sf->f_files = f_files; -+ sf->f_ffree = f_ffree; -+ sf->f_type = HOSTFS_SUPER_MAGIC; -+ return(0); -+} -+ -+static struct super_operations hostfs_sbops = { -+ .put_inode = force_delete, -+ .delete_inode = hostfs_delete_inode, -+ .statfs = hostfs_statfs, -+}; -+ -+int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) -+{ -+ void *dir; -+ char *name; -+ unsigned long long next, ino; -+ int error, len; -+ -+ name = dentry_name(file->f_dentry, 0); -+ if(name == NULL) return(-ENOMEM); -+ dir = open_dir(name, &error); -+ kfree(name); -+ if(dir == NULL) return(-error); -+ next = file->f_pos; -+ while((name = read_dir(dir, &next, &ino, &len)) != NULL){ -+ error = (*filldir)(ent, name, len, file->f_pos, -+ ino, DT_UNKNOWN); -+ if(error) break; -+ file->f_pos = next; -+ } -+ close_dir(dir); -+ return(0); -+} -+ -+int hostfs_file_open(struct inode *ino, struct file *file) -+{ -+ char *name; -+ int mode = 0, r = 0, w = 0, fd; -+ -+ mode = file->f_mode & (FMODE_READ | FMODE_WRITE); -+ if((mode & ino->u.hostfs_i.mode) == mode) -+ return(0); -+ -+ /* The file may already have been opened, but with the wrong access, -+ * so this resets things and reopens the file with the new access. -+ */ -+ if(ino->u.hostfs_i.fd != -1){ -+ close_file(&ino->u.hostfs_i.fd); -+ ino->u.hostfs_i.fd = -1; -+ } -+ -+ ino->u.hostfs_i.mode |= mode; -+ if(ino->u.hostfs_i.mode & FMODE_READ) -+ r = 1; -+ if(ino->u.hostfs_i.mode & FMODE_WRITE) -+ w = 1; -+ if(w) -+ r = 1; -+ -+ name = dentry_name(file->f_dentry, 0); -+ if(name == NULL) -+ return(-ENOMEM); -+ -+ fd = open_file(name, r, w, append); -+ kfree(name); -+ if(fd < 0) return(fd); -+ file_hostfs_i(file)->fd = fd; -+ -+ return(0); -+} -+ -+int hostfs_dir_open(struct inode *ino, struct file *file) -+{ -+ return(0); -+} -+ -+int hostfs_dir_release(struct inode *ino, struct file *file) -+{ -+ return(0); -+} -+ -+int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) -+{ -+ return(0); -+} -+ -+static struct file_operations hostfs_file_fops = { -+ .owner = NULL, -+ .read = generic_file_read, -+ .write = generic_file_write, -+ .mmap = generic_file_mmap, -+ .open = hostfs_file_open, -+ .release = NULL, -+ .fsync = hostfs_fsync, -+}; -+ -+static struct file_operations hostfs_dir_fops = { -+ .owner = NULL, -+ .readdir = hostfs_readdir, -+ .open = hostfs_dir_open, -+ .release = hostfs_dir_release, -+ .fsync = hostfs_fsync, -+}; -+ -+int hostfs_writepage(struct page *page) -+{ -+ struct address_space *mapping = page->mapping; -+ struct inode *inode = mapping->host; -+ char *buffer; -+ unsigned long long base; -+ int count = PAGE_CACHE_SIZE; -+ int end_index = inode->i_size >> PAGE_CACHE_SHIFT; -+ int err; -+ -+ if (page->index >= end_index) -+ count = inode->i_size & (PAGE_CACHE_SIZE-1); -+ -+ buffer = kmap(page); -+ base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT; -+ -+ err = write_file(inode->u.hostfs_i.fd, &base, buffer, count); -+ if(err != count){ -+ ClearPageUptodate(page); -+ goto out; -+ } -+ -+ if (base > inode->i_size) -+ inode->i_size = base; -+ -+ if (PageError(page)) -+ ClearPageError(page); -+ err = 0; -+ -+ out: -+ kunmap(page); -+ -+ UnlockPage(page); -+ return err; -+} -+ -+int hostfs_readpage(struct file *file, struct page *page) -+{ -+ char *buffer; -+ long long start; -+ int err = 0; -+ -+ start = (long long) page->index << PAGE_CACHE_SHIFT; -+ buffer = kmap(page); -+ err = read_file(file_hostfs_i(file)->fd, &start, buffer, -+ PAGE_CACHE_SIZE); -+ if(err < 0) goto out; -+ -+ memset(&buffer[err], 0, PAGE_CACHE_SIZE - err); -+ -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ if (PageError(page)) ClearPageError(page); -+ err = 0; -+ out: -+ kunmap(page); -+ UnlockPage(page); -+ return(err); -+} -+ -+int hostfs_prepare_write(struct file *file, struct page *page, -+ unsigned int from, unsigned int to) -+{ -+ char *buffer; -+ long long start, tmp; -+ int err; -+ -+ start = (long long) page->index << PAGE_CACHE_SHIFT; -+ buffer = kmap(page); -+ if(from != 0){ -+ tmp = start; -+ err = read_file(file_hostfs_i(file)->fd, &tmp, buffer, -+ from); -+ if(err < 0) goto out; -+ } -+ if(to != PAGE_CACHE_SIZE){ -+ start += to; -+ err = read_file(file_hostfs_i(file)->fd, &start, buffer + to, -+ PAGE_CACHE_SIZE - to); -+ if(err < 0) goto out; -+ } -+ err = 0; -+ out: -+ kunmap(page); -+ return(err); -+} -+ -+int hostfs_commit_write(struct file *file, struct page *page, unsigned from, -+ unsigned to) -+{ -+ struct address_space *mapping = page->mapping; -+ struct inode *inode = mapping->host; -+ char *buffer; -+ long long start; -+ int err = 0; -+ -+ start = (long long) (page->index << PAGE_CACHE_SHIFT) + from; -+ buffer = kmap(page); -+ err = write_file(file_hostfs_i(file)->fd, &start, buffer + from, -+ to - from); -+ if(err > 0) err = 0; -+ if(!err && (start > inode->i_size)) -+ inode->i_size = start; -+ -+ kunmap(page); -+ return(err); -+} -+ -+static struct address_space_operations hostfs_aops = { -+ .writepage = hostfs_writepage, -+ .readpage = hostfs_readpage, -+/* .set_page_dirty = __set_page_dirty_nobuffers, */ -+ .prepare_write = hostfs_prepare_write, -+ .commit_write = hostfs_commit_write -+}; -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error) -+{ -+ struct inode *inode; -+ char *name; -+ int type, err = -ENOMEM, rdev; -+ -+ inode = new_inode(sb); -+ if(inode == NULL) -+ goto out; -+ -+ inode->u.hostfs_i.host_filename = NULL; -+ inode->u.hostfs_i.fd = -1; -+ inode->u.hostfs_i.mode = 0; -+ insert_inode_hash(inode); -+ if(dentry){ -+ name = dentry_name(dentry, 0); -+ if(name == NULL){ -+ err = -ENOMEM; -+ goto out_put; -+ } -+ type = file_type(name, &rdev); -+ kfree(name); -+ } -+ else type = OS_TYPE_DIR; -+ inode->i_sb = sb; -+ -+ err = 0; -+ if(type == OS_TYPE_SYMLINK) -+ inode->i_op = &page_symlink_inode_operations; -+ else if(type == OS_TYPE_DIR) -+ inode->i_op = &hostfs_dir_iops; -+ else inode->i_op = &hostfs_iops; -+ -+ if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops; -+ else inode->i_fop = &hostfs_file_fops; -+ -+ if(type == OS_TYPE_SYMLINK) -+ inode->i_mapping->a_ops = &hostfs_link_aops; -+ else inode->i_mapping->a_ops = &hostfs_aops; -+ -+ switch (type) { -+ case OS_TYPE_CHARDEV: -+ init_special_inode(inode, S_IFCHR, rdev); -+ break; -+ case OS_TYPE_BLOCKDEV: -+ init_special_inode(inode, S_IFBLK, rdev); -+ break; -+ case OS_TYPE_FIFO: -+ init_special_inode(inode, S_IFIFO, 0); -+ break; -+ case OS_TYPE_SOCK: -+ init_special_inode(inode, S_IFSOCK, 0); -+ break; -+ } -+ -+ if(error) *error = err; -+ return(inode); -+ out_put: -+ make_bad_inode(inode); -+ iput(inode); -+ out: -+ if(error) *error = err; -+ return(NULL); -+} -+ -+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ struct inode *inode; -+ char *name; -+ int error, fd; -+ -+ inode = get_inode(dir->i_sb, dentry, &error); -+ if(error) return(error); -+ name = dentry_name(dentry, 0); -+ if(name == NULL){ -+ iput(inode); -+ return(-ENOMEM); -+ } -+ fd = file_create(name, -+ mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR, -+ mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP, -+ mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH); -+ if(fd < 0) -+ error = fd; -+ else error = read_name(inode, name); -+ -+ kfree(name); -+ if(error){ -+ iput(inode); -+ return(error); -+ } -+ inode->u.hostfs_i.fd = fd; -+ inode->u.hostfs_i.mode = FMODE_READ | FMODE_WRITE; -+ d_instantiate(dentry, inode); -+ return(0); -+} -+ -+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry) -+{ -+ struct inode *inode; -+ char *name; -+ int error; -+ -+ inode = get_inode(ino->i_sb, dentry, &error); -+ if(error != 0) return(ERR_PTR(error)); -+ name = dentry_name(dentry, 0); -+ if(name == NULL) return(ERR_PTR(-ENOMEM)); -+ error = read_name(inode, name); -+ kfree(name); -+ if(error){ -+ iput(inode); -+ if(error == -ENOENT) inode = NULL; -+ else return(ERR_PTR(error)); -+ } -+ d_add(dentry, inode); -+ dentry->d_op = &hostfs_dentry_ops; -+ return(NULL); -+} -+ -+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry) -+{ -+ char *file; -+ int len; -+ -+ file = inode_name(ino, dentry->d_name.len + 1); -+ if(file == NULL) return(NULL); -+ strcat(file, "/"); -+ len = strlen(file); -+ strncat(file, dentry->d_name.name, dentry->d_name.len); -+ file[len + dentry->d_name.len] = '\0'; -+ return(file); -+} -+ -+int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from) -+{ -+ char *from_name, *to_name; -+ int err; -+ -+ from_name = inode_dentry_name(ino, from); -+ if(from_name == NULL) -+ return(-ENOMEM); -+ to_name = dentry_name(to, 0); -+ if(to_name == NULL){ -+ kfree(from_name); -+ return(-ENOMEM); -+ } -+ err = link_file(to_name, from_name); -+ kfree(from_name); -+ kfree(to_name); -+ return(err); -+} -+ -+int hostfs_unlink(struct inode *ino, struct dentry *dentry) -+{ -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) return(-ENOMEM); -+ if(append) -+ return(-EPERM); -+ -+ err = unlink_file(file); -+ kfree(file); -+ return(err); -+} -+ -+int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to) -+{ -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) return(-ENOMEM); -+ err = make_symlink(file, to); -+ kfree(file); -+ return(err); -+} -+ -+int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode) -+{ -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) return(-ENOMEM); -+ err = do_mkdir(file, mode); -+ kfree(file); -+ return(err); -+} -+ -+int hostfs_rmdir(struct inode *ino, struct dentry *dentry) -+{ -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) return(-ENOMEM); -+ err = do_rmdir(file); -+ kfree(file); -+ return(err); -+} -+ -+int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) -+{ -+ struct inode *inode; -+ char *name; -+ int error; -+ -+ inode = get_inode(dir->i_sb, dentry, &error); -+ if(error) return(error); -+ name = dentry_name(dentry, 0); -+ if(name == NULL){ -+ iput(inode); -+ return(-ENOMEM); -+ } -+ init_special_inode(inode, mode, dev); -+ error = do_mknod(name, mode, dev); -+ if(!error) error = read_name(inode, name); -+ kfree(name); -+ if(error){ -+ iput(inode); -+ return(error); -+ } -+ d_instantiate(dentry, inode); -+ return(0); -+} -+ -+int hostfs_rename(struct inode *from_ino, struct dentry *from, -+ struct inode *to_ino, struct dentry *to) -+{ -+ char *from_name, *to_name; -+ int err; -+ -+ from_name = inode_dentry_name(from_ino, from); -+ if(from_name == NULL) -+ return(-ENOMEM); -+ to_name = inode_dentry_name(to_ino, to); -+ if(to_name == NULL){ -+ kfree(from_name); -+ return(-ENOMEM); -+ } -+ err = rename_file(from_name, to_name); -+ kfree(from_name); -+ kfree(to_name); -+ return(err); -+} -+ -+void hostfs_truncate(struct inode *ino) -+{ -+ not_implemented(); -+} -+ -+int hostfs_permission(struct inode *ino, int desired) -+{ -+ char *name; -+ int r = 0, w = 0, x = 0, err; -+ -+ if(desired & MAY_READ) r = 1; -+ if(desired & MAY_WRITE) w = 1; -+ if(desired & MAY_EXEC) x = 1; -+ name = inode_name(ino, 0); -+ if(name == NULL) return(-ENOMEM); -+ err = access_file(name, r, w, x); -+ kfree(name); -+ if(!err) err = vfs_permission(ino, desired); -+ return(err); -+} -+ -+int hostfs_setattr(struct dentry *dentry, struct iattr *attr) -+{ -+ struct hostfs_iattr attrs; -+ char *name; -+ int err; -+ -+ if(append) -+ attr->ia_valid &= ~ATTR_SIZE; -+ -+ attrs.ia_valid = 0; -+ if(attr->ia_valid & ATTR_MODE){ -+ attrs.ia_valid |= HOSTFS_ATTR_MODE; -+ attrs.ia_mode = attr->ia_mode; -+ } -+ if(attr->ia_valid & ATTR_UID){ -+ if(kdev_same(dentry->d_inode->i_sb->s_dev, ROOT_DEV) && -+ (attr->ia_uid == 0)) -+ attr->ia_uid = getuid(); -+ attrs.ia_valid |= HOSTFS_ATTR_UID; -+ attrs.ia_uid = attr->ia_uid; -+ } -+ if(attr->ia_valid & ATTR_GID){ -+ if(kdev_same(dentry->d_inode->i_sb->s_dev, ROOT_DEV) && -+ (attr->ia_gid == 0)) -+ attr->ia_gid = getuid(); -+ attrs.ia_valid |= HOSTFS_ATTR_GID; -+ attrs.ia_gid = attr->ia_gid; -+ } -+ if(attr->ia_valid & ATTR_SIZE){ -+ attrs.ia_valid |= HOSTFS_ATTR_SIZE; -+ attrs.ia_size = attr->ia_size; -+ } -+ if(attr->ia_valid & ATTR_ATIME){ -+ attrs.ia_valid |= HOSTFS_ATTR_ATIME; -+ attrs.ia_atime = attr->ia_atime; -+ } -+ if(attr->ia_valid & ATTR_MTIME){ -+ attrs.ia_valid |= HOSTFS_ATTR_MTIME; -+ attrs.ia_mtime = attr->ia_mtime; -+ } -+ if(attr->ia_valid & ATTR_CTIME){ -+ attrs.ia_valid |= HOSTFS_ATTR_CTIME; -+ attrs.ia_ctime = attr->ia_ctime; -+ } -+ if(attr->ia_valid & ATTR_ATIME_SET){ -+ attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET; -+ } -+ if(attr->ia_valid & ATTR_MTIME_SET){ -+ attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET; -+ } -+ name = dentry_name(dentry, 0); -+ if(name == NULL) return(-ENOMEM); -+ err = set_attr(name, &attrs); -+ kfree(name); -+ if(err) -+ return(err); -+ -+ return(inode_setattr(dentry->d_inode, attr)); -+} -+ -+int hostfs_getattr(struct dentry *dentry, struct iattr *attr) -+{ -+ not_implemented(); -+ return(-EINVAL); -+} -+ -+static struct inode_operations hostfs_iops = { -+ .create = hostfs_create, -+ .link = hostfs_link, -+ .unlink = hostfs_unlink, -+ .symlink = hostfs_symlink, -+ .mkdir = hostfs_mkdir, -+ .rmdir = hostfs_rmdir, -+ .mknod = hostfs_mknod, -+ .rename = hostfs_rename, -+ .truncate = hostfs_truncate, -+ .permission = hostfs_permission, -+ .setattr = hostfs_setattr, -+ .getattr = hostfs_getattr, -+}; -+ -+static struct inode_operations hostfs_dir_iops = { -+ .create = hostfs_create, -+ .lookup = hostfs_lookup, -+ .link = hostfs_link, -+ .unlink = hostfs_unlink, -+ .symlink = hostfs_symlink, -+ .mkdir = hostfs_mkdir, -+ .rmdir = hostfs_rmdir, -+ .mknod = hostfs_mknod, -+ .rename = hostfs_rename, -+ .truncate = hostfs_truncate, -+ .permission = hostfs_permission, -+ .setattr = hostfs_setattr, -+ .getattr = hostfs_getattr, -+}; -+ -+int hostfs_link_readpage(struct file *file, struct page *page) -+{ -+ char *buffer, *name; -+ long long start; -+ int err; -+ -+ start = page->index << PAGE_CACHE_SHIFT; -+ buffer = kmap(page); -+ name = inode_name(page->mapping->host, 0); -+ if(name == NULL) return(-ENOMEM); -+ err = do_readlink(name, buffer, PAGE_CACHE_SIZE); -+ kfree(name); -+ if(err == PAGE_CACHE_SIZE) -+ err = -E2BIG; -+ else if(err > 0){ -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ if (PageError(page)) ClearPageError(page); -+ err = 0; -+ } -+ kunmap(page); -+ UnlockPage(page); -+ return(err); -+} -+ -+static struct address_space_operations hostfs_link_aops = { -+ .readpage = hostfs_link_readpage, -+}; -+ -+static char *get_root(char *mount_arg) -+{ -+ char *root, *slash = ""; -+ int len = 0; -+ -+ if(jail_dir != NULL){ -+ len += strlen(jail_dir); -+ if((*jail_dir == '\0') || -+ (jail_dir[strlen(jail_dir) - 1] != '/')) -+ slash = "/"; -+ len += strlen(slash); -+ } -+ -+ if((mount_arg == NULL) || (*mount_arg == '\0')) -+ mount_arg = DEFAULT_ROOT; -+ -+ len += strlen(mount_arg) + 1; -+ -+ root = kmalloc(len, GFP_KERNEL); -+ if(root == NULL) -+ return(NULL); -+ -+ if(jail_dir != NULL) -+ sprintf(root, "%s%s%s", jail_dir, slash, mount_arg); -+ else -+ strcpy(root, mount_arg); -+ -+ return(root); -+} -+ -+struct super_block *hostfs_read_super(struct super_block *sb, void *data, -+ int silent) -+{ -+ struct inode *root_inode; -+ char *root_dir; -+ -+ sb->s_blocksize = 1024; -+ sb->s_blocksize_bits = 10; -+ sb->s_magic = HOSTFS_SUPER_MAGIC; -+ sb->s_op = &hostfs_sbops; -+ -+ root_inode = get_inode(sb, NULL, NULL); -+ if(root_inode == NULL) -+ goto out; -+ -+ root_dir = get_root(data); -+ if(root_dir == NULL) -+ goto out_put; -+ -+ root_inode->u.hostfs_i.host_filename = root_dir; -+ sb->s_root = d_alloc_root(root_inode); -+ if(sb->s_root == NULL) -+ goto out_free; -+ -+ if(read_inode(root_inode)) -+ goto out_dput; -+ return(sb); -+ -+ out_dput: -+ dput(sb->s_root); -+ out_free: -+ kfree(root_dir); -+ out_put: -+ make_bad_inode(root_inode); -+ iput(root_inode); -+ out: -+ return(NULL); -+} -+ -+DECLARE_FSTYPE(hostfs_type, "hostfs", hostfs_read_super, 0); -+ -+static int __init init_hostfs(void) -+{ -+ return(register_filesystem(&hostfs_type)); -+} -+ -+static void __exit exit_hostfs(void) -+{ -+ unregister_filesystem(&hostfs_type); -+} -+ -+module_init(init_hostfs) -+module_exit(exit_hostfs) -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/hostfs_user.c um/arch/um/fs/hostfs/hostfs_user.c ---- orig/arch/um/fs/hostfs/hostfs_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/hostfs/hostfs_user.c 2003-11-14 08:51:20.000000000 -0500 -@@ -0,0 +1,359 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <fcntl.h> -+#include <dirent.h> -+#include <errno.h> -+#include <utime.h> -+#include <string.h> -+#include <sys/stat.h> -+#include <sys/time.h> -+#include <sys/vfs.h> -+#include "hostfs.h" -+#include "kern_util.h" -+#include "user.h" -+ -+int stat_file(const char *path, int *dev_out, unsigned long long *inode_out, -+ int *mode_out, int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, unsigned long *atime_out, -+ unsigned long *mtime_out, unsigned long *ctime_out, -+ int *blksize_out, unsigned long long *blocks_out) -+{ -+ struct stat64 buf; -+ -+ if(lstat64(path, &buf) < 0) -+ return(-errno); -+ if(dev_out != NULL) *dev_out = buf.st_dev; -+ -+ /* See the Makefile for why STAT64_INO_FIELD is passed in -+ * by the build -+ */ -+ if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD; -+ if(mode_out != NULL) *mode_out = buf.st_mode; -+ if(nlink_out != NULL) *nlink_out = buf.st_nlink; -+ if(uid_out != NULL) *uid_out = buf.st_uid; -+ if(gid_out != NULL) *gid_out = buf.st_gid; -+ if(size_out != NULL) *size_out = buf.st_size; -+ if(atime_out != NULL) *atime_out = buf.st_atime; -+ if(mtime_out != NULL) *mtime_out = buf.st_mtime; -+ if(ctime_out != NULL) *ctime_out = buf.st_ctime; -+ if(blksize_out != NULL) *blksize_out = buf.st_blksize; -+ if(blocks_out != NULL) *blocks_out = buf.st_blocks; -+ return(0); -+} -+ -+int file_type(const char *path, int *rdev) -+{ -+ struct stat64 buf; -+ -+ if(lstat64(path, &buf) < 0) -+ return(-errno); -+ if(rdev != NULL) -+ *rdev = buf.st_rdev; -+ -+ if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); -+ else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); -+ else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); -+ else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); -+ else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO); -+ else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK); -+ else return(OS_TYPE_FILE); -+} -+ -+int access_file(char *path, int r, int w, int x) -+{ -+ int mode = 0; -+ -+ if(r) mode = R_OK; -+ if(w) mode |= W_OK; -+ if(x) mode |= X_OK; -+ if(access(path, mode) != 0) return(-errno); -+ else return(0); -+} -+ -+int open_file(char *path, int r, int w, int append) -+{ -+ int mode = 0, fd; -+ -+ if(r && !w) -+ mode = O_RDONLY; -+ else if(!r && w) -+ mode = O_WRONLY; -+ else if(r && w) -+ mode = O_RDWR; -+ else panic("Impossible mode in open_file"); -+ -+ if(append) -+ mode |= O_APPEND; -+ fd = open64(path, mode); -+ if(fd < 0) return(-errno); -+ else return(fd); -+} -+ -+void *open_dir(char *path, int *err_out) -+{ -+ DIR *dir; -+ -+ dir = opendir(path); -+ *err_out = errno; -+ if(dir == NULL) return(NULL); -+ return(dir); -+} -+ -+char *read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out) -+{ -+ DIR *dir = stream; -+ struct dirent *ent; -+ -+ seekdir(dir, *pos); -+ ent = readdir(dir); -+ if(ent == NULL) return(NULL); -+ *len_out = strlen(ent->d_name); -+ *ino_out = ent->d_ino; -+ *pos = telldir(dir); -+ return(ent->d_name); -+} -+ -+int read_file(int fd, unsigned long long *offset, char *buf, int len) -+{ -+ int n, err; -+ -+ err = os_seek_file(fd, *offset); -+ if(err) -+ return(err); -+ -+ n = os_read_file(fd, buf, len); -+ if(n < 0) -+ return(n); -+ -+ *offset += n; -+ return(n); -+} -+ -+int write_file(int fd, unsigned long long *offset, const char *buf, int len) -+{ -+ int n, err; -+ -+ err = os_seek_file(fd, *offset); -+ if(err) -+ return(err); -+ -+ n = os_write_file(fd, buf, len); -+ if(n < 0) -+ return(n); -+ -+ *offset += n; -+ return(n); -+} -+ -+int lseek_file(int fd, long long offset, int whence) -+{ -+ int ret; -+ -+ ret = lseek64(fd, offset, whence); -+ if(ret < 0) return(-errno); -+ return(0); -+} -+ -+void close_file(void *stream) -+{ -+ close(*((int *) stream)); -+} -+ -+void close_dir(void *stream) -+{ -+ closedir(stream); -+} -+ -+int file_create(char *name, int ur, int uw, int ux, int gr, -+ int gw, int gx, int or, int ow, int ox) -+{ -+ int mode, fd; -+ -+ mode = 0; -+ mode |= ur ? S_IRUSR : 0; -+ mode |= uw ? S_IWUSR : 0; -+ mode |= ux ? S_IXUSR : 0; -+ mode |= gr ? S_IRGRP : 0; -+ mode |= gw ? S_IWGRP : 0; -+ mode |= gx ? S_IXGRP : 0; -+ mode |= or ? S_IROTH : 0; -+ mode |= ow ? S_IWOTH : 0; -+ mode |= ox ? S_IXOTH : 0; -+ fd = open64(name, O_CREAT | O_RDWR, mode); -+ if(fd < 0) -+ return(-errno); -+ return(fd); -+} -+ -+int set_attr(const char *file, struct hostfs_iattr *attrs) -+{ -+ struct utimbuf buf; -+ int err, ma; -+ -+ if(attrs->ia_valid & HOSTFS_ATTR_MODE){ -+ if(chmod(file, attrs->ia_mode) != 0) return(-errno); -+ } -+ if(attrs->ia_valid & HOSTFS_ATTR_UID){ -+ if(chown(file, attrs->ia_uid, -1)) return(-errno); -+ } -+ if(attrs->ia_valid & HOSTFS_ATTR_GID){ -+ if(chown(file, -1, attrs->ia_gid)) return(-errno); -+ } -+ if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ -+ if(truncate64(file, attrs->ia_size)) return(-errno); -+ } -+ ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; -+ if((attrs->ia_valid & ma) == ma){ -+ buf.actime = attrs->ia_atime; -+ buf.modtime = attrs->ia_mtime; -+ if(utime(file, &buf) != 0) return(-errno); -+ } -+ else { -+ if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ -+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, &buf.modtime, NULL, -+ NULL, NULL); -+ if(err != 0) return(err); -+ buf.actime = attrs->ia_atime; -+ if(utime(file, &buf) != 0) return(-errno); -+ } -+ if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ -+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, &buf.actime, NULL, NULL, -+ NULL, NULL); -+ if(err != 0) return(err); -+ buf.modtime = attrs->ia_mtime; -+ if(utime(file, &buf) != 0) return(-errno); -+ } -+ } -+ if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; -+ if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ -+ err = stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, &attrs->ia_atime, &attrs->ia_mtime, -+ NULL, NULL, NULL); -+ if(err != 0) return(err); -+ } -+ return(0); -+} -+ -+int make_symlink(const char *from, const char *to) -+{ -+ int err; -+ -+ err = symlink(to, from); -+ if(err) return(-errno); -+ return(0); -+} -+ -+int unlink_file(const char *file) -+{ -+ int err; -+ -+ err = unlink(file); -+ if(err) return(-errno); -+ return(0); -+} -+ -+int do_mkdir(const char *file, int mode) -+{ -+ int err; -+ -+ err = mkdir(file, mode); -+ if(err) return(-errno); -+ return(0); -+} -+ -+int do_rmdir(const char *file) -+{ -+ int err; -+ -+ err = rmdir(file); -+ if(err) return(-errno); -+ return(0); -+} -+ -+int do_mknod(const char *file, int mode, int dev) -+{ -+ int err; -+ -+ err = mknod(file, mode, dev); -+ if(err) return(-errno); -+ return(0); -+} -+ -+int link_file(const char *to, const char *from) -+{ -+ int err; -+ -+ err = link(to, from); -+ if(err) return(-errno); -+ return(0); -+} -+ -+int do_readlink(char *file, char *buf, int size) -+{ -+ int n; -+ -+ n = readlink(file, buf, size); -+ if(n < 0) -+ return(-errno); -+ if(n < size) -+ buf[n] = '\0'; -+ return(n); -+} -+ -+int rename_file(char *from, char *to) -+{ -+ int err; -+ -+ err = rename(from, to); -+ if(err < 0) return(-errno); -+ return(0); -+} -+ -+int do_statfs(char *root, long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, -+ void *fsid_out, int fsid_size, long *namelen_out, -+ long *spare_out) -+{ -+ struct statfs64 buf; -+ int err; -+ -+ err = statfs64(root, &buf); -+ if(err < 0) return(-errno); -+ *bsize_out = buf.f_bsize; -+ *blocks_out = buf.f_blocks; -+ *bfree_out = buf.f_bfree; -+ *bavail_out = buf.f_bavail; -+ *files_out = buf.f_files; -+ *ffree_out = buf.f_ffree; -+ memcpy(fsid_out, &buf.f_fsid, -+ sizeof(buf.f_fsid) > fsid_size ? fsid_size : -+ sizeof(buf.f_fsid)); -+ *namelen_out = buf.f_namelen; -+ spare_out[0] = buf.f_spare[0]; -+ spare_out[1] = buf.f_spare[1]; -+ spare_out[2] = buf.f_spare[2]; -+ spare_out[3] = buf.f_spare[3]; -+ spare_out[4] = buf.f_spare[4]; -+ spare_out[5] = buf.f_spare[5]; -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/fs/hostfs/Makefile um/arch/um/fs/hostfs/Makefile ---- orig/arch/um/fs/hostfs/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/hostfs/Makefile 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,24 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino -+# to __st_ino. It stayed in the same place, so as long as the correct name -+# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa. -+ -+STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \ -+ echo __)st_ino -+ -+USER_CFLAGS := $(USER_CFLAGS) -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD) -+ -+O_TARGET := hostfs.o -+obj-y = hostfs_kern.o hostfs_user.o -+obj-m = $(O_TARGET) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -diff -Naur -X ../exclude-files orig/arch/um/fs/hppfs/hppfs_kern.c um/arch/um/fs/hppfs/hppfs_kern.c ---- orig/arch/um/fs/hppfs/hppfs_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/hppfs/hppfs_kern.c 2004-01-08 23:35:58.000000000 -0500 -@@ -0,0 +1,737 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/fs.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/list.h> -+#include <linux/kernel.h> -+#include <linux/ctype.h> -+#include <asm/uaccess.h> -+#include "os.h" -+ -+struct hppfs_data { -+ struct list_head list; -+ char contents[PAGE_SIZE - sizeof(struct list_head)]; -+}; -+ -+struct hppfs_private { -+ struct file proc_file; -+ int host_fd; -+ loff_t len; -+ struct hppfs_data *contents; -+}; -+ -+#define HPPFS_SUPER_MAGIC 0xb00000ee -+ -+static struct super_operations hppfs_sbops; -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error); -+ -+static int is_pid(struct dentry *dentry) -+{ -+ struct super_block *sb; -+ int i; -+ -+ sb = dentry->d_sb; -+ if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) -+ return(0); -+ -+ for(i = 0; i < dentry->d_name.len; i++){ -+ if(!isdigit(dentry->d_name.name[i])) -+ return(0); -+ } -+ return(1); -+} -+ -+static char *dentry_name(struct dentry *dentry, int extra) -+{ -+ struct dentry *parent; -+ char *root, *name; -+ const char *seg_name; -+ int len, seg_len; -+ -+ len = 0; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ if(is_pid(parent)) -+ len += strlen("pid") + 1; -+ else len += parent->d_name.len + 1; -+ parent = parent->d_parent; -+ } -+ -+ root = "proc"; -+ len += strlen(root); -+ name = kmalloc(len + extra + 1, GFP_KERNEL); -+ if(name == NULL) return(NULL); -+ -+ name[len] = '\0'; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ if(is_pid(parent)){ -+ seg_name = "pid"; -+ seg_len = strlen("pid"); -+ } -+ else { -+ seg_name = parent->d_name.name; -+ seg_len = parent->d_name.len; -+ } -+ -+ len -= seg_len + 1; -+ name[len] = '/'; -+ strncpy(&name[len + 1], seg_name, seg_len); -+ parent = parent->d_parent; -+ } -+ strncpy(name, root, strlen(root)); -+ return(name); -+} -+ -+struct dentry_operations hppfs_dentry_ops = { -+}; -+ -+static int file_removed(struct dentry *dentry, const char *file) -+{ -+ char *host_file; -+ int extra, fd; -+ -+ extra = 0; -+ if(file != NULL) extra += strlen(file) + 1; -+ -+ host_file = dentry_name(dentry, extra + strlen("/remove")); -+ if(host_file == NULL){ -+ printk("file_removed : allocation failed\n"); -+ return(-ENOMEM); -+ } -+ -+ if(file != NULL){ -+ strcat(host_file, "/"); -+ strcat(host_file, file); -+ } -+ strcat(host_file, "/remove"); -+ -+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); -+ kfree(host_file); -+ if(fd >= 0){ -+ os_close_file(fd); -+ return(1); -+ } -+ return(0); -+} -+ -+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry) -+{ -+ struct dentry *proc_dentry; -+ struct inode *inode; -+ int err, deleted; -+ -+ deleted = file_removed(dentry, NULL); -+ if(deleted < 0) -+ return(ERR_PTR(deleted)); -+ else if(deleted) -+ return(ERR_PTR(-ENOENT)); -+ -+ proc_dentry = lookup_hash(&dentry->d_name, ino->u.hppfs_i.proc_dentry); -+ if(IS_ERR(proc_dentry)) -+ return(proc_dentry); -+ -+ inode = get_inode(ino->i_sb, proc_dentry, &err); -+ if(err != 0) -+ return(ERR_PTR(err)); -+ -+ d_add(dentry, inode); -+ dentry->d_op = &hppfs_dentry_ops; -+ return(NULL); -+} -+ -+static struct inode_operations hppfs_file_iops = { -+}; -+ -+static struct inode_operations hppfs_dir_iops = { -+ .lookup = hppfs_lookup, -+}; -+ -+static ssize_t read_proc(struct file *file, char *buf, ssize_t count, -+ loff_t *ppos, int is_user) -+{ -+ ssize_t (*read)(struct file *, char *, size_t, loff_t *); -+ ssize_t n; -+ -+ read = file->f_dentry->d_inode->i_fop->read; -+ if(read == NULL) -+ return(-EOPNOTSUPP); -+ -+ if(!is_user) -+ set_fs(KERNEL_DS); -+ -+ n = (*read)(file, buf, count, &file->f_pos); -+ -+ if(!is_user) -+ set_fs(USER_DS); -+ -+ if(ppos) *ppos = file->f_pos; -+ return(n); -+} -+ -+static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count) -+{ -+ ssize_t n; -+ int cur, err; -+ char *new_buf; -+ -+ n = -ENOMEM; -+ new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ if(new_buf == NULL){ -+ printk("hppfs_read_file : kmalloc failed\n"); -+ goto out; -+ } -+ n = 0; -+ while(count > 0){ -+ cur = min_t(ssize_t, count, PAGE_SIZE); -+ err = os_read_file(fd, new_buf, cur); -+ if(err < 0){ -+ printk("hppfs_read : read failed, err = %d\n", -err); -+ n = err; -+ goto out_free; -+ } -+ else if(err == 0) -+ break; -+ -+ if(copy_to_user(buf, new_buf, err)){ -+ n = -EFAULT; -+ goto out_free; -+ } -+ n += err; -+ count -= err; -+ } -+ out_free: -+ kfree(new_buf); -+ out: -+ return(n); -+} -+ -+static ssize_t hppfs_read(struct file *file, char *buf, size_t count, -+ loff_t *ppos) -+{ -+ struct hppfs_private *hppfs = file->private_data; -+ struct hppfs_data *data; -+ loff_t off; -+ int err; -+ -+ if(hppfs->contents != NULL){ -+ if(*ppos >= hppfs->len) return(0); -+ -+ data = hppfs->contents; -+ off = *ppos; -+ while(off >= sizeof(data->contents)){ -+ data = list_entry(data->list.next, struct hppfs_data, -+ list); -+ off -= sizeof(data->contents); -+ } -+ -+ if(off + count > hppfs->len) -+ count = hppfs->len - off; -+ copy_to_user(buf, &data->contents[off], count); -+ *ppos += count; -+ } -+ else if(hppfs->host_fd != -1){ -+ err = os_seek_file(hppfs->host_fd, *ppos); -+ if(err < 0){ -+ printk("hppfs_read : seek failed, err = %d\n", -err); -+ return(err); -+ } -+ count = hppfs_read_file(hppfs->host_fd, buf, count); -+ if(count > 0) -+ *ppos += count; -+ } -+ else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1); -+ -+ return(count); -+} -+ -+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, -+ loff_t *ppos) -+{ -+ struct hppfs_private *data = file->private_data; -+ struct file *proc_file = &data->proc_file; -+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *); -+ int err; -+ -+ write = proc_file->f_dentry->d_inode->i_fop->write; -+ if(write == NULL) -+ return(-EOPNOTSUPP); -+ -+ proc_file->f_pos = file->f_pos; -+ err = (*write)(proc_file, buf, len, &proc_file->f_pos); -+ file->f_pos = proc_file->f_pos; -+ -+ return(err); -+} -+ -+static int open_host_sock(char *host_file, int *filter_out) -+{ -+ char *end; -+ int fd; -+ -+ end = &host_file[strlen(host_file)]; -+ strcpy(end, "/rw"); -+ *filter_out = 1; -+ fd = os_connect_socket(host_file); -+ if(fd >= 0) -+ return(fd); -+ -+ strcpy(end, "/r"); -+ *filter_out = 0; -+ fd = os_connect_socket(host_file); -+ return(fd); -+} -+ -+static void free_contents(struct hppfs_data *head) -+{ -+ struct hppfs_data *data; -+ struct list_head *ele, *next; -+ -+ if(head == NULL) return; -+ -+ list_for_each_safe(ele, next, &head->list){ -+ data = list_entry(ele, struct hppfs_data, list); -+ kfree(data); -+ } -+ kfree(head); -+} -+ -+static struct hppfs_data *hppfs_get_data(int fd, int filter, -+ struct file *proc_file, -+ struct file *hppfs_file, -+ loff_t *size_out) -+{ -+ struct hppfs_data *data, *new, *head; -+ int n, err; -+ -+ err = -ENOMEM; -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL){ -+ printk("hppfs_get_data : head allocation failed\n"); -+ goto failed; -+ } -+ -+ INIT_LIST_HEAD(&data->list); -+ -+ head = data; -+ *size_out = 0; -+ -+ if(filter){ -+ while((n = read_proc(proc_file, data->contents, -+ sizeof(data->contents), NULL, 0)) > 0) { -+ err = os_write_file(fd, data->contents, n); -+ if(err != n) -+ printk("hppfs_get_data : failed to write out " -+ "%d bytes, err = %d\n", n, -err); -+ } -+ err = os_shutdown_socket(fd, 0, 1); -+ if(err < 0){ -+ printk("hppfs_get_data : failed to shut down " -+ "socket\n"); -+ goto failed_free; -+ } -+ } -+ while(1){ -+ n = os_read_file(fd, data->contents, sizeof(data->contents)); -+ if(n < 0){ -+ err = n; -+ printk("hppfs_get_data : read failed, err = %d\n", -n); -+ goto failed_free; -+ } -+ else if(n == 0) -+ break; -+ -+ *size_out += n; -+ -+ if(n < sizeof(data->contents)) -+ break; -+ -+ new = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(new == 0){ -+ printk("hppfs_get_data : data allocation failed\n"); -+ err = -ENOMEM; -+ goto failed_free; -+ } -+ -+ INIT_LIST_HEAD(&new->list); -+ list_add(&new->list, &data->list); -+ data = new; -+ } -+ return(head); -+ -+ failed_free: -+ free_contents(head); -+ failed: -+ return(ERR_PTR(err)); -+} -+ -+static struct hppfs_private *hppfs_data(void) -+{ -+ struct hppfs_private *data; -+ -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL) -+ return(data); -+ -+ *data = ((struct hppfs_private ) { .host_fd = -1, -+ .len = -1, -+ .contents = NULL } ); -+ return(data); -+} -+ -+static int hppfs_open(struct inode *inode, struct file *file) -+{ -+ struct hppfs_private *data; -+ struct dentry *proc_dentry; -+ char *host_file; -+ int err, fd, type, filter; -+ -+ err = -ENOMEM; -+ data = hppfs_data(); -+ if(data == NULL) -+ goto out; -+ -+ host_file = dentry_name(file->f_dentry, strlen("/rw")); -+ if(host_file == NULL) -+ goto out_free2; -+ -+ proc_dentry = inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&data->proc_file, proc_dentry, file->f_mode); -+ if(err) -+ goto out_free1; -+ -+ type = os_file_type(host_file); -+ if(type == OS_TYPE_FILE){ -+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); -+ if(fd >= 0) -+ data->host_fd = fd; -+ else printk("hppfs_open : failed to open '%s', err = %d\n", -+ host_file, -fd); -+ -+ data->contents = NULL; -+ } -+ else if(type == OS_TYPE_DIR){ -+ fd = open_host_sock(host_file, &filter); -+ if(fd >= 0){ -+ data->contents = hppfs_get_data(fd, filter, -+ &data->proc_file, -+ file, &data->len); -+ if(!IS_ERR(data->contents)) -+ data->host_fd = fd; -+ } -+ else printk("hppfs_open : failed to open a socket in " -+ "'%s', err = %d\n", host_file, -fd); -+ } -+ kfree(host_file); -+ -+ file->private_data = data; -+ return(0); -+ -+ out_free1: -+ kfree(host_file); -+ out_free2: -+ free_contents(data->contents); -+ kfree(data); -+ out: -+ return(err); -+} -+ -+static int hppfs_dir_open(struct inode *inode, struct file *file) -+{ -+ struct hppfs_private *data; -+ struct dentry *proc_dentry; -+ int err; -+ -+ err = -ENOMEM; -+ data = hppfs_data(); -+ if(data == NULL) -+ goto out; -+ -+ proc_dentry = inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&data->proc_file, proc_dentry, file->f_mode); -+ if(err) -+ goto out_free; -+ -+ file->private_data = data; -+ return(0); -+ -+ out_free: -+ kfree(data); -+ out: -+ return(err); -+} -+ -+static loff_t hppfs_llseek(struct file *file, loff_t off, int where) -+{ -+ struct hppfs_private *data = file->private_data; -+ struct file *proc_file = &data->proc_file; -+ loff_t (*llseek)(struct file *, loff_t, int); -+ loff_t ret; -+ -+ llseek = proc_file->f_dentry->d_inode->i_fop->llseek; -+ if(llseek != NULL){ -+ ret = (*llseek)(proc_file, off, where); -+ if(ret < 0) -+ return(ret); -+ } -+ -+ return(default_llseek(file, off, where)); -+} -+ -+struct hppfs_dirent { -+ void *vfs_dirent; -+ filldir_t filldir; -+ struct dentry *dentry; -+}; -+ -+static int hppfs_filldir(void *d, const char *name, int size, -+ loff_t offset, ino_t inode, unsigned int type) -+{ -+ struct hppfs_dirent *dirent = d; -+ -+ if(file_removed(dirent->dentry, name)) -+ return(0); -+ -+ return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, -+ inode, type)); -+} -+ -+static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) -+{ -+ struct hppfs_private *data = file->private_data; -+ struct file *proc_file = &data->proc_file; -+ int (*readdir)(struct file *, void *, filldir_t); -+ struct hppfs_dirent dirent = ((struct hppfs_dirent) -+ { .vfs_dirent = ent, -+ .filldir = filldir, -+ .dentry = file->f_dentry } ); -+ int err; -+ -+ readdir = proc_file->f_dentry->d_inode->i_fop->readdir; -+ if(readdir == NULL) -+ return(-EOPNOTSUPP); -+ -+ proc_file->f_pos = file->f_pos; -+ err = (*readdir)(proc_file, &dirent, hppfs_filldir); -+ file->f_pos = proc_file->f_pos; -+ -+ return(err); -+} -+ -+static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) -+{ -+ return(0); -+} -+ -+static struct file_operations hppfs_file_fops = { -+ .owner = NULL, -+ .llseek = hppfs_llseek, -+ .read = hppfs_read, -+ .write = hppfs_write, -+ .open = hppfs_open, -+}; -+ -+static struct file_operations hppfs_dir_fops = { -+ .owner = NULL, -+ .readdir = hppfs_readdir, -+ .open = hppfs_dir_open, -+ .fsync = hppfs_fsync, -+}; -+ -+static int hppfs_statfs(struct super_block *sb, struct statfs *sf) -+{ -+ sf->f_blocks = 0; -+ sf->f_bfree = 0; -+ sf->f_bavail = 0; -+ sf->f_files = 0; -+ sf->f_ffree = 0; -+ sf->f_type = HPPFS_SUPER_MAGIC; -+ return(0); -+} -+ -+static struct super_operations hppfs_sbops = { -+ .put_inode = force_delete, -+ .delete_inode = NULL, -+ .statfs = hppfs_statfs, -+}; -+ -+static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen) -+{ -+ struct file proc_file; -+ struct dentry *proc_dentry; -+ int (*readlink)(struct dentry *, char *, int); -+ int err, n; -+ -+ proc_dentry = dentry->d_inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ); -+ if(err) -+ return(err); -+ -+ readlink = proc_dentry->d_inode->i_op->readlink; -+ if(readlink == NULL) -+ return(-EOPNOTSUPP); -+ n = (*readlink)(proc_dentry, buffer, buflen); -+ -+ if(proc_file.f_op->release) -+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file); -+ -+ return(n); -+} -+ -+static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) -+{ -+ struct file proc_file; -+ struct dentry *proc_dentry; -+ int (*follow_link)(struct dentry *, struct nameidata *); -+ int err, n; -+ -+ proc_dentry = dentry->d_inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ); -+ if(err) -+ return(err); -+ -+ follow_link = proc_dentry->d_inode->i_op->follow_link; -+ if(follow_link == NULL) -+ return(-EOPNOTSUPP); -+ n = (*follow_link)(proc_dentry, nd); -+ -+ if(proc_file.f_op->release) -+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file); -+ -+ return(n); -+} -+ -+static struct inode_operations hppfs_link_iops = { -+ .readlink = hppfs_readlink, -+ .follow_link = hppfs_follow_link, -+}; -+ -+static void read_inode(struct inode *ino) -+{ -+ struct inode *proc_ino; -+ -+ proc_ino = ino->u.hppfs_i.proc_dentry->d_inode; -+ ino->i_uid = proc_ino->i_uid; -+ ino->i_gid = proc_ino->i_gid; -+ ino->i_atime = proc_ino->i_atime; -+ ino->i_mtime = proc_ino->i_mtime; -+ ino->i_ctime = proc_ino->i_ctime; -+ ino->i_ino = proc_ino->i_ino; -+ ino->i_dev = proc_ino->i_dev; -+ ino->i_mode = proc_ino->i_mode; -+ ino->i_nlink = proc_ino->i_nlink; -+ ino->i_size = proc_ino->i_size; -+ ino->i_blksize = proc_ino->i_blksize; -+ ino->i_blocks = proc_ino->i_blocks; -+} -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error) -+{ -+ struct inode *inode; -+ int err = -ENOMEM; -+ -+ inode = new_inode(sb); -+ if(inode == NULL) -+ goto out; -+ -+ insert_inode_hash(inode); -+ if(S_ISDIR(dentry->d_inode->i_mode)){ -+ inode->i_op = &hppfs_dir_iops; -+ inode->i_fop = &hppfs_dir_fops; -+ } -+ else if(S_ISLNK(dentry->d_inode->i_mode)){ -+ inode->i_op = &hppfs_link_iops; -+ inode->i_fop = &hppfs_file_fops; -+ } -+ else { -+ inode->i_op = &hppfs_file_iops; -+ inode->i_fop = &hppfs_file_fops; -+ } -+ -+ inode->i_sb = sb; -+ inode->u.hppfs_i.proc_dentry = dentry; -+ -+ read_inode(inode); -+ err = 0; -+ -+ if(error) *error = err; -+ return(inode); -+ out: -+ if(error) *error = err; -+ return(NULL); -+} -+ -+static struct super_block *hppfs_read_super(struct super_block *sb, void *d, -+ int silent) -+{ -+ struct inode *root_inode; -+ struct file_system_type *procfs; -+ struct super_block *proc_sb; -+ -+ procfs = get_fs_type("proc"); -+ if(procfs == NULL) -+ goto out; -+ -+ if(list_empty(&procfs->fs_supers)) -+ goto out; -+ -+ proc_sb = list_entry(procfs->fs_supers.next, struct super_block, -+ s_instances); -+ -+ sb->s_blocksize = 1024; -+ sb->s_blocksize_bits = 10; -+ sb->s_magic = HPPFS_SUPER_MAGIC; -+ sb->s_op = &hppfs_sbops; -+ -+ dget(proc_sb->s_root); -+ root_inode = get_inode(sb, proc_sb->s_root, NULL); -+ if(root_inode == NULL) -+ goto out_dput; -+ -+ sb->s_root = d_alloc_root(root_inode); -+ if(sb->s_root == NULL) -+ goto out_put; -+ -+ return(sb); -+ -+ out_put: -+ iput(root_inode); -+ out_dput: -+ dput(proc_sb->s_root); -+ out: -+ return(NULL); -+} -+ -+DECLARE_FSTYPE(hppfs_type, "hppfs", hppfs_read_super, 0); -+ -+static int __init init_hppfs(void) -+{ -+ return(register_filesystem(&hppfs_type)); -+} -+ -+static void __exit exit_hppfs(void) -+{ -+ unregister_filesystem(&hppfs_type); -+} -+ -+module_init(init_hppfs) -+module_exit(exit_hppfs) -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/fs/hppfs/Makefile um/arch/um/fs/hppfs/Makefile ---- orig/arch/um/fs/hppfs/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/hppfs/Makefile 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,10 @@ -+O_TARGET := hppfs.o -+obj-y = hppfs_kern.o #hppfs_user.o -+obj-m = $(O_TARGET) -+ -+CFLAGS_hppfs_kern.o := $(CFLAGS) -+#CFLAGS_hppfs_user.o := $(USER_CFLAGS) -+ -+override CFLAGS = -+ -+include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/arch/um/fs/Makefile um/arch/um/fs/Makefile ---- orig/arch/um/fs/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/fs/Makefile 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,23 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := built-in.o -+ -+subdir-y = -+subdir-m = -+ -+subdir-$(CONFIG_HOSTFS) += hostfs -+subdir-$(CONFIG_HPPFS) += hppfs -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+obj-m += $(join $(subdir-m),$(subdir-m:%=/%.o)) -+ -+include $(TOPDIR)/Rules.make -+ -+dep: -+ -+clean: -+ -+archmrproper: -diff -Naur -X ../exclude-files orig/arch/um/include/2_5compat.h um/arch/um/include/2_5compat.h ---- orig/arch/um/include/2_5compat.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/2_5compat.h 2003-11-07 02:49:26.000000000 -0500 -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __2_5_COMPAT_H__ -+#define __2_5_COMPAT_H__ -+ -+#include "linux/version.h" -+ -+#define INIT_ELV(queue, elv) elevator_init(elv, ELV_NOOP) -+ -+#define ELV_NOOP ELEVATOR_NOOP -+ -+#define INIT_HARDSECT(arr, maj, sizes) arr[maj] = sizes -+ -+#define IS_WRITE(req) ((req)->cmd == WRITE) -+ -+#define SET_PRI(task) \ -+ do { (task)->nice = 20; (task)->counter = -100; } while(0); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/chan_kern.h um/arch/um/include/chan_kern.h ---- orig/arch/um/include/chan_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/chan_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHAN_KERN_H__ -+#define __CHAN_KERN_H__ -+ -+#include "linux/tty.h" -+#include "linux/list.h" -+#include "chan_user.h" -+ -+struct chan { -+ struct list_head list; -+ char *dev; -+ unsigned int primary:1; -+ unsigned int input:1; -+ unsigned int output:1; -+ unsigned int opened:1; -+ int fd; -+ enum chan_init_pri pri; -+ struct chan_ops *ops; -+ void *data; -+}; -+ -+extern void chan_interrupt(struct list_head *chans, struct tq_struct *task, -+ struct tty_struct *tty, int irq, void *dev); -+extern int parse_chan_pair(char *str, struct list_head *chans, int pri, -+ int device, struct chan_opts *opts); -+extern int open_chan(struct list_head *chans); -+extern int write_chan(struct list_head *chans, const char *buf, int len, -+ int write_irq); -+extern int console_write_chan(struct list_head *chans, const char *buf, -+ int len); -+extern void close_chan(struct list_head *chans); -+extern void chan_enable_winch(struct list_head *chans, void *line); -+extern void enable_chan(struct list_head *chans, void *data); -+extern int chan_window_size(struct list_head *chans, -+ unsigned short *rows_out, -+ unsigned short *cols_out); -+extern int chan_out_fd(struct list_head *chans); -+extern int chan_config_string(struct list_head *chans, char *str, int size, -+ char **error_out); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/chan_user.h um/arch/um/include/chan_user.h ---- orig/arch/um/include/chan_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/chan_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHAN_USER_H__ -+#define __CHAN_USER_H__ -+ -+#include "init.h" -+ -+struct chan_opts { -+ void (*announce)(char *dev_name, int dev); -+ char *xterm_title; -+ int raw; -+ unsigned long tramp_stack; -+ int in_kernel; -+}; -+ -+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; -+ -+struct chan_ops { -+ char *type; -+ void *(*init)(char *, int, struct chan_opts *); -+ int (*open)(int, int, int, void *, char **); -+ void (*close)(int, void *); -+ int (*read)(int, char *, void *); -+ int (*write)(int, const char *, int, void *); -+ int (*console_write)(int, const char *, int, void *); -+ int (*window_size)(int, void *, unsigned short *, unsigned short *); -+ void (*free)(void *); -+ int winch; -+}; -+ -+extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, -+ xterm_ops; -+ -+extern void generic_close(int fd, void *unused); -+extern int generic_read(int fd, char *c_out, void *unused); -+extern int generic_write(int fd, const char *buf, int n, void *unused); -+extern int generic_console_write(int fd, const char *buf, int n, void *state); -+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, -+ unsigned short *cols_out); -+extern void generic_free(void *data); -+ -+extern void register_winch(int fd, void *device_data); -+extern void register_winch_irq(int fd, int tty_fd, int pid, void *line); -+ -+#define __channel_help(fn, prefix) \ -+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \ -+" Attach a console or serial line to a host channel. See\n" \ -+" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \ -+" description of this switch.\n\n" \ -+); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/choose-mode.h um/arch/um/include/choose-mode.h ---- orig/arch/um/include/choose-mode.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/choose-mode.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHOOSE_MODE_H__ -+#define __CHOOSE_MODE_H__ -+ -+#include "uml-config.h" -+ -+#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS) -+#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas)) -+ -+#elif defined(UML_CONFIG_MODE_SKAS) -+#define CHOOSE_MODE(tt, skas) (skas) -+ -+#elif defined(UML_CONFIG_MODE_TT) -+#define CHOOSE_MODE(tt, skas) (tt) -+#endif -+ -+#define CHOOSE_MODE_PROC(tt, skas, args...) \ -+ CHOOSE_MODE(tt(args), skas(args)) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/frame.h um/arch/um/include/frame.h ---- orig/arch/um/include/frame.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/frame.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_H_ -+#define __FRAME_H_ -+ -+#include "sysdep/frame.h" -+ -+struct frame_common { -+ void *data; -+ int len; -+ int sig_index; -+ int sr_index; -+ int sr_relative; -+ int sp_index; -+ struct arch_frame_data arch; -+}; -+ -+struct sc_frame { -+ struct frame_common common; -+ int sc_index; -+}; -+ -+extern struct sc_frame signal_frame_sc; -+ -+extern struct sc_frame signal_frame_sc_sr; -+ -+struct si_frame { -+ struct frame_common common; -+ int sip_index; -+ int si_index; -+ int ucp_index; -+ int uc_index; -+}; -+ -+extern struct si_frame signal_frame_si; -+ -+extern void capture_signal_stack(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/frame_kern.h um/arch/um/include/frame_kern.h ---- orig/arch/um/include/frame_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/frame_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_KERN_H_ -+#define __FRAME_KERN_H_ -+ -+#include "frame.h" -+#include "sysdep/frame_kern.h" -+ -+extern int setup_signal_stack_sc(unsigned long stack_top, int sig, -+ unsigned long handler, -+ void (*restorer)(void), -+ struct pt_regs *regs, -+ sigset_t *mask); -+extern int setup_signal_stack_si(unsigned long stack_top, int sig, -+ unsigned long handler, -+ void (*restorer)(void), -+ struct pt_regs *regs, siginfo_t *info, -+ sigset_t *mask); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/frame_user.h um/arch/um/include/frame_user.h ---- orig/arch/um/include/frame_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/frame_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_USER_H_ -+#define __FRAME_USER_H_ -+ -+#include "sysdep/frame_user.h" -+#include "frame.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/helper.h um/arch/um/include/helper.h ---- orig/arch/um/include/helper.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/helper.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __HELPER_H__ -+#define __HELPER_H__ -+ -+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, -+ unsigned long *stack_out); -+extern int run_helper_thread(int (*proc)(void *), void *arg, -+ unsigned int flags, unsigned long *stack_out, -+ int stack_order); -+extern int helper_wait(int pid); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/init.h um/arch/um/include/init.h ---- orig/arch/um/include/init.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/init.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,114 @@ -+#ifndef _LINUX_UML_INIT_H -+#define _LINUX_UML_INIT_H -+ -+/* These macros are used to mark some functions or -+ * initialized data (doesn't apply to uninitialized data) -+ * as `initialization' functions. The kernel can take this -+ * as hint that the function is used only during the initialization -+ * phase and free up used memory resources after -+ * -+ * Usage: -+ * For functions: -+ * -+ * You should add __init immediately before the function name, like: -+ * -+ * static void __init initme(int x, int y) -+ * { -+ * extern int z; z = x * y; -+ * } -+ * -+ * If the function has a prototype somewhere, you can also add -+ * __init between closing brace of the prototype and semicolon: -+ * -+ * extern int initialize_foobar_device(int, int, int) __init; -+ * -+ * For initialized data: -+ * You should insert __initdata between the variable name and equal -+ * sign followed by value, e.g.: -+ * -+ * static int init_variable __initdata = 0; -+ * static char linux_logo[] __initdata = { 0x32, 0x36, ... }; -+ * -+ * Don't forget to initialize data not at file scope, i.e. within a function, -+ * as gcc otherwise puts the data into the bss section and not into the init -+ * section. -+ * -+ * Also note, that this data cannot be "const". -+ */ -+ -+#ifndef _LINUX_INIT_H -+typedef int (*initcall_t)(void); -+typedef void (*exitcall_t)(void); -+ -+#define __init __attribute__ ((__section__ (".text.init"))) -+#define __exit __attribute__ ((unused, __section__(".text.exit"))) -+#define __initdata __attribute__ ((__section__ (".data.init"))) -+ -+#endif -+ -+#ifndef MODULE -+struct uml_param { -+ const char *str; -+ int (*setup_func)(char *, int *); -+}; -+ -+extern initcall_t __uml_initcall_start, __uml_initcall_end; -+extern initcall_t __uml_postsetup_start, __uml_postsetup_end; -+extern const char *__uml_help_start, *__uml_help_end; -+#endif -+ -+#define __uml_initcall(fn) \ -+ static initcall_t __uml_initcall_##fn __uml_init_call = fn -+ -+#define __uml_exitcall(fn) \ -+ static exitcall_t __uml_exitcall_##fn __uml_exit_call = fn -+ -+extern struct uml_param __uml_setup_start, __uml_setup_end; -+ -+#define __uml_postsetup(fn) \ -+ static initcall_t __uml_postsetup_##fn __uml_postsetup_call = fn -+ -+#define __non_empty_string(dummyname,string) \ -+ struct __uml_non_empty_string_struct_##dummyname \ -+ { \ -+ char _string[sizeof(string)-2]; \ -+ } -+ -+#ifndef MODULE -+#define __uml_setup(str, fn, help...) \ -+ __non_empty_string(fn ##_setup, str); \ -+ __uml_help(fn, help); \ -+ static char __uml_setup_str_##fn[] __initdata = str; \ -+ static struct uml_param __uml_setup_##fn __uml_init_setup = { __uml_setup_str_##fn, fn } -+#else -+#define __uml_setup(str, fn, help...) \ -+ -+#endif -+ -+#define __uml_help(fn, help...) \ -+ __non_empty_string(fn ##__help, help); \ -+ static char __uml_help_str_##fn[] __initdata = help; \ -+ static const char *__uml_help_##fn __uml_setup_help = __uml_help_str_##fn -+ -+/* -+ * Mark functions and data as being only used at initialization -+ * or exit time. -+ */ -+#define __uml_init_setup __attribute__ ((unused,__section__ (".uml.setup.init"))) -+#define __uml_setup_help __attribute__ ((unused,__section__ (".uml.help.init"))) -+#define __uml_init_call __attribute__ ((unused,__section__ (".uml.initcall.init"))) -+#define __uml_postsetup_call __attribute__ ((unused,__section__ (".uml.postsetup.init"))) -+#define __uml_exit_call __attribute__ ((unused,__section__ (".uml.exitcall.exit"))) -+ -+#endif /* _LINUX_UML_INIT_H */ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/initrd.h um/arch/um/include/initrd.h ---- orig/arch/um/include/initrd.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/initrd.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __INITRD_USER_H__ -+#define __INITRD_USER_H__ -+ -+extern int load_initrd(char *filename, void *buf, int size); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/irq_kern.h um/arch/um/include/irq_kern.h ---- orig/arch/um/include/irq_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/irq_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __IRQ_KERN_H__ -+#define __IRQ_KERN_H__ -+ -+#include "linux/interrupt.h" -+ -+extern int um_request_irq(unsigned int irq, int fd, int type, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, const char * devname, -+ void *dev_id); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/irq_user.h um/arch/um/include/irq_user.h ---- orig/arch/um/include/irq_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/irq_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __IRQ_USER_H__ -+#define __IRQ_USER_H__ -+ -+enum { IRQ_READ, IRQ_WRITE }; -+ -+extern void sigio_handler(int sig, union uml_pt_regs *regs); -+extern int activate_fd(int irq, int fd, int type, void *dev_id); -+extern void free_irq_by_irq_and_dev(int irq, void *dev_id); -+extern void free_irq_by_fd(int fd); -+extern void reactivate_fd(int fd, int irqnum); -+extern void deactivate_fd(int fd, int irqnum); -+extern void forward_interrupts(int pid); -+extern void init_irq_signals(int on_sigstack); -+extern void forward_ipi(int fd, int pid); -+extern void free_irq_later(int irq, void *dev_id); -+extern int activate_ipi(int fd, int pid); -+extern unsigned long irq_lock(void); -+extern void irq_unlock(unsigned long flags); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/kern.h um/arch/um/include/kern.h ---- orig/arch/um/include/kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __KERN_H__ -+#define __KERN_H__ -+ -+/* These are all user-mode things which are convenient to call directly -+ * from kernel code and for which writing a wrapper is too much of a pain. -+ * The regular include files can't be included because this file is included -+ * only into kernel code, and user-space includes conflict with kernel -+ * includes. -+ */ -+ -+extern int errno; -+ -+extern int clone(int (*proc)(void *), void *sp, int flags, void *data); -+extern int sleep(int); -+extern int printf(char *fmt, ...); -+extern char *strerror(int errnum); -+extern char *ptsname(int __fd); -+extern int munmap(void *, int); -+extern void *sbrk(int increment); -+extern void *malloc(int size); -+extern void perror(char *err); -+extern int kill(int pid, int sig); -+extern int getuid(void); -+extern int pause(void); -+extern int write(int, const void *, int); -+extern int exit(int); -+extern int close(int); -+extern int read(unsigned int, char *, int); -+extern int pipe(int *); -+extern int sched_yield(void); -+extern int ptrace(int op, int pid, long addr, long data); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/kern_util.h um/arch/um/include/kern_util.h ---- orig/arch/um/include/kern_util.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/kern_util.h 2003-11-10 00:58:10.000000000 -0500 -@@ -0,0 +1,123 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __KERN_UTIL_H__ -+#define __KERN_UTIL_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int ncpus; -+extern char *linux_prog; -+extern char *gdb_init; -+extern int kmalloc_ok; -+extern int timer_irq_inited; -+extern int jail; -+extern int nsyscalls; -+ -+#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) -+#define UML_ROUND_UP(addr) \ -+ UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) -+ -+extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); -+extern unsigned long stack_sp(unsigned long page); -+extern int kernel_thread_proc(void *data); -+extern void syscall_segv(int sig); -+extern int current_pid(void); -+extern unsigned long alloc_stack(int order, int atomic); -+extern int do_signal(int error); -+extern int is_stack_fault(unsigned long sp); -+extern unsigned long segv(unsigned long address, unsigned long ip, -+ int is_write, int is_user, void *sc); -+extern unsigned long handle_page_fault(unsigned long address, unsigned long ip, -+ int is_write, int is_user, -+ int *code_out); -+extern void syscall_ready(void); -+extern int segv_syscall(void); -+extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); -+extern int page_size(void); -+extern int page_mask(void); -+extern int need_finish_fork(void); -+extern void free_stack(unsigned long stack, int order); -+extern void add_input_request(int op, void (*proc)(int), void *arg); -+extern int sys_execve(char *file, char **argv, char **env); -+extern char *current_cmd(void); -+extern void timer_handler(int sig, union uml_pt_regs *regs); -+extern int set_signals(int enable); -+extern void force_sigbus(void); -+extern int pid_to_processor_id(int pid); -+extern void block_signals(void); -+extern void unblock_signals(void); -+extern void deliver_signals(void *t); -+extern int next_syscall_index(int max); -+extern int next_trap_index(int max); -+extern void cpu_idle(void); -+extern void finish_fork(void); -+extern void paging_init(void); -+extern void init_flush_vm(void); -+extern void *syscall_sp(void *t); -+extern void syscall_trace(void); -+extern int hz(void); -+extern void idle_timer(void); -+extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); -+extern int external_pid(void *t); -+extern void boot_timer_handler(int sig); -+extern void interrupt_end(void); -+extern void initial_thread_cb(void (*proc)(void *), void *arg); -+extern int debugger_signal(int status, int pid); -+extern void debugger_parent_signal(int status, int pid); -+extern void child_signal(int pid, int status); -+extern int init_ptrace_proxy(int idle_pid, int startup, int stop); -+extern int init_parent_proxy(int pid); -+extern void check_stack_overflow(void *ptr); -+extern void relay_signal(int sig, union uml_pt_regs *regs); -+extern void not_implemented(void); -+extern int user_context(unsigned long sp); -+extern void timer_irq(union uml_pt_regs *regs); -+extern void unprotect_stack(unsigned long stack); -+extern void do_uml_exitcalls(void); -+extern int attach_debugger(int idle_pid, int pid, int stop); -+extern void bad_segv(unsigned long address, unsigned long ip, int is_write); -+extern int config_gdb(char *str); -+extern int remove_gdb(void); -+extern char *uml_strdup(char *string); -+extern void unprotect_kernel_mem(void); -+extern void protect_kernel_mem(void); -+extern void set_kmem_end(unsigned long); -+extern void uml_cleanup(void); -+extern void set_current(void *t); -+extern void lock_signalled_task(void *t); -+extern void IPI_handler(int cpu); -+extern int jail_setup(char *line, int *add); -+extern void *get_init_task(void); -+extern int clear_user_proc(void *buf, int size); -+extern int copy_to_user_proc(void *to, void *from, int size); -+extern int copy_from_user_proc(void *to, void *from, int size); -+extern int strlen_user_proc(char *str); -+extern void bus_handler(int sig, union uml_pt_regs *regs); -+extern void winch(int sig, union uml_pt_regs *regs); -+extern long execute_syscall(void *r); -+extern int smp_sigio_handler(void); -+extern void *get_current(void); -+extern struct task_struct *get_task(int pid, int require); -+extern void machine_halt(void); -+extern int is_syscall(unsigned long addr); -+extern void arch_switch(void); -+extern void free_irq(unsigned int, void *); -+extern int um_in_interrupt(void); -+extern int cpu(void); -+extern unsigned long long time_stamp(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/line.h um/arch/um/include/line.h ---- orig/arch/um/include/line.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/line.h 2003-11-07 02:25:37.000000000 -0500 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __LINE_H__ -+#define __LINE_H__ -+ -+#include "linux/list.h" -+#include "linux/tqueue.h" -+#include "linux/tty.h" -+#include "asm/semaphore.h" -+#include "chan_user.h" -+#include "mconsole_kern.h" -+ -+struct line_driver { -+ char *name; -+ char *devfs_name; -+ short major; -+ short minor_start; -+ short type; -+ short subtype; -+ int read_irq; -+ char *read_irq_name; -+ int write_irq; -+ char *write_irq_name; -+ char *symlink_from; -+ char *symlink_to; -+ struct mc_device mc; -+}; -+ -+struct line { -+ char *init_str; -+ int init_pri; -+ struct list_head chan_list; -+ int valid; -+ int count; -+ struct tty_struct *tty; -+ struct semaphore sem; -+ char *buffer; -+ char *head; -+ char *tail; -+ int sigio; -+ struct tq_struct task; -+ struct line_driver *driver; -+ int have_irq; -+}; -+ -+#define LINE_INIT(str, d) \ -+ { init_str : str, \ -+ init_pri : INIT_STATIC, \ -+ chan_list : { }, \ -+ valid : 1, \ -+ count : 0, \ -+ tty : NULL, \ -+ sem : { }, \ -+ buffer : NULL, \ -+ head : NULL, \ -+ tail : NULL, \ -+ sigio : 0, \ -+ driver : d, \ -+ have_irq : 0 } -+ -+struct lines { -+ int num; -+}; -+ -+#define LINES_INIT(n) { num : n } -+ -+extern void line_close(struct line *lines, struct tty_struct *tty); -+extern int line_open(struct line *lines, struct tty_struct *tty, -+ struct chan_opts *opts); -+extern int line_setup(struct line *lines, int num, char *init, -+ int all_allowed); -+extern int line_write(struct line *line, struct tty_struct *tty, int from_user, -+ const char *buf, int len); -+extern char *add_xterm_umid(char *base); -+extern int line_setup_irq(int fd, int input, int output, void *data); -+extern void line_close_chan(struct line *line); -+extern void line_disable(struct line *line, int current_irq); -+extern void line_register_devfs(struct lines *set, -+ struct line_driver *line_driver, -+ struct tty_driver *driver, struct line *lines, -+ int nlines); -+extern void lines_init(struct line *lines, int nlines); -+extern void close_lines(struct line *lines, int nlines); -+extern int line_config(struct line *lines, int num, char *str); -+extern int line_remove(struct line *lines, int num, char *str); -+extern int line_get_config(char *dev, struct line *lines, int num, char *str, -+ int size, char **error_out); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/Makefile um/arch/um/include/Makefile ---- orig/arch/um/include/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/Makefile 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,7 @@ -+all : sc.h -+ -+sc.h : ../util/mk_sc -+ ../util/mk_sc > $@ -+ -+../util/mk_sc : -+ $(MAKE) -C ../util mk_sc -diff -Naur -X ../exclude-files orig/arch/um/include/mconsole.h um/arch/um/include/mconsole.h ---- orig/arch/um/include/mconsole.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mconsole.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MCONSOLE_H__ -+#define __MCONSOLE_H__ -+ -+#ifndef __KERNEL__ -+#include <stdint.h> -+#define u32 uint32_t -+#endif -+ -+#define MCONSOLE_MAGIC (0xcafebabe) -+#define MCONSOLE_MAX_DATA (512) -+#define MCONSOLE_VERSION 2 -+ -+struct mconsole_request { -+ u32 magic; -+ u32 version; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mconsole_reply { -+ u32 err; -+ u32 more; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mconsole_notify { -+ u32 magic; -+ u32 version; -+ enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, -+ MCONSOLE_USER_NOTIFY } type; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mc_request; -+ -+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC }; -+ -+struct mconsole_command -+{ -+ char *command; -+ void (*handler)(struct mc_request *req); -+ enum mc_context context; -+}; -+ -+struct mc_request -+{ -+ int len; -+ int as_interrupt; -+ -+ int originating_fd; -+ int originlen; -+ unsigned char origin[128]; /* sockaddr_un */ -+ -+ struct mconsole_request request; -+ struct mconsole_command *cmd; -+}; -+ -+extern char mconsole_socket_name[]; -+ -+extern int mconsole_unlink_socket(void); -+extern int mconsole_reply(struct mc_request *req, char *reply, int err, -+ int more); -+ -+extern void mconsole_version(struct mc_request *req); -+extern void mconsole_help(struct mc_request *req); -+extern void mconsole_halt(struct mc_request *req); -+extern void mconsole_reboot(struct mc_request *req); -+extern void mconsole_config(struct mc_request *req); -+extern void mconsole_remove(struct mc_request *req); -+extern void mconsole_sysrq(struct mc_request *req); -+extern void mconsole_cad(struct mc_request *req); -+extern void mconsole_stop(struct mc_request *req); -+extern void mconsole_go(struct mc_request *req); -+extern void mconsole_log(struct mc_request *req); -+extern void mconsole_proc(struct mc_request *req); -+ -+extern int mconsole_get_request(int fd, struct mc_request *req); -+extern int mconsole_notify(char *sock_name, int type, const void *data, -+ int len); -+extern char *mconsole_notify_socket(void); -+extern void lock_notify(void); -+extern void unlock_notify(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/mconsole_kern.h um/arch/um/include/mconsole_kern.h ---- orig/arch/um/include/mconsole_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mconsole_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MCONSOLE_KERN_H__ -+#define __MCONSOLE_KERN_H__ -+ -+#include "linux/config.h" -+#include "linux/list.h" -+#include "mconsole.h" -+ -+struct mconsole_entry { -+ struct list_head list; -+ struct mc_request request; -+}; -+ -+struct mc_device { -+ struct list_head list; -+ char *name; -+ int (*config)(char *); -+ int (*get_config)(char *, char *, int, char **); -+ int (*remove)(char *); -+}; -+ -+#define CONFIG_CHUNK(str, size, current, chunk, end) \ -+do { \ -+ current += strlen(chunk); \ -+ if(current >= size) \ -+ str = NULL; \ -+ if(str != NULL){ \ -+ strcpy(str, chunk); \ -+ str += strlen(chunk); \ -+ } \ -+ if(end) \ -+ current++; \ -+} while(0) -+ -+#ifdef CONFIG_MCONSOLE -+ -+extern void mconsole_register_dev(struct mc_device *new); -+ -+#else -+ -+static inline void mconsole_register_dev(struct mc_device *new) -+{ -+} -+ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/mem.h um/arch/um/include/mem.h ---- orig/arch/um/include/mem.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mem.h 2004-01-16 11:14:38.000000000 -0500 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MEM_H__ -+#define __MEM_H__ -+ -+#include "linux/types.h" -+ -+extern void set_kmem_end(unsigned long new); -+extern int phys_mapping(unsigned long phys, __u64 *offset_out); -+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); -+extern int is_remapped(void *virt); -+extern int physmem_remove_mapping(void *virt); -+extern void physmem_forget_descriptor(int fd); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/mem_kern.h um/arch/um/include/mem_kern.h ---- orig/arch/um/include/mem_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mem_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MEM_KERN_H__ -+#define __MEM_KERN_H__ -+ -+#include "linux/list.h" -+#include "linux/types.h" -+ -+struct remapper { -+ struct list_head list; -+ int (*proc)(int, unsigned long, int, __u64); -+}; -+ -+extern void register_remapper(struct remapper *info); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/mem_user.h um/arch/um/include/mem_user.h ---- orig/arch/um/include/mem_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mem_user.h 2004-01-10 00:11:06.000000000 -0500 -@@ -0,0 +1,81 @@ -+/* -+ * arch/um/include/mem_user.h -+ * -+ * BRIEF MODULE DESCRIPTION -+ * user side memory interface for support IO memory inside user mode linux -+ * -+ * Copyright (C) 2001 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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. -+ */ -+ -+#ifndef _MEM_USER_H -+#define _MEM_USER_H -+ -+struct iomem_region { -+ struct iomem_region *next; -+ char *driver; -+ int fd; -+ int size; -+ unsigned long phys; -+ unsigned long virt; -+}; -+ -+extern struct iomem_region *iomem_regions; -+extern int iomem_size; -+ -+#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) -+ -+extern unsigned long host_task_size; -+extern unsigned long task_size; -+ -+extern int init_mem_user(void); -+extern int create_mem_file(unsigned long len); -+extern void setup_memory(void *entry); -+extern unsigned long find_iomem(char *driver, unsigned long *len_out); -+extern int init_maps(unsigned long physmem, unsigned long iomem, -+ unsigned long highmem); -+extern unsigned long get_vm(unsigned long len); -+extern void setup_physmem(unsigned long start, unsigned long usable, -+ unsigned long len, unsigned long highmem); -+extern void add_iomem(char *name, int fd, unsigned long size); -+extern unsigned long phys_offset(unsigned long phys); -+extern void unmap_physmem(void); -+extern void map_memory(unsigned long virt, unsigned long phys, -+ unsigned long len, int r, int w, int x); -+extern int protect_memory(unsigned long addr, unsigned long len, -+ int r, int w, int x, int must_succeed); -+extern unsigned long get_kmem_end(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/mode.h um/arch/um/include/mode.h ---- orig/arch/um/include/mode.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mode.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_H__ -+#define __MODE_H__ -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "../kernel/tt/include/mode.h" -+#endif -+ -+#ifdef UML_CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mode.h" -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/mode_kern.h um/arch/um/include/mode_kern.h ---- orig/arch/um/include/mode_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/mode_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_KERN_H__ -+#define __MODE_KERN_H__ -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/mode_kern.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mode_kern.h" -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/net_kern.h um/arch/um/include/net_kern.h ---- orig/arch/um/include/net_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/net_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_NET_KERN_H -+#define __UM_NET_KERN_H -+ -+#include "linux/netdevice.h" -+#include "linux/skbuff.h" -+#include "linux/socket.h" -+#include "linux/list.h" -+ -+struct uml_net { -+ struct list_head list; -+ struct net_device *dev; -+ int index; -+ unsigned char mac[ETH_ALEN]; -+ int have_mac; -+}; -+ -+struct uml_net_private { -+ struct list_head list; -+ spinlock_t lock; -+ struct net_device *dev; -+ struct timer_list tl; -+ struct net_device_stats stats; -+ int fd; -+ unsigned char mac[ETH_ALEN]; -+ int have_mac; -+ unsigned short (*protocol)(struct sk_buff *); -+ int (*open)(void *); -+ void (*close)(int, void *); -+ void (*remove)(void *); -+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *); -+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *); -+ -+ void (*add_address)(unsigned char *, unsigned char *, void *); -+ void (*delete_address)(unsigned char *, unsigned char *, void *); -+ int (*set_mtu)(int mtu, void *); -+ int user[1]; -+}; -+ -+struct net_kern_info { -+ void (*init)(struct net_device *, void *); -+ unsigned short (*protocol)(struct sk_buff *); -+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *); -+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *); -+}; -+ -+struct transport { -+ struct list_head list; -+ char *name; -+ int (*setup)(char *, char **, void *); -+ struct net_user_info *user; -+ struct net_kern_info *kern; -+ int private_size; -+ int setup_size; -+}; -+ -+extern struct net_device *ether_init(int); -+extern unsigned short ether_protocol(struct sk_buff *); -+extern int setup_etheraddr(char *str, unsigned char *addr); -+extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); -+extern int tap_setup_common(char *str, char *type, char **dev_name, -+ char **mac_out, char **gate_addr); -+extern void register_transport(struct transport *new); -+extern unsigned short eth_protocol(struct sk_buff *skb); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/net_user.h um/arch/um/include/net_user.h ---- orig/arch/um/include/net_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/net_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_NET_USER_H__ -+#define __UM_NET_USER_H__ -+ -+#define ETH_ADDR_LEN (6) -+#define ETH_HEADER_ETHERTAP (16) -+#define ETH_HEADER_OTHER (14) -+#define ETH_MAX_PACKET (1500) -+ -+#define UML_NET_VERSION (4) -+ -+struct net_user_info { -+ void (*init)(void *, void *); -+ int (*open)(void *); -+ void (*close)(int, void *); -+ void (*remove)(void *); -+ int (*set_mtu)(int mtu, void *); -+ void (*add_address)(unsigned char *, unsigned char *, void *); -+ void (*delete_address)(unsigned char *, unsigned char *, void *); -+ int max_packet; -+}; -+ -+extern void ether_user_init(void *data, void *dev); -+extern void dev_ip_addr(void *d, char *buf, char *bin_buf); -+extern void set_ether_mac(void *d, unsigned char *addr); -+extern void iter_addresses(void *d, void (*cb)(unsigned char *, -+ unsigned char *, void *), -+ void *arg); -+ -+extern void *get_output_buffer(int *len_out); -+extern void free_output_buffer(void *buffer); -+ -+extern int tap_open_common(void *dev, char *gate_addr); -+extern void tap_check_ips(char *gate_addr, char *eth_addr); -+ -+extern void read_output(int fd, char *output_out, int len); -+ -+extern int net_read(int fd, void *buf, int len); -+extern int net_recvfrom(int fd, void *buf, int len); -+extern int net_write(int fd, void *buf, int len); -+extern int net_send(int fd, void *buf, int len); -+extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len); -+ -+extern void open_addr(unsigned char *addr, unsigned char *netmask, void *arg); -+extern void close_addr(unsigned char *addr, unsigned char *netmask, void *arg); -+ -+extern char *split_if_spec(char *str, ...); -+ -+extern int dev_netmask(void *d, void *m); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/os.h um/arch/um/include/os.h ---- orig/arch/um/include/os.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/os.h 2003-12-17 10:48:12.000000000 -0500 -@@ -0,0 +1,180 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __OS_H__ -+#define __OS_H__ -+ -+#include "asm/types.h" -+#include "../os/include/file.h" -+ -+#define OS_TYPE_FILE 1 -+#define OS_TYPE_DIR 2 -+#define OS_TYPE_SYMLINK 3 -+#define OS_TYPE_CHARDEV 4 -+#define OS_TYPE_BLOCKDEV 5 -+#define OS_TYPE_FIFO 6 -+#define OS_TYPE_SOCK 7 -+ -+/* os_access() flags */ -+#define OS_ACC_F_OK 0 /* Test for existence. */ -+#define OS_ACC_X_OK 1 /* Test for execute permission. */ -+#define OS_ACC_W_OK 2 /* Test for write permission. */ -+#define OS_ACC_R_OK 4 /* Test for read permission. */ -+#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ -+ -+/* -+ * types taken from stat_file() in hostfs_user.c -+ * (if they are wrong here, they are wrong there...). -+ */ -+struct uml_stat { -+ int ust_dev; /* device */ -+ unsigned long long ust_ino; /* inode */ -+ int ust_mode; /* protection */ -+ int ust_nlink; /* number of hard links */ -+ int ust_uid; /* user ID of owner */ -+ int ust_gid; /* group ID of owner */ -+ unsigned long long ust_size; /* total size, in bytes */ -+ int ust_blksize; /* blocksize for filesystem I/O */ -+ unsigned long long ust_blocks; /* number of blocks allocated */ -+ unsigned long ust_atime; /* time of last access */ -+ unsigned long ust_mtime; /* time of last modification */ -+ unsigned long ust_ctime; /* time of last change */ -+}; -+ -+struct openflags { -+ unsigned int r : 1; -+ unsigned int w : 1; -+ unsigned int s : 1; /* O_SYNC */ -+ unsigned int c : 1; /* O_CREAT */ -+ unsigned int t : 1; /* O_TRUNC */ -+ unsigned int a : 1; /* O_APPEND */ -+ unsigned int e : 1; /* O_EXCL */ -+ unsigned int cl : 1; /* FD_CLOEXEC */ -+}; -+ -+#define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \ -+ .t = 0, .a = 0, .e = 0, .cl = 0 }) -+ -+static inline struct openflags of_read(struct openflags flags) -+{ -+ flags.r = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_write(struct openflags flags) -+{ -+ flags.w = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_rdwr(struct openflags flags) -+{ -+ return(of_read(of_write(flags))); -+} -+ -+static inline struct openflags of_set_rw(struct openflags flags, int r, int w) -+{ -+ flags.r = r; -+ flags.w = w; -+ return(flags); -+} -+ -+static inline struct openflags of_sync(struct openflags flags) -+{ -+ flags.s = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_create(struct openflags flags) -+{ -+ flags.c = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_trunc(struct openflags flags) -+{ -+ flags.t = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_append(struct openflags flags) -+{ -+ flags.a = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_excl(struct openflags flags) -+{ -+ flags.e = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_cloexec(struct openflags flags) -+{ -+ flags.cl = 1; -+ return(flags); -+} -+ -+extern int os_stat_file(const char *file_name, struct uml_stat *buf); -+extern int os_stat_fd(const int fd, struct uml_stat *buf); -+extern int os_access(const char *file, int mode); -+extern void os_print_error(int error, const char* str); -+extern int os_get_exec_close(int fd, int *close_on_exec); -+extern int os_set_exec_close(int fd, int close_on_exec); -+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); -+extern int os_window_size(int fd, int *rows, int *cols); -+extern int os_new_tty_pgrp(int fd, int pid); -+extern int os_get_ifname(int fd, char *namebuf); -+extern int os_set_slip(int fd); -+extern int os_set_owner(int fd, int pid); -+extern int os_sigio_async(int master, int slave); -+extern int os_mode_fd(int fd, int mode); -+ -+extern int os_seek_file(int fd, __u64 offset); -+extern int os_open_file(char *file, struct openflags flags, int mode); -+extern int os_read_file(int fd, void *buf, int len); -+extern int os_write_file(int fd, const void *buf, int count); -+extern int os_file_size(char *file, long long *size_out); -+extern int os_file_modtime(char *file, unsigned long *modtime); -+extern int os_pipe(int *fd, int stream, int close_on_exec); -+extern int os_set_fd_async(int fd, int owner); -+extern int os_set_fd_block(int fd, int blocking); -+extern int os_accept_connection(int fd); -+extern int os_create_unix_socket(char *file, int len, int close_on_exec); -+extern int os_shutdown_socket(int fd, int r, int w); -+extern void os_close_file(int fd); -+extern int os_rcv_fd(int fd, int *helper_pid_out); -+extern int create_unix_socket(char *file, int len, int close_on_exec); -+extern int os_connect_socket(char *name); -+extern int os_file_type(char *file); -+extern int os_file_mode(char *file, struct openflags *mode_out); -+extern int os_lock_file(int fd, int excl); -+ -+extern unsigned long os_process_pc(int pid); -+extern int os_process_parent(int pid); -+extern void os_stop_process(int pid); -+extern void os_kill_process(int pid, int reap_child); -+extern void os_usr1_process(int pid); -+extern int os_getpid(void); -+ -+extern int os_map_memory(void *virt, int fd, unsigned long long off, -+ unsigned long len, int r, int w, int x); -+extern int os_protect_memory(void *addr, unsigned long len, -+ int r, int w, int x); -+extern int os_unmap_memory(void *addr, int len); -+extern void os_flush_stdout(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/process.h um/arch/um/include/process.h ---- orig/arch/um/include/process.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/process.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROCESS_H__ -+#define __PROCESS_H__ -+ -+#include <asm/sigcontext.h> -+ -+extern void sig_handler(int sig, struct sigcontext sc); -+extern void alarm_handler(int sig, struct sigcontext sc); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/ptrace_user.h um/arch/um/include/ptrace_user.h ---- orig/arch/um/include/ptrace_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/ptrace_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,18 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_USER_H__ -+#define __PTRACE_USER_H__ -+ -+#include "sysdep/ptrace_user.h" -+ -+extern int ptrace_getregs(long pid, unsigned long *regs_out); -+extern int ptrace_setregs(long pid, unsigned long *regs_in); -+extern int ptrace_getfpregs(long pid, unsigned long *regs_out); -+extern void arch_enter_kernel(void *task, int pid); -+extern void arch_leave_kernel(void *task, int pid); -+extern void ptrace_pokeuser(unsigned long addr, unsigned long data); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/sigcontext.h um/arch/um/include/sigcontext.h ---- orig/arch/um/include/sigcontext.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sigcontext.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UML_SIGCONTEXT_H__ -+#define __UML_SIGCONTEXT_H__ -+ -+#include "sysdep/sigcontext.h" -+ -+extern int sc_size(void *data); -+extern void sc_to_sc(void *to_ptr, void *from_ptr); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sigio.h um/arch/um/include/sigio.h ---- orig/arch/um/include/sigio.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sigio.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGIO_H__ -+#define __SIGIO_H__ -+ -+extern int write_sigio_irq(int fd); -+extern int register_sigio_fd(int fd); -+extern int read_sigio_fd(int fd); -+extern int add_sigio_fd(int fd, int read); -+extern int ignore_sigio_fd(int fd); -+extern void sigio_lock(void); -+extern void sigio_unlock(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/signal_kern.h um/arch/um/include/signal_kern.h ---- orig/arch/um/include/signal_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/signal_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGNAL_KERN_H__ -+#define __SIGNAL_KERN_H__ -+ -+extern int have_signals(void *t); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/signal_user.h um/arch/um/include/signal_user.h ---- orig/arch/um/include/signal_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/signal_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGNAL_USER_H__ -+#define __SIGNAL_USER_H__ -+ -+extern int signal_stack_size; -+ -+extern int change_sig(int signal, int on); -+extern void set_sigstack(void *stack, int size); -+extern void set_handler(int sig, void (*handler)(int), int flags, ...); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/skas_ptrace.h um/arch/um/include/skas_ptrace.h ---- orig/arch/um/include/skas_ptrace.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/skas_ptrace.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_PTRACE_H -+#define __SKAS_PTRACE_H -+ -+struct ptrace_faultinfo { -+ int is_write; -+ unsigned long addr; -+}; -+ -+struct ptrace_ldt { -+ int func; -+ void *ptr; -+ unsigned long bytecount; -+}; -+ -+#define PTRACE_FAULTINFO 52 -+#define PTRACE_SIGPENDING 53 -+#define PTRACE_LDT 54 -+#define PTRACE_SWITCH_MM 55 -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/syscall_user.h um/arch/um/include/syscall_user.h ---- orig/arch/um/include/syscall_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/syscall_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSCALL_USER_H -+#define __SYSCALL_USER_H -+ -+extern int record_syscall_start(int syscall); -+extern void record_syscall_end(int index, int result); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/checksum.h um/arch/um/include/sysdep-i386/checksum.h ---- orig/arch/um/include/sysdep-i386/checksum.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/checksum.h 2004-01-13 23:40:05.000000000 -0500 -@@ -0,0 +1,218 @@ -+/* -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SYSDEP_CHECKSUM_H -+#define __UM_SYSDEP_CHECKSUM_H -+ -+#include "linux/string.h" -+#include "asm/uaccess.h" -+ -+/* -+ * computes the checksum of a memory block at buff, length len, -+ * and adds in "sum" (32-bit) -+ * -+ * returns a 32-bit number suitable for feeding into itself -+ * or csum_tcpudp_magic -+ * -+ * this function must be called with even lengths, except -+ * for the last fragment, which may be odd -+ * -+ * it's best to have buff aligned on a 32-bit boundary -+ */ -+unsigned int csum_partial(const unsigned char * buff, int len, -+ unsigned int sum); -+ -+/* -+ * the same as csum_partial, but copies from src while it -+ * checksums, and handles user-space pointer exceptions correctly, when needed. -+ * -+ * here even more important to align src and dst on a 32-bit (or even -+ * better 64-bit) boundary -+ */ -+ -+unsigned int csum_partial_copy_to(const char *src, char *dst, int len, -+ int sum, int *err_ptr); -+unsigned int csum_partial_copy_from(const char *src, char *dst, int len, -+ int sum, int *err_ptr); -+ -+/* -+ * Note: when you get a NULL pointer exception here this means someone -+ * passed in an incorrect kernel address to one of these functions. -+ * -+ * If you use these functions directly please don't forget the -+ * verify_area(). -+ */ -+ -+static __inline__ -+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, -+ int len, int sum) -+{ -+ memcpy(dst, src, len); -+ return(csum_partial(dst, len, sum)); -+} -+ -+static __inline__ -+unsigned int csum_partial_copy_from_user(const char *src, char *dst, -+ int len, int sum, int *err_ptr) -+{ -+ return csum_partial_copy_from(src, dst, len, sum, err_ptr); -+} -+ -+/* -+ * These are the old (and unsafe) way of doing checksums, a warning message -+ * will be printed if they are used and an exception occurs. -+ * -+ * these functions should go away after some time. -+ */ -+ -+#define csum_partial_copy_fromuser csum_partial_copy_from_user -+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); -+ -+/* -+ * This is a version of ip_compute_csum() optimized for IP headers, -+ * which always checksum on 4 octet boundaries. -+ * -+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by -+ * Arnt Gulbrandsen. -+ */ -+static inline unsigned short ip_fast_csum(unsigned char * iph, -+ unsigned int ihl) -+{ -+ unsigned int sum; -+ -+ __asm__ __volatile__( -+ "movl (%1), %0 ;\n" -+ "subl $4, %2 ;\n" -+ "jbe 2f ;\n" -+ "addl 4(%1), %0 ;\n" -+ "adcl 8(%1), %0 ;\n" -+ "adcl 12(%1), %0 ;\n" -+"1: adcl 16(%1), %0 ;\n" -+ "lea 4(%1), %1 ;\n" -+ "decl %2 ;\n" -+ "jne 1b ;\n" -+ "adcl $0, %0 ;\n" -+ "movl %0, %2 ;\n" -+ "shrl $16, %0 ;\n" -+ "addw %w2, %w0 ;\n" -+ "adcl $0, %0 ;\n" -+ "notl %0 ;\n" -+"2: ;\n" -+ /* Since the input registers which are loaded with iph and ipl -+ are modified, we must also specify them as outputs, or gcc -+ will assume they contain their original values. */ -+ : "=r" (sum), "=r" (iph), "=r" (ihl) -+ : "1" (iph), "2" (ihl)); -+ return(sum); -+} -+ -+/* -+ * Fold a partial checksum -+ */ -+ -+static inline unsigned int csum_fold(unsigned int sum) -+{ -+ __asm__( -+ "addl %1, %0 ;\n" -+ "adcl $0xffff, %0 ;\n" -+ : "=r" (sum) -+ : "r" (sum << 16), "0" (sum & 0xffff0000) -+ ); -+ return (~sum) >> 16; -+} -+ -+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, -+ unsigned long daddr, -+ unsigned short len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ __asm__( -+ "addl %1, %0 ;\n" -+ "adcl %2, %0 ;\n" -+ "adcl %3, %0 ;\n" -+ "adcl $0, %0 ;\n" -+ : "=r" (sum) -+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum)); -+ return sum; -+} -+ -+/* -+ * computes the checksum of the TCP/UDP pseudo-header -+ * returns a 16-bit checksum, already complemented -+ */ -+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, -+ unsigned long daddr, -+ unsigned short len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -+} -+ -+/* -+ * this routine is used for miscellaneous IP-like checksums, mainly -+ * in icmp.c -+ */ -+ -+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) -+{ -+ return csum_fold (csum_partial(buff, len, 0)); -+} -+ -+#define _HAVE_ARCH_IPV6_CSUM -+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, -+ struct in6_addr *daddr, -+ __u32 len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ __asm__( -+ "addl 0(%1), %0 ;\n" -+ "adcl 4(%1), %0 ;\n" -+ "adcl 8(%1), %0 ;\n" -+ "adcl 12(%1), %0 ;\n" -+ "adcl 0(%2), %0 ;\n" -+ "adcl 4(%2), %0 ;\n" -+ "adcl 8(%2), %0 ;\n" -+ "adcl 12(%2), %0 ;\n" -+ "adcl %3, %0 ;\n" -+ "adcl %4, %0 ;\n" -+ "adcl $0, %0 ;\n" -+ : "=&r" (sum) -+ : "r" (saddr), "r" (daddr), -+ "r"(htonl(len)), "r"(htonl(proto)), "0"(sum)); -+ -+ return csum_fold(sum); -+} -+ -+/* -+ * Copy and checksum to user -+ */ -+#define HAVE_CSUM_COPY_USER -+static __inline__ unsigned int csum_and_copy_to_user(const char *src, -+ char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if (access_ok(VERIFY_WRITE, dst, len)) -+ return(csum_partial_copy_to(src, dst, len, sum, err_ptr)); -+ -+ if (len) -+ *err_ptr = -EFAULT; -+ -+ return -1; /* invalid checksum */ -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame.h um/arch/um/include/sysdep-i386/frame.h ---- orig/arch/um/include/sysdep-i386/frame.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/frame.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_I386_H -+#define __FRAME_I386_H -+ -+struct arch_frame_data_raw { -+ unsigned long fp_start; -+ unsigned long sr; -+}; -+ -+struct arch_frame_data { -+ int fpstate_size; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame_kern.h um/arch/um/include/sysdep-i386/frame_kern.h ---- orig/arch/um/include/sysdep-i386/frame_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/frame_kern.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_KERN_I386_H -+#define __FRAME_KERN_I386_H -+ -+/* This is called from sys_sigreturn. It takes the sp at the point of the -+ * sigreturn system call and returns the address of the sigcontext struct -+ * on the stack. -+ */ -+ -+static inline void *sp_to_sc(unsigned long sp) -+{ -+ return((void *) sp); -+} -+ -+static inline void *sp_to_uc(unsigned long sp) -+{ -+ unsigned long uc; -+ -+ uc = sp + signal_frame_si.uc_index - -+ signal_frame_si.common.sp_index - 4; -+ return((void *) uc); -+} -+ -+static inline void *sp_to_rt_sc(unsigned long sp) -+{ -+ unsigned long sc; -+ -+ sc = sp - signal_frame_si.common.sp_index + -+ signal_frame_si.common.len - 4; -+ return((void *) sc); -+} -+ -+static inline void *sp_to_mask(unsigned long sp) -+{ -+ unsigned long mask; -+ -+ mask = sp - signal_frame_sc.common.sp_index + -+ signal_frame_sc.common.len - 8; -+ return((void *) mask); -+} -+ -+extern int sc_size(void *data); -+ -+static inline void *sp_to_rt_mask(unsigned long sp) -+{ -+ unsigned long mask; -+ -+ mask = sp - signal_frame_si.common.sp_index + -+ signal_frame_si.common.len + -+ sc_size(&signal_frame_si.common.arch) - 4; -+ return((void *) mask); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/frame_user.h um/arch/um/include/sysdep-i386/frame_user.h ---- orig/arch/um/include/sysdep-i386/frame_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/frame_user.h 2004-01-14 03:54:47.000000000 -0500 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_USER_I386_H -+#define __FRAME_USER_I386_H -+ -+#include <asm/page.h> -+#include "sysdep/frame.h" -+ -+/* This stuff is to calculate the size of the fp state struct at runtime -+ * because it has changed between 2.2 and 2.4 and it would be good for a -+ * UML compiled on one to work on the other. -+ * So, setup_arch_frame_raw fills in the arch struct with the raw data, which -+ * just contains the address of the end of the sigcontext. This is invoked -+ * from the signal handler. -+ * setup_arch_frame uses that data to figure out what -+ * arch_frame_data.fpstate_size should be. It really has no idea, since it's -+ * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's -+ * everything from the end of the sigcontext up to the top of the stack. So, -+ * it masks off the page number to get the offset within the page and subtracts -+ * that from the page size, and that's how big the fpstate struct will be -+ * considered to be. -+ */ -+ -+static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data, -+ void *end, unsigned long srp) -+{ -+ unsigned long sr = *((unsigned long *) srp); -+ -+ data->fp_start = (unsigned long) end; -+ if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK)) -+ data->sr = sr; -+ else data->sr = 0; -+} -+ -+static inline void setup_arch_frame(struct arch_frame_data_raw *in, -+ struct arch_frame_data *out) -+{ -+ unsigned long fpstate_start = in->fp_start; -+ -+ if(in->sr == 0){ -+ fpstate_start &= ~PAGE_MASK; -+ out->fpstate_size = PAGE_SIZE - fpstate_start; -+ } -+ else { -+ out->fpstate_size = in->sr - fpstate_start; -+ } -+} -+ -+/* This figures out where on the stack the SA_RESTORER function address -+ * is stored. For i386, it's the signal handler return address, so it's -+ * located next to the frame pointer. -+ * This is inlined, so __builtin_frame_address(0) is correct. Otherwise, -+ * it would have to be __builtin_frame_address(1). -+ */ -+ -+#define frame_restorer() \ -+({ \ -+ unsigned long *fp; \ -+\ -+ fp = __builtin_frame_address(0); \ -+ ((unsigned long) (fp + 1)); \ -+}) -+ -+/* Similarly, this returns the value of sp when the handler was first -+ * entered. This is used to calculate the proper sp when delivering -+ * signals. -+ */ -+ -+#define frame_sp() \ -+({ \ -+ unsigned long *fp; \ -+\ -+ fp = __builtin_frame_address(0); \ -+ ((unsigned long) (fp + 1)); \ -+}) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/ptrace.h um/arch/um/include/sysdep-i386/ptrace.h ---- orig/arch/um/include/sysdep-i386/ptrace.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/ptrace.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,193 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_I386_PTRACE_H -+#define __SYSDEP_I386_PTRACE_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "ptrace-tt.h" -+#endif -+ -+#ifdef UML_CONFIG_MODE_SKAS -+#include "ptrace-skas.h" -+#endif -+ -+#include "choose-mode.h" -+ -+union uml_pt_regs { -+#ifdef UML_CONFIG_MODE_TT -+ struct tt_regs { -+ long syscall; -+ void *sc; -+ } tt; -+#endif -+#ifdef UML_CONFIG_MODE_SKAS -+ struct skas_regs { -+ unsigned long regs[HOST_FRAME_SIZE]; -+ unsigned long fp[HOST_FP_SIZE]; -+ unsigned long xfp[HOST_XFP_SIZE]; -+ unsigned long fault_addr; -+ unsigned long fault_type; -+ unsigned long trap_type; -+ long syscall; -+ int is_user; -+ } skas; -+#endif -+}; -+ -+#define EMPTY_UML_PT_REGS { } -+ -+extern int mode_tt; -+ -+#define UPT_SC(r) ((r)->tt.sc) -+#define UPT_IP(r) \ -+ CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) -+#define UPT_SP(r) \ -+ CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) -+#define UPT_EFLAGS(r) \ -+ CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) -+#define UPT_EAX(r) \ -+ CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs)) -+#define UPT_EBX(r) \ -+ CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs)) -+#define UPT_ECX(r) \ -+ CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs)) -+#define UPT_EDX(r) \ -+ CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs)) -+#define UPT_ESI(r) \ -+ CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs)) -+#define UPT_EDI(r) \ -+ CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs)) -+#define UPT_EBP(r) \ -+ CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs)) -+#define UPT_ORIG_EAX(r) \ -+ CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) -+#define UPT_CS(r) \ -+ CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) -+#define UPT_SS(r) \ -+ CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) -+#define UPT_DS(r) \ -+ CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) -+#define UPT_ES(r) \ -+ CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) -+#define UPT_FS(r) \ -+ CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) -+#define UPT_GS(r) \ -+ CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) -+ -+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r) -+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r) -+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r) -+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r) -+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r) -+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r) -+ -+extern int user_context(unsigned long sp); -+ -+#define UPT_IS_USER(r) \ -+ CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) -+ -+struct syscall_args { -+ unsigned long args[6]; -+}; -+ -+#define SYSCALL_ARGS(r) ((struct syscall_args) \ -+ { .args = { UPT_SYSCALL_ARG1(r), \ -+ UPT_SYSCALL_ARG2(r), \ -+ UPT_SYSCALL_ARG3(r), \ -+ UPT_SYSCALL_ARG4(r), \ -+ UPT_SYSCALL_ARG5(r), \ -+ UPT_SYSCALL_ARG6(r) } } ) -+ -+#define UPT_REG(regs, reg) \ -+ ({ unsigned long val; \ -+ switch(reg){ \ -+ case EIP: val = UPT_IP(regs); break; \ -+ case UESP: val = UPT_SP(regs); break; \ -+ case EAX: val = UPT_EAX(regs); break; \ -+ case EBX: val = UPT_EBX(regs); break; \ -+ case ECX: val = UPT_ECX(regs); break; \ -+ case EDX: val = UPT_EDX(regs); break; \ -+ case ESI: val = UPT_ESI(regs); break; \ -+ case EDI: val = UPT_EDI(regs); break; \ -+ case EBP: val = UPT_EBP(regs); break; \ -+ case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \ -+ case CS: val = UPT_CS(regs); break; \ -+ case SS: val = UPT_SS(regs); break; \ -+ case DS: val = UPT_DS(regs); break; \ -+ case ES: val = UPT_ES(regs); break; \ -+ case FS: val = UPT_FS(regs); break; \ -+ case GS: val = UPT_GS(regs); break; \ -+ case EFL: val = UPT_EFLAGS(regs); break; \ -+ default : \ -+ panic("Bad register in UPT_REG : %d\n", reg); \ -+ val = -1; \ -+ } \ -+ val; \ -+ }) -+ -+ -+#define UPT_SET(regs, reg, val) \ -+ do { \ -+ switch(reg){ \ -+ case EIP: UPT_IP(regs) = val; break; \ -+ case UESP: UPT_SP(regs) = val; break; \ -+ case EAX: UPT_EAX(regs) = val; break; \ -+ case EBX: UPT_EBX(regs) = val; break; \ -+ case ECX: UPT_ECX(regs) = val; break; \ -+ case EDX: UPT_EDX(regs) = val; break; \ -+ case ESI: UPT_ESI(regs) = val; break; \ -+ case EDI: UPT_EDI(regs) = val; break; \ -+ case EBP: UPT_EBP(regs) = val; break; \ -+ case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \ -+ case CS: UPT_CS(regs) = val; break; \ -+ case SS: UPT_SS(regs) = val; break; \ -+ case DS: UPT_DS(regs) = val; break; \ -+ case ES: UPT_ES(regs) = val; break; \ -+ case FS: UPT_FS(regs) = val; break; \ -+ case GS: UPT_GS(regs) = val; break; \ -+ case EFL: UPT_EFLAGS(regs) = val; break; \ -+ default : \ -+ panic("Bad register in UPT_SET : %d\n", reg); \ -+ break; \ -+ } \ -+ } while (0) -+ -+#define UPT_SET_SYSCALL_RETURN(r, res) \ -+ CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ -+ REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) -+ -+#define UPT_RESTART_SYSCALL(r) \ -+ CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ -+ REGS_RESTART_SYSCALL((r)->skas.regs)) -+ -+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r) -+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) -+#define UPT_SYSCALL_RET(r) UPT_EAX(r) -+ -+#define UPT_SEGV_IS_FIXABLE(r) \ -+ CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ -+ REGS_SEGV_IS_FIXABLE(&r->skas)) -+ -+#define UPT_FAULT_ADDR(r) \ -+ CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas)) -+ -+#define UPT_FAULT_WRITE(r) \ -+ CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas)) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/ptrace_user.h um/arch/um/include/sysdep-i386/ptrace_user.h ---- orig/arch/um/include/sysdep-i386/ptrace_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/ptrace_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_I386_PTRACE_USER_H__ -+#define __SYSDEP_I386_PTRACE_USER_H__ -+ -+#include <asm/ptrace.h> -+ -+#define PT_OFFSET(r) ((r) * sizeof(long)) -+ -+#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX]) -+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX) -+ -+#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX) -+#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX) -+#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX) -+#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI) -+#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI) -+ -+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX) -+ -+#define PT_IP_OFFSET PT_OFFSET(EIP) -+#define PT_IP(regs) ((regs)[EIP]) -+#define PT_SP(regs) ((regs)[UESP]) -+ -+#ifndef FRAME_SIZE -+#define FRAME_SIZE (17) -+#endif -+#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long)) -+ -+#define FP_FRAME_SIZE (27) -+#define FPX_FRAME_SIZE (128) -+ -+#ifdef PTRACE_GETREGS -+#define UM_HAVE_GETREGS -+#endif -+ -+#ifdef PTRACE_SETREGS -+#define UM_HAVE_SETREGS -+#endif -+ -+#ifdef PTRACE_GETFPREGS -+#define UM_HAVE_GETFPREGS -+#endif -+ -+#ifdef PTRACE_SETFPREGS -+#define UM_HAVE_SETFPREGS -+#endif -+ -+#ifdef PTRACE_GETFPXREGS -+#define UM_HAVE_GETFPXREGS -+#endif -+ -+#ifdef PTRACE_SETFPXREGS -+#define UM_HAVE_SETFPXREGS -+#endif -+ -+extern void update_debugregs(int seq); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/sigcontext.h um/arch/um/include/sysdep-i386/sigcontext.h ---- orig/arch/um/include/sysdep-i386/sigcontext.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/sigcontext.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_SIGCONTEXT_I386_H -+#define __SYS_SIGCONTEXT_I386_H -+ -+#include "sc.h" -+ -+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -+ -+#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) -+#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) -+ -+#define SC_FAULT_ADDR(sc) SC_CR2(sc) -+#define SC_FAULT_TYPE(sc) SC_ERR(sc) -+ -+#define FAULT_WRITE(err) (err & 2) -+#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0) -+ -+#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc))) -+ -+#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc) -+ -+/* ptrace expects that, at the start of a system call, %eax contains -+ * -ENOSYS, so this makes it so. -+ */ -+#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) -+ -+/* This is Page Fault */ -+#define SEGV_IS_FIXABLE(trap) (trap == 14) -+ -+#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc))) -+ -+extern unsigned long *sc_sigmask(void *sc_ptr); -+extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-i386/syscalls.h um/arch/um/include/sysdep-i386/syscalls.h ---- orig/arch/um/include/sysdep-i386/syscalls.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-i386/syscalls.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/unistd.h" -+#include "sysdep/ptrace.h" -+ -+typedef long syscall_handler_t(struct pt_regs); -+ -+#define EXECUTE_SYSCALL(syscall, regs) \ -+ ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) -+ -+extern syscall_handler_t sys_modify_ldt; -+extern syscall_handler_t old_mmap_i386; -+extern syscall_handler_t old_select; -+extern syscall_handler_t sys_ni_syscall; -+ -+#define ARCH_SYSCALLS \ -+ [ __NR_mmap ] = old_mmap_i386, \ -+ [ __NR_select ] = old_select, \ -+ [ __NR_vm86old ] = sys_ni_syscall, \ -+ [ __NR_modify_ldt ] = sys_modify_ldt, \ -+ [ __NR_lchown32 ] = sys_lchown, \ -+ [ __NR_getuid32 ] = sys_getuid, \ -+ [ __NR_getgid32 ] = sys_getgid, \ -+ [ __NR_geteuid32 ] = sys_geteuid, \ -+ [ __NR_getegid32 ] = sys_getegid, \ -+ [ __NR_setreuid32 ] = sys_setreuid, \ -+ [ __NR_setregid32 ] = sys_setregid, \ -+ [ __NR_getgroups32 ] = sys_getgroups, \ -+ [ __NR_setgroups32 ] = sys_setgroups, \ -+ [ __NR_fchown32 ] = sys_fchown, \ -+ [ __NR_setresuid32 ] = sys_setresuid, \ -+ [ __NR_getresuid32 ] = sys_getresuid, \ -+ [ __NR_setresgid32 ] = sys_setresgid, \ -+ [ __NR_getresgid32 ] = sys_getresgid, \ -+ [ __NR_chown32 ] = sys_chown, \ -+ [ __NR_setuid32 ] = sys_setuid, \ -+ [ __NR_setgid32 ] = sys_setgid, \ -+ [ __NR_setfsuid32 ] = sys_setfsuid, \ -+ [ __NR_setfsgid32 ] = sys_setfsgid, \ -+ [ __NR_pivot_root ] = sys_pivot_root, \ -+ [ __NR_mincore ] = sys_mincore, \ -+ [ __NR_madvise ] = sys_madvise, \ -+ [ 222 ] = sys_ni_syscall, -+ -+/* 222 doesn't yet have a name in include/asm-i386/unistd.h */ -+ -+#define LAST_ARCH_SYSCALL 222 -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/ptrace.h um/arch/um/include/sysdep-ia64/ptrace.h ---- orig/arch/um/include/sysdep-ia64/ptrace.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-ia64/ptrace.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_PTRACE_H -+#define __SYSDEP_IA64_PTRACE_H -+ -+struct sys_pt_regs { -+ int foo; -+}; -+ -+#define EMPTY_REGS { 0 } -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/sigcontext.h um/arch/um/include/sysdep-ia64/sigcontext.h ---- orig/arch/um/include/sysdep-ia64/sigcontext.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-ia64/sigcontext.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_SIGCONTEXT_H -+#define __SYSDEP_IA64_SIGCONTEXT_H -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ia64/syscalls.h um/arch/um/include/sysdep-ia64/syscalls.h ---- orig/arch/um/include/sysdep-ia64/syscalls.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-ia64/syscalls.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_SYSCALLS_H -+#define __SYSDEP_IA64_SYSCALLS_H -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/ptrace.h um/arch/um/include/sysdep-ppc/ptrace.h ---- orig/arch/um/include/sysdep-ppc/ptrace.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-ppc/ptrace.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,104 @@ -+/* -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_PTRACE_PPC_H -+#define __SYS_PTRACE_PPC_H -+ -+#include "linux/config.h" -+#include "linux/types.h" -+ -+/* the following taken from <asm-ppc/ptrace.h> */ -+ -+#ifdef CONFIG_PPC64 -+#define PPC_REG unsigned long /*long*/ -+#else -+#define PPC_REG unsigned long -+#endif -+struct sys_pt_regs_s { -+ PPC_REG gpr[32]; -+ PPC_REG nip; -+ PPC_REG msr; -+ PPC_REG orig_gpr3; /* Used for restarting system calls */ -+ PPC_REG ctr; -+ PPC_REG link; -+ PPC_REG xer; -+ PPC_REG ccr; -+ PPC_REG mq; /* 601 only (not used at present) */ -+ /* Used on APUS to hold IPL value. */ -+ PPC_REG trap; /* Reason for being here */ -+ PPC_REG dar; /* Fault registers */ -+ PPC_REG dsisr; -+ PPC_REG result; /* Result of a system call */ -+}; -+ -+#define NUM_REGS (sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)) -+ -+struct sys_pt_regs { -+ PPC_REG regs[sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)]; -+}; -+ -+#define UM_MAX_REG (PT_FPR0) -+#define UM_MAX_REG_OFFSET (UM_MAX_REG * sizeof(PPC_REG)) -+ -+#define EMPTY_REGS { { [ 0 ... NUM_REGS - 1] = 0 } } -+ -+#define UM_REG(r, n) ((r)->regs[n]) -+ -+#define UM_SYSCALL_RET(r) UM_REG(r, PT_R3) -+#define UM_SP(r) UM_REG(r, PT_R1) -+#define UM_IP(r) UM_REG(r, PT_NIP) -+#define UM_ELF_ZERO(r) UM_REG(r, PT_FPSCR) -+#define UM_SYSCALL_NR(r) UM_REG(r, PT_R0) -+#define UM_SYSCALL_ARG1(r) UM_REG(r, PT_ORIG_R3) -+#define UM_SYSCALL_ARG2(r) UM_REG(r, PT_R4) -+#define UM_SYSCALL_ARG3(r) UM_REG(r, PT_R5) -+#define UM_SYSCALL_ARG4(r) UM_REG(r, PT_R6) -+#define UM_SYSCALL_ARG5(r) UM_REG(r, PT_R7) -+#define UM_SYSCALL_ARG6(r) UM_REG(r, PT_R8) -+ -+#define UM_SYSCALL_NR_OFFSET (PT_R0 * sizeof(PPC_REG)) -+#define UM_SYSCALL_RET_OFFSET (PT_R3 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG1_OFFSET (PT_R3 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG2_OFFSET (PT_R4 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG3_OFFSET (PT_R5 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG4_OFFSET (PT_R6 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG5_OFFSET (PT_R7 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG6_OFFSET (PT_R8 * sizeof(PPC_REG)) -+#define UM_SP_OFFSET (PT_R1 * sizeof(PPC_REG)) -+#define UM_IP_OFFSET (PT_NIP * sizeof(PPC_REG)) -+#define UM_ELF_ZERO_OFFSET (PT_R3 * sizeof(PPC_REG)) -+ -+#define UM_SET_SYSCALL_RETURN(_regs, result) \ -+do { \ -+ if (result < 0) { \ -+ (_regs)->regs[PT_CCR] |= 0x10000000; \ -+ UM_SYSCALL_RET((_regs)) = -result; \ -+ } else { \ -+ UM_SYSCALL_RET((_regs)) = result; \ -+ } \ -+} while(0) -+ -+extern void shove_aux_table(unsigned long sp); -+#define UM_FIX_EXEC_STACK(sp) shove_aux_table(sp); -+ -+/* These aren't actually defined. The undefs are just to make sure -+ * everyone's clear on the concept. -+ */ -+#undef UML_HAVE_GETREGS -+#undef UML_HAVE_GETFPREGS -+#undef UML_HAVE_SETREGS -+#undef UML_HAVE_SETFPREGS -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/sigcontext.h um/arch/um/include/sysdep-ppc/sigcontext.h ---- orig/arch/um/include/sysdep-ppc/sigcontext.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-ppc/sigcontext.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_SIGCONTEXT_PPC_H -+#define __SYS_SIGCONTEXT_PPC_H -+ -+#define DSISR_WRITE 0x02000000 -+ -+#define SC_FAULT_ADDR(sc) ({ \ -+ struct sigcontext *_sc = (sc); \ -+ long retval = -1; \ -+ switch (_sc->regs->trap) { \ -+ case 0x300: \ -+ /* data exception */ \ -+ retval = _sc->regs->dar; \ -+ break; \ -+ case 0x400: \ -+ /* instruction exception */ \ -+ retval = _sc->regs->nip; \ -+ break; \ -+ default: \ -+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \ -+ } \ -+ retval; \ -+ }) -+ -+#define SC_FAULT_WRITE(sc) ({ \ -+ struct sigcontext *_sc = (sc); \ -+ long retval = -1; \ -+ switch (_sc->regs->trap) { \ -+ case 0x300: \ -+ /* data exception */ \ -+ retval = !!(_sc->regs->dsisr & DSISR_WRITE); \ -+ break; \ -+ case 0x400: \ -+ /* instruction exception: not a write */ \ -+ retval = 0; \ -+ break; \ -+ default: \ -+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \ -+ } \ -+ retval; \ -+ }) -+ -+#define SC_IP(sc) ((sc)->regs->nip) -+#define SC_SP(sc) ((sc)->regs->gpr[1]) -+#define SEGV_IS_FIXABLE(sc) (1) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysdep-ppc/syscalls.h um/arch/um/include/sysdep-ppc/syscalls.h ---- orig/arch/um/include/sysdep-ppc/syscalls.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysdep-ppc/syscalls.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+typedef long syscall_handler_t(unsigned long arg1, unsigned long arg2, -+ unsigned long arg3, unsigned long arg4, -+ unsigned long arg5, unsigned long arg6); -+ -+#define EXECUTE_SYSCALL(syscall, regs) \ -+ (*sys_call_table[syscall])(UM_SYSCALL_ARG1(®s), \ -+ UM_SYSCALL_ARG2(®s), \ -+ UM_SYSCALL_ARG3(®s), \ -+ UM_SYSCALL_ARG4(®s), \ -+ UM_SYSCALL_ARG5(®s), \ -+ UM_SYSCALL_ARG6(®s)) -+ -+extern syscall_handler_t sys_mincore; -+extern syscall_handler_t sys_madvise; -+ -+/* old_mmap needs the correct prototype since syscall_kern.c includes -+ * this file. -+ */ -+int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset); -+ -+#define ARCH_SYSCALLS \ -+ [ __NR_modify_ldt ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_read ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_write ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_iobase ] = sys_ni_syscall, \ -+ [ __NR_pivot_root ] = sys_ni_syscall, \ -+ [ __NR_multiplexer ] = sys_ni_syscall, \ -+ [ __NR_mmap ] = old_mmap, \ -+ [ __NR_madvise ] = sys_madvise, \ -+ [ __NR_mincore ] = sys_mincore, -+ -+#define LAST_ARCH_SYSCALL __NR_mincore -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/sysrq.h um/arch/um/include/sysrq.h ---- orig/arch/um/include/sysrq.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/sysrq.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SYSRQ_H -+#define __UM_SYSRQ_H -+ -+extern void show_trace(unsigned long *stack); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/tempfile.h um/arch/um/include/tempfile.h ---- orig/arch/um/include/tempfile.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/tempfile.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TEMPFILE_H__ -+#define __TEMPFILE_H__ -+ -+extern int make_tempfile(const char *template, char **tempname, int do_unlink); -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/time_user.h um/arch/um/include/time_user.h ---- orig/arch/um/include/time_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/time_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,17 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TIME_USER_H__ -+#define __TIME_USER_H__ -+ -+extern void timer(void); -+extern void switch_timers(int to_real); -+extern void set_interval(int timer_type); -+extern void idle_sleep(int secs); -+extern void enable_timer(void); -+extern unsigned long time_lock(void); -+extern void time_unlock(unsigned long); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/include/tlb.h um/arch/um/include/tlb.h ---- orig/arch/um/include/tlb.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/tlb.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TLB_H__ -+#define __TLB_H__ -+ -+extern void mprotect_kernel_vm(int w); -+extern void force_flush_all(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/ubd_user.h um/arch/um/include/ubd_user.h ---- orig/arch/um/include/ubd_user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/ubd_user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,79 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_UBD_USER_H -+#define __UM_UBD_USER_H -+ -+#include "os.h" -+ -+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; -+ -+struct io_thread_req { -+ enum ubd_req op; -+ int fds[2]; -+ unsigned long offsets[2]; -+ unsigned long long offset; -+ unsigned long length; -+ char *buffer; -+ int sectorsize; -+ unsigned long sector_mask; -+ unsigned long long cow_offset; -+ unsigned long bitmap_words[2]; -+ int map_fd; -+ unsigned long long map_offset; -+ int error; -+}; -+ -+extern int open_ubd_file(char *file, struct openflags *openflags, -+ char **backing_file_out, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out, -+ int *create_cow_out); -+extern int create_cow_file(char *cow_file, char *backing_file, -+ struct openflags flags, int sectorsize, -+ int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, -+ int *data_offset_out); -+extern int read_cow_bitmap(int fd, void *buf, int offset, int len); -+extern int read_ubd_fs(int fd, void *buffer, int len); -+extern int write_ubd_fs(int fd, char *buffer, int len); -+extern int start_io_thread(unsigned long sp, int *fds_out); -+extern void do_io(struct io_thread_req *req); -+ -+static inline int ubd_test_bit(__u64 bit, unsigned char *data) -+{ -+ __u64 n; -+ int bits, off; -+ -+ bits = sizeof(data[0]) * 8; -+ n = bit / bits; -+ off = bit % bits; -+ return((data[n] & (1 << off)) != 0); -+} -+ -+static inline void ubd_set_bit(__u64 bit, unsigned char *data) -+{ -+ __u64 n; -+ int bits, off; -+ -+ bits = sizeof(data[0]) * 8; -+ n = bit / bits; -+ off = bit % bits; -+ data[n] |= (1 << off); -+} -+ -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/umid.h um/arch/um/include/umid.h ---- orig/arch/um/include/umid.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/umid.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UMID_H__ -+#define __UMID_H__ -+ -+extern int umid_file_name(char *name, char *buf, int len); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/uml_uaccess.h um/arch/um/include/uml_uaccess.h ---- orig/arch/um/include/uml_uaccess.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/uml_uaccess.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UML_UACCESS_H__ -+#define __UML_UACCESS_H__ -+ -+extern int __do_copy_to_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher); -+extern unsigned long __do_user_copy(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher, -+ void (*op)(void *to, const void *from, -+ int n), int *faulted_out); -+void __do_copy(void *to, const void *from, int n); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/um_mmu.h um/arch/um/include/um_mmu.h ---- orig/arch/um/include/um_mmu.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/um_mmu.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __ARCH_UM_MMU_H -+#define __ARCH_UM_MMU_H -+ -+#include "linux/config.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/mmu.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mmu.h" -+#endif -+ -+typedef union { -+#ifdef CONFIG_MODE_TT -+ struct mmu_context_tt tt; -+#endif -+#ifdef CONFIG_MODE_SKAS -+ struct mmu_context_skas skas; -+#endif -+} mm_context_t; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/umn.h um/arch/um/include/umn.h ---- orig/arch/um/include/umn.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/umn.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UMN_H -+#define __UMN_H -+ -+extern int open_umn_tty(int *slave_out, int *slipno_out); -+extern void close_umn_tty(int master, int slave); -+extern int umn_send_packet(int fd, void *data, int len); -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern void slip_unesc(unsigned char s); -+extern void umn_read(int fd); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/um_uaccess.h um/arch/um/include/um_uaccess.h ---- orig/arch/um/include/um_uaccess.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/um_uaccess.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __ARCH_UM_UACCESS_H -+#define __ARCH_UM_UACCESS_H -+ -+#include "linux/config.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/uaccess.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/uaccess.h" -+#endif -+ -+#define access_ok(type, addr, size) \ -+ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) -+ -+static inline int verify_area(int type, const void * addr, unsigned long size) -+{ -+ return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, -+ size)); -+} -+ -+static inline int copy_from_user(void *to, const void *from, int n) -+{ -+ return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, -+ from, n)); -+} -+ -+static inline int copy_to_user(void *to, const void *from, int n) -+{ -+ return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, -+ from, n)); -+} -+ -+/* -+ * strncpy_from_user: - Copy a NUL terminated string from userspace. -+ * @dst: Destination address, in kernel space. This buffer must be at -+ * least @count bytes long. -+ * @src: Source address, in user space. -+ * @count: Maximum number of bytes to copy, including the trailing NUL. -+ * -+ * Copies a NUL-terminated string from userspace to kernel space. -+ * -+ * On success, returns the length of the string (not including the trailing -+ * NUL). -+ * -+ * If access to userspace fails, returns -EFAULT (some data may have been -+ * copied). -+ * -+ * If @count is smaller than the length of the string, copies @count bytes -+ * and returns @count. -+ */ -+ -+static inline int strncpy_from_user(char *dst, const char *src, int count) -+{ -+ return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, -+ dst, src, count)); -+} -+ -+/* -+ * __clear_user: - Zero a block of memory in user space, with less checking. -+ * @to: Destination address, in user space. -+ * @n: Number of bytes to zero. -+ * -+ * Zero a block of memory in user space. Caller must check -+ * the specified block with access_ok() before calling this function. -+ * -+ * Returns number of bytes that could not be cleared. -+ * On success, this will be zero. -+ */ -+static inline int __clear_user(void *mem, int len) -+{ -+ return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); -+} -+ -+/* -+ * clear_user: - Zero a block of memory in user space. -+ * @to: Destination address, in user space. -+ * @n: Number of bytes to zero. -+ * -+ * Zero a block of memory in user space. -+ * -+ * Returns number of bytes that could not be cleared. -+ * On success, this will be zero. -+ */ -+static inline int clear_user(void *mem, int len) -+{ -+ return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); -+} -+ -+/* -+ * strlen_user: - Get the size of a string in user space. -+ * @str: The string to measure. -+ * @n: The maximum valid length -+ * -+ * Get the size of a NUL-terminated string in user space. -+ * -+ * Returns the size of the string INCLUDING the terminating NUL. -+ * On exception, returns 0. -+ * If the string is too long, returns a value greater than @n. -+ */ -+static inline int strnlen_user(const void *str, int len) -+{ -+ return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/user.h um/arch/um/include/user.h ---- orig/arch/um/include/user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/user.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __USER_H__ -+#define __USER_H__ -+ -+extern void panic(const char *fmt, ...); -+extern int printk(const char *fmt, ...); -+extern void schedule(void); -+extern void *um_kmalloc(int size); -+extern void *um_kmalloc_atomic(int size); -+extern void kfree(void *ptr); -+extern int in_aton(char *str); -+extern int open_gdb_chan(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/include/user_util.h um/arch/um/include/user_util.h ---- orig/arch/um/include/user_util.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/include/user_util.h 2003-11-09 11:36:31.000000000 -0500 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __USER_UTIL_H__ -+#define __USER_UTIL_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int mode_tt; -+ -+extern int grantpt(int __fd); -+extern int unlockpt(int __fd); -+extern char *ptsname(int __fd); -+ -+struct cpu_task { -+ int pid; -+ void *task; -+}; -+ -+extern struct cpu_task cpu_tasks[]; -+ -+struct signal_info { -+ void (*handler)(int, union uml_pt_regs *); -+ int is_irq; -+}; -+ -+extern struct signal_info sig_info[]; -+ -+extern unsigned long low_physmem; -+extern unsigned long high_physmem; -+extern unsigned long uml_physmem; -+extern unsigned long uml_reserved; -+extern unsigned long end_vm; -+extern unsigned long start_vm; -+extern unsigned long highmem; -+ -+extern char host_info[]; -+ -+extern char saved_command_line[]; -+extern char command_line[]; -+ -+extern char *tempdir; -+ -+extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; -+extern unsigned long _unprotected_end; -+extern unsigned long brk_start; -+ -+extern int pty_output_sigio; -+extern int pty_close_sigio; -+ -+extern void stop(void); -+extern void stack_protections(unsigned long address); -+extern void task_protections(unsigned long address); -+extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); -+extern void *add_signal_handler(int sig, void (*handler)(int)); -+extern int start_fork_tramp(void *arg, unsigned long temp_stack, -+ int clone_flags, int (*tramp)(void *)); -+extern int linux_main(int argc, char **argv); -+extern void set_cmdline(char *cmd); -+extern void input_cb(void (*proc)(void *), void *arg, int arg_len); -+extern int get_pty(void); -+extern void *um_kmalloc(int size); -+extern int raw(int fd, int complain); -+extern int switcheroo(int fd, int prot, void *from, void *to, int size); -+extern void setup_machinename(char *machine_out); -+extern void setup_hostinfo(void); -+extern void add_arg(char *cmd_line, char *arg); -+extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); -+extern void init_new_thread_signals(int altstack); -+extern void do_exec(int old_pid, int new_pid); -+extern void tracer_panic(char *msg, ...); -+extern char *get_umid(int only_if_set); -+extern void do_longjmp(void *p, int val); -+extern void suspend_new_thread(int fd); -+extern int detach(int pid, int sig); -+extern int attach(int pid); -+extern void kill_child_dead(int pid); -+extern int cont(int pid); -+extern void check_ptrace(void); -+extern void check_sigio(void); -+extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); -+extern void write_sigio_workaround(void); -+extern void arch_check_bugs(void); -+extern int cpu_feature(char *what, char *buf, int len); -+extern int arch_handle_signal(int sig, union uml_pt_regs *regs); -+extern int arch_fixup(unsigned long address, void *sc_ptr); -+extern int can_do_skas(void); -+extern void arch_init_thread(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/checksum.c um/arch/um/kernel/checksum.c ---- orig/arch/um/kernel/checksum.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/checksum.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,42 @@ -+#include "asm/uaccess.h" -+#include "linux/errno.h" -+ -+extern unsigned int arch_csum_partial(const char *buff, int len, int sum); -+ -+extern unsigned int csum_partial(char *buff, int len, int sum) -+{ -+ return(arch_csum_partial(buff, len, sum)); -+} -+ -+unsigned int csum_partial_copy_to(const char *src, char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if(copy_to_user(dst, src, len)){ -+ *err_ptr = -EFAULT; -+ return(-1); -+ } -+ -+ return(arch_csum_partial(src, len, sum)); -+} -+ -+unsigned int csum_partial_copy_from(const char *src, char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if(copy_from_user(dst, src, len)){ -+ *err_ptr = -EFAULT; -+ return(-1); -+ } -+ -+ return(arch_csum_partial(dst, len, sum)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/config.c.in um/arch/um/kernel/config.c.in ---- orig/arch/um/kernel/config.c.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/config.c.in 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include "init.h" -+ -+static __initdata char *config = "CONFIG"; -+ -+static int __init print_config(char *line, int *add) -+{ -+ printf("%s", config); -+ exit(0); -+} -+ -+__uml_setup("--showconfig", print_config, -+"--showconfig\n" -+" Prints the config file that this UML binary was generated from.\n\n" -+); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/exec_kern.c um/arch/um/kernel/exec_kern.c ---- orig/arch/um/kernel/exec_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/exec_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/slab.h" -+#include "linux/smp_lock.h" -+#include "asm/ptrace.h" -+#include "asm/pgtable.h" -+#include "asm/pgalloc.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "mem_user.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "tlb.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "time_user.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+ -+void flush_thread(void) -+{ -+ CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); -+} -+ -+void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) -+{ -+ CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); -+} -+ -+extern void log_exec(char **argv, void *tty); -+ -+static int execve1(char *file, char **argv, char **env) -+{ -+ int error; -+ -+#ifdef CONFIG_TTY_LOG -+ log_exec(argv, current->tty); -+#endif -+ error = do_execve(file, argv, env, ¤t->thread.regs); -+ if (error == 0){ -+ current->ptrace &= ~PT_DTRACE; -+ set_cmdline(current_cmd()); -+ } -+ return(error); -+} -+ -+int um_execve(char *file, char **argv, char **env) -+{ -+ int err; -+ -+ err = execve1(file, argv, env); -+ if(!err) -+ do_longjmp(current->thread.exec_buf, 1); -+ return(err); -+} -+ -+int sys_execve(char *file, char **argv, char **env) -+{ -+ int error; -+ char *filename; -+ -+ lock_kernel(); -+ filename = getname((char *) file); -+ error = PTR_ERR(filename); -+ if (IS_ERR(filename)) goto out; -+ error = execve1(filename, argv, env); -+ putname(filename); -+ out: -+ unlock_kernel(); -+ return(error); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/exitcode.c um/arch/um/kernel/exitcode.c ---- orig/arch/um/kernel/exitcode.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/exitcode.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/ctype.h" -+#include "linux/proc_fs.h" -+#include "asm/uaccess.h" -+ -+/* If read and write race, the read will still atomically read a valid -+ * value. -+ */ -+int uml_exitcode = 0; -+ -+static int read_proc_exitcode(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len; -+ -+ len = sprintf(page, "%d\n", uml_exitcode); -+ len -= off; -+ if(len <= off+count) *eof = 1; -+ *start = page + off; -+ if(len > count) len = count; -+ if(len < 0) len = 0; -+ return(len); -+} -+ -+static int write_proc_exitcode(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char *end, buf[sizeof("nnnnn\0")]; -+ int tmp; -+ -+ if(copy_from_user(buf, buffer, count)) -+ return(-EFAULT); -+ tmp = simple_strtol(buf, &end, 0); -+ if((*end != '\0') && !isspace(*end)) -+ return(-EINVAL); -+ uml_exitcode = tmp; -+ return(count); -+} -+ -+static int make_proc_exitcode(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ ent = create_proc_entry("exitcode", 0600, &proc_root); -+ if(ent == NULL){ -+ printk("make_proc_exitcode : Failed to register " -+ "/proc/exitcode\n"); -+ return(0); -+ } -+ -+ ent->read_proc = read_proc_exitcode; -+ ent->write_proc = write_proc_exitcode; -+ -+ return(0); -+} -+ -+__initcall(make_proc_exitcode); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/frame.c um/arch/um/kernel/frame.c ---- orig/arch/um/kernel/frame.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/frame.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,341 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <signal.h> -+#include <wait.h> -+#include <sched.h> -+#include <errno.h> -+#include <sys/ptrace.h> -+#include <sys/syscall.h> -+#include <sys/mman.h> -+#include <asm/page.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+#include "frame_user.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+#include "os.h" -+ -+static int capture_stack(int (*child)(void *arg), void *arg, void *sp, -+ unsigned long top, void **data_out) -+{ -+ unsigned long regs[FRAME_SIZE]; -+ int pid, status, n, len; -+ -+ /* Start the child as a thread */ -+ pid = clone(child, sp, CLONE_VM | SIGCHLD, arg); -+ if(pid < 0){ -+ printf("capture_stack : clone failed - errno = %d\n", errno); -+ exit(1); -+ } -+ -+ /* Wait for it to stop itself and continue it with a SIGUSR1 to force -+ * it into the signal handler. -+ */ -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ fprintf(stderr, "capture_stack : Expected SIGSTOP, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ if(ptrace(PTRACE_CONT, pid, 0, SIGUSR1) < 0){ -+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ /* Wait for it to stop itself again and grab its registers again. -+ * At this point, the handler has stuffed the addresses of -+ * sig, sc, and SA_RESTORER in raw. -+ */ -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ fprintf(stderr, "capture_stack : Expected SIGSTOP, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0){ -+ printf("capture_stack : PTRACE_GETREGS failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ /* It has outlived its usefulness, so continue it so it can exit */ -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0){ -+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ if(waitpid(pid, &status, 0) < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){ -+ printf("capture_stack : Expected exit signal 9, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ -+ /* The frame that we want is the top of the signal stack */ -+ -+ len = top - PT_SP(regs); -+ *data_out = malloc(len); -+ if(*data_out == NULL){ -+ printf("capture_stack : malloc failed - errno = %d\n", errno); -+ exit(1); -+ } -+ memcpy(*data_out, (void *) PT_SP(regs), len); -+ -+ return(len); -+} -+ -+struct common_raw { -+ void *stack; -+ int size; -+ unsigned long sig; -+ unsigned long sr; -+ unsigned long sp; -+ struct arch_frame_data_raw arch; -+}; -+ -+#define SA_RESTORER (0x04000000) -+ -+typedef unsigned long old_sigset_t; -+ -+struct old_sigaction { -+ __sighandler_t handler; -+ old_sigset_t sa_mask; -+ unsigned long sa_flags; -+ void (*sa_restorer)(void); -+}; -+ -+static void child_common(struct common_raw *common, sighandler_t handler, -+ int restorer, int flags) -+{ -+ stack_t ss = ((stack_t) { .ss_sp = common->stack, -+ .ss_flags = 0, -+ .ss_size = common->size }); -+ int err; -+ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ printf("PTRACE_TRACEME failed, errno = %d\n", errno); -+ } -+ if(sigaltstack(&ss, NULL) < 0){ -+ printf("sigaltstack failed - errno = %d\n", errno); -+ kill(getpid(), SIGKILL); -+ } -+ -+ if(restorer){ -+ struct sigaction sa; -+ -+ sa.sa_handler = handler; -+ sigemptyset(&sa.sa_mask); -+ sa.sa_flags = SA_ONSTACK | flags; -+ err = sigaction(SIGUSR1, &sa, NULL); -+ } -+ else { -+ struct old_sigaction sa; -+ -+ sa.handler = handler; -+ sa.sa_mask = 0; -+ sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER; -+ err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL); -+ } -+ -+ if(err < 0){ -+ printf("sigaction failed - errno = %d\n", errno); -+ kill(getpid(), SIGKILL); -+ } -+ -+ os_stop_process(os_getpid()); -+} -+ -+/* Changed only during early boot */ -+struct sc_frame signal_frame_sc; -+ -+struct sc_frame signal_frame_sc_sr; -+ -+struct sc_frame_raw { -+ struct common_raw common; -+ unsigned long sc; -+ int restorer; -+}; -+ -+/* Changed only during early boot */ -+static struct sc_frame_raw *raw_sc = NULL; -+ -+static void sc_handler(int sig, struct sigcontext sc) -+{ -+ raw_sc->common.sig = (unsigned long) &sig; -+ raw_sc->common.sr = frame_restorer(); -+ raw_sc->common.sp = frame_sp(); -+ raw_sc->sc = (unsigned long) ≻ -+ setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr); -+ -+ os_stop_process(os_getpid()); -+ kill(getpid(), SIGKILL); -+} -+ -+static int sc_child(void *arg) -+{ -+ raw_sc = arg; -+ child_common(&raw_sc->common, (sighandler_t) sc_handler, -+ raw_sc->restorer, 0); -+ return(-1); -+} -+ -+/* Changed only during early boot */ -+struct si_frame signal_frame_si; -+ -+struct si_frame_raw { -+ struct common_raw common; -+ unsigned long sip; -+ unsigned long si; -+ unsigned long ucp; -+ unsigned long uc; -+}; -+ -+/* Changed only during early boot */ -+static struct si_frame_raw *raw_si = NULL; -+ -+static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext) -+{ -+ raw_si->common.sig = (unsigned long) &sig; -+ raw_si->common.sr = frame_restorer(); -+ raw_si->common.sp = frame_sp(); -+ raw_si->sip = (unsigned long) &si; -+ raw_si->si = (unsigned long) si; -+ raw_si->ucp = (unsigned long) &ucontext; -+ raw_si->uc = (unsigned long) ucontext; -+ setup_arch_frame_raw(&raw_si->common.arch, -+ ucontext->uc_mcontext.fpregs, raw_si->common.sr); -+ -+ os_stop_process(os_getpid()); -+ kill(getpid(), SIGKILL); -+} -+ -+static int si_child(void *arg) -+{ -+ raw_si = arg; -+ child_common(&raw_si->common, (sighandler_t) si_handler, 1, -+ SA_SIGINFO); -+ return(-1); -+} -+ -+static int relative_sr(unsigned long sr, int sr_index, void *stack, -+ void *framep) -+{ -+ unsigned long *srp = (unsigned long *) sr; -+ unsigned long frame = (unsigned long) framep; -+ -+ if((*srp & PAGE_MASK) == (unsigned long) stack){ -+ *srp -= sr; -+ *((unsigned long *) (frame + sr_index)) = *srp; -+ return(1); -+ } -+ else return(0); -+} -+ -+static unsigned long capture_stack_common(int (*proc)(void *), void *arg, -+ struct common_raw *common_in, -+ void *top, void *sigstack, -+ int stack_len, -+ struct frame_common *common_out) -+{ -+ unsigned long sig_top = (unsigned long) sigstack + stack_len, base; -+ -+ common_in->stack = (void *) sigstack; -+ common_in->size = stack_len; -+ common_out->len = capture_stack(proc, arg, top, sig_top, -+ &common_out->data); -+ base = sig_top - common_out->len; -+ common_out->sig_index = common_in->sig - base; -+ common_out->sp_index = common_in->sp - base; -+ common_out->sr_index = common_in->sr - base; -+ common_out->sr_relative = relative_sr(common_in->sr, -+ common_out->sr_index, sigstack, -+ common_out->data); -+ return(base); -+} -+ -+void capture_signal_stack(void) -+{ -+ struct sc_frame_raw raw_sc; -+ struct si_frame_raw raw_si; -+ void *stack, *sigstack; -+ unsigned long top, base; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ sigstack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if((stack == MAP_FAILED) || (sigstack == MAP_FAILED)){ -+ printf("capture_signal_stack : mmap failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ top = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ -+ /* Get the sigcontext, no sigrestorer layout */ -+ raw_sc.restorer = 0; -+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_sc.common); -+ -+ signal_frame_sc.sc_index = raw_sc.sc - base; -+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc.common.arch); -+ -+ /* Ditto for the sigcontext, sigrestorer layout */ -+ raw_sc.restorer = 1; -+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_sc_sr.common); -+ signal_frame_sc_sr.sc_index = raw_sc.sc - base; -+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc_sr.common.arch); -+ -+ /* And the siginfo layout */ -+ -+ base = capture_stack_common(si_child, &raw_si, &raw_si.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_si.common); -+ signal_frame_si.sip_index = raw_si.sip - base; -+ signal_frame_si.si_index = raw_si.si - base; -+ signal_frame_si.ucp_index = raw_si.ucp - base; -+ signal_frame_si.uc_index = raw_si.uc - base; -+ setup_arch_frame(&raw_si.common.arch, &signal_frame_si.common.arch); -+ -+ if((munmap(stack, PAGE_SIZE) < 0) || -+ (munmap(sigstack, PAGE_SIZE) < 0)){ -+ printf("capture_signal_stack : munmap failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/frame_kern.c um/arch/um/kernel/frame_kern.c ---- orig/arch/um/kernel/frame_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/frame_kern.c 2003-11-19 03:32:43.000000000 -0500 -@@ -0,0 +1,174 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/signal.h" -+#include "asm/uaccess.h" -+#include "asm/ucontext.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "sysdep/ptrace.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) -+{ -+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) -+ return -EFAULT; -+ if (from->si_code < 0) -+ return __copy_to_user(to, from, sizeof(siginfo_t)); -+ else { -+ int err; -+ -+ /* If you change siginfo_t structure, please be sure -+ this code is fixed accordingly. -+ It should never copy any pad contained in the structure -+ to avoid security leaks, but must copy the generic -+ 3 ints plus the relevant union member. */ -+ err = __put_user(from->si_signo, &to->si_signo); -+ err |= __put_user(from->si_errno, &to->si_errno); -+ err |= __put_user((short)from->si_code, &to->si_code); -+ /* First 32bits of unions are always present. */ -+ err |= __put_user(from->si_pid, &to->si_pid); -+ switch (from->si_code >> 16) { -+ case __SI_FAULT >> 16: -+ break; -+ case __SI_CHLD >> 16: -+ err |= __put_user(from->si_utime, &to->si_utime); -+ err |= __put_user(from->si_stime, &to->si_stime); -+ err |= __put_user(from->si_status, &to->si_status); -+ default: -+ err |= __put_user(from->si_uid, &to->si_uid); -+ break; -+ } -+ return err; -+ } -+} -+ -+static int copy_restorer(void (*restorer)(void), unsigned long start, -+ unsigned long sr_index, int sr_relative) -+{ -+ unsigned long sr; -+ -+ if(sr_relative){ -+ sr = (unsigned long) restorer; -+ sr += start + sr_index; -+ restorer = (void (*)(void)) sr; -+ } -+ -+ return(copy_to_user((void *) (start + sr_index), &restorer, -+ sizeof(restorer))); -+} -+ -+extern int userspace_pid[]; -+ -+static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, -+ struct arch_frame_data *arch) -+{ -+ return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), -+ arch), -+ copy_sc_to_user_skas(userspace_pid[0], to, fp, -+ &from->regs, -+ current->thread.cr2, -+ current->thread.err))); -+} -+ -+static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set, -+ unsigned long sp) -+{ -+ int err = 0; -+ -+ err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); -+ err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); -+ err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); -+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, -+ &signal_frame_si.common.arch); -+ err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); -+ return(err); -+} -+ -+int setup_signal_stack_si(unsigned long stack_top, int sig, -+ unsigned long handler, void (*restorer)(void), -+ struct pt_regs *regs, siginfo_t *info, -+ sigset_t *mask) -+{ -+ unsigned long start; -+ void *sip, *ucp, *fp; -+ -+ start = stack_top - signal_frame_si.common.len; -+ sip = (void *) (start + signal_frame_si.si_index); -+ ucp = (void *) (start + signal_frame_si.uc_index); -+ fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext)); -+ -+ if(restorer == NULL) -+ panic("setup_signal_stack_si - no restorer"); -+ -+ if(copy_to_user((void *) start, signal_frame_si.common.data, -+ signal_frame_si.common.len) || -+ copy_to_user((void *) (start + signal_frame_si.common.sig_index), -+ &sig, sizeof(sig)) || -+ copy_siginfo_to_user(sip, info) || -+ copy_to_user((void *) (start + signal_frame_si.sip_index), &sip, -+ sizeof(sip)) || -+ copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) || -+ copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp, -+ sizeof(ucp)) || -+ copy_restorer(restorer, start, signal_frame_si.common.sr_index, -+ signal_frame_si.common.sr_relative)) -+ return(1); -+ -+ PT_REGS_IP(regs) = handler; -+ PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index; -+ return(0); -+} -+ -+int setup_signal_stack_sc(unsigned long stack_top, int sig, -+ unsigned long handler, void (*restorer)(void), -+ struct pt_regs *regs, sigset_t *mask) -+{ -+ struct frame_common *frame = &signal_frame_sc_sr.common; -+ void *user_sc; -+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); -+ unsigned long sigs, sr; -+ unsigned long start = stack_top - frame->len - sig_size; -+ -+ user_sc = (void *) (start + signal_frame_sc_sr.sc_index); -+ if(restorer == NULL){ -+ frame = &signal_frame_sc.common; -+ user_sc = (void *) (start + signal_frame_sc.sc_index); -+ sr = (unsigned long) frame->data; -+ sr += frame->sr_index; -+ sr = *((unsigned long *) sr); -+ restorer = ((void (*)(void)) sr); -+ } -+ -+ sigs = start + frame->len; -+ if(copy_to_user((void *) start, frame->data, frame->len) || -+ copy_to_user((void *) (start + frame->sig_index), &sig, -+ sizeof(sig)) || -+ copy_sc_to_user(user_sc, NULL, regs, -+ &signal_frame_sc.common.arch) || -+ copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) || -+ copy_to_user((void *) sigs, &mask->sig[1], sig_size) || -+ copy_restorer(restorer, start, frame->sr_index, frame->sr_relative)) -+ return(1); -+ -+ PT_REGS_IP(regs) = handler; -+ PT_REGS_SP(regs) = start + frame->sp_index; -+ -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/gmon_syms.c um/arch/um/kernel/gmon_syms.c ---- orig/arch/um/kernel/gmon_syms.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/gmon_syms.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+ -+extern void __bb_init_func(void *); -+EXPORT_SYMBOL(__bb_init_func); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/gprof_syms.c um/arch/um/kernel/gprof_syms.c ---- orig/arch/um/kernel/gprof_syms.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/gprof_syms.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+ -+extern void mcount(void); -+EXPORT_SYMBOL(mcount); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/helper.c um/arch/um/kernel/helper.c ---- orig/arch/um/kernel/helper.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/helper.c 2003-11-08 07:41:30.000000000 -0500 -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <sched.h> -+#include <sys/signal.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "kern_util.h" -+#include "os.h" -+ -+struct helper_data { -+ void (*pre_exec)(void*); -+ void *pre_data; -+ char **argv; -+ int fd; -+}; -+ -+/* Debugging aid, changed only from gdb */ -+int helper_pause = 0; -+ -+static void helper_hup(int sig) -+{ -+} -+ -+static int helper_child(void *arg) -+{ -+ struct helper_data *data = arg; -+ char **argv = data->argv; -+ int errval; -+ -+ if(helper_pause){ -+ signal(SIGHUP, helper_hup); -+ pause(); -+ } -+ if(data->pre_exec != NULL) -+ (*data->pre_exec)(data->pre_data); -+ execvp(argv[0], argv); -+ errval = errno; -+ printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); -+ os_write_file(data->fd, &errval, sizeof(errval)); -+ os_kill_process(os_getpid(), 0); -+ return(0); -+} -+ -+/* XXX The alloc_stack here breaks if this is called in the tracing thread */ -+ -+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, -+ unsigned long *stack_out) -+{ -+ struct helper_data data; -+ unsigned long stack, sp; -+ int pid, fds[2], err, n; -+ -+ if((stack_out != NULL) && (*stack_out != 0)) -+ stack = *stack_out; -+ else stack = alloc_stack(0, um_in_interrupt()); -+ if(stack == 0) -+ return(-ENOMEM); -+ -+ err = os_pipe(fds, 1, 0); -+ if(err < 0){ -+ printk("run_helper : pipe failed, err = %d\n", -err); -+ goto out_free; -+ } -+ -+ err = os_set_exec_close(fds[1], 1); -+ if(err < 0){ -+ printk("run_helper : setting FD_CLOEXEC failed, err = %d\n", -+ -err); -+ goto out_close; -+ } -+ -+ sp = stack + page_size() - sizeof(void *); -+ data.pre_exec = pre_exec; -+ data.pre_data = pre_data; -+ data.argv = argv; -+ data.fd = fds[1]; -+ pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); -+ if(pid < 0){ -+ printk("run_helper : clone failed, errno = %d\n", errno); -+ err = -errno; -+ goto out_close; -+ } -+ -+ os_close_file(fds[1]); -+ n = os_read_file(fds[0], &err, sizeof(err)); -+ if(n < 0){ -+ printk("run_helper : read on pipe failed, err = %d\n", -n); -+ err = n; -+ goto out_kill; -+ } -+ else if(n != 0){ -+ waitpid(pid, NULL, 0); -+ pid = -errno; -+ } -+ -+ if(stack_out == NULL) free_stack(stack, 0); -+ else *stack_out = stack; -+ return(pid); -+ -+ out_kill: -+ os_kill_process(pid, 1); -+ out_close: -+ os_close_file(fds[0]); -+ os_close_file(fds[1]); -+ out_free: -+ free_stack(stack, 0); -+ return(err); -+} -+ -+int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, -+ unsigned long *stack_out, int stack_order) -+{ -+ unsigned long stack, sp; -+ int pid, status; -+ -+ stack = alloc_stack(stack_order, um_in_interrupt()); -+ if(stack == 0) return(-ENOMEM); -+ -+ sp = stack + (page_size() << stack_order) - sizeof(void *); -+ pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); -+ if(pid < 0){ -+ printk("run_helper_thread : clone failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ if(stack_out == NULL){ -+ pid = waitpid(pid, &status, 0); -+ if(pid < 0){ -+ printk("run_helper_thread - wait failed, errno = %d\n", -+ errno); -+ pid = -errno; -+ } -+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) -+ printk("run_helper_thread - thread returned status " -+ "0x%x\n", status); -+ free_stack(stack, stack_order); -+ } -+ else *stack_out = stack; -+ return(pid); -+} -+ -+int helper_wait(int pid, int block) -+{ -+ int ret; -+ -+ ret = waitpid(pid, NULL, WNOHANG); -+ if(ret < 0){ -+ printk("helper_wait : waitpid failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/initrd_kern.c um/arch/um/kernel/initrd_kern.c ---- orig/arch/um/kernel/initrd_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/initrd_kern.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/bootmem.h" -+#include "linux/blk.h" -+#include "asm/types.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "initrd.h" -+#include "init.h" -+#include "os.h" -+ -+/* Changed by uml_initrd_setup, which is a setup */ -+static char *initrd __initdata = NULL; -+ -+static int __init read_initrd(void) -+{ -+ void *area; -+ long long size; -+ int err; -+ -+ if(initrd == NULL) return 0; -+ err = os_file_size(initrd, &size); -+ if(err) return 0; -+ area = alloc_bootmem(size); -+ if(area == NULL) return 0; -+ if(load_initrd(initrd, area, size) == -1) return 0; -+ initrd_start = (unsigned long) area; -+ initrd_end = initrd_start + size; -+ return 0; -+} -+ -+__uml_postsetup(read_initrd); -+ -+static int __init uml_initrd_setup(char *line, int *add) -+{ -+ initrd = line; -+ return 0; -+} -+ -+__uml_setup("initrd=", uml_initrd_setup, -+"initrd=<initrd image>\n" -+" This is used to boot UML from an initrd image. The argument is the\n" -+" name of the file containing the image.\n\n" -+); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/initrd_user.c um/arch/um/kernel/initrd_user.c ---- orig/arch/um/kernel/initrd_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/initrd_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <errno.h> -+ -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "initrd.h" -+#include "os.h" -+ -+int load_initrd(char *filename, void *buf, int size) -+{ -+ int fd, n; -+ -+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Opening '%s' failed - err = %d\n", filename, -fd); -+ return(-1); -+ } -+ n = os_read_file(fd, buf, size); -+ if(n != size){ -+ printk("Read of %d bytes from '%s' failed, err = %d\n", size, -+ filename, -n); -+ return(-1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/init_task.c um/arch/um/kernel/init_task.c ---- orig/arch/um/kernel/init_task.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/init_task.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "linux/sched.h" -+#include "linux/version.h" -+#include "asm/uaccess.h" -+#include "asm/pgtable.h" -+#include "user_util.h" -+#include "mem_user.h" -+ -+static struct fs_struct init_fs = INIT_FS; -+static struct files_struct init_files = INIT_FILES; -+static struct signal_struct init_signals = INIT_SIGNALS; -+struct mm_struct init_mm = INIT_MM(init_mm); -+ -+/* -+ * Initial task structure. -+ * -+ * We need to make sure that this is 16384-byte aligned due to the -+ * way process stacks are handled. This is done by having a special -+ * "init_task" linker map entry.. -+ */ -+ -+union task_union init_task_union -+__attribute__((__section__(".data.init_task"))) = -+{ INIT_TASK(init_task_union.task) }; -+ -+struct task_struct *alloc_task_struct(void) -+{ -+ return((struct task_struct *) -+ __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER)); -+} -+ -+void unprotect_stack(unsigned long stack) -+{ -+ protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, -+ 1, 1, 0, 1); -+} -+ -+void free_task_struct(struct task_struct *task) -+{ -+ /* free_pages decrements the page counter and only actually frees -+ * the pages if they are now not accessed by anything. -+ */ -+ free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/irq.c um/arch/um/kernel/irq.c ---- orig/arch/um/kernel/irq.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/irq.c 2003-12-16 22:45:27.000000000 -0500 -@@ -0,0 +1,840 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: -+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "linux/irq.h" -+#include "linux/kernel_stat.h" -+#include "linux/interrupt.h" -+#include "linux/random.h" -+#include "linux/slab.h" -+#include "linux/file.h" -+#include "linux/proc_fs.h" -+#include "linux/init.h" -+#include "linux/seq_file.h" -+#include "asm/irq.h" -+#include "asm/hw_irq.h" -+#include "asm/hardirq.h" -+#include "asm/atomic.h" -+#include "asm/signal.h" -+#include "asm/system.h" -+#include "asm/errno.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+ -+static void register_irq_proc (unsigned int irq); -+ -+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = -+ { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; -+ -+/* -+ * Generic no controller code -+ */ -+ -+static void enable_none(unsigned int irq) { } -+static unsigned int startup_none(unsigned int irq) { return 0; } -+static void disable_none(unsigned int irq) { } -+static void ack_none(unsigned int irq) -+{ -+/* -+ * 'what should we do if we get a hw irq event on an illegal vector'. -+ * each architecture has to answer this themselves, it doesnt deserve -+ * a generic callback i think. -+ */ -+#if CONFIG_X86 -+ printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); -+#ifdef CONFIG_X86_LOCAL_APIC -+ /* -+ * 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. -+ */ -+ ack_APIC_irq(); -+#endif -+#endif -+} -+ -+/* startup is the same as "enable", shutdown is same as "disable" */ -+#define shutdown_none disable_none -+#define end_none enable_none -+ -+struct hw_interrupt_type no_irq_type = { -+ "none", -+ startup_none, -+ shutdown_none, -+ enable_none, -+ disable_none, -+ ack_none, -+ end_none -+}; -+ -+/* -+ * Generic, controller-independent functions: -+ */ -+ -+int get_irq_list(char *buf) -+{ -+ int i, j; -+ unsigned long flags; -+ struct irqaction * action; -+ char *p = buf; -+ -+ p += sprintf(p, " "); -+ for (j=0; j<smp_num_cpus; j++) -+ p += sprintf(p, "CPU%d ",j); -+ *p++ = '\n'; -+ -+ for (i = 0 ; i < NR_IRQS ; i++) { -+ spin_lock_irqsave(&irq_desc[i].lock, flags); -+ action = irq_desc[i].action; -+ if (!action) -+ goto end; -+ p += sprintf(p, "%3d: ",i); -+#ifndef CONFIG_SMP -+ p += sprintf(p, "%10u ", kstat_irqs(i)); -+#else -+ for (j = 0; j < smp_num_cpus; j++) -+ p += sprintf(p, "%10u ", -+ kstat.irqs[cpu_logical_map(j)][i]); -+#endif -+ p += sprintf(p, " %14s", irq_desc[i].handler->typename); -+ p += sprintf(p, " %s", action->name); -+ -+ for (action=action->next; action; action = action->next) -+ p += sprintf(p, ", %s", action->name); -+ *p++ = '\n'; -+ end: -+ spin_unlock_irqrestore(&irq_desc[i].lock, flags); -+ } -+ p += sprintf(p, "\n"); -+#ifdef notdef -+#if CONFIG_SMP -+ p += sprintf(p, "LOC: "); -+ for (j = 0; j < smp_num_cpus; j++) -+ p += sprintf(p, "%10u ", -+ apic_timer_irqs[cpu_logical_map(j)]); -+ p += sprintf(p, "\n"); -+#endif -+#endif -+ p += sprintf(p, "ERR: %10lu\n", 0L); -+ return p - buf; -+} -+ -+/* -+ * This should really return information about whether -+ * we should do bottom half handling etc. Right now we -+ * end up _always_ checking the bottom half, which is a -+ * waste of time and is not what some drivers would -+ * prefer. -+ */ -+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, -+ struct irqaction * action) -+{ -+ int status; -+ int cpu = smp_processor_id(); -+ -+ irq_enter(cpu, irq); -+ -+ status = 1; /* Force the "do bottom halves" bit */ -+ -+ if (!(action->flags & SA_INTERRUPT)) -+ __sti(); -+ -+ do { -+ status |= action->flags; -+ action->handler(irq, action->dev_id, regs); -+ action = action->next; -+ } while (action); -+ if (status & SA_SAMPLE_RANDOM) -+ add_interrupt_randomness(irq); -+ __cli(); -+ -+ irq_exit(cpu, irq); -+ -+ return status; -+} -+ -+/* -+ * Generic enable/disable code: this just calls -+ * down into the PIC-specific version for the actual -+ * hardware disable after having gotten the irq -+ * controller lock. -+ */ -+ -+/** -+ * disable_irq_nosync - disable an irq without waiting -+ * @irq: Interrupt to disable -+ * -+ * Disable the selected interrupt line. Disables of an interrupt -+ * stack. Unlike disable_irq(), this function does not ensure existing -+ * instances of the IRQ handler have completed before returning. -+ * -+ * This function may be called from IRQ context. -+ */ -+ -+void inline disable_irq_nosync(unsigned int irq) -+{ -+ irq_desc_t *desc = irq_desc + irq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&desc->lock, flags); -+ if (!desc->depth++) { -+ desc->status |= IRQ_DISABLED; -+ desc->handler->disable(irq); -+ } -+ spin_unlock_irqrestore(&desc->lock, flags); -+} -+ -+/** -+ * disable_irq - disable an irq and wait for completion -+ * @irq: Interrupt to disable -+ * -+ * Disable the selected interrupt line. Disables of an interrupt -+ * stack. That is for two disables you need two enables. This -+ * function waits for any pending IRQ handlers for this interrupt -+ * to complete before returning. If you use this function while -+ * holding a resource the IRQ handler may need you will deadlock. -+ * -+ * This function may be called - with care - from IRQ context. -+ */ -+ -+void disable_irq(unsigned int irq) -+{ -+ disable_irq_nosync(irq); -+ -+ if (!local_irq_count(smp_processor_id())) { -+ do { -+ barrier(); -+ } while (irq_desc[irq].status & IRQ_INPROGRESS); -+ } -+} -+ -+/** -+ * enable_irq - enable interrupt handling on an irq -+ * @irq: Interrupt to enable -+ * -+ * Re-enables the processing of interrupts on this IRQ line -+ * providing no disable_irq calls are now in effect. -+ * -+ * This function may be called from IRQ context. -+ */ -+ -+void enable_irq(unsigned int irq) -+{ -+ irq_desc_t *desc = irq_desc + irq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&desc->lock, flags); -+ switch (desc->depth) { -+ case 1: { -+ unsigned int status = desc->status & ~IRQ_DISABLED; -+ desc->status = status; -+ if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { -+ desc->status = status | IRQ_REPLAY; -+ hw_resend_irq(desc->handler,irq); -+ } -+ desc->handler->enable(irq); -+ /* fall-through */ -+ } -+ default: -+ desc->depth--; -+ break; -+ case 0: -+ printk(KERN_ERR "enable_irq() unbalanced from %p\n", -+ __builtin_return_address(0)); -+ } -+ spin_unlock_irqrestore(&desc->lock, flags); -+} -+ -+/* -+ * do_IRQ handles all normal device IRQ's (the special -+ * SMP cross-CPU interrupts have their own specific -+ * handlers). -+ */ -+unsigned int do_IRQ(int irq, union uml_pt_regs *regs) -+{ -+ /* -+ * 0 return value means that this irq is already being -+ * handled by some other CPU. (or is disabled) -+ */ -+ int cpu = smp_processor_id(); -+ irq_desc_t *desc = irq_desc + irq; -+ struct irqaction * action; -+ unsigned int status; -+ -+ kstat.irqs[cpu][irq]++; -+ spin_lock(&desc->lock); -+ desc->handler->ack(irq); -+ /* -+ REPLAY is when Linux resends an IRQ that was dropped earlier -+ WAITING is used by probe to mark irqs that are being tested -+ */ -+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); -+ status |= IRQ_PENDING; /* we _want_ to handle it */ -+ -+ /* -+ * If the IRQ is disabled for whatever reason, we cannot -+ * use the action we have. -+ */ -+ action = NULL; -+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { -+ action = desc->action; -+ status &= ~IRQ_PENDING; /* we commit to handling */ -+ status |= IRQ_INPROGRESS; /* we are handling it */ -+ } -+ desc->status = status; -+ -+ /* -+ * If there is no IRQ handler or it was disabled, exit early. -+ Since we set PENDING, if another processor is handling -+ a different instance of this same irq, the other processor -+ will take care of it. -+ */ -+ if (!action) -+ goto out; -+ -+ /* -+ * Edge triggered interrupts need to remember -+ * pending events. -+ * This applies to any hw interrupts that allow a second -+ * instance of the same irq to arrive while we are in do_IRQ -+ * or in the handler. But the code here only handles the _second_ -+ * instance of the irq, not the third or fourth. So it is mostly -+ * useful for irq hardware that does not mask cleanly in an -+ * SMP environment. -+ */ -+ for (;;) { -+ spin_unlock(&desc->lock); -+ handle_IRQ_event(irq, (struct pt_regs *) regs, action); -+ spin_lock(&desc->lock); -+ -+ if (!(desc->status & IRQ_PENDING)) -+ break; -+ desc->status &= ~IRQ_PENDING; -+ } -+ desc->status &= ~IRQ_INPROGRESS; -+out: -+ /* -+ * The ->end() handler has to deal with interrupts which got -+ * disabled while the handler was running. -+ */ -+ desc->handler->end(irq); -+ spin_unlock(&desc->lock); -+ -+ if (softirq_pending(cpu)) -+ do_softirq(); -+ return 1; -+} -+ -+/** -+ * request_irq - allocate an interrupt line -+ * @irq: Interrupt line to allocate -+ * @handler: Function to be called when the IRQ occurs -+ * @irqflags: Interrupt type flags -+ * @devname: An ascii name for the claiming device -+ * @dev_id: A cookie passed back to the handler function -+ * -+ * This call allocates interrupt resources and enables the -+ * interrupt line and IRQ handling. From the point this -+ * call is made your handler function may be invoked. Since -+ * your handler function must clear any interrupt the board -+ * raises, you must take care both to initialise your hardware -+ * and to set up the interrupt handler in the right order. -+ * -+ * Dev_id must be globally unique. Normally the address of the -+ * device data structure is used as the cookie. Since the handler -+ * receives this value it makes sense to use it. -+ * -+ * If your interrupt is shared you must pass a non NULL dev_id -+ * as this is required when freeing the interrupt. -+ * -+ * Flags: -+ * -+ * SA_SHIRQ Interrupt is shared -+ * -+ * SA_INTERRUPT Disable local interrupts while processing -+ * -+ * SA_SAMPLE_RANDOM The interrupt can be used for entropy -+ * -+ */ -+ -+int request_irq(unsigned int irq, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ const char * devname, -+ void *dev_id) -+{ -+ int retval; -+ struct irqaction * action; -+ -+#if 1 -+ /* -+ * Sanity-check: shared interrupts should REALLY pass in -+ * a real dev-ID, otherwise we'll have trouble later trying -+ * to figure out which interrupt is which (messes up the -+ * interrupt freeing logic etc). -+ */ -+ if (irqflags & SA_SHIRQ) { -+ if (!dev_id) -+ printk(KERN_ERR "Bad boy: %s (at 0x%x) called us " -+ "without a dev_id!\n", devname, (&irq)[-1]); -+ } -+#endif -+ -+ if (irq >= NR_IRQS) -+ return -EINVAL; -+ if (!handler) -+ return -EINVAL; -+ -+ action = (struct irqaction *) -+ kmalloc(sizeof(struct irqaction), GFP_KERNEL); -+ if (!action) -+ return -ENOMEM; -+ -+ action->handler = handler; -+ action->flags = irqflags; -+ action->mask = 0; -+ action->name = devname; -+ action->next = NULL; -+ action->dev_id = dev_id; -+ -+ retval = setup_irq(irq, action); -+ if (retval) -+ kfree(action); -+ return retval; -+} -+ -+int um_request_irq(unsigned int irq, int fd, int type, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, const char * devname, -+ void *dev_id) -+{ -+ int err; -+ -+ err = request_irq(irq, handler, irqflags, devname, dev_id); -+ if(err) -+ return(err); -+ -+ if(fd != -1) -+ err = activate_fd(irq, fd, type, dev_id); -+ return(err); -+} -+ -+/* this was setup_x86_irq but it seems pretty generic */ -+int setup_irq(unsigned int irq, struct irqaction * new) -+{ -+ int shared = 0; -+ unsigned long flags; -+ struct irqaction *old, **p; -+ irq_desc_t *desc = irq_desc + irq; -+ -+ /* -+ * Some drivers like serial.c use request_irq() heavily, -+ * so we have to be careful not to interfere with a -+ * running system. -+ */ -+ if (new->flags & SA_SAMPLE_RANDOM) { -+ /* -+ * This function might sleep, we want to call it first, -+ * outside of the atomic block. -+ * Yes, this might clear the entropy pool if the wrong -+ * driver is attempted to be loaded, without actually -+ * installing a new handler, but is this really a problem, -+ * only the sysadmin is able to do this. -+ */ -+ rand_initialize_irq(irq); -+ } -+ -+ /* -+ * The following block of code has to be executed atomically -+ */ -+ spin_lock_irqsave(&desc->lock,flags); -+ p = &desc->action; -+ old = *p; -+ if (old != NULL) { -+ /* Can't share interrupts unless both agree to */ -+ if (!(old->flags & new->flags & SA_SHIRQ)) { -+ spin_unlock_irqrestore(&desc->lock,flags); -+ return -EBUSY; -+ } -+ -+ /* add new interrupt at end of irq queue */ -+ do { -+ p = &old->next; -+ old = *p; -+ } while (old); -+ shared = 1; -+ } -+ -+ *p = new; -+ -+ if (!shared) { -+ desc->depth = 0; -+ desc->status &= ~IRQ_DISABLED; -+ desc->handler->startup(irq); -+ } -+ spin_unlock_irqrestore(&desc->lock,flags); -+ -+ register_irq_proc(irq); -+ return 0; -+} -+ -+/** -+ * free_irq - free an interrupt -+ * @irq: Interrupt line to free -+ * @dev_id: Device identity to free -+ * -+ * Remove an interrupt handler. The handler is removed and if the -+ * interrupt line is no longer in use by any driver it is disabled. -+ * On a shared IRQ the caller must ensure the interrupt is disabled -+ * on the card it drives before calling this function. The function -+ * does not return until any executing interrupts for this IRQ -+ * have completed. -+ * -+ * This function may be called from interrupt context. -+ * -+ * Bugs: Attempting to free an irq in a handler for the same irq hangs -+ * the machine. -+ */ -+ -+void free_irq(unsigned int irq, void *dev_id) -+{ -+ irq_desc_t *desc; -+ struct irqaction **p; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS) -+ return; -+ -+ desc = irq_desc + irq; -+ spin_lock_irqsave(&desc->lock,flags); -+ p = &desc->action; -+ for (;;) { -+ struct irqaction * action = *p; -+ if (action) { -+ struct irqaction **pp = p; -+ p = &action->next; -+ if (action->dev_id != dev_id) -+ continue; -+ -+ /* Found it - now remove it from the list of entries */ -+ *pp = action->next; -+ if (!desc->action) { -+ desc->status |= IRQ_DISABLED; -+ desc->handler->shutdown(irq); -+ } -+ free_irq_by_irq_and_dev(irq, dev_id); -+ spin_unlock_irqrestore(&desc->lock,flags); -+ -+#ifdef CONFIG_SMP -+ /* Wait to make sure it's not being used on another CPU */ -+ while (desc->status & IRQ_INPROGRESS) -+ barrier(); -+#endif -+ kfree(action); -+ return; -+ } -+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq); -+ spin_unlock_irqrestore(&desc->lock,flags); -+ return; -+ } -+} -+ -+/* These are initialized by sysctl_init, which is called from init/main.c */ -+static struct proc_dir_entry * root_irq_dir; -+static struct proc_dir_entry * irq_dir [NR_IRQS]; -+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; -+ -+/* These are read and written as longs, so a read won't see a partial write -+ * even during a race. -+ */ -+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; -+ -+#define HEX_DIGITS 8 -+ -+static int irq_affinity_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ if (count < HEX_DIGITS+1) -+ return -EINVAL; -+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]); -+} -+ -+static unsigned int parse_hex_value (const char *buffer, -+ unsigned long count, unsigned long *ret) -+{ -+ unsigned char hexnum [HEX_DIGITS]; -+ unsigned long value; -+ int i; -+ -+ if (!count) -+ return -EINVAL; -+ if (count > HEX_DIGITS) -+ count = HEX_DIGITS; -+ if (copy_from_user(hexnum, buffer, count)) -+ return -EFAULT; -+ -+ /* -+ * Parse the first HEX_DIGITS characters as a hex string, any non-hex -+ * char is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. -+ */ -+ value = 0; -+ -+ for (i = 0; i < count; i++) { -+ unsigned int c = hexnum[i]; -+ -+ switch (c) { -+ case '0' ... '9': c -= '0'; break; -+ case 'a' ... 'f': c -= 'a'-10; break; -+ case 'A' ... 'F': c -= 'A'-10; break; -+ default: -+ goto out; -+ } -+ value = (value << 4) | c; -+ } -+out: -+ *ret = value; -+ return 0; -+} -+ -+static int irq_affinity_write_proc (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ int irq = (long) data, full_count = count, err; -+ unsigned long new_value; -+ -+ if (!irq_desc[irq].handler->set_affinity) -+ return -EIO; -+ -+ err = parse_hex_value(buffer, count, &new_value); -+ -+#if CONFIG_SMP -+ /* -+ * Do not allow disabling IRQs completely - it's a too easy -+ * way to make the system unusable accidentally :-) At least -+ * one online CPU still has to be targeted. -+ */ -+ if (!(new_value & cpu_online_map)) -+ return -EINVAL; -+#endif -+ -+ irq_affinity[irq] = new_value; -+ irq_desc[irq].handler->set_affinity(irq, new_value); -+ -+ return full_count; -+} -+ -+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ unsigned long *mask = (unsigned long *) data; -+ if (count < HEX_DIGITS+1) -+ return -EINVAL; -+ return sprintf (page, "%08lx\n", *mask); -+} -+ -+static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ unsigned long *mask = (unsigned long *) data, full_count = count, err; -+ unsigned long new_value; -+ -+ err = parse_hex_value(buffer, count, &new_value); -+ if (err) -+ return err; -+ -+ *mask = new_value; -+ return full_count; -+} -+ -+#define MAX_NAMELEN 10 -+ -+static void register_irq_proc (unsigned int irq) -+{ -+ struct proc_dir_entry *entry; -+ char name [MAX_NAMELEN]; -+ -+ if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || -+ irq_dir[irq]) -+ return; -+ -+ memset(name, 0, MAX_NAMELEN); -+ sprintf(name, "%d", irq); -+ -+ /* create /proc/irq/1234 */ -+ irq_dir[irq] = proc_mkdir(name, root_irq_dir); -+ -+ /* create /proc/irq/1234/smp_affinity */ -+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); -+ -+ entry->nlink = 1; -+ entry->data = (void *)(long)irq; -+ entry->read_proc = irq_affinity_read_proc; -+ entry->write_proc = irq_affinity_write_proc; -+ -+ smp_affinity_entry[irq] = entry; -+} -+ -+/* Read and written as a long */ -+unsigned long prof_cpu_mask = -1; -+ -+void __init init_irq_proc (void) -+{ -+ struct proc_dir_entry *entry; -+ int i; -+ -+ /* create /proc/irq */ -+ root_irq_dir = proc_mkdir("irq", 0); -+ -+ /* create /proc/irq/prof_cpu_mask */ -+ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); -+ -+ entry->nlink = 1; -+ entry->data = (void *)&prof_cpu_mask; -+ entry->read_proc = prof_cpu_mask_read_proc; -+ entry->write_proc = prof_cpu_mask_write_proc; -+ -+ /* -+ * Create entries for all existing IRQs. -+ */ -+ for (i = 0; i < NR_IRQS; i++) -+ register_irq_proc(i); -+} -+ -+static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED; -+ -+unsigned long irq_lock(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&irq_spinlock, flags); -+ return(flags); -+} -+ -+void irq_unlock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&irq_spinlock, flags); -+} -+ -+unsigned long probe_irq_on(void) -+{ -+ return(0); -+} -+ -+int probe_irq_off(unsigned long val) -+{ -+ return(0); -+} -+ -+static unsigned int startup_SIGIO_irq(unsigned int irq) -+{ -+ return(0); -+} -+ -+static void shutdown_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void enable_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void disable_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void mask_and_ack_SIGIO(unsigned int irq) -+{ -+} -+ -+static void end_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static unsigned int startup_SIGVTALRM_irq(unsigned int irq) -+{ -+ return(0); -+} -+ -+static void shutdown_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void enable_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void disable_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void mask_and_ack_SIGVTALRM(unsigned int irq) -+{ -+} -+ -+static void end_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static struct hw_interrupt_type SIGIO_irq_type = { -+ "SIGIO", -+ startup_SIGIO_irq, -+ shutdown_SIGIO_irq, -+ enable_SIGIO_irq, -+ disable_SIGIO_irq, -+ mask_and_ack_SIGIO, -+ end_SIGIO_irq, -+ NULL -+}; -+ -+static struct hw_interrupt_type SIGVTALRM_irq_type = { -+ "SIGVTALRM", -+ startup_SIGVTALRM_irq, -+ shutdown_SIGVTALRM_irq, -+ enable_SIGVTALRM_irq, -+ disable_SIGVTALRM_irq, -+ mask_and_ack_SIGVTALRM, -+ end_SIGVTALRM_irq, -+ NULL -+}; -+ -+void __init init_IRQ(void) -+{ -+ int i; -+ -+ irq_desc[TIMER_IRQ].status = IRQ_DISABLED; -+ irq_desc[TIMER_IRQ].action = 0; -+ irq_desc[TIMER_IRQ].depth = 1; -+ irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type; -+ enable_irq(TIMER_IRQ); -+ for(i=1;i<NR_IRQS;i++){ -+ irq_desc[i].status = IRQ_DISABLED; -+ irq_desc[i].action = 0; -+ irq_desc[i].depth = 1; -+ irq_desc[i].handler = &SIGIO_irq_type; -+ enable_irq(i); -+ } -+ init_irq_signals(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/irq_user.c um/arch/um/kernel/irq_user.c ---- orig/arch/um/kernel/irq_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/irq_user.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,424 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <signal.h> -+#include <string.h> -+#include <sys/poll.h> -+#include <sys/types.h> -+#include <sys/time.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_user.h" -+#include "sigio.h" -+#include "irq_user.h" -+#include "os.h" -+ -+struct irq_fd { -+ struct irq_fd *next; -+ void *id; -+ int fd; -+ int type; -+ int irq; -+ int pid; -+ int events; -+ int current_events; -+ int freed; -+}; -+ -+static struct irq_fd *active_fds = NULL; -+static struct irq_fd **last_irq_ptr = &active_fds; -+ -+static struct pollfd *pollfds = NULL; -+static int pollfds_num = 0; -+static int pollfds_size = 0; -+ -+extern int io_count, intr_count; -+ -+void sigio_handler(int sig, union uml_pt_regs *regs) -+{ -+ struct irq_fd *irq_fd, *next; -+ int i, n; -+ -+ if(smp_sigio_handler()) return; -+ while(1){ -+ n = poll(pollfds, pollfds_num, 0); -+ if(n < 0){ -+ if(errno == EINTR) continue; -+ printk("sigio_handler : poll returned %d, " -+ "errno = %d\n", n, errno); -+ break; -+ } -+ if(n == 0) break; -+ -+ irq_fd = active_fds; -+ for(i = 0; i < pollfds_num; i++){ -+ if(pollfds[i].revents != 0){ -+ irq_fd->current_events = pollfds[i].revents; -+ pollfds[i].fd = -1; -+ } -+ irq_fd = irq_fd->next; -+ } -+ -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ -+ next = irq_fd->next; -+ if(irq_fd->current_events != 0){ -+ irq_fd->current_events = 0; -+ do_IRQ(irq_fd->irq, regs); -+ -+ /* This is here because the next irq may be -+ * freed in the handler. If a console goes -+ * away, both the read and write irqs will be -+ * freed. After do_IRQ, ->next will point to -+ * a good IRQ. -+ * Irqs can't be freed inside their handlers, -+ * so the next best thing is to have them -+ * marked as needing freeing, so that they -+ * can be freed here. -+ */ -+ next = irq_fd->next; -+ if(irq_fd->freed) -+ free_irq(irq_fd->irq, irq_fd->id); -+ } -+ } -+ } -+} -+ -+int activate_ipi(int fd, int pid) -+{ -+ return(os_set_fd_async(fd, pid)); -+} -+ -+static void maybe_sigio_broken(int fd, int type) -+{ -+ if(isatty(fd)){ -+ if((type == IRQ_WRITE) && !pty_output_sigio){ -+ write_sigio_workaround(); -+ add_sigio_fd(fd, 0); -+ } -+ else if((type == IRQ_READ) && !pty_close_sigio){ -+ write_sigio_workaround(); -+ add_sigio_fd(fd, 1); -+ } -+ } -+} -+ -+int activate_fd(int irq, int fd, int type, void *dev_id) -+{ -+ struct pollfd *tmp_pfd; -+ struct irq_fd *new_fd, *irq_fd; -+ unsigned long flags; -+ int pid, events, err, n, size; -+ -+ pid = os_getpid(); -+ err = os_set_fd_async(fd, pid); -+ if(err < 0) -+ goto out; -+ -+ new_fd = um_kmalloc(sizeof(*new_fd)); -+ err = -ENOMEM; -+ if(new_fd == NULL) -+ goto out; -+ -+ if(type == IRQ_READ) events = POLLIN | POLLPRI; -+ else events = POLLOUT; -+ *new_fd = ((struct irq_fd) { .next = NULL, -+ .id = dev_id, -+ .fd = fd, -+ .type = type, -+ .irq = irq, -+ .pid = pid, -+ .events = events, -+ .current_events = 0, -+ .freed = 0 } ); -+ -+ /* Critical section - locked by a spinlock because this stuff can -+ * be changed from interrupt handlers. The stuff above is done -+ * outside the lock because it allocates memory. -+ */ -+ -+ /* Actually, it only looks like it can be called from interrupt -+ * context. The culprit is reactivate_fd, which calls -+ * maybe_sigio_broken, which calls write_sigio_workaround, -+ * which calls activate_fd. However, write_sigio_workaround should -+ * only be called once, at boot time. That would make it clear that -+ * this is called only from process context, and can be locked with -+ * a semaphore. -+ */ -+ flags = irq_lock(); -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ -+ if((irq_fd->fd == fd) && (irq_fd->type == type)){ -+ printk("Registering fd %d twice\n", fd); -+ printk("Irqs : %d, %d\n", irq_fd->irq, irq); -+ printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id); -+ goto out_unlock; -+ } -+ } -+ -+ n = pollfds_num; -+ if(n == pollfds_size){ -+ while(1){ -+ /* Here we have to drop the lock in order to call -+ * kmalloc, which might sleep. If something else -+ * came in and changed the pollfds array, we free -+ * the buffer and try again. -+ */ -+ irq_unlock(flags); -+ size = (pollfds_num + 1) * sizeof(pollfds[0]); -+ tmp_pfd = um_kmalloc(size); -+ flags = irq_lock(); -+ if(tmp_pfd == NULL) -+ goto out_unlock; -+ if(n == pollfds_size) -+ break; -+ kfree(tmp_pfd); -+ } -+ if(pollfds != NULL){ -+ memcpy(tmp_pfd, pollfds, -+ sizeof(pollfds[0]) * pollfds_size); -+ kfree(pollfds); -+ } -+ pollfds = tmp_pfd; -+ pollfds_size++; -+ } -+ -+ if(type == IRQ_WRITE) -+ fd = -1; -+ -+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, -+ .events = events, -+ .revents = 0 }); -+ pollfds_num++; -+ -+ *last_irq_ptr = new_fd; -+ last_irq_ptr = &new_fd->next; -+ -+ irq_unlock(flags); -+ -+ /* This calls activate_fd, so it has to be outside the critical -+ * section. -+ */ -+ maybe_sigio_broken(fd, type); -+ -+ return(0); -+ -+ out_unlock: -+ irq_unlock(flags); -+ kfree(new_fd); -+ out: -+ return(err); -+} -+ -+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) -+{ -+ struct irq_fd **prev; -+ unsigned long flags; -+ int i = 0; -+ -+ flags = irq_lock(); -+ prev = &active_fds; -+ while(*prev != NULL){ -+ if((*test)(*prev, arg)){ -+ struct irq_fd *old_fd = *prev; -+ if((pollfds[i].fd != -1) && -+ (pollfds[i].fd != (*prev)->fd)){ -+ printk("free_irq_by_cb - mismatch between " -+ "active_fds and pollfds, fd %d vs %d\n", -+ (*prev)->fd, pollfds[i].fd); -+ goto out; -+ } -+ memcpy(&pollfds[i], &pollfds[i + 1], -+ (pollfds_num - i - 1) * sizeof(pollfds[0])); -+ pollfds_num--; -+ if(last_irq_ptr == &old_fd->next) -+ last_irq_ptr = prev; -+ *prev = (*prev)->next; -+ if(old_fd->type == IRQ_WRITE) -+ ignore_sigio_fd(old_fd->fd); -+ kfree(old_fd); -+ continue; -+ } -+ prev = &(*prev)->next; -+ i++; -+ } -+ out: -+ irq_unlock(flags); -+} -+ -+struct irq_and_dev { -+ int irq; -+ void *dev; -+}; -+ -+static int same_irq_and_dev(struct irq_fd *irq, void *d) -+{ -+ struct irq_and_dev *data = d; -+ -+ return((irq->irq == data->irq) && (irq->id == data->dev)); -+} -+ -+void free_irq_by_irq_and_dev(int irq, void *dev) -+{ -+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, -+ .dev = dev }); -+ -+ free_irq_by_cb(same_irq_and_dev, &data); -+} -+ -+static int same_fd(struct irq_fd *irq, void *fd) -+{ -+ return(irq->fd == *((int *) fd)); -+} -+ -+void free_irq_by_fd(int fd) -+{ -+ free_irq_by_cb(same_fd, &fd); -+} -+ -+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) -+{ -+ struct irq_fd *irq; -+ int i = 0; -+ -+ for(irq=active_fds; irq != NULL; irq = irq->next){ -+ if((irq->fd == fd) && (irq->irq == irqnum)) break; -+ i++; -+ } -+ if(irq == NULL){ -+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd); -+ goto out; -+ } -+ if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){ -+ printk("find_irq_by_fd - mismatch between active_fds and " -+ "pollfds, fd %d vs %d, need %d\n", irq->fd, -+ pollfds[i].fd, fd); -+ irq = NULL; -+ goto out; -+ } -+ *index_out = i; -+ out: -+ return(irq); -+} -+ -+void free_irq_later(int irq, void *dev_id) -+{ -+ struct irq_fd *irq_fd; -+ unsigned long flags; -+ -+ flags = irq_lock(); -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ -+ if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) -+ break; -+ } -+ if(irq_fd == NULL){ -+ printk("free_irq_later found no irq, irq = %d, " -+ "dev_id = 0x%p\n", irq, dev_id); -+ goto out; -+ } -+ irq_fd->freed = 1; -+ out: -+ irq_unlock(flags); -+} -+ -+void reactivate_fd(int fd, int irqnum) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int i; -+ -+ flags = irq_lock(); -+ irq = find_irq_by_fd(fd, irqnum, &i); -+ if(irq == NULL){ -+ irq_unlock(flags); -+ return; -+ } -+ -+ pollfds[i].fd = irq->fd; -+ -+ irq_unlock(flags); -+ -+ /* This calls activate_fd, so it has to be outside the critical -+ * section. -+ */ -+ maybe_sigio_broken(fd, irq->type); -+} -+ -+void deactivate_fd(int fd, int irqnum) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int i; -+ -+ flags = irq_lock(); -+ irq = find_irq_by_fd(fd, irqnum, &i); -+ if(irq == NULL) -+ goto out; -+ pollfds[i].fd = -1; -+ out: -+ irq_unlock(flags); -+} -+ -+void forward_ipi(int fd, int pid) -+{ -+ int err; -+ -+ err = os_set_owner(fd, pid); -+ if(err < 0) -+ printk("forward_ipi: set_owner failed, fd = %d, me = %d, " -+ "target = %d, err = %d\n", fd, os_getpid(), pid, -err); -+} -+ -+void forward_interrupts(int pid) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int err; -+ -+ flags = irq_lock(); -+ for(irq=active_fds;irq != NULL;irq = irq->next){ -+ err = os_set_owner(irq->fd, pid); -+ if(err < 0){ -+ /* XXX Just remove the irq rather than -+ * print out an infinite stream of these -+ */ -+ printk("Failed to forward %d to pid %d, err = %d\n", -+ irq->fd, pid, -err); -+ } -+ -+ irq->pid = pid; -+ } -+ irq_unlock(flags); -+} -+ -+void init_irq_signals(int on_sigstack) -+{ -+ __sighandler_t h; -+ int flags; -+ -+ flags = on_sigstack ? SA_ONSTACK : 0; -+ if(timer_irq_inited) h = (__sighandler_t) alarm_handler; -+ else h = boot_timer_handler; -+ -+ set_handler(SIGVTALRM, h, flags | SA_RESTART, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); -+ set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ signal(SIGWINCH, SIG_IGN); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/ksyms.c um/arch/um/kernel/ksyms.c ---- orig/arch/um/kernel/ksyms.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/ksyms.c 2004-01-23 00:44:09.000000000 -0500 -@@ -0,0 +1,120 @@ -+/* -+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/module.h" -+#include "linux/string.h" -+#include "linux/smp_lock.h" -+#include "linux/spinlock.h" -+#include "asm/current.h" -+#include "asm/delay.h" -+#include "asm/processor.h" -+#include "asm/unistd.h" -+#include "asm/pgalloc.h" -+#include "asm/pgtable.h" -+#include "asm/page.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "helper.h" -+ -+EXPORT_SYMBOL(stop); -+EXPORT_SYMBOL(strtok); -+EXPORT_SYMBOL(uml_physmem); -+EXPORT_SYMBOL(set_signals); -+EXPORT_SYMBOL(get_signals); -+EXPORT_SYMBOL(kernel_thread); -+EXPORT_SYMBOL(__const_udelay); -+EXPORT_SYMBOL(__udelay); -+EXPORT_SYMBOL(sys_waitpid); -+EXPORT_SYMBOL(task_size); -+EXPORT_SYMBOL(flush_tlb_range); -+EXPORT_SYMBOL(host_task_size); -+EXPORT_SYMBOL(arch_validate); -+EXPORT_SYMBOL(get_kmem_end); -+ -+EXPORT_SYMBOL(high_physmem); -+EXPORT_SYMBOL(empty_zero_page); -+EXPORT_SYMBOL(um_virt_to_phys); -+EXPORT_SYMBOL(__virt_to_page); -+EXPORT_SYMBOL(to_phys); -+EXPORT_SYMBOL(to_virt); -+EXPORT_SYMBOL(mode_tt); -+EXPORT_SYMBOL(handle_page_fault); -+ -+#ifdef CONFIG_MODE_TT -+EXPORT_SYMBOL(copy_from_user_tt); -+EXPORT_SYMBOL(copy_to_user_tt); -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+EXPORT_SYMBOL(copy_to_user_skas); -+EXPORT_SYMBOL(copy_from_user_skas); -+#endif -+ -+EXPORT_SYMBOL(os_stat_fd); -+EXPORT_SYMBOL(os_stat_file); -+EXPORT_SYMBOL(os_access); -+EXPORT_SYMBOL(os_print_error); -+EXPORT_SYMBOL(os_get_exec_close); -+EXPORT_SYMBOL(os_set_exec_close); -+EXPORT_SYMBOL(os_getpid); -+EXPORT_SYMBOL(os_open_file); -+EXPORT_SYMBOL(os_read_file); -+EXPORT_SYMBOL(os_write_file); -+EXPORT_SYMBOL(os_seek_file); -+EXPORT_SYMBOL(os_lock_file); -+EXPORT_SYMBOL(os_pipe); -+EXPORT_SYMBOL(os_file_type); -+EXPORT_SYMBOL(os_file_mode); -+EXPORT_SYMBOL(os_file_size); -+EXPORT_SYMBOL(os_flush_stdout); -+EXPORT_SYMBOL(os_close_file); -+EXPORT_SYMBOL(os_set_fd_async); -+EXPORT_SYMBOL(os_set_fd_block); -+EXPORT_SYMBOL(helper_wait); -+EXPORT_SYMBOL(os_shutdown_socket); -+EXPORT_SYMBOL(os_create_unix_socket); -+EXPORT_SYMBOL(os_connect_socket); -+EXPORT_SYMBOL(os_accept_connection); -+EXPORT_SYMBOL(os_ioctl_generic); -+EXPORT_SYMBOL(os_rcv_fd); -+EXPORT_SYMBOL(run_helper); -+EXPORT_SYMBOL(start_thread); -+EXPORT_SYMBOL(dump_thread); -+ -+/* This is here because UML expands open to sys_open, not to a system -+ * call instruction. -+ */ -+EXPORT_SYMBOL(sys_open); -+EXPORT_SYMBOL(sys_lseek); -+EXPORT_SYMBOL(sys_read); -+EXPORT_SYMBOL(sys_wait4); -+ -+#ifdef CONFIG_SMP -+ -+/* required for SMP */ -+ -+extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); -+EXPORT_SYMBOL_NOVERS(__write_lock_failed); -+ -+extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); -+EXPORT_SYMBOL_NOVERS(__read_lock_failed); -+ -+EXPORT_SYMBOL(kernel_flag_cacheline); -+EXPORT_SYMBOL(smp_num_cpus); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/Makefile um/arch/um/kernel/Makefile ---- orig/arch/um/kernel/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/Makefile 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,73 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = config.o checksum.o exec_kern.o exitcode.o frame_kern.o frame.o \ -+ helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \ -+ physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \ -+ sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \ -+ syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \ -+ time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \ -+ um_arch.o umid.o user_syms.o user_util.o -+ -+obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o -+obj-$(CONFIG_GPROF) += gprof_syms.o -+obj-$(CONFIG_GCOV) += gmon_syms.o -+obj-$(CONFIG_TTY_LOG) += tty_log.o -+ -+subdir-$(CONFIG_MODE_TT) += tt -+subdir-$(CONFIG_MODE_SKAS) += skas -+ -+user-objs-$(CONFIG_TTY_LOG) += tty_log.o -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+# user_syms.o not included here because Rules.make has its own ideas about -+# building anything in export-objs -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \ -+ process.o tempfile.o time.o umid.o user_util.o -+ -+DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__ -+DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__ -+ -+export-objs-$(CONFIG_GPROF) += gprof_syms.o -+export-objs-$(CONFIG_GCOV) += gmon_syms.o -+ -+export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o $(export-objs-y) -+ -+CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \ -+ -I/usr/include -I../include -+ -+CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+# This has to be separate because it needs be compiled with frame pointers -+# regardless of how the rest of the kernel is built. -+ -+frame.o: frame.c -+ $(CC) $(CFLAGS_$@) -c -o $@ $< -+ -+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }' -+ -+config.c : config.c.in $(TOPDIR)/.config -+ $(PERL) -e $(QUOTE) < config.c.in > $@ -+ -+clean: -+ $(RM) config.c -+ for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done -+ -+modules: -+ -+fastdep: -+ -+dep: -+ -+archmrproper: clean -diff -Naur -X ../exclude-files orig/arch/um/kernel/mem.c um/arch/um/kernel/mem.c ---- orig/arch/um/kernel/mem.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/mem.c 2003-12-22 01:25:00.000000000 -0500 -@@ -0,0 +1,336 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/mm.h" -+#include "linux/bootmem.h" -+#include "linux/highmem.h" -+#include "asm/page.h" -+#include "asm/fixmap.h" -+#include "asm/pgalloc.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mem_user.h" -+#include "uml_uaccess.h" -+#include "os.h" -+ -+extern char __binary_start; -+ -+/* Changed during early boot */ -+unsigned long *empty_zero_page = NULL; -+unsigned long *empty_bad_page = NULL; -+pgd_t swapper_pg_dir[1024]; -+unsigned long highmem; -+int kmalloc_ok = 0; -+ -+static unsigned long brk_end; -+static unsigned long totalram_pages = 0; -+ -+void unmap_physmem(void) -+{ -+ os_unmap_memory((void *) brk_end, uml_reserved - brk_end); -+} -+ -+static void map_cb(void *unused) -+{ -+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); -+} -+ -+#ifdef CONFIG_HIGHMEM -+static void setup_highmem(unsigned long highmem_start, -+ unsigned long highmem_len) -+{ -+ struct page *page; -+ unsigned long highmem_pfn; -+ int i; -+ -+ highmem_start_page = virt_to_page(highmem_start); -+ -+ highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; -+ for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ -+ page = &mem_map[highmem_pfn + i]; -+ ClearPageReserved(page); -+ set_bit(PG_highmem, &page->flags); -+ atomic_set(&page->count, 1); -+ __free_page(page); -+ } -+} -+#endif -+ -+void mem_init(void) -+{ -+ unsigned long start; -+ -+ /* clear the zero-page */ -+ memset((void *) empty_zero_page, 0, PAGE_SIZE); -+ -+ /* Map in the area just after the brk now that kmalloc is about -+ * to be turned on. -+ */ -+ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); -+ map_cb(NULL); -+ initial_thread_cb(map_cb, NULL); -+ free_bootmem(__pa(brk_end), uml_reserved - brk_end); -+ uml_reserved = brk_end; -+ -+ /* Fill in any hole at the start of the binary */ -+ start = (unsigned long) &__binary_start; -+ if(uml_physmem != start){ -+ map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem, -+ 1, 1, 0); -+ } -+ -+ /* this will put all low memory onto the freelists */ -+ totalram_pages = free_all_bootmem(); -+ totalram_pages += highmem >> PAGE_SHIFT; -+ num_physpages = totalram_pages; -+ printk(KERN_INFO "Memory: %luk available\n", -+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); -+ kmalloc_ok = 1; -+ -+#ifdef CONFIG_HIGHMEM -+ setup_highmem(end_iomem, highmem); -+#endif -+} -+ -+static void __init fixrange_init(unsigned long start, unsigned long end, -+ pgd_t *pgd_base) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ int i, j; -+ unsigned long vaddr; -+ -+ vaddr = start; -+ i = __pgd_offset(vaddr); -+ j = __pmd_offset(vaddr); -+ pgd = pgd_base + i; -+ -+ for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { -+ pmd = (pmd_t *)pgd; -+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { -+ if (pmd_none(*pmd)) { -+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); -+ set_pmd(pmd, __pmd(_KERNPG_TABLE + -+ (unsigned long) __pa(pte))); -+ if (pte != pte_offset(pmd, 0)) -+ BUG(); -+ } -+ vaddr += PMD_SIZE; -+ } -+ j = 0; -+ } -+} -+ -+#ifdef CONFIG_HIGHMEM -+pte_t *kmap_pte; -+pgprot_t kmap_prot; -+ -+#define kmap_get_fixmap_pte(vaddr) \ -+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) -+ -+void __init kmap_init(void) -+{ -+ unsigned long kmap_vstart; -+ -+ /* cache the first kmap pte */ -+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); -+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart); -+ -+ kmap_prot = PAGE_KERNEL; -+} -+ -+static void init_highmem(void) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long vaddr; -+ -+ /* -+ * Permanent kmaps: -+ */ -+ vaddr = PKMAP_BASE; -+ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir); -+ -+ pgd = swapper_pg_dir + __pgd_offset(vaddr); -+ pmd = pmd_offset(pgd, vaddr); -+ pte = pte_offset(pmd, vaddr); -+ pkmap_page_table = pte; -+ -+ kmap_init(); -+} -+ -+#endif /* CONFIG_HIGHMEM */ -+ -+void paging_init(void) -+{ -+ unsigned long zones_size[MAX_NR_ZONES], vaddr; -+ int i; -+ -+ empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); -+ empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); -+ for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) -+ zones_size[i] = 0; -+ zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); -+ zones_size[2] = highmem >> PAGE_SHIFT; -+ free_area_init(zones_size); -+ -+ /* -+ * Fixed mappings, only the page table structure has to be -+ * created - mappings will be set by set_fixmap(): -+ */ -+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; -+ fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir); -+ -+#if CONFIG_HIGHMEM -+ init_highmem(); -+#endif -+} -+ -+struct page *arch_validate(struct page *page, int mask, int order) -+{ -+ unsigned long addr, zero = 0; -+ int i; -+ -+ again: -+ if(page == NULL) return(page); -+ if(PageHighMem(page)) return(page); -+ -+ addr = (unsigned long) page_address(page); -+ for(i = 0; i < (1 << order); i++){ -+ current->thread.fault_addr = (void *) addr; -+ if(__do_copy_to_user((void *) addr, &zero, -+ sizeof(zero), -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)){ -+ if(!(mask & __GFP_WAIT)) return(NULL); -+ else break; -+ } -+ addr += PAGE_SIZE; -+ } -+ if(i == (1 << order)) return(page); -+ page = _alloc_pages(mask, order); -+ goto again; -+} -+ -+/* This can't do anything because nothing in the kernel image can be freed -+ * since it's not in kernel physical memory. -+ */ -+ -+void free_initmem(void) -+{ -+} -+ -+#ifdef CONFIG_BLK_DEV_INITRD -+ -+void free_initrd_mem(unsigned long start, unsigned long end) -+{ -+ if (start < end) -+ printk ("Freeing initrd memory: %ldk freed\n", -+ (end - start) >> 10); -+ for (; start < end; start += PAGE_SIZE) { -+ ClearPageReserved(virt_to_page(start)); -+ set_page_count(virt_to_page(start), 1); -+ free_page(start); -+ totalram_pages++; -+ } -+} -+ -+#endif -+ -+int do_check_pgt_cache(int low, int high) -+{ -+ int freed = 0; -+ if(pgtable_cache_size > high) { -+ do { -+ if (pgd_quicklist) { -+ free_pgd_slow(get_pgd_fast()); -+ freed++; -+ } -+ if (pmd_quicklist) { -+ pmd_free_slow(pmd_alloc_one_fast(NULL, 0)); -+ freed++; -+ } -+ if (pte_quicklist) { -+ pte_free_slow(pte_alloc_one_fast(NULL, 0)); -+ freed++; -+ } -+ } while(pgtable_cache_size > low); -+ } -+ return freed; -+} -+ -+void show_mem(void) -+{ -+ int i, total = 0, reserved = 0; -+ int shared = 0, cached = 0; -+ int highmem = 0; -+ -+ printk("Mem-info:\n"); -+ show_free_areas(); -+ printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); -+ i = max_mapnr; -+ while(i-- > 0) { -+ total++; -+ if(PageHighMem(mem_map + i)) -+ highmem++; -+ if(PageReserved(mem_map + i)) -+ reserved++; -+ else if(PageSwapCache(mem_map + i)) -+ cached++; -+ else if(page_count(mem_map + i)) -+ shared += page_count(mem_map + i) - 1; -+ } -+ printk("%d pages of RAM\n", total); -+ printk("%d pages of HIGHMEM\n", highmem); -+ printk("%d reserved pages\n", reserved); -+ printk("%d pages shared\n", shared); -+ printk("%d pages swap cached\n", cached); -+ printk("%ld pages in page table cache\n", pgtable_cache_size); -+ show_buffers(); -+} -+ -+/* Changed by meminfo_compat, which is a setup */ -+static int meminfo_22 = 0; -+ -+static int meminfo_compat(char *str) -+{ -+ meminfo_22 = 1; -+ return(1); -+} -+ -+__setup("22_meminfo", meminfo_compat); -+ -+void si_meminfo(struct sysinfo *val) -+{ -+ val->totalram = totalram_pages; -+ val->sharedram = 0; -+ val->freeram = nr_free_pages(); -+ val->bufferram = atomic_read(&buffermem_pages); -+ val->totalhigh = highmem >> PAGE_SHIFT; -+ val->freehigh = nr_free_highpages(); -+ val->mem_unit = PAGE_SIZE; -+ if(meminfo_22){ -+ val->freeram <<= PAGE_SHIFT; -+ val->bufferram <<= PAGE_SHIFT; -+ val->totalram <<= PAGE_SHIFT; -+ val->sharedram <<= PAGE_SHIFT; -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/mem_user.c um/arch/um/kernel/mem_user.c ---- orig/arch/um/kernel/mem_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/mem_user.c 2004-01-10 00:19:09.000000000 -0500 -@@ -0,0 +1,216 @@ -+/* -+ * arch/um/kernel/mem_user.c -+ * -+ * BRIEF MODULE DESCRIPTION -+ * user side memory routines for supporting IO memory inside user mode linux -+ * -+ * Copyright (C) 2001 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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. -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stddef.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <errno.h> -+#include <string.h> -+#include <fcntl.h> -+#include <sys/types.h> -+#include <sys/mman.h> -+#include "kern_util.h" -+#include "user.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "init.h" -+#include "os.h" -+#include "tempfile.h" -+#include "kern_constants.h" -+ -+extern struct mem_region physmem_region; -+ -+#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" -+ -+static int create_tmp_file(unsigned long len) -+{ -+ int fd, err; -+ char zero; -+ -+ fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); -+ if(fd < 0) { -+ os_print_error(fd, "make_tempfile"); -+ exit(1); -+ } -+ -+ err = os_mode_fd(fd, 0777); -+ if(err < 0){ -+ os_print_error(err, "os_mode_fd"); -+ exit(1); -+ } -+ err = os_seek_file(fd, len); -+ if(err < 0){ -+ os_print_error(err, "os_seek_file"); -+ exit(1); -+ } -+ zero = 0; -+ err = os_write_file(fd, &zero, 1); -+ if(err != 1){ -+ os_print_error(err, "os_write_file"); -+ exit(1); -+ } -+ -+ return(fd); -+} -+ -+static int have_devanon(void) -+{ -+ int fd; -+ -+ printk("Checking for /dev/anon on the host..."); -+ fd = open("/dev/anon", O_RDWR); -+ if(fd < 0){ -+ printk("Not available (open failed with errno %d)\n", errno); -+ return(0); -+ } -+ -+ printk("OK\n"); -+ return(1); -+} -+ -+static int create_anon_file(unsigned long len) -+{ -+ void *addr; -+ int fd; -+ -+ fd = open("/dev/anon", O_RDWR); -+ if(fd < 0) { -+ os_print_error(fd, "opening /dev/anon"); -+ exit(1); -+ } -+ -+ addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0); -+ if(addr == MAP_FAILED){ -+ os_print_error((int) addr, "mapping physmem file"); -+ exit(1); -+ } -+ munmap(addr, len); -+ -+ return(fd); -+} -+ -+int create_mem_file(unsigned long len) -+{ -+ int err, fd; -+ -+ if(have_devanon()) -+ fd = create_anon_file(len); -+ else fd = create_tmp_file(len); -+ -+ err = os_set_exec_close(fd, 1); -+ if(err < 0) -+ os_print_error(err, "exec_close"); -+ return(fd); -+} -+ -+struct iomem_region *iomem_regions = NULL; -+int iomem_size = 0; -+ -+static int __init parse_iomem(char *str, int *add) -+{ -+ struct iomem_region *new; -+ struct uml_stat buf; -+ char *file, *driver; -+ int fd, err; -+ -+ driver = str; -+ file = strchr(str,','); -+ if(file == NULL){ -+ printf("parse_iomem : failed to parse iomem\n"); -+ goto out; -+ } -+ *file = '\0'; -+ file++; -+ fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); -+ if(fd < 0){ -+ os_print_error(fd, "parse_iomem - Couldn't open io file"); -+ goto out; -+ } -+ -+ err = os_stat_fd(fd, &buf); -+ if(err < 0){ -+ os_print_error(err, "parse_iomem - cannot stat_fd file"); -+ goto out_close; -+ } -+ -+ new = malloc(sizeof(*new)); -+ if(new == NULL){ -+ perror("Couldn't allocate iomem_region struct"); -+ goto out_close; -+ } -+ -+ *new = ((struct iomem_region) { .next = iomem_regions, -+ .driver = driver, -+ .fd = fd, -+ .size = buf.ust_size, -+ .phys = 0, -+ .virt = 0 }); -+ iomem_regions = new; -+ iomem_size += new->size + UM_KERN_PAGE_SIZE; -+ -+ return(0); -+ out_close: -+ os_close_file(fd); -+ out: -+ return(1); -+} -+ -+__uml_setup("iomem=", parse_iomem, -+"iomem=<name>,<file>\n" -+" Configure <file> as an IO memory region named <name>.\n\n" -+); -+ -+int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, -+ int must_succeed) -+{ -+ int err; -+ -+ err = os_protect_memory((void *) addr, len, r, w, x); -+ if(err < 0){ -+ if(must_succeed) -+ panic("protect failed, err = %d", -err); -+ else return(err); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/mprot.h um/arch/um/kernel/mprot.h ---- orig/arch/um/kernel/mprot.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/mprot.h 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __MPROT_H__ -+#define __MPROT_H__ -+ -+extern void no_access(unsigned long addr, unsigned int len); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/kernel/physmem.c um/arch/um/kernel/physmem.c ---- orig/arch/um/kernel/physmem.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/physmem.c 2004-01-16 23:38:02.000000000 -0500 -@@ -0,0 +1,446 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/mm.h" -+#include "linux/ghash.h" -+#include "linux/slab.h" -+#include "linux/vmalloc.h" -+#include "linux/bootmem.h" -+#include "asm/types.h" -+#include "asm/pgtable.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "mode_kern.h" -+#include "mem.h" -+#include "mem_user.h" -+#include "os.h" -+#include "kern.h" -+#include "init.h" -+ -+#define PHYS_HASHSIZE (8192) -+ -+struct phys_desc; -+ -+DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc); -+ -+struct phys_desc { -+ struct virtmem_ptrs virt_ptrs; -+ int fd; -+ __u64 offset; -+ void *virt; -+ unsigned long phys; -+ struct list_head list; -+}; -+ -+struct virtmem_table virtmem_hash; -+ -+static int virt_cmp(void *virt1, void *virt2) -+{ -+ return(virt1 != virt2); -+} -+ -+static int virt_hash(void *virt) -+{ -+ unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT; -+ return(addr % PHYS_HASHSIZE); -+} -+ -+DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp, -+ virt_hash); -+ -+LIST_HEAD(descriptor_mappings); -+ -+struct desc_mapping { -+ int fd; -+ struct list_head list; -+ struct list_head pages; -+}; -+ -+static struct desc_mapping *find_mapping(int fd) -+{ -+ struct desc_mapping *desc; -+ struct list_head *ele; -+ -+ list_for_each(ele, &descriptor_mappings){ -+ desc = list_entry(ele, struct desc_mapping, list); -+ if(desc->fd == fd) -+ return(desc); -+ } -+ -+ return(NULL); -+} -+ -+static struct desc_mapping *descriptor_mapping(int fd) -+{ -+ struct desc_mapping *desc; -+ -+ desc = find_mapping(fd); -+ if(desc != NULL) -+ return(desc); -+ -+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC); -+ if(desc == NULL) -+ return(NULL); -+ -+ *desc = ((struct desc_mapping) -+ { .fd = fd, -+ .list = LIST_HEAD_INIT(desc->list), -+ .pages = LIST_HEAD_INIT(desc->pages) }); -+ list_add(&desc->list, &descriptor_mappings); -+ -+ return(desc); -+} -+ -+int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) -+{ -+ struct desc_mapping *fd_maps; -+ struct phys_desc *desc; -+ unsigned long phys; -+ int err; -+ -+ fd_maps = descriptor_mapping(fd); -+ if(fd_maps == NULL) -+ return(-ENOMEM); -+ -+ phys = __pa(virt); -+ if(find_virtmem_hash(&virtmem_hash, virt) != NULL) -+ panic("Address 0x%p is already substituted\n", virt); -+ -+ err = -ENOMEM; -+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC); -+ if(desc == NULL) -+ goto out; -+ -+ *desc = ((struct phys_desc) -+ { .virt_ptrs = { NULL, NULL }, -+ .fd = fd, -+ .offset = offset, -+ .virt = virt, -+ .phys = __pa(virt), -+ .list = LIST_HEAD_INIT(desc->list) }); -+ insert_virtmem_hash(&virtmem_hash, desc); -+ -+ list_add(&desc->list, &fd_maps->pages); -+ -+ virt = (void *) ((unsigned long) virt & PAGE_MASK); -+ err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0); -+ if(!err) -+ goto out; -+ -+ remove_virtmem_hash(&virtmem_hash, desc); -+ kfree(desc); -+ out: -+ return(err); -+} -+ -+static int physmem_fd = -1; -+ -+static void remove_mapping(struct phys_desc *desc) -+{ -+ void *virt = desc->virt; -+ int err; -+ -+ remove_virtmem_hash(&virtmem_hash, desc); -+ list_del(&desc->list); -+ kfree(desc); -+ -+ err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0); -+ if(err) -+ panic("Failed to unmap block device page from physical memory, " -+ "errno = %d", -err); -+} -+ -+int physmem_remove_mapping(void *virt) -+{ -+ struct phys_desc *desc; -+ -+ virt = (void *) ((unsigned long) virt & PAGE_MASK); -+ desc = find_virtmem_hash(&virtmem_hash, virt); -+ if(desc == NULL) -+ return(0); -+ -+ remove_mapping(desc); -+ return(1); -+} -+ -+void physmem_forget_descriptor(int fd) -+{ -+ struct desc_mapping *desc; -+ struct phys_desc *page; -+ struct list_head *ele, *next; -+ __u64 offset; -+ void *addr; -+ int err; -+ -+ desc = find_mapping(fd); -+ if(desc == NULL) -+ return; -+ -+ list_for_each_safe(ele, next, &desc->pages){ -+ page = list_entry(ele, struct phys_desc, list); -+ offset = page->offset; -+ addr = page->virt; -+ remove_mapping(page); -+ err = os_seek_file(fd, offset); -+ if(err) -+ panic("physmem_forget_descriptor - failed to seek " -+ "to %lld in fd %d, error = %d\n", -+ offset, fd, -err); -+ err = os_read_file(fd, addr, PAGE_SIZE); -+ if(err < 0) -+ panic("physmem_forget_descriptor - failed to read " -+ "from fd %d to 0x%p, error = %d\n", -+ fd, addr, -err); -+ } -+ -+ list_del(&desc->list); -+ kfree(desc); -+} -+ -+void arch_free_page(struct page *page, int order) -+{ -+ void *virt; -+ int i; -+ -+ for(i = 0; i < (1 << order); i++){ -+ virt = __va(page_to_phys(page + i)); -+ physmem_remove_mapping(virt); -+ } -+} -+ -+int is_remapped(void *virt) -+{ -+ return(find_virtmem_hash(&virtmem_hash, virt) != NULL); -+} -+ -+/* Changed during early boot */ -+unsigned long high_physmem; -+ -+extern unsigned long physmem_size; -+ -+void *to_virt(unsigned long phys) -+{ -+ return((void *) uml_physmem + phys); -+} -+ -+unsigned long to_phys(void *virt) -+{ -+ return(((unsigned long) virt) - uml_physmem); -+} -+ -+int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) -+{ -+ struct page *p, *map; -+ unsigned long phys_len, phys_pages, highmem_len, highmem_pages; -+ unsigned long iomem_len, iomem_pages, total_len, total_pages; -+ int i; -+ -+ phys_pages = physmem >> PAGE_SHIFT; -+ phys_len = phys_pages * sizeof(struct page); -+ -+ iomem_pages = iomem >> PAGE_SHIFT; -+ iomem_len = iomem_pages * sizeof(struct page); -+ -+ highmem_pages = highmem >> PAGE_SHIFT; -+ highmem_len = highmem_pages * sizeof(struct page); -+ -+ total_pages = phys_pages + iomem_pages + highmem_pages; -+ total_len = phys_len + iomem_pages + highmem_len; -+ -+ if(kmalloc_ok){ -+ map = kmalloc(total_len, GFP_KERNEL); -+ if(map == NULL) -+ map = vmalloc(total_len); -+ } -+ else map = alloc_bootmem_low_pages(total_len); -+ -+ if(map == NULL) -+ return(-ENOMEM); -+ -+ for(i = 0; i < total_pages; i++){ -+ p = &map[i]; -+ set_page_count(p, 0); -+ SetPageReserved(p); -+ INIT_LIST_HEAD(&p->list); -+ } -+ -+ mem_map = map; -+ max_mapnr = total_pages; -+ return(0); -+} -+ -+struct page *phys_to_page(const unsigned long phys) -+{ -+ return(&mem_map[phys >> PAGE_SHIFT]); -+} -+ -+struct page *__virt_to_page(const unsigned long virt) -+{ -+ return(&mem_map[__pa(virt) >> PAGE_SHIFT]); -+} -+ -+unsigned long page_to_phys(struct page *page) -+{ -+ return((page - mem_map) << PAGE_SHIFT); -+} -+ -+pte_t mk_pte(struct page *page, pgprot_t pgprot) -+{ -+ pte_t pte; -+ -+ pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot); -+ if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte)); -+ return(pte); -+} -+ -+/* Changed during early boot */ -+static unsigned long kmem_top = 0; -+ -+unsigned long get_kmem_end(void) -+{ -+ if(kmem_top == 0) -+ kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); -+ return(kmem_top); -+} -+ -+void map_memory(unsigned long virt, unsigned long phys, unsigned long len, -+ int r, int w, int x) -+{ -+ __u64 offset; -+ int fd, err; -+ -+ fd = phys_mapping(phys, &offset); -+ err = os_map_memory((void *) virt, fd, offset, len, r, w, x); -+ if(err) -+ panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " -+ "err = %d\n", virt, fd, offset, len, r, w, x, err); -+} -+ -+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -+ -+void setup_physmem(unsigned long start, unsigned long reserve_end, -+ unsigned long len, unsigned long highmem) -+{ -+ unsigned long reserve = reserve_end - start; -+ int pfn = PFN_UP(__pa(reserve_end)); -+ int delta = (len - reserve) >> PAGE_SHIFT; -+ int err, offset, bootmap_size; -+ -+ physmem_fd = create_mem_file(len + highmem); -+ -+ offset = uml_reserved - uml_physmem; -+ err = os_map_memory((void *) uml_reserved, physmem_fd, offset, -+ len - offset, 1, 1, 0); -+ if(err < 0){ -+ os_print_error(err, "Mapping memory"); -+ exit(1); -+ } -+ -+ bootmap_size = init_bootmem(pfn, pfn + delta); -+ free_bootmem(__pa(reserve_end) + bootmap_size, -+ len - bootmap_size - reserve); -+} -+ -+int phys_mapping(unsigned long phys, __u64 *offset_out) -+{ -+ struct phys_desc *desc = find_virtmem_hash(&virtmem_hash, -+ __va(phys & PAGE_MASK)); -+ int fd = -1; -+ -+ if(desc != NULL){ -+ fd = desc->fd; -+ *offset_out = desc->offset; -+ } -+ else if(phys < physmem_size){ -+ fd = physmem_fd; -+ *offset_out = phys; -+ } -+ else if(phys < __pa(end_iomem)){ -+ struct iomem_region *region = iomem_regions; -+ -+ while(region != NULL){ -+ if((phys >= region->phys) && -+ (phys < region->phys + region->size)){ -+ fd = region->fd; -+ *offset_out = phys - region->phys; -+ break; -+ } -+ region = region->next; -+ } -+ } -+ else if(phys < __pa(end_iomem) + highmem){ -+ fd = physmem_fd; -+ *offset_out = phys - iomem_size; -+ } -+ -+ return(fd); -+} -+ -+static int __init uml_mem_setup(char *line, int *add) -+{ -+ char *retptr; -+ physmem_size = memparse(line,&retptr); -+ return 0; -+} -+__uml_setup("mem=", uml_mem_setup, -+"mem=<Amount of desired ram>\n" -+" This controls how much \"physical\" memory the kernel allocates\n" -+" for the system. The size is specified as a number followed by\n" -+" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" -+" This is not related to the amount of memory in the host. It can\n" -+" be more, and the excess, if it's ever used, will just be swapped out.\n" -+" Example: mem=64M\n\n" -+); -+ -+unsigned long find_iomem(char *driver, unsigned long *len_out) -+{ -+ struct iomem_region *region = iomem_regions; -+ -+ while(region != NULL){ -+ if(!strcmp(region->driver, driver)){ -+ *len_out = region->size; -+ return(region->virt); -+ } -+ } -+ -+ return(0); -+} -+ -+int setup_iomem(void) -+{ -+ struct iomem_region *region = iomem_regions; -+ unsigned long iomem_start = high_physmem + PAGE_SIZE; -+ int err; -+ -+ while(region != NULL){ -+ err = os_map_memory((void *) iomem_start, region->fd, 0, -+ region->size, 1, 1, 0); -+ if(err) -+ printk("Mapping iomem region for driver '%s' failed, " -+ "errno = %d\n", region->driver, -err); -+ else { -+ region->virt = iomem_start; -+ region->phys = __pa(region->virt); -+ } -+ -+ iomem_start += region->size + PAGE_SIZE; -+ region = region->next; -+ } -+ -+ return(0); -+} -+ -+__initcall(setup_iomem); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/process.c um/arch/um/kernel/process.c ---- orig/arch/um/kernel/process.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/process.c 2004-01-31 02:47:57.000000000 -0500 -@@ -0,0 +1,289 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <signal.h> -+#include <sched.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <stdlib.h> -+#include <setjmp.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <sys/mman.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include <asm/unistd.h> -+#include <asm/page.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+#include "irq_user.h" -+#include "ptrace_user.h" -+#include "time_user.h" -+#include "init.h" -+#include "os.h" -+#include "uml-config.h" -+#include "choose-mode.h" -+#include "mode.h" -+#ifdef UML_CONFIG_MODE_SKAS -+#include "skas.h" -+#include "skas_ptrace.h" -+#endif -+ -+void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) -+{ -+ int flags = 0, pages; -+ -+ if(sig_stack != NULL){ -+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; -+ set_sigstack(sig_stack, pages * page_size()); -+ flags = SA_ONSTACK; -+ } -+ if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); -+} -+ -+void init_new_thread_signals(int altstack) -+{ -+ int flags = altstack ? SA_ONSTACK : 0; -+ -+ /* NODEFER is set here because SEGV isn't turned back on when the -+ * handler is ready to receive signals. This causes any segfault -+ * during a copy_user to kill the process because the fault is blocked. -+ */ -+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags | SA_NODEFER, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGFPE, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGILL, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGUSR2, (__sighandler_t) sig_handler, -+ SA_NOMASK | flags, -1); -+ signal(SIGHUP, SIG_IGN); -+ -+ init_irq_signals(altstack); -+} -+ -+struct tramp { -+ int (*tramp)(void *); -+ void *tramp_data; -+ unsigned long temp_stack; -+ int flags; -+ int pid; -+}; -+ -+/* See above for why sigkill is here */ -+ -+int sigkill = SIGKILL; -+ -+int outer_tramp(void *arg) -+{ -+ struct tramp *t; -+ int sig = sigkill; -+ -+ t = arg; -+ t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, -+ t->flags, t->tramp_data); -+ if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); -+ kill(os_getpid(), sig); -+ _exit(0); -+} -+ -+int start_fork_tramp(void *thread_arg, unsigned long temp_stack, -+ int clone_flags, int (*tramp)(void *)) -+{ -+ struct tramp arg; -+ unsigned long sp; -+ int new_pid, status, err; -+ -+ /* The trampoline will run on the temporary stack */ -+ sp = stack_sp(temp_stack); -+ -+ clone_flags |= CLONE_FILES | SIGCHLD; -+ -+ arg.tramp = tramp; -+ arg.tramp_data = thread_arg; -+ arg.temp_stack = temp_stack; -+ arg.flags = clone_flags; -+ -+ /* Start the process and wait for it to kill itself */ -+ new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); -+ if(new_pid < 0) return(-errno); -+ while(((err = waitpid(new_pid, &status, 0)) < 0) && (errno == EINTR)) ; -+ if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", -+ errno); -+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) -+ panic("outer trampoline didn't exit with SIGKILL, " -+ "status = %d", status); -+ -+ return(arg.pid); -+} -+ -+void suspend_new_thread(int fd) -+{ -+ char c; -+ -+ os_stop_process(os_getpid()); -+ -+ if(os_read_file(fd, &c, sizeof(c)) != sizeof(c)) -+ panic("read failed in suspend_new_thread"); -+} -+ -+static int ptrace_child(void *arg) -+{ -+ int pid = os_getpid(); -+ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ perror("ptrace"); -+ os_kill_process(pid, 0); -+ } -+ os_stop_process(pid); -+ _exit(os_getpid() == pid); -+} -+ -+static int start_ptraced_child(void **stack_out) -+{ -+ void *stack; -+ unsigned long sp; -+ int pid, n, status; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if(stack == MAP_FAILED) -+ panic("check_ptrace : mmap failed, errno = %d", errno); -+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); -+ if(pid < 0) -+ panic("check_ptrace : clone failed, errno = %d", errno); -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) -+ panic("check_ptrace : expected SIGSTOP, got status = %d", -+ status); -+ -+ *stack_out = stack; -+ return(pid); -+} -+ -+static void stop_ptraced_child(int pid, void *stack, int exitcode) -+{ -+ int status, n; -+ -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) -+ panic("check_ptrace : ptrace failed, errno = %d", errno); -+ n = waitpid(pid, &status, 0); -+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) -+ panic("check_ptrace : child exited with status 0x%x", status); -+ -+ if(munmap(stack, PAGE_SIZE) < 0) -+ panic("check_ptrace : munmap failed, errno = %d", errno); -+} -+ -+void __init check_ptrace(void) -+{ -+ void *stack; -+ int pid, syscall, n, status; -+ -+ printk("Checking that ptrace can change system call numbers..."); -+ pid = start_ptraced_child(&stack); -+ -+ while(1){ -+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) -+ panic("check_ptrace : ptrace failed, errno = %d", -+ errno); -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -+ panic("check_ptrace : expected SIGTRAP, " -+ "got status = %d", status); -+ -+ syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, -+ 0); -+ if(syscall == __NR_getpid){ -+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getppid); -+ if(n < 0) -+ panic("check_ptrace : failed to modify system " -+ "call, errno = %d", errno); -+ break; -+ } -+ } -+ stop_ptraced_child(pid, stack, 0); -+ printk("OK\n"); -+} -+ -+int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) -+{ -+ sigjmp_buf buf; -+ int n; -+ -+ *jmp_ptr = &buf; -+ n = sigsetjmp(buf, 1); -+ if(n != 0) -+ return(n); -+ (*fn)(arg); -+ return(0); -+} -+ -+int can_do_skas(void) -+{ -+#ifdef UML_CONFIG_MODE_SKAS -+ struct ptrace_faultinfo fi; -+ void *stack; -+ int pid, n, ret = 1; -+ -+ printf("Checking for the skas3 patch in the host..."); -+ pid = start_ptraced_child(&stack); -+ -+ n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); -+ if(n < 0){ -+ if(errno == EIO) -+ printf("not found\n"); -+ else printf("No (unexpected errno - %d)\n", errno); -+ ret = 0; -+ } -+ else printf("found\n"); -+ -+ init_registers(pid); -+ stop_ptraced_child(pid, stack, 1); -+ -+ printf("Checking for /proc/mm..."); -+ if(os_access("/proc/mm", OS_ACC_W_OK) < 0){ -+ printf("not found\n"); -+ ret = 0; -+ } -+ else printf("found\n"); -+ -+ return(ret); -+#else -+ return(0); -+#endif -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/process_kern.c um/arch/um/kernel/process_kern.c ---- orig/arch/um/kernel/process_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/process_kern.c 2003-11-08 08:37:04.000000000 -0500 -@@ -0,0 +1,396 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/interrupt.h" -+#include "linux/mm.h" -+#include "linux/slab.h" -+#include "linux/utsname.h" -+#include "linux/fs.h" -+#include "linux/utime.h" -+#include "linux/smp_lock.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/capability.h" -+#include "asm/unistd.h" -+#include "asm/mman.h" -+#include "asm/segment.h" -+#include "asm/stat.h" -+#include "asm/pgtable.h" -+#include "asm/processor.h" -+#include "asm/pgalloc.h" -+#include "asm/spinlock.h" -+#include "asm/uaccess.h" -+#include "asm/user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "init.h" -+#include "irq_user.h" -+#include "mem_user.h" -+#include "time_user.h" -+#include "tlb.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "mode.h" -+#include "mode_kern.h" -+#include "choose-mode.h" -+ -+/* This is a per-cpu array. A processor only modifies its entry and it only -+ * cares about its entry, so it's OK if another processor is modifying its -+ * entry. -+ */ -+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; -+ -+struct task_struct *get_task(int pid, int require) -+{ -+ struct task_struct *ret; -+ -+ read_lock(&tasklist_lock); -+ ret = find_task_by_pid(pid); -+ read_unlock(&tasklist_lock); -+ -+ if(require && (ret == NULL)) panic("get_task couldn't find a task\n"); -+ return(ret); -+} -+ -+int external_pid(void *t) -+{ -+ struct task_struct *task = t ? t : current; -+ -+ return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); -+} -+ -+int pid_to_processor_id(int pid) -+{ -+ int i; -+ -+ for(i = 0; i < smp_num_cpus; i++){ -+ if(cpu_tasks[i].pid == pid) return(i); -+ } -+ return(-1); -+} -+ -+void free_stack(unsigned long stack, int order) -+{ -+ free_pages(stack, order); -+} -+ -+unsigned long alloc_stack(int order, int atomic) -+{ -+ unsigned long page; -+ int flags = GFP_KERNEL; -+ -+ if(atomic) flags |= GFP_ATOMIC; -+ page = __get_free_pages(flags, order); -+ if(page == 0) -+ return(0); -+ stack_protections(page); -+ return(page); -+} -+ -+int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -+{ -+ int pid; -+ -+ current->thread.request.u.thread.proc = fn; -+ current->thread.request.u.thread.arg = arg; -+ pid = do_fork(CLONE_VM | flags, 0, NULL, 0); -+#if 0 /* CLONE_UNTRACED for 2.6 */ -+ pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0); -+#endif -+ if(pid < 0) -+ panic("do_fork failed in kernel_thread, errno = %d", pid); -+ return(pid); -+} -+ -+void switch_mm(struct mm_struct *prev, struct mm_struct *next, -+ struct task_struct *tsk, unsigned cpu) -+{ -+ if (prev != next) -+ clear_bit(cpu, &prev->cpu_vm_mask); -+ set_bit(cpu, &next->cpu_vm_mask); -+} -+ -+void set_current(void *t) -+{ -+ struct task_struct *task = t; -+ -+ cpu_tasks[task->processor] = ((struct cpu_task) -+ { external_pid(task), task }); -+} -+ -+void *_switch_to(void *prev, void *next) -+{ -+ return(CHOOSE_MODE(_switch_to_tt(prev, next), -+ _switch_to_skas(prev, next))); -+} -+ -+void interrupt_end(void) -+{ -+ if(current->need_resched) schedule(); -+ if(current->sigpending != 0) do_signal(0); -+} -+ -+void release_thread(struct task_struct *task) -+{ -+ CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); -+} -+ -+void exit_thread(void) -+{ -+ CHOOSE_MODE(exit_thread_tt(), exit_thread_skas()); -+ unprotect_stack((unsigned long) current); -+} -+ -+void *get_current(void) -+{ -+ return(current); -+} -+ -+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ p->thread = (struct thread_struct) INIT_THREAD; -+ p->thread.kernel_stack = (unsigned long) p + 2 * PAGE_SIZE; -+ -+ return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, -+ clone_flags, sp, stack_top, p, regs)); -+} -+ -+void initial_thread_cb(void (*proc)(void *), void *arg) -+{ -+ int save_kmalloc_ok = kmalloc_ok; -+ -+ kmalloc_ok = 0; -+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, -+ arg); -+ kmalloc_ok = save_kmalloc_ok; -+} -+ -+unsigned long stack_sp(unsigned long page) -+{ -+ return(page + PAGE_SIZE - sizeof(void *)); -+} -+ -+int current_pid(void) -+{ -+ return(current->pid); -+} -+ -+void cpu_idle(void) -+{ -+ CHOOSE_MODE(init_idle_tt(), init_idle_skas()); -+ -+ atomic_inc(&init_mm.mm_count); -+ current->mm = &init_mm; -+ current->active_mm = &init_mm; -+ -+ while(1){ -+ /* endless idle loop with no priority at all */ -+ SET_PRI(current); -+ -+ /* -+ * although we are an idle CPU, we do not want to -+ * get into the scheduler unnecessarily. -+ */ -+ if (current->need_resched) { -+ schedule(); -+ check_pgt_cache(); -+ } -+ idle_sleep(10); -+ } -+} -+ -+int page_size(void) -+{ -+ return(PAGE_SIZE); -+} -+ -+int page_mask(void) -+{ -+ return(PAGE_MASK); -+} -+ -+void *um_virt_to_phys(struct task_struct *task, unsigned long addr, -+ pte_t *pte_out) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ -+ if(task->mm == NULL) -+ return(ERR_PTR(-EINVAL)); -+ pgd = pgd_offset(task->mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(!pmd_present(*pmd)) -+ return(ERR_PTR(-EINVAL)); -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte)) -+ return(ERR_PTR(-EINVAL)); -+ if(pte_out != NULL) -+ *pte_out = *pte; -+ return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); -+} -+ -+char *current_cmd(void) -+{ -+#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) -+ return("(Unknown)"); -+#else -+ void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); -+ return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); -+#endif -+} -+ -+void force_sigbus(void) -+{ -+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n", -+ current->pid); -+ lock_kernel(); -+ sigaddset(¤t->pending.signal, SIGBUS); -+ recalc_sigpending(current); -+ current->flags |= PF_SIGNALED; -+ do_exit(SIGBUS | 0x80); -+} -+ -+void dump_thread(struct pt_regs *regs, struct user *u) -+{ -+} -+ -+void enable_hlt(void) -+{ -+ panic("enable_hlt"); -+} -+ -+void disable_hlt(void) -+{ -+ panic("disable_hlt"); -+} -+ -+extern int signal_frame_size; -+ -+void *um_kmalloc(int size) -+{ -+ return(kmalloc(size, GFP_KERNEL)); -+} -+ -+void *um_kmalloc_atomic(int size) -+{ -+ return(kmalloc(size, GFP_ATOMIC)); -+} -+ -+unsigned long get_fault_addr(void) -+{ -+ return((unsigned long) current->thread.fault_addr); -+} -+ -+EXPORT_SYMBOL(get_fault_addr); -+ -+void not_implemented(void) -+{ -+ printk(KERN_DEBUG "Something isn't implemented in here\n"); -+} -+ -+EXPORT_SYMBOL(not_implemented); -+ -+int user_context(unsigned long sp) -+{ -+ unsigned long stack; -+ -+ stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); -+ stack += 2 * PAGE_SIZE; -+ return(stack != current->thread.kernel_stack); -+} -+ -+extern void remove_umid_dir(void); -+ -+__uml_exitcall(remove_umid_dir); -+ -+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; -+ -+void do_uml_exitcalls(void) -+{ -+ exitcall_t *call; -+ -+ call = &__uml_exitcall_end; -+ while (--call >= &__uml_exitcall_begin) -+ (*call)(); -+} -+ -+char *uml_strdup(char *string) -+{ -+ char *new; -+ -+ new = kmalloc(strlen(string) + 1, GFP_KERNEL); -+ if(new == NULL) return(NULL); -+ strcpy(new, string); -+ return(new); -+} -+ -+void *get_init_task(void) -+{ -+ return(&init_task_union.task); -+} -+ -+int copy_to_user_proc(void *to, void *from, int size) -+{ -+ return(copy_to_user(to, from, size)); -+} -+ -+int copy_from_user_proc(void *to, void *from, int size) -+{ -+ return(copy_from_user(to, from, size)); -+} -+ -+int clear_user_proc(void *buf, int size) -+{ -+ return(clear_user(buf, size)); -+} -+ -+int strlen_user_proc(char *str) -+{ -+ return(strlen_user(str)); -+} -+ -+int smp_sigio_handler(void) -+{ -+#ifdef CONFIG_SMP -+ int cpu = current->processor; -+ -+ IPI_handler(cpu); -+ if(cpu != 0) -+ return(1); -+#endif -+ return(0); -+} -+ -+int um_in_interrupt(void) -+{ -+ return(in_interrupt()); -+} -+ -+int cpu(void) -+{ -+ return(current->processor); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/ptrace.c um/arch/um/kernel/ptrace.c ---- orig/arch/um/kernel/ptrace.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/ptrace.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,325 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/mm.h" -+#include "linux/errno.h" -+#include "linux/smp_lock.h" -+#ifdef CONFIG_PROC_MM -+#include "linux/proc_mm.h" -+#endif -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+ -+/* -+ * Called by kernel/ptrace.c when detaching.. -+ */ -+void ptrace_disable(struct task_struct *child) -+{ -+} -+ -+extern long do_mmap2(struct task_struct *task, unsigned long addr, -+ unsigned long len, unsigned long prot, -+ unsigned long flags, unsigned long fd, -+ unsigned long pgoff); -+ -+int sys_ptrace(long request, long pid, long addr, long data) -+{ -+ struct task_struct *child; -+ int i, ret; -+ -+ lock_kernel(); -+ ret = -EPERM; -+ if (request == PTRACE_TRACEME) { -+ /* are we already being traced? */ -+ if (current->ptrace & PT_PTRACED) -+ goto out; -+ /* set the ptrace bit in the process flags. */ -+ current->ptrace |= PT_PTRACED; -+ ret = 0; -+ goto out; -+ } -+ ret = -ESRCH; -+ read_lock(&tasklist_lock); -+ child = find_task_by_pid(pid); -+ if (child) -+ get_task_struct(child); -+ read_unlock(&tasklist_lock); -+ if (!child) -+ goto out; -+ -+ ret = -EPERM; -+ if (pid == 1) /* you may not mess with init */ -+ goto out_tsk; -+ -+ if (request == PTRACE_ATTACH) { -+ ret = ptrace_attach(child); -+ goto out_tsk; -+ } -+ -+ ret = ptrace_check_attach(child, request == PTRACE_KILL); -+ if (ret < 0) -+ goto out_tsk; -+ -+ switch (request) { -+ /* when I and D space are separate, these will need to be fixed. */ -+ case PTRACE_PEEKTEXT: /* read word at location addr. */ -+ case PTRACE_PEEKDATA: { -+ unsigned long tmp; -+ int copied; -+ -+ ret = -EIO; -+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); -+ if (copied != sizeof(tmp)) -+ break; -+ ret = put_user(tmp,(unsigned long *) data); -+ break; -+ } -+ -+ /* read the word at location addr in the USER area. */ -+ case PTRACE_PEEKUSR: { -+ unsigned long tmp; -+ -+ ret = -EIO; -+ if ((addr & 3) || addr < 0) -+ break; -+ -+ tmp = 0; /* Default return condition */ -+ if(addr < FRAME_SIZE_OFFSET){ -+ tmp = getreg(child, addr); -+ } -+ else if((addr >= offsetof(struct user, u_debugreg[0])) && -+ (addr <= offsetof(struct user, u_debugreg[7]))){ -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ tmp = child->thread.arch.debugregs[addr]; -+ } -+ ret = put_user(tmp, (unsigned long *) data); -+ break; -+ } -+ -+ /* when I and D space are separate, this will have to be fixed. */ -+ case PTRACE_POKETEXT: /* write the word at location addr. */ -+ case PTRACE_POKEDATA: -+ ret = -EIO; -+ if (access_process_vm(child, addr, &data, sizeof(data), -+ 1) != sizeof(data)) -+ break; -+ ret = 0; -+ break; -+ -+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ -+ ret = -EIO; -+ if ((addr & 3) || addr < 0) -+ break; -+ -+ if (addr < FRAME_SIZE_OFFSET) { -+ ret = putreg(child, addr, data); -+ break; -+ } -+ else if((addr >= offsetof(struct user, u_debugreg[0])) && -+ (addr <= offsetof(struct user, u_debugreg[7]))){ -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ if((addr == 4) || (addr == 5)) break; -+ child->thread.arch.debugregs[addr] = data; -+ ret = 0; -+ } -+ -+ break; -+ -+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ -+ case PTRACE_CONT: { /* restart after signal. */ -+ ret = -EIO; -+ if ((unsigned long) data > _NSIG) -+ break; -+ if (request == PTRACE_SYSCALL) -+ child->ptrace |= PT_TRACESYS; -+ else -+ child->ptrace &= ~PT_TRACESYS; -+ child->exit_code = data; -+ wake_up_process(child); -+ ret = 0; -+ break; -+ } -+ -+/* -+ * make the child exit. Best I can do is send it a sigkill. -+ * perhaps it should be put in the status that it wants to -+ * exit. -+ */ -+ case PTRACE_KILL: { -+ ret = 0; -+ if (child->state == TASK_ZOMBIE) /* already dead */ -+ break; -+ child->exit_code = SIGKILL; -+ wake_up_process(child); -+ break; -+ } -+ -+ case PTRACE_SINGLESTEP: { /* set the trap flag. */ -+ ret = -EIO; -+ if ((unsigned long) data > _NSIG) -+ break; -+ child->ptrace &= ~PT_TRACESYS; -+ child->ptrace |= PT_DTRACE; -+ child->exit_code = data; -+ /* give it a chance to run. */ -+ wake_up_process(child); -+ ret = 0; -+ break; -+ } -+ -+ case PTRACE_DETACH: -+ /* detach a process that was attached. */ -+ ret = ptrace_detach(child, data); -+ break; -+ -+#ifdef PTRACE_GETREGS -+ case PTRACE_GETREGS: { /* Get all gp regs from the child. */ -+ if (!access_ok(VERIFY_WRITE, (unsigned long *)data, -+ FRAME_SIZE_OFFSET)) { -+ ret = -EIO; -+ break; -+ } -+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { -+ __put_user(getreg(child, i), (unsigned long *) data); -+ data += sizeof(long); -+ } -+ ret = 0; -+ break; -+ } -+#endif -+#ifdef PTRACE_SETREGS -+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */ -+ unsigned long tmp = 0; -+ if (!access_ok(VERIFY_READ, (unsigned *)data, -+ FRAME_SIZE_OFFSET)) { -+ ret = -EIO; -+ break; -+ } -+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { -+ __get_user(tmp, (unsigned long *) data); -+ putreg(child, i, tmp); -+ data += sizeof(long); -+ } -+ ret = 0; -+ break; -+ } -+#endif -+#ifdef PTRACE_GETFPREGS -+ case PTRACE_GETFPREGS: /* Get the child FPU state. */ -+ ret = get_fpregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_SETFPREGS -+ case PTRACE_SETFPREGS: /* Set the child FPU state. */ -+ ret = set_fpregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_GETFPXREGS -+ case PTRACE_GETFPXREGS: /* Get the child FPU state. */ -+ ret = get_fpxregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_SETFPXREGS -+ case PTRACE_SETFPXREGS: /* Set the child FPU state. */ -+ ret = set_fpxregs(data, child); -+ break; -+#endif -+ case PTRACE_FAULTINFO: { -+ struct ptrace_faultinfo fault; -+ -+ fault = ((struct ptrace_faultinfo) -+ { .is_write = child->thread.err, -+ .addr = child->thread.cr2 }); -+ ret = copy_to_user((unsigned long *) data, &fault, -+ sizeof(fault)); -+ if(ret) -+ break; -+ break; -+ } -+ case PTRACE_SIGPENDING: -+ ret = copy_to_user((unsigned long *) data, -+ &child->pending.signal, -+ sizeof(child->pending.signal)); -+ break; -+ -+ case PTRACE_LDT: { -+ struct ptrace_ldt ldt; -+ -+ if(copy_from_user(&ldt, (unsigned long *) data, -+ sizeof(ldt))){ -+ ret = -EIO; -+ break; -+ } -+ -+ /* This one is confusing, so just punt and return -EIO for -+ * now -+ */ -+ ret = -EIO; -+ break; -+ } -+#ifdef CONFIG_PROC_MM -+ case PTRACE_SWITCH_MM: { -+ struct mm_struct *old = child->mm; -+ struct mm_struct *new = proc_mm_get_mm(data); -+ -+ if(IS_ERR(new)){ -+ ret = PTR_ERR(new); -+ break; -+ } -+ -+ atomic_inc(&new->mm_users); -+ child->mm = new; -+ child->active_mm = new; -+ mmput(old); -+ ret = 0; -+ break; -+ } -+#endif -+ default: -+ ret = -EIO; -+ break; -+ } -+ out_tsk: -+ free_task_struct(child); -+ out: -+ unlock_kernel(); -+ return ret; -+} -+ -+void syscall_trace(void) -+{ -+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) -+ != (PT_PTRACED|PT_TRACESYS)) -+ return; -+ current->exit_code = SIGTRAP; -+ current->state = TASK_STOPPED; -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ /* -+ * this isn't the same as continuing with a signal, but it will do -+ * for normal use. strace only continues with a signal if the -+ * stopping signal is not SIGTRAP. -brl -+ */ -+ if (current->exit_code) { -+ send_sig(current->exit_code, current, 1); -+ current->exit_code = 0; -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/reboot.c um/arch/um/kernel/reboot.c ---- orig/arch/um/kernel/reboot.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/reboot.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "os.h" -+#include "mode.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_SMP -+static void kill_idlers(int me) -+{ -+#ifdef CONFIG_MODE_TT -+ struct task_struct *p; -+ int i; -+ -+ for(i = 0; i < sizeof(init_tasks)/sizeof(init_tasks[0]); i++){ -+ p = init_tasks[i]; -+ if((p != NULL) && (p->thread.mode.tt.extern_pid != me) && -+ (p->thread.mode.tt.extern_pid != -1)) -+ os_kill_process(p->thread.mode.tt.extern_pid, 0); -+ } -+#endif -+} -+#endif -+ -+static void kill_off_processes(void) -+{ -+ CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas()); -+#ifdef CONFIG_SMP -+ kill_idlers(os_getpid()); -+#endif -+} -+ -+void uml_cleanup(void) -+{ -+ kill_off_processes(); -+ do_uml_exitcalls(); -+} -+ -+void machine_restart(char * __unused) -+{ -+ do_uml_exitcalls(); -+ kill_off_processes(); -+ CHOOSE_MODE(reboot_tt(), reboot_skas()); -+} -+ -+void machine_power_off(void) -+{ -+ do_uml_exitcalls(); -+ kill_off_processes(); -+ CHOOSE_MODE(halt_tt(), halt_skas()); -+} -+ -+void machine_halt(void) -+{ -+ machine_power_off(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/resource.c um/arch/um/kernel/resource.c ---- orig/arch/um/kernel/resource.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/resource.c 2003-10-21 03:26:06.000000000 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/pci.h" -+ -+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, -+ unsigned long start, unsigned long size) -+{ -+ return start; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/sigio_kern.c um/arch/um/kernel/sigio_kern.c ---- orig/arch/um/kernel/sigio_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/sigio_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/list.h" -+#include "linux/slab.h" -+#include "asm/irq.h" -+#include "init.h" -+#include "sigio.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+ -+/* Protected by sigio_lock() called from write_sigio_workaround */ -+static int sigio_irq_fd = -1; -+ -+void sigio_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ read_sigio_fd(sigio_irq_fd); -+ reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); -+} -+ -+int write_sigio_irq(int fd) -+{ -+ if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, -+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", -+ NULL)){ -+ printk("write_sigio_irq : um_request_irq failed\n"); -+ return(-1); -+ } -+ sigio_irq_fd = fd; -+ return(0); -+} -+ -+static spinlock_t sigio_spinlock = SPIN_LOCK_UNLOCKED; -+ -+void sigio_lock(void) -+{ -+ spin_lock(&sigio_spinlock); -+} -+ -+void sigio_unlock(void) -+{ -+ spin_unlock(&sigio_spinlock); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/sigio_user.c um/arch/um/kernel/sigio_user.c ---- orig/arch/um/kernel/sigio_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/sigio_user.c 2003-11-07 01:41:13.000000000 -0500 -@@ -0,0 +1,438 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdlib.h> -+#include <termios.h> -+#include <pty.h> -+#include <signal.h> -+#include <errno.h> -+#include <string.h> -+#include <sched.h> -+#include <sys/socket.h> -+#include <sys/poll.h> -+#include "init.h" -+#include "user.h" -+#include "kern_util.h" -+#include "sigio.h" -+#include "helper.h" -+#include "os.h" -+ -+/* Changed during early boot */ -+int pty_output_sigio = 0; -+int pty_close_sigio = 0; -+ -+/* Used as a flag during SIGIO testing early in boot */ -+static volatile int got_sigio = 0; -+ -+void __init handler(int sig) -+{ -+ got_sigio = 1; -+} -+ -+struct openpty_arg { -+ int master; -+ int slave; -+ int err; -+}; -+ -+static void openpty_cb(void *arg) -+{ -+ struct openpty_arg *info = arg; -+ -+ info->err = 0; -+ if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) -+ info->err = -errno; -+} -+ -+void __init check_one_sigio(void (*proc)(int, int)) -+{ -+ struct sigaction old, new; -+ struct termios tt; -+ struct openpty_arg pty = { .master = -1, .slave = -1 }; -+ int master, slave, err; -+ -+ initial_thread_cb(openpty_cb, &pty); -+ if(pty.err){ -+ printk("openpty failed, errno = %d\n", -pty.err); -+ return; -+ } -+ -+ master = pty.master; -+ slave = pty.slave; -+ -+ if((master == -1) || (slave == -1)){ -+ printk("openpty failed to allocate a pty\n"); -+ return; -+ } -+ -+ /* XXX These can fail with EINTR */ -+ if(tcgetattr(master, &tt) < 0) -+ panic("check_sigio : tcgetattr failed, errno = %d\n", errno); -+ cfmakeraw(&tt); -+ if(tcsetattr(master, TCSADRAIN, &tt) < 0) -+ panic("check_sigio : tcsetattr failed, errno = %d\n", errno); -+ -+ err = os_sigio_async(master, slave); -+ if(err < 0) -+ panic("tty_fds : sigio_async failed, err = %d\n", -err); -+ -+ if(sigaction(SIGIO, NULL, &old) < 0) -+ panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); -+ new = old; -+ new.sa_handler = handler; -+ if(sigaction(SIGIO, &new, NULL) < 0) -+ panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); -+ -+ got_sigio = 0; -+ (*proc)(master, slave); -+ -+ os_close_file(master); -+ os_close_file(slave); -+ -+ if(sigaction(SIGIO, &old, NULL) < 0) -+ panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); -+} -+ -+static void tty_output(int master, int slave) -+{ -+ int n; -+ char buf[512]; -+ -+ printk("Checking that host ptys support output SIGIO..."); -+ -+ memset(buf, 0, sizeof(buf)); -+ -+ while(os_write_file(master, buf, sizeof(buf)) > 0) ; -+ if(errno != EAGAIN) -+ panic("check_sigio : write failed, errno = %d\n", errno); -+ while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; -+ -+ if(got_sigio){ -+ printk("Yes\n"); -+ pty_output_sigio = 1; -+ } -+ else if(n == -EAGAIN) printk("No, enabling workaround\n"); -+ else panic("check_sigio : read failed, err = %d\n", n); -+} -+ -+static void tty_close(int master, int slave) -+{ -+ printk("Checking that host ptys support SIGIO on close..."); -+ -+ os_close_file(slave); -+ if(got_sigio){ -+ printk("Yes\n"); -+ pty_close_sigio = 1; -+ } -+ else printk("No, enabling workaround\n"); -+} -+ -+void __init check_sigio(void) -+{ -+ if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && -+ (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ -+ printk("No pseudo-terminals available - skipping pty SIGIO " -+ "check\n"); -+ return; -+ } -+ check_one_sigio(tty_output); -+ check_one_sigio(tty_close); -+} -+ -+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an -+ * exitcall. -+ */ -+static int write_sigio_pid = -1; -+ -+/* These arrays are initialized before the sigio thread is started, and -+ * the descriptors closed after it is killed. So, it can't see them change. -+ * On the UML side, they are changed under the sigio_lock. -+ */ -+static int write_sigio_fds[2] = { -1, -1 }; -+static int sigio_private[2] = { -1, -1 }; -+ -+struct pollfds { -+ struct pollfd *poll; -+ int size; -+ int used; -+}; -+ -+/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread -+ * synchronizes with it. -+ */ -+struct pollfds current_poll = { -+ .poll = NULL, -+ .size = 0, -+ .used = 0 -+}; -+ -+struct pollfds next_poll = { -+ .poll = NULL, -+ .size = 0, -+ .used = 0 -+}; -+ -+static int write_sigio_thread(void *unused) -+{ -+ struct pollfds *fds, tmp; -+ struct pollfd *p; -+ int i, n, respond_fd; -+ char c; -+ -+ fds = ¤t_poll; -+ while(1){ -+ n = poll(fds->poll, fds->used, -1); -+ if(n < 0){ -+ if(errno == EINTR) continue; -+ printk("write_sigio_thread : poll returned %d, " -+ "errno = %d\n", n, errno); -+ } -+ for(i = 0; i < fds->used; i++){ -+ p = &fds->poll[i]; -+ if(p->revents == 0) continue; -+ if(p->fd == sigio_private[1]){ -+ n = os_read_file(sigio_private[1], &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("write_sigio_thread : " -+ "read failed, err = %d\n", -n); -+ tmp = current_poll; -+ current_poll = next_poll; -+ next_poll = tmp; -+ respond_fd = sigio_private[1]; -+ } -+ else { -+ respond_fd = write_sigio_fds[1]; -+ fds->used--; -+ memmove(&fds->poll[i], &fds->poll[i + 1], -+ (fds->used - i) * sizeof(*fds->poll)); -+ } -+ -+ n = os_write_file(respond_fd, &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("write_sigio_thread : write failed, " -+ "err = %d\n", -n); -+ } -+ } -+} -+ -+static int need_poll(int n) -+{ -+ if(n <= next_poll.size){ -+ next_poll.used = n; -+ return(0); -+ } -+ if(next_poll.poll != NULL) kfree(next_poll.poll); -+ next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); -+ if(next_poll.poll == NULL){ -+ printk("need_poll : failed to allocate new pollfds\n"); -+ next_poll.size = 0; -+ next_poll.used = 0; -+ return(-1); -+ } -+ next_poll.size = n; -+ next_poll.used = n; -+ return(0); -+} -+ -+static void update_thread(void) -+{ -+ unsigned long flags; -+ int n; -+ char c; -+ -+ flags = set_signals(0); -+ n = os_write_file(sigio_private[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("update_thread : write failed, err = %d\n", -n); -+ goto fail; -+ } -+ -+ n = os_read_file(sigio_private[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("update_thread : read failed, err = %d\n", -n); -+ goto fail; -+ } -+ -+ set_signals(flags); -+ return; -+ fail: -+ sigio_lock(); -+ if(write_sigio_pid != -1) -+ os_kill_process(write_sigio_pid, 1); -+ write_sigio_pid = -1; -+ os_close_file(sigio_private[0]); -+ os_close_file(sigio_private[1]); -+ os_close_file(write_sigio_fds[0]); -+ os_close_file(write_sigio_fds[1]); -+ sigio_unlock(); -+ set_signals(flags); -+} -+ -+int add_sigio_fd(int fd, int read) -+{ -+ int err = 0, i, n, events; -+ -+ sigio_lock(); -+ for(i = 0; i < current_poll.used; i++){ -+ if(current_poll.poll[i].fd == fd) -+ goto out; -+ } -+ -+ n = current_poll.used + 1; -+ err = need_poll(n); -+ if(err) -+ goto out; -+ -+ for(i = 0; i < current_poll.used; i++) -+ next_poll.poll[i] = current_poll.poll[i]; -+ -+ if(read) events = POLLIN; -+ else events = POLLOUT; -+ -+ next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd, -+ .events = events, -+ .revents = 0 }); -+ update_thread(); -+ out: -+ sigio_unlock(); -+ return(err); -+} -+ -+int ignore_sigio_fd(int fd) -+{ -+ struct pollfd *p; -+ int err = 0, i, n = 0; -+ -+ sigio_lock(); -+ for(i = 0; i < current_poll.used; i++){ -+ if(current_poll.poll[i].fd == fd) break; -+ } -+ if(i == current_poll.used) -+ goto out; -+ -+ err = need_poll(current_poll.used - 1); -+ if(err) -+ goto out; -+ -+ for(i = 0; i < current_poll.used; i++){ -+ p = ¤t_poll.poll[i]; -+ if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; -+ } -+ if(n == i){ -+ printk("ignore_sigio_fd : fd %d not found\n", fd); -+ err = -1; -+ goto out; -+ } -+ -+ update_thread(); -+ out: -+ sigio_unlock(); -+ return(err); -+} -+ -+static int setup_initial_poll(int fd) -+{ -+ struct pollfd *p; -+ -+ p = um_kmalloc(sizeof(struct pollfd)); -+ if(p == NULL){ -+ printk("setup_initial_poll : failed to allocate poll\n"); -+ return(-1); -+ } -+ *p = ((struct pollfd) { .fd = fd, -+ .events = POLLIN, -+ .revents = 0 }); -+ current_poll = ((struct pollfds) { .poll = p, -+ .used = 1, -+ .size = 1 }); -+ return(0); -+} -+ -+void write_sigio_workaround(void) -+{ -+ unsigned long stack; -+ int err; -+ -+ sigio_lock(); -+ if(write_sigio_pid != -1) -+ goto out; -+ -+ err = os_pipe(write_sigio_fds, 1, 1); -+ if(err < 0){ -+ printk("write_sigio_workaround - os_pipe 1 failed, " -+ "err = %d\n", -err); -+ goto out; -+ } -+ err = os_pipe(sigio_private, 1, 1); -+ if(err < 0){ -+ printk("write_sigio_workaround - os_pipe 2 failed, " -+ "err = %d\n", -err); -+ goto out_close1; -+ } -+ if(setup_initial_poll(sigio_private[1])) -+ goto out_close2; -+ -+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, -+ CLONE_FILES | CLONE_VM, &stack, 0); -+ -+ if(write_sigio_pid < 0) goto out_close2; -+ -+ if(write_sigio_irq(write_sigio_fds[0])) -+ goto out_kill; -+ -+ out: -+ sigio_unlock(); -+ return; -+ -+ out_kill: -+ os_kill_process(write_sigio_pid, 1); -+ write_sigio_pid = -1; -+ out_close2: -+ os_close_file(sigio_private[0]); -+ os_close_file(sigio_private[1]); -+ out_close1: -+ os_close_file(write_sigio_fds[0]); -+ os_close_file(write_sigio_fds[1]); -+ sigio_unlock(); -+} -+ -+int read_sigio_fd(int fd) -+{ -+ int n; -+ char c; -+ -+ n = os_read_file(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ if(n < 0) { -+ printk("read_sigio_fd - read failed, err = %d\n", -n); -+ return(n); -+ } -+ else { -+ printk("read_sigio_fd - short read, bytes = %d\n", n); -+ return(-EIO); -+ } -+ } -+ return(n); -+} -+ -+static void sigio_cleanup(void) -+{ -+ if(write_sigio_pid != -1) -+ os_kill_process(write_sigio_pid, 1); -+} -+ -+__uml_exitcall(sigio_cleanup); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/signal_kern.c um/arch/um/kernel/signal_kern.c ---- orig/arch/um/kernel/signal_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/signal_kern.c 2003-11-19 03:50:58.000000000 -0500 -@@ -0,0 +1,369 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/stddef.h" -+#include "linux/sys.h" -+#include "linux/sched.h" -+#include "linux/wait.h" -+#include "linux/kernel.h" -+#include "linux/smp_lock.h" -+#include "linux/module.h" -+#include "linux/slab.h" -+#include "asm/signal.h" -+#include "asm/uaccess.h" -+#include "asm/ucontext.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "kern.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "mode.h" -+ -+EXPORT_SYMBOL(block_signals); -+EXPORT_SYMBOL(unblock_signals); -+ -+static void force_segv(int sig) -+{ -+ if(sig == SIGSEGV){ -+ struct k_sigaction *ka; -+ -+ ka = ¤t->sig->action[SIGSEGV - 1]; -+ ka->sa.sa_handler = SIG_DFL; -+ } -+ force_sig(SIGSEGV, current); -+} -+ -+#define _S(nr) (1<<((nr)-1)) -+ -+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) -+ -+/* -+ * OK, we're invoking a handler -+ */ -+static int handle_signal(struct pt_regs *regs, unsigned long signr, -+ struct k_sigaction *ka, siginfo_t *info, -+ sigset_t *oldset, int error) -+{ -+ __sighandler_t handler; -+ void (*restorer)(void); -+ unsigned long sp; -+ sigset_t save; -+ int err, ret; -+ -+ ret = 0; -+ switch(error){ -+ case -ERESTARTNOHAND: -+ ret = -EINTR; -+ break; -+ -+ case -ERESTARTSYS: -+ if (!(ka->sa.sa_flags & SA_RESTART)) { -+ ret = -EINTR; -+ break; -+ } -+ /* fallthrough */ -+ case -ERESTARTNOINTR: -+ PT_REGS_RESTART_SYSCALL(regs); -+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); -+ -+ /* This is because of the UM_SET_SYSCALL_RETURN and the fact -+ * that on i386 the system call number and return value are -+ * in the same register. When the system call restarts, %eax -+ * had better have the system call number in it. Since the -+ * return value doesn't matter (except that it shouldn't be -+ * -ERESTART*), we'll stick the system call number there. -+ */ -+ ret = PT_REGS_SYSCALL_NR(regs); -+ break; -+ } -+ -+ handler = ka->sa.sa_handler; -+ save = *oldset; -+ -+ if (ka->sa.sa_flags & SA_ONESHOT) -+ ka->sa.sa_handler = SIG_DFL; -+ -+ if (!(ka->sa.sa_flags & SA_NODEFER)) { -+ spin_lock_irq(¤t->sigmask_lock); -+ sigorsets(¤t->blocked, ¤t->blocked, -+ &ka->sa.sa_mask); -+ sigaddset(¤t->blocked, signr); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ } -+ -+ sp = PT_REGS_SP(regs); -+ -+ if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) -+ sp = current->sas_ss_sp + current->sas_ss_size; -+ -+ if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret); -+ -+ if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; -+ else restorer = NULL; -+ -+ if(ka->sa.sa_flags & SA_SIGINFO) -+ err = setup_signal_stack_si(sp, signr, (unsigned long) handler, -+ restorer, regs, info, &save); -+ else -+ err = setup_signal_stack_sc(sp, signr, (unsigned long) handler, -+ restorer, regs, &save); -+ if(err) goto segv; -+ -+ return(0); -+ segv: -+ force_segv(signr); -+ return(1); -+} -+ -+/* -+ * Note that 'init' is a special process: it doesn't get signals it doesn't -+ * want to handle. Thus you cannot kill init even with a SIGKILL even by -+ * mistake. -+ */ -+ -+static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) -+{ -+ siginfo_t info; -+ struct k_sigaction *ka; -+ int err; -+ -+ if (!oldset) -+ oldset = ¤t->blocked; -+ -+ for (;;) { -+ unsigned long signr; -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ signr = dequeue_signal(¤t->blocked, &info); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ if (!signr) -+ break; -+ -+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { -+ /* Let the debugger run. */ -+ current->exit_code = signr; -+ current->state = TASK_STOPPED; -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ -+ /* We're back. Did the debugger cancel the sig? */ -+ signr = current->exit_code; -+ if (!signr) -+ continue; -+ current->exit_code = 0; -+ -+ /* The debugger continued. Ignore SIGSTOP. */ -+ if (signr == SIGSTOP) -+ continue; -+ -+ /* Update the siginfo structure. Is this good? */ -+ if (signr != info.si_signo) { -+ info.si_signo = signr; -+ info.si_errno = 0; -+ info.si_code = SI_USER; -+ info.si_pid = current->p_pptr->pid; -+ info.si_uid = current->p_pptr->uid; -+ } -+ -+ /* If the (new) signal is now blocked, requeue it. */ -+ if (sigismember(¤t->blocked, signr)) { -+ send_sig_info(signr, &info, current); -+ continue; -+ } -+ } -+ -+ ka = ¤t->sig->action[signr-1]; -+ if (ka->sa.sa_handler == SIG_IGN) { -+ if (signr != SIGCHLD) -+ continue; -+ /* Check for SIGCHLD: it's special. */ -+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) -+ /* nothing */; -+ continue; -+ } -+ -+ if (ka->sa.sa_handler == SIG_DFL) { -+ int exit_code = signr; -+ -+ /* Init gets no signals it doesn't want. */ -+ if (current->pid == 1) -+ continue; -+ -+ switch (signr) { -+ case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: -+ continue; -+ -+ case SIGTSTP: case SIGTTIN: case SIGTTOU: -+ if (is_orphaned_pgrp(current->pgrp)) -+ continue; -+ /* FALLTHRU */ -+ -+ case SIGSTOP: { -+ struct signal_struct *sig; -+ current->state = TASK_STOPPED; -+ current->exit_code = signr; -+ sig = current->p_pptr->sig; -+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ continue; -+ } -+ case SIGQUIT: case SIGILL: case SIGTRAP: -+ case SIGABRT: case SIGFPE: case SIGSEGV: -+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: -+ if (do_coredump(signr, ¤t->thread.regs)) -+ exit_code |= 0x80; -+ /* FALLTHRU */ -+ -+ default: -+ sig_exit(signr, exit_code, &info); -+ /* NOTREACHED */ -+ } -+ } -+ -+ /* Whee! Actually deliver the signal. */ -+ err = handle_signal(regs, signr, ka, &info, oldset, error); -+ if(!err) return(1); -+ } -+ -+ /* Did we come from a system call? */ -+ if(PT_REGS_SYSCALL_NR(regs) >= 0){ -+ /* Restart the system call - no handlers present */ -+ if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || -+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || -+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ -+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); -+ PT_REGS_RESTART_SYSCALL(regs); -+ } -+ } -+ -+ /* This closes a way to execute a system call on the host. If -+ * you set a breakpoint on a system call instruction and singlestep -+ * from it, the tracing thread used to PTRACE_SINGLESTEP the process -+ * rather than PTRACE_SYSCALL it, allowing the system call to execute -+ * on the host. The tracing thread will check this flag and -+ * PTRACE_SYSCALL if necessary. -+ */ -+ if((current->ptrace & PT_DTRACE) && -+ is_syscall(PT_REGS_IP(¤t->thread.regs))) -+ (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0); -+ -+ return(0); -+} -+ -+int do_signal(int error) -+{ -+ return(kern_do_signal(¤t->thread.regs, NULL, error)); -+} -+ -+/* -+ * Atomically swap in the new signal mask, and wait for a signal. -+ */ -+int sys_sigsuspend(int history0, int history1, old_sigset_t mask) -+{ -+ sigset_t saveset; -+ -+ mask &= _BLOCKABLE; -+ spin_lock_irq(¤t->sigmask_lock); -+ saveset = current->blocked; -+ siginitset(¤t->blocked, mask); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if(kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) -+ return(-EINTR); -+ } -+} -+ -+int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) -+{ -+ sigset_t saveset, newset; -+ -+ /* XXX: Don't preclude handling different sized sigset_t's. */ -+ if (sigsetsize != sizeof(sigset_t)) -+ return -EINVAL; -+ -+ if (copy_from_user(&newset, unewset, sizeof(newset))) -+ return -EFAULT; -+ sigdelsetmask(&newset, ~_BLOCKABLE); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ saveset = current->blocked; -+ current->blocked = newset; -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if (kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) -+ return(-EINTR); -+ } -+} -+ -+extern int userspace_pid[]; -+ -+static int copy_sc_from_user(struct pt_regs *to, void *from, -+ struct arch_frame_data *arch) -+{ -+ int ret; -+ -+ ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch), -+ copy_sc_from_user_skas(userspace_pid[0], -+ &to->regs, from)); -+ return(ret); -+} -+ -+int sys_sigreturn(struct pt_regs regs) -+{ -+ void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); -+ void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); -+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc), -+ sizeof(current->blocked.sig[0])); -+ copy_from_user(¤t->blocked.sig[1], mask, sig_size); -+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ copy_sc_from_user(¤t->thread.regs, sc, -+ &signal_frame_sc.common.arch); -+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); -+} -+ -+int sys_rt_sigreturn(struct pt_regs regs) -+{ -+ struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs)); -+ int sig_size = _NSIG_WORDS * sizeof(unsigned long); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ copy_from_user(¤t->blocked, &uc->uc_sigmask, sig_size); -+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, -+ &signal_frame_si.common.arch); -+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/signal_user.c um/arch/um/kernel/signal_user.c ---- orig/arch/um/kernel/signal_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/signal_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <signal.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <string.h> -+#include <sys/mman.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "signal_user.h" -+#include "signal_kern.h" -+#include "sysdep/sigcontext.h" -+#include "sigcontext.h" -+ -+void set_sigstack(void *sig_stack, int size) -+{ -+ stack_t stack = ((stack_t) { .ss_flags = 0, -+ .ss_sp = (__ptr_t) sig_stack, -+ .ss_size = size - sizeof(void *) }); -+ -+ if(sigaltstack(&stack, NULL) != 0) -+ panic("enabling signal stack failed, errno = %d\n", errno); -+} -+ -+void set_handler(int sig, void (*handler)(int), int flags, ...) -+{ -+ struct sigaction action; -+ va_list ap; -+ int mask; -+ -+ va_start(ap, flags); -+ action.sa_handler = handler; -+ sigemptyset(&action.sa_mask); -+ while((mask = va_arg(ap, int)) != -1){ -+ sigaddset(&action.sa_mask, mask); -+ } -+ action.sa_flags = flags; -+ action.sa_restorer = NULL; -+ if(sigaction(sig, &action, NULL) < 0) -+ panic("sigaction failed"); -+} -+ -+int change_sig(int signal, int on) -+{ -+ sigset_t sigset, old; -+ -+ sigemptyset(&sigset); -+ sigaddset(&sigset, signal); -+ sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); -+ return(!sigismember(&old, signal)); -+} -+ -+static void change_signals(int type) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ sigaddset(&mask, SIGIO); -+ sigaddset(&mask, SIGPROF); -+ if(sigprocmask(type, &mask, NULL) < 0) -+ panic("Failed to change signal mask - errno = %d", errno); -+} -+ -+void block_signals(void) -+{ -+ change_signals(SIG_BLOCK); -+} -+ -+void unblock_signals(void) -+{ -+ change_signals(SIG_UNBLOCK); -+} -+ -+#define SIGIO_BIT 0 -+#define SIGVTALRM_BIT 1 -+ -+static int enable_mask(sigset_t *mask) -+{ -+ int sigs; -+ -+ sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; -+ sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; -+ sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; -+ return(sigs); -+} -+ -+int get_signals(void) -+{ -+ sigset_t mask; -+ -+ if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) -+ panic("Failed to get signal mask"); -+ return(enable_mask(&mask)); -+} -+ -+int set_signals(int enable) -+{ -+ sigset_t mask; -+ int ret; -+ -+ sigemptyset(&mask); -+ if(enable & (1 << SIGIO_BIT)) -+ sigaddset(&mask, SIGIO); -+ if(enable & (1 << SIGVTALRM_BIT)){ -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ } -+ if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) -+ panic("Failed to enable signals"); -+ ret = enable_mask(&mask); -+ sigemptyset(&mask); -+ if((enable & (1 << SIGIO_BIT)) == 0) -+ sigaddset(&mask, SIGIO); -+ if((enable & (1 << SIGVTALRM_BIT)) == 0){ -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ } -+ if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) -+ panic("Failed to block signals"); -+ -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/exec_kern.c um/arch/um/kernel/skas/exec_kern.c ---- orig/arch/um/kernel/skas/exec_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/exec_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "asm/current.h" -+#include "asm/page.h" -+#include "asm/signal.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/mmu_context.h" -+#include "tlb.h" -+#include "skas.h" -+#include "mmu.h" -+#include "os.h" -+ -+void flush_thread_skas(void) -+{ -+ force_flush_all(); -+ switch_mm_skas(current->mm->context.skas.mm_fd); -+} -+ -+void start_thread_skas(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp) -+{ -+ set_fs(USER_DS); -+ PT_REGS_IP(regs) = eip; -+ PT_REGS_SP(regs) = esp; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/exec_user.c um/arch/um/kernel/skas/exec_user.c ---- orig/arch/um/kernel/skas/exec_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/exec_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <sched.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include "user.h" -+#include "kern_util.h" -+#include "os.h" -+#include "time_user.h" -+ -+static int user_thread_tramp(void *arg) -+{ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) -+ panic("user_thread_tramp - PTRACE_TRACEME failed, " -+ "errno = %d\n", errno); -+ enable_timer(); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+int user_thread(unsigned long stack, int flags) -+{ -+ int pid, status; -+ -+ pid = clone(user_thread_tramp, (void *) stack_sp(stack), -+ flags | CLONE_FILES | SIGCHLD, NULL); -+ if(pid < 0){ -+ printk("user_thread - clone failed, errno = %d\n", errno); -+ return(pid); -+ } -+ -+ if(waitpid(pid, &status, WUNTRACED) < 0){ -+ printk("user_thread - waitpid failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ printk("user_thread - trampoline didn't stop, status = %d\n", -+ status); -+ return(-EINVAL); -+ } -+ -+ return(pid); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mmu.h um/arch/um/kernel/skas/include/mmu.h ---- orig/arch/um/kernel/skas/include/mmu.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/mmu.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_MMU_H -+#define __SKAS_MMU_H -+ -+#include "linux/list.h" -+#include "linux/spinlock.h" -+ -+struct mmu_context_skas { -+ int mm_fd; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mode.h um/arch/um/kernel/skas/include/mode.h ---- orig/arch/um/kernel/skas/include/mode.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/mode.h 2003-11-19 03:27:36.000000000 -0500 -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_SKAS_H__ -+#define __MODE_SKAS_H__ -+ -+extern unsigned long exec_regs[]; -+extern unsigned long exec_fp_regs[]; -+extern unsigned long exec_fpx_regs[]; -+extern int have_fpx_regs; -+ -+extern void user_time_init_skas(void); -+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, -+ void *from_ptr); -+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, -+ union uml_pt_regs *regs, -+ unsigned long fault_addr, int fault_type); -+extern void sig_handler_common_skas(int sig, void *sc_ptr); -+extern void halt_skas(void); -+extern void reboot_skas(void); -+extern void kill_off_processes_skas(void); -+extern int is_skas_winch(int pid, int fd, void *data); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/mode_kern.h um/arch/um/kernel/skas/include/mode_kern.h ---- orig/arch/um/kernel/skas/include/mode_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/mode_kern.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_MODE_KERN_H__ -+#define __SKAS_MODE_KERN_H__ -+ -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/ptrace.h" -+ -+extern void flush_thread_skas(void); -+extern void *_switch_to_skas(void *prev, void *next); -+extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp); -+extern int copy_thread_skas(int nr, unsigned long clone_flags, -+ unsigned long sp, unsigned long stack_top, -+ struct task_struct *p, struct pt_regs *regs); -+extern void release_thread_skas(struct task_struct *task); -+extern void exit_thread_skas(void); -+extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); -+extern void init_idle_skas(void); -+extern void flush_tlb_kernel_vm_skas(void); -+extern void __flush_tlb_one_skas(unsigned long addr); -+extern void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_mm_skas(struct mm_struct *mm); -+extern void force_flush_all_skas(void); -+extern long execute_syscall_skas(void *r); -+extern void before_mem_skas(unsigned long unused); -+extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out); -+extern int start_uml_skas(void); -+extern int external_pid_skas(struct task_struct *task); -+extern int thread_pid_skas(struct thread_struct *thread); -+ -+#define kmem_end_skas (host_task_size - 1024 * 1024) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/proc_mm.h um/arch/um/kernel/skas/include/proc_mm.h ---- orig/arch/um/kernel/skas/include/proc_mm.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/proc_mm.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_PROC_MM_H -+#define __SKAS_PROC_MM_H -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/ptrace-skas.h um/arch/um/kernel/skas/include/ptrace-skas.h ---- orig/arch/um/kernel/skas/include/ptrace-skas.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/ptrace-skas.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_SKAS_H -+#define __PTRACE_SKAS_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_SKAS -+ -+#include "skas_ptregs.h" -+ -+#define HOST_FRAME_SIZE 17 -+ -+#define REGS_IP(r) ((r)[HOST_IP]) -+#define REGS_SP(r) ((r)[HOST_SP]) -+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -+#define REGS_EAX(r) ((r)[HOST_EAX]) -+#define REGS_EBX(r) ((r)[HOST_EBX]) -+#define REGS_ECX(r) ((r)[HOST_ECX]) -+#define REGS_EDX(r) ((r)[HOST_EDX]) -+#define REGS_ESI(r) ((r)[HOST_ESI]) -+#define REGS_EDI(r) ((r)[HOST_EDI]) -+#define REGS_EBP(r) ((r)[HOST_EBP]) -+#define REGS_CS(r) ((r)[HOST_CS]) -+#define REGS_SS(r) ((r)[HOST_SS]) -+#define REGS_DS(r) ((r)[HOST_DS]) -+#define REGS_ES(r) ((r)[HOST_ES]) -+#define REGS_FS(r) ((r)[HOST_FS]) -+#define REGS_GS(r) ((r)[HOST_GS]) -+ -+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) -+ -+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) -+ -+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) -+ -+#define REGS_FAULT_ADDR(r) ((r)->fault_addr) -+ -+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) -+ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/skas.h um/arch/um/kernel/skas/include/skas.h ---- orig/arch/um/kernel/skas/include/skas.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/skas.h 2003-11-19 03:00:51.000000000 -0500 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_H -+#define __SKAS_H -+ -+#include "sysdep/ptrace.h" -+ -+extern int userspace_pid[]; -+ -+extern void switch_threads(void *me, void *next); -+extern void thread_wait(void *sw, void *fb); -+extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, -+ void (*handler)(int)); -+extern int start_idle_thread(void *stack, void *switch_buf_ptr, -+ void **fork_buf_ptr); -+extern int user_thread(unsigned long stack, int flags); -+extern void userspace(union uml_pt_regs *regs); -+extern void new_thread_proc(void *stack, void (*handler)(int sig)); -+extern void remove_sigstack(void); -+extern void new_thread_handler(int sig); -+extern void handle_syscall(union uml_pt_regs *regs); -+extern void map(int fd, unsigned long virt, unsigned long phys, -+ unsigned long len, int r, int w, int x); -+extern int unmap(int fd, void *addr, int len); -+extern int protect(int fd, unsigned long addr, unsigned long len, -+ int r, int w, int x, int must_succeed); -+extern void user_signal(int sig, union uml_pt_regs *regs); -+extern int singlestepping_skas(void); -+extern int new_mm(int from); -+extern void save_registers(union uml_pt_regs *regs); -+extern void restore_registers(union uml_pt_regs *regs); -+extern void start_userspace(int cpu); -+extern void init_registers(int pid); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/include/uaccess.h um/arch/um/kernel/skas/include/uaccess.h ---- orig/arch/um/kernel/skas/include/uaccess.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/include/uaccess.h 2004-01-17 06:35:41.000000000 -0500 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_UACCESS_H -+#define __SKAS_UACCESS_H -+ -+#include "asm/errno.h" -+ -+#define access_ok_skas(type, addr, size) \ -+ ((segment_eq(get_fs(), KERNEL_DS)) || \ -+ (((unsigned long) (addr) < TASK_SIZE) && \ -+ ((unsigned long) (addr) + (size) <= TASK_SIZE))) -+ -+static inline int verify_area_skas(int type, const void * addr, -+ unsigned long size) -+{ -+ return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); -+} -+ -+extern int copy_from_user_skas(void *to, const void *from, int n); -+extern int copy_to_user_skas(void *to, const void *from, int n); -+extern int strncpy_from_user_skas(char *dst, const char *src, int count); -+extern int __clear_user_skas(void *mem, int len); -+extern int clear_user_skas(void *mem, int len); -+extern int strnlen_user_skas(const void *str, int len); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/Makefile um/arch/um/kernel/skas/Makefile ---- orig/arch/um/kernel/skas/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/Makefile 2003-11-11 06:36:12.000000000 -0500 -@@ -0,0 +1,31 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = skas.o -+ -+obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \ -+ process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \ -+ uaccess.o -+ -+subdir-y = sys-$(SUBARCH) -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o -+ -+include $(TOPDIR)/Rules.make -+ -+include/skas_ptregs.h : util/mk_ptregs -+ util/mk_ptregs > $@ -+ -+util/mk_ptregs : -+ $(MAKE) -C util -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -+ $(MAKE) -C util clean -+ $(RM) -f include/skas_ptregs.h -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/mem.c um/arch/um/kernel/skas/mem.c ---- orig/arch/um/kernel/skas/mem.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/mem.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "mem_user.h" -+ -+unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out) -+{ -+ /* Round up to the nearest 4M */ -+ unsigned long top = ROUND_4M((unsigned long) &arg); -+ -+ *host_size_out = top; -+ *task_size_out = top; -+ return(((unsigned long) set_task_sizes_skas) & ~0xffffff); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/mem_user.c um/arch/um/kernel/skas/mem_user.c ---- orig/arch/um/kernel/skas/mem_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/mem_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,105 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <sys/mman.h> -+#include <sys/ptrace.h> -+#include "mem_user.h" -+#include "mem.h" -+#include "user.h" -+#include "os.h" -+#include "proc_mm.h" -+ -+void map(int fd, unsigned long virt, unsigned long phys, unsigned long len, -+ int r, int w, int x) -+{ -+ struct proc_mm_op map; -+ __u64 offset; -+ int prot, n, phys_fd; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ phys_fd = phys_mapping(phys, &offset); -+ -+ map = ((struct proc_mm_op) { .op = MM_MMAP, -+ .u = -+ { .mmap = -+ { .addr = virt, -+ .len = len, -+ .prot = prot, -+ .flags = MAP_SHARED | -+ MAP_FIXED, -+ .fd = phys_fd, -+ .offset = offset -+ } } } ); -+ n = os_write_file(fd, &map, sizeof(map)); -+ if(n != sizeof(map)) -+ printk("map : /proc/mm map failed, err = %d\n", -n); -+} -+ -+int unmap(int fd, void *addr, int len) -+{ -+ struct proc_mm_op unmap; -+ int n; -+ -+ unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, -+ .u = -+ { .munmap = -+ { .addr = (unsigned long) addr, -+ .len = len } } } ); -+ n = os_write_file(fd, &unmap, sizeof(unmap)); -+ if(n != sizeof(unmap)) { -+ if(n < 0) -+ return(n); -+ else if(n > 0) -+ return(-EIO); -+ } -+ -+ return(0); -+} -+ -+int protect(int fd, unsigned long addr, unsigned long len, int r, int w, -+ int x, int must_succeed) -+{ -+ struct proc_mm_op protect; -+ int prot, n; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ -+ protect = ((struct proc_mm_op) { .op = MM_MPROTECT, -+ .u = -+ { .mprotect = -+ { .addr = (unsigned long) addr, -+ .len = len, -+ .prot = prot } } } ); -+ -+ n = os_write_file(fd, &protect, sizeof(protect)); -+ if(n != sizeof(protect)) { -+ if(n == 0) return(0); -+ -+ if(must_succeed) -+ panic("protect failed, err = %d", -n); -+ -+ return(-EIO); -+ } -+ -+ return(0); -+} -+ -+void before_mem_skas(unsigned long unused) -+{ -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/mmu.c um/arch/um/kernel/skas/mmu.c ---- orig/arch/um/kernel/skas/mmu.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/mmu.c 2003-11-15 22:25:20.000000000 -0500 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/list.h" -+#include "linux/spinlock.h" -+#include "linux/slab.h" -+#include "asm/segment.h" -+#include "asm/mmu.h" -+#include "os.h" -+#include "skas.h" -+ -+int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) -+{ -+ int from; -+ -+ if((current->mm != NULL) && (current->mm != &init_mm)) -+ from = current->mm->context.skas.mm_fd; -+ else from = -1; -+ -+ mm->context.skas.mm_fd = new_mm(from); -+ if(mm->context.skas.mm_fd < 0){ -+ printk("init_new_context_skas - new_mm failed, errno = %d\n", -+ mm->context.skas.mm_fd); -+ return(mm->context.skas.mm_fd); -+ } -+ -+ return(0); -+} -+ -+void destroy_context_skas(struct mm_struct *mm) -+{ -+ os_close_file(mm->context.skas.mm_fd); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/process.c um/arch/um/kernel/skas/process.c ---- orig/arch/um/kernel/skas/process.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/process.c 2004-01-31 02:49:36.000000000 -0500 -@@ -0,0 +1,417 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <signal.h> -+#include <setjmp.h> -+#include <sched.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <sys/mman.h> -+#include <sys/user.h> -+#include <asm/unistd.h> -+#include "user.h" -+#include "ptrace_user.h" -+#include "time_user.h" -+#include "sysdep/ptrace.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "skas.h" -+#include "sysdep/sigcontext.h" -+#include "os.h" -+#include "proc_mm.h" -+#include "skas_ptrace.h" -+#include "chan_user.h" -+ -+int is_skas_winch(int pid, int fd, void *data) -+{ -+ if(pid != getpid()) -+ return(0); -+ -+ register_winch_irq(-1, fd, -1, data); -+ return(1); -+} -+ -+/* These are set once at boot time and not changed thereafter */ -+ -+unsigned long exec_regs[FRAME_SIZE]; -+unsigned long exec_fp_regs[HOST_FP_SIZE]; -+unsigned long exec_fpx_regs[HOST_XFP_SIZE]; -+int have_fpx_regs = 1; -+ -+static void handle_segv(int pid) -+{ -+ struct ptrace_faultinfo fault; -+ int err; -+ -+ err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault); -+ if(err) -+ panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n", -+ errno); -+ -+ segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); -+} -+ -+static void handle_trap(int pid, union uml_pt_regs *regs) -+{ -+ int err, syscall_nr, status; -+ -+ syscall_nr = PT_SYSCALL_NR(regs->skas.regs); -+ UPT_SYSCALL_NR(regs) = syscall_nr; -+ if(syscall_nr < 1){ -+ relay_signal(SIGTRAP, regs); -+ return; -+ } -+ -+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); -+ if(err < 0) -+ panic("handle_trap - nullifying syscall failed errno = %d\n", -+ errno); -+ -+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ if(err < 0) -+ panic("handle_trap - continuing to end of syscall failed, " -+ "errno = %d\n", errno); -+ -+ err = waitpid(pid, &status, WUNTRACED); -+ if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -+ panic("handle_trap - failed to wait at end of syscall, " -+ "errno = %d, status = %d\n", errno, status); -+ -+ handle_syscall(regs); -+} -+ -+static int userspace_tramp(void *arg) -+{ -+ init_new_thread_signals(0); -+ enable_timer(); -+ ptrace(PTRACE_TRACEME, 0, 0, 0); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+/* Each element set once, and only accessed by a single processor anyway */ -+#define NR_CPUS 1 -+int userspace_pid[NR_CPUS]; -+ -+void start_userspace(int cpu) -+{ -+ void *stack; -+ unsigned long sp; -+ int pid, status, n; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if(stack == MAP_FAILED) -+ panic("start_userspace : mmap failed, errno = %d", errno); -+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ -+ pid = clone(userspace_tramp, (void *) sp, -+ CLONE_FILES | CLONE_VM | SIGCHLD, NULL); -+ if(pid < 0) -+ panic("start_userspace : clone failed, errno = %d", errno); -+ -+ do { -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0) -+ panic("start_userspace : wait failed, errno = %d", -+ errno); -+ } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) -+ panic("start_userspace : expected SIGSTOP, got status = %d", -+ status); -+ -+ if(munmap(stack, PAGE_SIZE) < 0) -+ panic("start_userspace : munmap failed, errno = %d\n", errno); -+ -+ userspace_pid[cpu] = pid; -+} -+ -+void userspace(union uml_pt_regs *regs) -+{ -+ int err, status, op, pid = userspace_pid[0]; -+ -+ restore_registers(regs); -+ -+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ if(err) -+ panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", -+ errno); -+ while(1){ -+ err = waitpid(pid, &status, WUNTRACED); -+ if(err < 0) -+ panic("userspace - waitpid failed, errno = %d\n", -+ errno); -+ -+ regs->skas.is_user = 1; -+ save_registers(regs); -+ -+ if(WIFSTOPPED(status)){ -+ switch(WSTOPSIG(status)){ -+ case SIGSEGV: -+ handle_segv(pid); -+ break; -+ case SIGTRAP: -+ handle_trap(pid, regs); -+ break; -+ case SIGIO: -+ case SIGVTALRM: -+ case SIGILL: -+ case SIGBUS: -+ case SIGFPE: -+ case SIGWINCH: -+ user_signal(WSTOPSIG(status), regs); -+ break; -+ default: -+ printk("userspace - child stopped with signal " -+ "%d\n", WSTOPSIG(status)); -+ } -+ interrupt_end(); -+ } -+ -+ restore_registers(regs); -+ -+ op = singlestepping_skas() ? PTRACE_SINGLESTEP : -+ PTRACE_SYSCALL; -+ err = ptrace(op, pid, 0, 0); -+ if(err) -+ panic("userspace - PTRACE_SYSCALL failed, " -+ "errno = %d\n", errno); -+ } -+} -+ -+void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, -+ void (*handler)(int)) -+{ -+ sigjmp_buf switch_buf, fork_buf; -+ -+ *switch_buf_ptr = &switch_buf; -+ *fork_buf_ptr = &fork_buf; -+ -+ if(sigsetjmp(fork_buf, 1) == 0) -+ new_thread_proc(stack, handler); -+ -+ remove_sigstack(); -+} -+ -+void thread_wait(void *sw, void *fb) -+{ -+ sigjmp_buf buf, **switch_buf = sw, *fork_buf; -+ -+ *switch_buf = &buf; -+ fork_buf = fb; -+ if(sigsetjmp(buf, 1) == 0) -+ siglongjmp(*fork_buf, 1); -+} -+ -+static int move_registers(int pid, int int_op, int fp_op, -+ union uml_pt_regs *regs, unsigned long *fp_regs) -+{ -+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) -+ return(-errno); -+ if(ptrace(fp_op, pid, 0, fp_regs) < 0) -+ return(-errno); -+ return(0); -+} -+ -+void save_registers(union uml_pt_regs *regs) -+{ -+ unsigned long *fp_regs; -+ int err, fp_op; -+ -+ if(have_fpx_regs){ -+ fp_op = PTRACE_GETFPXREGS; -+ fp_regs = regs->skas.xfp; -+ } -+ else { -+ fp_op = PTRACE_GETFPREGS; -+ fp_regs = regs->skas.fp; -+ } -+ -+ err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs, -+ fp_regs); -+ if(err) -+ panic("save_registers - saving registers failed, errno = %d\n", -+ -err); -+} -+ -+void restore_registers(union uml_pt_regs *regs) -+{ -+ unsigned long *fp_regs; -+ int err, fp_op; -+ -+ if(have_fpx_regs){ -+ fp_op = PTRACE_SETFPXREGS; -+ fp_regs = regs->skas.xfp; -+ } -+ else { -+ fp_op = PTRACE_SETFPREGS; -+ fp_regs = regs->skas.fp; -+ } -+ -+ err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs, -+ fp_regs); -+ if(err) -+ panic("restore_registers - saving registers failed, " -+ "errno = %d\n", -err); -+} -+ -+void switch_threads(void *me, void *next) -+{ -+ sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; -+ -+ *me_ptr = &my_buf; -+ if(sigsetjmp(my_buf, 1) == 0) -+ siglongjmp(*next_buf, 1); -+} -+ -+static sigjmp_buf initial_jmpbuf; -+ -+/* XXX Make these percpu */ -+static void (*cb_proc)(void *arg); -+static void *cb_arg; -+static sigjmp_buf *cb_back; -+ -+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) -+{ -+ sigjmp_buf **switch_buf = switch_buf_ptr; -+ int n; -+ -+ *fork_buf_ptr = &initial_jmpbuf; -+ n = sigsetjmp(initial_jmpbuf, 1); -+ if(n == 0) -+ new_thread_proc((void *) stack, new_thread_handler); -+ else if(n == 1) -+ remove_sigstack(); -+ else if(n == 2){ -+ (*cb_proc)(cb_arg); -+ siglongjmp(*cb_back, 1); -+ } -+ else if(n == 3){ -+ kmalloc_ok = 0; -+ return(0); -+ } -+ else if(n == 4){ -+ kmalloc_ok = 0; -+ return(1); -+ } -+ siglongjmp(**switch_buf, 1); -+} -+ -+void remove_sigstack(void) -+{ -+ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, -+ .ss_sp = NULL, -+ .ss_size = 0 }); -+ -+ if(sigaltstack(&stack, NULL) != 0) -+ panic("disabling signal stack failed, errno = %d\n", errno); -+} -+ -+void initial_thread_cb_skas(void (*proc)(void *), void *arg) -+{ -+ sigjmp_buf here; -+ -+ cb_proc = proc; -+ cb_arg = arg; -+ cb_back = &here; -+ -+ block_signals(); -+ if(sigsetjmp(here, 1) == 0) -+ siglongjmp(initial_jmpbuf, 2); -+ unblock_signals(); -+ -+ cb_proc = NULL; -+ cb_arg = NULL; -+ cb_back = NULL; -+} -+ -+void halt_skas(void) -+{ -+ block_signals(); -+ siglongjmp(initial_jmpbuf, 3); -+} -+ -+void reboot_skas(void) -+{ -+ block_signals(); -+ siglongjmp(initial_jmpbuf, 4); -+} -+ -+int new_mm(int from) -+{ -+ struct proc_mm_op copy; -+ int n, fd = os_open_file("/proc/mm", -+ of_cloexec(of_write(OPENFLAGS())), 0); -+ -+ if(fd < 0) -+ return(fd); -+ -+ if(from != -1){ -+ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, -+ .u = -+ { .copy_segments = from } } ); -+ n = os_write_file(fd, ©, sizeof(copy)); -+ if(n != sizeof(copy)) -+ printk("new_mm : /proc/mm copy_segments failed, " -+ "err = %d\n", -n); -+ } -+ -+ return(fd); -+} -+ -+void switch_mm_skas(int mm_fd) -+{ -+ int err; -+ -+#warning need cpu pid in switch_mm_skas -+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); -+ if(err) -+ panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", -+ errno); -+} -+ -+void kill_off_processes_skas(void) -+{ -+#warning need to loop over userspace_pids in kill_off_processes_skas -+ os_kill_process(userspace_pid[0], 1); -+} -+ -+void init_registers(int pid) -+{ -+ int err; -+ -+ if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0) -+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", -+ errno); -+ -+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); -+ if(!err) -+ return; -+ -+ have_fpx_regs = 0; -+ if(errno != EIO) -+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", -+ errno); -+ -+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); -+ if(err) -+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", -+ errno); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/process_kern.c um/arch/um/kernel/skas/process_kern.c ---- orig/arch/um/kernel/skas/process_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/process_kern.c 2003-11-19 03:18:25.000000000 -0500 -@@ -0,0 +1,196 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "kern_util.h" -+#include "time_user.h" -+#include "signal_user.h" -+#include "skas.h" -+#include "os.h" -+#include "user_util.h" -+#include "tlb.h" -+#include "frame.h" -+#include "kern.h" -+#include "mode.h" -+ -+int singlestepping_skas(void) -+{ -+ int ret = current->ptrace & PT_DTRACE; -+ -+ current->ptrace &= ~PT_DTRACE; -+ return(ret); -+} -+ -+void *_switch_to_skas(void *prev, void *next) -+{ -+ struct task_struct *from, *to; -+ -+ from = prev; -+ to = next; -+ -+ /* XXX need to check runqueues[cpu].idle */ -+ if(current->pid == 0) -+ switch_timers(0); -+ -+ to->thread.prev_sched = from; -+ set_current(to); -+ -+ switch_threads(&from->thread.mode.skas.switch_buf, -+ to->thread.mode.skas.switch_buf); -+ -+ if(current->pid == 0) -+ switch_timers(1); -+ -+ return(current->thread.prev_sched); -+} -+ -+extern void schedule_tail(struct task_struct *prev); -+ -+void new_thread_handler(int sig) -+{ -+ int (*fn)(void *), n; -+ void *arg; -+ -+ fn = current->thread.request.u.thread.proc; -+ arg = current->thread.request.u.thread.arg; -+ change_sig(SIGUSR1, 1); -+ thread_wait(¤t->thread.mode.skas.switch_buf, -+ current->thread.mode.skas.fork_buf); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ /* The return value is 1 if the kernel thread execs a process, -+ * 0 if it just exits -+ */ -+ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); -+ if(n == 1) -+ userspace(¤t->thread.regs.regs); -+ else do_exit(0); -+} -+ -+void new_thread_proc(void *stack, void (*handler)(int sig)) -+{ -+ init_new_thread_stack(stack, handler); -+ os_usr1_process(os_getpid()); -+} -+ -+void release_thread_skas(struct task_struct *task) -+{ -+} -+ -+void exit_thread_skas(void) -+{ -+} -+ -+void fork_handler(int sig) -+{ -+ change_sig(SIGUSR1, 1); -+ thread_wait(¤t->thread.mode.skas.switch_buf, -+ current->thread.mode.skas.fork_buf); -+ -+ force_flush_all(); -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ unblock_signals(); -+ -+ userspace(¤t->thread.regs.regs); -+} -+ -+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ void (*handler)(int); -+ -+ if(current->thread.forking){ -+ memcpy(&p->thread.regs.regs.skas, -+ ¤t->thread.regs.regs.skas, -+ sizeof(p->thread.regs.regs.skas)); -+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); -+ if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; -+ -+ handler = fork_handler; -+ } -+ else { -+ memcpy(p->thread.regs.regs.skas.regs, exec_regs, -+ sizeof(p->thread.regs.regs.skas.regs)); -+ memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, -+ sizeof(p->thread.regs.regs.skas.fp)); -+ memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, -+ sizeof(p->thread.regs.regs.skas.xfp)); -+ p->thread.request.u.thread = current->thread.request.u.thread; -+ handler = new_thread_handler; -+ } -+ -+ new_thread((void *) p->thread.kernel_stack, -+ &p->thread.mode.skas.switch_buf, -+ &p->thread.mode.skas.fork_buf, handler); -+ return(0); -+} -+ -+void init_idle_skas(void) -+{ -+ cpu_tasks[current->processor].pid = os_getpid(); -+} -+ -+extern void start_kernel(void); -+ -+static int start_kernel_proc(void *unused) -+{ -+ int pid; -+ -+ block_signals(); -+ pid = os_getpid(); -+ -+ cpu_tasks[0].pid = pid; -+ cpu_tasks[0].task = current; -+#ifdef CONFIG_SMP -+ cpu_online_map = 1; -+#endif -+ start_kernel(); -+ return(0); -+} -+ -+int start_uml_skas(void) -+{ -+ start_userspace(0); -+ capture_signal_stack(); -+ idle_timer(); -+ -+ init_new_thread_signals(1); -+ -+ init_task.thread.request.u.thread.proc = start_kernel_proc; -+ init_task.thread.request.u.thread.arg = NULL; -+ return(start_idle_thread((void *) init_task.thread.kernel_stack, -+ &init_task.thread.mode.skas.switch_buf, -+ &init_task.thread.mode.skas.fork_buf)); -+} -+ -+int external_pid_skas(struct task_struct *task) -+{ -+#warning Need to look up userspace_pid by cpu -+ return(userspace_pid[0]); -+} -+ -+int thread_pid_skas(struct thread_struct *thread) -+{ -+#warning Need to look up userspace_pid by cpu -+ return(userspace_pid[0]); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/syscall_kern.c um/arch/um/kernel/skas/syscall_kern.c ---- orig/arch/um/kernel/skas/syscall_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/syscall_kern.c 2004-01-04 08:20:29.000000000 -0500 -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sys.h" -+#include "asm/errno.h" -+#include "asm/unistd.h" -+#include "asm/ptrace.h" -+#include "asm/current.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+extern syscall_handler_t *sys_call_table[]; -+ -+long execute_syscall_skas(void *r) -+{ -+ struct pt_regs *regs = r; -+ long res; -+ int syscall; -+ -+ current->thread.nsyscalls++; -+ nsyscalls++; -+ syscall = UPT_SYSCALL_NR(®s->regs); -+ -+ if((syscall >= NR_syscalls) || (syscall < 1)) -+ res = -ENOSYS; -+ else res = EXECUTE_SYSCALL(syscall, regs); -+ -+ return(res); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/syscall_user.c um/arch/um/kernel/skas/syscall_user.c ---- orig/arch/um/kernel/skas/syscall_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/syscall_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <signal.h> -+#include "kern_util.h" -+#include "syscall_user.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+ -+/* XXX Bogus */ -+#define ERESTARTSYS 512 -+#define ERESTARTNOINTR 513 -+#define ERESTARTNOHAND 514 -+ -+void handle_syscall(union uml_pt_regs *regs) -+{ -+ long result; -+ int index; -+ -+ index = record_syscall_start(UPT_SYSCALL_NR(regs)); -+ -+ syscall_trace(); -+ result = execute_syscall(regs); -+ -+ REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); -+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || -+ (result == -ERESTARTNOINTR)) -+ do_signal(result); -+ -+ syscall_trace(); -+ record_syscall_end(index, result); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/sys-i386/Makefile um/arch/um/kernel/skas/sys-i386/Makefile ---- orig/arch/um/kernel/skas/sys-i386/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/sys-i386/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = sys-i386.o -+ -+obj-y = sigcontext.o -+ -+USER_OBJS = sigcontext.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/sys-i386/sigcontext.c um/arch/um/kernel/skas/sys-i386/sigcontext.c ---- orig/arch/um/kernel/skas/sys-i386/sigcontext.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/sys-i386/sigcontext.c 2003-11-19 03:27:43.000000000 -0500 -@@ -0,0 +1,114 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <asm/sigcontext.h> -+#include <sys/ptrace.h> -+#include <linux/ptrace.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/ptrace_user.h" -+#include "kern_util.h" -+#include "user.h" -+#include "sigcontext.h" -+#include "mode.h" -+ -+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr) -+{ -+ struct sigcontext sc, *from = from_ptr; -+ unsigned long fpregs[FP_FRAME_SIZE]; -+ int err; -+ -+ err = copy_from_user_proc(&sc, from, sizeof(sc)); -+ err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs)); -+ if(err) -+ return(err); -+ -+ regs->skas.regs[GS] = sc.gs; -+ regs->skas.regs[FS] = sc.fs; -+ regs->skas.regs[ES] = sc.es; -+ regs->skas.regs[DS] = sc.ds; -+ regs->skas.regs[EDI] = sc.edi; -+ regs->skas.regs[ESI] = sc.esi; -+ regs->skas.regs[EBP] = sc.ebp; -+ regs->skas.regs[UESP] = sc.esp; -+ regs->skas.regs[EBX] = sc.ebx; -+ regs->skas.regs[EDX] = sc.edx; -+ regs->skas.regs[ECX] = sc.ecx; -+ regs->skas.regs[EAX] = sc.eax; -+ regs->skas.regs[EIP] = sc.eip; -+ regs->skas.regs[CS] = sc.cs; -+ regs->skas.regs[EFL] = sc.eflags; -+ regs->skas.regs[SS] = sc.ss; -+ regs->skas.fault_addr = sc.cr2; -+ regs->skas.fault_type = FAULT_WRITE(sc.err); -+ regs->skas.trap_type = sc.trapno; -+ -+ err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs); -+ if(err < 0){ -+ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, " -+ "errno = %d\n", errno); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, -+ union uml_pt_regs *regs, unsigned long fault_addr, -+ int fault_type) -+{ -+ struct sigcontext sc, *to = to_ptr; -+ struct _fpstate *to_fp; -+ unsigned long fpregs[FP_FRAME_SIZE]; -+ int err; -+ -+ sc.gs = regs->skas.regs[GS]; -+ sc.fs = regs->skas.regs[FS]; -+ sc.es = regs->skas.regs[ES]; -+ sc.ds = regs->skas.regs[DS]; -+ sc.edi = regs->skas.regs[EDI]; -+ sc.esi = regs->skas.regs[ESI]; -+ sc.ebp = regs->skas.regs[EBP]; -+ sc.esp = regs->skas.regs[UESP]; -+ sc.ebx = regs->skas.regs[EBX]; -+ sc.edx = regs->skas.regs[EDX]; -+ sc.ecx = regs->skas.regs[ECX]; -+ sc.eax = regs->skas.regs[EAX]; -+ sc.eip = regs->skas.regs[EIP]; -+ sc.cs = regs->skas.regs[CS]; -+ sc.eflags = regs->skas.regs[EFL]; -+ sc.esp_at_signal = regs->skas.regs[UESP]; -+ sc.ss = regs->skas.regs[SS]; -+ sc.cr2 = fault_addr; -+ sc.err = TO_SC_ERR(fault_type); -+ sc.trapno = regs->skas.trap_type; -+ -+ err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs); -+ if(err < 0){ -+ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, " -+ "errno = %d\n", errno); -+ return(1); -+ } -+ to_fp = (struct _fpstate *) -+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -+ sc.fpstate = to_fp; -+ -+ if(err) -+ return(err); -+ -+ return(copy_to_user_proc(to, &sc, sizeof(sc)) || -+ copy_to_user_proc(to_fp, fpregs, sizeof(fpregs))); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/time.c um/arch/um/kernel/skas/time.c ---- orig/arch/um/kernel/skas/time.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/time.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <sys/signal.h> -+#include <sys/time.h> -+#include "time_user.h" -+#include "process.h" -+#include "user.h" -+ -+void user_time_init_skas(void) -+{ -+ if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGALRM handler"); -+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/tlb.c um/arch/um/kernel/skas/tlb.c ---- orig/arch/um/kernel/skas/tlb.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/tlb.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,153 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/mmu.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "skas.h" -+#include "os.h" -+ -+static void fix_range(struct mm_struct *mm, unsigned long start_addr, -+ unsigned long end_addr, int force) -+{ -+ pgd_t *npgd; -+ pmd_t *npmd; -+ pte_t *npte; -+ unsigned long addr; -+ int r, w, x, err, fd; -+ -+ if(mm == NULL) return; -+ fd = mm->context.skas.mm_fd; -+ for(addr = start_addr; addr < end_addr;){ -+ npgd = pgd_offset(mm, addr); -+ npmd = pmd_offset(npgd, addr); -+ if(pmd_present(*npmd)){ -+ npte = pte_offset(npmd, addr); -+ r = pte_read(*npte); -+ w = pte_write(*npte); -+ x = pte_exec(*npte); -+ if(!pte_dirty(*npte)) w = 0; -+ if(!pte_young(*npte)){ -+ r = 0; -+ w = 0; -+ } -+ if(force || pte_newpage(*npte)){ -+ err = unmap(fd, (void *) addr, PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*npte)) -+ map(fd, addr, -+ pte_val(*npte) & PAGE_MASK, -+ PAGE_SIZE, r, w, x); -+ } -+ else if(pte_newprot(*npte)){ -+ protect(fd, addr, PAGE_SIZE, r, w, x, 1); -+ } -+ *npte = pte_mkuptodate(*npte); -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(force || pmd_newpage(*npmd)){ -+ err = unmap(fd, (void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ pmd_mkuptodate(*npmd); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+static void flush_kernel_vm_range(unsigned long start, unsigned long end) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ int updated = 0, err; -+ -+ mm = &init_mm; -+ for(addr = start_vm; addr < end_vm;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte) || pte_newpage(*pte)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*pte)) -+ map_memory(addr, -+ pte_val(*pte) & PAGE_MASK, -+ PAGE_SIZE, 1, 1, 1); -+ } -+ else if(pte_newprot(*pte)){ -+ updated = 1; -+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); -+ } -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(pmd_newpage(*pmd)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+void flush_tlb_kernel_vm_skas(void) -+{ -+ flush_kernel_vm_range(start_vm, end_vm); -+} -+ -+void __flush_tlb_one_skas(unsigned long addr) -+{ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE); -+} -+ -+void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ if(mm == NULL) -+ flush_kernel_vm_range(start, end); -+ else fix_range(mm, start, end, 0); -+} -+ -+void flush_tlb_mm_skas(struct mm_struct *mm) -+{ -+ flush_tlb_kernel_vm_skas(); -+ fix_range(mm, 0, host_task_size, 0); -+} -+ -+void force_flush_all_skas(void) -+{ -+ fix_range(current->mm, 0, host_task_size, 1); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/trap_user.c um/arch/um/kernel/skas/trap_user.c ---- orig/arch/um/kernel/skas/trap_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/trap_user.c 2004-01-21 01:17:05.000000000 -0500 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include <errno.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "task.h" -+#include "sigcontext.h" -+ -+void sig_handler_common_skas(int sig, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct skas_regs *r; -+ struct signal_info *info; -+ int save_errno = errno; -+ int save_user; -+ -+ r = &TASK_REGS(get_current())->skas; -+ save_user = r->is_user; -+ r->is_user = 0; -+ r->fault_addr = SC_FAULT_ADDR(sc); -+ r->fault_type = SC_FAULT_TYPE(sc); -+ r->trap_type = SC_TRAP_TYPE(sc); -+ -+ change_sig(SIGUSR1, 1); -+ info = &sig_info[sig]; -+ if(!info->is_irq) unblock_signals(); -+ -+ (*info->handler)(sig, (union uml_pt_regs *) r); -+ -+ errno = save_errno; -+ r->is_user = save_user; -+} -+ -+extern int missed_ticks[]; -+ -+void user_signal(int sig, union uml_pt_regs *regs) -+{ -+ struct signal_info *info; -+ -+ regs->skas.is_user = 1; -+ regs->skas.fault_addr = 0; -+ regs->skas.fault_type = 0; -+ regs->skas.trap_type = 0; -+ info = &sig_info[sig]; -+ (*info->handler)(sig, regs); -+ -+ unblock_signals(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/uaccess.c um/arch/um/kernel/skas/uaccess.c ---- orig/arch/um/kernel/skas/uaccess.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/uaccess.c 2003-12-22 01:30:09.000000000 -0500 -@@ -0,0 +1,217 @@ -+/* -+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/string.h" -+#include "linux/fs.h" -+#include "linux/highmem.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+ -+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, -+ pte_t *pte_out); -+ -+static unsigned long maybe_map(unsigned long virt, int is_write) -+{ -+ pte_t pte; -+ -+ void *phys = um_virt_to_phys(current, virt, &pte); -+ int dummy_code; -+ -+ if(IS_ERR(phys) || (is_write && !pte_write(pte))){ -+ if(!handle_page_fault(virt, 0, is_write, 0, &dummy_code)) -+ return(0); -+ phys = um_virt_to_phys(current, virt, NULL); -+ } -+ return((unsigned long) phys); -+} -+ -+static int do_op(unsigned long addr, int len, int is_write, -+ int (*op)(unsigned long addr, int len, void *arg), void *arg) -+{ -+ struct page *page; -+ int n; -+ -+ addr = maybe_map(addr, is_write); -+ if(addr == -1) -+ return(-1); -+ -+ page = phys_to_page(addr); -+ addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); -+ n = (*op)(addr, len, arg); -+ kunmap(page); -+ -+ return(n); -+} -+ -+static int buffer_op(unsigned long addr, int len, int is_write, -+ int (*op)(unsigned long addr, int len, void *arg), -+ void *arg) -+{ -+ int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); -+ int remain = len, n; -+ -+ n = do_op(addr, size, is_write, op, arg); -+ if(n != 0) -+ return(n < 0 ? remain : 0); -+ -+ addr += size; -+ remain -= size; -+ if(remain == 0) -+ return(0); -+ -+ while(addr < ((addr + remain) & PAGE_MASK)){ -+ n = do_op(addr, PAGE_SIZE, is_write, op, arg); -+ if(n != 0) -+ return(n < 0 ? remain : 0); -+ -+ addr += PAGE_SIZE; -+ remain -= PAGE_SIZE; -+ } -+ if(remain == 0) -+ return(0); -+ -+ n = do_op(addr, remain, is_write, op, arg); -+ if(n != 0) -+ return(n < 0 ? remain : 0); -+ return(0); -+} -+ -+static int copy_chunk_from_user(unsigned long from, int len, void *arg) -+{ -+ unsigned long *to_ptr = arg, to = *to_ptr; -+ -+ memcpy((void *) to, (void *) from, len); -+ *to_ptr += len; -+ return(0); -+} -+ -+int copy_from_user_skas(void *to, const void *from, int n) -+{ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ memcpy(to, from, n); -+ return(0); -+ } -+ -+ return(access_ok_skas(VERIFY_READ, from, n) ? -+ buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): -+ n); -+} -+ -+static int copy_chunk_to_user(unsigned long to, int len, void *arg) -+{ -+ unsigned long *from_ptr = arg, from = *from_ptr; -+ -+ memcpy((void *) to, (void *) from, len); -+ *from_ptr += len; -+ return(0); -+} -+ -+int copy_to_user_skas(void *to, const void *from, int n) -+{ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ memcpy(to, from, n); -+ return(0); -+ } -+ -+ return(access_ok_skas(VERIFY_WRITE, to, n) ? -+ buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : -+ n); -+} -+ -+static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) -+{ -+ char **to_ptr = arg, *to = *to_ptr; -+ int n; -+ -+ strncpy(to, (void *) from, len); -+ n = strnlen(to, len); -+ *to_ptr += n; -+ -+ if(n < len) -+ return(1); -+ return(0); -+} -+ -+int strncpy_from_user_skas(char *dst, const char *src, int count) -+{ -+ int n; -+ char *ptr = dst; -+ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ strncpy(dst, src, count); -+ return(strnlen(dst, count)); -+ } -+ -+ if(!access_ok_skas(VERIFY_READ, src, 1)) -+ return(-EFAULT); -+ -+ n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, -+ &ptr); -+ if(n != 0) -+ return(-EFAULT); -+ return(strnlen(dst, count)); -+} -+ -+static int clear_chunk(unsigned long addr, int len, void *unused) -+{ -+ memset((void *) addr, 0, len); -+ return(0); -+} -+ -+int __clear_user_skas(void *mem, int len) -+{ -+ return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); -+} -+ -+int clear_user_skas(void *mem, int len) -+{ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ memset(mem, 0, len); -+ return(0); -+ } -+ -+ return(access_ok_skas(VERIFY_WRITE, mem, len) ? -+ buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); -+} -+ -+static int strnlen_chunk(unsigned long str, int len, void *arg) -+{ -+ int *len_ptr = arg, n; -+ -+ n = strnlen((void *) str, len); -+ *len_ptr += n; -+ -+ if(n < len) -+ return(1); -+ return(0); -+} -+ -+int strnlen_user_skas(const void *str, int len) -+{ -+ int count = 0, n; -+ -+ if(segment_eq(get_fs(), KERNEL_DS)) -+ return(strnlen(str, len) + 1); -+ -+ n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); -+ if(n == 0) -+ return(count + 1); -+ return(-EFAULT); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/util/Makefile um/arch/um/kernel/skas/util/Makefile ---- orig/arch/um/kernel/skas/util/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/util/Makefile 2003-11-08 02:52:22.000000000 -0500 -@@ -0,0 +1,10 @@ -+all: mk_ptregs -+ -+mk_ptregs : mk_ptregs.o -+ $(HOSTCC) -o mk_ptregs mk_ptregs.o -+ -+mk_ptregs.o : mk_ptregs.c -+ $(HOSTCC) -c $< -+ -+clean : -+ $(RM) -f mk_ptregs *.o *~ -diff -Naur -X ../exclude-files orig/arch/um/kernel/skas/util/mk_ptregs.c um/arch/um/kernel/skas/util/mk_ptregs.c ---- orig/arch/um/kernel/skas/util/mk_ptregs.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/skas/util/mk_ptregs.c 2003-12-22 01:31:11.000000000 -0500 -@@ -0,0 +1,51 @@ -+#include <stdio.h> -+#include <asm/ptrace.h> -+#include <asm/user.h> -+ -+#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) -+ -+int main(int argc, char **argv) -+{ -+ printf("/* Automatically generated by " -+ "arch/um/kernel/skas/util/mk_ptregs */\n"); -+ printf("\n"); -+ printf("#ifndef __SKAS_PT_REGS_\n"); -+ printf("#define __SKAS_PT_REGS_\n"); -+ printf("\n"); -+ printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); -+ printf("#define HOST_FP_SIZE %d\n", -+ sizeof(struct user_i387_struct) / sizeof(unsigned long)); -+ printf("#define HOST_XFP_SIZE %d\n", -+ sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); -+ -+ PRINT_REG("IP", EIP); -+ PRINT_REG("SP", UESP); -+ PRINT_REG("EFLAGS", EFL); -+ PRINT_REG("EAX", EAX); -+ PRINT_REG("EBX", EBX); -+ PRINT_REG("ECX", ECX); -+ PRINT_REG("EDX", EDX); -+ PRINT_REG("ESI", ESI); -+ PRINT_REG("EDI", EDI); -+ PRINT_REG("EBP", EBP); -+ PRINT_REG("CS", CS); -+ PRINT_REG("SS", SS); -+ PRINT_REG("DS", DS); -+ PRINT_REG("FS", FS); -+ PRINT_REG("ES", ES); -+ PRINT_REG("GS", GS); -+ printf("\n"); -+ printf("#endif\n"); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/smp.c um/arch/um/kernel/smp.c ---- orig/arch/um/kernel/smp.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/smp.c 2003-11-15 02:59:25.000000000 -0500 -@@ -0,0 +1,328 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_SMP -+ -+#include "linux/sched.h" -+#include "linux/threads.h" -+#include "linux/interrupt.h" -+#include "asm/smp.h" -+#include "asm/processor.h" -+#include "asm/spinlock.h" -+#include "asm/softirq.h" -+#include "asm/hardirq.h" -+#include "asm/tlb.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "kern.h" -+#include "os.h" -+ -+/* Total count of live CPUs, set by smp_boot_cpus */ -+int smp_num_cpus = 1; -+ -+/* The 'big kernel lock' */ -+spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED}; -+ -+/* Per CPU bogomips and other parameters */ -+ -+/* The only piece used here is the ipi pipe, which is set before SMP is -+ * started and never changed. -+ */ -+struct cpuinfo_um cpu_data[NR_CPUS]; -+ -+/* CPU online map, set by smp_boot_cpus */ -+unsigned long cpu_online_map; -+ -+atomic_t global_bh_count; -+ -+/* Set when the idlers are all forked */ -+int smp_threads_ready = 0; -+ -+/* Not used by UML */ -+unsigned char global_irq_holder = 0; -+unsigned volatile long global_irq_lock; -+ -+/* A statistic, can be a little off */ -+static int num_reschedules_sent = 0; -+ -+mmu_gather_t mmu_gathers[NR_CPUS]; -+ -+void smp_send_reschedule(int cpu) -+{ -+ os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1); -+ num_reschedules_sent++; -+} -+ -+static void show(char * str) -+{ -+ int cpu = smp_processor_id(); -+ -+ printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu); -+} -+ -+#define MAXCOUNT 100000000 -+ -+static inline void wait_on_bh(void) -+{ -+ int count = MAXCOUNT; -+ do { -+ if (!--count) { -+ show("wait_on_bh"); -+ count = ~0; -+ } -+ /* nothing .. wait for the other bh's to go away */ -+ } while (atomic_read(&global_bh_count) != 0); -+} -+ -+/* -+ * This is called when we want to synchronize with -+ * bottom half handlers. We need to wait until -+ * no other CPU is executing any bottom half handler. -+ * -+ * Don't wait if we're already running in an interrupt -+ * context or are inside a bh handler. -+ */ -+void synchronize_bh(void) -+{ -+ if (atomic_read(&global_bh_count) && !in_interrupt()) -+ wait_on_bh(); -+} -+ -+void smp_send_stop(void) -+{ -+ int i; -+ -+ printk(KERN_INFO "Stopping all CPUs..."); -+ for(i = 0; i < ncpus; i++){ -+ if(i == current->processor) -+ continue; -+ os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); -+ } -+ printk("done\n"); -+} -+ -+ -+static atomic_t smp_commenced = ATOMIC_INIT(0); -+static volatile unsigned long smp_callin_map = 0; -+ -+void smp_commence(void) -+{ -+ printk("All CPUs are go!\n"); -+ -+ wmb(); -+ atomic_set(&smp_commenced, 1); -+} -+ -+static int idle_proc(void *unused) -+{ -+ int cpu, err; -+ -+ set_current(current); -+ del_from_runqueue(current); -+ unhash_process(current); -+ -+ cpu = current->processor; -+ err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); -+ if(err < 0) -+ panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); -+ -+ activate_ipi(cpu_data[cpu].ipi_pipe[0], -+ current->thread.mode.tt.extern_pid); -+ -+ wmb(); -+ if (test_and_set_bit(current->processor, &smp_callin_map)) { -+ printk("huh, CPU#%d already present??\n", current->processor); -+ BUG(); -+ } -+ -+ while (!atomic_read(&smp_commenced)) -+ cpu_relax(); -+ -+ init_idle(); -+ cpu_idle(); -+ return(0); -+} -+ -+static int idle_thread(int (*fn)(void *), int cpu) -+{ -+ struct task_struct *new_task; -+ int pid; -+ unsigned char c; -+ -+ current->thread.request.u.thread.proc = fn; -+ current->thread.request.u.thread.arg = NULL; -+ pid = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0); -+ if(pid < 0) -+ panic("do_fork failed in idle_thread"); -+ new_task = get_task(pid, 1); -+ -+ cpu_tasks[cpu] = ((struct cpu_task) -+ { .pid = new_task->thread.mode.tt.extern_pid, -+ .task = new_task } ); -+ init_tasks[cpu] = new_task; -+ new_task->processor = cpu; -+ new_task->cpus_allowed = 1 << cpu; -+ new_task->cpus_runnable = new_task->cpus_allowed; -+ CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, -+ sizeof(c)), -+ ({ panic("skas mode doesn't support SMP"); })); -+ return(new_task->thread.mode.tt.extern_pid); -+} -+ -+void smp_boot_cpus(void) -+{ -+ int err; -+ -+ set_bit(0, &cpu_online_map); -+ set_bit(0, &smp_callin_map); -+ -+ err = os_pipe(cpu_data[0].ipi_pipe, 1, 1); -+ if(err < 0) -+ panic("CPU#0 failed to create IPI pipe, err = %d", -err); -+ -+ activate_ipi(cpu_data[0].ipi_pipe[0], -+ current->thread.mode.tt.extern_pid); -+ -+ if(ncpus < 1){ -+ printk(KERN_INFO "ncpus set to 1\n"); -+ ncpus = 1; -+ } -+ else if(ncpus > NR_CPUS){ -+ printk(KERN_INFO -+ "ncpus can't be greater than NR_CPUS, set to %d\n", -+ NR_CPUS); -+ ncpus = NR_CPUS; -+ } -+ -+ if(ncpus > 1){ -+ int i, pid; -+ -+ printk(KERN_INFO "Starting up other processors:\n"); -+ for(i=1;i<ncpus;i++){ -+ int waittime; -+ -+ /* Do this early, for hard_smp_processor_id() */ -+ cpu_tasks[i].pid = -1; -+ set_bit(i, &cpu_online_map); -+ smp_num_cpus++; -+ -+ pid = idle_thread(idle_proc, i); -+ printk(KERN_INFO "\t#%d - idle thread pid = %d.. ", -+ i, pid); -+ -+ waittime = 200000000; -+ while (waittime-- && !test_bit(i, &smp_callin_map)) -+ cpu_relax(); -+ -+ if (test_bit(i, &smp_callin_map)) -+ printk("online\n"); -+ else { -+ printk("failed\n"); -+ clear_bit(i, &cpu_online_map); -+ } -+ } -+ } -+} -+ -+int setup_profiling_timer(unsigned int multiplier) -+{ -+ printk(KERN_INFO "setup_profiling_timer\n"); -+ return(0); -+} -+ -+void smp_call_function_slave(int cpu); -+ -+void IPI_handler(int cpu) -+{ -+ unsigned char c; -+ int fd; -+ -+ fd = cpu_data[cpu].ipi_pipe[0]; -+ while (os_read_file(fd, &c, 1) == 1) { -+ switch (c) { -+ case 'C': -+ smp_call_function_slave(cpu); -+ break; -+ -+ case 'R': -+ current->need_resched = 1; -+ break; -+ -+ case 'S': -+ printk("CPU#%d stopping\n", cpu); -+ while(1) -+ pause(); -+ break; -+ -+ default: -+ printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); -+ break; -+ } -+ } -+} -+ -+int hard_smp_processor_id(void) -+{ -+ return(pid_to_processor_id(os_getpid())); -+} -+ -+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; -+static atomic_t scf_started; -+static atomic_t scf_finished; -+static void (*func)(void *info); -+static void *info; -+ -+void smp_call_function_slave(int cpu) -+{ -+ atomic_inc(&scf_started); -+ (*func)(info); -+ atomic_inc(&scf_finished); -+} -+ -+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, -+ int wait) -+{ -+ int cpus = smp_num_cpus - 1; -+ int i; -+ -+ if (!cpus) -+ return 0; -+ -+ spin_lock_bh(&call_lock); -+ atomic_set(&scf_started, 0); -+ atomic_set(&scf_finished, 0); -+ func = _func; -+ info = _info; -+ -+ for (i=0;i<NR_CPUS;i++) -+ if (i != current->processor && test_bit(i, &cpu_online_map)) -+ os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); -+ -+ while (atomic_read(&scf_started) != cpus) -+ barrier(); -+ -+ if (wait) -+ while (atomic_read(&scf_finished) != cpus) -+ barrier(); -+ -+ spin_unlock_bh(&call_lock); -+ return 0; -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/syscall_kern.c um/arch/um/kernel/syscall_kern.c ---- orig/arch/um/kernel/syscall_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/syscall_kern.c 2004-01-10 06:37:46.000000000 -0500 -@@ -0,0 +1,343 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/file.h" -+#include "linux/smp_lock.h" -+#include "linux/mm.h" -+#include "linux/utsname.h" -+#include "linux/msg.h" -+#include "linux/shm.h" -+#include "linux/sys.h" -+#include "linux/unistd.h" -+#include "linux/slab.h" -+#include "linux/utime.h" -+#include "asm/mman.h" -+#include "asm/uaccess.h" -+#include "asm/ipc.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "sysdep/syscalls.h" -+#include "mode_kern.h" -+#include "choose-mode.h" -+ -+/* Unlocked, I don't care if this is a bit off */ -+int nsyscalls = 0; -+ -+long um_mount(char * dev_name, char * dir_name, char * type, -+ unsigned long new_flags, void * data) -+{ -+ if(type == NULL) type = ""; -+ return(sys_mount(dev_name, dir_name, type, new_flags, data)); -+} -+ -+long sys_fork(void) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(SIGCHLD, 0, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+long sys_clone(unsigned long clone_flags, unsigned long newsp) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(clone_flags, newsp, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+long sys_vfork(void) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+/* common code for old and new mmaps */ -+long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, unsigned long fd, -+ unsigned long pgoff) -+{ -+ int error = -EBADF; -+ struct file * file = NULL; -+ -+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); -+ if (!(flags & MAP_ANONYMOUS)) { -+ file = fget(fd); -+ if (!file) -+ goto out; -+ } -+ -+ down_write(&mm->mmap_sem); -+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); -+ up_write(&mm->mmap_sem); -+ -+ if (file) -+ fput(file); -+ out: -+ return error; -+} -+ -+long sys_mmap2(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long pgoff) -+{ -+ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); -+} -+ -+/* -+ * Perform the select(nd, in, out, ex, tv) and mmap() system -+ * calls. Linux/i386 didn't use to be able to handle more than -+ * 4 system call parameters, so these system calls used a memory -+ * block for parameter passing.. -+ */ -+ -+struct mmap_arg_struct { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset) -+{ -+ int err = -EINVAL; -+ if (offset & ~PAGE_MASK) -+ goto out; -+ -+ err = do_mmap2(current->mm, addr, len, prot, flags, fd, -+ offset >> PAGE_SHIFT); -+ out: -+ return err; -+} -+/* -+ * sys_pipe() is the normal C calling standard for creating -+ * a pipe. It's not the way unix traditionally does this, though. -+ */ -+int sys_pipe(unsigned long * fildes) -+{ -+ int fd[2]; -+ int error; -+ -+ error = do_pipe(fd); -+ if (!error) { -+ if (copy_to_user(fildes, fd, sizeof(fd))) -+ error = -EFAULT; -+ } -+ return error; -+} -+ -+int sys_pause(void) -+{ -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ return -ERESTARTNOHAND; -+} -+ -+int sys_sigaction(int sig, const struct old_sigaction *act, -+ struct old_sigaction *oact) -+{ -+ struct k_sigaction new_ka, old_ka; -+ int ret; -+ -+ if (act) { -+ old_sigset_t mask; -+ if (verify_area(VERIFY_READ, act, sizeof(*act)) || -+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) || -+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) -+ return -EFAULT; -+ __get_user(new_ka.sa.sa_flags, &act->sa_flags); -+ __get_user(mask, &act->sa_mask); -+ siginitset(&new_ka.sa.sa_mask, mask); -+ } -+ -+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); -+ -+ if (!ret && oact) { -+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || -+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || -+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) -+ return -EFAULT; -+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags); -+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); -+ } -+ -+ return ret; -+} -+ -+/* -+ * sys_ipc() is the de-multiplexer for the SysV IPC calls.. -+ * -+ * This is really horribly ugly. -+ */ -+int sys_ipc (uint call, int first, int second, -+ int third, void *ptr, long fifth) -+{ -+ int version, ret; -+ -+ version = call >> 16; /* hack for backward compatibility */ -+ call &= 0xffff; -+ -+ switch (call) { -+ case SEMOP: -+ return sys_semop (first, (struct sembuf *)ptr, second); -+ case SEMGET: -+ return sys_semget (first, second, third); -+ case SEMCTL: { -+ union semun fourth; -+ if (!ptr) -+ return -EINVAL; -+ if (get_user(fourth.__pad, (void **) ptr)) -+ return -EFAULT; -+ return sys_semctl (first, second, third, fourth); -+ } -+ -+ case MSGSND: -+ return sys_msgsnd (first, (struct msgbuf *) ptr, -+ second, third); -+ case MSGRCV: -+ switch (version) { -+ case 0: { -+ struct ipc_kludge tmp; -+ if (!ptr) -+ return -EINVAL; -+ -+ if (copy_from_user(&tmp, -+ (struct ipc_kludge *) ptr, -+ sizeof (tmp))) -+ return -EFAULT; -+ return sys_msgrcv (first, tmp.msgp, second, -+ tmp.msgtyp, third); -+ } -+ default: -+ panic("msgrcv with version != 0"); -+ return sys_msgrcv (first, -+ (struct msgbuf *) ptr, -+ second, fifth, third); -+ } -+ case MSGGET: -+ return sys_msgget ((key_t) first, second); -+ case MSGCTL: -+ return sys_msgctl (first, second, (struct msqid_ds *) ptr); -+ -+ case SHMAT: -+ switch (version) { -+ default: { -+ ulong raddr; -+ ret = sys_shmat (first, (char *) ptr, second, &raddr); -+ if (ret) -+ return ret; -+ return put_user (raddr, (ulong *) third); -+ } -+ case 1: /* iBCS2 emulator entry point */ -+ if (!segment_eq(get_fs(), get_ds())) -+ return -EINVAL; -+ return sys_shmat (first, (char *) ptr, second, (ulong *) third); -+ } -+ case SHMDT: -+ return sys_shmdt ((char *)ptr); -+ case SHMGET: -+ return sys_shmget (first, second, third); -+ case SHMCTL: -+ return sys_shmctl (first, second, -+ (struct shmid_ds *) ptr); -+ default: -+ return -EINVAL; -+ } -+} -+ -+int sys_uname(struct old_utsname * name) -+{ -+ int err; -+ if (!name) -+ return -EFAULT; -+ down_read(&uts_sem); -+ err=copy_to_user(name, &system_utsname, sizeof (*name)); -+ up_read(&uts_sem); -+ return err?-EFAULT:0; -+} -+ -+int sys_olduname(struct oldold_utsname * name) -+{ -+ int error; -+ -+ if (!name) -+ return -EFAULT; -+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) -+ return -EFAULT; -+ -+ down_read(&uts_sem); -+ -+ error = __copy_to_user(&name->sysname,&system_utsname.sysname, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->release,&system_utsname.release, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->release+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->version,&system_utsname.version, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->version+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->machine,&system_utsname.machine, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->machine+__OLD_UTS_LEN); -+ -+ up_read(&uts_sem); -+ -+ error = error ? -EFAULT : 0; -+ -+ return error; -+} -+ -+int sys_sigaltstack(const stack_t *uss, stack_t *uoss) -+{ -+ return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); -+} -+ -+long execute_syscall(void *r) -+{ -+ return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r)); -+} -+ -+spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED; -+ -+static int syscall_index = 0; -+ -+int next_syscall_index(int limit) -+{ -+ int ret; -+ -+ spin_lock(&syscall_lock); -+ ret = syscall_index; -+ if(++syscall_index == limit) -+ syscall_index = 0; -+ spin_unlock(&syscall_lock); -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/sys_call_table.c um/arch/um/kernel/sys_call_table.c ---- orig/arch/um/kernel/sys_call_table.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/sys_call_table.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,496 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/unistd.h" -+#include "linux/version.h" -+#include "linux/sys.h" -+#include "asm/signal.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_exit; -+extern syscall_handler_t sys_fork; -+extern syscall_handler_t sys_creat; -+extern syscall_handler_t sys_link; -+extern syscall_handler_t sys_unlink; -+extern syscall_handler_t sys_chdir; -+extern syscall_handler_t sys_mknod; -+extern syscall_handler_t sys_chmod; -+extern syscall_handler_t sys_lchown16; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_stat; -+extern syscall_handler_t sys_getpid; -+extern syscall_handler_t sys_oldumount; -+extern syscall_handler_t sys_setuid16; -+extern syscall_handler_t sys_getuid16; -+extern syscall_handler_t sys_ptrace; -+extern syscall_handler_t sys_alarm; -+extern syscall_handler_t sys_fstat; -+extern syscall_handler_t sys_pause; -+extern syscall_handler_t sys_utime; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_access; -+extern syscall_handler_t sys_nice; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_sync; -+extern syscall_handler_t sys_kill; -+extern syscall_handler_t sys_rename; -+extern syscall_handler_t sys_mkdir; -+extern syscall_handler_t sys_rmdir; -+extern syscall_handler_t sys_pipe; -+extern syscall_handler_t sys_times; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_brk; -+extern syscall_handler_t sys_setgid16; -+extern syscall_handler_t sys_getgid16; -+extern syscall_handler_t sys_signal; -+extern syscall_handler_t sys_geteuid16; -+extern syscall_handler_t sys_getegid16; -+extern syscall_handler_t sys_acct; -+extern syscall_handler_t sys_umount; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ioctl; -+extern syscall_handler_t sys_fcntl; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_setpgid; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_olduname; -+extern syscall_handler_t sys_umask; -+extern syscall_handler_t sys_chroot; -+extern syscall_handler_t sys_ustat; -+extern syscall_handler_t sys_dup2; -+extern syscall_handler_t sys_getppid; -+extern syscall_handler_t sys_getpgrp; -+extern syscall_handler_t sys_sigaction; -+extern syscall_handler_t sys_sgetmask; -+extern syscall_handler_t sys_ssetmask; -+extern syscall_handler_t sys_setreuid16; -+extern syscall_handler_t sys_setregid16; -+extern syscall_handler_t sys_sigsuspend; -+extern syscall_handler_t sys_sigpending; -+extern syscall_handler_t sys_sethostname; -+extern syscall_handler_t sys_setrlimit; -+extern syscall_handler_t sys_old_getrlimit; -+extern syscall_handler_t sys_getrusage; -+extern syscall_handler_t sys_gettimeofday; -+extern syscall_handler_t sys_settimeofday; -+extern syscall_handler_t sys_getgroups16; -+extern syscall_handler_t sys_setgroups16; -+extern syscall_handler_t sys_symlink; -+extern syscall_handler_t sys_lstat; -+extern syscall_handler_t sys_readlink; -+extern syscall_handler_t sys_uselib; -+extern syscall_handler_t sys_swapon; -+extern syscall_handler_t sys_reboot; -+extern syscall_handler_t old_readdir; -+extern syscall_handler_t sys_munmap; -+extern syscall_handler_t sys_truncate; -+extern syscall_handler_t sys_ftruncate; -+extern syscall_handler_t sys_fchmod; -+extern syscall_handler_t sys_fchown16; -+extern syscall_handler_t sys_getpriority; -+extern syscall_handler_t sys_setpriority; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_statfs; -+extern syscall_handler_t sys_fstatfs; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_socketcall; -+extern syscall_handler_t sys_syslog; -+extern syscall_handler_t sys_setitimer; -+extern syscall_handler_t sys_getitimer; -+extern syscall_handler_t sys_newstat; -+extern syscall_handler_t sys_newlstat; -+extern syscall_handler_t sys_newfstat; -+extern syscall_handler_t sys_uname; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_vhangup; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_swapoff; -+extern syscall_handler_t sys_sysinfo; -+extern syscall_handler_t sys_ipc; -+extern syscall_handler_t sys_fsync; -+extern syscall_handler_t sys_sigreturn; -+extern syscall_handler_t sys_rt_sigreturn; -+extern syscall_handler_t sys_clone; -+extern syscall_handler_t sys_setdomainname; -+extern syscall_handler_t sys_newuname; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_adjtimex; -+extern syscall_handler_t sys_mprotect; -+extern syscall_handler_t sys_sigprocmask; -+extern syscall_handler_t sys_create_module; -+extern syscall_handler_t sys_init_module; -+extern syscall_handler_t sys_delete_module; -+extern syscall_handler_t sys_get_kernel_syms; -+extern syscall_handler_t sys_quotactl; -+extern syscall_handler_t sys_getpgid; -+extern syscall_handler_t sys_fchdir; -+extern syscall_handler_t sys_bdflush; -+extern syscall_handler_t sys_sysfs; -+extern syscall_handler_t sys_personality; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_setfsuid16; -+extern syscall_handler_t sys_setfsgid16; -+extern syscall_handler_t sys_llseek; -+extern syscall_handler_t sys_getdents; -+extern syscall_handler_t sys_flock; -+extern syscall_handler_t sys_msync; -+extern syscall_handler_t sys_readv; -+extern syscall_handler_t sys_writev; -+extern syscall_handler_t sys_getsid; -+extern syscall_handler_t sys_fdatasync; -+extern syscall_handler_t sys_sysctl; -+extern syscall_handler_t sys_mlock; -+extern syscall_handler_t sys_munlock; -+extern syscall_handler_t sys_mlockall; -+extern syscall_handler_t sys_munlockall; -+extern syscall_handler_t sys_sched_setparam; -+extern syscall_handler_t sys_sched_getparam; -+extern syscall_handler_t sys_sched_setscheduler; -+extern syscall_handler_t sys_sched_getscheduler; -+extern syscall_handler_t sys_sched_get_priority_max; -+extern syscall_handler_t sys_sched_get_priority_min; -+extern syscall_handler_t sys_sched_rr_get_interval; -+extern syscall_handler_t sys_nanosleep; -+extern syscall_handler_t sys_mremap; -+extern syscall_handler_t sys_setresuid16; -+extern syscall_handler_t sys_getresuid16; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_query_module; -+extern syscall_handler_t sys_poll; -+extern syscall_handler_t sys_nfsservctl; -+extern syscall_handler_t sys_setresgid16; -+extern syscall_handler_t sys_getresgid16; -+extern syscall_handler_t sys_prctl; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_rt_sigaction; -+extern syscall_handler_t sys_rt_sigprocmask; -+extern syscall_handler_t sys_rt_sigpending; -+extern syscall_handler_t sys_rt_sigtimedwait; -+extern syscall_handler_t sys_rt_sigqueueinfo; -+extern syscall_handler_t sys_rt_sigsuspend; -+extern syscall_handler_t sys_pread; -+extern syscall_handler_t sys_pwrite; -+extern syscall_handler_t sys_chown16; -+extern syscall_handler_t sys_getcwd; -+extern syscall_handler_t sys_capget; -+extern syscall_handler_t sys_capset; -+extern syscall_handler_t sys_sigaltstack; -+extern syscall_handler_t sys_sendfile; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_vfork; -+extern syscall_handler_t sys_getrlimit; -+extern syscall_handler_t sys_mmap2; -+extern syscall_handler_t sys_truncate64; -+extern syscall_handler_t sys_ftruncate64; -+extern syscall_handler_t sys_stat64; -+extern syscall_handler_t sys_lstat64; -+extern syscall_handler_t sys_fstat64; -+extern syscall_handler_t sys_lchown; -+extern syscall_handler_t sys_getuid; -+extern syscall_handler_t sys_getgid; -+extern syscall_handler_t sys_geteuid; -+extern syscall_handler_t sys_getegid; -+extern syscall_handler_t sys_setreuid; -+extern syscall_handler_t sys_setregid; -+extern syscall_handler_t sys_getgroups; -+extern syscall_handler_t sys_setgroups; -+extern syscall_handler_t sys_fchown; -+extern syscall_handler_t sys_setresuid; -+extern syscall_handler_t sys_getresuid; -+extern syscall_handler_t sys_setresgid; -+extern syscall_handler_t sys_getresgid; -+extern syscall_handler_t sys_chown; -+extern syscall_handler_t sys_setuid; -+extern syscall_handler_t sys_setgid; -+extern syscall_handler_t sys_setfsuid; -+extern syscall_handler_t sys_setfsgid; -+extern syscall_handler_t sys_pivot_root; -+extern syscall_handler_t sys_mincore; -+extern syscall_handler_t sys_madvise; -+extern syscall_handler_t sys_fcntl64; -+extern syscall_handler_t sys_getdents64; -+extern syscall_handler_t sys_gettid; -+extern syscall_handler_t sys_readahead; -+extern syscall_handler_t sys_tkill; -+extern syscall_handler_t sys_setxattr; -+extern syscall_handler_t sys_lsetxattr; -+extern syscall_handler_t sys_fsetxattr; -+extern syscall_handler_t sys_getxattr; -+extern syscall_handler_t sys_lgetxattr; -+extern syscall_handler_t sys_fgetxattr; -+extern syscall_handler_t sys_listxattr; -+extern syscall_handler_t sys_llistxattr; -+extern syscall_handler_t sys_flistxattr; -+extern syscall_handler_t sys_removexattr; -+extern syscall_handler_t sys_lremovexattr; -+extern syscall_handler_t sys_fremovexattr; -+extern syscall_handler_t sys_sendfile64; -+ -+extern syscall_handler_t um_mount; -+extern syscall_handler_t um_time; -+extern syscall_handler_t um_stime; -+ -+#define LAST_GENERIC_SYSCALL __NR_exit_group -+ -+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL -+#define LAST_SYSCALL LAST_GENERIC_SYSCALL -+#else -+#define LAST_SYSCALL LAST_ARCH_SYSCALL -+#endif -+ -+syscall_handler_t *sys_call_table[] = { -+ [ 0 ] = sys_ni_syscall, -+ [ __NR_exit ] = sys_exit, -+ [ __NR_fork ] = sys_fork, -+ [ __NR_read ] = (syscall_handler_t *) sys_read, -+ [ __NR_write ] = (syscall_handler_t *) sys_write, -+ -+ /* These three are declared differently in asm/unistd.h */ -+ [ __NR_open ] = (syscall_handler_t *) sys_open, -+ [ __NR_close ] = (syscall_handler_t *) sys_close, -+ [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, -+ [ __NR_creat ] = sys_creat, -+ [ __NR_link ] = sys_link, -+ [ __NR_unlink ] = sys_unlink, -+ -+ /* declared differently in kern_util.h */ -+ [ __NR_execve ] = (syscall_handler_t *) sys_execve, -+ [ __NR_chdir ] = sys_chdir, -+ [ __NR_time ] = um_time, -+ [ __NR_mknod ] = sys_mknod, -+ [ __NR_chmod ] = sys_chmod, -+ [ __NR_lchown ] = sys_lchown16, -+ [ __NR_break ] = sys_ni_syscall, -+ [ __NR_oldstat ] = sys_stat, -+ [ __NR_lseek ] = (syscall_handler_t *) sys_lseek, -+ [ __NR_getpid ] = sys_getpid, -+ [ __NR_mount ] = um_mount, -+ [ __NR_umount ] = sys_oldumount, -+ [ __NR_setuid ] = sys_setuid16, -+ [ __NR_getuid ] = sys_getuid16, -+ [ __NR_stime ] = um_stime, -+ [ __NR_ptrace ] = sys_ptrace, -+ [ __NR_alarm ] = sys_alarm, -+ [ __NR_oldfstat ] = sys_fstat, -+ [ __NR_pause ] = sys_pause, -+ [ __NR_utime ] = sys_utime, -+ [ __NR_stty ] = sys_ni_syscall, -+ [ __NR_gtty ] = sys_ni_syscall, -+ [ __NR_access ] = sys_access, -+ [ __NR_nice ] = sys_nice, -+ [ __NR_ftime ] = sys_ni_syscall, -+ [ __NR_sync ] = sys_sync, -+ [ __NR_kill ] = sys_kill, -+ [ __NR_rename ] = sys_rename, -+ [ __NR_mkdir ] = sys_mkdir, -+ [ __NR_rmdir ] = sys_rmdir, -+ -+ /* Declared differently in asm/unistd.h */ -+ [ __NR_dup ] = (syscall_handler_t *) sys_dup, -+ [ __NR_pipe ] = sys_pipe, -+ [ __NR_times ] = sys_times, -+ [ __NR_prof ] = sys_ni_syscall, -+ [ __NR_brk ] = sys_brk, -+ [ __NR_setgid ] = sys_setgid16, -+ [ __NR_getgid ] = sys_getgid16, -+ [ __NR_signal ] = sys_signal, -+ [ __NR_geteuid ] = sys_geteuid16, -+ [ __NR_getegid ] = sys_getegid16, -+ [ __NR_acct ] = sys_acct, -+ [ __NR_umount2 ] = sys_umount, -+ [ __NR_lock ] = sys_ni_syscall, -+ [ __NR_ioctl ] = sys_ioctl, -+ [ __NR_fcntl ] = sys_fcntl, -+ [ __NR_mpx ] = sys_ni_syscall, -+ [ __NR_setpgid ] = sys_setpgid, -+ [ __NR_ulimit ] = sys_ni_syscall, -+ [ __NR_oldolduname ] = sys_olduname, -+ [ __NR_umask ] = sys_umask, -+ [ __NR_chroot ] = sys_chroot, -+ [ __NR_ustat ] = sys_ustat, -+ [ __NR_dup2 ] = sys_dup2, -+ [ __NR_getppid ] = sys_getppid, -+ [ __NR_getpgrp ] = sys_getpgrp, -+ [ __NR_setsid ] = (syscall_handler_t *) sys_setsid, -+ [ __NR_sigaction ] = sys_sigaction, -+ [ __NR_sgetmask ] = sys_sgetmask, -+ [ __NR_ssetmask ] = sys_ssetmask, -+ [ __NR_setreuid ] = sys_setreuid16, -+ [ __NR_setregid ] = sys_setregid16, -+ [ __NR_sigsuspend ] = sys_sigsuspend, -+ [ __NR_sigpending ] = sys_sigpending, -+ [ __NR_sethostname ] = sys_sethostname, -+ [ __NR_setrlimit ] = sys_setrlimit, -+ [ __NR_getrlimit ] = sys_old_getrlimit, -+ [ __NR_getrusage ] = sys_getrusage, -+ [ __NR_gettimeofday ] = sys_gettimeofday, -+ [ __NR_settimeofday ] = sys_settimeofday, -+ [ __NR_getgroups ] = sys_getgroups16, -+ [ __NR_setgroups ] = sys_setgroups16, -+ [ __NR_symlink ] = sys_symlink, -+ [ __NR_oldlstat ] = sys_lstat, -+ [ __NR_readlink ] = sys_readlink, -+ [ __NR_uselib ] = sys_uselib, -+ [ __NR_swapon ] = sys_swapon, -+ [ __NR_reboot ] = sys_reboot, -+ [ __NR_readdir ] = old_readdir, -+ [ __NR_munmap ] = sys_munmap, -+ [ __NR_truncate ] = sys_truncate, -+ [ __NR_ftruncate ] = sys_ftruncate, -+ [ __NR_fchmod ] = sys_fchmod, -+ [ __NR_fchown ] = sys_fchown16, -+ [ __NR_getpriority ] = sys_getpriority, -+ [ __NR_setpriority ] = sys_setpriority, -+ [ __NR_profil ] = sys_ni_syscall, -+ [ __NR_statfs ] = sys_statfs, -+ [ __NR_fstatfs ] = sys_fstatfs, -+ [ __NR_ioperm ] = sys_ni_syscall, -+ [ __NR_socketcall ] = sys_socketcall, -+ [ __NR_syslog ] = sys_syslog, -+ [ __NR_setitimer ] = sys_setitimer, -+ [ __NR_getitimer ] = sys_getitimer, -+ [ __NR_stat ] = sys_newstat, -+ [ __NR_lstat ] = sys_newlstat, -+ [ __NR_fstat ] = sys_newfstat, -+ [ __NR_olduname ] = sys_uname, -+ [ __NR_iopl ] = sys_ni_syscall, -+ [ __NR_vhangup ] = sys_vhangup, -+ [ __NR_idle ] = sys_ni_syscall, -+ [ __NR_wait4 ] = (syscall_handler_t *) sys_wait4, -+ [ __NR_swapoff ] = sys_swapoff, -+ [ __NR_sysinfo ] = sys_sysinfo, -+ [ __NR_ipc ] = sys_ipc, -+ [ __NR_fsync ] = sys_fsync, -+ [ __NR_sigreturn ] = sys_sigreturn, -+ [ __NR_clone ] = sys_clone, -+ [ __NR_setdomainname ] = sys_setdomainname, -+ [ __NR_uname ] = sys_newuname, -+ [ __NR_adjtimex ] = sys_adjtimex, -+ [ __NR_mprotect ] = sys_mprotect, -+ [ __NR_sigprocmask ] = sys_sigprocmask, -+ [ __NR_create_module ] = sys_create_module, -+ [ __NR_init_module ] = sys_init_module, -+ [ __NR_delete_module ] = sys_delete_module, -+ [ __NR_get_kernel_syms ] = sys_get_kernel_syms, -+ [ __NR_quotactl ] = sys_quotactl, -+ [ __NR_getpgid ] = sys_getpgid, -+ [ __NR_fchdir ] = sys_fchdir, -+ [ __NR_bdflush ] = sys_bdflush, -+ [ __NR_sysfs ] = sys_sysfs, -+ [ __NR_personality ] = sys_personality, -+ [ __NR_afs_syscall ] = sys_ni_syscall, -+ [ __NR_setfsuid ] = sys_setfsuid16, -+ [ __NR_setfsgid ] = sys_setfsgid16, -+ [ __NR__llseek ] = sys_llseek, -+ [ __NR_getdents ] = sys_getdents, -+ [ __NR__newselect ] = (syscall_handler_t *) sys_select, -+ [ __NR_flock ] = sys_flock, -+ [ __NR_msync ] = sys_msync, -+ [ __NR_readv ] = sys_readv, -+ [ __NR_writev ] = sys_writev, -+ [ __NR_getsid ] = sys_getsid, -+ [ __NR_fdatasync ] = sys_fdatasync, -+ [ __NR__sysctl ] = sys_sysctl, -+ [ __NR_mlock ] = sys_mlock, -+ [ __NR_munlock ] = sys_munlock, -+ [ __NR_mlockall ] = sys_mlockall, -+ [ __NR_munlockall ] = sys_munlockall, -+ [ __NR_sched_setparam ] = sys_sched_setparam, -+ [ __NR_sched_getparam ] = sys_sched_getparam, -+ [ __NR_sched_setscheduler ] = sys_sched_setscheduler, -+ [ __NR_sched_getscheduler ] = sys_sched_getscheduler, -+ [ __NR_sched_yield ] = (syscall_handler_t *) yield, -+ [ __NR_sched_get_priority_max ] = sys_sched_get_priority_max, -+ [ __NR_sched_get_priority_min ] = sys_sched_get_priority_min, -+ [ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval, -+ [ __NR_nanosleep ] = sys_nanosleep, -+ [ __NR_mremap ] = sys_mremap, -+ [ __NR_setresuid ] = sys_setresuid16, -+ [ __NR_getresuid ] = sys_getresuid16, -+ [ __NR_vm86 ] = sys_ni_syscall, -+ [ __NR_query_module ] = sys_query_module, -+ [ __NR_poll ] = sys_poll, -+ [ __NR_nfsservctl ] = sys_nfsservctl, -+ [ __NR_setresgid ] = sys_setresgid16, -+ [ __NR_getresgid ] = sys_getresgid16, -+ [ __NR_prctl ] = sys_prctl, -+ [ __NR_rt_sigreturn ] = sys_rt_sigreturn, -+ [ __NR_rt_sigaction ] = sys_rt_sigaction, -+ [ __NR_rt_sigprocmask ] = sys_rt_sigprocmask, -+ [ __NR_rt_sigpending ] = sys_rt_sigpending, -+ [ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait, -+ [ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo, -+ [ __NR_rt_sigsuspend ] = sys_rt_sigsuspend, -+ [ __NR_pread ] = sys_pread, -+ [ __NR_pwrite ] = sys_pwrite, -+ [ __NR_chown ] = sys_chown16, -+ [ __NR_getcwd ] = sys_getcwd, -+ [ __NR_capget ] = sys_capget, -+ [ __NR_capset ] = sys_capset, -+ [ __NR_sigaltstack ] = sys_sigaltstack, -+ [ __NR_sendfile ] = sys_sendfile, -+ [ __NR_getpmsg ] = sys_ni_syscall, -+ [ __NR_putpmsg ] = sys_ni_syscall, -+ [ __NR_vfork ] = sys_vfork, -+ [ __NR_ugetrlimit ] = sys_getrlimit, -+ [ __NR_mmap2 ] = sys_mmap2, -+ [ __NR_truncate64 ] = sys_truncate64, -+ [ __NR_ftruncate64 ] = sys_ftruncate64, -+ [ __NR_stat64 ] = sys_stat64, -+ [ __NR_lstat64 ] = sys_lstat64, -+ [ __NR_fstat64 ] = sys_fstat64, -+ [ __NR_fcntl64 ] = sys_fcntl64, -+ [ __NR_getdents64 ] = sys_getdents64, -+ [ __NR_security ] = sys_ni_syscall, -+ [ __NR_gettid ] = sys_gettid, -+ [ __NR_readahead ] = sys_readahead, -+ [ __NR_setxattr ] = sys_setxattr, -+ [ __NR_lsetxattr ] = sys_lsetxattr, -+ [ __NR_fsetxattr ] = sys_fsetxattr, -+ [ __NR_getxattr ] = sys_getxattr, -+ [ __NR_lgetxattr ] = sys_lgetxattr, -+ [ __NR_fgetxattr ] = sys_fgetxattr, -+ [ __NR_listxattr ] = sys_listxattr, -+ [ __NR_llistxattr ] = sys_llistxattr, -+ [ __NR_flistxattr ] = sys_flistxattr, -+ [ __NR_removexattr ] = sys_removexattr, -+ [ __NR_lremovexattr ] = sys_lremovexattr, -+ [ __NR_fremovexattr ] = sys_fremovexattr, -+ [ __NR_tkill ] = sys_tkill, -+ [ __NR_sendfile64 ] = sys_sendfile64, -+ [ __NR_futex ] = sys_ni_syscall, -+ [ __NR_sched_setaffinity ] = sys_ni_syscall, -+ [ __NR_sched_getaffinity ] = sys_ni_syscall, -+ [ __NR_set_thread_area ] = sys_ni_syscall, -+ [ __NR_get_thread_area ] = sys_ni_syscall, -+ [ __NR_io_setup ] = sys_ni_syscall, -+ [ __NR_io_destroy ] = sys_ni_syscall, -+ [ __NR_io_getevents ] = sys_ni_syscall, -+ [ __NR_io_submit ] = sys_ni_syscall, -+ [ __NR_io_cancel ] = sys_ni_syscall, -+ [ __NR_alloc_hugepages ] = sys_ni_syscall, -+ [ __NR_free_hugepages ] = sys_ni_syscall, -+ [ __NR_exit_group ] = sys_ni_syscall, -+ -+ ARCH_SYSCALLS -+ [ LAST_SYSCALL + 1 ... NR_syscalls ] = -+ (syscall_handler_t *) sys_ni_syscall -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/syscall_user.c um/arch/um/kernel/syscall_user.c ---- orig/arch/um/kernel/syscall_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/syscall_user.c 2003-12-22 01:32:48.000000000 -0500 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <sys/time.h> -+#include "kern_util.h" -+#include "syscall_user.h" -+ -+struct { -+ int syscall; -+ int pid; -+ int result; -+ struct timeval start; -+ struct timeval end; -+} syscall_record[1024]; -+ -+int record_syscall_start(int syscall) -+{ -+ int max, index; -+ -+ max = sizeof(syscall_record)/sizeof(syscall_record[0]); -+ index = next_syscall_index(max); -+ -+ syscall_record[index].syscall = syscall; -+ syscall_record[index].pid = current_pid(); -+ syscall_record[index].result = 0xdeadbeef; -+ gettimeofday(&syscall_record[index].start, NULL); -+ return(index); -+} -+ -+void record_syscall_end(int index, int result) -+{ -+ syscall_record[index].result = result; -+ gettimeofday(&syscall_record[index].end, NULL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/sysrq.c um/arch/um/kernel/sysrq.c ---- orig/arch/um/kernel/sysrq.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/sysrq.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/kernel.h" -+#include "linux/module.h" -+#include "asm/page.h" -+#include "asm/processor.h" -+#include "sysrq.h" -+#include "user_util.h" -+ -+ /* -+ * If the address is either in the .text section of the -+ * kernel, or in the vmalloc'ed module regions, it *may* -+ * be the address of a calling routine -+ */ -+ -+#ifdef CONFIG_MODULES -+ -+extern struct module *module_list; -+extern struct module kernel_module; -+ -+static inline int kernel_text_address(unsigned long addr) -+{ -+ int retval = 0; -+ struct module *mod; -+ -+ if (addr >= (unsigned long) &_stext && -+ addr <= (unsigned long) &_etext) -+ return 1; -+ -+ for (mod = module_list; mod != &kernel_module; mod = mod->next) { -+ /* mod_bound tests for addr being inside the vmalloc'ed -+ * module area. Of course it'd be better to test only -+ * for the .text subset... */ -+ if (mod_bound(addr, 0, mod)) { -+ retval = 1; -+ break; -+ } -+ } -+ -+ return retval; -+} -+ -+#else -+ -+static inline int kernel_text_address(unsigned long addr) -+{ -+ return (addr >= (unsigned long) &_stext && -+ addr <= (unsigned long) &_etext); -+} -+ -+#endif -+ -+void show_trace(unsigned long * stack) -+{ -+ int i; -+ unsigned long addr; -+ -+ if (!stack) -+ stack = (unsigned long*) &stack; -+ -+ printk("Call Trace: "); -+ i = 1; -+ while (((long) stack & (THREAD_SIZE-1)) != 0) { -+ addr = *stack++; -+ if (kernel_text_address(addr)) { -+ if (i && ((i % 6) == 0)) -+ printk("\n "); -+ printk("[<%08lx>] ", addr); -+ i++; -+ } -+ } -+ printk("\n"); -+} -+ -+void show_trace_task(struct task_struct *tsk) -+{ -+ unsigned long esp = PT_REGS_SP(&tsk->thread.regs); -+ -+ /* User space on another CPU? */ -+ if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ return; -+ show_trace((unsigned long *)esp); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tempfile.c um/arch/um/kernel/tempfile.c ---- orig/arch/um/kernel/tempfile.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tempfile.c 2003-12-22 01:33:38.000000000 -0500 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/param.h> -+#include "init.h" -+ -+/* Modified from create_mem_file and start_debugger */ -+static char *tempdir = NULL; -+ -+static void __init find_tempdir(void) -+{ -+ char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; -+ int i; -+ char *dir = NULL; -+ -+ if(tempdir != NULL) return; /* We've already been called */ -+ for(i = 0; dirs[i]; i++){ -+ dir = getenv(dirs[i]); -+ if((dir != NULL) && (*dir != '\0')) -+ break; -+ } -+ if((dir == NULL) || (*dir == '\0')) -+ dir = "/tmp"; -+ -+ tempdir = malloc(strlen(dir) + 2); -+ if(tempdir == NULL){ -+ fprintf(stderr, "Failed to malloc tempdir, " -+ "errno = %d\n", errno); -+ return; -+ } -+ strcpy(tempdir, dir); -+ strcat(tempdir, "/"); -+} -+ -+int make_tempfile(const char *template, char **out_tempname, int do_unlink) -+{ -+ char tempname[MAXPATHLEN]; -+ int fd; -+ -+ find_tempdir(); -+ if (*template != '/') -+ strcpy(tempname, tempdir); -+ else -+ *tempname = 0; -+ strcat(tempname, template); -+ fd = mkstemp(tempname); -+ if(fd < 0){ -+ fprintf(stderr, "open - cannot create %s: %s\n", tempname, -+ strerror(errno)); -+ return -1; -+ } -+ if(do_unlink && (unlink(tempname) < 0)){ -+ perror("unlink"); -+ return -1; -+ } -+ if(out_tempname){ -+ *out_tempname = strdup(tempname); -+ if(*out_tempname == NULL){ -+ perror("strdup"); -+ return -1; -+ } -+ } -+ return(fd); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/time.c um/arch/um/kernel/time.c ---- orig/arch/um/kernel/time.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/time.c 2004-02-12 07:09:48.000000000 -0500 -@@ -0,0 +1,172 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <time.h> -+#include <sys/time.h> -+#include <signal.h> -+#include <errno.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_user.h" -+#include "time_user.h" -+ -+extern struct timeval xtime; -+ -+struct timeval local_offset = { 0, 0 }; -+ -+void timer(void) -+{ -+ gettimeofday(&xtime, NULL); -+ timeradd(&xtime, &local_offset, &xtime); -+} -+ -+void set_interval(int timer_type) -+{ -+ int usec = 1000000/hz(); -+ struct itimerval interval = ((struct itimerval) { { 0, usec }, -+ { 0, usec } }); -+ -+ if(setitimer(timer_type, &interval, NULL) == -1) -+ panic("setitimer failed - errno = %d\n", errno); -+} -+ -+void enable_timer(void) -+{ -+ int usec = 1000000/hz(); -+ struct itimerval enable = ((struct itimerval) { { 0, usec }, -+ { 0, usec }}); -+ if(setitimer(ITIMER_VIRTUAL, &enable, NULL)) -+ printk("enable_timer - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void switch_timers(int to_real) -+{ -+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); -+ struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, -+ { 0, 1000000/hz() }}); -+ int old, new; -+ -+ if(to_real){ -+ old = ITIMER_VIRTUAL; -+ new = ITIMER_REAL; -+ } -+ else { -+ old = ITIMER_REAL; -+ new = ITIMER_VIRTUAL; -+ } -+ -+ if((setitimer(old, &disable, NULL) < 0) || -+ (setitimer(new, &enable, NULL))) -+ printk("switch_timers - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void idle_timer(void) -+{ -+ if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) -+ panic("Couldn't unset SIGVTALRM handler"); -+ -+ set_handler(SIGALRM, (__sighandler_t) alarm_handler, -+ SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); -+ set_interval(ITIMER_REAL); -+} -+ -+static unsigned long long get_host_hz(void) -+{ -+ char mhzline[16], *end; -+ unsigned long long mhz; -+ int ret, mult, rest, len; -+ -+ ret = cpu_feature("cpu MHz", mhzline, -+ sizeof(mhzline) / sizeof(mhzline[0])); -+ if(!ret) -+ panic ("Could not get host MHZ"); -+ -+ mhz = strtoul(mhzline, &end, 10); -+ -+ /* This business is to parse a floating point number without using -+ * floating types. -+ */ -+ -+ rest = 0; -+ mult = 0; -+ if(*end == '.'){ -+ end++; -+ len = strlen(end); -+ if(len < 6) -+ mult = 6 - len; -+ else if(len > 6) -+ end[6] = '\0'; -+ rest = strtoul(end, NULL, 10); -+ while(mult-- > 0) -+ rest *= 10; -+ } -+ -+ return(1000000 * mhz + rest); -+} -+ -+unsigned long long host_hz = 0; -+ -+void time_init(void) -+{ -+ /* XXX This is to fill xtime with something real - otherwise by the -+ * time /proc is mounted, no timers have fired, and xtime is still 0, -+ * meaning it shows times of Jan 1 1970. The real fix is to figure -+ * out why no timers have happened by then. -+ */ -+ timer(); -+ -+ host_hz = get_host_hz(); -+ if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+void do_gettimeofday(struct timeval *tv) -+{ -+ unsigned long flags; -+ -+ flags = time_lock(); -+ gettimeofday(tv, NULL); -+ timeradd(tv, &local_offset, tv); -+ time_unlock(flags); -+} -+ -+void do_settimeofday(struct timeval *tv) -+{ -+ struct timeval now; -+ unsigned long flags; -+ -+ flags = time_lock(); -+ gettimeofday(&now, NULL); -+ timersub(tv, &now, &local_offset); -+ time_unlock(flags); -+} -+ -+void idle_sleep(int secs) -+{ -+ struct timespec ts; -+ -+ ts.tv_sec = secs; -+ ts.tv_nsec = 0; -+ nanosleep(&ts, NULL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/time_kern.c um/arch/um/kernel/time_kern.c ---- orig/arch/um/kernel/time_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/time_kern.c 2004-02-14 06:51:31.000000000 -0500 -@@ -0,0 +1,205 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/unistd.h" -+#include "linux/stddef.h" -+#include "linux/spinlock.h" -+#include "linux/sched.h" -+#include "linux/interrupt.h" -+#include "linux/init.h" -+#include "linux/delay.h" -+#include "asm/irq.h" -+#include "asm/param.h" -+#include "asm/current.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "time_user.h" -+#include "mode.h" -+ -+extern rwlock_t xtime_lock; -+ -+int hz(void) -+{ -+ return(HZ); -+} -+ -+/* Changed at early boot */ -+int timer_irq_inited = 0; -+ -+/* missed_ticks will be modified after kernel memory has been -+ * write-protected, so this puts it in a section which will be left -+ * write-enabled. -+ */ -+int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS]; -+ -+static int first_tick; -+static unsigned long long prev_tsc; -+static long long delta; /* Deviation per interval */ -+ -+extern unsigned long long host_hz; -+ -+void timer_irq(union uml_pt_regs *regs) -+{ -+ unsigned long long ticks = 0; -+ -+ if(!timer_irq_inited){ -+ /* This is to ensure that ticks don't pile up when -+ * the timer handler is suspended */ -+ first_tick = 0; -+ return; -+ } -+ -+ if(first_tick){ -+#if defined(CONFIG_UML_REAL_TIME_CLOCK) -+ unsigned long long tsc; -+ /* We've had 1 tick */ -+ tsc = time_stamp(); -+ -+ delta += tsc - prev_tsc; -+ prev_tsc = tsc; -+ -+ ticks += (delta * HZ) / host_hz; -+ delta -= (ticks * host_hz) / HZ; -+#else -+ ticks = 1; -+#endif -+ } -+ else { -+ prev_tsc = time_stamp(); -+ first_tick = 1; -+ } -+ -+ while(ticks > 0){ -+ do_IRQ(TIMER_IRQ, regs); -+ ticks--; -+ } -+} -+ -+void boot_timer_handler(int sig) -+{ -+ struct pt_regs regs; -+ -+ CHOOSE_MODE((void) -+ (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), -+ (void) (regs.regs.skas.is_user = 0)); -+ do_timer(®s); -+} -+ -+void um_timer(int irq, void *dev, struct pt_regs *regs) -+{ -+ do_timer(regs); -+ write_lock(&xtime_lock); -+ vxtime_lock(); -+ timer(); -+ vxtime_unlock(); -+ write_unlock(&xtime_lock); -+} -+ -+long um_time(int * tloc) -+{ -+ struct timeval now; -+ -+ do_gettimeofday(&now); -+ if (tloc) { -+ if (put_user(now.tv_sec,tloc)) -+ now.tv_sec = -EFAULT; -+ } -+ return now.tv_sec; -+} -+ -+long um_stime(int * tptr) -+{ -+ int value; -+ struct timeval new; -+ -+ if (get_user(value, tptr)) -+ return -EFAULT; -+ new.tv_sec = value; -+ new.tv_usec = 0; -+ do_settimeofday(&new); -+ return 0; -+} -+ -+/* XXX Needs to be moved under sys-i386 */ -+void __delay(um_udelay_t time) -+{ -+ /* Stolen from the i386 __loop_delay */ -+ int d0; -+ __asm__ __volatile__( -+ "\tjmp 1f\n" -+ ".align 16\n" -+ "1:\tjmp 2f\n" -+ ".align 16\n" -+ "2:\tdecl %0\n\tjns 2b" -+ :"=&a" (d0) -+ :"0" (time)); -+} -+ -+void __udelay(um_udelay_t usecs) -+{ -+ int i, n; -+ -+ n = (loops_per_jiffy * HZ * usecs) / 1000000; -+ for(i=0;i<n;i++) ; -+} -+ -+void __const_udelay(um_udelay_t usecs) -+{ -+ int i, n; -+ -+ n = (loops_per_jiffy * HZ * usecs) / 1000000; -+ for(i=0;i<n;i++) ; -+} -+ -+void timer_handler(int sig, union uml_pt_regs *regs) -+{ -+#ifdef CONFIG_SMP -+ update_process_times(user_context(UPT_SP(regs))); -+#endif -+ if(current->processor == 0) -+ timer_irq(regs); -+} -+ -+static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED; -+ -+unsigned long time_lock(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&timer_spinlock, flags); -+ return(flags); -+} -+ -+void time_unlock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&timer_spinlock, flags); -+} -+ -+int __init timer_init(void) -+{ -+ int err; -+ -+ CHOOSE_MODE(user_time_init_tt(), user_time_init_skas()); -+ err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL); -+ if(err != 0) -+ printk(KERN_ERR "timer_init : request_irq failed - " -+ "errno = %d\n", -err); -+ timer_irq_inited = 1; -+ return(0); -+} -+ -+__initcall(timer_init); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tlb.c um/arch/um/kernel/tlb.c ---- orig/arch/um/kernel/tlb.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tlb.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/mm.h" -+#include "asm/page.h" -+#include "asm/pgalloc.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+ -+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) -+{ -+ address &= PAGE_MASK; -+ flush_tlb_range(vma->vm_mm, address, address + PAGE_SIZE); -+} -+ -+void flush_tlb_all(void) -+{ -+ flush_tlb_mm(current->mm); -+} -+ -+void flush_tlb_kernel_vm(void) -+{ -+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas()); -+} -+ -+void __flush_tlb_one(unsigned long addr) -+{ -+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); -+} -+ -+void flush_tlb_range(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, mm, start, -+ end); -+} -+ -+void flush_tlb_mm(struct mm_struct *mm) -+{ -+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); -+} -+ -+void force_flush_all(void) -+{ -+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); -+} -+ -+ -+pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) -+{ -+ return(pgd_offset(mm, address)); -+} -+ -+pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) -+{ -+ return(pmd_offset(pgd, address)); -+} -+ -+pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) -+{ -+ return(pte_offset(pmd, address)); -+} -+ -+pte_t *addr_pte(struct task_struct *task, unsigned long addr) -+{ -+ return(pte_offset(pmd_offset(pgd_offset(task->mm, addr), addr), addr)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/trap_kern.c um/arch/um/kernel/trap_kern.c ---- orig/arch/um/kernel/trap_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/trap_kern.c 2003-12-22 22:48:41.000000000 -0500 -@@ -0,0 +1,220 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/mm.h" -+#include "linux/spinlock.h" -+#include "linux/config.h" -+#include "linux/init.h" -+#include "asm/semaphore.h" -+#include "asm/pgtable.h" -+#include "asm/pgalloc.h" -+#include "asm/a.out.h" -+#include "asm/current.h" -+#include "asm/irq.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "chan_kern.h" -+#include "mconsole_kern.h" -+#include "2_5compat.h" -+#include "mem.h" -+#include "mem_kern.h" -+ -+unsigned long handle_page_fault(unsigned long address, unsigned long ip, -+ int is_write, int is_user, int *code_out) -+{ -+ struct mm_struct *mm = current->mm; -+ struct vm_area_struct *vma; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long page; -+ int handled = 0; -+ -+ *code_out = SEGV_MAPERR; -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, address); -+ if(!vma) -+ goto out; -+ else if(vma->vm_start <= address) -+ goto good_area; -+ else if(!(vma->vm_flags & VM_GROWSDOWN)) -+ goto out; -+ else if(expand_stack(vma, address)) -+ goto out; -+ -+ good_area: -+ *code_out = SEGV_ACCERR; -+ if(is_write && !(vma->vm_flags & VM_WRITE)) -+ goto out; -+ page = address & PAGE_MASK; -+ if(page == (unsigned long) current + PAGE_SIZE) -+ panic("Kernel stack overflow"); -+ pgd = pgd_offset(mm, page); -+ pmd = pmd_offset(pgd, page); -+ do { -+ survive: -+ switch (handle_mm_fault(mm, vma, address, is_write)) { -+ case 1: -+ current->min_flt++; -+ break; -+ case 2: -+ current->maj_flt++; -+ break; -+ default: -+ if (current->pid == 1) { -+ up_read(&mm->mmap_sem); -+ yield(); -+ down_read(&mm->mmap_sem); -+ goto survive; -+ } -+ /* Fall through to bad area case */ -+ case 0: -+ goto out; -+ } -+ pte = pte_offset(pmd, page); -+ } while(!pte_present(*pte)); -+ handled = 1; -+ *pte = pte_mkyoung(*pte); -+ if(pte_write(*pte)) *pte = pte_mkdirty(*pte); -+ flush_tlb_page(vma, page); -+ out: -+ up_read(&mm->mmap_sem); -+ return(handled); -+} -+ -+LIST_HEAD(physmem_remappers); -+ -+void register_remapper(struct remapper *info) -+{ -+ list_add(&info->list, &physmem_remappers); -+} -+ -+static int check_remapped_addr(unsigned long address, int is_write) -+{ -+ struct remapper *remapper; -+ struct list_head *ele; -+ __u64 offset; -+ int fd; -+ -+ fd = phys_mapping(__pa(address), &offset); -+ if(fd == -1) -+ return(0); -+ -+ list_for_each(ele, &physmem_remappers){ -+ remapper = list_entry(ele, struct remapper, list); -+ if((*remapper->proc)(fd, address, is_write, offset)) -+ return(1); -+ } -+ -+ return(0); -+} -+ -+unsigned long segv(unsigned long address, unsigned long ip, int is_write, -+ int is_user, void *sc) -+{ -+ struct siginfo si; -+ void *catcher; -+ int handled; -+ -+ if(!is_user && (address >= start_vm) && (address < end_vm)){ -+ flush_tlb_kernel_vm(); -+ return(0); -+ } -+ else if(check_remapped_addr(address & PAGE_MASK, is_write)) -+ return(0); -+ else if(current->mm == NULL) -+ panic("Segfault with no mm"); -+ -+ handled = handle_page_fault(address, ip, is_write, is_user, -+ &si.si_code); -+ -+ catcher = current->thread.fault_catcher; -+ if(handled) -+ return(0); -+ else if(catcher != NULL){ -+ current->thread.fault_addr = (void *) address; -+ do_longjmp(catcher, 1); -+ } -+ else if(current->thread.fault_addr != NULL) -+ panic("fault_addr set but no fault catcher"); -+ else if(arch_fixup(ip, sc)) -+ return(0); -+ -+ if(!is_user) -+ panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", -+ address, ip); -+ si.si_signo = SIGSEGV; -+ si.si_addr = (void *) address; -+ current->thread.cr2 = address; -+ current->thread.err = is_write; -+ force_sig_info(SIGSEGV, &si, current); -+ return(0); -+} -+ -+void bad_segv(unsigned long address, unsigned long ip, int is_write) -+{ -+ struct siginfo si; -+ -+ si.si_signo = SIGSEGV; -+ si.si_code = SEGV_ACCERR; -+ si.si_addr = (void *) address; -+ current->thread.cr2 = address; -+ current->thread.err = is_write; -+ force_sig_info(SIGSEGV, &si, current); -+} -+ -+void relay_signal(int sig, union uml_pt_regs *regs) -+{ -+ if(arch_handle_signal(sig, regs)) return; -+ if(!UPT_IS_USER(regs)) -+ panic("Kernel mode signal %d", sig); -+ force_sig(sig, current); -+} -+ -+void bus_handler(int sig, union uml_pt_regs *regs) -+{ -+ if(current->thread.fault_catcher != NULL) -+ do_longjmp(current->thread.fault_catcher, 1); -+ else relay_signal(sig, regs); -+} -+ -+void winch(int sig, union uml_pt_regs *regs) -+{ -+ do_IRQ(WINCH_IRQ, regs); -+} -+ -+void trap_init(void) -+{ -+} -+ -+spinlock_t trap_lock = SPIN_LOCK_UNLOCKED; -+ -+static int trap_index = 0; -+ -+int next_trap_index(int limit) -+{ -+ int ret; -+ -+ spin_lock(&trap_lock); -+ ret = trap_index; -+ if(++trap_index == limit) -+ trap_index = 0; -+ spin_unlock(&trap_lock); -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/trap_user.c um/arch/um/kernel/trap_user.c ---- orig/arch/um/kernel/trap_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/trap_user.c 2004-01-31 02:47:39.000000000 -0500 -@@ -0,0 +1,138 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <setjmp.h> -+#include <signal.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <asm/page.h> -+#include <asm/unistd.h> -+#include <asm/ptrace.h> -+#include "init.h" -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "sysdep/sigcontext.h" -+#include "irq_user.h" -+#include "frame_user.h" -+#include "signal_user.h" -+#include "time_user.h" -+#include "task.h" -+#include "mode.h" -+#include "choose-mode.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+ -+void kill_child_dead(int pid) -+{ -+ kill(pid, SIGKILL); -+ kill(pid, SIGCONT); -+ while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT); -+} -+ -+/* Unlocked - don't care if this is a bit off */ -+int nsegfaults = 0; -+ -+struct { -+ unsigned long address; -+ int is_write; -+ int pid; -+ unsigned long sp; -+ int is_user; -+} segfault_record[1024]; -+ -+void segv_handler(int sig, union uml_pt_regs *regs) -+{ -+ int index, max; -+ -+ if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){ -+ bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), -+ UPT_FAULT_WRITE(regs)); -+ return; -+ } -+ max = sizeof(segfault_record)/sizeof(segfault_record[0]); -+ index = next_trap_index(max); -+ -+ nsegfaults++; -+ segfault_record[index].address = UPT_FAULT_ADDR(regs); -+ segfault_record[index].pid = os_getpid(); -+ segfault_record[index].is_write = UPT_FAULT_WRITE(regs); -+ segfault_record[index].sp = UPT_SP(regs); -+ segfault_record[index].is_user = UPT_IS_USER(regs); -+ segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs), -+ UPT_IS_USER(regs), regs); -+} -+ -+void usr2_handler(int sig, union uml_pt_regs *regs) -+{ -+ CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -+} -+ -+struct signal_info sig_info[] = { -+ [ SIGTRAP ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGFPE ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGILL ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGWINCH ] { .handler = winch, -+ .is_irq = 1 }, -+ [ SIGBUS ] { .handler = bus_handler, -+ .is_irq = 0 }, -+ [ SIGSEGV] { .handler = segv_handler, -+ .is_irq = 0 }, -+ [ SIGIO ] { .handler = sigio_handler, -+ .is_irq = 1 }, -+ [ SIGVTALRM ] { .handler = timer_handler, -+ .is_irq = 1 }, -+ [ SIGALRM ] { .handler = timer_handler, -+ .is_irq = 1 }, -+ [ SIGUSR2 ] { .handler = usr2_handler, -+ .is_irq = 0 }, -+}; -+ -+void sig_handler(int sig, struct sigcontext sc) -+{ -+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, -+ sig, &sc); -+} -+ -+extern int timer_irq_inited, missed_ticks[]; -+ -+void alarm_handler(int sig, struct sigcontext sc) -+{ -+ if(!timer_irq_inited) return; -+ missed_ticks[cpu()]++; -+ -+ if(sig == SIGALRM) -+ switch_timers(0); -+ -+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, -+ sig, &sc); -+ -+ if(sig == SIGALRM) -+ switch_timers(1); -+} -+ -+void do_longjmp(void *b, int val) -+{ -+ sigjmp_buf *buf = b; -+ -+ siglongjmp(*buf, val); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/exec_kern.c um/arch/um/kernel/tt/exec_kern.c ---- orig/arch/um/kernel/tt/exec_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/exec_kern.c 2003-11-07 02:23:10.000000000 -0500 -@@ -0,0 +1,84 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/mm.h" -+#include "asm/signal.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/pgalloc.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "time_user.h" -+#include "mem_user.h" -+#include "os.h" -+#include "tlb.h" -+#include "mode.h" -+ -+static int exec_tramp(void *sig_stack) -+{ -+ init_new_thread_stack(sig_stack, NULL); -+ init_new_thread_signals(1); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+void flush_thread_tt(void) -+{ -+ unsigned long stack; -+ int new_pid; -+ -+ stack = alloc_stack(0, 0); -+ if(stack == 0){ -+ printk(KERN_ERR -+ "flush_thread : failed to allocate temporary stack\n"); -+ do_exit(SIGKILL); -+ } -+ -+ new_pid = start_fork_tramp((void *) current->thread.kernel_stack, -+ stack, 0, exec_tramp); -+ if(new_pid < 0){ -+ printk(KERN_ERR -+ "flush_thread : new thread failed, errno = %d\n", -+ -new_pid); -+ do_exit(SIGKILL); -+ } -+ -+ if(current->processor == 0) -+ forward_interrupts(new_pid); -+ current->thread.request.op = OP_EXEC; -+ current->thread.request.u.exec.pid = new_pid; -+ unprotect_stack((unsigned long) current); -+ os_usr1_process(os_getpid()); -+ -+ enable_timer(); -+ free_page(stack); -+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); -+ task_protections((unsigned long) current); -+ force_flush_all(); -+ unblock_signals(); -+} -+ -+void start_thread_tt(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp) -+{ -+ set_fs(USER_DS); -+ flush_tlb_mm(current->mm); -+ PT_REGS_IP(regs) = eip; -+ PT_REGS_SP(regs) = esp; -+ PT_FIX_EXEC_STACK(esp); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/exec_user.c um/arch/um/kernel/tt/exec_user.c ---- orig/arch/um/kernel/tt/exec_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/exec_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <sched.h> -+#include <errno.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <signal.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "ptrace_user.h" -+ -+void do_exec(int old_pid, int new_pid) -+{ -+ unsigned long regs[FRAME_SIZE]; -+ -+ if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || -+ (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) || -+ (waitpid(new_pid, 0, WUNTRACED) < 0)) -+ tracer_panic("do_exec failed to attach proc - errno = %d", -+ errno); -+ -+ if(ptrace_getregs(old_pid, regs) < 0) -+ tracer_panic("do_exec failed to get registers - errno = %d", -+ errno); -+ -+ kill(old_pid, SIGKILL); -+ -+ if(ptrace_setregs(new_pid, regs) < 0) -+ tracer_panic("do_exec failed to start new proc - errno = %d", -+ errno); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/gdb.c um/arch/um/kernel/tt/gdb.c ---- orig/arch/um/kernel/tt/gdb.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/gdb.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,278 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <errno.h> -+#include <string.h> -+#include <signal.h> -+#include <sys/ptrace.h> -+#include <sys/types.h> -+#include "uml-config.h" -+#include "kern_constants.h" -+#include "chan_user.h" -+#include "init.h" -+#include "user.h" -+#include "debug.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "tt.h" -+#include "sysdep/thread.h" -+ -+extern int debugger_pid; -+extern int debugger_fd; -+extern int debugger_parent; -+ -+int detach(int pid, int sig) -+{ -+ return(ptrace(PTRACE_DETACH, pid, 0, sig)); -+} -+ -+int attach(int pid) -+{ -+ int err; -+ -+ err = ptrace(PTRACE_ATTACH, pid, 0, 0); -+ if(err < 0) return(-errno); -+ else return(err); -+} -+ -+int cont(int pid) -+{ -+ return(ptrace(PTRACE_CONT, pid, 0, 0)); -+} -+ -+#ifdef UML_CONFIG_PT_PROXY -+ -+int debugger_signal(int status, pid_t pid) -+{ -+ return(debugger_proxy(status, pid)); -+} -+ -+void child_signal(pid_t pid, int status) -+{ -+ child_proxy(pid, status); -+} -+ -+static void gdb_announce(char *dev_name, int dev) -+{ -+ printf("gdb assigned device '%s'\n", dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = gdb_announce, -+ .xterm_title = "UML kernel debugger", -+ .raw = 0, -+ .tramp_stack = 0, -+ .in_kernel = 0, -+}; -+ -+/* Accessed by the tracing thread, which automatically serializes access */ -+static void *xterm_data; -+static int xterm_fd; -+ -+extern void *xterm_init(char *, int, struct chan_opts *); -+extern int xterm_open(int, int, int, void *, char **); -+extern void xterm_close(int, void *); -+ -+int open_gdb_chan(void) -+{ -+ char stack[UM_KERN_PAGE_SIZE], *dummy; -+ -+ opts.tramp_stack = (unsigned long) stack; -+ xterm_data = xterm_init("", 0, &opts); -+ xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); -+ return(xterm_fd); -+} -+ -+static void exit_debugger_cb(void *unused) -+{ -+ if(debugger_pid != -1){ -+ if(gdb_pid != -1){ -+ fake_child_exit(); -+ gdb_pid = -1; -+ } -+ else kill_child_dead(debugger_pid); -+ debugger_pid = -1; -+ if(debugger_parent != -1) -+ detach(debugger_parent, SIGINT); -+ } -+ if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); -+} -+ -+static void exit_debugger(void) -+{ -+ initial_thread_cb(exit_debugger_cb, NULL); -+} -+ -+__uml_exitcall(exit_debugger); -+ -+struct gdb_data { -+ char *str; -+ int err; -+}; -+ -+static void config_gdb_cb(void *arg) -+{ -+ struct gdb_data *data = arg; -+ void *task; -+ int pid; -+ -+ data->err = -1; -+ if(debugger_pid != -1) exit_debugger_cb(NULL); -+ if(!strncmp(data->str, "pid,", strlen("pid,"))){ -+ data->str += strlen("pid,"); -+ pid = strtoul(data->str, NULL, 0); -+ task = cpu_tasks[0].task; -+ debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); -+ if(debugger_pid != -1){ -+ data->err = 0; -+ gdb_pid = pid; -+ } -+ return; -+ } -+ data->err = 0; -+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); -+ init_proxy(debugger_pid, 0, 0); -+} -+ -+int gdb_config(char *str) -+{ -+ struct gdb_data data; -+ -+ if(*str++ != '=') return(-1); -+ data.str = str; -+ initial_thread_cb(config_gdb_cb, &data); -+ return(data.err); -+} -+ -+void remove_gdb_cb(void *unused) -+{ -+ exit_debugger_cb(NULL); -+} -+ -+int gdb_remove(char *unused) -+{ -+ initial_thread_cb(remove_gdb_cb, NULL); -+ return(0); -+} -+ -+void signal_usr1(int sig) -+{ -+ if(debugger_pid != -1){ -+ printk(UM_KERN_ERR "The debugger is already running\n"); -+ return; -+ } -+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); -+ init_proxy(debugger_pid, 0, 0); -+} -+ -+int init_ptrace_proxy(int idle_pid, int startup, int stop) -+{ -+ int pid, status; -+ -+ pid = start_debugger(linux_prog, startup, stop, &debugger_fd); -+ status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); -+ if(pid < 0){ -+ cont(idle_pid); -+ return(-1); -+ } -+ init_proxy(pid, 1, status); -+ return(pid); -+} -+ -+int attach_debugger(int idle_pid, int pid, int stop) -+{ -+ int status = 0, err; -+ -+ err = attach(pid); -+ if(err < 0){ -+ printf("Failed to attach pid %d, errno = %d\n", pid, -err); -+ return(-1); -+ } -+ if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); -+ init_proxy(pid, 1, status); -+ return(pid); -+} -+ -+#ifdef notdef /* Put this back in when it does something useful */ -+static int __init uml_gdb_init_setup(char *line, int *add) -+{ -+ gdb_init = uml_strdup(line); -+ return 0; -+} -+ -+__uml_setup("gdb=", uml_gdb_init_setup, -+"gdb=<channel description>\n\n" -+); -+#endif -+ -+static int __init uml_gdb_pid_setup(char *line, int *add) -+{ -+ gdb_pid = strtoul(line, NULL, 0); -+ *add = 0; -+ return 0; -+} -+ -+__uml_setup("gdb-pid=", uml_gdb_pid_setup, -+"gdb-pid=<pid>\n" -+" gdb-pid is used to attach an external debugger to UML. This may be\n" -+" an already-running gdb or a debugger-like process like strace.\n\n" -+); -+ -+#else -+ -+int debugger_signal(int status, pid_t pid){ return(0); } -+void child_signal(pid_t pid, int status){ } -+int init_ptrace_proxy(int idle_pid, int startup, int stop) -+{ -+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); -+ kill_child_dead(idle_pid); -+ exit(1); -+} -+ -+void signal_usr1(int sig) -+{ -+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); -+} -+ -+int attach_debugger(int idle_pid, int pid, int stop) -+{ -+ printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY " -+ "is off\n"); -+ return(-1); -+} -+ -+int config_gdb(char *str) -+{ -+ return(-1); -+} -+ -+int remove_gdb(void) -+{ -+ return(-1); -+} -+ -+int init_parent_proxy(int pid) -+{ -+ return(-1); -+} -+ -+void debugger_parent_signal(int status, int pid) -+{ -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/gdb_kern.c um/arch/um/kernel/tt/gdb_kern.c ---- orig/arch/um/kernel/tt/gdb_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/gdb_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/config.h" -+#include "mconsole_kern.h" -+ -+#ifdef CONFIG_MCONSOLE -+ -+extern int gdb_config(char *str); -+extern int gdb_remove(char *unused); -+ -+static struct mc_device gdb_mc = { -+ .name = "gdb", -+ .config = gdb_config, -+ .remove = gdb_remove, -+}; -+ -+int gdb_mc_init(void) -+{ -+ mconsole_register_dev(&gdb_mc); -+ return(0); -+} -+ -+__initcall(gdb_mc_init); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/debug.h um/arch/um/kernel/tt/include/debug.h ---- orig/arch/um/kernel/tt/include/debug.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/debug.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and -+ * Lars Brinkhoff. -+ * Licensed under the GPL -+ */ -+ -+#ifndef __DEBUG_H -+#define __DEBUG_H -+ -+extern int debugger_proxy(int status, pid_t pid); -+extern void child_proxy(pid_t pid, int status); -+extern void init_proxy (pid_t pid, int waiting, int status); -+extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); -+extern void fake_child_exit(void); -+extern int gdb_config(char *str); -+extern int gdb_remove(char *unused); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mmu.h um/arch/um/kernel/tt/include/mmu.h ---- orig/arch/um/kernel/tt/include/mmu.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/mmu.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_MMU_H -+#define __TT_MMU_H -+ -+struct mmu_context_tt { -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mode.h um/arch/um/kernel/tt/include/mode.h ---- orig/arch/um/kernel/tt/include/mode.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/mode.h 2003-11-07 01:42:09.000000000 -0500 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_TT_H__ -+#define __MODE_TT_H__ -+ -+#include "sysdep/ptrace.h" -+ -+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; -+ -+extern int tracing_pid; -+ -+extern int tracer(int (*init_proc)(void *), void *sp); -+extern void user_time_init_tt(void); -+extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data); -+extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, -+ void *data); -+extern void sig_handler_common_tt(int sig, void *sc); -+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); -+extern void reboot_tt(void); -+extern void halt_tt(void); -+extern int is_tracer_winch(int pid, int fd, void *data); -+extern void kill_off_processes_tt(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/mode_kern.h um/arch/um/kernel/tt/include/mode_kern.h ---- orig/arch/um/kernel/tt/include/mode_kern.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/mode_kern.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_MODE_KERN_H__ -+#define __TT_MODE_KERN_H__ -+ -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+ -+extern void *_switch_to_tt(void *prev, void *next); -+extern void flush_thread_tt(void); -+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp); -+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct *p, -+ struct pt_regs *regs); -+extern void release_thread_tt(struct task_struct *task); -+extern void exit_thread_tt(void); -+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); -+extern void init_idle_tt(void); -+extern void flush_tlb_kernel_vm_tt(void); -+extern void __flush_tlb_one_tt(unsigned long addr); -+extern void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_mm_tt(struct mm_struct *mm); -+extern void force_flush_all_tt(void); -+extern long execute_syscall_tt(void *r); -+extern void before_mem_tt(unsigned long brk_start); -+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out); -+extern int start_uml_tt(void); -+extern int external_pid_tt(struct task_struct *task); -+extern int thread_pid_tt(struct thread_struct *thread); -+ -+#define kmem_end_tt (host_task_size - ABOVE_KMEM) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/ptrace-tt.h um/arch/um/kernel/tt/include/ptrace-tt.h ---- orig/arch/um/kernel/tt/include/ptrace-tt.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/ptrace-tt.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_TT_H -+#define __PTRACE_TT_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "sysdep/sc.h" -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/tt.h um/arch/um/kernel/tt/include/tt.h ---- orig/arch/um/kernel/tt/include/tt.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/tt.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_H__ -+#define __TT_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int gdb_pid; -+extern int debug; -+extern int debug_stop; -+extern int debug_trace; -+ -+extern int honeypot; -+ -+extern int fork_tramp(void *sig_stack); -+extern int do_proc_op(void *t, int proc_id); -+extern int tracer(int (*init_proc)(void *), void *sp); -+extern void attach_process(int pid); -+extern void tracer_panic(char *format, ...); -+extern void set_init_pid(int pid); -+extern int set_user_mode(void *task); -+extern void set_tracing(void *t, int tracing); -+extern int is_tracing(void *task); -+extern int singlestepping_tt(void *t); -+extern void clear_singlestep(void *t); -+extern void syscall_handler(int sig, union uml_pt_regs *regs); -+extern void exit_kernel(int pid, void *task); -+extern int do_syscall(void *task, int pid); -+extern int is_valid_pid(int pid); -+extern void remap_data(void *segment_start, void *segment_end, int w); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/include/uaccess.h um/arch/um/kernel/tt/include/uaccess.h ---- orig/arch/um/kernel/tt/include/uaccess.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/include/uaccess.h 2003-11-12 08:37:20.000000000 -0500 -@@ -0,0 +1,71 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_UACCESS_H -+#define __TT_UACCESS_H -+ -+#include "linux/string.h" -+#include "linux/sched.h" -+#include "asm/processor.h" -+#include "asm/errno.h" -+#include "asm/current.h" -+#include "asm/a.out.h" -+#include "uml_uaccess.h" -+ -+#define ABOVE_KMEM (16 * 1024 * 1024) -+ -+extern unsigned long end_vm; -+extern unsigned long uml_physmem; -+ -+#define under_task_size(addr, size) \ -+ (((unsigned long) (addr) < TASK_SIZE) && \ -+ (((unsigned long) (addr) + (size)) < TASK_SIZE)) -+ -+#define is_stack(addr, size) \ -+ (((unsigned long) (addr) < STACK_TOP) && \ -+ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ -+ (((unsigned long) (addr) + (size)) <= STACK_TOP)) -+ -+#define access_ok_tt(type, addr, size) \ -+ ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ -+ (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ -+ (under_task_size(addr, size) || is_stack(addr, size)))) -+ -+static inline int verify_area_tt(int type, const void * addr, -+ unsigned long size) -+{ -+ return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); -+} -+ -+extern unsigned long get_fault_addr(void); -+ -+extern int __do_copy_from_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher); -+extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, -+ void **fault_addr, void **fault_catcher); -+extern int __do_clear_user(void *mem, size_t len, void **fault_addr, -+ void **fault_catcher); -+extern int __do_strnlen_user(const char *str, unsigned long n, -+ void **fault_addr, void **fault_catcher); -+ -+extern int copy_from_user_tt(void *to, const void *from, int n); -+extern int copy_to_user_tt(void *to, const void *from, int n); -+extern int strncpy_from_user_tt(char *dst, const char *src, int count); -+extern int __clear_user_tt(void *mem, int len); -+extern int clear_user_tt(void *mem, int len); -+extern int strnlen_user_tt(const void *str, int len); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ksyms.c um/arch/um/kernel/tt/ksyms.c ---- orig/arch/um/kernel/tt/ksyms.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ksyms.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+#include "asm/uaccess.h" -+#include "mode.h" -+ -+EXPORT_SYMBOL(__do_copy_from_user); -+EXPORT_SYMBOL(__do_copy_to_user); -+EXPORT_SYMBOL(__do_strncpy_from_user); -+EXPORT_SYMBOL(__do_strnlen_user); -+EXPORT_SYMBOL(__do_clear_user); -+ -+EXPORT_SYMBOL(tracing_pid); -+EXPORT_SYMBOL(honeypot); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/Makefile um/arch/um/kernel/tt/Makefile ---- orig/arch/um/kernel/tt/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/Makefile 2003-11-12 08:34:27.000000000 -0500 -@@ -0,0 +1,39 @@ -+# -+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = tt.o -+ -+obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ -+ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ -+ uaccess.o uaccess_user.o -+ -+obj-$(CONFIG_PT_PROXY) += gdb_kern.o -+ -+subdir-y = sys-$(SUBARCH) -+subdir-$(CONFIG_PT_PROXY) += ptproxy -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+export-objs = ksyms.o -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) gdb.o time.o tracer.o -+ -+UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS)) -+UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+$(O_TARGET) : unmap_fin.o -+ -+unmap.o: unmap.c -+ $(CC) $(UNMAP_CFLAGS) -c -o $@ $< -+ -+unmap_fin.o : unmap.o -+ ld -r -o $@ $< -lc -L/usr/lib -+ -+clean : -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/mem.c um/arch/um/kernel/tt/mem.c ---- orig/arch/um/kernel/tt/mem.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/mem.c 2004-01-31 02:38:28.000000000 -0500 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "asm/uaccess.h" -+#include "mem_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "kern.h" -+#include "tt.h" -+ -+void before_mem_tt(unsigned long brk_start) -+{ -+ if(!jail || debug) -+ remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); -+ remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); -+ remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); -+} -+ -+#ifdef CONFIG_HOST_2G_2G -+#define TOP 0x80000000 -+#else -+#define TOP 0xc0000000 -+#endif -+ -+#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) -+#define START (TOP - SIZE) -+ -+unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out) -+{ -+ /* Round up to the nearest 4M */ -+ *host_size_out = ROUND_4M((unsigned long) &arg); -+ *task_size_out = START; -+ return(START); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/mem_user.c um/arch/um/kernel/tt/mem_user.c ---- orig/arch/um/kernel/tt/mem_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/mem_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <stdio.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/mman.h> -+#include "tt.h" -+#include "mem_user.h" -+#include "user_util.h" -+ -+void remap_data(void *segment_start, void *segment_end, int w) -+{ -+ void *addr; -+ unsigned long size; -+ int data, prot; -+ -+ if(w) prot = PROT_WRITE; -+ else prot = 0; -+ prot |= PROT_READ | PROT_EXEC; -+ size = (unsigned long) segment_end - -+ (unsigned long) segment_start; -+ data = create_mem_file(size); -+ addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); -+ if(addr == MAP_FAILED){ -+ perror("mapping new data segment"); -+ exit(1); -+ } -+ memcpy(addr, segment_start, size); -+ if(switcheroo(data, prot, addr, segment_start, size) < 0){ -+ printf("switcheroo failed\n"); -+ exit(1); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/process_kern.c um/arch/um/kernel/tt/process_kern.c ---- orig/arch/um/kernel/tt/process_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/process_kern.c 2004-01-31 02:39:08.000000000 -0500 -@@ -0,0 +1,535 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/signal.h" -+#include "linux/kernel.h" -+#include "asm/system.h" -+#include "asm/pgalloc.h" -+#include "asm/ptrace.h" -+#include "irq_user.h" -+#include "signal_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "kern.h" -+#include "sigcontext.h" -+#include "time_user.h" -+#include "mem_user.h" -+#include "tlb.h" -+#include "mode.h" -+#include "init.h" -+#include "tt.h" -+ -+void *_switch_to_tt(void *prev, void *next) -+{ -+ struct task_struct *from, *to; -+ unsigned long flags; -+ int err, vtalrm, alrm, prof, cpu; -+ char c; -+ /* jailing and SMP are incompatible, so this doesn't need to be -+ * made per-cpu -+ */ -+ static int reading; -+ -+ from = prev; -+ to = next; -+ -+ to->thread.prev_sched = from; -+ -+ cpu = from->processor; -+ if(cpu == 0) -+ forward_interrupts(to->thread.mode.tt.extern_pid); -+#ifdef CONFIG_SMP -+ forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); -+#endif -+ local_irq_save(flags); -+ -+ vtalrm = change_sig(SIGVTALRM, 0); -+ alrm = change_sig(SIGALRM, 0); -+ prof = change_sig(SIGPROF, 0); -+ -+ c = 0; -+ set_current(to); -+ -+ reading = 0; -+ err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); -+ if(err != sizeof(c)) -+ panic("write of switch_pipe failed, err = %d", -err); -+ -+ reading = 1; -+ if(from->state == TASK_ZOMBIE) -+ os_kill_process(os_getpid(), 0); -+ -+ err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c)); -+ if(err != sizeof(c)) -+ panic("read of switch_pipe failed, errno = %d", -err); -+ -+ /* This works around a nasty race with 'jail'. If we are switching -+ * between two threads of a threaded app and the incoming process -+ * runs before the outgoing process reaches the read, and it makes -+ * it all the way out to userspace, then it will have write-protected -+ * the outgoing process stack. Then, when the outgoing process -+ * returns from the write, it will segfault because it can no longer -+ * write its own stack. So, in order to avoid that, the incoming -+ * thread sits in a loop yielding until 'reading' is set. This -+ * isn't entirely safe, since there may be a reschedule from a timer -+ * happening between setting 'reading' and sleeping in read. But, -+ * it should get a whole quantum in which to reach the read and sleep, -+ * which should be enough. -+ */ -+ -+ if(jail){ -+ while(!reading) sched_yield(); -+ } -+ -+ change_sig(SIGVTALRM, vtalrm); -+ change_sig(SIGALRM, alrm); -+ change_sig(SIGPROF, prof); -+ -+ arch_switch(); -+ -+ flush_tlb_all(); -+ local_irq_restore(flags); -+ -+ return(current->thread.prev_sched); -+} -+ -+void release_thread_tt(struct task_struct *task) -+{ -+ os_kill_process(task->thread.mode.tt.extern_pid, 0); -+} -+ -+void exit_thread_tt(void) -+{ -+ os_close_file(current->thread.mode.tt.switch_pipe[0]); -+ os_close_file(current->thread.mode.tt.switch_pipe[1]); -+} -+ -+extern void schedule_tail(struct task_struct *prev); -+ -+static void new_thread_handler(int sig) -+{ -+ unsigned long disable; -+ int (*fn)(void *); -+ void *arg; -+ -+ fn = current->thread.request.u.thread.proc; -+ arg = current->thread.request.u.thread.arg; -+ -+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); -+ disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | -+ (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); -+ SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; -+ -+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); -+ -+ init_new_thread_signals(1); -+ enable_timer(); -+ free_page(current->thread.temp_stack); -+ set_cmdline("(kernel thread)"); -+ force_flush_all(); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ change_sig(SIGUSR1, 1); -+ change_sig(SIGVTALRM, 1); -+ change_sig(SIGPROF, 1); -+ sti(); -+ if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) -+ do_exit(0); -+} -+ -+static int new_thread_proc(void *stack) -+{ -+ /* cli is needed to block out signals until this thread is properly -+ * scheduled. Otherwise, the tracing thread will get mighty upset -+ * about any signals that arrive before that. -+ * This has the complication that it sets the saved signal mask in -+ * the sigcontext to block signals. This gets restored when this -+ * thread (or a descendant, since they get a copy of this sigcontext) -+ * returns to userspace. -+ * So, this is compensated for elsewhere. -+ * XXX There is still a small window until cli() actually finishes -+ * where signals are possible - shouldn't be a problem in practice -+ * since SIGIO hasn't been forwarded here yet, and the cli should -+ * finish before a SIGVTALRM has time to be delivered. -+ */ -+ cli(); -+ init_new_thread_stack(stack, new_thread_handler); -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+/* Signal masking - signals are blocked at the start of fork_tramp. They -+ * are re-enabled when finish_fork_handler is entered by fork_tramp hitting -+ * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, -+ * so it is blocked before it's called. They are re-enabled on sigreturn -+ * despite the fact that they were blocked when the SIGUSR1 was issued because -+ * copy_thread copies the parent's sigcontext, including the signal mask -+ * onto the signal frame. -+ */ -+ -+static void finish_fork_handler(int sig) -+{ -+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); -+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); -+ -+ init_new_thread_signals(1); -+ enable_timer(); -+ sti(); -+ force_flush_all(); -+ if(current->mm != current->p_pptr->mm) -+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, -+ 1, 0, 1); -+ task_protections((unsigned long) current); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ free_page(current->thread.temp_stack); -+ cli(); -+ change_sig(SIGUSR1, 0); -+ set_user_mode(current); -+} -+ -+int fork_tramp(void *stack) -+{ -+ cli(); -+ arch_init_thread(); -+ init_new_thread_stack(stack, finish_fork_handler); -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ int (*tramp)(void *); -+ int new_pid, err; -+ unsigned long stack; -+ -+ if(current->thread.forking) -+ tramp = fork_tramp; -+ else { -+ tramp = new_thread_proc; -+ p->thread.request.u.thread = current->thread.request.u.thread; -+ } -+ -+ err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); -+ if(err < 0){ -+ printk("copy_thread : pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ -+ stack = alloc_stack(0, 0); -+ if(stack == 0){ -+ printk(KERN_ERR "copy_thread : failed to allocate " -+ "temporary stack\n"); -+ return(-ENOMEM); -+ } -+ -+ clone_flags &= CLONE_VM; -+ p->thread.temp_stack = stack; -+ new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack, -+ clone_flags, tramp); -+ if(new_pid < 0){ -+ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -+ -new_pid); -+ return(new_pid); -+ } -+ -+ if(current->thread.forking){ -+ sc_to_sc(UPT_SC(&p->thread.regs.regs), -+ UPT_SC(¤t->thread.regs.regs)); -+ SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); -+ if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; -+ } -+ p->thread.mode.tt.extern_pid = new_pid; -+ -+ current->thread.request.op = OP_FORK; -+ current->thread.request.u.fork.pid = new_pid; -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+void reboot_tt(void) -+{ -+ current->thread.request.op = OP_REBOOT; -+ os_usr1_process(os_getpid()); -+} -+ -+void halt_tt(void) -+{ -+ current->thread.request.op = OP_HALT; -+ os_usr1_process(os_getpid()); -+} -+ -+void kill_off_processes_tt(void) -+{ -+ struct task_struct *p; -+ int me; -+ -+ me = os_getpid(); -+ for_each_task(p){ -+ int pid = p->thread.mode.tt.extern_pid; -+ if((pid != me) && (pid != -1)) -+ os_kill_process(p->thread.mode.tt.extern_pid, 0); -+ } -+ if((init_task.thread.mode.tt.extern_pid != me) && -+ (init_task.thread.mode.tt.extern_pid != -1)) -+ os_kill_process(init_task.thread.mode.tt.extern_pid, 0); -+} -+ -+void initial_thread_cb_tt(void (*proc)(void *), void *arg) -+{ -+ if(os_getpid() == tracing_pid){ -+ (*proc)(arg); -+ } -+ else { -+ current->thread.request.op = OP_CB; -+ current->thread.request.u.cb.proc = proc; -+ current->thread.request.u.cb.arg = arg; -+ os_usr1_process(os_getpid()); -+ } -+} -+ -+int do_proc_op(void *t, int proc_id) -+{ -+ struct task_struct *task; -+ struct thread_struct *thread; -+ int op, pid; -+ -+ task = t; -+ thread = &task->thread; -+ op = thread->request.op; -+ switch(op){ -+ case OP_NONE: -+ case OP_TRACE_ON: -+ break; -+ case OP_EXEC: -+ pid = thread->request.u.exec.pid; -+ do_exec(thread->mode.tt.extern_pid, pid); -+ thread->mode.tt.extern_pid = pid; -+ cpu_tasks[task->processor].pid = pid; -+ break; -+ case OP_FORK: -+ attach_process(thread->request.u.fork.pid); -+ break; -+ case OP_CB: -+ (*thread->request.u.cb.proc)(thread->request.u.cb.arg); -+ break; -+ case OP_REBOOT: -+ case OP_HALT: -+ break; -+ default: -+ tracer_panic("Bad op in do_proc_op"); -+ break; -+ } -+ thread->request.op = OP_NONE; -+ return(op); -+} -+ -+void init_idle_tt(void) -+{ -+ idle_timer(); -+} -+ -+/* Changed by jail_setup, which is a setup */ -+int jail = 0; -+ -+int __init jail_setup(char *line, int *add) -+{ -+ int ok = 1; -+ -+ if(jail) return(0); -+#ifdef CONFIG_SMP -+ printf("'jail' may not used used in a kernel with CONFIG_SMP " -+ "enabled\n"); -+ ok = 0; -+#endif -+#ifdef CONFIG_HOSTFS -+ printf("'jail' may not used used in a kernel with CONFIG_HOSTFS " -+ "enabled\n"); -+ ok = 0; -+#endif -+#ifdef CONFIG_MODULES -+ printf("'jail' may not used used in a kernel with CONFIG_MODULES " -+ "enabled\n"); -+ ok = 0; -+#endif -+ if(!ok) exit(1); -+ -+ /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem. -+ * Removing it from the bounding set eliminates the ability of anything -+ * to acquire it, and thus read or write kernel memory. -+ */ -+ cap_lower(cap_bset, CAP_SYS_RAWIO); -+ jail = 1; -+ return(0); -+} -+ -+__uml_setup("jail", jail_setup, -+"jail\n" -+" Enables the protection of kernel memory from processes.\n\n" -+); -+ -+static void mprotect_kernel_mem(int w) -+{ -+ unsigned long start, end; -+ int pages; -+ -+ if(!jail || (current == &init_task)) return; -+ -+ pages = (1 << CONFIG_KERNEL_STACK_ORDER); -+ -+ start = (unsigned long) current + PAGE_SIZE; -+ end = (unsigned long) current + PAGE_SIZE * pages; -+ protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1); -+ protect_memory(end, high_physmem - end, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&_stext); -+ end = (unsigned long) UML_ROUND_UP(&_etext); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end); -+ end = (unsigned long) UML_ROUND_UP(&_edata); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&__bss_start); -+ end = (unsigned long) UML_ROUND_UP(&_end); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ mprotect_kernel_vm(w); -+} -+ -+void unprotect_kernel_mem(void) -+{ -+ mprotect_kernel_mem(1); -+} -+ -+void protect_kernel_mem(void) -+{ -+ mprotect_kernel_mem(0); -+} -+ -+extern void start_kernel(void); -+ -+static int start_kernel_proc(void *unused) -+{ -+ int pid; -+ -+ block_signals(); -+ pid = os_getpid(); -+ -+ cpu_tasks[0].pid = pid; -+ cpu_tasks[0].task = current; -+#ifdef CONFIG_SMP -+ cpu_online_map = 1; -+#endif -+ if(debug) os_stop_process(pid); -+ start_kernel(); -+ return(0); -+} -+ -+void set_tracing(void *task, int tracing) -+{ -+ ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; -+} -+ -+int is_tracing(void *t) -+{ -+ return (((struct task_struct *) t)->thread.mode.tt.tracing); -+} -+ -+int set_user_mode(void *t) -+{ -+ struct task_struct *task; -+ -+ task = t ? t : current; -+ if(task->thread.mode.tt.tracing) -+ return(1); -+ task->thread.request.op = OP_TRACE_ON; -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+void set_init_pid(int pid) -+{ -+ int err; -+ -+ init_task.thread.mode.tt.extern_pid = pid; -+ err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); -+ if(err) -+ panic("Can't create switch pipe for init_task, errno = %d", -+ -err); -+} -+ -+int singlestepping_tt(void *t) -+{ -+ struct task_struct *task = t; -+ -+ if(task->thread.mode.tt.singlestep_syscall) -+ return(0); -+ return(task->ptrace & PT_DTRACE); -+} -+ -+void clear_singlestep(void *t) -+{ -+ struct task_struct *task = t; -+ -+ task->ptrace &= ~PT_DTRACE; -+} -+ -+int start_uml_tt(void) -+{ -+ void *sp; -+ int pages; -+ -+ pages = (1 << CONFIG_KERNEL_STACK_ORDER) - 2; -+ sp = (void *) init_task.thread.kernel_stack + pages * PAGE_SIZE - -+ sizeof(unsigned long); -+ return(tracer(start_kernel_proc, sp)); -+} -+ -+int external_pid_tt(struct task_struct *task) -+{ -+ return(task->thread.mode.tt.extern_pid); -+} -+ -+int thread_pid_tt(struct thread_struct *thread) -+{ -+ return(thread->mode.tt.extern_pid); -+} -+ -+int is_valid_pid(int pid) -+{ -+ struct task_struct *task; -+ -+ read_lock(&tasklist_lock); -+ for_each_task(task){ -+ if(task->thread.mode.tt.extern_pid == pid){ -+ read_unlock(&tasklist_lock); -+ return(1); -+ } -+ } -+ read_unlock(&tasklist_lock); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/Makefile um/arch/um/kernel/tt/ptproxy/Makefile ---- orig/arch/um/kernel/tt/ptproxy/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,12 @@ -+O_TARGET = ptproxy.o -+ -+obj-y = proxy.o ptrace.o sysdep.o wait.o -+ -+USER_OBJS = $(obj-y) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean: -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/proxy.c um/arch/um/kernel/tt/ptproxy/proxy.c ---- orig/arch/um/kernel/tt/ptproxy/proxy.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/proxy.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,371 @@ -+/********************************************************************** -+proxy.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+Jeff Dike (jdike@karaya.com) : Modified for integration into uml -+**********************************************************************/ -+ -+/* XXX This file shouldn't refer to CONFIG_* */ -+ -+#include <errno.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <signal.h> -+#include <string.h> -+#include <termios.h> -+#include <sys/wait.h> -+#include <sys/types.h> -+#include <sys/ptrace.h> -+#include <sys/ioctl.h> -+#include <asm/unistd.h> -+ -+#include "ptproxy.h" -+#include "sysdep.h" -+#include "wait.h" -+ -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+#include "tempfile.h" -+ -+static int debugger_wait(debugger_state *debugger, int *status, int options, -+ int (*syscall)(debugger_state *debugger, pid_t child), -+ int (*normal_return)(debugger_state *debugger, -+ pid_t unused), -+ int (*wait_return)(debugger_state *debugger, -+ pid_t unused)) -+{ -+ if(debugger->real_wait){ -+ debugger->handle_trace = normal_return; -+ syscall_continue(debugger->pid); -+ debugger->real_wait = 0; -+ return(1); -+ } -+ debugger->wait_status_ptr = status; -+ debugger->wait_options = options; -+ if((debugger->debugee != NULL) && debugger->debugee->event){ -+ syscall_continue(debugger->pid); -+ wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, -+ NULL); -+ (*wait_return)(debugger, -1); -+ return(0); -+ } -+ else if(debugger->wait_options & WNOHANG){ -+ syscall_cancel(debugger->pid, 0); -+ debugger->handle_trace = syscall; -+ return(0); -+ } -+ else { -+ syscall_pause(debugger->pid); -+ debugger->handle_trace = wait_return; -+ debugger->waiting = 1; -+ } -+ return(1); -+} -+ -+/* -+ * Handle debugger trap, i.e. syscall. -+ */ -+ -+int debugger_syscall(debugger_state *debugger, pid_t child) -+{ -+ long arg1, arg2, arg3, arg4, arg5, result; -+ int syscall, ret = 0; -+ -+ syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, -+ &arg5); -+ -+ switch(syscall){ -+ case __NR_execve: -+ /* execve never returns */ -+ debugger->handle_trace = debugger_syscall; -+ break; -+ -+ case __NR_ptrace: -+ if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; -+ if(!debugger->debugee->in_context) -+ child = debugger->debugee->pid; -+ result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, -+ &ret); -+ syscall_cancel(debugger->pid, result); -+ debugger->handle_trace = debugger_syscall; -+ return(ret); -+ -+ case __NR_waitpid: -+ case __NR_wait4: -+ if(!debugger_wait(debugger, (int *) arg2, arg3, -+ debugger_syscall, debugger_normal_return, -+ proxy_wait_return)) -+ return(0); -+ break; -+ -+ case __NR_kill: -+ if(!debugger->debugee->in_context) -+ child = debugger->debugee->pid; -+ if(arg1 == debugger->debugee->pid){ -+ result = kill(child, arg2); -+ syscall_cancel(debugger->pid, result); -+ debugger->handle_trace = debugger_syscall; -+ return(0); -+ } -+ else debugger->handle_trace = debugger_normal_return; -+ break; -+ -+ default: -+ debugger->handle_trace = debugger_normal_return; -+ } -+ -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+/* Used by the tracing thread */ -+static debugger_state parent; -+static int parent_syscall(debugger_state *debugger, int pid); -+ -+int init_parent_proxy(int pid) -+{ -+ parent = ((debugger_state) { .pid = pid, -+ .wait_options = 0, -+ .wait_status_ptr = NULL, -+ .waiting = 0, -+ .real_wait = 0, -+ .expecting_child = 0, -+ .handle_trace = parent_syscall, -+ .debugee = NULL } ); -+ return(0); -+} -+ -+int parent_normal_return(debugger_state *debugger, pid_t unused) -+{ -+ debugger->handle_trace = parent_syscall; -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+static int parent_syscall(debugger_state *debugger, int pid) -+{ -+ long arg1, arg2, arg3, arg4, arg5; -+ int syscall; -+ -+ syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); -+ -+ if((syscall == __NR_waitpid) || (syscall == __NR_wait4)){ -+ debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, -+ parent_normal_return, parent_wait_return); -+ } -+ else ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ return(0); -+} -+ -+int debugger_normal_return(debugger_state *debugger, pid_t unused) -+{ -+ debugger->handle_trace = debugger_syscall; -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+void debugger_cancelled_return(debugger_state *debugger, int result) -+{ -+ debugger->handle_trace = debugger_syscall; -+ syscall_set_result(debugger->pid, result); -+ syscall_continue(debugger->pid); -+} -+ -+/* Used by the tracing thread */ -+static debugger_state debugger; -+static debugee_state debugee; -+ -+void init_proxy (pid_t debugger_pid, int stopped, int status) -+{ -+ debugger.pid = debugger_pid; -+ debugger.handle_trace = debugger_syscall; -+ debugger.debugee = &debugee; -+ debugger.waiting = 0; -+ debugger.real_wait = 0; -+ debugger.expecting_child = 0; -+ -+ debugee.pid = 0; -+ debugee.traced = 0; -+ debugee.stopped = stopped; -+ debugee.event = 0; -+ debugee.zombie = 0; -+ debugee.died = 0; -+ debugee.wait_status = status; -+ debugee.in_context = 1; -+} -+ -+int debugger_proxy(int status, int pid) -+{ -+ int ret = 0, sig; -+ -+ if(WIFSTOPPED(status)){ -+ sig = WSTOPSIG(status); -+ if (sig == SIGTRAP) -+ ret = (*debugger.handle_trace)(&debugger, pid); -+ -+ else if(sig == SIGCHLD){ -+ if(debugger.expecting_child){ -+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ debugger.expecting_child = 0; -+ } -+ else if(debugger.waiting) -+ real_wait_return(&debugger); -+ else { -+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ debugger.real_wait = 1; -+ } -+ } -+ else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ } -+ else if(WIFEXITED(status)){ -+ tracer_panic("debugger (pid %d) exited with status %d", -+ debugger.pid, WEXITSTATUS(status)); -+ } -+ else if(WIFSIGNALED(status)){ -+ tracer_panic("debugger (pid %d) exited with signal %d", -+ debugger.pid, WTERMSIG(status)); -+ } -+ else { -+ tracer_panic("proxy got unknown status (0x%x) on debugger " -+ "(pid %d)", status, debugger.pid); -+ } -+ return(ret); -+} -+ -+void child_proxy(pid_t pid, int status) -+{ -+ debugee.event = 1; -+ debugee.wait_status = status; -+ -+ if(WIFSTOPPED(status)){ -+ debugee.stopped = 1; -+ debugger.expecting_child = 1; -+ kill(debugger.pid, SIGCHLD); -+ } -+ else if(WIFEXITED(status) || WIFSIGNALED(status)){ -+ debugee.zombie = 1; -+ debugger.expecting_child = 1; -+ kill(debugger.pid, SIGCHLD); -+ } -+ else panic("proxy got unknown status (0x%x) on child (pid %d)", -+ status, pid); -+} -+ -+void debugger_parent_signal(int status, int pid) -+{ -+ int sig; -+ -+ if(WIFSTOPPED(status)){ -+ sig = WSTOPSIG(status); -+ if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); -+ else ptrace(PTRACE_SYSCALL, pid, 0, sig); -+ } -+} -+ -+void fake_child_exit(void) -+{ -+ int status, pid; -+ -+ child_proxy(1, W_EXITCODE(0, 0)); -+ while(debugger.waiting == 1){ -+ pid = waitpid(debugger.pid, &status, WUNTRACED); -+ if(pid != debugger.pid){ -+ printk("fake_child_exit - waitpid failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ debugger_proxy(status, debugger.pid); -+ } -+ pid = waitpid(debugger.pid, &status, WUNTRACED); -+ if(pid != debugger.pid){ -+ printk("fake_child_exit - waitpid failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) -+ printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", -+ errno); -+} -+ -+char gdb_init_string[] = -+"att 1 \n\ -+b panic \n\ -+b stop \n\ -+handle SIGWINCH nostop noprint pass \n\ -+"; -+ -+int start_debugger(char *prog, int startup, int stop, int *fd_out) -+{ -+ int slave, child; -+ -+ slave = open_gdb_chan(); -+ child = fork(); -+ if(child == 0){ -+ char *tempname = NULL; -+ int fd; -+ -+ if(setsid() < 0) perror("setsid"); -+ if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || -+ (dup2(slave, 2) < 0)){ -+ printk("start_debugger : dup2 failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ if(ioctl(0, TIOCSCTTY, 0) < 0){ -+ printk("start_debugger : TIOCSCTTY failed, " -+ "errno = %d\n", errno); -+ exit(1); -+ } -+ if(tcsetpgrp (1, os_getpid()) < 0){ -+ printk("start_debugger : tcsetpgrp failed, " -+ "errno = %d\n", errno); -+#ifdef notdef -+ exit(1); -+#endif -+ } -+ fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); -+ if(fd < 0){ -+ printk("start_debugger : make_tempfile failed," -+ "err = %d\n", -fd); -+ exit(1); -+ } -+ os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); -+ if(startup){ -+ if(stop){ -+ os_write_file(fd, "b start_kernel\n", -+ strlen("b start_kernel\n")); -+ } -+ os_write_file(fd, "c\n", strlen("c\n")); -+ } -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ printk("start_debugger : PTRACE_TRACEME failed, " -+ "errno = %d\n", errno); -+ exit(1); -+ } -+ execlp("gdb", "gdb", "--command", tempname, prog, NULL); -+ printk("start_debugger : exec of gdb failed, errno = %d\n", -+ errno); -+ } -+ if(child < 0){ -+ printk("start_debugger : fork for gdb failed, errno = %d\n", -+ errno); -+ return(-1); -+ } -+ *fd_out = slave; -+ return(child); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/ptproxy.h um/arch/um/kernel/tt/ptproxy/ptproxy.h ---- orig/arch/um/kernel/tt/ptproxy/ptproxy.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/ptproxy.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,61 @@ -+/********************************************************************** -+ptproxy.h -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#ifndef __PTPROXY_H -+#define __PTPROXY_H -+ -+#include <sys/types.h> -+ -+typedef struct debugger debugger_state; -+typedef struct debugee debugee_state; -+ -+struct debugger -+{ -+ pid_t pid; -+ int wait_options; -+ int *wait_status_ptr; -+ unsigned int waiting : 1; -+ unsigned int real_wait : 1; -+ unsigned int expecting_child : 1; -+ int (*handle_trace) (debugger_state *, pid_t); -+ -+ debugee_state *debugee; -+}; -+ -+struct debugee -+{ -+ pid_t pid; -+ int wait_status; -+ unsigned int died : 1; -+ unsigned int event : 1; -+ unsigned int stopped : 1; -+ unsigned int trace_singlestep : 1; -+ unsigned int trace_syscall : 1; -+ unsigned int traced : 1; -+ unsigned int zombie : 1; -+ unsigned int in_context : 1; -+}; -+ -+extern int debugger_syscall(debugger_state *debugger, pid_t pid); -+extern int debugger_normal_return (debugger_state *debugger, pid_t unused); -+ -+extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, -+ int *strace_out); -+extern void debugger_cancelled_return(debugger_state *debugger, int result); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/ptrace.c um/arch/um/kernel/tt/ptproxy/ptrace.c ---- orig/arch/um/kernel/tt/ptproxy/ptrace.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/ptrace.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,239 @@ -+/********************************************************************** -+ptrace.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+Jeff Dike (jdike@karaya.com) : Modified for integration into uml -+**********************************************************************/ -+ -+#include <errno.h> -+#include <unistd.h> -+#include <signal.h> -+#include <sys/types.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <asm/ptrace.h> -+ -+#include "ptproxy.h" -+#include "debug.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+#include "tt.h" -+ -+long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, -+ long arg3, long arg4, pid_t child, int *ret) -+{ -+ sigset_t relay; -+ long result; -+ int status; -+ -+ *ret = 0; -+ if(debugger->debugee->died) return(-ESRCH); -+ -+ switch(arg1){ -+ case PTRACE_ATTACH: -+ if(debugger->debugee->traced) return(-EPERM); -+ -+ debugger->debugee->pid = arg2; -+ debugger->debugee->traced = 1; -+ -+ if(is_valid_pid(arg2) && (arg2 != child)){ -+ debugger->debugee->in_context = 0; -+ kill(arg2, SIGSTOP); -+ debugger->debugee->event = 1; -+ debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); -+ } -+ else { -+ debugger->debugee->in_context = 1; -+ if(debugger->debugee->stopped) -+ child_proxy(child, W_STOPCODE(SIGSTOP)); -+ else kill(child, SIGSTOP); -+ } -+ -+ return(0); -+ -+ case PTRACE_DETACH: -+ if(!debugger->debugee->traced) return(-EPERM); -+ -+ debugger->debugee->traced = 0; -+ debugger->debugee->pid = 0; -+ if(!debugger->debugee->in_context) -+ kill(child, SIGCONT); -+ -+ return(0); -+ -+ case PTRACE_CONT: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ *ret = PTRACE_CONT; -+ return(ptrace(PTRACE_CONT, child, arg3, arg4)); -+ -+#ifdef UM_HAVE_GETFPREGS -+ case PTRACE_GETFPREGS: -+ { -+ long regs[FP_FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETFPREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, -+ regs[i]); -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_GETFPXREGS -+ case PTRACE_GETFPXREGS: -+ { -+ long regs[FPX_FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, -+ regs[i]); -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_GETREGS -+ case PTRACE_GETREGS: -+ { -+ long regs[FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace (PTRACE_POKEDATA, debugger->pid, -+ arg4 + 4 * i, regs[i]); -+ return(result); -+ } -+ break; -+#endif -+ -+ case PTRACE_KILL: -+ result = ptrace(PTRACE_KILL, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ -+ case PTRACE_PEEKDATA: -+ case PTRACE_PEEKTEXT: -+ case PTRACE_PEEKUSER: -+ /* The value being read out could be -1, so we have to -+ * check errno to see if there's an error, and zero it -+ * beforehand so we're not faked out by an old error -+ */ -+ -+ errno = 0; -+ result = ptrace(arg1, child, arg3, 0); -+ if((result == -1) && (errno != 0)) return(-errno); -+ -+ result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ -+ case PTRACE_POKEDATA: -+ case PTRACE_POKETEXT: -+ case PTRACE_POKEUSER: -+ result = ptrace(arg1, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ if(arg1 == PTRACE_POKEUSER) ptrace_pokeuser(arg3, arg4); -+ return(result); -+ -+#ifdef UM_HAVE_SETFPREGS -+ case PTRACE_SETFPREGS: -+ { -+ long regs[FP_FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETFPREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_SETFPXREGS -+ case PTRACE_SETFPXREGS: -+ { -+ long regs[FPX_FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_SETREGS -+ case PTRACE_SETREGS: -+ { -+ long regs[FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+ case PTRACE_SINGLESTEP: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ sigemptyset(&relay); -+ sigaddset(&relay, SIGSEGV); -+ sigaddset(&relay, SIGILL); -+ sigaddset(&relay, SIGBUS); -+ result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, -+ &relay); -+ child_proxy(child, status); -+ return(result); -+ -+ case PTRACE_SYSCALL: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ *ret = PTRACE_SYSCALL; -+ return(result); -+ -+ case PTRACE_TRACEME: -+ default: -+ return(-EINVAL); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/sysdep.c um/arch/um/kernel/tt/ptproxy/sysdep.c ---- orig/arch/um/kernel/tt/ptproxy/sysdep.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/sysdep.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,72 @@ -+/********************************************************************** -+sysdep.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#include <stdio.h> -+#include <string.h> -+#include <stdlib.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/types.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+#include <linux/unistd.h> -+#include "ptrace_user.h" -+#include "user_util.h" -+#include "user.h" -+ -+int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, -+ long *arg5) -+{ -+ *arg1 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG1_OFFSET, 0); -+ *arg2 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG2_OFFSET, 0); -+ *arg3 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG3_OFFSET, 0); -+ *arg4 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG4_OFFSET, 0); -+ *arg5 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG5_OFFSET, 0); -+ return(ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0)); -+} -+ -+void syscall_cancel(pid_t pid, int result) -+{ -+ if((ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid) < 0) || -+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || -+ (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || -+ (ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || -+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) -+ printk("ptproxy: couldn't cancel syscall: errno = %d\n", -+ errno); -+} -+ -+void syscall_set_result(pid_t pid, long result) -+{ -+ ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result); -+} -+ -+void syscall_continue(pid_t pid) -+{ -+ ptrace(PTRACE_SYSCALL, pid, 0, 0); -+} -+ -+int syscall_pause(pid_t pid) -+{ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ -+ printk("syscall_change - ptrace failed, errno = %d\n", errno); -+ return(-1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/sysdep.h um/arch/um/kernel/tt/ptproxy/sysdep.h ---- orig/arch/um/kernel/tt/ptproxy/sysdep.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/sysdep.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,25 @@ -+/********************************************************************** -+sysdep.h -+ -+Copyright (C) 1999 Lars Brinkhoff. -+Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+See the file COPYING for licensing terms and conditions. -+**********************************************************************/ -+ -+extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, -+ long *arg4, long *arg5); -+extern void syscall_cancel (pid_t pid, long result); -+extern void syscall_set_result (pid_t pid, long result); -+extern void syscall_continue (pid_t pid); -+extern int syscall_pause(pid_t pid); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/wait.c um/arch/um/kernel/tt/ptproxy/wait.c ---- orig/arch/um/kernel/tt/ptproxy/wait.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/wait.c 2004-01-17 05:27:18.000000000 -0500 -@@ -0,0 +1,88 @@ -+/********************************************************************** -+wait.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+**********************************************************************/ -+ -+#include <errno.h> -+#include <signal.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+ -+#include "ptproxy.h" -+#include "sysdep.h" -+#include "wait.h" -+#include "user_util.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/ptrace_user.h" -+#include "sysdep/sigcontext.h" -+ -+int proxy_wait_return(struct debugger *debugger, pid_t unused) -+{ -+ debugger->waiting = 0; -+ -+ if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ -+ debugger_cancelled_return(debugger, -ECHILD); -+ return(0); -+ } -+ -+ if(debugger->debugee->zombie && debugger->debugee->event) -+ debugger->debugee->died = 1; -+ -+ if(debugger->debugee->event){ -+ debugger->debugee->event = 0; -+ ptrace(PTRACE_POKEDATA, debugger->pid, -+ debugger->wait_status_ptr, -+ debugger->debugee->wait_status); -+ /* if (wait4) -+ ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ -+ debugger_cancelled_return(debugger, debugger->debugee->pid); -+ return(0); -+ } -+ -+ /* pause will return -EINTR, which happens to be right for wait */ -+ debugger_normal_return(debugger, -1); -+ return(0); -+} -+ -+int parent_wait_return(struct debugger *debugger, pid_t unused) -+{ -+ return(debugger_normal_return(debugger, -1)); -+} -+ -+int real_wait_return(struct debugger *debugger) -+{ -+ unsigned long ip; -+ int pid; -+ -+ pid = debugger->pid; -+ -+ ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); -+ IP_RESTART_SYSCALL(ip); -+ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0) -+ tracer_panic("real_wait_return : Failed to restart system " -+ "call, errno = %d\n", errno); -+ -+ if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || -+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || -+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || -+ debugger_normal_return(debugger, -1)) -+ tracer_panic("real_wait_return : gdb failed to wait, " -+ "errno = %d\n", errno); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/ptproxy/wait.h um/arch/um/kernel/tt/ptproxy/wait.h ---- orig/arch/um/kernel/tt/ptproxy/wait.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/ptproxy/wait.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,15 @@ -+/********************************************************************** -+wait.h -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#ifndef __PTPROXY_WAIT_H -+#define __PTPROXY_WAIT_H -+ -+extern int proxy_wait_return(struct debugger *debugger, pid_t unused); -+extern int real_wait_return(struct debugger *debugger); -+extern int parent_wait_return(struct debugger *debugger, pid_t unused); -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/syscall_kern.c um/arch/um/kernel/tt/syscall_kern.c ---- orig/arch/um/kernel/tt/syscall_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/syscall_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/types.h" -+#include "linux/utime.h" -+#include "linux/sys.h" -+#include "asm/unistd.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+static inline int check_area(void *ptr, int size) -+{ -+ return(verify_area(VERIFY_WRITE, ptr, size)); -+} -+ -+static int check_readlink(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ UPT_SYSCALL_ARG2(®s->regs))); -+} -+ -+static int check_utime(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct utimbuf))); -+} -+ -+static int check_oldstat(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct __old_kernel_stat))); -+} -+ -+static int check_stat(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct stat))); -+} -+ -+static int check_stat64(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct stat64))); -+} -+ -+struct bogus { -+ int kernel_ds; -+ int (*check_params)(struct pt_regs *); -+}; -+ -+struct bogus this_is_bogus[256] = { -+ [ __NR_mknod ] = { 1, NULL }, -+ [ __NR_mkdir ] = { 1, NULL }, -+ [ __NR_rmdir ] = { 1, NULL }, -+ [ __NR_unlink ] = { 1, NULL }, -+ [ __NR_symlink ] = { 1, NULL }, -+ [ __NR_link ] = { 1, NULL }, -+ [ __NR_rename ] = { 1, NULL }, -+ [ __NR_umount ] = { 1, NULL }, -+ [ __NR_mount ] = { 1, NULL }, -+ [ __NR_pivot_root ] = { 1, NULL }, -+ [ __NR_chdir ] = { 1, NULL }, -+ [ __NR_chroot ] = { 1, NULL }, -+ [ __NR_open ] = { 1, NULL }, -+ [ __NR_quotactl ] = { 1, NULL }, -+ [ __NR_sysfs ] = { 1, NULL }, -+ [ __NR_readlink ] = { 1, check_readlink }, -+ [ __NR_acct ] = { 1, NULL }, -+ [ __NR_execve ] = { 1, NULL }, -+ [ __NR_uselib ] = { 1, NULL }, -+ [ __NR_statfs ] = { 1, NULL }, -+ [ __NR_truncate ] = { 1, NULL }, -+ [ __NR_access ] = { 1, NULL }, -+ [ __NR_chmod ] = { 1, NULL }, -+ [ __NR_chown ] = { 1, NULL }, -+ [ __NR_lchown ] = { 1, NULL }, -+ [ __NR_utime ] = { 1, check_utime }, -+ [ __NR_oldlstat ] = { 1, check_oldstat }, -+ [ __NR_oldstat ] = { 1, check_oldstat }, -+ [ __NR_stat ] = { 1, check_stat }, -+ [ __NR_lstat ] = { 1, check_stat }, -+ [ __NR_stat64 ] = { 1, check_stat64 }, -+ [ __NR_lstat64 ] = { 1, check_stat64 }, -+ [ __NR_chown32 ] = { 1, NULL }, -+}; -+ -+/* sys_utimes */ -+ -+static int check_bogosity(struct pt_regs *regs) -+{ -+ struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(®s->regs)]; -+ -+ if(!bogon->kernel_ds) return(0); -+ if(bogon->check_params && (*bogon->check_params)(regs)) -+ return(-EFAULT); -+ set_fs(KERNEL_DS); -+ return(0); -+} -+ -+extern syscall_handler_t *sys_call_table[]; -+ -+long execute_syscall_tt(void *r) -+{ -+ struct pt_regs *regs = r; -+ long res; -+ int syscall; -+ -+ current->thread.nsyscalls++; -+ nsyscalls++; -+ syscall = UPT_SYSCALL_NR(®s->regs); -+ -+ if((syscall >= NR_syscalls) || (syscall < 0)) -+ res = -ENOSYS; -+ else if(honeypot && check_bogosity(regs)) -+ res = -EFAULT; -+ else res = EXECUTE_SYSCALL(syscall, regs); -+ -+ set_fs(USER_DS); -+ -+ if(current->thread.mode.tt.singlestep_syscall){ -+ current->thread.mode.tt.singlestep_syscall = 0; -+ current->ptrace &= ~PT_DTRACE; -+ force_sig(SIGTRAP, current); -+ } -+ -+ return(res); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/syscall_user.c um/arch/um/kernel/tt/syscall_user.c ---- orig/arch/um/kernel/tt/syscall_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/syscall_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,89 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/ptrace.h> -+#include <asm/unistd.h> -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "ptrace_user.h" -+#include "task.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "syscall_user.h" -+#include "tt.h" -+ -+/* XXX Bogus */ -+#define ERESTARTSYS 512 -+#define ERESTARTNOINTR 513 -+#define ERESTARTNOHAND 514 -+ -+void syscall_handler_tt(int sig, union uml_pt_regs *regs) -+{ -+ void *sc; -+ long result; -+ int index, syscall; -+ -+ syscall = UPT_SYSCALL_NR(regs); -+ sc = UPT_SC(regs); -+ SC_START_SYSCALL(sc); -+ -+ index = record_syscall_start(syscall); -+ syscall_trace(); -+ result = execute_syscall(regs); -+ -+ /* regs->sc may have changed while the system call ran (there may -+ * have been an interrupt or segfault), so it needs to be refreshed. -+ */ -+ UPT_SC(regs) = sc; -+ -+ SC_SET_SYSCALL_RETURN(sc, result); -+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || -+ (result == -ERESTARTNOINTR)) -+ do_signal(result); -+ -+ syscall_trace(); -+ record_syscall_end(index, result); -+} -+ -+int do_syscall(void *task, int pid) -+{ -+ unsigned long proc_regs[FRAME_SIZE]; -+ union uml_pt_regs *regs; -+ int syscall; -+ -+ if(ptrace_getregs(pid, proc_regs) < 0) -+ tracer_panic("Couldn't read registers"); -+ syscall = PT_SYSCALL_NR(proc_regs); -+ -+ regs = TASK_REGS(task); -+ UPT_SYSCALL_NR(regs) = syscall; -+ -+ if(syscall < 1) return(0); -+ -+ if((syscall != __NR_sigreturn) && -+ ((unsigned long *) PT_IP(proc_regs) >= &_stext) && -+ ((unsigned long *) PT_IP(proc_regs) <= &_etext)) -+ tracer_panic("I'm tracing myself and I can't get out"); -+ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid) < 0) -+ tracer_panic("do_syscall : Nullifying syscall failed, " -+ "errno = %d", errno); -+ return(1); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/sys-i386/Makefile um/arch/um/kernel/tt/sys-i386/Makefile ---- orig/arch/um/kernel/tt/sys-i386/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/sys-i386/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = sys-i386.o -+ -+obj-y = sigcontext.o -+ -+USER_OBJS = sigcontext.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/sys-i386/sigcontext.c um/arch/um/kernel/tt/sys-i386/sigcontext.c ---- orig/arch/um/kernel/tt/sys-i386/sigcontext.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/sys-i386/sigcontext.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,60 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <asm/sigcontext.h> -+#include "kern_util.h" -+#include "sysdep/frame.h" -+ -+int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data) -+{ -+ struct arch_frame_data *arch = data; -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ struct _fpstate *to_fp, *from_fp; -+ unsigned long sigs; -+ int err; -+ -+ to_fp = to->fpstate; -+ from_fp = from->fpstate; -+ sigs = to->oldmask; -+ err = copy_from_user_proc(to, from, sizeof(*to)); -+ to->oldmask = sigs; -+ if(to_fp != NULL){ -+ err |= copy_from_user_proc(&to->fpstate, &to_fp, -+ sizeof(to->fpstate)); -+ err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size); -+ } -+ return(err); -+} -+ -+int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data) -+{ -+ struct arch_frame_data *arch = data; -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ struct _fpstate *to_fp, *from_fp; -+ int err; -+ -+ to_fp = (struct _fpstate *) -+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -+ from_fp = from->fpstate; -+ err = copy_to_user_proc(to, from, sizeof(*to)); -+ if(from_fp != NULL){ -+ err |= copy_to_user_proc(&to->fpstate, &to_fp, -+ sizeof(to->fpstate)); -+ err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size); -+ } -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/time.c um/arch/um/kernel/tt/time.c ---- orig/arch/um/kernel/tt/time.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/time.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include <sys/time.h> -+#include <time_user.h> -+#include "process.h" -+#include "user.h" -+ -+void user_time_init_tt(void) -+{ -+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/tlb.c um/arch/um/kernel/tt/tlb.c ---- orig/arch/um/kernel/tt/tlb.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/tlb.c 2003-11-13 00:40:57.000000000 -0500 -@@ -0,0 +1,220 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "os.h" -+ -+static void fix_range(struct mm_struct *mm, unsigned long start_addr, -+ unsigned long end_addr, int force) -+{ -+ pgd_t *npgd; -+ pmd_t *npmd; -+ pte_t *npte; -+ unsigned long addr; -+ int r, w, x, err; -+ -+ if((current->thread.mode.tt.extern_pid != -1) && -+ (current->thread.mode.tt.extern_pid != os_getpid())) -+ panic("fix_range fixing wrong address space, current = 0x%p", -+ current); -+ if(mm == NULL) return; -+ for(addr=start_addr;addr<end_addr;){ -+ if(addr == TASK_SIZE){ -+ /* Skip over kernel text, kernel data, and physical -+ * memory, which don't have ptes, plus kernel virtual -+ * memory, which is flushed separately, and remap -+ * the process stack. The only way to get here is -+ * if (end_addr == STACK_TOP) > TASK_SIZE, which is -+ * only true in the honeypot case. -+ */ -+ addr = STACK_TOP - ABOVE_KMEM; -+ continue; -+ } -+ npgd = pgd_offset(mm, addr); -+ npmd = pmd_offset(npgd, addr); -+ if(pmd_present(*npmd)){ -+ npte = pte_offset(npmd, addr); -+ r = pte_read(*npte); -+ w = pte_write(*npte); -+ x = pte_exec(*npte); -+ if(!pte_dirty(*npte)) w = 0; -+ if(!pte_young(*npte)){ -+ r = 0; -+ w = 0; -+ } -+ if(force || pte_newpage(*npte)){ -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*npte)) -+ map_memory(addr, -+ pte_val(*npte) & PAGE_MASK, -+ PAGE_SIZE, r, w, x); -+ } -+ else if(pte_newprot(*npte)){ -+ protect_memory(addr, PAGE_SIZE, r, w, x, 1); -+ } -+ *npte = pte_mkuptodate(*npte); -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(force || pmd_newpage(*npmd)){ -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ pmd_mkuptodate(*npmd); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+atomic_t vmchange_seq = ATOMIC_INIT(1); -+ -+static void flush_kernel_vm_range(unsigned long start, unsigned long end, -+ int update_seq) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ int updated = 0, err; -+ -+ mm = &init_mm; -+ for(addr = start; addr < end;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte) || pte_newpage(*pte)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*pte)) -+ map_memory(addr, -+ pte_val(*pte) & PAGE_MASK, -+ PAGE_SIZE, 1, 1, 1); -+ } -+ else if(pte_newprot(*pte)){ -+ updated = 1; -+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); -+ } -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(pmd_newpage(*pmd)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+ if(updated && update_seq) atomic_inc(&vmchange_seq); -+} -+ -+static void protect_vm_page(unsigned long addr, int w, int must_succeed) -+{ -+ int err; -+ -+ err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed); -+ if(err == 0) return; -+ else if((err == -EFAULT) || (err == -ENOMEM)){ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1); -+ protect_vm_page(addr, w, 1); -+ } -+ else panic("protect_vm_page : protect failed, errno = %d\n", err); -+} -+ -+void mprotect_kernel_vm(int w) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ -+ mm = &init_mm; -+ for(addr = start_vm; addr < end_vm;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(pte_present(*pte)) protect_vm_page(addr, w, 0); -+ addr += PAGE_SIZE; -+ } -+ else addr += PMD_SIZE; -+ } -+} -+ -+void flush_tlb_kernel_vm_tt(void) -+{ -+ flush_kernel_vm_range(start_vm, end_vm, 1); -+} -+ -+void __flush_tlb_one_tt(unsigned long addr) -+{ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1); -+} -+ -+void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ if(mm != current->mm) return; -+ -+ /* Assumes that the range start ... end is entirely within -+ * either process memory or kernel vm -+ */ -+ if((start >= start_vm) && (start < end_vm)) -+ flush_kernel_vm_range(start, end, 1); -+ else fix_range(mm, start, end, 0); -+} -+ -+void flush_tlb_mm_tt(struct mm_struct *mm) -+{ -+ unsigned long seq; -+ -+ if(mm != current->mm) return; -+ -+ fix_range(mm, 0, STACK_TOP, 0); -+ -+ seq = atomic_read(&vmchange_seq); -+ if(current->thread.mode.tt.vm_seq == seq) return; -+ current->thread.mode.tt.vm_seq = seq; -+ flush_kernel_vm_range(start_vm, end_vm, 0); -+} -+ -+void force_flush_all_tt(void) -+{ -+ fix_range(current->mm, 0, STACK_TOP, 1); -+ flush_kernel_vm_range(start_vm, end_vm, 0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/tracer.c um/arch/um/kernel/tt/tracer.c ---- orig/arch/um/kernel/tt/tracer.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/tracer.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,454 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sched.h> -+#include <string.h> -+#include <sys/mman.h> -+#include <sys/ptrace.h> -+#include <sys/time.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "sysdep/sigcontext.h" -+#include "os.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "process.h" -+#include "kern_util.h" -+#include "frame.h" -+#include "chan_user.h" -+#include "ptrace_user.h" -+#include "mode.h" -+#include "tt.h" -+ -+static int tracer_winch[2]; -+ -+int is_tracer_winch(int pid, int fd, void *data) -+{ -+ if(pid != tracing_pid) -+ return(0); -+ -+ register_winch_irq(tracer_winch[0], fd, -1, data); -+ return(1); -+} -+ -+static void tracer_winch_handler(int sig) -+{ -+ int n; -+ char c = 1; -+ -+ n = os_write_file(tracer_winch[1], &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("tracer_winch_handler - write failed, err = %d\n", -n); -+} -+ -+/* Called only by the tracing thread during initialization */ -+ -+static void setup_tracer_winch(void) -+{ -+ int err; -+ -+ err = os_pipe(tracer_winch, 1, 1); -+ if(err < 0){ -+ printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); -+ return; -+ } -+ signal(SIGWINCH, tracer_winch_handler); -+} -+ -+void attach_process(int pid) -+{ -+ if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || -+ (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) -+ tracer_panic("OP_FORK failed to attach pid"); -+ wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) -+ tracer_panic("OP_FORK failed to continue process"); -+} -+ -+void tracer_panic(char *format, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, format); -+ vprintf(format, ap); -+ printf("\n"); -+ while(1) pause(); -+} -+ -+static void tracer_segv(int sig, struct sigcontext sc) -+{ -+ printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", -+ SC_FAULT_ADDR(&sc), SC_IP(&sc)); -+ while(1) -+ pause(); -+} -+ -+/* Changed early in boot, and then only read */ -+int debug = 0; -+int debug_stop = 1; -+int debug_parent = 0; -+int honeypot = 0; -+ -+static int signal_tramp(void *arg) -+{ -+ int (*proc)(void *); -+ -+ if(honeypot && munmap((void *) (host_task_size - 0x10000000), -+ 0x10000000)) -+ panic("Unmapping stack failed"); -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) -+ panic("ptrace PTRACE_TRACEME failed"); -+ os_stop_process(os_getpid()); -+ change_sig(SIGWINCH, 0); -+ signal(SIGUSR1, SIG_IGN); -+ change_sig(SIGCHLD, 0); -+ signal(SIGSEGV, (__sighandler_t) sig_handler); -+ set_cmdline("(idle thread)"); -+ set_init_pid(os_getpid()); -+ proc = arg; -+ return((*proc)(NULL)); -+} -+ -+static void sleeping_process_signal(int pid, int sig) -+{ -+ switch(sig){ -+ /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is -+ * right because the process must be in the kernel already. -+ */ -+ case SIGCONT: -+ case SIGTSTP: -+ if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) -+ tracer_panic("sleeping_process_signal : Failed to " -+ "continue pid %d, signal = %d, " -+ "errno = %d\n", pid, sig, errno); -+ break; -+ -+ /* This happens when the debugger (e.g. strace) is doing system call -+ * tracing on the kernel. During a context switch, the current task -+ * will be set to the incoming process and the outgoing process will -+ * hop into write and then read. Since it's not the current process -+ * any more, the trace of those will land here. So, we need to just -+ * PTRACE_SYSCALL it. -+ */ -+ case SIGTRAP: -+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) -+ tracer_panic("sleeping_process_signal : Failed to " -+ "PTRACE_SYSCALL pid %d, errno = %d\n", -+ pid, errno); -+ break; -+ case SIGSTOP: -+ break; -+ default: -+ tracer_panic("sleeping process %d got unexpected " -+ "signal : %d\n", pid, sig); -+ break; -+ } -+} -+ -+/* Accessed only by the tracing thread */ -+int debugger_pid = -1; -+int debugger_parent = -1; -+int debugger_fd = -1; -+int gdb_pid = -1; -+ -+struct { -+ int pid; -+ int signal; -+ unsigned long addr; -+ struct timeval time; -+} signal_record[1024][32]; -+ -+int signal_index[32]; -+int nsignals = 0; -+int debug_trace = 0; -+extern int io_nsignals, io_count, intr_count; -+ -+extern void signal_usr1(int sig); -+ -+int tracing_pid = -1; -+ -+int tracer(int (*init_proc)(void *), void *sp) -+{ -+ void *task = NULL; -+ unsigned long eip = 0; -+ int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; -+ int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; -+ -+ capture_signal_stack(); -+ signal(SIGPIPE, SIG_IGN); -+ setup_tracer_winch(); -+ tracing_pid = os_getpid(); -+ printf("tracing thread pid = %d\n", tracing_pid); -+ -+ pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); -+ n = waitpid(pid, &status, WUNTRACED); -+ if(n < 0){ -+ printf("waitpid on idle thread failed, errno = %d\n", errno); -+ exit(1); -+ } -+ if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ -+ printf("Failed to continue idle thread, errno = %d\n", errno); -+ exit(1); -+ } -+ -+ signal(SIGSEGV, (sighandler_t) tracer_segv); -+ signal(SIGUSR1, signal_usr1); -+ if(debug_trace){ -+ printf("Tracing thread pausing to be attached\n"); -+ stop(); -+ } -+ if(debug){ -+ if(gdb_pid != -1) -+ debugger_pid = attach_debugger(pid, gdb_pid, 1); -+ else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); -+ if(debug_parent){ -+ debugger_parent = os_process_parent(debugger_pid); -+ init_parent_proxy(debugger_parent); -+ err = attach(debugger_parent); -+ if(err){ -+ printf("Failed to attach debugger parent %d, " -+ "errno = %d\n", debugger_parent, -err); -+ debugger_parent = -1; -+ } -+ else { -+ if(ptrace(PTRACE_SYSCALL, debugger_parent, -+ 0, 0) < 0){ -+ printf("Failed to continue debugger " -+ "parent, errno = %d\n", errno); -+ debugger_parent = -1; -+ } -+ } -+ } -+ } -+ set_cmdline("(tracing thread)"); -+ while(1){ -+ pid = waitpid(-1, &status, WUNTRACED); -+ if(pid <= 0){ -+ if(errno != ECHILD){ -+ printf("wait failed - errno = %d\n", errno); -+ } -+ continue; -+ } -+ if(pid == debugger_pid){ -+ int cont = 0; -+ -+ if(WIFEXITED(status) || WIFSIGNALED(status)) -+ debugger_pid = -1; -+ /* XXX Figure out how to deal with gdb and SMP */ -+ else cont = debugger_signal(status, cpu_tasks[0].pid); -+ if(cont == PTRACE_SYSCALL) strace = 1; -+ continue; -+ } -+ else if(pid == debugger_parent){ -+ debugger_parent_signal(status, pid); -+ continue; -+ } -+ nsignals++; -+ if(WIFEXITED(status)) ; -+#ifdef notdef -+ { -+ printf("Child %d exited with status %d\n", pid, -+ WEXITSTATUS(status)); -+ } -+#endif -+ else if(WIFSIGNALED(status)){ -+ sig = WTERMSIG(status); -+ if(sig != 9){ -+ printf("Child %d exited with signal %d\n", pid, -+ sig); -+ } -+ } -+ else if(WIFSTOPPED(status)){ -+ proc_id = pid_to_processor_id(pid); -+ sig = WSTOPSIG(status); -+ if(signal_index[proc_id] == 1024){ -+ signal_index[proc_id] = 0; -+ last_index = 1023; -+ } -+ else last_index = signal_index[proc_id] - 1; -+ if(((sig == SIGPROF) || (sig == SIGVTALRM) || -+ (sig == SIGALRM)) && -+ (signal_record[proc_id][last_index].signal == sig)&& -+ (signal_record[proc_id][last_index].pid == pid)) -+ signal_index[proc_id] = last_index; -+ signal_record[proc_id][signal_index[proc_id]].pid = pid; -+ gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); -+ eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); -+ signal_record[proc_id][signal_index[proc_id]].addr = eip; -+ signal_record[proc_id][signal_index[proc_id]++].signal = sig; -+ -+ if(proc_id == -1){ -+ sleeping_process_signal(pid, sig); -+ continue; -+ } -+ -+ task = cpu_tasks[proc_id].task; -+ tracing = is_tracing(task); -+ old_tracing = tracing; -+ -+ switch(sig){ -+ case SIGUSR1: -+ sig = 0; -+ op = do_proc_op(task, proc_id); -+ switch(op){ -+ case OP_TRACE_ON: -+ arch_leave_kernel(task, pid); -+ tracing = 1; -+ break; -+ case OP_REBOOT: -+ case OP_HALT: -+ unmap_physmem(); -+ kmalloc_ok = 0; -+ ptrace(PTRACE_KILL, pid, 0, 0); -+ return(op == OP_REBOOT); -+ case OP_NONE: -+ printf("Detaching pid %d\n", pid); -+ detach(pid, SIGSTOP); -+ continue; -+ default: -+ break; -+ } -+ /* OP_EXEC switches host processes on us, -+ * we want to continue the new one. -+ */ -+ pid = cpu_tasks[proc_id].pid; -+ break; -+ case SIGTRAP: -+ if(!tracing && (debugger_pid != -1)){ -+ child_signal(pid, status); -+ continue; -+ } -+ tracing = 0; -+ if(do_syscall(task, pid)) sig = SIGUSR2; -+ else clear_singlestep(task); -+ break; -+ case SIGPROF: -+ if(tracing) sig = 0; -+ break; -+ case SIGCHLD: -+ case SIGHUP: -+ sig = 0; -+ break; -+ case SIGSEGV: -+ case SIGIO: -+ case SIGALRM: -+ case SIGVTALRM: -+ case SIGFPE: -+ case SIGBUS: -+ case SIGILL: -+ case SIGWINCH: -+ default: -+ tracing = 0; -+ break; -+ } -+ set_tracing(task, tracing); -+ -+ if(!tracing && old_tracing) -+ arch_enter_kernel(task, pid); -+ -+ if(!tracing && (debugger_pid != -1) && (sig != 0) && -+ (sig != SIGALRM) && (sig != SIGVTALRM) && -+ (sig != SIGSEGV) && (sig != SIGTRAP) && -+ (sig != SIGUSR2) && (sig != SIGIO) && -+ (sig != SIGFPE)){ -+ child_signal(pid, status); -+ continue; -+ } -+ -+ if(tracing){ -+ if(singlestepping_tt(task)) -+ cont_type = PTRACE_SINGLESTEP; -+ else cont_type = PTRACE_SYSCALL; -+ } -+ else cont_type = PTRACE_CONT; -+ -+ if((cont_type == PTRACE_CONT) && -+ (debugger_pid != -1) && strace) -+ cont_type = PTRACE_SYSCALL; -+ -+ if(ptrace(cont_type, pid, 0, sig) != 0){ -+ tracer_panic("ptrace failed to continue " -+ "process - errno = %d\n", -+ errno); -+ } -+ } -+ } -+ return(0); -+} -+ -+static int __init uml_debug_setup(char *line, int *add) -+{ -+ char *next; -+ -+ debug = 1; -+ *add = 0; -+ if(*line != '=') return(0); -+ line++; -+ -+ while(line != NULL){ -+ next = strchr(line, ','); -+ if(next) *next++ = '\0'; -+ -+ if(!strcmp(line, "go")) debug_stop = 0; -+ else if(!strcmp(line, "parent")) debug_parent = 1; -+ else printf("Unknown debug option : '%s'\n", line); -+ -+ line = next; -+ } -+ return(0); -+} -+ -+__uml_setup("debug", uml_debug_setup, -+"debug\n" -+" Starts up the kernel under the control of gdb. See the \n" -+" kernel debugging tutorial and the debugging session pages\n" -+" at http://user-mode-linux.sourceforge.net/ for more information.\n\n" -+); -+ -+static int __init uml_debugtrace_setup(char *line, int *add) -+{ -+ debug_trace = 1; -+ return 0; -+} -+__uml_setup("debugtrace", uml_debugtrace_setup, -+"debugtrace\n" -+" Causes the tracing thread to pause until it is attached by a\n" -+" debugger and continued. This is mostly for debugging crashes\n" -+" early during boot, and should be pretty much obsoleted by\n" -+" the debug switch.\n\n" -+); -+ -+static int __init uml_honeypot_setup(char *line, int *add) -+{ -+ jail_setup("", add); -+ honeypot = 1; -+ return 0; -+} -+__uml_setup("honeypot", uml_honeypot_setup, -+"honeypot\n" -+" This makes UML put process stacks in the same location as they are\n" -+" on the host, allowing expoits such as stack smashes to work against\n" -+" UML. This implies 'jail'.\n\n" -+); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/trap_user.c um/arch/um/kernel/tt/trap_user.c ---- orig/arch/um/kernel/tt/trap_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/trap_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "task.h" -+#include "tt.h" -+ -+void sig_handler_common_tt(int sig, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct tt_regs save_regs, *r; -+ struct signal_info *info; -+ int save_errno = errno, is_user; -+ -+ unprotect_kernel_mem(); -+ -+ r = &TASK_REGS(get_current())->tt; -+ save_regs = *r; -+ is_user = user_context(SC_SP(sc)); -+ r->sc = sc; -+ if(sig != SIGUSR2) -+ r->syscall = -1; -+ -+ change_sig(SIGUSR1, 1); -+ info = &sig_info[sig]; -+ if(!info->is_irq) unblock_signals(); -+ -+ (*info->handler)(sig, (union uml_pt_regs *) r); -+ -+ if(is_user){ -+ interrupt_end(); -+ block_signals(); -+ change_sig(SIGUSR1, 0); -+ set_user_mode(NULL); -+ } -+ *r = save_regs; -+ errno = save_errno; -+ if(is_user) protect_kernel_mem(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/uaccess.c um/arch/um/kernel/tt/uaccess.c ---- orig/arch/um/kernel/tt/uaccess.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/uaccess.c 2003-11-13 00:12:45.000000000 -0500 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "asm/uaccess.h" -+ -+int copy_from_user_tt(void *to, const void *from, int n) -+{ -+ if(!access_ok_tt(VERIFY_READ, from, n)) -+ return(n); -+ -+ return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int copy_to_user_tt(void *to, const void *from, int n) -+{ -+ if(!access_ok_tt(VERIFY_WRITE, to, n)) -+ return(n); -+ -+ return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int strncpy_from_user_tt(char *dst, const char *src, int count) -+{ -+ int n; -+ -+ if(!access_ok_tt(VERIFY_READ, src, 1)) -+ return(-EFAULT); -+ -+ n = __do_strncpy_from_user(dst, src, count, -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher); -+ if(n < 0) return(-EFAULT); -+ return(n); -+} -+ -+int __clear_user_tt(void *mem, int len) -+{ -+ return(__do_clear_user(mem, len, -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int clear_user_tt(void *mem, int len) -+{ -+ if(!access_ok_tt(VERIFY_WRITE, mem, len)) -+ return(len); -+ -+ return(__do_clear_user(mem, len, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int strnlen_user_tt(const void *str, int len) -+{ -+ return(__do_strnlen_user(str, len, -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/uaccess_user.c um/arch/um/kernel/tt/uaccess_user.c ---- orig/arch/um/kernel/tt/uaccess_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/uaccess_user.c 2004-01-31 02:48:29.000000000 -0500 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <setjmp.h> -+#include <string.h> -+#include "user_util.h" -+#include "uml_uaccess.h" -+#include "task.h" -+#include "kern_util.h" -+ -+int __do_copy_from_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, -+ __do_copy, &faulted); -+ TASK_REGS(get_current())->tt = save; -+ -+ if(!faulted) return(0); -+ else return(n - (fault - (unsigned long) from)); -+} -+ -+static void __do_strncpy(void *dst, const void *src, int count) -+{ -+ strncpy(dst, src, count); -+} -+ -+int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, -+ __do_strncpy, &faulted); -+ TASK_REGS(get_current())->tt = save; -+ -+ if(!faulted) return(strlen(dst)); -+ else return(-1); -+} -+ -+static void __do_clear(void *to, const void *from, int n) -+{ -+ memset(to, 0, n); -+} -+ -+int __do_clear_user(void *mem, unsigned long len, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, -+ __do_clear, &faulted); -+ TASK_REGS(get_current())->tt = save; -+ -+ if(!faulted) return(0); -+ else return(len - (fault - (unsigned long) mem)); -+} -+ -+int __do_strnlen_user(const char *str, unsigned long n, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ int ret; -+ unsigned long *faddrp = (unsigned long *)fault_addr; -+ sigjmp_buf jbuf; -+ -+ *fault_catcher = &jbuf; -+ if(sigsetjmp(jbuf, 1) == 0) -+ ret = strlen(str) + 1; -+ else ret = *faddrp - (unsigned long) str; -+ -+ *fault_addr = NULL; -+ *fault_catcher = NULL; -+ -+ TASK_REGS(get_current())->tt = save; -+ return ret; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tt/unmap.c um/arch/um/kernel/tt/unmap.c ---- orig/arch/um/kernel/tt/unmap.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tt/unmap.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <sys/mman.h> -+ -+int switcheroo(int fd, int prot, void *from, void *to, int size) -+{ -+ if(munmap(to, size) < 0){ -+ return(-1); -+ } -+ if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){ -+ return(-1); -+ } -+ if(munmap(from, size) < 0){ -+ return(-1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/tty_log.c um/arch/um/kernel/tty_log.c ---- orig/arch/um/kernel/tty_log.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/tty_log.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,228 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and -+ * geoffrey hing <ghing@net.ohio-state.edu> -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <string.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <sys/time.h> -+#include "init.h" -+#include "user.h" -+#include "kern_util.h" -+#include "os.h" -+ -+#define TTY_LOG_DIR "./" -+ -+/* Set early in boot and then unchanged */ -+static char *tty_log_dir = TTY_LOG_DIR; -+static int tty_log_fd = -1; -+ -+#define TTY_LOG_OPEN 1 -+#define TTY_LOG_CLOSE 2 -+#define TTY_LOG_WRITE 3 -+#define TTY_LOG_EXEC 4 -+ -+#define TTY_READ 1 -+#define TTY_WRITE 2 -+ -+struct tty_log_buf { -+ int what; -+ unsigned long tty; -+ int len; -+ int direction; -+ unsigned long sec; -+ unsigned long usec; -+}; -+ -+int open_tty_log(void *tty, void *current_tty) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")]; -+ int fd; -+ -+ gettimeofday(&tv, NULL); -+ if(tty_log_fd != -1){ -+ data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN, -+ .tty = (unsigned long) tty, -+ .len = sizeof(current_tty), -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ os_write_file(tty_log_fd, ¤t_tty, data.len); -+ return(tty_log_fd); -+ } -+ -+ sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, -+ (unsigned int) tv.tv_usec); -+ -+ fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))), -+ 0644); -+ if(fd < 0){ -+ printk("open_tty_log : couldn't open '%s', errno = %d\n", -+ buf, -fd); -+ } -+ return(fd); -+} -+ -+void close_tty_log(int fd, void *tty) -+{ -+ struct tty_log_buf data; -+ struct timeval tv; -+ -+ if(tty_log_fd != -1){ -+ gettimeofday(&tv, NULL); -+ data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE, -+ .tty = (unsigned long) tty, -+ .len = 0, -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ return; -+ } -+ os_close_file(fd); -+} -+ -+static int log_chunk(int fd, const char *buf, int len) -+{ -+ int total = 0, try, missed, n; -+ char chunk[64]; -+ -+ while(len > 0){ -+ try = (len > sizeof(chunk)) ? sizeof(chunk) : len; -+ missed = copy_from_user_proc(chunk, (char *) buf, try); -+ try -= missed; -+ n = os_write_file(fd, chunk, try); -+ if(n != try) { -+ if(n < 0) -+ return(n); -+ return(-EIO); -+ } -+ if(missed != 0) -+ return(-EFAULT); -+ -+ len -= try; -+ total += try; -+ buf += try; -+ } -+ -+ return(total); -+} -+ -+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ int direction; -+ -+ if(fd == tty_log_fd){ -+ gettimeofday(&tv, NULL); -+ direction = is_read ? TTY_READ : TTY_WRITE; -+ data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE, -+ .tty = (unsigned long) tty, -+ .len = len, -+ .direction = direction, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ } -+ -+ return(log_chunk(fd, buf, len)); -+} -+ -+void log_exec(char **argv, void *tty) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ char **ptr,*arg; -+ int len; -+ -+ if(tty_log_fd == -1) return; -+ -+ gettimeofday(&tv, NULL); -+ -+ len = 0; -+ for(ptr = argv; ; ptr++){ -+ if(copy_from_user_proc(&arg, ptr, sizeof(arg))) -+ return; -+ if(arg == NULL) break; -+ len += strlen_user_proc(arg); -+ } -+ -+ data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC, -+ .tty = (unsigned long) tty, -+ .len = len, -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ -+ for(ptr = argv; ; ptr++){ -+ if(copy_from_user_proc(&arg, ptr, sizeof(arg))) -+ return; -+ if(arg == NULL) break; -+ log_chunk(tty_log_fd, arg, strlen_user_proc(arg)); -+ } -+} -+ -+extern void register_tty_logger(int (*opener)(void *, void *), -+ int (*writer)(int, const char *, int, -+ void *, int), -+ void (*closer)(int, void *)); -+ -+static int register_logger(void) -+{ -+ register_tty_logger(open_tty_log, write_tty_log, close_tty_log); -+ return(0); -+} -+ -+__uml_initcall(register_logger); -+ -+static int __init set_tty_log_dir(char *name, int *add) -+{ -+ tty_log_dir = name; -+ return 0; -+} -+ -+__uml_setup("tty_log_dir=", set_tty_log_dir, -+"tty_log_dir=<directory>\n" -+" This is used to specify the directory where the logs of all pty\n" -+" data from this UML machine will be written.\n\n" -+); -+ -+static int __init set_tty_log_fd(char *name, int *add) -+{ -+ char *end; -+ -+ tty_log_fd = strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ printf("set_tty_log_fd - strtoul failed on '%s'\n", name); -+ tty_log_fd = -1; -+ } -+ return 0; -+} -+ -+__uml_setup("tty_log_fd=", set_tty_log_fd, -+"tty_log_fd=<fd>\n" -+" This is used to specify a preconfigured file descriptor to which all\n" -+" tty data will be written. Preconfigure the descriptor with something\n" -+" like '10>tty_log tty_log_fd=10'.\n\n" -+); -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/uaccess_user.c um/arch/um/kernel/uaccess_user.c ---- orig/arch/um/kernel/uaccess_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/uaccess_user.c 2004-01-31 02:48:08.000000000 -0500 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <setjmp.h> -+#include <string.h> -+ -+/* These are here rather than tt/uaccess.c because skas mode needs them in -+ * order to do SIGBUS recovery when a tmpfs mount runs out of room. -+ */ -+ -+unsigned long __do_user_copy(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher, -+ void (*op)(void *to, const void *from, -+ int n), int *faulted_out) -+{ -+ unsigned long *faddrp = (unsigned long *) fault_addr, ret; -+ -+ sigjmp_buf jbuf; -+ *fault_catcher = &jbuf; -+ if(sigsetjmp(jbuf, 1) == 0){ -+ (*op)(to, from, n); -+ ret = 0; -+ *faulted_out = 0; -+ } -+ else { -+ ret = *faddrp; -+ *faulted_out = 1; -+ } -+ *fault_addr = NULL; -+ *fault_catcher = NULL; -+ return ret; -+} -+ -+void __do_copy(void *to, const void *from, int n) -+{ -+ memcpy(to, from, n); -+} -+ -+ -+int __do_copy_to_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher) -+{ -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, -+ __do_copy, &faulted); -+ if(!faulted) return(0); -+ else return(n - (fault - (unsigned long) to)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/um_arch.c um/arch/um/kernel/um_arch.c ---- orig/arch/um/kernel/um_arch.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/um_arch.c 2004-01-10 00:11:09.000000000 -0500 -@@ -0,0 +1,431 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/notifier.h" -+#include "linux/mm.h" -+#include "linux/types.h" -+#include "linux/tty.h" -+#include "linux/init.h" -+#include "linux/bootmem.h" -+#include "linux/spinlock.h" -+#include "linux/utsname.h" -+#include "linux/sysrq.h" -+#include "linux/seq_file.h" -+#include "linux/delay.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/ptrace.h" -+#include "asm/elf.h" -+#include "asm/user.h" -+#include "ubd_user.h" -+#include "asm/current.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mprot.h" -+#include "mem_user.h" -+#include "mem.h" -+#include "umid.h" -+#include "initrd.h" -+#include "init.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+#include "mode.h" -+ -+#define DEFAULT_COMMAND_LINE "root=/dev/ubd0" -+ -+struct cpuinfo_um boot_cpu_data = { -+ .loops_per_jiffy = 0, -+ .pgd_quick = NULL, -+ .pmd_quick = NULL, -+ .pte_quick = NULL, -+ .pgtable_cache_sz = 0, -+ .ipi_pipe = { -1, -1 } -+}; -+ -+unsigned long thread_saved_pc(struct thread_struct *thread) -+{ -+ return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, -+ thread))); -+} -+ -+static int show_cpuinfo(struct seq_file *m, void *v) -+{ -+ int index = 0; -+ -+#ifdef CONFIG_SMP -+ index = (struct cpuinfo_um *)v - cpu_data; -+ if (!(cpu_online_map & (1 << index))) -+ return 0; -+#endif -+ -+ seq_printf(m, "processor\t: %d\n", index); -+ seq_printf(m, "vendor_id\t: User Mode Linux\n"); -+ seq_printf(m, "model name\t: UML\n"); -+ seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); -+ seq_printf(m, "host\t\t: %s\n", host_info); -+ seq_printf(m, "bogomips\t: %lu.%02lu\n\n", -+ loops_per_jiffy/(500000/HZ), -+ (loops_per_jiffy/(5000/HZ)) % 100); -+ -+ return(0); -+} -+ -+static void *c_start(struct seq_file *m, loff_t *pos) -+{ -+ return *pos < NR_CPUS ? cpu_data + *pos : NULL; -+} -+ -+static void *c_next(struct seq_file *m, void *v, loff_t *pos) -+{ -+ ++*pos; -+ return c_start(m, pos); -+} -+ -+static void c_stop(struct seq_file *m, void *v) -+{ -+} -+ -+struct seq_operations cpuinfo_op = { -+ .start = c_start, -+ .next = c_next, -+ .stop = c_stop, -+ .show = show_cpuinfo, -+}; -+ -+pte_t * __bad_pagetable(void) -+{ -+ panic("Someone should implement __bad_pagetable"); -+ return(NULL); -+} -+ -+/* Set in linux_main */ -+unsigned long host_task_size; -+unsigned long task_size; -+unsigned long uml_start; -+ -+/* Set in early boot */ -+unsigned long uml_physmem; -+unsigned long uml_reserved; -+unsigned long start_vm; -+unsigned long end_vm; -+int ncpus = 1; -+ -+#ifdef CONFIG_MODE_TT -+/* Pointer set in linux_main, the array itself is private to each thread, -+ * and changed at address space creation time so this poses no concurrency -+ * problems. -+ */ -+static char *argv1_begin = NULL; -+static char *argv1_end = NULL; -+#endif -+ -+/* Set in early boot */ -+static int have_root __initdata = 0; -+long physmem_size = 32 * 1024 * 1024; -+ -+void set_cmdline(char *cmd) -+{ -+#ifdef CONFIG_MODE_TT -+ char *umid, *ptr; -+ -+ if(CHOOSE_MODE(honeypot, 0)) return; -+ -+ umid = get_umid(1); -+ if(umid != NULL){ -+ snprintf(argv1_begin, -+ (argv1_end - argv1_begin) * sizeof(*ptr), -+ "(%s) ", umid); -+ ptr = &argv1_begin[strlen(argv1_begin)]; -+ } -+ else ptr = argv1_begin; -+ -+ snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); -+ memset(argv1_begin + strlen(argv1_begin), '\0', -+ argv1_end - argv1_begin - strlen(argv1_begin)); -+#endif -+} -+ -+static char *usage_string = -+"User Mode Linux v%s\n" -+" available at http://user-mode-linux.sourceforge.net/\n\n"; -+ -+static int __init uml_version_setup(char *line, int *add) -+{ -+ printf("%s\n", system_utsname.release); -+ exit(0); -+} -+ -+__uml_setup("--version", uml_version_setup, -+"--version\n" -+" Prints the version number of the kernel.\n\n" -+); -+ -+static int __init uml_root_setup(char *line, int *add) -+{ -+ have_root = 1; -+ return 0; -+} -+ -+__uml_setup("root=", uml_root_setup, -+"root=<file containing the root fs>\n" -+" This is actually used by the generic kernel in exactly the same\n" -+" way as in any other kernel. If you configure a number of block\n" -+" devices and want to boot off something other than ubd0, you \n" -+" would use something like:\n" -+" root=/dev/ubd5\n\n" -+); -+ -+#ifdef CONFIG_SMP -+static int __init uml_ncpus_setup(char *line, int *add) -+{ -+ if (!sscanf(line, "%d", &ncpus)) { -+ printf("Couldn't parse [%s]\n", line); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+__uml_setup("ncpus=", uml_ncpus_setup, -+"ncpus=<# of desired CPUs>\n" -+" This tells an SMP kernel how many virtual processors to start.\n\n" -+); -+#endif -+ -+int force_tt = 0; -+ -+#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) -+#define DEFAULT_TT 0 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ force_tt = 1; -+ return(0); -+} -+ -+#else -+#ifdef CONFIG_MODE_SKAS -+ -+#define DEFAULT_TT 0 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); -+ return(0); -+} -+ -+#else -+#ifdef CONFIG_MODE_TT -+ -+#define DEFAULT_TT 1 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); -+ return(0); -+} -+ -+#else -+ -+#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled -+ -+#endif -+#endif -+#endif -+ -+__uml_setup("mode=tt", mode_tt_setup, -+"mode=tt\n" -+" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" -+" forces UML to run in tt (tracing thread) mode. It is not the default\n" -+" because it's slower and less secure than skas mode.\n\n" -+); -+ -+int mode_tt = DEFAULT_TT; -+ -+static int __init Usage(char *line, int *add) -+{ -+ const char **p; -+ -+ printf(usage_string, system_utsname.release); -+ p = &__uml_help_start; -+ while (p < &__uml_help_end) { -+ printf("%s", *p); -+ p++; -+ } -+ exit(0); -+} -+ -+__uml_setup("--help", Usage, -+"--help\n" -+" Prints this message.\n\n" -+); -+ -+static int __init uml_checksetup(char *line, int *add) -+{ -+ struct uml_param *p; -+ -+ p = &__uml_setup_start; -+ while(p < &__uml_setup_end) { -+ int n; -+ -+ n = strlen(p->str); -+ if(!strncmp(line, p->str, n)){ -+ if (p->setup_func(line + n, add)) return 1; -+ } -+ p++; -+ } -+ return 0; -+} -+ -+static void __init uml_postsetup(void) -+{ -+ initcall_t *p; -+ -+ p = &__uml_postsetup_start; -+ while(p < &__uml_postsetup_end){ -+ (*p)(); -+ p++; -+ } -+ return; -+} -+ -+/* Set during early boot */ -+unsigned long brk_start; -+unsigned long end_iomem; -+ -+#define MIN_VMALLOC (32 * 1024 * 1024) -+ -+int linux_main(int argc, char **argv) -+{ -+ unsigned long avail; -+ unsigned long virtmem_size, max_physmem; -+ unsigned int i, add; -+ -+ for (i = 1; i < argc; i++){ -+ if((i == 1) && (argv[i][0] == ' ')) continue; -+ add = 1; -+ uml_checksetup(argv[i], &add); -+ if(add) add_arg(saved_command_line, argv[i]); -+ } -+ if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE); -+ -+ mode_tt = force_tt ? 1 : !can_do_skas(); -+ uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, -+ &host_task_size, &task_size); -+ -+ brk_start = (unsigned long) sbrk(0); -+ CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); -+ -+ uml_physmem = uml_start; -+ -+ /* Reserve up to 4M after the current brk */ -+ uml_reserved = ROUND_4M(brk_start) + (1 << 22); -+ -+ setup_machinename(system_utsname.machine); -+ -+#ifdef CONFIG_MODE_TT -+ argv1_begin = argv[1]; -+ argv1_end = &argv[1][strlen(argv[1])]; -+#endif -+ -+ highmem = 0; -+ iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; -+ max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; -+ -+ /* Zones have to begin on a 1 << MAX_ORDER page boundary, -+ * so this makes sure that's true for highmem -+ */ -+ max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); -+ if(physmem_size + iomem_size > max_physmem){ -+ highmem = physmem_size + iomem_size - max_physmem; -+ physmem_size -= highmem; -+#ifndef CONFIG_HIGHMEM -+ highmem = 0; -+ printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " -+ "to %ld bytes\n", physmem_size); -+#endif -+ } -+ -+ high_physmem = uml_physmem + physmem_size; -+ end_iomem = high_physmem + iomem_size; -+ high_memory = (void *) end_iomem; -+ -+ start_vm = VMALLOC_START; -+ -+ setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); -+ if(init_maps(physmem_size, iomem_size, highmem)){ -+ printf("Failed to allocate mem_map for %ld bytes of physical " -+ "memory and %ld bytes of highmem\n", physmem_size, -+ highmem); -+ exit(1); -+ } -+ -+ virtmem_size = physmem_size; -+ avail = get_kmem_end() - start_vm; -+ if(physmem_size > avail) virtmem_size = avail; -+ end_vm = start_vm + virtmem_size; -+ -+ if(virtmem_size < physmem_size) -+ printf("Kernel virtual memory size shrunk to %ld bytes\n", -+ virtmem_size); -+ -+ uml_postsetup(); -+ -+ init_task.thread.kernel_stack = (unsigned long) &init_task + -+ 2 * PAGE_SIZE; -+ -+ task_protections((unsigned long) &init_task); -+ os_flush_stdout(); -+ -+ return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); -+} -+ -+static int panic_exit(struct notifier_block *self, unsigned long unused1, -+ void *unused2) -+{ -+#ifdef CONFIG_SYSRQ -+ handle_sysrq('p', ¤t->thread.regs, NULL, NULL); -+#endif -+ machine_halt(); -+ return(0); -+} -+ -+static struct notifier_block panic_exit_notifier = { -+ .notifier_call = panic_exit, -+ .next = NULL, -+ .priority = 0 -+}; -+ -+void __init setup_arch(char **cmdline_p) -+{ -+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); -+ paging_init(); -+ strcpy(command_line, saved_command_line); -+ *cmdline_p = command_line; -+ setup_hostinfo(); -+} -+ -+void __init check_bugs(void) -+{ -+ arch_check_bugs(); -+ check_ptrace(); -+ check_sigio(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/umid.c um/arch/um/kernel/umid.c ---- orig/arch/um/kernel/umid.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/umid.c 2004-01-26 10:13:01.000000000 -0500 -@@ -0,0 +1,327 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <errno.h> -+#include <string.h> -+#include <stdlib.h> -+#include <dirent.h> -+#include <signal.h> -+#include <sys/stat.h> -+#include <sys/param.h> -+#include "user.h" -+#include "umid.h" -+#include "init.h" -+#include "os.h" -+#include "user_util.h" -+#include "choose-mode.h" -+ -+#define UMID_LEN 64 -+#define UML_DIR "~/.uml/" -+ -+/* Changed by set_umid and make_umid, which are run early in boot */ -+static char umid[UMID_LEN] = { 0 }; -+ -+/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -+static char *uml_dir = UML_DIR; -+ -+/* Changed by set_umid */ -+static int umid_is_random = 1; -+static int umid_inited = 0; -+ -+static int make_umid(int (*printer)(const char *fmt, ...)); -+ -+static int __init set_umid(char *name, int is_random, -+ int (*printer)(const char *fmt, ...)) -+{ -+ if(umid_inited){ -+ (*printer)("Unique machine name can't be set twice\n"); -+ return(-1); -+ } -+ -+ if(strlen(name) > UMID_LEN - 1) -+ (*printer)("Unique machine name is being truncated to %s " -+ "characters\n", UMID_LEN); -+ strncpy(umid, name, UMID_LEN - 1); -+ umid[UMID_LEN - 1] = '\0'; -+ -+ umid_is_random = is_random; -+ umid_inited = 1; -+ return 0; -+} -+ -+static int __init set_umid_arg(char *name, int *add) -+{ -+ return(set_umid(name, 0, printf)); -+} -+ -+__uml_setup("umid=", set_umid_arg, -+"umid=<name>\n" -+" This is used to assign a unique identity to this UML machine and\n" -+" is used for naming the pid file and management console socket.\n\n" -+); -+ -+int __init umid_file_name(char *name, char *buf, int len) -+{ -+ int n; -+ -+ if(!umid_inited && make_umid(printk)) return(-1); -+ -+ n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; -+ if(n > len){ -+ printk("umid_file_name : buffer too short\n"); -+ return(-1); -+ } -+ -+ sprintf(buf, "%s%s/%s", uml_dir, umid, name); -+ return(0); -+} -+ -+extern int tracing_pid; -+ -+static int __init create_pid_file(void) -+{ -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")]; -+ int fd, n; -+ -+ if(umid_file_name("pid", file, sizeof(file))) return 0; -+ -+ fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), -+ 0644); -+ if(fd < 0){ -+ printf("Open of machine pid file \"%s\" failed - " -+ "err = %d\n", file, -fd); -+ return 0; -+ } -+ -+ sprintf(pid, "%d\n", os_getpid()); -+ n = os_write_file(fd, pid, strlen(pid)); -+ if(n != strlen(pid)) -+ printf("Write of pid file failed - err = %d\n", -n); -+ os_close_file(fd); -+ return 0; -+} -+ -+static int actually_do_remove(char *dir) -+{ -+ DIR *directory; -+ struct dirent *ent; -+ int len; -+ char file[256]; -+ -+ directory = opendir(dir); -+ if(directory == NULL){ -+ printk("actually_do_remove : couldn't open directory '%s', " -+ "errno = %d\n", dir, errno); -+ return(1); -+ } -+ while((ent = readdir(directory)) != NULL){ -+ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) -+ continue; -+ len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; -+ if(len > sizeof(file)){ -+ printk("Not deleting '%s' from '%s' - name too long\n", -+ ent->d_name, dir); -+ continue; -+ } -+ sprintf(file, "%s/%s", dir, ent->d_name); -+ if(unlink(file) < 0){ -+ printk("actually_do_remove : couldn't remove '%s' " -+ "from '%s', errno = %d\n", ent->d_name, dir, -+ errno); -+ return(1); -+ } -+ } -+ if(rmdir(dir) < 0){ -+ printk("actually_do_remove : couldn't rmdir '%s', " -+ "errno = %d\n", dir, errno); -+ return(1); -+ } -+ return(0); -+} -+ -+void remove_umid_dir(void) -+{ -+ char dir[strlen(uml_dir) + UMID_LEN + 1]; -+ if(!umid_inited) return; -+ -+ sprintf(dir, "%s%s", uml_dir, umid); -+ actually_do_remove(dir); -+} -+ -+char *get_umid(int only_if_set) -+{ -+ if(only_if_set && umid_is_random) return(NULL); -+ return(umid); -+} -+ -+int not_dead_yet(char *dir) -+{ -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")], *end; -+ int dead, fd, p, n; -+ -+ sprintf(file, "%s/pid", dir); -+ dead = 0; -+ fd = os_open_file(file, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ if(fd != -ENOENT){ -+ printk("not_dead_yet : couldn't open pid file '%s', " -+ "err = %d\n", file, -fd); -+ return(1); -+ } -+ dead = 1; -+ } -+ if(fd > 0){ -+ n = os_read_file(fd, pid, sizeof(pid)); -+ if(n < 0){ -+ printk("not_dead_yet : couldn't read pid file '%s', " -+ "err = %d\n", file, -n); -+ return(1); -+ } -+ p = strtoul(pid, &end, 0); -+ if(end == pid){ -+ printk("not_dead_yet : couldn't parse pid file '%s', " -+ "errno = %d\n", file, errno); -+ dead = 1; -+ } -+ if(((kill(p, 0) < 0) && (errno == ESRCH)) || -+ (p == CHOOSE_MODE(tracing_pid, os_getpid()))) -+ dead = 1; -+ } -+ if(!dead) return(1); -+ return(actually_do_remove(dir)); -+} -+ -+static int __init set_uml_dir(char *name, int *add) -+{ -+ if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ -+ uml_dir = malloc(strlen(name) + 1); -+ if(uml_dir == NULL){ -+ printf("Failed to malloc uml_dir - error = %d\n", -+ errno); -+ uml_dir = name; -+ /* Return 0 here because do_initcalls doesn't look at -+ * the return value. -+ */ -+ return(0); -+ } -+ sprintf(uml_dir, "%s/", name); -+ } -+ else uml_dir = name; -+ return(0); -+} -+ -+static int __init make_uml_dir(void) -+{ -+ char dir[MAXPATHLEN + 1] = { '\0' }; -+ int len; -+ -+ if(*uml_dir == '~'){ -+ char *home = getenv("HOME"); -+ -+ if(home == NULL){ -+ printf("make_uml_dir : no value in environment for " -+ "$HOME\n"); -+ exit(1); -+ } -+ strncpy(dir, home, sizeof(dir)); -+ uml_dir++; -+ } -+ len = strlen(dir); -+ strncat(dir, uml_dir, sizeof(dir) - len); -+ len = strlen(dir); -+ if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){ -+ dir[len] = '/'; -+ dir[len + 1] = '\0'; -+ } -+ -+ uml_dir = malloc(strlen(dir) + 1); -+ if(uml_dir == NULL){ -+ printf("make_uml_dir : malloc failed, errno = %d\n", errno); -+ exit(1); -+ } -+ strcpy(uml_dir, dir); -+ -+ if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ -+ printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno); -+ return(-1); -+ } -+ return 0; -+} -+ -+static int __init make_umid(int (*printer)(const char *fmt, ...)) -+{ -+ int fd, err; -+ char tmp[strlen(uml_dir) + UMID_LEN + 1]; -+ -+ strncpy(tmp, uml_dir, sizeof(tmp) - 1); -+ tmp[sizeof(tmp) - 1] = '\0'; -+ -+ if(!umid_inited){ -+ strcat(tmp, "XXXXXX"); -+ fd = mkstemp(tmp); -+ if(fd < 0){ -+ (*printer)("make_umid - mkstemp failed, errno = %d\n", -+ errno); -+ return(1); -+ } -+ -+ os_close_file(fd); -+ /* There's a nice tiny little race between this unlink and -+ * the mkdir below. It'd be nice if there were a mkstemp -+ * for directories. -+ */ -+ unlink(tmp); -+ set_umid(&tmp[strlen(uml_dir)], 1, printer); -+ } -+ -+ sprintf(tmp, "%s%s", uml_dir, umid); -+ -+ err = mkdir(tmp, 0777); -+ if(err < 0){ -+ if(errno == EEXIST){ -+ if(not_dead_yet(tmp)){ -+ (*printer)("umid '%s' is in use\n", umid); -+ return(-1); -+ } -+ err = mkdir(tmp, 0777); -+ } -+ } -+ if(err < 0){ -+ (*printer)("Failed to create %s - errno = %d\n", umid, errno); -+ return(-1); -+ } -+ -+ return(0); -+} -+ -+__uml_setup("uml_dir=", set_uml_dir, -+"uml_dir=<directory>\n" -+" The location to place the pid and umid files.\n\n" -+); -+ -+__uml_postsetup(make_uml_dir); -+ -+static int __init make_umid_setup(void) -+{ -+ return(make_umid(printf)); -+} -+ -+__uml_postsetup(make_umid_setup); -+__uml_postsetup(create_pid_file); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/kernel/user_syms.c um/arch/um/kernel/user_syms.c ---- orig/arch/um/kernel/user_syms.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/user_syms.c 2004-01-23 00:44:09.000000000 -0500 -@@ -0,0 +1,119 @@ -+#include <stdio.h> -+#include <unistd.h> -+#include <dirent.h> -+#include <fcntl.h> -+#include <errno.h> -+#include <utime.h> -+#include <string.h> -+#include <sys/stat.h> -+#include <sys/vfs.h> -+#include <sys/ioctl.h> -+#include "user_util.h" -+#include "mem_user.h" -+ -+/* XXX All the __CONFIG_* stuff is broken because this file can't include -+ * config.h -+ */ -+ -+/* Had to steal this from linux/module.h because that file can't be included -+ * since this includes various user-level headers. -+ */ -+ -+struct module_symbol -+{ -+ unsigned long value; -+ const char *name; -+}; -+ -+/* Indirect stringification. */ -+ -+#define __MODULE_STRING_1(x) #x -+#define __MODULE_STRING(x) __MODULE_STRING_1(x) -+ -+#if !defined(__AUTOCONF_INCLUDED__) -+ -+#define __EXPORT_SYMBOL(sym,str) error config_must_be_included_before_module -+#define EXPORT_SYMBOL(var) error config_must_be_included_before_module -+#define EXPORT_SYMBOL_NOVERS(var) error config_must_be_included_before_module -+ -+#elif !defined(__CONFIG_MODULES__) -+ -+#define __EXPORT_SYMBOL(sym,str) -+#define EXPORT_SYMBOL(var) -+#define EXPORT_SYMBOL_NOVERS(var) -+ -+#else -+ -+#define __EXPORT_SYMBOL(sym, str) \ -+const char __kstrtab_##sym[] \ -+__attribute__((section(".kstrtab"))) = str; \ -+const struct module_symbol __ksymtab_##sym \ -+__attribute__((section("__ksymtab"))) = \ -+{ (unsigned long)&sym, __kstrtab_##sym } -+ -+#if defined(__MODVERSIONS__) || !defined(__CONFIG_MODVERSIONS__) -+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) -+#else -+#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var))) -+#endif -+ -+#define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) -+ -+#endif -+ -+EXPORT_SYMBOL(__errno_location); -+ -+EXPORT_SYMBOL(access); -+EXPORT_SYMBOL(open); -+EXPORT_SYMBOL(open64); -+EXPORT_SYMBOL(close); -+EXPORT_SYMBOL(read); -+EXPORT_SYMBOL(write); -+EXPORT_SYMBOL(dup2); -+EXPORT_SYMBOL(__xstat); -+EXPORT_SYMBOL(__lxstat); -+EXPORT_SYMBOL(__lxstat64); -+EXPORT_SYMBOL(lseek); -+EXPORT_SYMBOL(lseek64); -+EXPORT_SYMBOL(chown); -+EXPORT_SYMBOL(truncate); -+EXPORT_SYMBOL(utime); -+EXPORT_SYMBOL(chmod); -+EXPORT_SYMBOL(rename); -+EXPORT_SYMBOL(__xmknod); -+ -+EXPORT_SYMBOL(symlink); -+EXPORT_SYMBOL(link); -+EXPORT_SYMBOL(unlink); -+EXPORT_SYMBOL(readlink); -+ -+EXPORT_SYMBOL(mkdir); -+EXPORT_SYMBOL(rmdir); -+EXPORT_SYMBOL(opendir); -+EXPORT_SYMBOL(readdir); -+EXPORT_SYMBOL(closedir); -+EXPORT_SYMBOL(seekdir); -+EXPORT_SYMBOL(telldir); -+ -+EXPORT_SYMBOL(ioctl); -+ -+extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, -+ __off64_t __offset); -+extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n, -+ __off64_t __offset); -+EXPORT_SYMBOL(pread64); -+EXPORT_SYMBOL(pwrite64); -+ -+EXPORT_SYMBOL(statfs); -+EXPORT_SYMBOL(statfs64); -+ -+EXPORT_SYMBOL(memcpy); -+EXPORT_SYMBOL(getuid); -+ -+EXPORT_SYMBOL(memset); -+EXPORT_SYMBOL(strstr); -+EXPORT_SYMBOL(strpbrk); -+EXPORT_SYMBOL(strlen); -+EXPORT_SYMBOL(printf); -+ -+EXPORT_SYMBOL(find_iomem); -diff -Naur -X ../exclude-files orig/arch/um/kernel/user_util.c um/arch/um/kernel/user_util.c ---- orig/arch/um/kernel/user_util.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/kernel/user_util.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,164 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <limits.h> -+#include <sys/mman.h> -+#include <sys/stat.h> -+#include <sys/ptrace.h> -+#include <sys/utsname.h> -+#include <sys/param.h> -+#include <sys/time.h> -+#include "asm/types.h" -+#include <ctype.h> -+#include <signal.h> -+#include <wait.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <sched.h> -+#include <termios.h> -+#include <string.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "mem_user.h" -+#include "init.h" -+#include "helper.h" -+#include "uml-config.h" -+ -+#define COMMAND_LINE_SIZE _POSIX_ARG_MAX -+ -+/* Changed in linux_main and setup_arch, which run before SMP is started */ -+char saved_command_line[COMMAND_LINE_SIZE] = { 0 }; -+char command_line[COMMAND_LINE_SIZE] = { 0 }; -+ -+void add_arg(char *cmd_line, char *arg) -+{ -+ if (strlen(cmd_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { -+ printf("add_arg: Too much command line!\n"); -+ exit(1); -+ } -+ if(strlen(cmd_line) > 0) strcat(cmd_line, " "); -+ strcat(cmd_line, arg); -+} -+ -+void stop(void) -+{ -+ while(1) sleep(1000000); -+} -+ -+void stack_protections(unsigned long address) -+{ -+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC; -+ -+ if(mprotect((void *) address, page_size(), prot) < 0) -+ panic("protecting stack failed, errno = %d", errno); -+} -+ -+void task_protections(unsigned long address) -+{ -+ unsigned long guard = address + page_size(); -+ unsigned long stack = guard + page_size(); -+ int prot = 0, pages; -+#ifdef notdef -+ if(mprotect((void *) guard, page_size(), prot) < 0) -+ panic("protecting guard page failed, errno = %d", errno); -+#endif -+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; -+ prot = PROT_READ | PROT_WRITE | PROT_EXEC; -+ if(mprotect((void *) stack, pages * page_size(), prot) < 0) -+ panic("protecting stack failed, errno = %d", errno); -+} -+ -+int wait_for_stop(int pid, int sig, int cont_type, void *relay) -+{ -+ sigset_t *relay_signals = relay; -+ int status, ret; -+ -+ while(1){ -+ ret = waitpid(pid, &status, WUNTRACED); -+ if((ret < 0) || -+ !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ -+ if(ret < 0){ -+ if(errno == EINTR) continue; -+ printk("wait failed, errno = %d\n", -+ errno); -+ } -+ else if(WIFEXITED(status)) -+ printk("process exited with status %d\n", -+ WEXITSTATUS(status)); -+ else if(WIFSIGNALED(status)) -+ printk("process exited with signal %d\n", -+ WTERMSIG(status)); -+ else if((WSTOPSIG(status) == SIGVTALRM) || -+ (WSTOPSIG(status) == SIGALRM) || -+ (WSTOPSIG(status) == SIGIO) || -+ (WSTOPSIG(status) == SIGPROF) || -+ (WSTOPSIG(status) == SIGCHLD) || -+ (WSTOPSIG(status) == SIGWINCH) || -+ (WSTOPSIG(status) == SIGINT)){ -+ ptrace(cont_type, pid, 0, WSTOPSIG(status)); -+ continue; -+ } -+ else if((relay_signals != NULL) && -+ sigismember(relay_signals, WSTOPSIG(status))){ -+ ptrace(cont_type, pid, 0, WSTOPSIG(status)); -+ continue; -+ } -+ else printk("process stopped with signal %d\n", -+ WSTOPSIG(status)); -+ panic("wait_for_stop failed to wait for %d to stop " -+ "with %d\n", pid, sig); -+ } -+ return(status); -+ } -+} -+ -+int raw(int fd, int complain) -+{ -+ struct termios tt; -+ int err; -+ -+ tcgetattr(fd, &tt); -+ cfmakeraw(&tt); -+ err = tcsetattr(fd, TCSANOW, &tt); -+ if((err < 0) && complain){ -+ printk("tcsetattr failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ return(0); -+} -+ -+void setup_machinename(char *machine_out) -+{ -+ struct utsname host; -+ -+ uname(&host); -+ strcpy(machine_out, host.machine); -+} -+ -+char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; -+ -+void setup_hostinfo(void) -+{ -+ struct utsname host; -+ -+ uname(&host); -+ sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, -+ host.release, host.version, host.machine); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/link.ld.in um/arch/um/link.ld.in ---- orig/arch/um/link.ld.in 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/link.ld.in 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,94 @@ -+OUTPUT_FORMAT("ELF_FORMAT") -+OUTPUT_ARCH(ELF_ARCH) -+ENTRY(_start) -+ -+SECTIONS -+{ -+ . = START() + SIZEOF_HEADERS; -+ -+ __binary_start = .; -+ifdef(`MODE_TT', ` -+ .thread_private : { -+ __start_thread_private = .; -+ errno = .; -+ . += 4; -+ arch/um/kernel/tt/unmap_fin.o (.data) -+ __end_thread_private = .; -+ } -+ . = ALIGN(4096); -+ .remap : { arch/um/kernel/tt/unmap_fin.o (.text) } -+') -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ . = ALIGN(4096); -+ .text : -+ { -+ *(.text) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ *(.gnu.linkonce.t*) -+ } -+ .fini : { *(.fini) } =0x9090 -+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) } -+ .rodata1 : { *(.rodata1) } -+ _etext = .; -+ PROVIDE (etext = .); -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+include(`arch/um/common.ld.in') -+ -+ .data : -+ { -+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ -+ *(.data.init_task) -+ *(.data) -+ *(.gnu.linkonce.d*) -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ .ctors : -+ { -+ *(.ctors) -+ } -+ .dtors : -+ { -+ *(.dtors) -+ } -+ -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ _edata = .; -+ PROVIDE (edata = .); -+ . = ALIGN(0x1000); -+ .sbss : -+ { -+ __bss_start = .; -+ PROVIDE(_bss_start = .); -+ *(.sbss) -+ *(.scommon) -+ } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ } -+ _end = . ; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+} -diff -Naur -X ../exclude-files orig/arch/um/main.c um/arch/um/main.c ---- orig/arch/um/main.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/main.c 2004-01-29 00:48:42.000000000 -0500 -@@ -0,0 +1,199 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/resource.h> -+#include <sys/mman.h> -+#include <sys/user.h> -+#include <asm/page.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "mem_user.h" -+#include "signal_user.h" -+#include "user.h" -+#include "init.h" -+#include "mode.h" -+#include "choose-mode.h" -+#include "uml-config.h" -+ -+/* Set in set_stklim, which is called from main and __wrap_malloc. -+ * __wrap_malloc only calls it if main hasn't started. -+ */ -+unsigned long stacksizelim; -+ -+/* Set in main */ -+char *linux_prog; -+ -+#define PGD_BOUND (4 * 1024 * 1024) -+#define STACKSIZE (8 * 1024 * 1024) -+#define THREAD_NAME_LEN (256) -+ -+static void set_stklim(void) -+{ -+ struct rlimit lim; -+ -+ if(getrlimit(RLIMIT_STACK, &lim) < 0){ -+ perror("getrlimit"); -+ exit(1); -+ } -+ if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ -+ lim.rlim_cur = STACKSIZE; -+ if(setrlimit(RLIMIT_STACK, &lim) < 0){ -+ perror("setrlimit"); -+ exit(1); -+ } -+ } -+ stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); -+} -+ -+static __init void do_uml_initcalls(void) -+{ -+ initcall_t *call; -+ -+ call = &__uml_initcall_start; -+ while (call < &__uml_initcall_end){; -+ (*call)(); -+ call++; -+ } -+} -+ -+static void last_ditch_exit(int sig) -+{ -+ CHOOSE_MODE(kmalloc_ok = 0, (void) 0); -+ signal(SIGINT, SIG_DFL); -+ signal(SIGTERM, SIG_DFL); -+ signal(SIGHUP, SIG_DFL); -+ uml_cleanup(); -+ exit(1); -+} -+ -+extern int uml_exitcode; -+ -+int main(int argc, char **argv, char **envp) -+{ -+ char **new_argv; -+ sigset_t mask; -+ int ret, i; -+ -+ /* Enable all signals except SIGIO - in some environments, we can -+ * enter with some signals blocked -+ */ -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, SIGIO); -+ if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ -+ perror("sigprocmask"); -+ exit(1); -+ } -+ -+#ifdef UML_CONFIG_MODE_TT -+ /* Allocate memory for thread command lines */ -+ if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ -+ -+ char padding[THREAD_NAME_LEN] = { -+ [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' -+ }; -+ -+ new_argv = malloc((argc + 2) * sizeof(char*)); -+ if(!new_argv) { -+ perror("Allocating extended argv"); -+ exit(1); -+ } -+ -+ new_argv[0] = argv[0]; -+ new_argv[1] = padding; -+ -+ for(i = 2; i <= argc; i++) -+ new_argv[i] = argv[i - 1]; -+ new_argv[argc + 1] = NULL; -+ -+ execvp(new_argv[0], new_argv); -+ perror("execing with extended args"); -+ exit(1); -+ } -+#endif -+ -+ linux_prog = argv[0]; -+ -+ set_stklim(); -+ -+ new_argv = malloc((argc + 1) * sizeof(char *)); -+ if(new_argv == NULL){ -+ perror("Mallocing argv"); -+ exit(1); -+ } -+ for(i=0;i<argc;i++){ -+ new_argv[i] = strdup(argv[i]); -+ if(new_argv[i] == NULL){ -+ perror("Mallocing an arg"); -+ exit(1); -+ } -+ } -+ new_argv[argc] = NULL; -+ -+ set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ -+ do_uml_initcalls(); -+ ret = linux_main(argc, argv); -+ -+ /* Reboot */ -+ if(ret){ -+ printf("\n"); -+ -+ execvp(new_argv[0], new_argv); -+ perror("Failed to exec kernel"); -+ ret = 1; -+ } -+ printf("\n"); -+ return(uml_exitcode); -+} -+ -+#define CAN_KMALLOC() \ -+ (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1)) -+ -+extern void *__real_malloc(int); -+ -+void *__wrap_malloc(int size) -+{ -+ if(CAN_KMALLOC()) -+ return(um_kmalloc(size)); -+ else -+ return(__real_malloc(size)); -+} -+ -+void *__wrap_calloc(int n, int size) -+{ -+ void *ptr = __wrap_malloc(n * size); -+ -+ if(ptr == NULL) return(NULL); -+ memset(ptr, 0, n * size); -+ return(ptr); -+} -+ -+extern void __real_free(void *); -+ -+void __wrap_free(void *ptr) -+{ -+ if(CAN_KMALLOC()) kfree(ptr); -+ else __real_free(ptr); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/Makefile um/arch/um/Makefile ---- orig/arch/um/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile 2004-02-14 06:26:41.000000000 -0500 -@@ -0,0 +1,174 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+OS := $(shell uname -s) -+ -+ARCH_DIR = arch/um -+ -+core-y := kernel sys-$(SUBARCH) os-$(OS) -+drivers-y := fs drivers -+subdir-y := $(core-y) $(drivers-y) -+SUBDIRS += $(foreach dir,$(subdir-y),$(ARCH_DIR)/$(dir)) -+ -+CORE_FILES += $(foreach dir,$(core-y),$(ARCH_DIR)/$(dir)/built-in.o) -+DRIVERS += $(foreach dir,$(drivers-y),$(ARCH_DIR)/$(dir)/built-in.o) -+ -+include $(ARCH_DIR)/Makefile-$(SUBARCH) -+include $(ARCH_DIR)/Makefile-os-$(OS) -+ -+MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt -+MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas -+ -+ifneq ($(MAKEFILE-y),) -+ include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y)) -+endif -+ -+EXTRAVERSION := $(EXTRAVERSION)-1um -+ -+include/linux/version.h: arch/$(ARCH)/Makefile -+ -+# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE) -+# The way the toplevel Makefile is written EXTRAVERSION is not supposed -+# to be changed outside the toplevel Makefile, but recalculating MODLIB is -+# a sufficient workaround until we no longer need architecture dependent -+# EXTRAVERSION... -+MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) -+ -+ifeq ($(CONFIG_DEBUGSYM),y) -+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -+endif -+ -+CFLAGS-$(CONFIG_DEBUGSYM) += -g -+ -+ARCH_INCLUDE = -I$(TOPDIR)/$(ARCH_DIR)/include -+ -+# -Derrno=kernel_errno - This turns all kernel references to errno into -+# kernel_errno to separate them from the libc errno. This allows -fno-common -+# in CFLAGS. Otherwise, it would cause ld to complain about the two different -+# errnos. -+ -+CFLAGS += $(ARCH_CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ -+ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \ -+ $(MODE_INCLUDE) -+ -+LINKFLAGS += -r -+ -+LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc -+ -+# These are needed for clean and mrproper, since in that case .config is not -+# included; the values here are meaningless -+ -+CONFIG_NEST_LEVEL ?= 0 -+CONFIG_KERNEL_HALF_GIGS ?= 0 -+ -+SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) -+ -+# These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT + -+# CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case. -+ -+LINK_TT = -static -+LD_SCRIPT_TT := link.ld -+ -+ifeq ($(CONFIG_STATIC_LINK),y) -+ LINK-y += $(LINK_TT) -+ LD_SCRIPT-y := $(LD_SCRIPT_TT) -+else -+ifeq ($(CONFIG_MODE_TT),y) -+ LINK-y += $(LINK_TT) -+ LD_SCRIPT-y := $(LD_SCRIPT_TT) -+else -+ifeq ($(CONFIG_MODE_SKAS),y) -+ LINK-y += $(LINK_SKAS) -+ LD_SCRIPT-y := $(LD_SCRIPT_SKAS) -+endif -+endif -+endif -+ -+LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y) -+M4_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT) -+ -+$(LD_SCRIPT-y): $(LD_SCRIPT-y).in -+ pages=$$(( 1 << $(CONFIG_KERNEL_STACK_ORDER) )) ; \ -+ m4 -DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \ -+ -DELF_FORMAT=$(ELF_FORMAT) $(M4_MODE_TT) \ -+ -DKERNEL_STACK_SIZE=$$(( 4096 * $$pages )) $< > $@ -+ -+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ -+ arch-signal.h -+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) -+ -+ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \ -+ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h -+ -+ifeq ($(CONFIG_MODE_SKAS), y) -+$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h -+endif -+ -+GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h -+ -+setup: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) -+ -+linux: setup $(ARCH_DIR)/main.o vmlinux $(LD_SCRIPT-y) -+ mv vmlinux vmlinux.o -+ $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \ -+ -o linux $(ARCH_DIR)/main.o vmlinux.o -L/usr/lib -lutil -+ -+USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) -+USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS)) -+USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ -+ $(MODE_INCLUDE) -+ -+# To get a definition of F_SETSIG -+USER_CFLAGS += -D_GNU_SOURCE -+ -+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/link.ld $(ARCH_DIR)/dyn_link.ld \ -+ $(GEN_HEADERS) $(ARCH_DIR)/include/uml-config.h -+ -+$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c -+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+archmrproper: -+ rm -f $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \ -+ $(LD_SCRIPT) $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) -+ -+archclean: sysclean -+ find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -+ -o -name '*.gcov' \) -type f -print | xargs rm -f -+ cd $(ARCH_DIR) ; \ -+ for dir in $(subdir-y) util ; do $(MAKE) -C $$dir clean; done -+ -+archdep: -+ -+$(SYMLINK_HEADERS): -+ cd $(TOPDIR)/$(dir $@) ; \ -+ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) -+ -+include/asm-um/arch: -+ cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch -+ -+arch/um/include/sysdep: -+ cd $(TOPDIR)/arch/um/include && ln -sf sysdep-$(SUBARCH) sysdep -+ -+arch/um/os: -+ cd $(ARCH_DIR) && ln -sf os-$(OS) os -+ -+$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task -+ $< > $@ -+ -+$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants -+ $< > $@ -+ -+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h -+ sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@ -+ -+$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/util/mk_task_user.c \ -+ $(ARCH_DIR)/util/mk_task_kern.c $(SYS_HEADERS) -+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_task -+ -+$(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util/mk_constants_user.c \ -+ $(ARCH_DIR)/util/mk_constants_kern.c -+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_constants -+ -+export SUBARCH USER_CFLAGS OS -diff -Naur -X ../exclude-files orig/arch/um/Makefile-i386 um/arch/um/Makefile-i386 ---- orig/arch/um/Makefile-i386 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile-i386 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,35 @@ -+ifeq ($(CONFIG_HOST_2G_2G), y) -+TOP_ADDR = 0x80000000 -+else -+TOP_ADDR = 0xc0000000 -+endif -+ -+ARCH_CFLAGS = -U__$(SUBARCH)__ -U$(SUBARCH) -DUM_FASTCALL -+ELF_ARCH = $(SUBARCH) -+ELF_FORMAT = elf32-$(SUBARCH) -+ -+I386_H = $(ARCH_DIR)/include/sysdep-i386 -+SYS = $(ARCH_DIR)/sys-i386 -+UTIL = $(SYS)/util -+SUBDIRS += $(UTIL) -+ -+SYS_HEADERS = $(I386_H)/sc.h $(I386_H)/thread.h -+ -+$(I386_H)/sc.h : $(UTIL)/mk_sc -+ $(UTIL)/mk_sc > $@ -+ -+$(I386_H)/thread.h : $(UTIL)/mk_thread -+ $(UTIL)/mk_thread > $@ -+ -+$(UTIL)/mk_sc : $(UTIL)/mk_sc.c -+ $(MAKE) -C $(UTIL) mk_sc -+ -+$(UTIL)/mk_thread : $(UTIL)/mk_thread_user.c $(UTIL)/mk_thread_kern.c \ -+ $(I386_H)/sc.h -+ $(MAKE) -C $(UTIL) mk_thread -+ -+sysclean : -+ rm -f $(SYS_HEADERS) -+ $(MAKE) -C $(UTIL) clean -+ $(MAKE) -C $(SYS) clean -+ -diff -Naur -X ../exclude-files orig/arch/um/Makefile-ia64 um/arch/um/Makefile-ia64 ---- orig/arch/um/Makefile-ia64 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile-ia64 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1 @@ -+START_ADDR = 0x1000000000000000 -diff -Naur -X ../exclude-files orig/arch/um/Makefile-os-Linux um/arch/um/Makefile-os-Linux ---- orig/arch/um/Makefile-os-Linux 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile-os-Linux 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,7 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+SUBDIRS += $(ARCH_DIR)/os-$(OS)/drivers -+DRIVERS += $(ARCH_DIR)/os-$(OS)/drivers/drivers.o -diff -Naur -X ../exclude-files orig/arch/um/Makefile-ppc um/arch/um/Makefile-ppc ---- orig/arch/um/Makefile-ppc 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile-ppc 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,9 @@ -+ifeq ($(CONFIG_HOST_2G_2G), y) -+START_ADDR = 0x80000000 -+else -+START_ADDR = 0xc0000000 -+endif -+ARCH_CFLAGS = -U__powerpc__ -D__UM_PPC__ -+ -+# The arch is ppc, but the elf32 name is powerpc -+ELF_SUBARCH = powerpc -diff -Naur -X ../exclude-files orig/arch/um/Makefile-skas um/arch/um/Makefile-skas ---- orig/arch/um/Makefile-skas 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile-skas 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,20 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+PROFILE += -pg -+ -+CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage -+CFLAGS-$(CONFIG_GPROF) += $(PROFILE) -+LINK-$(CONFIG_GPROF) += $(PROFILE) -+ -+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include -+ -+LINK_SKAS = -Wl,-rpath,/lib -+LD_SCRIPT_SKAS = dyn_link.ld -+ -+GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h -+ -+$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h : -+ $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h -diff -Naur -X ../exclude-files orig/arch/um/Makefile-tt um/arch/um/Makefile-tt ---- orig/arch/um/Makefile-tt 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/Makefile-tt 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,7 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include -+ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/etap.h um/arch/um/os-Linux/drivers/etap.h ---- orig/arch/um/os-Linux/drivers/etap.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/etap.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct ethertap_data { -+ char *dev_name; -+ char *gate_addr; -+ int data_fd; -+ int control_fd; -+ void *dev; -+}; -+ -+extern struct net_user_info ethertap_user_info; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/ethertap_kern.c um/arch/um/os-Linux/drivers/ethertap_kern.c ---- orig/arch/um/os-Linux/drivers/ethertap_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/ethertap_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,122 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/init.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "etap.h" -+ -+struct ethertap_init { -+ char *dev_name; -+ char *gate_addr; -+}; -+ -+static void etap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct ethertap_data *epri; -+ struct ethertap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ epri = (struct ethertap_data *) pri->user; -+ *epri = ((struct ethertap_data) -+ { .dev_name = init->dev_name, -+ .gate_addr = init->gate_addr, -+ .data_fd = -1, -+ .control_fd = -1, -+ .dev = dev }); -+ -+ printk("ethertap backend - %s", epri->dev_name); -+ if(epri->gate_addr != NULL) -+ printk(", IP = %s", epri->gate_addr); -+ printk("\n"); -+} -+ -+static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ int len; -+ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); -+ if(*skb == NULL) return(-ENOMEM); -+ len = net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); -+ if(len <= 0) return(len); -+ skb_pull(*skb, 2); -+ len -= 2; -+ return(len); -+} -+ -+static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ if(skb_headroom(*skb) < 2){ -+ struct sk_buff *skb2; -+ -+ skb2 = skb_realloc_headroom(*skb, 2); -+ dev_kfree_skb(*skb); -+ if (skb2 == NULL) return(-ENOMEM); -+ *skb = skb2; -+ } -+ skb_push(*skb, 2); -+ return(net_send(fd, (*skb)->data, (*skb)->len)); -+} -+ -+struct net_kern_info ethertap_kern_info = { -+ .init = etap_init, -+ .protocol = eth_protocol, -+ .read = etap_read, -+ .write = etap_write, -+}; -+ -+int ethertap_setup(char *str, char **mac_out, void *data) -+{ -+ struct ethertap_init *init = data; -+ -+ *init = ((struct ethertap_init) -+ { .dev_name = NULL, -+ .gate_addr = NULL }); -+ if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, -+ &init->gate_addr)) -+ return(0); -+ if(init->dev_name == NULL){ -+ printk("ethertap_setup : Missing tap device name\n"); -+ return(0); -+ } -+ -+ return(1); -+} -+ -+static struct transport ethertap_transport = { -+ .list = LIST_HEAD_INIT(ethertap_transport.list), -+ .name = "ethertap", -+ .setup = ethertap_setup, -+ .user = ðertap_user_info, -+ .kern = ðertap_kern_info, -+ .private_size = sizeof(struct ethertap_data), -+}; -+ -+static int register_ethertap(void) -+{ -+ register_transport(ðertap_transport); -+ return(1); -+} -+ -+__initcall(register_ethertap); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/ethertap_user.c um/arch/um/os-Linux/drivers/ethertap_user.c ---- orig/arch/um/os-Linux/drivers/ethertap_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/ethertap_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,238 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stddef.h> -+#include <stdlib.h> -+#include <sys/errno.h> -+#include <sys/socket.h> -+#include <sys/wait.h> -+#include <sys/un.h> -+#include <net/if.h> -+#include "user.h" -+#include "kern_util.h" -+#include "net_user.h" -+#include "etap.h" -+#include "helper.h" -+#include "os.h" -+ -+#define MAX_PACKET ETH_MAX_PACKET -+ -+void etap_user_init(void *data, void *dev) -+{ -+ struct ethertap_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+struct addr_change { -+ enum { ADD_ADDR, DEL_ADDR } what; -+ unsigned char addr[4]; -+ unsigned char netmask[4]; -+}; -+ -+static void etap_change(int op, unsigned char *addr, unsigned char *netmask, -+ int fd) -+{ -+ struct addr_change change; -+ void *output; -+ int n; -+ -+ change.what = op; -+ memcpy(change.addr, addr, sizeof(change.addr)); -+ memcpy(change.netmask, netmask, sizeof(change.netmask)); -+ n = os_write_file(fd, &change, sizeof(change)); -+ if(n != sizeof(change)) -+ printk("etap_change - request failed, err = %d\n", -n); -+ output = um_kmalloc(page_size()); -+ if(output == NULL) -+ printk("etap_change : Failed to allocate output buffer\n"); -+ read_output(fd, output, page_size()); -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+} -+ -+static void etap_open_addr(unsigned char *addr, unsigned char *netmask, -+ void *arg) -+{ -+ etap_change(ADD_ADDR, addr, netmask, *((int *) arg)); -+} -+ -+static void etap_close_addr(unsigned char *addr, unsigned char *netmask, -+ void *arg) -+{ -+ etap_change(DEL_ADDR, addr, netmask, *((int *) arg)); -+} -+ -+struct etap_pre_exec_data { -+ int control_remote; -+ int control_me; -+ int data_me; -+}; -+ -+static void etap_pre_exec(void *arg) -+{ -+ struct etap_pre_exec_data *data = arg; -+ -+ dup2(data->control_remote, 1); -+ os_close_file(data->data_me); -+ os_close_file(data->control_me); -+} -+ -+static int etap_tramp(char *dev, char *gate, int control_me, -+ int control_remote, int data_me, int data_remote) -+{ -+ struct etap_pre_exec_data pe_data; -+ int pid, status, err, n; -+ char version_buf[sizeof("nnnnn\0")]; -+ char data_fd_buf[sizeof("nnnnnn\0")]; -+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; -+ char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, -+ data_fd_buf, gate_buf, NULL }; -+ char *nosetup_args[] = { "uml_net", version_buf, "ethertap", -+ dev, data_fd_buf, NULL }; -+ char **args, c; -+ -+ sprintf(data_fd_buf, "%d", data_remote); -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ if(gate != NULL){ -+ strcpy(gate_buf, gate); -+ args = setup_args; -+ } -+ else args = nosetup_args; -+ -+ err = 0; -+ pe_data.control_remote = control_remote; -+ pe_data.control_me = control_me; -+ pe_data.data_me = data_me; -+ pid = run_helper(etap_pre_exec, &pe_data, args, NULL); -+ -+ if(pid < 0) err = pid; -+ os_close_file(data_remote); -+ os_close_file(control_remote); -+ n = os_read_file(control_me, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("etap_tramp : read of status failed, err = %d\n", -n); -+ return(-EINVAL); -+ } -+ if(c != 1){ -+ printk("etap_tramp : uml_net failed\n"); -+ err = -EINVAL; -+ if(waitpid(pid, &status, 0) < 0) -+ err = -errno; -+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) -+ printk("uml_net didn't exit with status 1\n"); -+ } -+ return(err); -+} -+ -+static int etap_open(void *data) -+{ -+ struct ethertap_data *pri = data; -+ char *output; -+ int data_fds[2], control_fds[2], err, output_len; -+ -+ err = tap_open_common(pri->dev, pri->gate_addr); -+ if(err) return(err); -+ -+ err = os_pipe(data_fds, 0, 0); -+ if(err < 0){ -+ printk("data os_pipe failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ err = os_pipe(control_fds, 1, 0); -+ if(err < 0){ -+ printk("control os_pipe failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], -+ control_fds[1], data_fds[0], data_fds[1]); -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ read_output(control_fds[0], output, output_len); -+ -+ if(output == NULL) -+ printk("etap_open : failed to allocate output buffer\n"); -+ else { -+ printk("%s", output); -+ kfree(output); -+ } -+ -+ if(err < 0){ -+ printk("etap_tramp failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ pri->data_fd = data_fds[0]; -+ pri->control_fd = control_fds[0]; -+ iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); -+ return(data_fds[0]); -+} -+ -+static void etap_close(int fd, void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); -+ os_close_file(fd); -+ os_shutdown_socket(pri->data_fd, 1, 1); -+ os_close_file(pri->data_fd); -+ pri->data_fd = -1; -+ os_close_file(pri->control_fd); -+ pri->control_fd = -1; -+} -+ -+static int etap_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+static void etap_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ tap_check_ips(pri->gate_addr, addr); -+ if(pri->control_fd == -1) return; -+ etap_open_addr(addr, netmask, &pri->control_fd); -+} -+ -+static void etap_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ if(pri->control_fd == -1) return; -+ etap_close_addr(addr, netmask, &pri->control_fd); -+} -+ -+struct net_user_info ethertap_user_info = { -+ .init = etap_user_init, -+ .open = etap_open, -+ .close = etap_close, -+ .remove = NULL, -+ .set_mtu = etap_set_mtu, -+ .add_address = etap_add_addr, -+ .delete_address = etap_del_addr, -+ .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/Makefile um/arch/um/os-Linux/drivers/Makefile ---- orig/arch/um/os-Linux/drivers/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,31 @@ -+# -+# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := drivers.o -+ -+list-multi := tuntap.o ethertap.o -+ -+ethertap-objs := ethertap_kern.o ethertap_user.o -+tuntap-objs := tuntap_kern.o tuntap_user.o -+ -+obj-y = -+obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o -+obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o -+ -+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y)),$($(f)-objs)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+ethertap.o : $(ethertap-objs) -+ -+tuntap.o : $(tuntap-objs) -+ -+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)' -+ $(LD) $(LD_RFLAG) -r -o $@ $($(patsubst %.o,%,$@)-objs) -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap.h um/arch/um/os-Linux/drivers/tuntap.h ---- orig/arch/um/os-Linux/drivers/tuntap.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/tuntap.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_TUNTAP_H -+#define __UM_TUNTAP_H -+ -+#include "net_user.h" -+ -+struct tuntap_data { -+ char *dev_name; -+ int fixed_config; -+ char *gate_addr; -+ int fd; -+ void *dev; -+}; -+ -+extern struct net_user_info tuntap_user_info; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap_kern.c um/arch/um/os-Linux/drivers/tuntap_kern.c ---- orig/arch/um/os-Linux/drivers/tuntap_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/tuntap_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,105 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/skbuff.h" -+#include "linux/init.h" -+#include "asm/errno.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "tuntap.h" -+ -+struct tuntap_init { -+ char *dev_name; -+ char *gate_addr; -+}; -+ -+static void tuntap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct tuntap_data *tpri; -+ struct tuntap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ tpri = (struct tuntap_data *) pri->user; -+ *tpri = ((struct tuntap_data) -+ { .dev_name = init->dev_name, -+ .fixed_config = (init->dev_name != NULL), -+ .gate_addr = init->gate_addr, -+ .fd = -1, -+ .dev = dev }); -+ printk("TUN/TAP backend - "); -+ if(tpri->gate_addr != NULL) -+ printk("IP = %s", tpri->gate_addr); -+ printk("\n"); -+} -+ -+static int tuntap_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_read(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int tuntap_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(net_write(fd, (*skb)->data, (*skb)->len)); -+} -+ -+struct net_kern_info tuntap_kern_info = { -+ .init = tuntap_init, -+ .protocol = eth_protocol, -+ .read = tuntap_read, -+ .write = tuntap_write, -+}; -+ -+int tuntap_setup(char *str, char **mac_out, void *data) -+{ -+ struct tuntap_init *init = data; -+ -+ *init = ((struct tuntap_init) -+ { .dev_name = NULL, -+ .gate_addr = NULL }); -+ if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, -+ &init->gate_addr)) -+ return(0); -+ -+ return(1); -+} -+ -+static struct transport tuntap_transport = { -+ .list = LIST_HEAD_INIT(tuntap_transport.list), -+ .name = "tuntap", -+ .setup = tuntap_setup, -+ .user = &tuntap_user_info, -+ .kern = &tuntap_kern_info, -+ .private_size = sizeof(struct tuntap_data), -+ .setup_size = sizeof(struct tuntap_init), -+}; -+ -+static int register_tuntap(void) -+{ -+ register_transport(&tuntap_transport); -+ return(1); -+} -+ -+__initcall(register_tuntap); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/drivers/tuntap_user.c um/arch/um/os-Linux/drivers/tuntap_user.c ---- orig/arch/um/os-Linux/drivers/tuntap_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/drivers/tuntap_user.c 2003-11-12 00:02:30.000000000 -0500 -@@ -0,0 +1,224 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stddef.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <sys/wait.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/uio.h> -+#include <sys/ioctl.h> -+#include <net/if.h> -+#include <linux/if_tun.h> -+#include "net_user.h" -+#include "tuntap.h" -+#include "kern_util.h" -+#include "user.h" -+#include "helper.h" -+#include "os.h" -+ -+#define MAX_PACKET ETH_MAX_PACKET -+ -+void tuntap_user_init(void *data, void *dev) -+{ -+ struct tuntap_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ tap_check_ips(pri->gate_addr, addr); -+ if((pri->fd == -1) || pri->fixed_config) return; -+ open_addr(addr, netmask, pri->dev_name); -+} -+ -+static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ if((pri->fd == -1) || pri->fixed_config) return; -+ close_addr(addr, netmask, pri->dev_name); -+} -+ -+struct tuntap_pre_exec_data { -+ int stdout; -+ int close_me; -+}; -+ -+static void tuntap_pre_exec(void *arg) -+{ -+ struct tuntap_pre_exec_data *data = arg; -+ -+ dup2(data->stdout, 1); -+ os_close_file(data->close_me); -+} -+ -+static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, -+ char *buffer, int buffer_len, int *used_out) -+{ -+ struct tuntap_pre_exec_data data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, -+ NULL }; -+ char buf[CMSG_SPACE(sizeof(*fd_out))]; -+ struct msghdr msg; -+ struct cmsghdr *cmsg; -+ struct iovec iov; -+ int pid, n; -+ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ -+ data.stdout = remote; -+ data.close_me = me; -+ -+ pid = run_helper(tuntap_pre_exec, &data, argv, NULL); -+ -+ if(pid < 0) return(-pid); -+ -+ os_close_file(remote); -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ if(buffer != NULL){ -+ iov = ((struct iovec) { buffer, buffer_len }); -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ } -+ else { -+ msg.msg_iov = NULL; -+ msg.msg_iovlen = 0; -+ } -+ msg.msg_control = buf; -+ msg.msg_controllen = sizeof(buf); -+ msg.msg_flags = 0; -+ n = recvmsg(me, &msg, 0); -+ *used_out = n; -+ if(n < 0){ -+ printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ waitpid(pid, NULL, 0); -+ -+ cmsg = CMSG_FIRSTHDR(&msg); -+ if(cmsg == NULL){ -+ printk("tuntap_open_tramp : didn't receive a message\n"); -+ return(-EINVAL); -+ } -+ if((cmsg->cmsg_level != SOL_SOCKET) || -+ (cmsg->cmsg_type != SCM_RIGHTS)){ -+ printk("tuntap_open_tramp : didn't receive a descriptor\n"); -+ return(-EINVAL); -+ } -+ *fd_out = ((int *) CMSG_DATA(cmsg))[0]; -+ return(0); -+} -+ -+static int tuntap_open(void *data) -+{ -+ struct ifreq ifr; -+ struct tuntap_data *pri = data; -+ char *output, *buffer; -+ int err, fds[2], len, used; -+ -+ err = tap_open_common(pri->dev, pri->gate_addr); -+ if(err < 0) -+ return(err); -+ -+ if(pri->fixed_config){ -+ pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); -+ if(pri->fd < 0){ -+ printk("Failed to open /dev/net/tun, err = %d\n", -+ -pri->fd); -+ return(pri->fd); -+ } -+ memset(&ifr, 0, sizeof(ifr)); -+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; -+ strncpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name) - 1); -+ if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ -+ printk("TUNSETIFF failed, errno = %d\n", errno); -+ os_close_file(pri->fd); -+ return(-errno); -+ } -+ } -+ else { -+ err = os_pipe(fds, 0, 0); -+ if(err < 0){ -+ printk("tuntap_open : os_pipe failed - err = %d\n", -+ -err); -+ return(err); -+ } -+ -+ buffer = get_output_buffer(&len); -+ if(buffer != NULL) len--; -+ used = 0; -+ -+ err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], -+ fds[1], buffer, len, &used); -+ -+ output = buffer; -+ if(err < 0) { -+ printk("%s", output); -+ free_output_buffer(buffer); -+ printk("tuntap_open_tramp failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ pri->dev_name = uml_strdup(buffer); -+ output += IFNAMSIZ; -+ printk("%s", output); -+ free_output_buffer(buffer); -+ -+ os_close_file(fds[0]); -+ iter_addresses(pri->dev, open_addr, pri->dev_name); -+ } -+ -+ return(pri->fd); -+} -+ -+static void tuntap_close(int fd, void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ if(!pri->fixed_config) -+ iter_addresses(pri->dev, close_addr, pri->dev_name); -+ os_close_file(fd); -+ pri->fd = -1; -+} -+ -+static int tuntap_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info tuntap_user_info = { -+ .init = tuntap_user_init, -+ .open = tuntap_open, -+ .close = tuntap_close, -+ .remove = NULL, -+ .set_mtu = tuntap_set_mtu, -+ .add_address = tuntap_add_addr, -+ .delete_address = tuntap_del_addr, -+ .max_packet = MAX_PACKET -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/file.c um/arch/um/os-Linux/file.c ---- orig/arch/um/os-Linux/file.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/file.c 2004-01-10 06:52:24.000000000 -0500 -@@ -0,0 +1,668 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <errno.h> -+#include <fcntl.h> -+#include <signal.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/ioctl.h> -+#include <sys/mount.h> -+#include <sys/uio.h> -+#include "os.h" -+#include "user.h" -+#include "kern_util.h" -+ -+static void copy_stat(struct uml_stat *dst, struct stat64 *src) -+{ -+ *dst = ((struct uml_stat) { -+ .ust_dev = src->st_dev, /* device */ -+ .ust_ino = src->st_ino, /* inode */ -+ .ust_mode = src->st_mode, /* protection */ -+ .ust_nlink = src->st_nlink, /* number of hard links */ -+ .ust_uid = src->st_uid, /* user ID of owner */ -+ .ust_gid = src->st_gid, /* group ID of owner */ -+ .ust_size = src->st_size, /* total size, in bytes */ -+ .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ -+ .ust_blocks = src->st_blocks, /* number of blocks allocated */ -+ .ust_atime = src->st_atime, /* time of last access */ -+ .ust_mtime = src->st_mtime, /* time of last modification */ -+ .ust_ctime = src->st_ctime, /* time of last change */ -+ }); -+} -+ -+int os_stat_fd(const int fd, struct uml_stat *ubuf) -+{ -+ struct stat64 sbuf; -+ int err; -+ -+ do { -+ err = fstat64(fd, &sbuf); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ if(ubuf != NULL) -+ copy_stat(ubuf, &sbuf); -+ return(err); -+} -+ -+int os_stat_file(const char *file_name, struct uml_stat *ubuf) -+{ -+ struct stat64 sbuf; -+ int err; -+ -+ do { -+ err = stat64(file_name, &sbuf); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ if(ubuf != NULL) -+ copy_stat(ubuf, &sbuf); -+ return(err); -+} -+ -+int os_access(const char* file, int mode) -+{ -+ int amode, err; -+ -+ amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | -+ (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; -+ -+ err = access(file, amode); -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+void os_print_error(int error, const char* str) -+{ -+ errno = error < 0 ? -error : error; -+ -+ perror(str); -+} -+ -+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ -+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) -+{ -+ int err; -+ -+ err = ioctl(fd, cmd, arg); -+ if(err < 0) -+ return(-errno); -+ -+ return(err); -+} -+ -+int os_window_size(int fd, int *rows, int *cols) -+{ -+ struct winsize size; -+ -+ if(ioctl(fd, TIOCGWINSZ, &size) < 0) -+ return(-errno); -+ -+ *rows = size.ws_row; -+ *cols = size.ws_col; -+ -+ return(0); -+} -+ -+int os_new_tty_pgrp(int fd, int pid) -+{ -+ if(ioctl(fd, TIOCSCTTY, 0) < 0){ -+ printk("TIOCSCTTY failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(tcsetpgrp(fd, pid) < 0){ -+ printk("tcsetpgrp failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+/* FIXME: ensure namebuf in os_get_if_name is big enough */ -+int os_get_ifname(int fd, char* namebuf) -+{ -+ if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_set_slip(int fd) -+{ -+ int disc, sencap; -+ -+ disc = N_SLIP; -+ if(ioctl(fd, TIOCSETD, &disc) < 0){ -+ printk("Failed to set slip line discipline - " -+ "errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ sencap = 0; -+ if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ -+ printk("Failed to set slip encapsulation - " -+ "errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_set_owner(int fd, int pid) -+{ -+ if(fcntl(fd, F_SETOWN, pid) < 0){ -+ int save_errno = errno; -+ -+ if(fcntl(fd, F_GETOWN, 0) != pid) -+ return(-save_errno); -+ } -+ -+ return(0); -+} -+ -+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ -+int os_sigio_async(int master, int slave) -+{ -+ int flags; -+ -+ flags = fcntl(master, F_GETFL); -+ if(flags < 0) { -+ printk("fcntl F_GETFL failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || -+ (fcntl(master, F_SETOWN, os_getpid()) < 0)){ -+ printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ -+ printk("fcntl F_SETFL failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_mode_fd(int fd, int mode) -+{ -+ int err; -+ -+ do { -+ err = fchmod(fd, mode); -+ } while((err < 0) && (errno==EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_file_type(char *file) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_stat_file(file, &buf); -+ if(err < 0) -+ return(err); -+ -+ if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR); -+ else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK); -+ else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV); -+ else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV); -+ else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO); -+ else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK); -+ else return(OS_TYPE_FILE); -+} -+ -+int os_file_mode(char *file, struct openflags *mode_out) -+{ -+ int err; -+ -+ *mode_out = OPENFLAGS(); -+ -+ err = os_access(file, OS_ACC_W_OK); -+ if((err < 0) && (err != -EACCES)) -+ return(err); -+ -+ *mode_out = of_write(*mode_out); -+ -+ err = os_access(file, OS_ACC_R_OK); -+ if((err < 0) && (err != -EACCES)) -+ return(err); -+ -+ *mode_out = of_read(*mode_out); -+ -+ return(0); -+} -+ -+int os_open_file(char *file, struct openflags flags, int mode) -+{ -+ int fd, f = 0; -+ -+ if(flags.r && flags.w) f = O_RDWR; -+ else if(flags.r) f = O_RDONLY; -+ else if(flags.w) f = O_WRONLY; -+ else f = 0; -+ -+ if(flags.s) f |= O_SYNC; -+ if(flags.c) f |= O_CREAT; -+ if(flags.t) f |= O_TRUNC; -+ if(flags.e) f |= O_EXCL; -+ -+ fd = open64(file, f, mode); -+ if(fd < 0) -+ return(-errno); -+ -+ if(flags.cl && fcntl(fd, F_SETFD, 1)){ -+ os_close_file(fd); -+ return(-errno); -+ } -+ -+ return(fd); -+} -+ -+int os_connect_socket(char *name) -+{ -+ struct sockaddr_un sock; -+ int fd, err; -+ -+ sock.sun_family = AF_UNIX; -+ snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); -+ -+ fd = socket(AF_UNIX, SOCK_STREAM, 0); -+ if(fd < 0) -+ return(fd); -+ -+ err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); -+ if(err) -+ return(-errno); -+ -+ return(fd); -+} -+ -+void os_close_file(int fd) -+{ -+ close(fd); -+} -+ -+int os_seek_file(int fd, __u64 offset) -+{ -+ __u64 actual; -+ -+ actual = lseek64(fd, offset, SEEK_SET); -+ if(actual != offset) return(-errno); -+ return(0); -+} -+ -+static int fault_buffer(void *start, int len, -+ int (*copy_proc)(void *addr, void *buf, int len)) -+{ -+ int page = getpagesize(), i; -+ char c; -+ -+ for(i = 0; i < len; i += page){ -+ if((*copy_proc)(start + i, &c, sizeof(c))) -+ return(-EFAULT); -+ } -+ if((len % page) != 0){ -+ if((*copy_proc)(start + len - 1, &c, sizeof(c))) -+ return(-EFAULT); -+ } -+ return(0); -+} -+ -+static int file_io(int fd, void *buf, int len, -+ int (*io_proc)(int fd, void *buf, int len), -+ int (*copy_user_proc)(void *addr, void *buf, int len)) -+{ -+ int n, err; -+ -+ do { -+ n = (*io_proc)(fd, buf, len); -+ if((n < 0) && (errno == EFAULT)){ -+ err = fault_buffer(buf, len, copy_user_proc); -+ if(err) -+ return(err); -+ n = (*io_proc)(fd, buf, len); -+ } -+ } while((n < 0) && (errno == EINTR)); -+ -+ if(n < 0) -+ return(-errno); -+ return(n); -+} -+ -+int os_read_file(int fd, void *buf, int len) -+{ -+ return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, -+ copy_from_user_proc)); -+} -+ -+int os_write_file(int fd, const void *buf, int len) -+{ -+ return(file_io(fd, (void *) buf, len, -+ (int (*)(int, void *, int)) write, copy_to_user_proc)); -+} -+ -+int os_file_size(char *file, long long *size_out) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_stat_file(file, &buf); -+ if(err < 0){ -+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); -+ return(err); -+ } -+ -+ if(S_ISBLK(buf.ust_mode)){ -+ int fd, blocks; -+ -+ fd = os_open_file(file, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open \"%s\", errno = %d\n", file, -fd); -+ return(fd); -+ } -+ if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ -+ printk("Couldn't get the block size of \"%s\", " -+ "errno = %d\n", file, errno); -+ err = -errno; -+ os_close_file(fd); -+ return(err); -+ } -+ *size_out = ((long long) blocks) * 512; -+ os_close_file(fd); -+ return(0); -+ } -+ *size_out = buf.ust_size; -+ return(0); -+} -+ -+int os_file_modtime(char *file, unsigned long *modtime) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_stat_file(file, &buf); -+ if(err < 0){ -+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); -+ return(err); -+ } -+ -+ *modtime = buf.ust_mtime; -+ return(0); -+} -+ -+int os_get_exec_close(int fd, int* close_on_exec) -+{ -+ int ret; -+ -+ do { -+ ret = fcntl(fd, F_GETFD); -+ } while((ret < 0) && (errno == EINTR)) ; -+ -+ if(ret < 0) -+ return(-errno); -+ -+ *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; -+ return(ret); -+} -+ -+int os_set_exec_close(int fd, int close_on_exec) -+{ -+ int flag, err; -+ -+ if(close_on_exec) flag = FD_CLOEXEC; -+ else flag = 0; -+ -+ do { -+ err = fcntl(fd, F_SETFD, flag); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ return(err); -+} -+ -+int os_pipe(int *fds, int stream, int close_on_exec) -+{ -+ int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; -+ -+ err = socketpair(AF_UNIX, type, 0, fds); -+ if(err < 0) -+ return(-errno); -+ -+ if(!close_on_exec) -+ return(0); -+ -+ err = os_set_exec_close(fds[0], 1); -+ if(err < 0) -+ goto error; -+ -+ err = os_set_exec_close(fds[1], 1); -+ if(err < 0) -+ goto error; -+ -+ return(0); -+ -+ error: -+ printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); -+ os_close_file(fds[1]); -+ os_close_file(fds[0]); -+ return(err); -+} -+ -+int os_set_fd_async(int fd, int owner) -+{ -+ /* XXX This should do F_GETFL first */ -+ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ -+ printk("os_set_fd_async : failed to set O_ASYNC and " -+ "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); -+ return(-errno); -+ } -+#ifdef notdef -+ if(fcntl(fd, F_SETFD, 1) < 0){ -+ printk("os_set_fd_async : Setting FD_CLOEXEC failed, " -+ "errno = %d\n", errno); -+ } -+#endif -+ -+ if((fcntl(fd, F_SETSIG, SIGIO) < 0) || -+ (fcntl(fd, F_SETOWN, owner) < 0)){ -+ printk("os_set_fd_async : Failed to fcntl F_SETOWN " -+ "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, -+ owner, errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_set_fd_block(int fd, int blocking) -+{ -+ int flags; -+ -+ flags = fcntl(fd, F_GETFL); -+ -+ if(blocking) flags &= ~O_NONBLOCK; -+ else flags |= O_NONBLOCK; -+ -+ if(fcntl(fd, F_SETFL, flags) < 0){ -+ printk("Failed to change blocking on fd # %d, errno = %d\n", -+ fd, errno); -+ return(-errno); -+ } -+ return(0); -+} -+ -+int os_accept_connection(int fd) -+{ -+ int new; -+ -+ new = accept(fd, NULL, 0); -+ if(new < 0) -+ return(-errno); -+ return(new); -+} -+ -+#ifndef SHUT_RD -+#define SHUT_RD 0 -+#endif -+ -+#ifndef SHUT_WR -+#define SHUT_WR 1 -+#endif -+ -+#ifndef SHUT_RDWR -+#define SHUT_RDWR 2 -+#endif -+ -+int os_shutdown_socket(int fd, int r, int w) -+{ -+ int what, err; -+ -+ if(r && w) what = SHUT_RDWR; -+ else if(r) what = SHUT_RD; -+ else if(w) what = SHUT_WR; -+ else { -+ printk("os_shutdown_socket : neither r or w was set\n"); -+ return(-EINVAL); -+ } -+ err = shutdown(fd, what); -+ if(err < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_rcv_fd(int fd, int *helper_pid_out) -+{ -+ int new, n; -+ char buf[CMSG_SPACE(sizeof(new))]; -+ struct msghdr msg; -+ struct cmsghdr *cmsg; -+ struct iovec iov; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ iov = ((struct iovec) { .iov_base = helper_pid_out, -+ .iov_len = sizeof(*helper_pid_out) }); -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_control = buf; -+ msg.msg_controllen = sizeof(buf); -+ msg.msg_flags = 0; -+ -+ n = recvmsg(fd, &msg, 0); -+ if(n < 0) -+ return(-errno); -+ -+ else if(n != sizeof(iov.iov_len)) -+ *helper_pid_out = -1; -+ -+ cmsg = CMSG_FIRSTHDR(&msg); -+ if(cmsg == NULL){ -+ printk("rcv_fd didn't receive anything, error = %d\n", errno); -+ return(-1); -+ } -+ if((cmsg->cmsg_level != SOL_SOCKET) || -+ (cmsg->cmsg_type != SCM_RIGHTS)){ -+ printk("rcv_fd didn't receive a descriptor\n"); -+ return(-1); -+ } -+ -+ new = ((int *) CMSG_DATA(cmsg))[0]; -+ return(new); -+} -+ -+int os_create_unix_socket(char *file, int len, int close_on_exec) -+{ -+ struct sockaddr_un addr; -+ int sock, err; -+ -+ sock = socket(PF_UNIX, SOCK_DGRAM, 0); -+ if (sock < 0){ -+ printk("create_unix_socket - socket failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ if(close_on_exec) { -+ err = os_set_exec_close(sock, 1); -+ if(err < 0) -+ printk("create_unix_socket : close_on_exec failed, " -+ "err = %d", -err); -+ } -+ -+ addr.sun_family = AF_UNIX; -+ -+ /* XXX Be more careful about overflow */ -+ snprintf(addr.sun_path, len, "%s", file); -+ -+ err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); -+ if (err < 0){ -+ printk("create_listening_socket at '%s' - bind failed, " -+ "errno = %d\n", file, errno); -+ return(-errno); -+ } -+ -+ return(sock); -+} -+ -+void os_flush_stdout(void) -+{ -+ fflush(stdout); -+} -+ -+int os_lock_file(int fd, int excl) -+{ -+ int type = excl ? F_WRLCK : F_RDLCK; -+ struct flock lock = ((struct flock) { .l_type = type, -+ .l_whence = SEEK_SET, -+ .l_start = 0, -+ .l_len = 0 } ); -+ int err, save; -+ -+ err = fcntl(fd, F_SETLK, &lock); -+ if(!err) -+ goto out; -+ -+ save = -errno; -+ err = fcntl(fd, F_GETLK, &lock); -+ if(err){ -+ err = -errno; -+ goto out; -+ } -+ -+ printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); -+ err = save; -+ out: -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/include/file.h um/arch/um/os-Linux/include/file.h ---- orig/arch/um/os-Linux/include/file.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/include/file.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __OS_FILE_H__ -+#define __OS_FILE_H__ -+ -+#define DEV_NULL "/dev/null" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/Makefile um/arch/um/os-Linux/Makefile ---- orig/arch/um/os-Linux/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = file.o process.o tty.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(obj-y) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -+ -+archmrproper: -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/process.c um/arch/um/os-Linux/process.c ---- orig/arch/um/os-Linux/process.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/process.c 2004-01-10 06:53:44.000000000 -0500 -@@ -0,0 +1,148 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <errno.h> -+#include <signal.h> -+#include <sys/mman.h> -+#include <sys/wait.h> -+#include "os.h" -+#include "user.h" -+ -+#define ARBITRARY_ADDR -1 -+#define FAILURE_PID -1 -+ -+unsigned long os_process_pc(int pid) -+{ -+ char proc_stat[sizeof("/proc/#####/stat\0")], buf[256]; -+ unsigned long pc; -+ int fd, err; -+ -+ sprintf(proc_stat, "/proc/%d/stat", pid); -+ fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("os_process_pc - couldn't open '%s', err = %d\n", -+ proc_stat, -fd); -+ return(ARBITRARY_ADDR); -+ } -+ err = os_read_file(fd, buf, sizeof(buf)); -+ if(err < 0){ -+ printk("os_process_pc - couldn't read '%s', err = %d\n", -+ proc_stat, -err); -+ os_close_file(fd); -+ return(ARBITRARY_ADDR); -+ } -+ os_close_file(fd); -+ pc = ARBITRARY_ADDR; -+ if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d " -+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " -+ "%*d %*d %*d %*d %ld", &pc) != 1){ -+ printk("os_process_pc - couldn't find pc in '%s'\n", buf); -+ } -+ return(pc); -+} -+ -+int os_process_parent(int pid) -+{ -+ char stat[sizeof("/proc/nnnnn/stat\0")]; -+ char data[256]; -+ int parent, n, fd; -+ -+ if(pid == -1) return(-1); -+ -+ snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); -+ fd = os_open_file(stat, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open '%s', err = %d\n", stat, -fd); -+ return(FAILURE_PID); -+ } -+ -+ n = os_read_file(fd, data, sizeof(data)); -+ os_close_file(fd); -+ -+ if(n < 0){ -+ printk("Couldn't read '%s', err = %d\n", stat, -n); -+ return(FAILURE_PID); -+ } -+ -+ parent = FAILURE_PID; -+ /* XXX This will break if there is a space in the command */ -+ n = sscanf(data, "%*d %*s %*c %d", &parent); -+ if(n != 1) -+ printk("Failed to scan '%s'\n", data); -+ -+ return(parent); -+} -+ -+void os_stop_process(int pid) -+{ -+ kill(pid, SIGSTOP); -+} -+ -+void os_kill_process(int pid, int reap_child) -+{ -+ kill(pid, SIGKILL); -+ if(reap_child) -+ waitpid(pid, NULL, 0); -+ -+} -+ -+void os_usr1_process(int pid) -+{ -+ kill(pid, SIGUSR1); -+} -+ -+int os_getpid(void) -+{ -+ return(getpid()); -+} -+ -+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, -+ int r, int w, int x) -+{ -+ void *loc; -+ int prot; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ -+ loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, -+ fd, off); -+ if(loc == MAP_FAILED) -+ return(-errno); -+ return(0); -+} -+ -+int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) -+{ -+ int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0)); -+ -+ if(mprotect(addr, len, prot) < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_unmap_memory(void *addr, int len) -+{ -+ int err; -+ -+ err = munmap(addr, len); -+ if(err < 0) -+ return(-errno); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/os-Linux/tty.c um/arch/um/os-Linux/tty.c ---- orig/arch/um/os-Linux/tty.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/os-Linux/tty.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include "os.h" -+#include "user.h" -+#include "kern_util.h" -+ -+struct grantpt_info { -+ int fd; -+ int res; -+ int err; -+}; -+ -+static void grantpt_cb(void *arg) -+{ -+ struct grantpt_info *info = arg; -+ -+ info->res = grantpt(info->fd); -+ info->err = errno; -+} -+ -+int get_pty(void) -+{ -+ struct grantpt_info info; -+ int fd; -+ -+ fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); -+ return(fd); -+ } -+ -+ info.fd = fd; -+ initial_thread_cb(grantpt_cb, &info); -+ -+ if(info.res < 0){ -+ printk("get_pty : Couldn't grant pty - errno = %d\n", -+ -info.err); -+ return(-1); -+ } -+ if(unlockpt(fd) < 0){ -+ printk("get_pty : Couldn't unlock pty - errno = %d\n", errno); -+ return(-1); -+ } -+ return(fd); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/bugs.c um/arch/um/sys-i386/bugs.c ---- orig/arch/um/sys-i386/bugs.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/bugs.c 2004-01-21 22:42:39.000000000 -0500 -@@ -0,0 +1,222 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <errno.h> -+#include <string.h> -+#include <sys/signal.h> -+#include <asm/ldt.h> -+#include "kern_util.h" -+#include "user.h" -+#include "sysdep/ptrace.h" -+#include "task.h" -+#include "os.h" -+ -+#define MAXTOKEN 64 -+ -+/* Set during early boot */ -+int host_has_cmov = 1; -+int host_has_xmm = 0; -+ -+static char token(int fd, char *buf, int len, char stop) -+{ -+ int n; -+ char *ptr, *end, c; -+ -+ ptr = buf; -+ end = &buf[len]; -+ do { -+ n = os_read_file(fd, ptr, sizeof(*ptr)); -+ c = *ptr++; -+ if(n != sizeof(*ptr)){ -+ if(n == 0) return(0); -+ printk("Reading /proc/cpuinfo failed, err = %d\n", -n); -+ if(n < 0) -+ return(n); -+ else -+ return(-EIO); -+ } -+ } while((c != '\n') && (c != stop) && (ptr < end)); -+ -+ if(ptr == end){ -+ printk("Failed to find '%c' in /proc/cpuinfo\n", stop); -+ return(-1); -+ } -+ *(ptr - 1) = '\0'; -+ return(c); -+} -+ -+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) -+{ -+ int n; -+ char c; -+ -+ scratch[len - 1] = '\0'; -+ while(1){ -+ c = token(fd, scratch, len - 1, ':'); -+ if(c <= 0) -+ return(0); -+ else if(c != ':'){ -+ printk("Failed to find ':' in /proc/cpuinfo\n"); -+ return(0); -+ } -+ -+ if(!strncmp(scratch, key, strlen(key))) -+ return(1); -+ -+ do { -+ n = os_read_file(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("Failed to find newline in " -+ "/proc/cpuinfo, err = %d\n", -n); -+ return(0); -+ } -+ } while(c != '\n'); -+ } -+ return(0); -+} -+ -+int cpu_feature(char *what, char *buf, int len) -+{ -+ int fd, ret = 0; -+ -+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); -+ return(0); -+ } -+ -+ if(!find_cpuinfo_line(fd, what, buf, len)){ -+ printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); -+ goto out_close; -+ } -+ -+ token(fd, buf, len, '\n'); -+ ret = 1; -+ -+ out_close: -+ os_close_file(fd); -+ return(ret); -+} -+ -+static int check_cpu_flag(char *feature, int *have_it) -+{ -+ char buf[MAXTOKEN], c; -+ int fd, len = sizeof(buf)/sizeof(buf[0]); -+ -+ printk("Checking for host processor %s support...", feature); -+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); -+ return(0); -+ } -+ -+ *have_it = 0; -+ if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0]))) -+ goto out; -+ -+ c = token(fd, buf, len - 1, ' '); -+ if(c < 0) goto out; -+ else if(c != ' '){ -+ printk("Failed to find ' ' in /proc/cpuinfo\n"); -+ goto out; -+ } -+ -+ while(1){ -+ c = token(fd, buf, len - 1, ' '); -+ if(c < 0) goto out; -+ else if(c == '\n') break; -+ -+ if(!strcmp(buf, feature)){ -+ *have_it = 1; -+ goto out; -+ } -+ } -+ out: -+ if(*have_it == 0) printk("No\n"); -+ else if(*have_it == 1) printk("Yes\n"); -+ os_close_file(fd); -+ return(1); -+} -+ -+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems -+ * for some people. -+ */ -+static void disable_lcall(void) -+{ -+ struct modify_ldt_ldt_s ldt; -+ int err; -+ -+ bzero(&ldt, sizeof(ldt)); -+ ldt.entry_number = 7; -+ ldt.base_addr = 0; -+ ldt.limit = 0; -+ err = modify_ldt(1, &ldt, sizeof(ldt)); -+ if(err) -+ printk("Failed to disable lcall7 - errno = %d\n", errno); -+} -+#endif -+ -+void arch_init_thread(void) -+{ -+#if 0 -+ disable_lcall(); -+#endif -+} -+ -+void arch_check_bugs(void) -+{ -+ int have_it; -+ -+ if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ -+ printk("/proc/cpuinfo not available - skipping CPU capability " -+ "checks\n"); -+ return; -+ } -+ if(check_cpu_flag("cmov", &have_it)) -+ host_has_cmov = have_it; -+ if(check_cpu_flag("xmm", &have_it)) -+ host_has_xmm = have_it; -+} -+ -+int arch_handle_signal(int sig, union uml_pt_regs *regs) -+{ -+ unsigned char tmp[2]; -+ -+ /* This is testing for a cmov (0x0f 0x4x) instruction causing a -+ * SIGILL in init. -+ */ -+ if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0); -+ -+ if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) -+ panic("SIGILL in init, could not read instructions!\n"); -+ if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) -+ return(0); -+ -+ if(host_has_cmov == 0) -+ panic("SIGILL caused by cmov, which this processor doesn't " -+ "implement, boot a filesystem compiled for older " -+ "processors"); -+ else if(host_has_cmov == 1) -+ panic("SIGILL caused by cmov, which this processor claims to " -+ "implement"); -+ else if(host_has_cmov == -1) -+ panic("SIGILL caused by cmov, couldn't tell if this processor " -+ "implements it, boot a filesystem compiled for older " -+ "processors"); -+ else panic("Bad value for host_has_cmov (%d)", host_has_cmov); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/checksum.S um/arch/um/sys-i386/checksum.S ---- orig/arch/um/sys-i386/checksum.S 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/checksum.S 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,460 @@ -+/* -+ * INET An implementation of the TCP/IP protocol suite for the LINUX -+ * operating system. INET is implemented using the BSD Socket -+ * interface as the means of communication with the user level. -+ * -+ * IP/TCP/UDP checksumming routines -+ * -+ * Authors: Jorge Cwik, <jorge@laser.satlink.net> -+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no> -+ * Tom May, <ftom@netcom.com> -+ * Pentium Pro/II routines: -+ * Alexander Kjeldaas <astor@guardian.no> -+ * Finn Arne Gangstad <finnag@guardian.no> -+ * Lots of code moved from tcp.c and ip.c; see those files -+ * for more names. -+ * -+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception -+ * handling. -+ * Andi Kleen, add zeroing on error -+ * converted to pure assembler -+ * -+ * 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. -+ */ -+ -+#include <linux/config.h> -+#include <asm/errno.h> -+ -+/* -+ * computes a partial checksum, e.g. for TCP/UDP fragments -+ */ -+ -+/* -+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) -+ */ -+ -+.text -+.align 4 -+.globl arch_csum_partial -+ -+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM -+ -+ /* -+ * Experiments with Ethernet and SLIP connections show that buff -+ * is aligned on either a 2-byte or 4-byte boundary. We get at -+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned. -+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte -+ * alignment for the unrolled loop. -+ */ -+arch_csum_partial: -+ pushl %esi -+ pushl %ebx -+ movl 20(%esp),%eax # Function arg: unsigned int sum -+ movl 16(%esp),%ecx # Function arg: int len -+ movl 12(%esp),%esi # Function arg: unsigned char *buff -+ testl $2, %esi # Check alignment. -+ jz 2f # Jump if alignment is ok. -+ subl $2, %ecx # Alignment uses up two bytes. -+ jae 1f # Jump if we had at least two bytes. -+ addl $2, %ecx # ecx was < 2. Deal with it. -+ jmp 4f -+1: movw (%esi), %bx -+ addl $2, %esi -+ addw %bx, %ax -+ adcl $0, %eax -+2: -+ movl %ecx, %edx -+ shrl $5, %ecx -+ jz 2f -+ testl %esi, %esi -+1: movl (%esi), %ebx -+ adcl %ebx, %eax -+ movl 4(%esi), %ebx -+ adcl %ebx, %eax -+ movl 8(%esi), %ebx -+ adcl %ebx, %eax -+ movl 12(%esi), %ebx -+ adcl %ebx, %eax -+ movl 16(%esi), %ebx -+ adcl %ebx, %eax -+ movl 20(%esi), %ebx -+ adcl %ebx, %eax -+ movl 24(%esi), %ebx -+ adcl %ebx, %eax -+ movl 28(%esi), %ebx -+ adcl %ebx, %eax -+ lea 32(%esi), %esi -+ dec %ecx -+ jne 1b -+ adcl $0, %eax -+2: movl %edx, %ecx -+ andl $0x1c, %edx -+ je 4f -+ shrl $2, %edx # This clears CF -+3: adcl (%esi), %eax -+ lea 4(%esi), %esi -+ dec %edx -+ jne 3b -+ adcl $0, %eax -+4: andl $3, %ecx -+ jz 7f -+ cmpl $2, %ecx -+ jb 5f -+ movw (%esi),%cx -+ leal 2(%esi),%esi -+ je 6f -+ shll $16,%ecx -+5: movb (%esi),%cl -+6: addl %ecx,%eax -+ adcl $0, %eax -+7: -+ popl %ebx -+ popl %esi -+ ret -+ -+#else -+ -+/* Version for PentiumII/PPro */ -+ -+arch_csum_partial: -+ pushl %esi -+ pushl %ebx -+ movl 20(%esp),%eax # Function arg: unsigned int sum -+ movl 16(%esp),%ecx # Function arg: int len -+ movl 12(%esp),%esi # Function arg: const unsigned char *buf -+ -+ testl $2, %esi -+ jnz 30f -+10: -+ movl %ecx, %edx -+ movl %ecx, %ebx -+ andl $0x7c, %ebx -+ shrl $7, %ecx -+ addl %ebx,%esi -+ shrl $2, %ebx -+ negl %ebx -+ lea 45f(%ebx,%ebx,2), %ebx -+ testl %esi, %esi -+ jmp *%ebx -+ -+ # Handle 2-byte-aligned regions -+20: addw (%esi), %ax -+ lea 2(%esi), %esi -+ adcl $0, %eax -+ jmp 10b -+ -+30: subl $2, %ecx -+ ja 20b -+ je 32f -+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned -+ addl %ebx, %eax -+ adcl $0, %eax -+ jmp 80f -+32: -+ addw (%esi), %ax # csumming 2 bytes, 2-aligned -+ adcl $0, %eax -+ jmp 80f -+ -+40: -+ addl -128(%esi), %eax -+ adcl -124(%esi), %eax -+ adcl -120(%esi), %eax -+ adcl -116(%esi), %eax -+ adcl -112(%esi), %eax -+ adcl -108(%esi), %eax -+ adcl -104(%esi), %eax -+ adcl -100(%esi), %eax -+ adcl -96(%esi), %eax -+ adcl -92(%esi), %eax -+ adcl -88(%esi), %eax -+ adcl -84(%esi), %eax -+ adcl -80(%esi), %eax -+ adcl -76(%esi), %eax -+ adcl -72(%esi), %eax -+ adcl -68(%esi), %eax -+ adcl -64(%esi), %eax -+ adcl -60(%esi), %eax -+ adcl -56(%esi), %eax -+ adcl -52(%esi), %eax -+ adcl -48(%esi), %eax -+ adcl -44(%esi), %eax -+ adcl -40(%esi), %eax -+ adcl -36(%esi), %eax -+ adcl -32(%esi), %eax -+ adcl -28(%esi), %eax -+ adcl -24(%esi), %eax -+ adcl -20(%esi), %eax -+ adcl -16(%esi), %eax -+ adcl -12(%esi), %eax -+ adcl -8(%esi), %eax -+ adcl -4(%esi), %eax -+45: -+ lea 128(%esi), %esi -+ adcl $0, %eax -+ dec %ecx -+ jge 40b -+ movl %edx, %ecx -+50: andl $3, %ecx -+ jz 80f -+ -+ # Handle the last 1-3 bytes without jumping -+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked -+ movl $0xffffff,%ebx # by the shll and shrl instructions -+ shll $3,%ecx -+ shrl %cl,%ebx -+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok -+ addl %ebx,%eax -+ adcl $0,%eax -+80: -+ popl %ebx -+ popl %esi -+ ret -+ -+#endif -+ -+/* -+unsigned int csum_partial_copy_generic (const char *src, char *dst, -+ int len, int sum, int *src_err_ptr, int *dst_err_ptr) -+ */ -+ -+/* -+ * Copy from ds while checksumming, otherwise like csum_partial -+ * -+ * The macros SRC and DST specify the type of access for the instruction. -+ * thus we can call a custom exception handler for all access types. -+ * -+ * FIXME: could someone double-check whether I haven't mixed up some SRC and -+ * DST definitions? It's damn hard to trigger all cases. I hope I got -+ * them all but there's no guarantee. -+ */ -+ -+#define SRC(y...) \ -+ 9999: y; \ -+ .section __ex_table, "a"; \ -+ .long 9999b, 6001f ; \ -+ .previous -+ -+#define DST(y...) \ -+ 9999: y; \ -+ .section __ex_table, "a"; \ -+ .long 9999b, 6002f ; \ -+ .previous -+ -+.align 4 -+.globl csum_partial_copy_generic_i386 -+ -+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM -+ -+#define ARGBASE 16 -+#define FP 12 -+ -+csum_partial_copy_generic_i386: -+ subl $4,%esp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ movl ARGBASE+16(%esp),%eax # sum -+ movl ARGBASE+12(%esp),%ecx # len -+ movl ARGBASE+4(%esp),%esi # src -+ movl ARGBASE+8(%esp),%edi # dst -+ -+ testl $2, %edi # Check alignment. -+ jz 2f # Jump if alignment is ok. -+ subl $2, %ecx # Alignment uses up two bytes. -+ jae 1f # Jump if we had at least two bytes. -+ addl $2, %ecx # ecx was < 2. Deal with it. -+ jmp 4f -+SRC(1: movw (%esi), %bx ) -+ addl $2, %esi -+DST( movw %bx, (%edi) ) -+ addl $2, %edi -+ addw %bx, %ax -+ adcl $0, %eax -+2: -+ movl %ecx, FP(%esp) -+ shrl $5, %ecx -+ jz 2f -+ testl %esi, %esi -+SRC(1: movl (%esi), %ebx ) -+SRC( movl 4(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, (%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 4(%edi) ) -+ -+SRC( movl 8(%esi), %ebx ) -+SRC( movl 12(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 8(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 12(%edi) ) -+ -+SRC( movl 16(%esi), %ebx ) -+SRC( movl 20(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 16(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 20(%edi) ) -+ -+SRC( movl 24(%esi), %ebx ) -+SRC( movl 28(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 24(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 28(%edi) ) -+ -+ lea 32(%esi), %esi -+ lea 32(%edi), %edi -+ dec %ecx -+ jne 1b -+ adcl $0, %eax -+2: movl FP(%esp), %edx -+ movl %edx, %ecx -+ andl $0x1c, %edx -+ je 4f -+ shrl $2, %edx # This clears CF -+SRC(3: movl (%esi), %ebx ) -+ adcl %ebx, %eax -+DST( movl %ebx, (%edi) ) -+ lea 4(%esi), %esi -+ lea 4(%edi), %edi -+ dec %edx -+ jne 3b -+ adcl $0, %eax -+4: andl $3, %ecx -+ jz 7f -+ cmpl $2, %ecx -+ jb 5f -+SRC( movw (%esi), %cx ) -+ leal 2(%esi), %esi -+DST( movw %cx, (%edi) ) -+ leal 2(%edi), %edi -+ je 6f -+ shll $16,%ecx -+SRC(5: movb (%esi), %cl ) -+DST( movb %cl, (%edi) ) -+6: addl %ecx, %eax -+ adcl $0, %eax -+7: -+5000: -+ -+# Exception handler: -+.section .fixup, "ax" -+ -+6001: -+ movl ARGBASE+20(%esp), %ebx # src_err_ptr -+ movl $-EFAULT, (%ebx) -+ -+ # zero the complete destination - computing the rest -+ # is too much work -+ movl ARGBASE+8(%esp), %edi # dst -+ movl ARGBASE+12(%esp), %ecx # len -+ xorl %eax,%eax -+ rep ; stosb -+ -+ jmp 5000b -+ -+6002: -+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr -+ movl $-EFAULT,(%ebx) -+ jmp 5000b -+ -+.previous -+ -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ecx # equivalent to addl $4,%esp -+ ret -+ -+#else -+ -+/* Version for PentiumII/PPro */ -+ -+#define ROUND1(x) \ -+ SRC(movl x(%esi), %ebx ) ; \ -+ addl %ebx, %eax ; \ -+ DST(movl %ebx, x(%edi) ) ; -+ -+#define ROUND(x) \ -+ SRC(movl x(%esi), %ebx ) ; \ -+ adcl %ebx, %eax ; \ -+ DST(movl %ebx, x(%edi) ) ; -+ -+#define ARGBASE 12 -+ -+csum_partial_copy_generic_i386: -+ pushl %ebx -+ pushl %edi -+ pushl %esi -+ movl ARGBASE+4(%esp),%esi #src -+ movl ARGBASE+8(%esp),%edi #dst -+ movl ARGBASE+12(%esp),%ecx #len -+ movl ARGBASE+16(%esp),%eax #sum -+# movl %ecx, %edx -+ movl %ecx, %ebx -+ movl %esi, %edx -+ shrl $6, %ecx -+ andl $0x3c, %ebx -+ negl %ebx -+ subl %ebx, %esi -+ subl %ebx, %edi -+ lea -1(%esi),%edx -+ andl $-32,%edx -+ lea 3f(%ebx,%ebx), %ebx -+ testl %esi, %esi -+ jmp *%ebx -+1: addl $64,%esi -+ addl $64,%edi -+ SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl) -+ ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52) -+ ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36) -+ ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20) -+ ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4) -+3: adcl $0,%eax -+ addl $64, %edx -+ dec %ecx -+ jge 1b -+4: movl ARGBASE+12(%esp),%edx #len -+ andl $3, %edx -+ jz 7f -+ cmpl $2, %edx -+ jb 5f -+SRC( movw (%esi), %dx ) -+ leal 2(%esi), %esi -+DST( movw %dx, (%edi) ) -+ leal 2(%edi), %edi -+ je 6f -+ shll $16,%edx -+5: -+SRC( movb (%esi), %dl ) -+DST( movb %dl, (%edi) ) -+6: addl %edx, %eax -+ adcl $0, %eax -+7: -+.section .fixup, "ax" -+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr -+ movl $-EFAULT, (%ebx) -+ # zero the complete destination (computing the rest is too much work) -+ movl ARGBASE+8(%esp),%edi # dst -+ movl ARGBASE+12(%esp),%ecx # len -+ xorl %eax,%eax -+ rep; stosb -+ jmp 7b -+6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr -+ movl $-EFAULT, (%ebx) -+ jmp 7b -+.previous -+ -+ popl %esi -+ popl %edi -+ popl %ebx -+ ret -+ -+#undef ROUND -+#undef ROUND1 -+ -+#endif -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/fault.c um/arch/um/sys-i386/fault.c ---- orig/arch/um/sys-i386/fault.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/fault.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+ -+extern unsigned long search_exception_table(unsigned long addr); -+ -+int arch_fixup(unsigned long address, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ unsigned long fixup; -+ -+ fixup = search_exception_table(address); -+ if(fixup != 0){ -+ sc->eip = fixup; -+ return(1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ksyms.c um/arch/um/sys-i386/ksyms.c ---- orig/arch/um/sys-i386/ksyms.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/ksyms.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,17 @@ -+#include "linux/module.h" -+#include "linux/in6.h" -+#include "linux/rwsem.h" -+#include "asm/byteorder.h" -+#include "asm/semaphore.h" -+#include "asm/uaccess.h" -+#include "asm/checksum.h" -+#include "asm/errno.h" -+ -+EXPORT_SYMBOL(__down_failed); -+EXPORT_SYMBOL(__down_failed_interruptible); -+EXPORT_SYMBOL(__down_failed_trylock); -+EXPORT_SYMBOL(__up_wakeup); -+ -+/* Networking helper routines. */ -+EXPORT_SYMBOL(csum_partial_copy_from); -+EXPORT_SYMBOL(csum_partial_copy_to); -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ldt.c um/arch/um/sys-i386/ldt.c ---- orig/arch/um/sys-i386/ldt.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/ldt.c 2004-01-19 04:01:11.000000000 -0500 -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/slab.h" -+#include "asm/uaccess.h" -+#include "asm/ptrace.h" -+#include "choose-mode.h" -+#include "kern.h" -+ -+#ifdef CONFIG_MODE_TT -+extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -+ -+/* XXX this needs copy_to_user and copy_from_user */ -+ -+int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -+{ -+ if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT); -+ return(modify_ldt(func, ptr, bytecount)); -+} -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+extern int userspace_pid; -+ -+int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -+{ -+ struct ptrace_ldt ldt; -+ void *buf; -+ int res, n; -+ -+ buf = kmalloc(bytecount, GFP_KERNEL); -+ if(buf == NULL) -+ return(-ENOMEM); -+ -+ res = 0; -+ -+ switch(func){ -+ case 1: -+ case 0x11: -+ res = copy_from_user(buf, ptr, bytecount); -+ break; -+ } -+ -+ if(res != 0){ -+ res = -EFAULT; -+ goto out; -+ } -+ -+ ldt = ((struct ptrace_ldt) { .func = func, -+ .ptr = buf, -+ .bytecount = bytecount }); -+ res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt); -+ if(res < 0) -+ goto out; -+ -+ switch(func){ -+ case 0: -+ case 2: -+ n = res; -+ res = copy_to_user(ptr, buf, n); -+ if(res != 0) -+ res = -EFAULT; -+ else -+ res = n; -+ break; -+ } -+ -+ out: -+ kfree(buf); -+ return(res); -+} -+#endif -+ -+int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) -+{ -+ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, -+ ptr, bytecount)); -+} -+ -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/Makefile um/arch/um/sys-i386/Makefile ---- orig/arch/um/sys-i386/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/Makefile 2003-11-09 11:55:24.000000000 -0500 -@@ -0,0 +1,46 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o ptrace.o \ -+ ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o time.o -+export-objs = ksyms.o -+ -+USER_OBJS = bugs.o ptrace_user.o sigcontext.o fault.o -+ -+SYMLINKS = semaphore.c extable.c -+ -+semaphore.c-dir = kernel -+extable.c-dir = mm -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+define make_link -+ -rm -f $1 -+ ln -sf $(TOPDIR)/arch/i386/$($1-dir)/$1 $1 -+endef -+ -+$(SYMLINKS): -+ $(call make_link,$@) -+ -+clean: -+ $(MAKE) -C util clean -+ rm -f $(SYMLINKS) -+ -+fastdep: -+ -+dep: -+ -+archmrproper: -+ -+archclean: -+ -+archdep: -+ -+modules: -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ptrace.c um/arch/um/sys-i386/ptrace.c ---- orig/arch/um/sys-i386/ptrace.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/ptrace.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,365 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "asm/elf.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "ptrace_user.h" -+#include "sysdep/sigcontext.h" -+#include "sysdep/sc.h" -+ -+void arch_switch(void) -+{ -+ update_debugregs(current->thread.arch.debugregs_seq); -+} -+ -+int is_syscall(unsigned long addr) -+{ -+ unsigned short instr; -+ int n; -+ -+ n = copy_from_user(&instr, (void *) addr, sizeof(instr)); -+ if(n){ -+ printk("is_syscall : failed to read instruction from 0x%lu\n", -+ addr); -+ return(0); -+ } -+ return(instr == 0x80cd); -+} -+ -+/* determines which flags the user has access to. */ -+/* 1 = access 0 = no access */ -+#define FLAG_MASK 0x00044dd5 -+ -+int putreg(struct task_struct *child, int regno, unsigned long value) -+{ -+ regno >>= 2; -+ switch (regno) { -+ case FS: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ PT_REGS_FS(&child->thread.regs) = value; -+ return 0; -+ case GS: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ PT_REGS_GS(&child->thread.regs) = value; -+ return 0; -+ case DS: -+ case ES: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ value &= 0xffff; -+ break; -+ case SS: -+ case CS: -+ if ((value & 3) != 3) -+ return -EIO; -+ value &= 0xffff; -+ break; -+ case EFL: -+ value &= FLAG_MASK; -+ value |= PT_REGS_EFLAGS(&child->thread.regs); -+ break; -+ } -+ PT_REGS_SET(&child->thread.regs, regno, value); -+ return 0; -+} -+ -+unsigned long getreg(struct task_struct *child, int regno) -+{ -+ unsigned long retval = ~0UL; -+ -+ regno >>= 2; -+ switch (regno) { -+ case FS: -+ case GS: -+ case DS: -+ case ES: -+ case SS: -+ case CS: -+ retval = 0xffff; -+ /* fall through */ -+ default: -+ retval &= PT_REG(&child->thread.regs, regno); -+ } -+ return retval; -+} -+ -+struct i387_fxsave_struct { -+ unsigned short cwd; -+ unsigned short swd; -+ unsigned short twd; -+ unsigned short fop; -+ long fip; -+ long fcs; -+ long foo; -+ long fos; -+ long mxcsr; -+ long reserved; -+ long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ -+ long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ -+ long padding[56]; -+}; -+ -+/* -+ * FPU tag word conversions. -+ */ -+ -+static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) -+{ -+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */ -+ -+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */ -+ tmp = ~twd; -+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ -+ /* and move the valid bits to the lower byte. */ -+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ -+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ -+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ -+ return tmp; -+} -+ -+static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) -+{ -+ struct _fpxreg *st = NULL; -+ unsigned long twd = (unsigned long) fxsave->twd; -+ unsigned long tag; -+ unsigned long ret = 0xffff0000; -+ int i; -+ -+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); -+ -+ for ( i = 0 ; i < 8 ; i++ ) { -+ if ( twd & 0x1 ) { -+ st = (struct _fpxreg *) FPREG_ADDR( fxsave, i ); -+ -+ switch ( st->exponent & 0x7fff ) { -+ case 0x7fff: -+ tag = 2; /* Special */ -+ break; -+ case 0x0000: -+ if ( !st->significand[0] && -+ !st->significand[1] && -+ !st->significand[2] && -+ !st->significand[3] ) { -+ tag = 1; /* Zero */ -+ } else { -+ tag = 2; /* Special */ -+ } -+ break; -+ default: -+ if ( st->significand[3] & 0x8000 ) { -+ tag = 0; /* Valid */ -+ } else { -+ tag = 2; /* Special */ -+ } -+ break; -+ } -+ } else { -+ tag = 3; /* Empty */ -+ } -+ ret |= (tag << (2 * i)); -+ twd = twd >> 1; -+ } -+ return ret; -+} -+ -+/* -+ * FXSR floating point environment conversions. -+ */ -+ -+#ifdef CONFIG_MODE_TT -+static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, -+ struct pt_regs *regs) -+{ -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned long env[7]; -+ struct _fpreg *to; -+ struct _fpxreg *from; -+ int i; -+ -+ env[0] = (unsigned long)fxsave->cwd | 0xffff0000; -+ env[1] = (unsigned long)fxsave->swd | 0xffff0000; -+ env[2] = twd_fxsr_to_i387(fxsave); -+ env[3] = fxsave->fip; -+ env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); -+ env[5] = fxsave->foo; -+ env[6] = fxsave->fos; -+ -+ if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) ) -+ return 1; -+ -+ to = &buf->_st[0]; -+ from = (struct _fpxreg *) &fxsave->st_space[0]; -+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) { -+ if ( __copy_to_user( to, from, sizeof(*to) ) ) -+ return 1; -+ } -+ return 0; -+} -+#endif -+ -+static inline int convert_fxsr_to_user(struct _fpstate *buf, -+ struct pt_regs *regs) -+{ -+ return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); -+} -+ -+#ifdef CONFIG_MODE_TT -+static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, -+ struct _fpstate *buf) -+{ -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned long env[7]; -+ struct _fpxreg *to; -+ struct _fpreg *from; -+ int i; -+ -+ if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) -+ return 1; -+ -+ fxsave->cwd = (unsigned short)(env[0] & 0xffff); -+ fxsave->swd = (unsigned short)(env[1] & 0xffff); -+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); -+ fxsave->fip = env[3]; -+ fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16); -+ fxsave->fcs = (env[4] & 0xffff); -+ fxsave->foo = env[5]; -+ fxsave->fos = env[6]; -+ -+ to = (struct _fpxreg *) &fxsave->st_space[0]; -+ from = &buf->_st[0]; -+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) { -+ if ( __copy_from_user( to, from, sizeof(*from) ) ) -+ return 1; -+ } -+ return 0; -+} -+#endif -+ -+static inline int convert_fxsr_from_user(struct pt_regs *regs, -+ struct _fpstate *buf) -+{ -+ return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); -+} -+ -+int get_fpregs(unsigned long buf, struct task_struct *child) -+{ -+ int err; -+ -+ err = convert_fxsr_to_user((struct _fpstate *) buf, -+ &child->thread.regs); -+ if(err) return(-EFAULT); -+ else return(0); -+} -+ -+int set_fpregs(unsigned long buf, struct task_struct *child) -+{ -+ int err; -+ -+ err = convert_fxsr_from_user(&child->thread.regs, -+ (struct _fpstate *) buf); -+ if(err) return(-EFAULT); -+ else return(0); -+} -+ -+#ifdef CONFIG_MODE_TT -+int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -+{ -+ struct pt_regs *regs = &tsk->thread.regs; -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ int err; -+ -+ err = __copy_to_user((void *) buf, fxsave, -+ sizeof(struct user_fxsr_struct)); -+ if(err) return -EFAULT; -+ else return 0; -+} -+#endif -+ -+int get_fpxregs(unsigned long buf, struct task_struct *tsk) -+{ -+ return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0)); -+} -+ -+#ifdef CONFIG_MODE_TT -+int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -+{ -+ struct pt_regs *regs = &tsk->thread.regs; -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ int err; -+ -+ err = __copy_from_user(fxsave, (void *) buf, -+ sizeof(struct user_fxsr_struct) ); -+ if(err) return -EFAULT; -+ else return 0; -+} -+#endif -+ -+int set_fpxregs(unsigned long buf, struct task_struct *tsk) -+{ -+ return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0)); -+} -+ -+#ifdef notdef -+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -+{ -+ fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) | -+ (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff)); -+ fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; -+ fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs)); -+ fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; -+ fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs)); -+ fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs)); -+ fpu->fos = 0; -+ memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), -+ sizeof(fpu->st_space)); -+ return(1); -+} -+#endif -+ -+#ifdef CONFIG_MODE_TT -+static inline void copy_fpu_fxsave_tt(struct pt_regs *regs, -+ struct user_i387_struct *buf) -+{ -+ struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned short *to; -+ unsigned short *from; -+ int i; -+ -+ memcpy( buf, fpu, 7 * sizeof(long) ); -+ -+ to = (unsigned short *) &buf->st_space[0]; -+ from = (unsigned short *) &fpu->st_space[0]; -+ for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) { -+ memcpy( to, from, 5 * sizeof(unsigned short) ); -+ } -+} -+#endif -+ -+static inline void copy_fpu_fxsave(struct pt_regs *regs, -+ struct user_i387_struct *buf) -+{ -+ (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0); -+} -+ -+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) -+{ -+ copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu); -+ return(1); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/ptrace_user.c um/arch/um/sys-i386/ptrace_user.c ---- orig/arch/um/sys-i386/ptrace_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/ptrace_user.c 2003-12-17 01:33:17.000000000 -0500 -@@ -0,0 +1,117 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <errno.h> -+#include <unistd.h> -+#include <linux/stddef.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+#include <asm/user.h> -+#include "kern_util.h" -+#include "sysdep/thread.h" -+#include "user.h" -+#include "os.h" -+ -+int ptrace_getregs(long pid, unsigned long *regs_out) -+{ -+ return(ptrace(PTRACE_GETREGS, pid, 0, regs_out)); -+} -+ -+int ptrace_setregs(long pid, unsigned long *regs) -+{ -+ return(ptrace(PTRACE_SETREGS, pid, 0, regs)); -+} -+ -+int ptrace_getfpregs(long pid, unsigned long *regs) -+{ -+ return(ptrace(PTRACE_GETFPREGS, pid, 0, regs)); -+} -+ -+static void write_debugregs(int pid, unsigned long *regs) -+{ -+ struct user *dummy; -+ int nregs, i; -+ -+ dummy = NULL; -+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); -+ for(i = 0; i < nregs; i++){ -+ if((i == 4) || (i == 5)) continue; -+ if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i], -+ regs[i]) < 0) -+ printk("write_debugregs - ptrace failed on " -+ "register %d, errno = %d\n", errno); -+ } -+} -+ -+static void read_debugregs(int pid, unsigned long *regs) -+{ -+ struct user *dummy; -+ int nregs, i; -+ -+ dummy = NULL; -+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); -+ for(i = 0; i < nregs; i++){ -+ regs[i] = ptrace(PTRACE_PEEKUSER, pid, -+ &dummy->u_debugreg[i], 0); -+ } -+} -+ -+/* Accessed only by the tracing thread */ -+static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; -+static int debugregs_seq = 0; -+ -+void arch_enter_kernel(void *task, int pid) -+{ -+ read_debugregs(pid, TASK_DEBUGREGS(task)); -+ write_debugregs(pid, kernel_debugregs); -+} -+ -+void arch_leave_kernel(void *task, int pid) -+{ -+ read_debugregs(pid, kernel_debugregs); -+ write_debugregs(pid, TASK_DEBUGREGS(task)); -+} -+ -+void ptrace_pokeuser(unsigned long addr, unsigned long data) -+{ -+ if((addr < offsetof(struct user, u_debugreg[0])) || -+ (addr > offsetof(struct user, u_debugreg[7]))) -+ return; -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ if(kernel_debugregs[addr] == data) return; -+ -+ kernel_debugregs[addr] = data; -+ debugregs_seq++; -+} -+ -+static void update_debugregs_cb(void *arg) -+{ -+ int pid = *((int *) arg); -+ -+ write_debugregs(pid, kernel_debugregs); -+} -+ -+void update_debugregs(int seq) -+{ -+ int me; -+ -+ if(seq == debugregs_seq) return; -+ -+ me = os_getpid(); -+ initial_thread_cb(update_debugregs_cb, &me); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/sigcontext.c um/arch/um/sys-i386/sigcontext.c ---- orig/arch/um/sys-i386/sigcontext.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/sigcontext.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stddef.h> -+#include <string.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "kern_util.h" -+#include "frame_user.h" -+ -+int sc_size(void *data) -+{ -+ struct arch_frame_data *arch = data; -+ -+ return(sizeof(struct sigcontext) + arch->fpstate_size); -+} -+ -+void sc_to_sc(void *to_ptr, void *from_ptr) -+{ -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size; -+ -+ memcpy(to, from, size); -+ if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1); -+} -+ -+unsigned long *sc_sigmask(void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ -+ return(&sc->oldmask); -+} -+ -+int sc_get_fpregs(unsigned long buf, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf; -+ int err = 0; -+ -+ if(from == NULL){ -+ err |= clear_user_proc(&to->cw, sizeof(to->cw)); -+ err |= clear_user_proc(&to->sw, sizeof(to->sw)); -+ err |= clear_user_proc(&to->tag, sizeof(to->tag)); -+ err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff)); -+ err |= clear_user_proc(&to->cssel, sizeof(to->cssel)); -+ err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff)); -+ err |= clear_user_proc(&to->datasel, sizeof(to->datasel)); -+ err |= clear_user_proc(&to->_st, sizeof(to->_st)); -+ } -+ else { -+ err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw)); -+ err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw)); -+ err |= copy_to_user_proc(&to->tag, &from->tag, -+ sizeof(to->tag)); -+ err |= copy_to_user_proc(&to->ipoff, &from->ipoff, -+ sizeof(to->ipoff)); -+ err |= copy_to_user_proc(&to->cssel,& from->cssel, -+ sizeof(to->cssel)); -+ err |= copy_to_user_proc(&to->dataoff, &from->dataoff, -+ sizeof(to->dataoff)); -+ err |= copy_to_user_proc(&to->datasel, &from->datasel, -+ sizeof(to->datasel)); -+ err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st)); -+ } -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/syscalls.c um/arch/um/sys-i386/syscalls.c ---- orig/arch/um/sys-i386/syscalls.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/syscalls.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/mman.h" -+#include "asm/uaccess.h" -+#include "asm/unistd.h" -+ -+/* -+ * Perform the select(nd, in, out, ex, tv) and mmap() system -+ * calls. Linux/i386 didn't use to be able to handle more than -+ * 4 system call parameters, so these system calls used a memory -+ * block for parameter passing.. -+ */ -+ -+struct mmap_arg_struct { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+extern int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset); -+ -+int old_mmap_i386(struct mmap_arg_struct *arg) -+{ -+ struct mmap_arg_struct a; -+ int err = -EFAULT; -+ -+ if (copy_from_user(&a, arg, sizeof(a))) -+ goto out; -+ -+ err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); -+ out: -+ return err; -+} -+ -+struct sel_arg_struct { -+ unsigned long n; -+ fd_set *inp, *outp, *exp; -+ struct timeval *tvp; -+}; -+ -+int old_select(struct sel_arg_struct *arg) -+{ -+ struct sel_arg_struct a; -+ -+ if (copy_from_user(&a, arg, sizeof(a))) -+ return -EFAULT; -+ /* sys_select() does the appropriate kernel locking */ -+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/sysrq.c um/arch/um/sys-i386/sysrq.c ---- orig/arch/um/sys-i386/sysrq.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/sysrq.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,30 @@ -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "linux/sched.h" -+#include "asm/ptrace.h" -+#include "sysrq.h" -+ -+void show_regs(struct pt_regs *regs) -+{ -+ printk("\n"); -+ printk("EIP: %04lx:[<%08lx>] CPU: %d %s", -+ 0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs), -+ smp_processor_id(), print_tainted()); -+ if (PT_REGS_CS(regs) & 3) -+ printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs), -+ PT_REGS_SP(regs)); -+ printk(" EFLAGS: %08lx\n %s\n", PT_REGS_EFLAGS(regs), -+ print_tainted()); -+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", -+ PT_REGS_EAX(regs), PT_REGS_EBX(regs), -+ PT_REGS_ECX(regs), -+ PT_REGS_EDX(regs)); -+ printk("ESI: %08lx EDI: %08lx EBP: %08lx", -+ PT_REGS_ESI(regs), PT_REGS_EDI(regs), -+ PT_REGS_EBP(regs)); -+ printk(" DS: %04lx ES: %04lx\n", -+ 0xffff & PT_REGS_DS(regs), -+ 0xffff & PT_REGS_ES(regs)); -+ -+ show_trace((unsigned long *) ®s); -+} -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/time.c um/arch/um/sys-i386/time.c ---- orig/arch/um/sys-i386/time.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/time.c 2003-11-10 01:46:49.000000000 -0500 -@@ -0,0 +1,24 @@ -+/* -+ * sys-i386/time.c -+ * Created 25.9.2002 Sapan Bhatia -+ * -+ */ -+ -+unsigned long long time_stamp(void) -+{ -+ unsigned long low, high; -+ -+ asm("rdtsc" : "=a" (low), "=d" (high)); -+ return((((unsigned long long) high) << 32) + low); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/Makefile um/arch/um/sys-i386/util/Makefile ---- orig/arch/um/sys-i386/util/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/util/Makefile 2003-11-08 08:26:40.000000000 -0500 -@@ -0,0 +1,28 @@ -+EXE = mk_sc mk_thread -+ -+include $(TOPDIR)/Rules.make -+ -+all : $(EXE) -+ -+mk_sc : mk_sc.o -+ $(HOSTCC) -o mk_sc mk_sc.o -+ -+mk_sc.o : mk_sc.c -+ $(HOSTCC) -c $< -+ -+mk_thread : mk_thread_user.o mk_thread_kern.o -+ $(HOSTCC) -o mk_thread mk_thread_user.o mk_thread_kern.o -+ -+mk_thread_user.o : mk_thread_user.c -+ $(HOSTCC) -c $< -+ -+mk_thread_kern.o : mk_thread_kern.c -+ $(HOSTCC) $(CFLAGS) -c $< -+ -+clean : -+ $(RM) $(EXE) *.o -+ -+archmrproper : clean -+ -+fastdep : -+ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_sc.c um/arch/um/sys-i386/util/mk_sc.c ---- orig/arch/um/sys-i386/util/mk_sc.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/util/mk_sc.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,52 @@ -+#include <stdio.h> -+#include <signal.h> -+#include <linux/stddef.h> -+ -+#define SC_OFFSET(name, field) \ -+ printf("#define " name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\ -+ offsetof(struct sigcontext, field)) -+ -+#define SC_FP_OFFSET(name, field) \ -+ printf("#define " name \ -+ "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ -+ offsetof(struct _fpstate, field)) -+ -+#define SC_FP_OFFSET_PTR(name, field, type) \ -+ printf("#define " name \ -+ "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ -+ offsetof(struct _fpstate, field)) -+ -+int main(int argc, char **argv) -+{ -+ SC_OFFSET("SC_IP", eip); -+ SC_OFFSET("SC_SP", esp); -+ SC_OFFSET("SC_FS", fs); -+ SC_OFFSET("SC_GS", gs); -+ SC_OFFSET("SC_DS", ds); -+ SC_OFFSET("SC_ES", es); -+ SC_OFFSET("SC_SS", ss); -+ SC_OFFSET("SC_CS", cs); -+ SC_OFFSET("SC_EFLAGS", eflags); -+ SC_OFFSET("SC_EAX", eax); -+ SC_OFFSET("SC_EBX", ebx); -+ SC_OFFSET("SC_ECX", ecx); -+ SC_OFFSET("SC_EDX", edx); -+ SC_OFFSET("SC_EDI", edi); -+ SC_OFFSET("SC_ESI", esi); -+ SC_OFFSET("SC_EBP", ebp); -+ SC_OFFSET("SC_TRAPNO", trapno); -+ SC_OFFSET("SC_ERR", err); -+ SC_OFFSET("SC_CR2", cr2); -+ SC_OFFSET("SC_FPSTATE", fpstate); -+ SC_OFFSET("SC_SIGMASK", oldmask); -+ SC_FP_OFFSET("SC_FP_CW", cw); -+ SC_FP_OFFSET("SC_FP_SW", sw); -+ SC_FP_OFFSET("SC_FP_TAG", tag); -+ SC_FP_OFFSET("SC_FP_IPOFF", ipoff); -+ SC_FP_OFFSET("SC_FP_CSSEL", cssel); -+ SC_FP_OFFSET("SC_FP_DATAOFF", dataoff); -+ SC_FP_OFFSET("SC_FP_DATASEL", datasel); -+ SC_FP_OFFSET_PTR("SC_FP_ST", _st, "struct _fpstate"); -+ SC_FP_OFFSET_PTR("SC_FXSR_ENV", _fxsr_env, "void"); -+ return(0); -+} -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_thread_kern.c um/arch/um/sys-i386/util/mk_thread_kern.c ---- orig/arch/um/sys-i386/util/mk_thread_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/util/mk_thread_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,22 @@ -+#include "linux/config.h" -+#include "linux/stddef.h" -+#include "linux/sched.h" -+ -+extern void print_head(void); -+extern void print_constant_ptr(char *name, int value); -+extern void print_constant(char *name, char *type, int value); -+extern void print_tail(void); -+ -+#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field) -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs)); -+#ifdef CONFIG_MODE_TT -+ print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid)); -+#endif -+ print_tail(); -+ return(0); -+} -+ -diff -Naur -X ../exclude-files orig/arch/um/sys-i386/util/mk_thread_user.c um/arch/um/sys-i386/util/mk_thread_user.c ---- orig/arch/um/sys-i386/util/mk_thread_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-i386/util/mk_thread_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,30 @@ -+#include <stdio.h> -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_thread\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __UM_THREAD_H\n"); -+ printf("#define __UM_THREAD_H\n"); -+ printf("\n"); -+} -+ -+void print_constant_ptr(char *name, int value) -+{ -+ printf("#define %s(task) ((unsigned long *) " -+ "&(((char *) (task))[%d]))\n", name, value); -+} -+ -+void print_constant(char *name, char *type, int value) -+{ -+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, -+ value); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -diff -Naur -X ../exclude-files orig/arch/um/sys-ia64/Makefile um/arch/um/sys-ia64/Makefile ---- orig/arch/um/sys-ia64/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ia64/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,26 @@ -+OBJ = sys.o -+ -+OBJS = -+ -+all: $(OBJ) -+ -+$(OBJ): $(OBJS) -+ rm -f $@ -+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -+clean: -+ rm -f $(OBJS) -+ -+fastdep: -+ -+archmrproper: -+ -+archclean: -+ rm -f link.ld -+ @$(MAKEBOOT) clean -+ -+archdep: -+ @$(MAKEBOOT) dep -+ -+modules: -+ -+include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/Makefile um/arch/um/sys-ppc/Makefile ---- orig/arch/um/sys-ppc/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/Makefile 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,80 @@ -+OBJ = sys.o -+ -+.S.o: -+ $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ -+OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ -+ ptrace_user.o sysrq.o -+ -+EXTRA_AFLAGS := -DCONFIG_ALL_PPC -I. -I$(TOPDIR)/arch/ppc/kernel -+ -+all: $(OBJ) -+ -+$(OBJ): $(OBJS) -+ rm -f $@ -+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -+ -+ptrace_user.o: ptrace_user.c -+ $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+sigcontext.o: sigcontext.c -+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+semaphore.c: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+checksum.S: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/lib/$@ $@ -+ -+mk_defs.c: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+ppc_defs.head: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+ppc_defs.h: mk_defs.c ppc_defs.head \ -+ $(TOPDIR)/include/asm-ppc/mmu.h \ -+ $(TOPDIR)/include/asm-ppc/processor.h \ -+ $(TOPDIR)/include/asm-ppc/pgtable.h \ -+ $(TOPDIR)/include/asm-ppc/ptrace.h -+# $(CC) $(CFLAGS) -S mk_defs.c -+ cp ppc_defs.head ppc_defs.h -+# for bk, this way we can write to the file even if it's not checked out -+ echo '#define THREAD 608' >> ppc_defs.h -+ echo '#define PT_REGS 8' >> ppc_defs.h -+ echo '#define CLONE_VM 256' >> ppc_defs.h -+# chmod u+w ppc_defs.h -+# grep '^#define' mk_defs.s >> ppc_defs.h -+# rm mk_defs.s -+ -+# the asm link is horrible, and breaks the other targets. This is also -+# not going to work with parallel makes. -+ -+checksum.o: checksum.S -+ rm -f asm -+ ln -s $(TOPDIR)/include/asm-ppc asm -+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ rm -f asm -+ -+misc.o: misc.S ppc_defs.h -+ rm -f asm -+ ln -s $(TOPDIR)/include/asm-ppc asm -+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ rm -f asm -+ -+clean: -+ rm -f $(OBJS) -+ rm -f ppc_defs.h -+ rm -f checksum.S semaphore.c mk_defs.c -+ -+fastdep: -+ -+dep: -+ -+modules: -+ -+include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/misc.S um/arch/um/sys-ppc/misc.S ---- orig/arch/um/sys-ppc/misc.S 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/misc.S 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,116 @@ -+/* -+ * This file contains miscellaneous low-level functions. -+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) -+ * -+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) -+ * and Paul Mackerras. -+ * -+ * A couple of functions stolen from arch/ppc/kernel/misc.S for UML -+ * by Chris Emerson. -+ * -+ * 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. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <asm/processor.h> -+#include "ppc_asm.h" -+ -+#if defined(CONFIG_4xx) || defined(CONFIG_8xx) -+#define CACHE_LINE_SIZE 16 -+#define LG_CACHE_LINE_SIZE 4 -+#define MAX_COPY_PREFETCH 1 -+#elif !defined(CONFIG_PPC64BRIDGE) -+#define CACHE_LINE_SIZE 32 -+#define LG_CACHE_LINE_SIZE 5 -+#define MAX_COPY_PREFETCH 4 -+#else -+#define CACHE_LINE_SIZE 128 -+#define LG_CACHE_LINE_SIZE 7 -+#define MAX_COPY_PREFETCH 1 -+#endif /* CONFIG_4xx || CONFIG_8xx */ -+ -+ .text -+ -+/* -+ * Clear a page using the dcbz instruction, which doesn't cause any -+ * memory traffic (except to write out any cache lines which get -+ * displaced). This only works on cacheable memory. -+ */ -+_GLOBAL(clear_page) -+ li r0,4096/CACHE_LINE_SIZE -+ mtctr r0 -+#ifdef CONFIG_8xx -+ li r4, 0 -+1: stw r4, 0(r3) -+ stw r4, 4(r3) -+ stw r4, 8(r3) -+ stw r4, 12(r3) -+#else -+1: dcbz 0,r3 -+#endif -+ addi r3,r3,CACHE_LINE_SIZE -+ bdnz 1b -+ blr -+ -+/* -+ * Copy a whole page. We use the dcbz instruction on the destination -+ * to reduce memory traffic (it eliminates the unnecessary reads of -+ * the destination into cache). This requires that the destination -+ * is cacheable. -+ */ -+#define COPY_16_BYTES \ -+ lwz r6,4(r4); \ -+ lwz r7,8(r4); \ -+ lwz r8,12(r4); \ -+ lwzu r9,16(r4); \ -+ stw r6,4(r3); \ -+ stw r7,8(r3); \ -+ stw r8,12(r3); \ -+ stwu r9,16(r3) -+ -+_GLOBAL(copy_page) -+ addi r3,r3,-4 -+ addi r4,r4,-4 -+ li r5,4 -+ -+#ifndef CONFIG_8xx -+#if MAX_COPY_PREFETCH > 1 -+ li r0,MAX_COPY_PREFETCH -+ li r11,4 -+ mtctr r0 -+11: dcbt r11,r4 -+ addi r11,r11,CACHE_LINE_SIZE -+ bdnz 11b -+#else /* MAX_COPY_PREFETCH == 1 */ -+ dcbt r5,r4 -+ li r11,CACHE_LINE_SIZE+4 -+#endif /* MAX_COPY_PREFETCH */ -+#endif /* CONFIG_8xx */ -+ -+ li r0,4096/CACHE_LINE_SIZE -+ mtctr r0 -+1: -+#ifndef CONFIG_8xx -+ dcbt r11,r4 -+ dcbz r5,r3 -+#endif -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 32 -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 64 -+ COPY_16_BYTES -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 128 -+ COPY_16_BYTES -+ COPY_16_BYTES -+ COPY_16_BYTES -+ COPY_16_BYTES -+#endif -+#endif -+#endif -+ bdnz 1b -+ blr -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/miscthings.c um/arch/um/sys-ppc/miscthings.c ---- orig/arch/um/sys-ppc/miscthings.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/miscthings.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,53 @@ -+#include "linux/threads.h" -+#include "linux/stddef.h" // for NULL -+#include "linux/elf.h" // for AT_NULL -+ -+/* The following function nicked from arch/ppc/kernel/process.c and -+ * adapted slightly */ -+/* -+ * XXX ld.so expects the auxiliary table to start on -+ * a 16-byte boundary, so we have to find it and -+ * move it up. :-( -+ */ -+void shove_aux_table(unsigned long sp) -+{ -+ int argc; -+ char *p; -+ unsigned long e; -+ unsigned long aux_start, offset; -+ -+ argc = *(int *)sp; -+ sp += sizeof(int) + (argc + 1) * sizeof(char *); -+ /* skip over the environment pointers */ -+ do { -+ p = *(char **)sp; -+ sp += sizeof(char *); -+ } while (p != NULL); -+ aux_start = sp; -+ /* skip to the end of the auxiliary table */ -+ do { -+ e = *(unsigned long *)sp; -+ sp += 2 * sizeof(unsigned long); -+ } while (e != AT_NULL); -+ offset = ((aux_start + 15) & ~15) - aux_start; -+ if (offset != 0) { -+ do { -+ sp -= sizeof(unsigned long); -+ e = *(unsigned long *)sp; -+ *(unsigned long *)(sp + offset) = e; -+ } while (sp > aux_start); -+ } -+} -+/* END stuff taken from arch/ppc/kernel/process.c */ -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/ptrace.c um/arch/um/sys-ppc/ptrace.c ---- orig/arch/um/sys-ppc/ptrace.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/ptrace.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,28 @@ -+#include "linux/sched.h" -+#include "asm/ptrace.h" -+ -+int putreg(struct task_struct *child, unsigned long regno, -+ unsigned long value) -+{ -+ child->thread.process_regs.regs[regno >> 2] = value; -+ return 0; -+} -+ -+unsigned long getreg(struct task_struct *child, unsigned long regno) -+{ -+ unsigned long retval = ~0UL; -+ -+ retval &= child->thread.process_regs.regs[regno >> 2]; -+ return retval; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/ptrace_user.c um/arch/um/sys-ppc/ptrace_user.c ---- orig/arch/um/sys-ppc/ptrace_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/ptrace_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,40 @@ -+#include <sys/ptrace.h> -+#include <errno.h> -+#include <asm/ptrace.h> -+#include "sysdep/ptrace.h" -+ -+int ptrace_getregs(long pid, unsigned long *regs_out) -+{ -+ int i; -+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { -+ errno = 0; -+ regs_out->regs[i] = ptrace(PTRACE_PEEKUSER, pid, i*4, 0); -+ if (errno) { -+ return -errno; -+ } -+ } -+ return 0; -+} -+ -+int ptrace_setregs(long pid, unsigned long *regs_in) -+{ -+ int i; -+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { -+ if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) { -+ if (ptrace(PTRACE_POKEUSER, pid, i*4, regs_in->regs[i]) < 0) { -+ return -errno; -+ } -+ } -+ } -+ return 0; -+} -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/sigcontext.c um/arch/um/sys-ppc/sigcontext.c ---- orig/arch/um/sys-ppc/sigcontext.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/sigcontext.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,15 @@ -+#include "asm/ptrace.h" -+#include "asm/sigcontext.h" -+#include "sysdep/ptrace.h" -+#include "user_util.h" -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/sys-ppc/sysrq.c um/arch/um/sys-ppc/sysrq.c ---- orig/arch/um/sys-ppc/sysrq.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/sys-ppc/sysrq.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "asm/ptrace.h" -+#include "sysrq.h" -+ -+void show_regs(struct pt_regs_subarch *regs) -+{ -+ printk("\n"); -+ printk("show_regs(): insert regs here.\n"); -+#if 0 -+ printk("\n"); -+ printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs, regs->eip, -+ smp_processor_id()); -+ if (regs->xcs & 3) -+ printk(" ESP: %04x:%08lx",0xffff & regs->xss, regs->esp); -+ printk(" EFLAGS: %08lx\n", regs->eflags); -+ 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); -+#endif -+ -+ show_trace(®s->gpr[1]); -+} -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/arch/um/util/Makefile um/arch/um/util/Makefile ---- orig/arch/um/util/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/util/Makefile 2003-11-08 02:51:30.000000000 -0500 -@@ -0,0 +1,26 @@ -+ALL = mk_task mk_constants -+ -+all : $(ALL) -+ -+mk_task : mk_task_user.o mk_task_kern.o -+ $(HOSTCC) -o mk_task mk_task_user.o mk_task_kern.o -+ -+mk_task_user.o : mk_task_user.c -+ $(HOSTCC) -c $< -+ -+mk_task_kern.o : mk_task_kern.c -+ $(HOSTCC) $(CFLAGS) -c $< -+ -+mk_constants : mk_constants_user.o mk_constants_kern.o -+ $(HOSTCC) -o mk_constants mk_constants_user.o mk_constants_kern.o -+ -+mk_constants_user.o : mk_constants_user.c -+ $(HOSTCC) -c $< -+ -+mk_constants_kern.o : mk_constants_kern.c -+ $(HOSTCC) $(CFLAGS) -c $< -+ -+clean : -+ $(RM) $(ALL) *.o *~ -+ -+archmrproper : clean -diff -Naur -X ../exclude-files orig/arch/um/util/mk_constants_kern.c um/arch/um/util/mk_constants_kern.c ---- orig/arch/um/util/mk_constants_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/util/mk_constants_kern.c 2004-01-10 06:54:51.000000000 -0500 -@@ -0,0 +1,25 @@ -+#include "linux/kernel.h" -+#include "linux/stringify.h" -+#include "asm/page.h" -+ -+extern void print_head(void); -+extern void print_constant_str(char *name, char *value); -+extern void print_constant_int(char *name, int value); -+extern void print_tail(void); -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE); -+ -+ print_constant_str("UM_KERN_EMERG", KERN_EMERG); -+ print_constant_str("UM_KERN_ALERT", KERN_ALERT); -+ print_constant_str("UM_KERN_CRIT", KERN_CRIT); -+ print_constant_str("UM_KERN_ERR", KERN_ERR); -+ print_constant_str("UM_KERN_WARNING", KERN_WARNING); -+ print_constant_str("UM_KERN_NOTICE", KERN_NOTICE); -+ print_constant_str("UM_KERN_INFO", KERN_INFO); -+ print_constant_str("UM_KERN_DEBUG", KERN_DEBUG); -+ print_tail(); -+ return(0); -+} -diff -Naur -X ../exclude-files orig/arch/um/util/mk_constants_user.c um/arch/um/util/mk_constants_user.c ---- orig/arch/um/util/mk_constants_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/util/mk_constants_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,28 @@ -+#include <stdio.h> -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_constants\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __UM_CONSTANTS_H\n"); -+ printf("#define __UM_CONSTANTS_H\n"); -+ printf("\n"); -+} -+ -+void print_constant_str(char *name, char *value) -+{ -+ printf("#define %s \"%s\"\n", name, value); -+} -+ -+void print_constant_int(char *name, int value) -+{ -+ printf("#define %s %d\n", name, value); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -diff -Naur -X ../exclude-files orig/arch/um/util/mk_task_kern.c um/arch/um/util/mk_task_kern.c ---- orig/arch/um/util/mk_task_kern.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/util/mk_task_kern.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,17 @@ -+#include "linux/sched.h" -+#include "linux/stddef.h" -+ -+extern void print(char *name, char *type, int offset); -+extern void print_ptr(char *name, char *type, int offset); -+extern void print_head(void); -+extern void print_tail(void); -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_ptr("TASK_REGS", "union uml_pt_regs", -+ offsetof(struct task_struct, thread.regs)); -+ print("TASK_PID", "int", offsetof(struct task_struct, pid)); -+ print_tail(); -+ return(0); -+} -diff -Naur -X ../exclude-files orig/arch/um/util/mk_task_user.c um/arch/um/util/mk_task_user.c ---- orig/arch/um/util/mk_task_user.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/arch/um/util/mk_task_user.c 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,30 @@ -+#include <stdio.h> -+ -+void print(char *name, char *type, int offset) -+{ -+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, -+ offset); -+} -+ -+void print_ptr(char *name, char *type, int offset) -+{ -+ printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type, -+ offset); -+} -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_task\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __TASK_H\n"); -+ printf("#define __TASK_H\n"); -+ printf("\n"); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -diff -Naur -X ../exclude-files orig/CREDITS um/CREDITS ---- orig/CREDITS 2003-12-16 22:16:23.000000000 -0500 -+++ um/CREDITS 2003-12-16 22:17:22.000000000 -0500 -@@ -434,6 +434,7 @@ - E: lars@nocrew.org - W: http://lars.nocrew.org/ - D: dsp56k device driver -+D: ptrace proxy in user mode kernel port - S: Kopmansg 2 - S: 411 13 Goteborg - S: Sweden -@@ -719,7 +720,7 @@ - E: jdike@karaya.com - W: http://user-mode-linux.sourceforge.net - D: User mode kernel port --S: RR1 Box 67C -+S: 375 Tubbs Hill Rd - S: Deering NH 03244 - S: USA - -diff -Naur -X ../exclude-files orig/Documentation/Configure.help um/Documentation/Configure.help ---- orig/Documentation/Configure.help 2003-12-16 22:16:23.000000000 -0500 -+++ um/Documentation/Configure.help 2003-12-16 22:17:22.000000000 -0500 -@@ -15821,6 +15821,63 @@ - The module will be called speedtch.o. If you want to compile it as - a module, say M here and read <file:Documentation/modules.txt>. - -+Support for /proc/mm -+CONFIG_PROC_MM -+ Enables support for address space separation through /proc/mm. -+ A host kernel needs to have this enabled in order for UML to -+ run in skas mode. UML kernels do not need to have this option -+ unless they will host sub-UMLs. -+ -+ If you don't know what this does just say Y. -+ -+Separate Kernel Address Space support -+CONFIG_MODE_SKAS -+ This option controls whether skas (separate kernel address space) -+ support is compiled in. If you have applied the skas patch to the -+ host and enabled support for /proc/mm in the host kernel, then you -+ certainly want to say Y here (and consider saying N to -+ CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this -+ option will shrink the UML binary slightly. -+ -+Tracing thread support -+CONFIG_MODE_TT -+ This option controls whether tracing thread support is compiled -+ into UML. Normally, this should be set to Y. If you intend to -+ use only skas mode (and the host has the skas patch applied to it), -+ then it is OK to say N here. -+ -+Force a static link -+CONFIG_STATIC_LINK -+ If CONFIG_MODE_TT is disabled, then this option gives you the ability -+ to force a static link of UML. Normally, if only skas mode is built -+ in to UML, it will be linked as a shared binary. This is inconvenient -+ for use in a chroot jail. So, if you intend to run UML inside a -+ chroot, and you disable CONFIG_MODE_TT, you probably want to say Y -+ here. -+ -+2G/2G host address space split -+CONFIG_HOST_2G_2G -+ Most Linux machines are configured so that the kernel occupies the -+ upper 1G of the 4G address space and processes use the lower 3G. -+ However, some machine are configured with a 2G/2G split, with the -+ kernel occupying the upper 2G and processes using the lower 2G. -+ -+ To allow UML to run on a such host you have to say Y here. N should be -+ a safe choice most of the time. -+ -+Kernel stack size order -+CONFIG_KERNEL_STACK_ORDER -+ This option determines the size of UML kernel stacks. They will -+ be 1 << order pages. The default is OK unless you're running Valgrind -+ on UML, in which case, set this to 3. -+ -+UML ubd block driver -+CONFIG_BLK_DEV_UBD -+ The User-Mode Linux port includes a driver called UBD which will let -+ you access arbitrary files on the host computer as block devices. -+ Unless you know that you do not need such virtual block devices say -+ Y here. -+ - CONFIG_USB_GADGET - USB is a master/slave protocol, organized with one master - host (such as a PC) controlling up to 127 peripheral devices. -@@ -15905,17 +15962,15 @@ - - Always do synchronous disk IO for UBD - CONFIG_BLK_DEV_UBD_SYNC -- The User-Mode Linux port includes a driver called UBD which will let -- you access arbitrary files on the host computer as block devices. -- Writes to such a block device are not immediately written to the -- host's disk; this may cause problems if, for example, the User-Mode -- Linux 'Virtual Machine' uses a journalling file system and the host -- computer crashes. -+ Writes to the virtual block device are not immediately written to the host's -+ disk; this may cause problems if, for example, the User-Mode Linux -+ 'Virtual Machine' uses a journalling filesystem and the host computer -+ crashes. - - Synchronous operation (i.e. always writing data to the host's disk - immediately) is configurable on a per-UBD basis by using a special - kernel command line option. Alternatively, you can say Y here to -- turn on synchronous operation by default for all block. -+ turn on synchronous operation by default for all block devices. - - If you're running a journalling file system (like reiserfs, for - example) in your virtual machine, you will want to say Y here. If -@@ -15927,6 +15982,7 @@ - CONFIG_PT_PROXY - This option enables a debugging interface which allows gdb to debug - the kernel without needing to actually attach to kernel threads. -+ CONFIG_XTERM_CHAN must be enabled in order to enable CONFIG_PT_PROXY. - If you want to do kernel debugging, say Y here; otherwise say N. - - Management console -@@ -15959,7 +16015,7 @@ - This option allows developers to retrieve coverage data from a UML - session. - -- See <http://user-mode-linux.sourceforge.net/gcov.html> for more -+ See <http://user-mode-linux.sourceforge.net/gprof.html> for more - details. - - If you're involved in UML kernel development and want to use gcov, -@@ -15996,6 +16052,19 @@ - If you'd like to be able to work with files stored on the host, - say Y or M here; otherwise say N. - -+HoneyPot ProcFS -+CONFIG_HPPFS -+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc -+ entries to be overridden, removed, or fabricated from the host. -+ Its purpose is to allow a UML to appear to be a physical machine -+ by removing or changing anything in /proc which gives away the -+ identity of a UML. -+ -+ See <http://user-mode-linux.sf.net/hppfs.html> for more information. -+ -+ You only need this if you are setting up a UML honeypot. Otherwise, -+ it is safe to say 'N' here. -+ - Example IO Memory driver - CONFIG_MMAPPER - The User-Mode Linux port can provide support for IO Memory -@@ -16011,6 +16080,21 @@ - If you'd like to be able to provide a simulated IO port space for - User-Mode Linux processes, say Y. If unsure, say N. - -+Anonymous Memory support -+CONFIG_DEV_ANON -+ Don't ask. Just say Y. -+ -+Support for software watchdog inside UML -+CONFIG_UML_WATCHDOG -+ Support for a virtual hardware watchdog. It's safe to say N here. -+ -+COW block device -+CONFIG_COW -+ This is a layered driver which sits above two other block devices. -+ One is read-only, and the other is a read-write layer which stores -+ all changes. This provides the illusion that the read-only layer -+ can be mounted read-write and changed. -+ - Virtual Serial Line - CONFIG_SSL - The User-Mode Linux environment allows you to create virtual serial -@@ -16121,26 +16205,197 @@ - - SLIP transport - CONFIG_UML_NET_SLIP -- The Slip User-Mode Linux network transport allows a running UML to -+ The slip User-Mode Linux network transport allows a running UML to - network with its host over a point-to-point link. Unlike Ethertap, - which can carry any Ethernet frame (and hence even non-IP packets), -- the Slip transport can only carry IP packets. -+ the slip transport can only carry IP packets. - -- To use this, your host must support Slip devices. -+ To use this, your host must support slip devices. - - For more information, see - <http://user-mode-linux.sourceforge.net/networking.html>. That site -- has examples of the UML command line to use to enable Slip -+ has examples of the UML command line to use to enable slip - networking, and details of a few quirks with it. - -- The Ethertap Transport is preferred over Slip because of its -- limitation. If you prefer Slip, however, say Y here. Otherwise -+ The Ethertap Transport is preferred over slip because of its -+ limitations. If you prefer slip, however, say Y here. Otherwise - choose the Multicast transport (to network multiple UMLs on - multiple hosts), Ethertap (to network with the host and the - outside world), and/or the Daemon transport (to network multiple - UMLs on a single host). You may choose more than one without - conflict. If you don't need UML networking, say N. - -+SLiRP transport -+CONFIG_UML_NET_SLIRP -+ The SLiRP User-Mode Linux network transport allows a running UML -+ to network by invoking a program that can handle SLIP encapsulated -+ packets. This is commonly (but not limited to) the application -+ known as SLiRP, a program that can re-socket IP packets back onto -+ the host on which it is run. Only IP packets are supported, -+ unlike other network transports that can handle all Ethernet -+ frames. In general, slirp allows the UML the same IP connectivity -+ to the outside world that the host user is permitted, and unlike -+ other transports, SLiRP works without the need of root level -+ privleges, setuid binaries, or SLIP devices on the host. This -+ also means not every type of connection is possible, but most -+ situations can be accomodated with carefully crafted slirp -+ commands that can be passed along as part of the network device's -+ setup string. The effect of this transport on the UML is similar -+ that of a host behind a firewall that masquerades all network -+ connections passing through it (but is less secure). -+ -+ To use this you should first have slirp compiled somewhere -+ accessible on the host, and have read its documentation. If you -+ don't need UML networking, say N. -+ -+ Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp" -+ -+pcap transport -+CONFIG_UML_NET_PCAP -+ The pcap transport makes a pcap packet stream on the host look -+ like an ethernet device inside UML. This is useful for making -+ UML act as a network monitor for the host. You must have libcap -+ installed in order to build the pcap transport into UML. -+ -+ For more information, see -+ <http://user-mode-linux.sourceforge.net/networking.html> That site -+ has examples of the UML command line to use to enable this option. -+ -+ If you intend to use UML as a network monitor for the host, say -+ Y here. Otherwise, say N. -+ -+Default main console channel initialization -+CONFIG_CON_ZERO_CHAN -+ This is the string describing the channel to which the main console -+ will be attached by default. This value can be overridden from the -+ command line. The default value is "fd:0,fd:1", which attaches the -+ main console to stdin and stdout. -+ It is safe to leave this unchanged. -+ -+Default console channel initialization -+CONFIG_CON_CHAN -+ This is the string describing the channel to which all consoles -+ except the main console will be attached by default. This value can -+ be overridden from the command line. The default value is "xterm", -+ which brings them up in xterms. -+ It is safe to leave this unchanged, although you may wish to change -+ this if you expect the UML that you build to be run in environments -+ which don't have X or xterm available. -+ -+Default serial line channel initialization -+CONFIG_SSL_CHAN -+ This is the string describing the channel to which the serial lines -+ will be attached by default. This value can be overridden from the -+ command line. The default value is "pty", which attaches them to -+ traditional pseudo-terminals. -+ It is safe to leave this unchanged, although you may wish to change -+ this if you expect the UML that you build to be run in environments -+ which don't have a set of /dev/pty* devices. -+ -+Nesting level -+CONFIG_NEST_LEVEL -+ This is set to the number of layers of UMLs that this UML will be run -+ in. Normally, this is zero, meaning that it will run directly on the -+ host. Setting it to one will build a UML that can run inside a UML -+ that is running on the host. Generally, if you intend this UML to run -+ inside another UML, set CONFIG_NEST_LEVEL to one more than the host UML. -+ Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to -+ greater than one, then the guest UML should have its CONFIG_NEST_LEVEL -+ set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. -+ Only change this if you are running nested UMLs. -+ -+Kernel address space size (in .5G units) -+CONFIG_KERNEL_HALF_GIGS -+ This determines the amount of address space that UML will allocate for -+ its own, measured in half Gigabyte units. The default is 1. -+ Change this only if you need to boot UML with an unusually large amount -+ of physical memory. -+ -+UML sound support -+CONFIG_UML_SOUND -+ This option enables UML sound support. If enabled, it will pull in -+ soundcore and the UML hostaudio relay, which acts as a intermediary -+ between the host's dsp and mixer devices and the UML sound system. -+ It is safe to say 'Y' here. -+ -+UML SMP support -+CONFIG_UML_SMP -+ This option enables UML SMP support. UML implements virtual SMP by -+ allowing as many processes to run simultaneously on the host as -+ there are virtual processors configured. Obviously, if the host is -+ a uniprocessor, those processes will timeshare, but, inside UML, -+ will appear to be running simultaneously. If the host is a -+ multiprocessor, then UML processes may run simultaneously, depending -+ on the host scheduler. -+ CONFIG_SMP will be set to whatever this option is set to. -+ It is safe to leave this unchanged. -+ -+file descriptor channel support -+CONFIG_FD_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to already set up file descriptors. Generally, the main -+ console is attached to file descriptors 0 and 1 (stdin and stdout), -+ so it would be wise to leave this enabled unless you intend to -+ attach it to some other host device. -+ -+null device channel support -+CONFIG_NULL_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to a device similar to /dev/null. Data written to it disappears -+ and there is never any data to be read. -+ -+port channel support -+CONFIG_PORT_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host portals. They may be accessed with 'telnet <host> -+ <port number>'. Any number of consoles and serial lines may be -+ attached to a single portal, although what UML device you get when -+ you telnet to that portal will be unpredictable. -+ It is safe to say 'Y' here. -+ -+pty channel support -+CONFIG_PTY_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host pseudo-terminals. Access to both traditional -+ pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled -+ with this option. The assignment of UML devices to host devices -+ will be announced in the kernel message log. -+ It is safe to say 'Y' here. -+ -+tty channel support -+CONFIG_TTY_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host terminals. Access to both virtual consoles -+ (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and -+ /dev/pts/*) are controlled by this option. -+ It is safe to say 'Y' here. -+ -+xterm channel support -+CONFIG_XTERM_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to xterms. Each UML device so assigned will be brought up in -+ its own xterm. -+ If you disable this option, then CONFIG_PT_PROXY will be disabled as -+ well, since UML's gdb currently requires an xterm. -+ It is safe to say 'Y' here. -+ -+tty logging -+CONFIG_TTY_LOG -+ This option enables logging of all data going through pseudo-terminals -+ to the host. This is primarily useful for honeypots, where you want -+ secure keystroke logging that can't be detected or disabled by root. -+ Say 'N' unless you are setting up a UML honeypot or otherwise know that -+ you want this option. -+ -+UML real-time clock support -+CONFIG_UML_REAL_TIME_CLOCK -+ This option ties the UML clock to the host clock, so that time passes at -+ the same rate as on the host, regardless of how much CPU time the UML is -+ getting. This should normally be enabled. The exception would be if you're -+ debugging UML. In this case, time spent staring at the debugger with UML -+ stopped will cause lots of timer ticks to be backed up, and UML will spent -+ lots of time calling the timer when it is finally continued. -+ - Microtek USB scanner support - CONFIG_USB_MICROTEK - Say Y here if you want support for the Microtek X6USB and -diff -Naur -X ../exclude-files orig/drivers/char/Makefile um/drivers/char/Makefile ---- orig/drivers/char/Makefile 2003-12-16 22:16:26.000000000 -0500 -+++ um/drivers/char/Makefile 2003-12-16 22:17:25.000000000 -0500 -@@ -109,6 +109,12 @@ - endif - endif - -+ifeq ($(ARCH),um) -+ KEYMAP = -+ KEYBD = -+ CONSOLE = -+endif -+ - ifeq ($(ARCH),sh) - KEYMAP = - KEYBD = -diff -Naur -X ../exclude-files orig/drivers/char/mem.c um/drivers/char/mem.c ---- orig/drivers/char/mem.c 2003-12-16 22:16:27.000000000 -0500 -+++ um/drivers/char/mem.c 2004-01-05 11:23:32.000000000 -0500 -@@ -220,7 +220,8 @@ - ssize_t read = 0; - ssize_t virtr = 0; - char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ -- -+ -+ p = (unsigned long) __va(p); - if (p < (unsigned long) high_memory) { - read = count; - if (count > (unsigned long) high_memory - p) -@@ -269,7 +270,7 @@ - } - free_page((unsigned long)kbuf); - } -- *ppos = p; -+ *ppos = __pa((void *) p); - return virtr + read; - } - -@@ -664,6 +665,8 @@ - write: write_full, - }; - -+extern struct file_operations anon_file_operations; -+ - static int memory_open(struct inode * inode, struct file * filp) - { - switch (MINOR(inode->i_rdev)) { -@@ -693,6 +696,9 @@ - case 9: - filp->f_op = &urandom_fops; - break; -+ case 10: -+ filp->f_op = &anon_file_operations; -+ break; - default: - return -ENXIO; - } -@@ -719,7 +725,8 @@ - {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, - {7, "full", S_IRUGO | S_IWUGO, &full_fops}, - {8, "random", S_IRUGO | S_IWUSR, &random_fops}, -- {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops} -+ {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, -+ {10, "anon", S_IRUGO | S_IWUSR, &anon_file_operations}, - }; - int i; - -diff -Naur -X ../exclude-files orig/drivers/char/tty_io.c um/drivers/char/tty_io.c ---- orig/drivers/char/tty_io.c 2003-12-16 22:16:27.000000000 -0500 -+++ um/drivers/char/tty_io.c 2003-12-16 22:17:25.000000000 -0500 -@@ -649,6 +649,23 @@ - wake_up_interruptible(&tty->write_wait); - } - -+#ifdef CONFIG_TTY_LOG -+ -+int (*open_log)(void *, void *) = NULL; -+int (*write_log)(int, const char *, int, void *, int) = NULL; -+void (*close_log)(int, void *) = NULL; -+ -+void register_tty_logger(int (*opener)(void *, void *), -+ int (*writer)(int, const char *, int, void *, int), -+ void (*closer)(int, void *)) -+{ -+ open_log = opener; -+ write_log = writer; -+ close_log = closer; -+} -+ -+#endif -+ - static ssize_t tty_read(struct file * file, char * buf, size_t count, - loff_t *ppos) - { -@@ -689,8 +706,13 @@ - else - i = -EIO; - unlock_kernel(); -- if (i > 0) -+ if (i > 0){ - inode->i_atime = CURRENT_TIME; -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd >= 0) && (write_log != NULL)) -+ (*write_log)(tty->log_fd, buf, i, tty, 1); -+#endif -+ } - return i; - } - -@@ -744,6 +766,10 @@ - if (written) { - file->f_dentry->d_inode->i_mtime = CURRENT_TIME; - ret = written; -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd >= 0) && (write_log != NULL)) -+ (*write_log)(tty->log_fd, buf - ret, ret, tty, 0); -+#endif - } - up(&tty->atomic_write); - return ret; -@@ -971,6 +997,7 @@ - goto release_mem_out; - } - } -+ - goto success; - - /* -@@ -1290,6 +1317,11 @@ - run_task_queue(&tq_timer); - flush_scheduled_tasks(); - -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd >= 0) && (close_log != NULL)) -+ (*close_log)(tty->log_fd, tty); -+#endif -+ - /* - * The release_mem function takes care of the details of clearing - * the slots and preserving the termios structure. -@@ -1448,6 +1480,11 @@ - nr_warns++; - } - } -+ -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd < 0) && (open_log != NULL)) -+ tty->log_fd = (*open_log)(tty, current->tty); -+#endif - return 0; - } - -@@ -2047,6 +2084,9 @@ - spin_lock_init(&tty->read_lock); - INIT_LIST_HEAD(&tty->tty_files); - INIT_TQUEUE(&tty->SAK_tq, 0, 0); -+#ifdef CONFIG_TTY_LOG -+ tty->log_fd = -1; -+#endif - } - - /* -diff -Naur -X ../exclude-files orig/drivers/net/setup.c um/drivers/net/setup.c ---- orig/drivers/net/setup.c 2002-09-15 12:13:19.000000000 -0400 -+++ um/drivers/net/setup.c 2003-10-21 03:26:07.000000000 -0400 -@@ -28,7 +28,6 @@ - extern int lmc_setup(void); - - extern int madgemc_probe(void); --extern int uml_net_probe(void); - - /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ - #define __PAD6 "\0\0\0\0\0\0\0\0\0" -@@ -103,9 +102,6 @@ - #ifdef CONFIG_MADGEMC - {madgemc_probe, 0}, - #endif --#ifdef CONFIG_UML_NET -- {uml_net_probe, 0}, --#endif - - {NULL, 0}, - }; -diff -Naur -X ../exclude-files orig/fs/bad_inode.c um/fs/bad_inode.c ---- orig/fs/bad_inode.c 2002-08-21 11:47:27.000000000 -0400 -+++ um/fs/bad_inode.c 2003-10-21 03:26:07.000000000 -0400 -@@ -83,6 +83,7 @@ - - void make_bad_inode(struct inode * inode) - { -+ inode->i_state = 0; - inode->i_mode = S_IFREG; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_op = &bad_inode_ops; -diff -Naur -X ../exclude-files orig/include/asm-i386/hardirq.h um/include/asm-i386/hardirq.h ---- orig/include/asm-i386/hardirq.h 2004-01-11 22:46:12.000000000 -0500 -+++ um/include/asm-i386/hardirq.h 2004-02-14 06:28:59.000000000 -0500 -@@ -4,6 +4,7 @@ - #include <linux/config.h> - #include <linux/threads.h> - #include <linux/irq.h> -+#include <asm/processor.h> /* for cpu_relax */ - - /* assembly code in softirq.h is sensitive to the offsets of these fields */ - typedef struct { -diff -Naur -X ../exclude-files orig/include/asm-um/a.out.h um/include/asm-um/a.out.h ---- orig/include/asm-um/a.out.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/a.out.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,20 @@ -+#ifndef __UM_A_OUT_H -+#define __UM_A_OUT_H -+ -+#include "linux/config.h" -+#include "asm/arch/a.out.h" -+#include "choose-mode.h" -+ -+#undef STACK_TOP -+ -+extern unsigned long stacksizelim; -+ -+extern unsigned long host_task_size; -+ -+#define STACK_ROOM (stacksizelim) -+ -+extern int honeypot; -+#define STACK_TOP \ -+ CHOOSE_MODE((honeypot ? host_task_size : task_size), task_size) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/archparam-i386.h um/include/asm-um/archparam-i386.h ---- orig/include/asm-um/archparam-i386.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/archparam-i386.h 2003-12-16 08:50:39.000000000 -0500 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_ARCHPARAM_I386_H -+#define __UM_ARCHPARAM_I386_H -+ -+/********* Bits for asm-um/elf.h ************/ -+ -+#include "user.h" -+ -+#define ELF_PLATFORM "i586" -+ -+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) -+ -+typedef struct user_i387_struct elf_fpregset_t; -+typedef unsigned long elf_greg_t; -+ -+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+#define ELF_DATA ELFDATA2LSB -+#define ELF_ARCH EM_386 -+ -+#define ELF_PLAT_INIT(regs, load_addr) do { \ -+ PT_REGS_EBX(regs) = 0; \ -+ PT_REGS_ECX(regs) = 0; \ -+ PT_REGS_EDX(regs) = 0; \ -+ PT_REGS_ESI(regs) = 0; \ -+ PT_REGS_EDI(regs) = 0; \ -+ PT_REGS_EBP(regs) = 0; \ -+ PT_REGS_EAX(regs) = 0; \ -+} while(0) -+ -+/* Shamelessly stolen from include/asm-i386/elf.h */ -+ -+#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ -+ pr_reg[0] = PT_REGS_EBX(regs); \ -+ pr_reg[1] = PT_REGS_ECX(regs); \ -+ pr_reg[2] = PT_REGS_EDX(regs); \ -+ pr_reg[3] = PT_REGS_ESI(regs); \ -+ pr_reg[4] = PT_REGS_EDI(regs); \ -+ pr_reg[5] = PT_REGS_EBP(regs); \ -+ pr_reg[6] = PT_REGS_EAX(regs); \ -+ pr_reg[7] = PT_REGS_DS(regs); \ -+ pr_reg[8] = PT_REGS_ES(regs); \ -+ /* fake once used fs and gs selectors? */ \ -+ pr_reg[9] = PT_REGS_DS(regs); \ -+ pr_reg[10] = PT_REGS_DS(regs); \ -+ pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \ -+ pr_reg[12] = PT_REGS_IP(regs); \ -+ pr_reg[13] = PT_REGS_CS(regs); \ -+ pr_reg[14] = PT_REGS_EFLAGS(regs); \ -+ pr_reg[15] = PT_REGS_SP(regs); \ -+ pr_reg[16] = PT_REGS_SS(regs); \ -+} while(0); -+ -+/********* Bits for asm-um/delay.h **********/ -+ -+typedef unsigned long um_udelay_t; -+ -+/********* Nothing for asm-um/hardirq.h **********/ -+ -+/********* Nothing for asm-um/hw_irq.h **********/ -+ -+/********* Nothing for asm-um/string.h **********/ -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/archparam-ppc.h um/include/asm-um/archparam-ppc.h ---- orig/include/asm-um/archparam-ppc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/archparam-ppc.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,41 @@ -+#ifndef __UM_ARCHPARAM_PPC_H -+#define __UM_ARCHPARAM_PPC_H -+ -+/********* Bits for asm-um/elf.h ************/ -+ -+#define ELF_PLATFORM (0) -+ -+#define ELF_ET_DYN_BASE (0x08000000) -+ -+/* the following stolen from asm-ppc/elf.h */ -+#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ -+#define ELF_NFPREG 33 /* includes fpscr */ -+/* General registers */ -+typedef unsigned long elf_greg_t; -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+/* Floating point registers */ -+typedef double elf_fpreg_t; -+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -+ -+#define ELF_DATA ELFDATA2MSB -+#define ELF_ARCH EM_PPC -+ -+/********* Bits for asm-um/delay.h **********/ -+ -+typedef unsigned int um_udelay_t; -+ -+/********* Bits for asm-um/hw_irq.h **********/ -+ -+struct hw_interrupt_type; -+ -+/********* Bits for asm-um/hardirq.h **********/ -+ -+#define irq_enter(cpu, irq) hardirq_enter(cpu) -+#define irq_exit(cpu, irq) hardirq_exit(cpu) -+ -+/********* Bits for asm-um/string.h **********/ -+ -+#define __HAVE_ARCH_STRRCHR -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/arch-signal-i386.h um/include/asm-um/arch-signal-i386.h ---- orig/include/asm-um/arch-signal-i386.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/arch-signal-i386.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_ARCH_SIGNAL_I386_H -+#define __UM_ARCH_SIGNAL_I386_H -+ -+struct arch_signal_context { -+ unsigned long extrasigs[_NSIG_WORDS]; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/atomic.h um/include/asm-um/atomic.h ---- orig/include/asm-um/atomic.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/atomic.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_ATOMIC_H -+#define __UM_ATOMIC_H -+ -+#include "asm/arch/atomic.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/bitops.h um/include/asm-um/bitops.h ---- orig/include/asm-um/bitops.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/bitops.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BITOPS_H -+#define __UM_BITOPS_H -+ -+#include "asm/arch/bitops.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/boot.h um/include/asm-um/boot.h ---- orig/include/asm-um/boot.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/boot.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BOOT_H -+#define __UM_BOOT_H -+ -+#include "asm/arch/boot.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/bugs.h um/include/asm-um/bugs.h ---- orig/include/asm-um/bugs.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/bugs.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BUGS_H -+#define __UM_BUGS_H -+ -+void check_bugs(void); -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/byteorder.h um/include/asm-um/byteorder.h ---- orig/include/asm-um/byteorder.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/byteorder.h 2004-01-16 03:32:58.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BYTEORDER_H -+#define __UM_BYTEORDER_H -+ -+#include "asm/arch/byteorder.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/cache.h um/include/asm-um/cache.h ---- orig/include/asm-um/cache.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/cache.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_CACHE_H -+#define __UM_CACHE_H -+ -+#define L1_CACHE_BYTES 32 -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/checksum.h um/include/asm-um/checksum.h ---- orig/include/asm-um/checksum.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/checksum.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_CHECKSUM_H -+#define __UM_CHECKSUM_H -+ -+#include "sysdep/checksum.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/cobalt.h um/include/asm-um/cobalt.h ---- orig/include/asm-um/cobalt.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/cobalt.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_COBALT_H -+#define __UM_COBALT_H -+ -+#include "asm/arch/cobalt.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/current.h um/include/asm-um/current.h ---- orig/include/asm-um/current.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/current.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_CURRENT_H -+#define __UM_CURRENT_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include "linux/config.h" -+#include "asm/page.h" -+ -+struct task_struct; -+ -+#define CURRENT_TASK(dummy) (((unsigned long) &dummy) & \ -+ (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER)) -+ -+#define current ({ int dummy; (struct task_struct *) CURRENT_TASK(dummy); }) -+ -+#endif /* __ASSEMBLY__ */ -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/delay.h um/include/asm-um/delay.h ---- orig/include/asm-um/delay.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/delay.h 2003-12-16 22:26:58.000000000 -0500 -@@ -0,0 +1,7 @@ -+#ifndef __UM_DELAY_H -+#define __UM_DELAY_H -+ -+#include "asm/arch/delay.h" -+#include "asm/archparam.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/desc.h um/include/asm-um/desc.h ---- orig/include/asm-um/desc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/desc.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_DESC_H -+#define __UM_DESC_H -+ -+#include "asm/arch/desc.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/div64.h um/include/asm-um/div64.h ---- orig/include/asm-um/div64.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/div64.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef _UM_DIV64_H -+#define _UM_DIV64_H -+ -+#include "asm/arch/div64.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/dma.h um/include/asm-um/dma.h ---- orig/include/asm-um/dma.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/dma.h 2004-01-16 03:32:59.000000000 -0500 -@@ -0,0 +1,10 @@ -+#ifndef __UM_DMA_H -+#define __UM_DMA_H -+ -+#include "asm/io.h" -+ -+extern unsigned long uml_physmem; -+ -+#define MAX_DMA_ADDRESS (uml_physmem) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/elf.h um/include/asm-um/elf.h ---- orig/include/asm-um/elf.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/elf.h 2003-12-16 22:29:20.000000000 -0500 -@@ -0,0 +1,18 @@ -+#ifndef __UM_ELF_H -+#define __UM_ELF_H -+ -+#include "asm/archparam.h" -+ -+#define ELF_HWCAP (0) -+ -+#define SET_PERSONALITY(ex, ibcs2) do ; while(0) -+ -+#define ELF_EXEC_PAGESIZE 4096 -+ -+#define elf_check_arch(x) (1) -+ -+#define ELF_CLASS ELFCLASS32 -+ -+#define USE_ELF_CORE_DUMP -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/errno.h um/include/asm-um/errno.h ---- orig/include/asm-um/errno.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/errno.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_ERRNO_H -+#define __UM_ERRNO_H -+ -+#include "asm/arch/errno.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/fcntl.h um/include/asm-um/fcntl.h ---- orig/include/asm-um/fcntl.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/fcntl.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_FCNTL_H -+#define __UM_FCNTL_H -+ -+#include "asm/arch/fcntl.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/fixmap.h um/include/asm-um/fixmap.h ---- orig/include/asm-um/fixmap.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/fixmap.h 2004-02-14 06:29:00.000000000 -0500 -@@ -0,0 +1,89 @@ -+#ifndef __UM_FIXMAP_H -+#define __UM_FIXMAP_H -+ -+#include <linux/config.h> -+#include <asm/kmap_types.h> -+ -+/* -+ * Here we define all the compile-time 'special' virtual -+ * addresses. The point is to have a constant address at -+ * compile time, but to set the physical address only -+ * in the boot process. We allocate these special addresses -+ * from the end of virtual memory (0xfffff000) backwards. -+ * Also this lets us do fail-safe vmalloc(), we -+ * can guarantee that these special addresses and -+ * vmalloc()-ed addresses never overlap. -+ * -+ * these 'compile-time allocated' memory buffers are -+ * fixed-size 4k pages. (or larger if used with an increment -+ * highger than 1) use fixmap_set(idx,phys) to associate -+ * physical memory with fixmap indices. -+ * -+ * TLB entries of such buffers will not be flushed across -+ * task switches. -+ */ -+ -+/* -+ * on UP currently we will have no trace of the fixmap mechanizm, -+ * no page table allocations, etc. This might change in the -+ * future, say framebuffers for the console driver(s) could be -+ * fix-mapped? -+ */ -+enum fixed_addresses { -+#ifdef CONFIG_HIGHMEM -+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ -+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, -+#endif -+ __end_of_fixed_addresses -+}; -+ -+extern void __set_fixmap (enum fixed_addresses idx, -+ unsigned long phys, pgprot_t flags); -+ -+#define set_fixmap(idx, phys) \ -+ __set_fixmap(idx, phys, PAGE_KERNEL) -+/* -+ * Some hardware wants to get fixmapped without caching. -+ */ -+#define set_fixmap_nocache(idx, phys) \ -+ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) -+/* -+ * used by vmalloc.c. -+ * -+ * Leave one empty page between vmalloc'ed areas and -+ * the start of the fixmap, and leave one page empty -+ * at the top of mem.. -+ */ -+extern unsigned long get_kmem_end(void); -+ -+#define FIXADDR_TOP (get_kmem_end() - 0x2000) -+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) -+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) -+ -+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) -+ -+extern void __this_fixmap_does_not_exist(void); -+ -+/* -+ * 'index to address' translation. If anyone tries to use the idx -+ * directly without tranlation, we catch the bug with a NULL-deference -+ * kernel oops. Illegal ranges of incoming indices are caught too. -+ */ -+static inline unsigned long fix_to_virt(const unsigned int idx) -+{ -+ /* -+ * this branch gets completely eliminated after inlining, -+ * except when someone tries to use fixaddr indices in an -+ * illegal way. (such as mixing up address types or using -+ * out-of-range indices). -+ * -+ * If it doesn't get removed, the linker will complain -+ * loudly with a reasonably clear error message.. -+ */ -+ if (idx >= __end_of_fixed_addresses) -+ __this_fixmap_does_not_exist(); -+ -+ return __fix_to_virt(idx); -+} -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/floppy.h um/include/asm-um/floppy.h ---- orig/include/asm-um/floppy.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/floppy.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_FLOPPY_H -+#define __UM_FLOPPY_H -+ -+#include "asm/arch/floppy.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/hardirq.h um/include/asm-um/hardirq.h ---- orig/include/asm-um/hardirq.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/hardirq.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_HARDIRQ_H -+#define __UM_HARDIRQ_H -+ -+#include "asm/arch/hardirq.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/hdreg.h um/include/asm-um/hdreg.h ---- orig/include/asm-um/hdreg.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/hdreg.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_HDREG_H -+#define __UM_HDREG_H -+ -+#include "asm/arch/hdreg.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/highmem.h um/include/asm-um/highmem.h ---- orig/include/asm-um/highmem.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/highmem.h 2004-02-14 06:29:00.000000000 -0500 -@@ -0,0 +1,12 @@ -+#ifndef __UM_HIGHMEM_H -+#define __UM_HIGHMEM_H -+ -+#include "asm/page.h" -+#include "asm/fixmap.h" -+#include "asm/arch/highmem.h" -+ -+#undef PKMAP_BASE -+ -+#define PKMAP_BASE ((FIXADDR_START - LAST_PKMAP * PAGE_SIZE) & PMD_MASK) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/hw_irq.h um/include/asm-um/hw_irq.h ---- orig/include/asm-um/hw_irq.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/hw_irq.h 2003-12-16 22:26:55.000000000 -0500 -@@ -0,0 +1,10 @@ -+#ifndef _ASM_UM_HW_IRQ_H -+#define _ASM_UM_HW_IRQ_H -+ -+#include "asm/irq.h" -+#include "asm/archparam.h" -+ -+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) -+{} -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ide.h um/include/asm-um/ide.h ---- orig/include/asm-um/ide.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ide.h 2004-01-16 23:40:52.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IDE_H -+#define __UM_IDE_H -+ -+#include "asm/arch/ide.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/init.h um/include/asm-um/init.h ---- orig/include/asm-um/init.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/init.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,11 @@ -+#ifndef _UM_INIT_H -+#define _UM_INIT_H -+ -+#ifdef notdef -+#define __init -+#define __initdata -+#define __initfunc(__arginit) __arginit -+#define __cacheline_aligned -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ioctl.h um/include/asm-um/ioctl.h ---- orig/include/asm-um/ioctl.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ioctl.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IOCTL_H -+#define __UM_IOCTL_H -+ -+#include "asm/arch/ioctl.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ioctls.h um/include/asm-um/ioctls.h ---- orig/include/asm-um/ioctls.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ioctls.h 2003-11-07 02:10:43.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IOCTLS_H -+#define __UM_IOCTLS_H -+ -+#include "asm/arch/ioctls.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/io.h um/include/asm-um/io.h ---- orig/include/asm-um/io.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/io.h 2004-01-16 03:32:59.000000000 -0500 -@@ -0,0 +1,25 @@ -+#ifndef __UM_IO_H -+#define __UM_IO_H -+ -+#include "asm/page.h" -+ -+#define IO_SPACE_LIMIT 0xdeadbeef /* Sure hope nothing uses this */ -+ -+static inline int inb(unsigned long i) { return(0); } -+static inline void outb(char c, unsigned long i) { } -+ -+/* -+ * Change virtual addresses to physical addresses and vv. -+ * These are pretty trivial -+ */ -+static inline unsigned long virt_to_phys(volatile void * address) -+{ -+ return __pa((void *) address); -+} -+ -+static inline void * phys_to_virt(unsigned long address) -+{ -+ return __va(address); -+} -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ipcbuf.h um/include/asm-um/ipcbuf.h ---- orig/include/asm-um/ipcbuf.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ipcbuf.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IPCBUF_H -+#define __UM_IPCBUF_H -+ -+#include "asm/arch/ipcbuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ipc.h um/include/asm-um/ipc.h ---- orig/include/asm-um/ipc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ipc.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IPC_H -+#define __UM_IPC_H -+ -+#include "asm/arch/ipc.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/irq.h um/include/asm-um/irq.h ---- orig/include/asm-um/irq.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/irq.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,22 @@ -+#ifndef __UM_IRQ_H -+#define __UM_IRQ_H -+ -+#define TIMER_IRQ 0 -+#define UMN_IRQ 1 -+#define CONSOLE_IRQ 2 -+#define CONSOLE_WRITE_IRQ 3 -+#define UBD_IRQ 4 -+#define UM_ETH_IRQ 5 -+#define SSL_IRQ 6 -+#define SSL_WRITE_IRQ 7 -+#define ACCEPT_IRQ 8 -+#define MCONSOLE_IRQ 9 -+#define WINCH_IRQ 10 -+#define SIGIO_WRITE_IRQ 11 -+#define TELNETD_IRQ 12 -+#define XTERM_IRQ 13 -+ -+#define LAST_IRQ XTERM_IRQ -+#define NR_IRQS (LAST_IRQ + 1) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/keyboard.h um/include/asm-um/keyboard.h ---- orig/include/asm-um/keyboard.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/keyboard.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_KEYBOARD_H -+#define __UM_KEYBOARD_H -+ -+#include "asm/arch/keyboard.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/kmap_types.h um/include/asm-um/kmap_types.h ---- orig/include/asm-um/kmap_types.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/kmap_types.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,11 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_KMAP_TYPES_H -+#define __UM_KMAP_TYPES_H -+ -+#include "asm/arch/kmap_types.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/linux_logo.h um/include/asm-um/linux_logo.h ---- orig/include/asm-um/linux_logo.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/linux_logo.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_LINUX_LOGO_H -+#define __UM_LINUX_LOGO_H -+ -+#include "asm/arch/linux_logo.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/locks.h um/include/asm-um/locks.h ---- orig/include/asm-um/locks.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/locks.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_LOCKS_H -+#define __UM_LOCKS_H -+ -+#include "asm/arch/locks.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mca_dma.h um/include/asm-um/mca_dma.h ---- orig/include/asm-um/mca_dma.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/mca_dma.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef mca___UM_DMA_H -+#define mca___UM_DMA_H -+ -+#include "asm/arch/mca_dma.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mman.h um/include/asm-um/mman.h ---- orig/include/asm-um/mman.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/mman.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MMAN_H -+#define __UM_MMAN_H -+ -+#include "asm/arch/mman.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mmu_context.h um/include/asm-um/mmu_context.h ---- orig/include/asm-um/mmu_context.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/mmu_context.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_MMU_CONTEXT_H -+#define __UM_MMU_CONTEXT_H -+ -+#include "linux/sched.h" -+#include "choose-mode.h" -+ -+#define get_mmu_context(task) do ; while(0) -+#define activate_context(tsk) do ; while(0) -+ -+static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) -+{ -+} -+ -+extern void switch_mm_skas(int mm_fd); -+ -+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, -+ struct task_struct *tsk, unsigned cpu) -+{ -+ if(prev != next){ -+ clear_bit(cpu, &prev->cpu_vm_mask); -+ set_bit(cpu, &next->cpu_vm_mask); -+ if(next != &init_mm) -+ CHOOSE_MODE((void) 0, -+ switch_mm_skas(next->context.skas.mm_fd)); -+ } -+} -+ -+static inline void enter_lazy_tlb(struct mm_struct *mm, -+ struct task_struct *tsk, unsigned cpu) -+{ -+} -+ -+extern int init_new_context_skas(struct task_struct *task, -+ struct mm_struct *mm); -+ -+static inline int init_new_context_tt(struct task_struct *task, -+ struct mm_struct *mm) -+{ -+ return(0); -+} -+ -+static inline int init_new_context(struct task_struct *task, -+ struct mm_struct *mm) -+{ -+ return(CHOOSE_MODE_PROC(init_new_context_tt, init_new_context_skas, -+ task, mm)); -+} -+ -+extern void destroy_context_skas(struct mm_struct *mm); -+ -+static inline void destroy_context(struct mm_struct *mm) -+{ -+ CHOOSE_MODE((void) 0, destroy_context_skas(mm)); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/mmu.h um/include/asm-um/mmu.h ---- orig/include/asm-um/mmu.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/mmu.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MMU_H -+#define __MMU_H -+ -+#include "um_mmu.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/module.h um/include/asm-um/module.h ---- orig/include/asm-um/module.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/module.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MODULE_H -+#define __UM_MODULE_H -+ -+#include "asm/arch/module.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/msgbuf.h um/include/asm-um/msgbuf.h ---- orig/include/asm-um/msgbuf.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/msgbuf.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MSGBUF_H -+#define __UM_MSGBUF_H -+ -+#include "asm/arch/msgbuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/mtrr.h um/include/asm-um/mtrr.h ---- orig/include/asm-um/mtrr.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/mtrr.h 2004-02-12 05:46:29.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MTRR_H -+#define __UM_MTRR_H -+ -+#include "asm/arch/mtrr.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/namei.h um/include/asm-um/namei.h ---- orig/include/asm-um/namei.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/namei.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_NAMEI_H -+#define __UM_NAMEI_H -+ -+#include "asm/arch/namei.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/page.h um/include/asm-um/page.h ---- orig/include/asm-um/page.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/page.h 2004-01-16 03:32:58.000000000 -0500 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PAGE_H -+#define __UM_PAGE_H -+ -+struct page; -+ -+#include "asm/arch/page.h" -+ -+#undef BUG -+#undef PAGE_BUG -+#undef __pa -+#undef __va -+#undef virt_to_page -+#undef VALID_PAGE -+#undef PAGE_OFFSET -+#undef KERNELBASE -+ -+extern unsigned long uml_physmem; -+ -+#define PAGE_OFFSET (uml_physmem) -+#define KERNELBASE PAGE_OFFSET -+ -+#ifndef __ASSEMBLY__ -+ -+extern void stop(void); -+ -+#define BUG() do { \ -+ panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ -+} while (0) -+ -+#define PAGE_BUG(page) do { \ -+ BUG(); \ -+} while (0) -+ -+#endif /* __ASSEMBLY__ */ -+ -+#define __va_space (8*1024*1024) -+ -+extern unsigned long to_phys(void *virt); -+extern void *to_virt(unsigned long phys); -+ -+#define __pa(virt) to_phys((void *) virt) -+#define __va(phys) to_virt((unsigned long) phys) -+ -+#define VALID_PAGE(page) ((page - mem_map) < max_mapnr) -+ -+extern struct page *arch_validate(struct page *page, int mask, int order); -+#define HAVE_ARCH_VALIDATE -+ -+extern void arch_free_page(struct page *page, int order); -+#define HAVE_ARCH_FREE_PAGE -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/page_offset.h um/include/asm-um/page_offset.h ---- orig/include/asm-um/page_offset.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/page_offset.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1 @@ -+#define PAGE_OFFSET_RAW (uml_physmem) -diff -Naur -X ../exclude-files orig/include/asm-um/param.h um/include/asm-um/param.h ---- orig/include/asm-um/param.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/param.h 2004-02-13 02:26:52.000000000 -0500 -@@ -0,0 +1,22 @@ -+#ifndef _UM_PARAM_H -+#define _UM_PARAM_H -+ -+#define HZ 100 -+ -+#define EXEC_PAGESIZE 4096 -+ -+#ifndef NGROUPS -+#define NGROUPS 32 -+#endif -+ -+#ifndef NOGROUP -+#define NOGROUP (-1) -+#endif -+ -+#define MAXHOSTNAMELEN 64 /* max length of hostname */ -+ -+#ifdef __KERNEL__ -+# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */ -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/pci.h um/include/asm-um/pci.h ---- orig/include/asm-um/pci.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/pci.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_PCI_H -+#define __UM_PCI_H -+ -+#define PCI_DMA_BUS_IS_PHYS (1) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/pgalloc.h um/include/asm-um/pgalloc.h ---- orig/include/asm-um/pgalloc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/pgalloc.h 2004-02-14 06:29:00.000000000 -0500 -@@ -0,0 +1,164 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PGALLOC_H -+#define __UM_PGALLOC_H -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "asm/fixmap.h" -+#include "choose-mode.h" -+ -+#define pgd_quicklist (current_cpu_data.pgd_quick) -+#define pmd_quicklist (current_cpu_data.pmd_quick) -+#define pte_quicklist (current_cpu_data.pte_quick) -+#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) -+ -+#define pmd_populate(mm, pmd, pte) set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) -+ -+/* -+ * Allocate and free page tables. -+ */ -+ -+static inline pgd_t *get_pgd_slow_tt(void) -+{ -+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); -+ -+ if (pgd) { -+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -+ memcpy(pgd + USER_PTRS_PER_PGD, -+ swapper_pg_dir + USER_PTRS_PER_PGD, -+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); -+ } -+ return pgd; -+} -+ -+static inline pgd_t *get_pgd_slow_skas(void) -+{ -+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); -+ -+ if (pgd) -+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -+ return pgd; -+} -+ -+static inline pgd_t *get_pgd_slow(void) -+{ -+ return(CHOOSE_MODE(get_pgd_slow_tt(), get_pgd_slow_skas())); -+} -+ -+static inline pgd_t *get_pgd_fast(void) -+{ -+ unsigned long *ret; -+ -+ ret = pgd_quicklist; -+ if (ret != NULL) { -+ pgd_quicklist = (unsigned long *)(*ret); -+ ret[0] = 0; -+ pgtable_cache_size--; -+ } else -+ ret = (unsigned long *)get_pgd_slow(); -+ return (pgd_t *)ret; -+} -+ -+static inline void free_pgd_fast(pgd_t *pgd) -+{ -+ *(unsigned long *)pgd = (unsigned long) pgd_quicklist; -+ pgd_quicklist = (unsigned long *) pgd; -+ pgtable_cache_size++; -+} -+ -+static inline void free_pgd_slow(pgd_t *pgd) -+{ -+ free_page((unsigned long)pgd); -+} -+ -+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) -+{ -+ pte_t *pte; -+ -+ pte = (pte_t *) __get_free_page(GFP_KERNEL); -+ if (pte) -+ clear_page(pte); -+ return pte; -+} -+ -+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address) -+{ -+ unsigned long *ret; -+ -+ ret = (unsigned long *)pte_quicklist; -+ if (ret != NULL) { -+ pte_quicklist = (unsigned long *)(*ret); -+ ret[0] = ret[1]; -+ pgtable_cache_size--; -+ } -+ return (pte_t *)ret; -+} -+ -+static inline void pte_free_fast(pte_t *pte) -+{ -+ *(unsigned long *)pte = (unsigned long) pte_quicklist; -+ pte_quicklist = (unsigned long *) pte; -+ pgtable_cache_size++; -+} -+ -+static inline void pte_free_slow(pte_t *pte) -+{ -+ free_page((unsigned long)pte); -+} -+ -+#define pte_free(pte) pte_free_fast(pte) -+#define pgd_free(pgd) free_pgd_slow(pgd) -+#define pgd_alloc(mm) get_pgd_fast() -+ -+/* -+ * allocating and freeing a pmd is trivial: the 1-entry pmd is -+ * inside the pgd, so has no extra memory associated with it. -+ */ -+ -+#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); }) -+#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) -+#define pmd_free_slow(x) do { } while (0) -+#define pmd_free_fast(x) do { } while (0) -+#define pmd_free(x) do { } while (0) -+#define pgd_populate(mm, pmd, pte) BUG() -+ -+/* -+ * TLB flushing: -+ * -+ * - flush_tlb() flushes the current mm struct TLBs -+ * - flush_tlb_all() flushes all processes TLBs -+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's -+ * - flush_tlb_page(vma, vmaddr) flushes one page -+ * - flush_tlb_kernel_vm() flushes the kernel vm area -+ * - flush_tlb_range(mm, start, end) flushes a range of pages -+ * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables -+ */ -+ -+extern void flush_tlb_all(void); -+extern void flush_tlb_mm(struct mm_struct *mm); -+extern void flush_tlb_range(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -+extern void flush_tlb_kernel_vm(void); -+ -+static inline void flush_tlb_pgtables(struct mm_struct *mm, -+ unsigned long start, unsigned long end) -+{ -+} -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/pgtable.h um/include/asm-um/pgtable.h ---- orig/include/asm-um/pgtable.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/pgtable.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,413 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Derived from include/asm-i386/pgtable.h -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PGTABLE_H -+#define __UM_PGTABLE_H -+ -+#include "linux/sched.h" -+#include "asm/processor.h" -+#include "asm/page.h" -+ -+extern pgd_t swapper_pg_dir[1024]; -+ -+#define flush_cache_all() do ; while (0) -+#define flush_cache_mm(mm) do ; while (0) -+#define flush_cache_range(vma, start, end) do ; while (0) -+#define flush_cache_page(vma, vmaddr) do ; while (0) -+#define flush_page_to_ram(page) do ; while (0) -+#define flush_dcache_page(page) do ; while (0) -+#define flush_icache_range(from, to) do ; while (0) -+#define flush_icache_page(vma,pg) do ; while (0) -+#define flush_icache_user_range(vma,pg,adr,len) do ; while (0) -+ -+extern void __flush_tlb_one(unsigned long addr); -+ -+extern void pte_free(pte_t *pte); -+ -+extern void pgd_free(pgd_t *pgd); -+ -+extern int do_check_pgt_cache(int, int); -+ -+extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt, -+ pte_t *pte_out); -+ -+/* zero page used for uninitialized stuff */ -+extern unsigned long *empty_zero_page; -+ -+#define pgtable_cache_init() do ; while (0) -+ -+/* PMD_SHIFT determines the size of the area a second-level page table can map */ -+#define PMD_SHIFT 22 -+#define PMD_SIZE (1UL << PMD_SHIFT) -+#define PMD_MASK (~(PMD_SIZE-1)) -+ -+/* PGDIR_SHIFT determines what a third-level page table entry can map */ -+#define PGDIR_SHIFT 22 -+#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -+#define PGDIR_MASK (~(PGDIR_SIZE-1)) -+ -+/* -+ * entries per page directory level: the i386 is two-level, so -+ * we don't really have any PMD directory physically. -+ */ -+#define PTRS_PER_PTE 1024 -+#define PTRS_PER_PMD 1 -+#define PTRS_PER_PGD 1024 -+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) -+#define FIRST_USER_PGD_NR 0 -+ -+#define pte_ERROR(e) \ -+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -+#define pmd_ERROR(e) \ -+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -+#define pgd_ERROR(e) \ -+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) -+ -+/* -+ * pgd entries used up by user/kernel: -+ */ -+ -+#define USER_PGD_PTRS (TASK_SIZE >> PGDIR_SHIFT) -+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) -+ -+#ifndef __ASSEMBLY__ -+/* Just any arbitrary offset to the start of the vmalloc VM area: the -+ * current 8MB value just means that there will be a 8MB "hole" after the -+ * physical memory until the kernel virtual memory starts. That means that -+ * any out-of-bounds memory accesses will hopefully be caught. -+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced -+ * area for the same reason. ;) -+ */ -+ -+extern unsigned long end_iomem; -+ -+#define VMALLOC_OFFSET (__va_space) -+#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -+#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -+ -+#if CONFIG_HIGHMEM -+# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) -+#else -+# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) -+#endif -+ -+#define _PAGE_PRESENT 0x001 -+#define _PAGE_NEWPAGE 0x002 -+#define _PAGE_PROTNONE 0x004 /* If not present */ -+#define _PAGE_RW 0x008 -+#define _PAGE_USER 0x010 -+#define _PAGE_ACCESSED 0x020 -+#define _PAGE_DIRTY 0x040 -+#define _PAGE_NEWPROT 0x080 -+ -+#define REGION_MASK 0xf0000000 -+#define REGION_SHIFT 28 -+ -+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -+#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -+ -+#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) -+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) -+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED) -+ -+/* -+ * The i386 can't do page protection for execute, and considers that the same are read. -+ * Also, write permissions imply read permissions. This is the closest we can get.. -+ */ -+#define __P000 PAGE_NONE -+#define __P001 PAGE_READONLY -+#define __P010 PAGE_COPY -+#define __P011 PAGE_COPY -+#define __P100 PAGE_READONLY -+#define __P101 PAGE_READONLY -+#define __P110 PAGE_COPY -+#define __P111 PAGE_COPY -+ -+#define __S000 PAGE_NONE -+#define __S001 PAGE_READONLY -+#define __S010 PAGE_SHARED -+#define __S011 PAGE_SHARED -+#define __S100 PAGE_READONLY -+#define __S101 PAGE_READONLY -+#define __S110 PAGE_SHARED -+#define __S111 PAGE_SHARED -+ -+/* -+ * Define this if things work differently on an i386 and an i486: -+ * it will (on an i486) warn about kernel memory accesses that are -+ * done without a 'verify_area(VERIFY_WRITE,..)' -+ */ -+#undef TEST_VERIFY_AREA -+ -+/* page table for 0-4MB for everybody */ -+extern unsigned long pg0[1024]; -+ -+/* -+ * BAD_PAGETABLE is used when we need a bogus page-table, while -+ * BAD_PAGE is used for a bogus page. -+ * -+ * ZERO_PAGE is a global shared page that is always zero: used -+ * for zero-mapped memory areas etc.. -+ */ -+extern pte_t __bad_page(void); -+extern pte_t * __bad_pagetable(void); -+ -+#define BAD_PAGETABLE __bad_pagetable() -+#define BAD_PAGE __bad_page() -+ -+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) -+ -+/* number of bits that fit into a memory pointer */ -+#define BITS_PER_PTR (8*sizeof(unsigned long)) -+ -+/* to align the pointer to a pointer address */ -+#define PTR_MASK (~(sizeof(void*)-1)) -+ -+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ -+/* 64-bit machines, beware! SRB. */ -+#define SIZEOF_PTR_LOG2 2 -+ -+/* to find an entry in a page-table */ -+#define PAGE_PTR(address) \ -+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) -+ -+#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE) -+#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) -+ -+#define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0) -+ -+#define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE)) -+#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) -+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) -+#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0) -+ -+#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) -+#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) -+ -+/* -+ * The "pgd_xxx()" functions here are trivial for a folded two-level -+ * setup: the pgd is never bad, and a pmd always exists (as it's folded -+ * into the pgd entry) -+ */ -+static inline int pgd_none(pgd_t pgd) { return 0; } -+static inline int pgd_bad(pgd_t pgd) { return 0; } -+static inline int pgd_present(pgd_t pgd) { return 1; } -+static inline void pgd_clear(pgd_t * pgdp) { } -+ -+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -+ -+#define pte_page(pte) virt_to_page(__va(pte_val(pte))) -+#define pmd_page(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) -+ -+extern struct page *phys_to_page(const unsigned long phys); -+extern struct page *__virt_to_page(const unsigned long virt); -+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr) -+ -+static inline pte_t pte_mknewprot(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_NEWPROT; -+ return(pte); -+} -+ -+static inline pte_t pte_mknewpage(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_NEWPAGE; -+ return(pte); -+} -+ -+static inline void set_pte(pte_t *pteptr, pte_t pteval) -+{ -+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so -+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to -+ * mapped pages. -+ */ -+ *pteptr = pte_mknewpage(pteval); -+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); -+} -+ -+/* -+ * (pmds are folded into pgds so this doesnt get actually called, -+ * but the define is needed for a generic inline function.) -+ */ -+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) -+ -+/* -+ * The following only work if pte_present() is true. -+ * Undefined behaviour if not.. -+ */ -+static inline int pte_read(pte_t pte) -+{ -+ return((pte_val(pte) & _PAGE_USER) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_exec(pte_t pte){ -+ return((pte_val(pte) & _PAGE_USER) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_write(pte_t pte) -+{ -+ return((pte_val(pte) & _PAGE_RW) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -+static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; } -+static inline int pte_newprot(pte_t pte) -+{ -+ return(pte_present(pte) && (pte_val(pte) & _PAGE_NEWPROT)); -+} -+ -+static inline pte_t pte_rdprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_exprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkclean(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_DIRTY; -+ return(pte); -+} -+ -+static inline pte_t pte_mkold(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_ACCESSED; -+ return(pte); -+} -+ -+static inline pte_t pte_wrprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_RW; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkread(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkexec(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkdirty(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_DIRTY; -+ return(pte); -+} -+ -+static inline pte_t pte_mkyoung(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_ACCESSED; -+ return(pte); -+} -+ -+static inline pte_t pte_mkwrite(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_RW; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkuptodate(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_NEWPAGE; -+ if(pte_present(pte)) pte_val(pte) &= ~_PAGE_NEWPROT; -+ return(pte); -+} -+ -+extern unsigned long page_to_phys(struct page *page); -+ -+/* -+ * Conversion functions: convert a page and protection to a page entry, -+ * and a page entry and page directory to the page they refer to. -+ */ -+ -+extern pte_t mk_pte(struct page *page, pgprot_t pgprot); -+ -+/* This takes a physical page address that is used by the remapping -+ * functions -+ */ -+#define mk_pte_phys(phys, pgprot) \ -+ (pte_mknewpage(mk_pte(virt_to_page(__va(phys)), pgprot))) -+ -+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -+{ -+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); -+ if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte)); -+ return pte; -+} -+ -+/* to find an entry in a page-table-directory. */ -+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -+#define __pgd_offset(address) pgd_index(address) -+ -+/* to find an entry in a page-table-directory */ -+#define pgd_offset(mm, address) \ -+((mm)->pgd + ((address) >> PGDIR_SHIFT)) -+ -+/* to find an entry in a kernel page-table-directory */ -+#define pgd_offset_k(address) pgd_offset(&init_mm, address) -+ -+#define __pmd_offset(address) \ -+ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -+ -+/* Find an entry in the second-level page table.. */ -+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -+{ -+ return (pmd_t *) dir; -+} -+ -+/* Find an entry in the third-level page table.. */ -+#define pte_offset(pmd, address) \ -+ ((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2)))) -+ -+#define update_mmu_cache(vma,address,pte) do ; while (0) -+ -+/* Encode and de-code a swap entry */ -+#define SWP_TYPE(x) (((x).val >> 3) & 0x7f) -+#define SWP_OFFSET(x) ((x).val >> 10) -+ -+#define SWP_ENTRY(type, offset) \ -+ ((swp_entry_t) { ((type) << 3) | ((offset) << 10) }) -+#define pte_to_swp_entry(pte) \ -+ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) -+#define swp_entry_to_pte(x) ((pte_t) { (x).val }) -+ -+#define PageSkip(x) (0) -+#define kern_addr_valid(addr) (1) -+ -+#include <asm-generic/pgtable.h> -+ -+#endif -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/poll.h um/include/asm-um/poll.h ---- orig/include/asm-um/poll.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/poll.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_POLL_H -+#define __UM_POLL_H -+ -+#include "asm/arch/poll.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/posix_types.h um/include/asm-um/posix_types.h ---- orig/include/asm-um/posix_types.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/posix_types.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_POSIX_TYPES_H -+#define __UM_POSIX_TYPES_H -+ -+#include "asm/arch/posix_types.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/processor-generic.h um/include/asm-um/processor-generic.h ---- orig/include/asm-um/processor-generic.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/processor-generic.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,177 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PROCESSOR_GENERIC_H -+#define __UM_PROCESSOR_GENERIC_H -+ -+struct pt_regs; -+ -+struct task_struct; -+ -+#include "linux/config.h" -+#include "linux/signal.h" -+#include "asm/ptrace.h" -+#include "asm/siginfo.h" -+#include "choose-mode.h" -+ -+struct mm_struct; -+ -+#define current_text_addr() ((void *) 0) -+ -+#define cpu_relax() do ; while (0) -+ -+struct thread_struct { -+ int forking; -+ unsigned long kernel_stack; -+ int nsyscalls; -+ struct pt_regs regs; -+ unsigned long cr2; -+ int err; -+ unsigned long trap_no; -+ void *fault_addr; -+ void *fault_catcher; -+ struct task_struct *prev_sched; -+ unsigned long temp_stack; -+ void *exec_buf; -+ struct arch_thread arch; -+ union { -+#ifdef CONFIG_MODE_TT -+ struct { -+ int extern_pid; -+ int tracing; -+ int switch_pipe[2]; -+ int singlestep_syscall; -+ int vm_seq; -+ } tt; -+#endif -+#ifdef CONFIG_MODE_SKAS -+ struct { -+ void *switch_buf; -+ void *fork_buf; -+ int mm_count; -+ } skas; -+#endif -+ } mode; -+ struct { -+ int op; -+ union { -+ struct { -+ int pid; -+ } fork, exec; -+ struct { -+ int (*proc)(void *); -+ void *arg; -+ } thread; -+ struct { -+ void (*proc)(void *); -+ void *arg; -+ } cb; -+ } u; -+ } request; -+}; -+ -+#define INIT_THREAD \ -+{ \ -+ .forking = 0, \ -+ .kernel_stack = 0, \ -+ .nsyscalls = 0, \ -+ .regs = EMPTY_REGS, \ -+ .cr2 = 0, \ -+ .err = 0, \ -+ .fault_addr = NULL, \ -+ .prev_sched = NULL, \ -+ .temp_stack = 0, \ -+ .exec_buf = NULL, \ -+ .arch = INIT_ARCH_THREAD, \ -+ .request = { 0 } \ -+} -+ -+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -+ -+typedef struct { -+ unsigned long seg; -+} mm_segment_t; -+ -+extern struct task_struct *alloc_task_struct(void); -+extern void free_task_struct(struct task_struct *task); -+ -+#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) -+ -+extern void release_thread(struct task_struct *); -+extern int arch_kernel_thread(int (*fn)(void *), void * arg, -+ unsigned long flags); -+extern void dump_thread(struct pt_regs *regs, struct user *u); -+ -+extern unsigned long thread_saved_pc(struct thread_struct *t); -+ -+static inline void mm_copy_segments(struct mm_struct *from_mm, -+ struct mm_struct *new_mm) -+{ -+} -+ -+static inline void copy_segments(struct task_struct *p, -+ struct mm_struct *new_mm) -+{ -+} -+ -+static inline void release_segments(struct mm_struct *mm) -+{ -+} -+ -+#define init_task (init_task_union.task) -+#define init_stack (init_task_union.stack) -+ -+/* -+ * User space process size: 3GB (default). -+ */ -+extern unsigned long task_size; -+ -+#define TASK_SIZE (task_size) -+ -+/* This decides where the kernel will search for a free chunk of vm -+ * space during mmap's. -+ */ -+#define TASK_UNMAPPED_BASE (0x40000000) -+ -+extern void start_thread(struct pt_regs *regs, unsigned long entry, -+ unsigned long stack); -+ -+struct cpuinfo_um { -+ unsigned long loops_per_jiffy; -+ unsigned long *pgd_quick; -+ unsigned long *pmd_quick; -+ unsigned long *pte_quick; -+ unsigned long pgtable_cache_sz; -+ int ipi_pipe[2]; -+}; -+ -+extern struct cpuinfo_um boot_cpu_data; -+ -+#define my_cpu_data cpu_data[smp_processor_id()] -+ -+#ifdef CONFIG_SMP -+extern struct cpuinfo_um cpu_data[]; -+#define current_cpu_data cpu_data[smp_processor_id()] -+#else -+#define cpu_data (&boot_cpu_data) -+#define current_cpu_data boot_cpu_data -+#endif -+ -+#define KSTK_EIP(tsk) (PT_REGS_IP(&tsk->thread.regs)) -+#define KSTK_ESP(tsk) (PT_REGS_SP(&tsk->thread.regs)) -+#define get_wchan(p) (0) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/processor-i386.h um/include/asm-um/processor-i386.h ---- orig/include/asm-um/processor-i386.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/processor-i386.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PROCESSOR_I386_H -+#define __UM_PROCESSOR_I386_H -+ -+extern int cpu_has_xmm; -+extern int cpu_has_cmov; -+ -+struct arch_thread { -+ unsigned long debugregs[8]; -+ int debugregs_seq; -+}; -+ -+#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \ -+ .debugregs_seq = 0 } -+ -+#include "asm/arch/user.h" -+ -+#include "asm/processor-generic.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/processor-ppc.h um/include/asm-um/processor-ppc.h ---- orig/include/asm-um/processor-ppc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/processor-ppc.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,15 @@ -+#ifndef __UM_PROCESSOR_PPC_H -+#define __UM_PROCESSOR_PPC_H -+ -+#if defined(__ASSEMBLY__) -+ -+#define CONFIG_ALL_PPC -+#include "arch/processor.h" -+ -+#else -+ -+#include "asm/processor-generic.h" -+ -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/ptrace-generic.h um/include/asm-um/ptrace-generic.h ---- orig/include/asm-um/ptrace-generic.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ptrace-generic.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PTRACE_GENERIC_H -+#define __UM_PTRACE_GENERIC_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include "linux/config.h" -+ -+#include "asm/current.h" -+ -+#define pt_regs pt_regs_subarch -+#define show_regs show_regs_subarch -+ -+#include "asm/arch/ptrace.h" -+ -+#undef pt_regs -+#undef show_regs -+#undef user_mode -+#undef instruction_pointer -+ -+#include "sysdep/ptrace.h" -+#include "skas_ptrace.h" -+ -+struct pt_regs { -+ union uml_pt_regs regs; -+}; -+ -+#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS } -+ -+#define PT_REGS_IP(r) UPT_IP(&(r)->regs) -+#define PT_REGS_SP(r) UPT_SP(&(r)->regs) -+ -+#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg) -+#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val) -+ -+#define PT_REGS_SET_SYSCALL_RETURN(r, res) \ -+ UPT_SET_SYSCALL_RETURN(&(r)->regs, res) -+#define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs) -+ -+#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs) -+ -+#define PT_REGS_SC(r) UPT_SC(&(r)->regs) -+ -+struct task_struct; -+ -+extern unsigned long getreg(struct task_struct *child, int regno); -+extern int putreg(struct task_struct *child, int regno, unsigned long value); -+extern int get_fpregs(unsigned long buf, struct task_struct *child); -+extern int set_fpregs(unsigned long buf, struct task_struct *child); -+extern int get_fpxregs(unsigned long buf, struct task_struct *child); -+extern int set_fpxregs(unsigned long buf, struct task_struct *tsk); -+ -+extern void show_regs(struct pt_regs *regs); -+ -+#define INIT_TASK_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -+ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/ptrace-i386.h um/include/asm-um/ptrace-i386.h ---- orig/include/asm-um/ptrace-i386.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ptrace-i386.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PTRACE_I386_H -+#define __UM_PTRACE_I386_H -+ -+#include "sysdep/ptrace.h" -+#include "asm/ptrace-generic.h" -+ -+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs) -+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs) -+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs) -+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs) -+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs) -+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs) -+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs) -+ -+#define PT_REGS_CS(r) UPT_CS(&(r)->regs) -+#define PT_REGS_SS(r) UPT_SS(&(r)->regs) -+#define PT_REGS_DS(r) UPT_DS(&(r)->regs) -+#define PT_REGS_ES(r) UPT_ES(&(r)->regs) -+#define PT_REGS_FS(r) UPT_FS(&(r)->regs) -+#define PT_REGS_GS(r) UPT_GS(&(r)->regs) -+ -+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) -+ -+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r) -+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r) -+#define PT_FIX_EXEC_STACK(sp) do ; while(0) -+ -+#define user_mode(r) UPT_IS_USER(&(r)->regs) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/resource.h um/include/asm-um/resource.h ---- orig/include/asm-um/resource.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/resource.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_RESOURCE_H -+#define __UM_RESOURCE_H -+ -+#include "asm/arch/resource.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/rwlock.h um/include/asm-um/rwlock.h ---- orig/include/asm-um/rwlock.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/rwlock.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_RWLOCK_H -+#define __UM_RWLOCK_H -+ -+#include "asm/arch/rwlock.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/rwsem.h um/include/asm-um/rwsem.h ---- orig/include/asm-um/rwsem.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/rwsem.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,10 @@ -+#ifndef __UM_RWSEM_H__ -+#define __UM_RWSEM_H__ -+ -+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) -+#define __builtin_expect(exp,c) (exp) -+#endif -+ -+#include "asm/arch/rwsem.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/scatterlist.h um/include/asm-um/scatterlist.h ---- orig/include/asm-um/scatterlist.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/scatterlist.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SCATTERLIST_H -+#define __UM_SCATTERLIST_H -+ -+#include "asm/arch/scatterlist.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/segment.h um/include/asm-um/segment.h ---- orig/include/asm-um/segment.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/segment.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,4 @@ -+#ifndef __UM_SEGMENT_H -+#define __UM_SEGMENT_H -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/semaphore.h um/include/asm-um/semaphore.h ---- orig/include/asm-um/semaphore.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/semaphore.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SEMAPHORE_H -+#define __UM_SEMAPHORE_H -+ -+#include "asm/arch/semaphore.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sembuf.h um/include/asm-um/sembuf.h ---- orig/include/asm-um/sembuf.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/sembuf.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SEMBUF_H -+#define __UM_SEMBUF_H -+ -+#include "asm/arch/sembuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/serial.h um/include/asm-um/serial.h ---- orig/include/asm-um/serial.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/serial.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SERIAL_H -+#define __UM_SERIAL_H -+ -+#include "asm/arch/serial.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/shmbuf.h um/include/asm-um/shmbuf.h ---- orig/include/asm-um/shmbuf.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/shmbuf.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SHMBUF_H -+#define __UM_SHMBUF_H -+ -+#include "asm/arch/shmbuf.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/shmparam.h um/include/asm-um/shmparam.h ---- orig/include/asm-um/shmparam.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/shmparam.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SHMPARAM_H -+#define __UM_SHMPARAM_H -+ -+#include "asm/arch/shmparam.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-generic.h um/include/asm-um/sigcontext-generic.h ---- orig/include/asm-um/sigcontext-generic.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/sigcontext-generic.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGCONTEXT_GENERIC_H -+#define __UM_SIGCONTEXT_GENERIC_H -+ -+#include "asm/arch/sigcontext.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-i386.h um/include/asm-um/sigcontext-i386.h ---- orig/include/asm-um/sigcontext-i386.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/sigcontext-i386.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGCONTEXT_I386_H -+#define __UM_SIGCONTEXT_I386_H -+ -+#include "asm/sigcontext-generic.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sigcontext-ppc.h um/include/asm-um/sigcontext-ppc.h ---- orig/include/asm-um/sigcontext-ppc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/sigcontext-ppc.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,10 @@ -+#ifndef __UM_SIGCONTEXT_PPC_H -+#define __UM_SIGCONTEXT_PPC_H -+ -+#define pt_regs sys_pt_regs -+ -+#include "asm/sigcontext-generic.h" -+ -+#undef pt_regs -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/siginfo.h um/include/asm-um/siginfo.h ---- orig/include/asm-um/siginfo.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/siginfo.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGINFO_H -+#define __UM_SIGINFO_H -+ -+#include "asm/arch/siginfo.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/signal.h um/include/asm-um/signal.h ---- orig/include/asm-um/signal.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/signal.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SIGNAL_H -+#define __UM_SIGNAL_H -+ -+#include "asm/arch/signal.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/smp.h um/include/asm-um/smp.h ---- orig/include/asm-um/smp.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/smp.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,19 @@ -+#ifndef __UM_SMP_H -+#define __UM_SMP_H -+ -+#ifdef CONFIG_SMP -+ -+#include "linux/config.h" -+#include "asm/current.h" -+ -+#define smp_processor_id() (current->processor) -+#define cpu_logical_map(n) (n) -+#define cpu_number_map(n) (n) -+#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ -+extern int hard_smp_processor_id(void); -+extern unsigned long cpu_online_map; -+#define NO_PROC_ID -1 -+ -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/smplock.h um/include/asm-um/smplock.h ---- orig/include/asm-um/smplock.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/smplock.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SMPLOCK_H -+#define __UM_SMPLOCK_H -+ -+#include "asm/arch/smplock.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/socket.h um/include/asm-um/socket.h ---- orig/include/asm-um/socket.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/socket.h 2003-11-07 02:10:43.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SOCKET_H -+#define __UM_SOCKET_H -+ -+#include "asm/arch/socket.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/sockios.h um/include/asm-um/sockios.h ---- orig/include/asm-um/sockios.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/sockios.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SOCKIOS_H -+#define __UM_SOCKIOS_H -+ -+#include "asm/arch/sockios.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/softirq.h um/include/asm-um/softirq.h ---- orig/include/asm-um/softirq.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/softirq.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,13 @@ -+#ifndef __UM_SOFTIRQ_H -+#define __UM_SOFTIRQ_H -+ -+#include "linux/smp.h" -+#include "asm/system.h" -+#include "asm/processor.h" -+ -+/* A gratuitous name change */ -+#define i386_bh_lock um_bh_lock -+#include "asm/arch/softirq.h" -+#undef i386_bh_lock -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/spinlock.h um/include/asm-um/spinlock.h ---- orig/include/asm-um/spinlock.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/spinlock.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,10 @@ -+#ifndef __UM_SPINLOCK_H -+#define __UM_SPINLOCK_H -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_SMP -+#include "asm/arch/spinlock.h" -+#endif -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/statfs.h um/include/asm-um/statfs.h ---- orig/include/asm-um/statfs.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/statfs.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef _UM_STATFS_H -+#define _UM_STATFS_H -+ -+#include "asm/arch/statfs.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/stat.h um/include/asm-um/stat.h ---- orig/include/asm-um/stat.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/stat.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_STAT_H -+#define __UM_STAT_H -+ -+#include "asm/arch/stat.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/string.h um/include/asm-um/string.h ---- orig/include/asm-um/string.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/string.h 2004-01-16 03:32:58.000000000 -0500 -@@ -0,0 +1,7 @@ -+#ifndef __UM_STRING_H -+#define __UM_STRING_H -+ -+#include "asm/arch/string.h" -+#include "asm/archparam.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/system-generic.h um/include/asm-um/system-generic.h ---- orig/include/asm-um/system-generic.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/system-generic.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,50 @@ -+#ifndef __UM_SYSTEM_GENERIC_H -+#define __UM_SYSTEM_GENERIC_H -+ -+#include "asm/arch/system.h" -+ -+#undef prepare_to_switch -+#undef switch_to -+#undef __save_flags -+#undef save_flags -+#undef __restore_flags -+#undef restore_flags -+#undef __cli -+#undef __sti -+#undef cli -+#undef sti -+#undef local_irq_save -+#undef local_irq_restore -+#undef local_irq_disable -+#undef local_irq_enable -+ -+#define prepare_to_switch() do ; while(0) -+ -+void *_switch_to(void *prev, void *next); -+ -+#define switch_to(prev, next, last) prev = _switch_to(prev, next) -+ -+extern int get_signals(void); -+extern int set_signals(int enable); -+extern void block_signals(void); -+extern void unblock_signals(void); -+ -+#define local_irq_save(flags) do { (flags) = set_signals(0); } while(0) -+ -+#define local_irq_restore(flags) do { set_signals(flags); } while(0) -+ -+#define local_irq_enable() unblock_signals() -+#define local_irq_disable() block_signals() -+ -+#define __sti() unblock_signals() -+#define sti() unblock_signals() -+#define __cli() block_signals() -+#define cli() block_signals() -+ -+#define __save_flags(x) do { (x) = get_signals(); } while(0) -+#define save_flags(x) __save_flags(x) -+ -+#define __restore_flags(x) local_irq_restore(x) -+#define restore_flags(x) __restore_flags(x) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/system-i386.h um/include/asm-um/system-i386.h ---- orig/include/asm-um/system-i386.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/system-i386.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,39 @@ -+#ifndef __UM_SYSTEM_I386_H -+#define __UM_SYSTEM_I386_H -+ -+#include "asm/system-generic.h" -+ -+#define __HAVE_ARCH_CMPXCHG 1 -+ -+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, -+ unsigned long new, int size) -+{ -+ unsigned long prev; -+ switch (size) { -+ case 1: -+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" -+ : "=a"(prev) -+ : "q"(new), "m"(*__xg(ptr)), "0"(old) -+ : "memory"); -+ return prev; -+ case 2: -+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" -+ : "=a"(prev) -+ : "q"(new), "m"(*__xg(ptr)), "0"(old) -+ : "memory"); -+ return prev; -+ case 4: -+ __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" -+ : "=a"(prev) -+ : "q"(new), "m"(*__xg(ptr)), "0"(old) -+ : "memory"); -+ return prev; -+ } -+ return old; -+} -+ -+#define cmpxchg(ptr,o,n)\ -+ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ -+ (unsigned long)(n),sizeof(*(ptr)))) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/system-ppc.h um/include/asm-um/system-ppc.h ---- orig/include/asm-um/system-ppc.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/system-ppc.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,12 @@ -+#ifndef __UM_SYSTEM_PPC_H -+#define __UM_SYSTEM_PPC_H -+ -+#define _switch_to _ppc_switch_to -+ -+#include "asm/arch/system.h" -+ -+#undef _switch_to -+ -+#include "asm/system-generic.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/termbits.h um/include/asm-um/termbits.h ---- orig/include/asm-um/termbits.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/termbits.h 2003-11-07 02:10:43.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TERMBITS_H -+#define __UM_TERMBITS_H -+ -+#include "asm/arch/termbits.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/termios.h um/include/asm-um/termios.h ---- orig/include/asm-um/termios.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/termios.h 2003-12-16 22:26:55.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TERMIOS_H -+#define __UM_TERMIOS_H -+ -+#include "asm/arch/termios.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/timex.h um/include/asm-um/timex.h ---- orig/include/asm-um/timex.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/timex.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,18 @@ -+#ifndef __UM_TIMEX_H -+#define __UM_TIMEX_H -+ -+#include "linux/time.h" -+ -+typedef unsigned long cycles_t; -+ -+#define cacheflush_time (0) -+ -+static inline cycles_t get_cycles (void) -+{ -+ return 0; -+} -+ -+#define vxtime_lock() do ; while (0) -+#define vxtime_unlock() do ; while (0) -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/tlb.h um/include/asm-um/tlb.h ---- orig/include/asm-um/tlb.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/tlb.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1 @@ -+#include <asm-generic/tlb.h> -diff -Naur -X ../exclude-files orig/include/asm-um/types.h um/include/asm-um/types.h ---- orig/include/asm-um/types.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/types.h 2004-01-16 03:32:58.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TYPES_H -+#define __UM_TYPES_H -+ -+#include "asm/arch/types.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/uaccess.h um/include/asm-um/uaccess.h ---- orig/include/asm-um/uaccess.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/uaccess.h 2004-02-14 06:28:59.000000000 -0500 -@@ -0,0 +1,99 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_UACCESS_H -+#define __UM_UACCESS_H -+ -+#include "linux/sched.h" -+ -+#define VERIFY_READ 0 -+#define VERIFY_WRITE 1 -+ -+/* -+ * The fs value determines whether argument validity checking should be -+ * performed or not. If get_fs() == USER_DS, checking is performed, with -+ * get_fs() == KERNEL_DS, checking is bypassed. -+ * -+ * For historical reasons, these macros are grossly misnamed. -+ */ -+ -+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -+ -+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -+#define USER_DS MAKE_MM_SEG(TASK_SIZE) -+ -+#define get_ds() (KERNEL_DS) -+#define get_fs() (current->addr_limit) -+#define set_fs(x) (current->addr_limit = (x)) -+ -+#define segment_eq(a, b) ((a).seg == (b).seg) -+ -+#include "um_uaccess.h" -+ -+#define __copy_from_user(to, from, n) copy_from_user(to, from, n) -+ -+#define __copy_to_user(to, from, n) copy_to_user(to, from, n) -+ -+#define __get_user(x, ptr) \ -+({ \ -+ const __typeof__(ptr) __private_ptr = ptr; \ -+ __typeof__(*(__private_ptr)) __private_val; \ -+ int __private_ret = -EFAULT; \ -+ (x) = 0; \ -+ if (__copy_from_user(&__private_val, (__private_ptr), \ -+ sizeof(*(__private_ptr))) == 0) {\ -+ (x) = (__typeof__(*(__private_ptr))) __private_val; \ -+ __private_ret = 0; \ -+ } \ -+ __private_ret; \ -+}) -+ -+#define get_user(x, ptr) \ -+({ \ -+ const __typeof__((*ptr)) *private_ptr = (ptr); \ -+ (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \ -+ __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \ -+}) -+ -+#define __put_user(x, ptr) \ -+({ \ -+ __typeof__(ptr) __private_ptr = ptr; \ -+ __typeof__(*(__private_ptr)) __private_val; \ -+ int __private_ret = -EFAULT; \ -+ __private_val = (__typeof__(*(__private_ptr))) (x); \ -+ if (__copy_to_user((__private_ptr), &__private_val, \ -+ sizeof(*(__private_ptr))) == 0) { \ -+ __private_ret = 0; \ -+ } \ -+ __private_ret; \ -+}) -+ -+#define put_user(x, ptr) \ -+({ \ -+ __typeof__(*(ptr)) *private_ptr = (ptr); \ -+ (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \ -+ __put_user(x, private_ptr) : -EFAULT); \ -+}) -+ -+#define strlen_user(str) strnlen_user(str, ~0UL >> 1) -+ -+struct exception_table_entry -+{ -+ unsigned long insn; -+ unsigned long fixup; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/ucontext.h um/include/asm-um/ucontext.h ---- orig/include/asm-um/ucontext.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/ucontext.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef _ASM_UM_UCONTEXT_H -+#define _ASM_UM_UCONTEXT_H -+ -+#include "asm/arch/ucontext.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/unaligned.h um/include/asm-um/unaligned.h ---- orig/include/asm-um/unaligned.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/unaligned.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_UNALIGNED_H -+#define __UM_UNALIGNED_H -+ -+#include "asm/arch/unaligned.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/unistd.h um/include/asm-um/unistd.h ---- orig/include/asm-um/unistd.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/unistd.h 2004-02-14 06:29:00.000000000 -0500 -@@ -0,0 +1,121 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef _UM_UNISTD_H_ -+#define _UM_UNISTD_H_ -+ -+#include "linux/resource.h" -+#include "asm/uaccess.h" -+ -+extern long sys_open(const char *filename, int flags, int mode); -+extern long sys_dup(unsigned int fildes); -+extern long sys_close(unsigned int fd); -+extern int um_execve(const char *file, char *const argv[], char *const env[]); -+extern long sys_setsid(void); -+extern long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options); -+extern long sys_wait4(pid_t pid,unsigned int *stat_addr, int options, -+ struct rusage *ru); -+extern long sys_mount(char *dev_name, char *dir_name, char *type, -+ unsigned long flags, void *data); -+extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, -+ struct timeval *tvp); -+extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence); -+extern long sys_read(unsigned int fildes, char *buf, int len); -+extern long sys_write(unsigned int fildes, char *buf, int len); -+ -+#ifdef __KERNEL_SYSCALLS__ -+ -+#define KERNEL_CALL(ret_t, sys, args...) \ -+ mm_segment_t fs = get_fs(); \ -+ ret_t ret; \ -+ set_fs(KERNEL_DS); \ -+ ret = sys(args); \ -+ set_fs(fs); \ -+ if (ret >= 0) \ -+ return ret; \ -+ errno = -(long)ret; \ -+ return -1; -+ -+static inline long open(const char *pathname, int flags, int mode) -+{ -+ KERNEL_CALL(int, sys_open, pathname, flags, mode) -+} -+ -+static inline long dup(unsigned int fd) -+{ -+ KERNEL_CALL(int, sys_dup, fd); -+} -+ -+static inline long close(unsigned int fd) -+{ -+ KERNEL_CALL(int, sys_close, fd); -+} -+ -+static inline int execve(const char *filename, char *const argv[], -+ char *const envp[]) -+{ -+ KERNEL_CALL(int, um_execve, filename, argv, envp); -+} -+ -+static inline long waitpid(pid_t pid, unsigned int *status, int options) -+{ -+ KERNEL_CALL(pid_t, sys_wait4, pid, status, options, NULL) -+} -+ -+static inline pid_t wait(int *status) -+{ -+ KERNEL_CALL(pid_t, sys_wait4, -1, status, 0, NULL) -+} -+ -+static inline pid_t setsid(void) -+{ -+ KERNEL_CALL(pid_t, sys_setsid) -+} -+ -+static inline long lseek(unsigned int fd, off_t offset, unsigned int whence) -+{ -+ KERNEL_CALL(long, sys_lseek, fd, offset, whence) -+} -+ -+static inline int read(unsigned int fd, char * buf, int len) -+{ -+ KERNEL_CALL(int, sys_read, fd, buf, len) -+} -+ -+static inline int write(unsigned int fd, char * buf, int len) -+{ -+ KERNEL_CALL(int, sys_write, fd, buf, len) -+} -+ -+#endif -+ -+/* Save the value of __KERNEL_SYSCALLS__, undefine it, include the underlying -+ * arch's unistd.h for the system call numbers, and restore the old -+ * __KERNEL_SYSCALLS__. -+ */ -+ -+#ifdef __KERNEL_SYSCALLS__ -+#define __SAVE_KERNEL_SYSCALLS__ __KERNEL_SYSCALLS__ -+#endif -+ -+#undef __KERNEL_SYSCALLS__ -+#include "asm/arch/unistd.h" -+ -+#ifdef __KERNEL_SYSCALLS__ -+#define __KERNEL_SYSCALLS__ __SAVE_KERNEL_SYSCALLS__ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/asm-um/user.h um/include/asm-um/user.h ---- orig/include/asm-um/user.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/user.h 2004-02-14 06:31:38.000000000 -0500 -@@ -0,0 +1,6 @@ -+#ifndef __UM_USER_H -+#define __UM_USER_H -+ -+#include "asm/arch/user.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/vga.h um/include/asm-um/vga.h ---- orig/include/asm-um/vga.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/vga.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_VGA_H -+#define __UM_VGA_H -+ -+#include "asm/arch/vga.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/asm-um/xor.h um/include/asm-um/xor.h ---- orig/include/asm-um/xor.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/asm-um/xor.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,6 @@ -+#ifndef __UM_XOR_H -+#define __UM_XOR_H -+ -+#include "asm-generic/xor.h" -+ -+#endif -diff -Naur -X ../exclude-files orig/include/linux/blk.h um/include/linux/blk.h ---- orig/include/linux/blk.h 2004-01-11 22:46:30.000000000 -0500 -+++ um/include/linux/blk.h 2004-02-14 06:29:18.000000000 -0500 -@@ -320,6 +320,24 @@ - #define DEVICE_REQUEST do_ida_request - #define DEVICE_NR(device) (MINOR(device) >> 4) - -+#elif (MAJOR_NR == UBD_MAJOR) -+ -+#define DEVICE_NAME "User-mode block device" -+#define DEVICE_INTR do_ubd -+#define DEVICE_REQUEST do_ubd_request -+#define DEVICE_NR(device) (MINOR(device) >> UBD_SHIFT) -+#define DEVICE_ON(device) -+#define DEVICE_OFF(device) -+ -+#elif (MAJOR_NR == COW_MAJOR) -+ -+#define DEVICE_NAME "COW device" -+#define DEVICE_INTR do_cow -+#define DEVICE_REQUEST do_cow_request -+#define DEVICE_NR(device) (MINOR(device) >> COW_SHIFT) -+#define DEVICE_ON(device) -+#define DEVICE_OFF(device) -+ - #endif /* MAJOR_NR == whatever */ - - /* provide DEVICE_xxx defaults, if not explicitly defined -diff -Naur -X ../exclude-files orig/include/linux/fs.h um/include/linux/fs.h ---- orig/include/linux/fs.h 2003-12-16 22:16:36.000000000 -0500 -+++ um/include/linux/fs.h 2004-02-14 06:28:59.000000000 -0500 -@@ -320,6 +320,8 @@ - #include <linux/ncp_fs_i.h> - #include <linux/proc_fs_i.h> - #include <linux/usbdev_fs_i.h> -+#include <linux/hostfs_fs_i.h> -+#include <linux/hppfs_fs_i.h> - #include <linux/jffs2_fs_i.h> - #include <linux/cramfs_fs_sb.h> - -@@ -516,7 +518,9 @@ - struct proc_inode_info proc_i; - struct socket socket_i; - struct usbdev_inode_info usbdev_i; -- struct jffs2_inode_info jffs2_i; -+ struct hostfs_inode_info hostfs_i; -+ struct hppfs_inode_info hppfs_i; -+ struct jffs2_inode_info jffs2_i; - void *generic_ip; - } u; - }; -@@ -864,6 +868,8 @@ - unsigned int (*poll) (struct file *, struct poll_table_struct *); - int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); - int (*mmap) (struct file *, struct vm_area_struct *); -+ void (*munmap) (struct file *, struct vm_area_struct *, -+ unsigned long start, unsigned long len); - int (*open) (struct inode *, struct file *); - int (*flush) (struct file *); - int (*release) (struct inode *, struct file *); -diff -Naur -X ../exclude-files orig/include/linux/ghash.h um/include/linux/ghash.h ---- orig/include/linux/ghash.h 1997-07-07 11:24:28.000000000 -0400 -+++ um/include/linux/ghash.h 2003-10-21 03:26:07.000000000 -0400 -@@ -153,6 +153,26 @@ - return NULL;\ - } - -+/* LINKAGE - empty or "static", depending on whether you want the definitions to -+ * be public or not -+ * NAME - a string to stick in names to make this hash table type distinct from -+ * any others -+ * HASHSIZE - number of buckets -+ * TYPE - type of data contained in the buckets - must be a structure, one -+ * field is of type NAME_ptrs, another is the hash key -+ * PTRS - TYPE must contain a field of type NAME_ptrs, PTRS is the name of that -+ * field -+ * KEYTYPE - type of the key field within TYPE -+ * KEY - name of the key field within TYPE -+ * KEYCMP - pointer to function that compares KEYTYPEs to each other - the -+ * prototype is int KEYCMP(KEYTYPE, KEYTYPE), it returns zero for equal, -+ * non-zero for not equal -+ * HASHFN - the hash function - the prototype is int HASHFN(KEYTYPE), -+ * it returns a number in the range 0 ... HASHSIZE - 1 -+ * Call DEF_HASH_STRUCTS, define your hash table as a NAME_table, then call -+ * DEF_HASH. -+ */ -+ - #define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \ - \ - struct NAME##_table {\ -@@ -165,7 +185,7 @@ - TYPE * prev_hash;\ - }; - --#define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\ -+#define DEF_HASH(LINKAGE,NAME,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,HASHFN)\ - \ - LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\ - {\ -@@ -206,12 +226,10 @@ - \ - LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\ - {\ -- int ix = hashfn(pos);\ -+ int ix = HASHFN(pos);\ - TYPE * ptr = tbl->hashtable[ix];\ - while(ptr && KEYCMP(ptr->KEY, pos))\ - ptr = ptr->PTRS.next_hash;\ -- if(ptr && !KEYEQ(ptr->KEY, pos))\ -- ptr = NULL;\ - return ptr;\ - } - -diff -Naur -X ../exclude-files orig/include/linux/hostfs_fs_i.h um/include/linux/hostfs_fs_i.h ---- orig/include/linux/hostfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/linux/hostfs_fs_i.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,21 @@ -+#ifndef _HOSTFS_FS_I -+#define _HOSTFS_FS_I -+ -+struct hostfs_inode_info { -+ char *host_filename; -+ int fd; -+ int mode; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/linux/hppfs_fs_i.h um/include/linux/hppfs_fs_i.h ---- orig/include/linux/hppfs_fs_i.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/linux/hppfs_fs_i.h 2003-10-21 03:26:07.000000000 -0400 -@@ -0,0 +1,19 @@ -+#ifndef _HPPFS_FS_I -+#define _HPPFS_FS_I -+ -+struct hppfs_inode_info { -+ struct dentry *proc_dentry; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/include/linux/kernel.h um/include/linux/kernel.h ---- orig/include/linux/kernel.h 2004-01-11 22:46:12.000000000 -0500 -+++ um/include/linux/kernel.h 2004-02-14 06:28:59.000000000 -0500 -@@ -49,7 +49,7 @@ - # define ATTRIB_NORET __attribute__((noreturn)) - # define NORET_AND noreturn, - --#ifdef __i386__ -+#if defined(__i386__) || defined(UM_FASTCALL) - #define FASTCALL(x) x __attribute__((regparm(3))) - #else - #define FASTCALL(x) x -diff -Naur -X ../exclude-files orig/include/linux/kernel_stat.h um/include/linux/kernel_stat.h ---- orig/include/linux/kernel_stat.h 2004-01-11 22:46:12.000000000 -0500 -+++ um/include/linux/kernel_stat.h 2004-02-14 06:28:59.000000000 -0500 -@@ -12,7 +12,7 @@ - * used by rstatd/perfmeter - */ - --#define DK_MAX_MAJOR 16 -+#define DK_MAX_MAJOR 99 - #define DK_MAX_DISK 16 - - struct kernel_stat { -diff -Naur -X ../exclude-files orig/include/linux/mm.h um/include/linux/mm.h ---- orig/include/linux/mm.h 2003-12-16 22:16:36.000000000 -0500 -+++ um/include/linux/mm.h 2004-02-14 06:28:59.000000000 -0500 -@@ -438,6 +438,18 @@ - extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)); - extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order); - -+#ifndef HAVE_ARCH_VALIDATE -+static inline struct page *arch_validate(struct page *page, -+ unsigned int gfp_mask, int order) -+{ -+ return(page); -+} -+#endif -+ -+#ifndef HAVE_ARCH_FREE_PAGE -+static inline void arch_free_page(struct page *page, int order) { } -+#endif -+ - static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order) - { - /* -@@ -445,7 +457,7 @@ - */ - if (order >= MAX_ORDER) - return NULL; -- return _alloc_pages(gfp_mask, order); -+ return arch_validate(_alloc_pages(gfp_mask, order), gfp_mask, order); - } - - #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) -@@ -505,6 +517,9 @@ - int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, - int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); - -+extern long do_mprotect(struct mm_struct *mm, unsigned long start, -+ size_t len, unsigned long prot); -+ - /* - * On a two-level page table, this ends up being trivial. Thus the - * inlining and the symmetry break with pte_alloc() that does all -@@ -552,9 +567,10 @@ - - extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - --extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, -- unsigned long len, unsigned long prot, -- unsigned long flag, unsigned long pgoff); -+extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flag, -+ unsigned long pgoff); - - static inline unsigned long do_mmap(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, -@@ -564,7 +580,8 @@ - if ((offset + PAGE_ALIGN(len)) < offset) - goto out; - if (!(offset & ~PAGE_MASK)) -- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag, -+ offset >> PAGE_SHIFT); - out: - return ret; - } -diff -Naur -X ../exclude-files orig/include/linux/proc_mm.h um/include/linux/proc_mm.h ---- orig/include/linux/proc_mm.h 1969-12-31 19:00:00.000000000 -0500 -+++ um/include/linux/proc_mm.h 2004-02-14 06:30:22.000000000 -0500 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROC_MM_H -+#define __PROC_MM_H -+ -+#include "linux/sched.h" -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+extern struct mm_struct *proc_mm_get_mm(int fd); -+ -+#endif -diff -Naur -X ../exclude-files orig/include/linux/shmem_fs.h um/include/linux/shmem_fs.h ---- orig/include/linux/shmem_fs.h 2003-09-02 15:44:03.000000000 -0400 -+++ um/include/linux/shmem_fs.h 2003-12-09 00:03:31.000000000 -0500 -@@ -22,6 +22,8 @@ - unsigned long next_index; - swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */ - void **i_indirect; /* indirect blocks */ -+ unsigned long map_direct[SHMEM_NR_DIRECT]; -+ void **map_indirect; - unsigned long swapped; /* data pages assigned to swap */ - unsigned long flags; - struct list_head list; -diff -Naur -X ../exclude-files orig/include/linux/tty.h um/include/linux/tty.h ---- orig/include/linux/tty.h 2004-01-11 22:46:12.000000000 -0500 -+++ um/include/linux/tty.h 2004-02-14 06:28:59.000000000 -0500 -@@ -309,6 +309,9 @@ - spinlock_t read_lock; - /* If the tty has a pending do_SAK, queue it here - akpm */ - struct tq_struct SAK_tq; -+#ifdef CONFIG_TTY_LOG -+ int log_fd; -+#endif - }; - - /* tty magic number */ -@@ -365,6 +368,7 @@ - extern int specialix_init(void); - extern int espserial_init(void); - extern int macserial_init(void); -+extern int stdio_init(void); - extern int a2232board_init(void); - - extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device, -@@ -420,5 +424,7 @@ - extern int vt_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg); - -+extern void stdio_console_init(void); -+ - #endif /* __KERNEL__ */ - #endif -diff -Naur -X ../exclude-files orig/init/do_mounts.c um/init/do_mounts.c ---- orig/init/do_mounts.c 2003-12-16 22:16:36.000000000 -0500 -+++ um/init/do_mounts.c 2003-12-16 22:17:32.000000000 -0500 -@@ -154,6 +154,22 @@ - { "pf", 0x2f00 }, - { "apblock", APBLOCK_MAJOR << 8}, - { "ddv", DDV_MAJOR << 8}, -+ { "ubd0", UBD_MAJOR << 8 | 0 << 4}, -+ { "ubda", UBD_MAJOR << 8 | 0 << 4}, -+ { "ubd1", UBD_MAJOR << 8 | 1 << 4}, -+ { "ubdb", UBD_MAJOR << 8 | 1 << 4}, -+ { "ubd2", UBD_MAJOR << 8 | 2 << 4}, -+ { "ubdc", UBD_MAJOR << 8 | 2 << 4}, -+ { "ubd3", UBD_MAJOR << 8 | 3 << 4}, -+ { "ubdd", UBD_MAJOR << 8 | 3 << 4}, -+ { "ubd4", UBD_MAJOR << 8 | 4 << 4}, -+ { "ubde", UBD_MAJOR << 8 | 4 << 4}, -+ { "ubd5", UBD_MAJOR << 8 | 5 << 4}, -+ { "ubdf", UBD_MAJOR << 8 | 5 << 4}, -+ { "ubd6", UBD_MAJOR << 8 | 6 << 4}, -+ { "ubdg", UBD_MAJOR << 8 | 6 << 4}, -+ { "ubd7", UBD_MAJOR << 8 | 7 << 4}, -+ { "ubdh", UBD_MAJOR << 8 | 7 << 4}, - { "jsfd", JSFD_MAJOR << 8}, - #if defined(CONFIG_ARCH_S390) - { "dasda", (DASD_MAJOR << MINORBITS) }, -diff -Naur -X ../exclude-files orig/kernel/panic.c um/kernel/panic.c ---- orig/kernel/panic.c 2003-12-16 22:16:36.000000000 -0500 -+++ um/kernel/panic.c 2003-12-16 22:17:32.000000000 -0500 -@@ -74,7 +74,7 @@ - smp_send_stop(); - #endif - -- notifier_call_chain(&panic_notifier_list, 0, NULL); -+ notifier_call_chain(&panic_notifier_list, 0, buf); - - if (panic_timeout > 0) - { -diff -Naur -X ../exclude-files orig/MAINTAINERS um/MAINTAINERS ---- orig/MAINTAINERS 2003-12-16 22:16:23.000000000 -0500 -+++ um/MAINTAINERS 2003-12-16 22:17:22.000000000 -0500 -@@ -2055,6 +2055,14 @@ - L: linux-usb-devel@lists.sourceforge.net - W: http://usb.in.tum.de - S: Maintained -+ -+USER-MODE PORT -+P: Jeff Dike -+M: jdike@karaya.com -+L: user-mode-linux-devel@lists.sourceforge.net -+L: user-mode-linux-user@lists.sourceforge.net -+W: http://user-mode-linux.sourceforge.net -+S: Maintained - - USB "USBNET" DRIVER - P: David Brownell -diff -Naur -X ../exclude-files orig/Makefile um/Makefile ---- orig/Makefile 2004-02-14 06:26:12.000000000 -0500 -+++ um/Makefile 2004-02-14 06:26:19.000000000 -0500 -@@ -5,7 +5,15 @@ - - KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) - --ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+# SUBARCH tells the usermode build what the underlying arch is. That is set -+# first, and if a usermode build is happening, the "ARCH=um" on the command -+# line overrides the setting of ARCH below. If a native build is happening, -+# then ARCH is assigned, getting whatever value it gets normally, and -+# SUBARCH is subsequently ignored. -+ -+SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+ARCH := $(SUBARCH) -+ - KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") - - CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ -diff -Naur -X ../exclude-files orig/mm/Makefile um/mm/Makefile ---- orig/mm/Makefile 2002-08-21 11:47:43.000000000 -0400 -+++ um/mm/Makefile 2003-10-21 03:26:08.000000000 -0400 -@@ -17,5 +17,6 @@ - shmem.o - - obj-$(CONFIG_HIGHMEM) += highmem.o -+obj-$(CONFIG_PROC_MM) += proc_mm.o - - include $(TOPDIR)/Rules.make -diff -Naur -X ../exclude-files orig/mm/mmap.c um/mm/mmap.c ---- orig/mm/mmap.c 2003-12-16 22:16:36.000000000 -0500 -+++ um/mm/mmap.c 2003-12-16 22:17:32.000000000 -0500 -@@ -390,10 +390,11 @@ - return 0; - } - --unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len, -- unsigned long prot, unsigned long flags, unsigned long pgoff) -+unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long pgoff) - { -- struct mm_struct * mm = current->mm; - struct vm_area_struct * vma, * prev; - unsigned int vm_flags; - int correct_wcount = 0; -@@ -994,6 +995,11 @@ - remove_shared_vm_struct(mpnt); - mm->map_count--; - -+ if((mpnt->vm_file != NULL) && (mpnt->vm_file->f_op != NULL) && -+ (mpnt->vm_file->f_op->munmap != NULL)) -+ mpnt->vm_file->f_op->munmap(mpnt->vm_file, mpnt, st, -+ size); -+ - zap_page_range(mm, st, size); - - /* -diff -Naur -X ../exclude-files orig/mm/mprotect.c um/mm/mprotect.c ---- orig/mm/mprotect.c 2003-12-16 22:16:36.000000000 -0500 -+++ um/mm/mprotect.c 2003-12-16 22:17:32.000000000 -0500 -@@ -264,7 +264,8 @@ - return 0; - } - --asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) -+long do_mprotect(struct mm_struct *mm, unsigned long start, size_t len, -+ unsigned long prot) - { - unsigned long nstart, end, tmp; - struct vm_area_struct * vma, * next, * prev; -@@ -281,9 +282,9 @@ - if (end == start) - return 0; - -- down_write(¤t->mm->mmap_sem); -+ down_write(&mm->mmap_sem); - -- vma = find_vma_prev(current->mm, start, &prev); -+ vma = find_vma_prev(mm, start, &prev); - error = -ENOMEM; - if (!vma || vma->vm_start > start) - goto out; -@@ -332,6 +333,11 @@ - prev->vm_mm->map_count--; - } - out: -- up_write(¤t->mm->mmap_sem); -+ up_write(&mm->mmap_sem); - return error; - } -+ -+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) -+{ -+ return(do_mprotect(current->mm, start, len, prot)); -+} -diff -Naur -X ../exclude-files orig/mm/page_alloc.c um/mm/page_alloc.c ---- orig/mm/page_alloc.c 2003-12-16 22:16:36.000000000 -0500 -+++ um/mm/page_alloc.c 2003-12-16 22:17:32.000000000 -0500 -@@ -89,6 +89,7 @@ - struct page *base; - zone_t *zone; - -+ arch_free_page(page, order); - /* - * Yes, think what happens when other parts of the kernel take - * a reference to a page in order to pin it for io. -ben -diff -Naur -X ../exclude-files orig/mm/proc_mm.c um/mm/proc_mm.c ---- orig/mm/proc_mm.c 1969-12-31 19:00:00.000000000 -0500 -+++ um/mm/proc_mm.c 2003-10-21 03:26:08.000000000 -0400 -@@ -0,0 +1,173 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/proc_fs.h" -+#include "linux/proc_mm.h" -+#include "linux/file.h" -+#include "asm/uaccess.h" -+#include "asm/mmu_context.h" -+ -+static struct file_operations proc_mm_fops; -+ -+struct mm_struct *proc_mm_get_mm(int fd) -+{ -+ struct mm_struct *ret = ERR_PTR(-EBADF); -+ struct file *file; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ ret = ERR_PTR(-EINVAL); -+ if(file->f_op != &proc_mm_fops) -+ goto out_fput; -+ -+ ret = file->private_data; -+ out_fput: -+ fput(file); -+ out: -+ return(ret); -+} -+ -+extern long do_mmap2(struct mm_struct *mm, unsigned long addr, -+ unsigned long len, unsigned long prot, -+ unsigned long flags, unsigned long fd, -+ unsigned long pgoff); -+ -+static ssize_t write_proc_mm(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct mm_struct *mm = file->private_data; -+ struct proc_mm_op req; -+ int n, ret; -+ -+ if(count > sizeof(req)) -+ return(-EINVAL); -+ -+ n = copy_from_user(&req, buffer, count); -+ if(n != 0) -+ return(-EFAULT); -+ -+ ret = count; -+ switch(req.op){ -+ case MM_MMAP: { -+ struct mm_mmap *map = &req.u.mmap; -+ -+ ret = do_mmap2(mm, map->addr, map->len, map->prot, -+ map->flags, map->fd, map->offset >> PAGE_SHIFT); -+ if((ret & ~PAGE_MASK) == 0) -+ ret = count; -+ -+ break; -+ } -+ case MM_MUNMAP: { -+ struct mm_munmap *unmap = &req.u.munmap; -+ -+ down_write(&mm->mmap_sem); -+ ret = do_munmap(mm, unmap->addr, unmap->len); -+ up_write(&mm->mmap_sem); -+ -+ if(ret == 0) -+ ret = count; -+ break; -+ } -+ case MM_MPROTECT: { -+ struct mm_mprotect *protect = &req.u.mprotect; -+ -+ ret = do_mprotect(mm, protect->addr, protect->len, -+ protect->prot); -+ if(ret == 0) -+ ret = count; -+ break; -+ } -+ -+ case MM_COPY_SEGMENTS: { -+ struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); -+ -+ if(IS_ERR(from)){ -+ ret = PTR_ERR(from); -+ break; -+ } -+ -+ mm_copy_segments(from, mm); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return(ret); -+} -+ -+static int open_proc_mm(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = mm_alloc(); -+ int ret; -+ -+ ret = -ENOMEM; -+ if(mm == NULL) -+ goto out_mem; -+ -+ ret = init_new_context(current, mm); -+ if(ret) -+ goto out_free; -+ -+ spin_lock(&mmlist_lock); -+ list_add(&mm->mmlist, ¤t->mm->mmlist); -+ mmlist_nr++; -+ spin_unlock(&mmlist_lock); -+ -+ file->private_data = mm; -+ -+ return(0); -+ -+ out_free: -+ mmput(mm); -+ out_mem: -+ return(ret); -+} -+ -+static int release_proc_mm(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = file->private_data; -+ -+ mmput(mm); -+ return(0); -+} -+ -+static struct file_operations proc_mm_fops = { -+ .open = open_proc_mm, -+ .release = release_proc_mm, -+ .write = write_proc_mm, -+}; -+ -+static int make_proc_mm(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ ent = create_proc_entry("mm", 0222, &proc_root); -+ if(ent == NULL){ -+ printk("make_proc_mm : Failed to register /proc/mm\n"); -+ return(0); -+ } -+ ent->proc_fops = &proc_mm_fops; -+ -+ return(0); -+} -+ -+__initcall(make_proc_mm); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -diff -Naur -X ../exclude-files orig/mm/shmem.c um/mm/shmem.c ---- orig/mm/shmem.c 2003-12-16 22:16:36.000000000 -0500 -+++ um/mm/shmem.c 2003-12-16 22:17:32.000000000 -0500 -@@ -128,16 +128,17 @@ - * +-> 48-51 - * +-> 52-55 - */ --static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, unsigned long *page) -+static void *shmem_block(unsigned long index, unsigned long *page, -+ unsigned long *direct, void ***indirect) - { - unsigned long offset; - void **dir; - - if (index < SHMEM_NR_DIRECT) -- return info->i_direct+index; -- if (!info->i_indirect) { -+ return direct+index; -+ if (!*indirect) { - if (page) { -- info->i_indirect = (void **) *page; -+ *indirect = (void **) *page; - *page = 0; - } - return NULL; /* need another page */ -@@ -146,7 +147,7 @@ - index -= SHMEM_NR_DIRECT; - offset = index % ENTRIES_PER_PAGE; - index /= ENTRIES_PER_PAGE; -- dir = info->i_indirect; -+ dir = *indirect; - - if (index >= ENTRIES_PER_PAGE/2) { - index -= ENTRIES_PER_PAGE/2; -@@ -169,7 +170,21 @@ - *dir = (void *) *page; - *page = 0; - } -- return (swp_entry_t *) *dir + offset; -+ return (unsigned long **) *dir + offset; -+} -+ -+static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, unsigned long *page) -+{ -+ return((swp_entry_t *) shmem_block(index, page, -+ (unsigned long *) info->i_direct, -+ &info->i_indirect)); -+} -+ -+static unsigned long *shmem_map_count(struct shmem_inode_info *info, -+ unsigned long index, unsigned long *page) -+{ -+ return((unsigned long *) shmem_block(index, page, info->map_direct, -+ &info->map_indirect)); - } - - /* -@@ -838,6 +853,7 @@ - ops = &shmem_vm_ops; - if (!S_ISREG(inode->i_mode)) - return -EACCES; -+ - UPDATE_ATIME(inode); - vma->vm_ops = ops; - return 0; -@@ -1723,4 +1739,125 @@ - return 0; - } - -+static int adjust_map_counts(struct shmem_inode_info *info, -+ unsigned long offset, unsigned long len, -+ int adjust) -+{ -+ unsigned long idx, i, *count, page = 0; -+ -+ spin_lock(&info->lock); -+ offset >>= PAGE_SHIFT; -+ len >>= PAGE_SHIFT; -+ for(i = 0; i < len; i++){ -+ idx = (i + offset) >> (PAGE_CACHE_SHIFT - PAGE_SHIFT); -+ -+ while((count = shmem_map_count(info, idx, &page)) == NULL){ -+ spin_unlock(&info->lock); -+ page = get_zeroed_page(GFP_KERNEL); -+ if(page == 0) -+ return(-ENOMEM); -+ spin_lock(&info->lock); -+ } -+ -+ if(page != 0) -+ free_page(page); -+ -+ *count += adjust; -+ } -+ spin_unlock(&info->lock); -+ return(0); -+} -+ - EXPORT_SYMBOL(shmem_file_setup); -+ -+struct file_operations anon_file_operations; -+ -+static int anon_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct file *new; -+ struct inode *inode; -+ loff_t size = vma->vm_end - vma->vm_start; -+ int err; -+ -+ if(file->private_data == NULL){ -+ new = shmem_file_setup("dev/anon", size); -+ if(IS_ERR(new)) -+ return(PTR_ERR(new)); -+ -+ new->f_op = &anon_file_operations; -+ file->private_data = new; -+ } -+ -+ if (vma->vm_file) -+ fput(vma->vm_file); -+ vma->vm_file = file->private_data; -+ get_file(vma->vm_file); -+ -+ inode = vma->vm_file->f_dentry->d_inode; -+ err = adjust_map_counts(SHMEM_I(inode), vma->vm_pgoff, size, 1); -+ if(err) -+ return(err); -+ -+ vma->vm_ops = &shmem_vm_ops; -+ return 0; -+} -+ -+static void anon_munmap(struct file *file, struct vm_area_struct *vma, -+ unsigned long start, unsigned long len) -+{ -+ struct inode *inode = file->f_dentry->d_inode; -+ struct shmem_inode_info *info = SHMEM_I(inode); -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ struct page *page; -+ unsigned long addr, idx, *count; -+ -+ for(addr = start; addr < start + len; addr += PAGE_SIZE){ -+ idx = (addr - vma->vm_start + vma->vm_pgoff); -+ idx >>= PAGE_CACHE_SHIFT; -+ -+ count = shmem_map_count(info, idx, NULL); -+ BUG_ON(count == NULL); -+ -+ (*count)--; -+ if(*count > 0) -+ continue; -+ -+ pgd = pgd_offset(vma->vm_mm, addr); -+ if(pgd_none(*pgd)) -+ continue; -+ -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_none(*pmd)) -+ continue; -+ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte)) /* XXX need to handle swapped pages */ -+ continue; -+ -+ *pte = pte_mkclean(*pte); -+ -+ page = pte_page(*pte); -+ LockPage(page); -+ lru_cache_del(page); -+ ClearPageDirty(page); -+ remove_inode_page(page); -+ UnlockPage(page); -+ -+ page_cache_release(page); -+ } -+} -+ -+int anon_release(struct inode *inode, struct file *file) -+{ -+ if(file->private_data != NULL) -+ fput(file->private_data); -+ return(0); -+} -+ -+struct file_operations anon_file_operations = { -+ .mmap = anon_mmap, -+ .munmap = anon_munmap, -+ .release = anon_release, -+}; diff --git a/lustre/kernel_patches/patches/uml-patch-2.4.29-1.patch b/lustre/kernel_patches/patches/uml-patch-2.4.29-1.patch deleted file mode 100644 index 16f449d..0000000 --- a/lustre/kernel_patches/patches/uml-patch-2.4.29-1.patch +++ /dev/null @@ -1,46719 +0,0 @@ -Index: linux-2.4.29/arch/um/config_block.in -=================================================================== ---- linux-2.4.29.orig/arch/um/config_block.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/config_block.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,22 @@ -+mainmenu_option next_comment -+comment 'Block Devices' -+ -+bool 'Virtual block device' CONFIG_BLK_DEV_UBD -+dep_bool ' Always do synchronous disk IO for UBD' CONFIG_BLK_DEV_UBD_SYNC $CONFIG_BLK_DEV_UBD -+bool 'COW device' CONFIG_COW -+ -+if [ "$CONFIG_BLK_DEV_UBD" = "y" -o "$CONFIG_COW" = "y" ] ; then -+ define_bool CONFIG_COW_COMMON y -+fi -+ -+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET -+tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -+if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then -+ int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 -+fi -+dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM -+ -+tristate 'Example IO memory driver' CONFIG_MMAPPER -+ -+endmenu -Index: linux-2.4.29/arch/um/config_char.in -=================================================================== ---- linux-2.4.29.orig/arch/um/config_char.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/config_char.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,37 @@ -+mainmenu_option next_comment -+comment 'Character Devices' -+ -+define_bool CONFIG_STDIO_CONSOLE y -+ -+bool 'Virtual serial line' CONFIG_SSL -+ -+bool 'file descriptor channel support' CONFIG_FD_CHAN -+bool 'null channel support' CONFIG_NULL_CHAN -+bool 'port channel support' CONFIG_PORT_CHAN -+bool 'pty channel support' CONFIG_PTY_CHAN -+bool 'tty channel support' CONFIG_TTY_CHAN -+bool 'xterm channel support' CONFIG_XTERM_CHAN -+string 'Default main console channel initialization' CONFIG_CON_ZERO_CHAN \ -+ "fd:0,fd:1" -+string 'Default console channel initialization' CONFIG_CON_CHAN "xterm" -+string 'Default serial line channel initialization' CONFIG_SSL_CHAN "pty" -+ -+ -+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS -+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then -+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 -+fi -+ -+bool 'Watchdog Timer Support' CONFIG_WATCHDOG -+dep_bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT \ -+ $CONFIG_WATCHDOG -+dep_tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG $CONFIG_WATCHDOG -+dep_tristate ' UML watchdog' CONFIG_UML_WATCHDOG $CONFIG_WATCHDOG -+ -+tristate 'Sound support' CONFIG_UML_SOUND -+define_tristate CONFIG_SOUND $CONFIG_UML_SOUND -+define_tristate CONFIG_HOSTAUDIO $CONFIG_UML_SOUND -+ -+bool 'Enable tty logging' CONFIG_TTY_LOG -+ -+endmenu -Index: linux-2.4.29/arch/um/config.in -=================================================================== ---- linux-2.4.29.orig/arch/um/config.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/config.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,123 @@ -+define_bool CONFIG_USERMODE y -+ -+mainmenu_name "Linux/Usermode Kernel Configuration" -+ -+define_bool CONFIG_ISA n -+define_bool CONFIG_SBUS n -+define_bool CONFIG_PCI n -+ -+define_bool CONFIG_UID16 y -+ -+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y -+ -+mainmenu_option next_comment -+comment 'Code maturity level options' -+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL -+endmenu -+ -+mainmenu_option next_comment -+comment 'General Setup' -+ -+bool 'Separate kernel address space support' CONFIG_MODE_SKAS -+ -+# This is to ensure that at least one of the modes is enabled. When neither -+# is present in defconfig, they default to N, which is bad. -+if [ "$CONFIG_MODE_SKAS" != "y" ]; then -+ define_bool CONFIG_MODE_TT y -+fi -+ -+bool 'Tracing thread support' CONFIG_MODE_TT -+if [ "$CONFIG_MODE_TT" != "y" ]; then -+ bool 'Statically linked binary when CONFIG_MODE_TT is disabled' CONFIG_STATIC_LINK -+fi -+bool 'Networking support' CONFIG_NET -+bool 'System V IPC' CONFIG_SYSVIPC -+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT -+bool 'Sysctl support' CONFIG_SYSCTL -+tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT -+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF -+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -+ -+tristate 'Host filesystem' CONFIG_HOSTFS -+tristate 'Usable host filesystem' CONFIG_HUMFS -+ -+if [ "$CONFIG_HOSTFS" = "y" -o "$CONFIG_HUMFS" = "y" ]; then -+ define_tristate CONFIG_EXTERNFS y -+fi -+ -+tristate 'Honeypot proc filesystem' CONFIG_HPPFS -+bool 'Management console' CONFIG_MCONSOLE -+dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_MCONSOLE -+bool '2G/2G host address space split' CONFIG_HOST_2G_2G -+ -+bool 'Symmetric multi-processing support' CONFIG_UML_SMP -+define_bool CONFIG_SMP $CONFIG_UML_SMP -+if [ "$CONFIG_SMP" = "y" ]; then -+ int 'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32 -+fi -+ -+int 'Nesting level' CONFIG_NEST_LEVEL 0 -+int 'Kernel address space size (in .5G units)' CONFIG_KERNEL_HALF_GIGS 1 -+bool 'Highmem support' CONFIG_HIGHMEM -+bool '/proc/mm' CONFIG_PROC_MM -+int 'Kernel stack size order' CONFIG_KERNEL_STACK_ORDER 2 -+bool 'Real-time Clock' CONFIG_UML_REAL_TIME_CLOCK -+endmenu -+ -+mainmenu_option next_comment -+comment 'Loadable module support' -+bool 'Enable loadable module support' CONFIG_MODULES -+if [ "$CONFIG_MODULES" = "y" ]; then -+# MODVERSIONS does not yet work in this architecture -+# bool ' Set version information on all module symbols' CONFIG_MODVERSIONS -+ bool ' Kernel module loader' CONFIG_KMOD -+fi -+endmenu -+ -+source arch/um/config_char.in -+ -+source arch/um/config_block.in -+ -+define_bool CONFIG_NETDEVICES $CONFIG_NET -+ -+if [ "$CONFIG_NET" = "y" ]; then -+ source arch/um/config_net.in -+ source net/Config.in -+fi -+ -+source fs/Config.in -+ -+mainmenu_option next_comment -+comment 'SCSI support' -+ -+tristate 'SCSI support' CONFIG_SCSI -+ -+if [ "$CONFIG_SCSI" != "n" ]; then -+ source arch/um/config_scsi.in -+fi -+endmenu -+ -+source drivers/md/Config.in -+ -+source drivers/mtd/Config.in -+ -+source lib/Config.in -+ -+source crypto/Config.in -+ -+mainmenu_option next_comment -+comment 'Kernel hacking' -+bool 'Debug memory allocations' CONFIG_DEBUG_SLAB -+bool 'Enable kernel debugging symbols' CONFIG_DEBUGSYM -+if [ "$CONFIG_XTERM_CHAN" = "y" ]; then -+ dep_bool 'Enable ptrace proxy' CONFIG_PT_PROXY $CONFIG_DEBUGSYM -+else -+ define_bool CONFIG_PT_PROXY n -+fi -+ -+if [ "$CONFIG_MODE_TT" = "n" ]; then -+ dep_bool 'Enable gprof support' CONFIG_GPROF $CONFIG_DEBUGSYM -+fi -+ -+dep_bool 'Enable gcov support' CONFIG_GCOV $CONFIG_DEBUGSYM -+endmenu -Index: linux-2.4.29/arch/um/config_net.in -=================================================================== ---- linux-2.4.29.orig/arch/um/config_net.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/config_net.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,48 @@ -+mainmenu_option next_comment -+comment 'Network Devices' -+ -+# UML virtual driver -+bool 'Virtual network device' CONFIG_UML_NET -+ -+dep_bool ' Ethertap transport' CONFIG_UML_NET_ETHERTAP $CONFIG_UML_NET -+dep_bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP $CONFIG_UML_NET -+dep_bool ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET -+dep_bool ' SLiRP transport' CONFIG_UML_NET_SLIRP $CONFIG_UML_NET -+dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $CONFIG_UML_NET -+dep_bool ' Multicast transport' CONFIG_UML_NET_MCAST $CONFIG_UML_NET -+dep_bool ' pcap transport' CONFIG_UML_NET_PCAP $CONFIG_UML_NET -+ -+# Below are hardware-independent drivers mirrored from -+# drivers/net/Config.in. It would be nice if Linux -+# had HW independent drivers separated from the other -+# but it does not. Until then each non-ISA/PCI arch -+# needs to provide it's own menu of network drivers -+ -+tristate 'Dummy net driver support' CONFIG_DUMMY -+tristate 'Bonding driver support' CONFIG_BONDING -+tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER -+tristate 'Universal TUN/TAP device driver support' CONFIG_TUN -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ if [ "$CONFIG_NETLINK" = "y" ]; then -+ tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP -+ fi -+fi -+ -+tristate 'PPP (point-to-point protocol) support' CONFIG_PPP -+if [ ! "$CONFIG_PPP" = "n" ]; then -+ dep_bool ' PPP multilink support (EXPERIMENTAL)' CONFIG_PPP_MULTILINK $CONFIG_EXPERIMENTAL -+ dep_bool ' PPP filtering' CONFIG_PPP_FILTER $CONFIG_FILTER -+ dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP -+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP -+ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP -+ dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP -+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL -+ dep_tristate ' PPP MPPE compression (encryption)' CONFIG_PPP_MPPE $CONFIG_PPP -+fi -+ -+tristate 'SLIP (serial line) support' CONFIG_SLIP -+dep_bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED $CONFIG_SLIP -+dep_bool ' Keepalive and linefill' CONFIG_SLIP_SMART $CONFIG_SLIP -+dep_bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 $CONFIG_SLIP -+ -+endmenu -Index: linux-2.4.29/arch/um/config.release -=================================================================== ---- linux-2.4.29.orig/arch/um/config.release 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/config.release 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,302 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_USERMODE=y -+# CONFIG_ISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_PCI is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+ -+# -+# General Setup -+# -+CONFIG_NET=y -+CONFIG_SYSVIPC=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_SYSCTL=y -+CONFIG_BINFMT_AOUT=y -+CONFIG_BINFMT_ELF=y -+CONFIG_BINFMT_MISC=y -+CONFIG_HOSTFS=y -+# CONFIG_HPPFS is not set -+CONFIG_MCONSOLE=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_HOST_2G_2G is not set -+# CONFIG_UML_SMP is not set -+# CONFIG_SMP is not set -+CONFIG_NEST_LEVEL=0 -+CONFIG_KERNEL_HALF_GIGS=1 -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+CONFIG_KMOD=y -+ -+# -+# Character Devices -+# -+CONFIG_STDIO_CONSOLE=y -+CONFIG_SSL=y -+CONFIG_FD_CHAN=y -+# CONFIG_NULL_CHAN is not set -+CONFIG_PORT_CHAN=y -+CONFIG_PTY_CHAN=y -+CONFIG_TTY_CHAN=y -+CONFIG_XTERM_CHAN=y -+CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -+CONFIG_CON_CHAN="xterm" -+CONFIG_SSL_CHAN="pty" -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=256 -+# CONFIG_WATCHDOG is not set -+CONFIG_UML_SOUND=y -+CONFIG_SOUND=y -+CONFIG_HOSTAUDIO=y -+# CONFIG_TTY_LOG is not set -+ -+# -+# Block Devices -+# -+CONFIG_BLK_DEV_UBD=y -+# CONFIG_BLK_DEV_UBD_SYNC is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_NBD=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_MMAPPER is not set -+CONFIG_NETDEVICES=y -+ -+# -+# Network Devices -+# -+CONFIG_UML_NET=y -+CONFIG_UML_NET_ETHERTAP=y -+CONFIG_UML_NET_TUNTAP=y -+CONFIG_UML_NET_SLIP=y -+CONFIG_UML_NET_DAEMON=y -+CONFIG_UML_NET_MCAST=y -+CONFIG_DUMMY=y -+CONFIG_BONDING=m -+CONFIG_EQUALIZER=m -+CONFIG_TUN=y -+CONFIG_PPP=m -+CONFIG_PPP_MULTILINK=y -+# CONFIG_PPP_ASYNC is not set -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPPOE=m -+CONFIG_SLIP=m -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+CONFIG_PACKET_MMAP=y -+# CONFIG_NETLINK_DEV is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_FILTER is not set -+CONFIG_UNIX=y -+CONFIG_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_PNP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+# CONFIG_ATM is not set -+# CONFIG_VLAN_8021Q is not set -+ -+# -+# -+# -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DECNET is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# File systems -+# -+CONFIG_QUOTA=y -+CONFIG_AUTOFS_FS=m -+CONFIG_AUTOFS4_FS=m -+CONFIG_REISERFS_FS=m -+# CONFIG_REISERFS_CHECK is not set -+# CONFIG_REISERFS_PROC_INFO is not set -+CONFIG_ADFS_FS=m -+# CONFIG_ADFS_FS_RW is not set -+CONFIG_AFFS_FS=m -+CONFIG_HFS_FS=m -+CONFIG_BFS_FS=m -+CONFIG_EXT3_FS=y -+CONFIG_JBD=y -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_UMSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_EFS_FS=m -+CONFIG_CRAMFS=m -+CONFIG_TMPFS=y -+CONFIG_RAMFS=y -+CONFIG_ISO9660_FS=y -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+CONFIG_MINIX_FS=m -+CONFIG_VXFS_FS=m -+# CONFIG_NTFS_FS is not set -+CONFIG_HPFS_FS=m -+CONFIG_PROC_FS=y -+CONFIG_DEVFS_FS=y -+CONFIG_DEVFS_MOUNT=y -+# CONFIG_DEVFS_DEBUG is not set -+CONFIG_DEVPTS_FS=y -+CONFIG_QNX4FS_FS=m -+# CONFIG_QNX4FS_RW is not set -+CONFIG_ROMFS_FS=m -+CONFIG_EXT2_FS=y -+CONFIG_SYSV_FS=m -+CONFIG_UDF_FS=m -+# CONFIG_UDF_RW is not set -+CONFIG_UFS_FS=m -+# CONFIG_UFS_FS_WRITE is not set -+ -+# -+# Network File Systems -+# -+# CONFIG_CODA_FS is not set -+# CONFIG_INTERMEZZO_FS is not set -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3=y -+CONFIG_NFSD=y -+CONFIG_NFSD_V3=y -+CONFIG_SUNRPC=y -+CONFIG_LOCKD=y -+CONFIG_LOCKD_V4=y -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_ZISOFS_FS is not set -+CONFIG_ZLIB_FS_INFLATE=m -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+# CONFIG_NLS_CODEPAGE_437 is not set -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ISO8859_1 is not set -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=y -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+# CONFIG_BLK_DEV_SD is not set -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+CONFIG_SCSI_DEBUG=m -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+# CONFIG_MTD is not set -+ -+# -+# Kernel hacking -+# -+# CONFIG_DEBUG_SLAB is not set -+# CONFIG_DEBUGSYM is not set -Index: linux-2.4.29/arch/um/config_scsi.in -=================================================================== ---- linux-2.4.29.orig/arch/um/config_scsi.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/config_scsi.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,30 @@ -+comment 'SCSI support type (disk, tape, CD-ROM)' -+ -+dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI -+ -+if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then -+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 -+fi -+ -+dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI -+ -+dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI -+ -+if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then -+ bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR -+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 -+fi -+dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI -+ -+comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' -+ -+#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ bool ' Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES -+#fi -+ -+bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN -+ -+bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS -+bool ' SCSI logging facility' CONFIG_SCSI_LOGGING -+ -+dep_tristate 'SCSI debugging host simulator (EXPERIMENTAL)' CONFIG_SCSI_DEBUG $CONFIG_SCSI -Index: linux-2.4.29/arch/um/defconfig -=================================================================== ---- linux-2.4.29.orig/arch/um/defconfig 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/defconfig 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,430 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_USERMODE=y -+# CONFIG_ISA is not set -+# CONFIG_SBUS is not set -+# CONFIG_PCI is not set -+CONFIG_UID16=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+ -+# -+# General Setup -+# -+CONFIG_MODE_SKAS=y -+CONFIG_MODE_TT=y -+CONFIG_NET=y -+CONFIG_SYSVIPC=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_SYSCTL=y -+CONFIG_BINFMT_AOUT=y -+CONFIG_BINFMT_ELF=y -+CONFIG_BINFMT_MISC=y -+CONFIG_HOSTFS=y -+CONFIG_HUMFS=y -+CONFIG_EXTERNFS=y -+CONFIG_HPPFS=y -+CONFIG_MCONSOLE=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_HOST_2G_2G is not set -+# CONFIG_UML_SMP is not set -+# CONFIG_SMP is not set -+CONFIG_NEST_LEVEL=0 -+CONFIG_KERNEL_HALF_GIGS=1 -+# CONFIG_HIGHMEM is not set -+CONFIG_PROC_MM=y -+CONFIG_KERNEL_STACK_ORDER=2 -+CONFIG_UML_REAL_TIME_CLOCK=y -+ -+# -+# Loadable module support -+# -+CONFIG_MODULES=y -+# CONFIG_KMOD is not set -+ -+# -+# Character Devices -+# -+CONFIG_STDIO_CONSOLE=y -+CONFIG_SSL=y -+CONFIG_FD_CHAN=y -+CONFIG_NULL_CHAN=y -+CONFIG_PORT_CHAN=y -+CONFIG_PTY_CHAN=y -+CONFIG_TTY_CHAN=y -+CONFIG_XTERM_CHAN=y -+CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -+CONFIG_CON_CHAN="xterm" -+CONFIG_SSL_CHAN="pty" -+CONFIG_UNIX98_PTYS=y -+CONFIG_UNIX98_PTY_COUNT=256 -+# CONFIG_WATCHDOG is not set -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+# CONFIG_SOFT_WATCHDOG is not set -+# CONFIG_UML_WATCHDOG is not set -+CONFIG_UML_SOUND=y -+CONFIG_SOUND=y -+CONFIG_HOSTAUDIO=y -+# CONFIG_TTY_LOG is not set -+ -+# -+# Block Devices -+# -+CONFIG_BLK_DEV_UBD=y -+# CONFIG_BLK_DEV_UBD_SYNC is not set -+# CONFIG_COW is not set -+CONFIG_COW_COMMON=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_NBD=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=4096 -+CONFIG_BLK_DEV_INITRD=y -+# CONFIG_MMAPPER is not set -+CONFIG_NETDEVICES=y -+ -+# -+# Network Devices -+# -+CONFIG_UML_NET=y -+CONFIG_UML_NET_ETHERTAP=y -+CONFIG_UML_NET_TUNTAP=y -+CONFIG_UML_NET_SLIP=y -+CONFIG_UML_NET_SLIRP=y -+CONFIG_UML_NET_DAEMON=y -+CONFIG_UML_NET_MCAST=y -+# CONFIG_UML_NET_PCAP is not set -+CONFIG_DUMMY=y -+# CONFIG_BONDING is not set -+# CONFIG_EQUALIZER is not set -+CONFIG_TUN=y -+CONFIG_PPP=y -+# CONFIG_PPP_MULTILINK is not set -+# CONFIG_PPP_FILTER is not set -+# CONFIG_PPP_ASYNC is not set -+# CONFIG_PPP_SYNC_TTY is not set -+# CONFIG_PPP_DEFLATE is not set -+# CONFIG_PPP_BSDCOMP is not set -+# CONFIG_PPPOE is not set -+# CONFIG_PPP_MPPE is not set -+CONFIG_SLIP=y -+# CONFIG_SLIP_COMPRESSED is not set -+# CONFIG_SLIP_SMART is not set -+# CONFIG_SLIP_MODE_SLIP6 is not set -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+CONFIG_PACKET_MMAP=y -+# CONFIG_NETLINK_DEV is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_FILTER is not set -+CONFIG_UNIX=y -+CONFIG_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+# CONFIG_IP_PNP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+# CONFIG_INET_ECN is not set -+# CONFIG_SYN_COOKIES is not set -+# CONFIG_IPV6 is not set -+# CONFIG_KHTTPD is not set -+ -+# -+# SCTP Configuration (EXPERIMENTAL) -+# -+CONFIG_IPV6_SCTP__=y -+# CONFIG_IP_SCTP is not set -+# CONFIG_ATM is not set -+# CONFIG_VLAN_8021Q is not set -+ -+# -+# -+# -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+ -+# -+# Appletalk devices -+# -+# CONFIG_DEV_APPLETALK is not set -+# CONFIG_DECNET is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_LLC is not set -+# CONFIG_NET_DIVERT is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_FASTROUTE is not set -+# CONFIG_NET_HW_FLOWCONTROL is not set -+ -+# -+# QoS and/or fair queueing -+# -+# CONFIG_NET_SCHED is not set -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+ -+# -+# File systems -+# -+CONFIG_QUOTA=y -+# CONFIG_QFMT_V2 is not set -+CONFIG_AUTOFS_FS=y -+CONFIG_AUTOFS4_FS=y -+CONFIG_REISERFS_FS=y -+# CONFIG_REISERFS_CHECK is not set -+# CONFIG_REISERFS_PROC_INFO is not set -+# CONFIG_ADFS_FS is not set -+# CONFIG_ADFS_FS_RW is not set -+# CONFIG_AFFS_FS is not set -+# CONFIG_HFS_FS is not set -+# CONFIG_HFSPLUS_FS is not set -+# CONFIG_BEFS_FS is not set -+# CONFIG_BEFS_DEBUG is not set -+# CONFIG_BFS_FS is not set -+CONFIG_EXT3_FS=y -+CONFIG_JBD=y -+# CONFIG_JBD_DEBUG is not set -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_UMSDOS_FS=y -+CONFIG_VFAT_FS=y -+# CONFIG_EFS_FS is not set -+CONFIG_JFFS_FS=y -+CONFIG_JFFS_FS_VERBOSE=0 -+CONFIG_JFFS_PROC_FS=y -+CONFIG_JFFS2_FS=y -+CONFIG_JFFS2_FS_DEBUG=0 -+# CONFIG_CRAMFS is not set -+CONFIG_TMPFS=y -+CONFIG_RAMFS=y -+CONFIG_ISO9660_FS=y -+# CONFIG_JOLIET is not set -+# CONFIG_ZISOFS is not set -+# CONFIG_JFS_FS is not set -+# CONFIG_JFS_DEBUG is not set -+# CONFIG_JFS_STATISTICS is not set -+CONFIG_MINIX_FS=y -+# CONFIG_VXFS_FS is not set -+# CONFIG_NTFS_FS is not set -+# CONFIG_NTFS_RW is not set -+# CONFIG_HPFS_FS is not set -+CONFIG_PROC_FS=y -+CONFIG_DEVFS_FS=y -+CONFIG_DEVFS_MOUNT=y -+# CONFIG_DEVFS_DEBUG is not set -+CONFIG_DEVPTS_FS=y -+# CONFIG_QNX4FS_FS is not set -+# CONFIG_QNX4FS_RW is not set -+# CONFIG_ROMFS_FS is not set -+CONFIG_EXT2_FS=y -+# CONFIG_SYSV_FS is not set -+# CONFIG_UDF_FS is not set -+# CONFIG_UDF_RW is not set -+# CONFIG_UFS_FS is not set -+# CONFIG_UFS_FS_WRITE is not set -+# CONFIG_XFS_FS is not set -+# CONFIG_XFS_QUOTA is not set -+# CONFIG_XFS_RT is not set -+# CONFIG_XFS_TRACE is not set -+# CONFIG_XFS_DEBUG is not set -+ -+# -+# Network File Systems -+# -+# CONFIG_CODA_FS is not set -+# CONFIG_INTERMEZZO_FS is not set -+# CONFIG_NFS_FS is not set -+# CONFIG_NFS_V3 is not set -+# CONFIG_NFS_DIRECTIO is not set -+# CONFIG_ROOT_NFS is not set -+# CONFIG_NFSD is not set -+# CONFIG_NFSD_V3 is not set -+# CONFIG_NFSD_TCP is not set -+# CONFIG_SUNRPC is not set -+# CONFIG_LOCKD is not set -+# CONFIG_SMB_FS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_NCPFS_PACKET_SIGNING is not set -+# CONFIG_NCPFS_IOCTL_LOCKING is not set -+# CONFIG_NCPFS_STRONG is not set -+# CONFIG_NCPFS_NFS_NS is not set -+# CONFIG_NCPFS_OS2_NS is not set -+# CONFIG_NCPFS_SMALLDOS is not set -+# CONFIG_NCPFS_NLS is not set -+# CONFIG_NCPFS_EXTRAS is not set -+# CONFIG_ZISOFS_FS is not set -+ -+# -+# Partition Types -+# -+# CONFIG_PARTITION_ADVANCED is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_SMB_NLS is not set -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_DEFAULT="iso8859-1" -+# CONFIG_NLS_CODEPAGE_437 is not set -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ISO8859_1 is not set -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+ -+# -+# SCSI support -+# -+CONFIG_SCSI=y -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+# CONFIG_BLK_DEV_SD is not set -+# CONFIG_CHR_DEV_ST is not set -+# CONFIG_BLK_DEV_SR is not set -+# CONFIG_CHR_DEV_SG is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_DEBUG_QUEUES is not set -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+CONFIG_SCSI_DEBUG=y -+ -+# -+# Multi-device support (RAID and LVM) -+# -+# CONFIG_MD is not set -+# CONFIG_BLK_DEV_MD is not set -+# CONFIG_MD_LINEAR is not set -+# CONFIG_MD_RAID0 is not set -+# CONFIG_MD_RAID1 is not set -+# CONFIG_MD_RAID5 is not set -+# CONFIG_MD_MULTIPATH is not set -+# CONFIG_BLK_DEV_LVM is not set -+ -+# -+# Memory Technology Devices (MTD) -+# -+CONFIG_MTD=y -+# CONFIG_MTD_DEBUG is not set -+# CONFIG_MTD_PARTITIONS is not set -+# CONFIG_MTD_CONCAT is not set -+# CONFIG_MTD_REDBOOT_PARTS is not set -+# CONFIG_MTD_CMDLINE_PARTS is not set -+ -+# -+# User Modules And Translation Layers -+# -+CONFIG_MTD_CHAR=y -+CONFIG_MTD_BLOCK=y -+# CONFIG_FTL is not set -+# CONFIG_NFTL is not set -+ -+# -+# RAM/ROM/Flash chip drivers -+# -+# CONFIG_MTD_CFI is not set -+# CONFIG_MTD_JEDECPROBE is not set -+# CONFIG_MTD_GEN_PROBE is not set -+# CONFIG_MTD_CFI_INTELEXT is not set -+# CONFIG_MTD_CFI_AMDSTD is not set -+# CONFIG_MTD_CFI_STAA is not set -+# CONFIG_MTD_RAM is not set -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_ABSENT is not set -+# CONFIG_MTD_OBSOLETE_CHIPS is not set -+# CONFIG_MTD_AMDSTD is not set -+# CONFIG_MTD_SHARP is not set -+# CONFIG_MTD_JEDEC is not set -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_PHYSMAP is not set -+# CONFIG_MTD_PCI is not set -+# CONFIG_MTD_PCMCIA is not set -+ -+# -+# Self-contained MTD device drivers -+# -+# CONFIG_MTD_PMC551 is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_MTDRAM is not set -+CONFIG_MTD_BLKMTD=y -+ -+# -+# Disk-On-Chip Device Drivers -+# -+# CONFIG_MTD_DOC1000 is not set -+# CONFIG_MTD_DOC2000 is not set -+# CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOCPROBE is not set -+ -+# -+# NAND Flash Device Drivers -+# -+# CONFIG_MTD_NAND is not set -+ -+# -+# Library routines -+# -+# CONFIG_CRC32 is not set -+CONFIG_ZLIB_INFLATE=y -+CONFIG_ZLIB_DEFLATE=y -+ -+# -+# Kernel hacking -+# -+# CONFIG_DEBUG_SLAB is not set -+CONFIG_DEBUGSYM=y -+CONFIG_PT_PROXY=y -+# CONFIG_GCOV is not set -Index: linux-2.4.29/arch/um/drivers/chan_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/chan_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/chan_kern.c 2005-05-03 22:28:14.196452024 +0300 -@@ -0,0 +1,568 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/stddef.h> -+#include <linux/kernel.h> -+#include <linux/list.h> -+#include <linux/slab.h> -+#include <linux/tty.h> -+#include <linux/string.h> -+#include <linux/tty_flip.h> -+#include <asm/irq.h> -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "sigio.h" -+#include "line.h" -+#include "os.h" -+ -+static void *not_configged_init(char *str, int device, struct chan_opts *opts) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(NULL); -+} -+ -+static int not_configged_open(int input, int output, int primary, void *data, -+ char **dev_out) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-ENODEV); -+} -+ -+static void not_configged_close(int fd, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+} -+ -+static int not_configged_read(int fd, char *c_out, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_write(int fd, const char *buf, int len, void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_console_write(int fd, const char *buf, int len, -+ void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-EIO); -+} -+ -+static int not_configged_window_size(int fd, void *data, unsigned short *rows, -+ unsigned short *cols) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+ return(-ENODEV); -+} -+ -+static void not_configged_free(void *data) -+{ -+ printk(KERN_ERR "Using a channel type which is configured out of " -+ "UML\n"); -+} -+ -+static struct chan_ops not_configged_ops = { -+ .init = not_configged_init, -+ .open = not_configged_open, -+ .close = not_configged_close, -+ .read = not_configged_read, -+ .write = not_configged_write, -+ .console_write = not_configged_console_write, -+ .window_size = not_configged_window_size, -+ .free = not_configged_free, -+ .winch = 0, -+}; -+ -+void generic_close(int fd, void *unused) -+{ -+ os_close_file(fd); -+} -+ -+int generic_read(int fd, char *c_out, void *unused) -+{ -+ int n; -+ -+ n = os_read_file(fd, c_out, sizeof(*c_out)); -+ -+ if(n == -EAGAIN) -+ return(0); -+ else if(n == 0) -+ return(-EIO); -+ return(n); -+} -+ -+/* XXX Trivial wrapper around os_write_file */ -+ -+int generic_write(int fd, const char *buf, int n, void *unused) -+{ -+ return(os_write_file(fd, buf, n)); -+} -+ -+int generic_window_size(int fd, void *unused, unsigned short *rows_out, -+ unsigned short *cols_out) -+{ -+ int rows, cols; -+ int ret; -+ -+ ret = os_window_size(fd, &rows, &cols); -+ if(ret < 0) -+ return(ret); -+ -+ ret = ((*rows_out != rows) || (*cols_out != cols)); -+ -+ *rows_out = rows; -+ *cols_out = cols; -+ -+ return(ret); -+} -+ -+void generic_free(void *data) -+{ -+ kfree(data); -+} -+ -+static void tty_receive_char(struct tty_struct *tty, char ch) -+{ -+ if(tty == NULL) return; -+ -+ if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { -+ if(ch == STOP_CHAR(tty)){ -+ stop_tty(tty); -+ return; -+ } -+ else if(ch == START_CHAR(tty)){ -+ start_tty(tty); -+ return; -+ } -+ } -+ -+ if((tty->flip.flag_buf_ptr == NULL) || -+ (tty->flip.char_buf_ptr == NULL)) -+ return; -+ tty_insert_flip_char(tty, ch, TTY_NORMAL); -+} -+ -+static int open_one_chan(struct chan *chan, int input, int output, int primary) -+{ -+ int fd; -+ -+ if(chan->opened) return(0); -+ if(chan->ops->open == NULL) fd = 0; -+ else fd = (*chan->ops->open)(input, output, primary, chan->data, -+ &chan->dev); -+ if(fd < 0) return(fd); -+ chan->fd = fd; -+ -+ chan->opened = 1; -+ return(0); -+} -+ -+int open_chan(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int ret, err = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ ret = open_one_chan(chan, chan->input, chan->output, -+ chan->primary); -+ if(chan->primary) err = ret; -+ } -+ return(err); -+} -+ -+void chan_enable_winch(struct list_head *chans, void *line) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary && chan->output && chan->ops->winch){ -+ register_winch(chan->fd, line); -+ return; -+ } -+ } -+} -+ -+void enable_chan(struct list_head *chans, void *data) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->opened) continue; -+ -+ line_setup_irq(chan->fd, chan->input, chan->output, data); -+ } -+} -+ -+void close_chan(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ /* Close in reverse order as open in case more than one of them -+ * refers to the same device and they save and restore that device's -+ * state. Then, the first one opened will have the original state, -+ * so it must be the last closed. -+ */ -+ for(ele = chans->prev; ele != chans; ele = ele->prev){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->opened) continue; -+ if(chan->ops->close != NULL) -+ (*chan->ops->close)(chan->fd, chan->data); -+ chan->opened = 0; -+ chan->fd = -1; -+ } -+} -+ -+int write_chan(struct list_head *chans, const char *buf, int len, -+ int write_irq) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int n, ret = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->output || (chan->ops->write == NULL)) continue; -+ n = chan->ops->write(chan->fd, buf, len, chan->data); -+ if(chan->primary){ -+ ret = n; -+ if((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){ -+ reactivate_fd(chan->fd, write_irq); -+ if(ret == -EAGAIN) ret = 0; -+ } -+ } -+ } -+ return(ret); -+} -+ -+int console_write_chan(struct list_head *chans, const char *buf, int len) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ int n, ret = 0; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->output || (chan->ops->console_write == NULL)) -+ continue; -+ n = chan->ops->console_write(chan->fd, buf, len, chan->data); -+ if(chan->primary) ret = n; -+ } -+ return(ret); -+} -+ -+int chan_window_size(struct list_head *chans, unsigned short *rows_out, -+ unsigned short *cols_out) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary){ -+ if(chan->ops->window_size == NULL) return(0); -+ return(chan->ops->window_size(chan->fd, chan->data, -+ rows_out, cols_out)); -+ } -+ } -+ return(0); -+} -+ -+void free_one_chan(struct chan *chan) -+{ -+ list_del(&chan->list); -+ if(chan->ops->free != NULL) -+ (*chan->ops->free)(chan->data); -+ free_irq_by_fd(chan->fd); -+ if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); -+ kfree(chan); -+} -+ -+void free_chan(struct list_head *chans) -+{ -+ struct list_head *ele, *next; -+ struct chan *chan; -+ -+ list_for_each_safe(ele, next, chans){ -+ chan = list_entry(ele, struct chan, list); -+ free_one_chan(chan); -+ } -+} -+ -+static int one_chan_config_string(struct chan *chan, char *str, int size, -+ char **error_out) -+{ -+ int n = 0; -+ -+ if(chan == NULL){ -+ CONFIG_CHUNK(str, size, n, "none", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, chan->ops->type, 0); -+ -+ if(chan->dev == NULL){ -+ CONFIG_CHUNK(str, size, n, "", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, ":", 0); -+ CONFIG_CHUNK(str, size, n, chan->dev, 0); -+ -+ return(n); -+} -+ -+static int chan_pair_config_string(struct chan *in, struct chan *out, -+ char *str, int size, char **error_out) -+{ -+ int n; -+ -+ n = one_chan_config_string(in, str, size, error_out); -+ str += n; -+ size -= n; -+ -+ if(in == out){ -+ CONFIG_CHUNK(str, size, n, "", 1); -+ return(n); -+ } -+ -+ CONFIG_CHUNK(str, size, n, ",", 1); -+ n = one_chan_config_string(out, str, size, error_out); -+ str += n; -+ size -= n; -+ CONFIG_CHUNK(str, size, n, "", 1); -+ -+ return(n); -+} -+ -+int chan_config_string(struct list_head *chans, char *str, int size, -+ char **error_out) -+{ -+ struct list_head *ele; -+ struct chan *chan, *in = NULL, *out = NULL; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->primary) -+ continue; -+ if(chan->input) -+ in = chan; -+ if(chan->output) -+ out = chan; -+ } -+ -+ return(chan_pair_config_string(in, out, str, size, error_out)); -+} -+ -+struct chan_type { -+ char *key; -+ struct chan_ops *ops; -+}; -+ -+struct chan_type chan_table[] = { -+#ifdef CONFIG_FD_CHAN -+ { "fd", &fd_ops }, -+#else -+ { "fd", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_NULL_CHAN -+ { "null", &null_ops }, -+#else -+ { "null", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_PORT_CHAN -+ { "port", &port_ops }, -+#else -+ { "port", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_PTY_CHAN -+ { "pty", &pty_ops }, -+ { "pts", &pts_ops }, -+#else -+ { "pty", ¬_configged_ops }, -+ { "pts", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_TTY_CHAN -+ { "tty", &tty_ops }, -+#else -+ { "tty", ¬_configged_ops }, -+#endif -+ -+#ifdef CONFIG_XTERM_CHAN -+ { "xterm", &xterm_ops }, -+#else -+ { "xterm", ¬_configged_ops }, -+#endif -+}; -+ -+static struct chan *parse_chan(char *str, int pri, int device, -+ struct chan_opts *opts) -+{ -+ struct chan_type *entry; -+ struct chan_ops *ops; -+ struct chan *chan; -+ void *data; -+ int i; -+ -+ ops = NULL; -+ data = NULL; -+ for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){ -+ entry = &chan_table[i]; -+ if(!strncmp(str, entry->key, strlen(entry->key))){ -+ ops = entry->ops; -+ str += strlen(entry->key); -+ break; -+ } -+ } -+ if(ops == NULL){ -+ printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n", -+ str); -+ return(NULL); -+ } -+ if(ops->init == NULL) return(NULL); -+ data = (*ops->init)(str, device, opts); -+ if(data == NULL) return(NULL); -+ -+ chan = kmalloc(sizeof(*chan), GFP_KERNEL); -+ if(chan == NULL) return(NULL); -+ *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), -+ .primary = 1, -+ .input = 0, -+ .output = 0, -+ .opened = 0, -+ .fd = -1, -+ .pri = pri, -+ .ops = ops, -+ .data = data }); -+ return(chan); -+} -+ -+int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, -+ struct chan_opts *opts) -+{ -+ struct chan *new, *chan; -+ char *in, *out; -+ -+ if(!list_empty(chans)){ -+ chan = list_entry(chans->next, struct chan, list); -+ if(chan->pri >= pri) return(0); -+ free_chan(chans); -+ INIT_LIST_HEAD(chans); -+ } -+ -+ out = strchr(str, ','); -+ if(out != NULL){ -+ in = str; -+ *out = '\0'; -+ out++; -+ new = parse_chan(in, pri, device, opts); -+ if(new == NULL) return(-1); -+ new->input = 1; -+ list_add(&new->list, chans); -+ -+ new = parse_chan(out, pri, device, opts); -+ if(new == NULL) return(-1); -+ list_add(&new->list, chans); -+ new->output = 1; -+ } -+ else { -+ new = parse_chan(str, pri, device, opts); -+ if(new == NULL) return(-1); -+ list_add(&new->list, chans); -+ new->input = 1; -+ new->output = 1; -+ } -+ return(0); -+} -+ -+int chan_out_fd(struct list_head *chans) -+{ -+ struct list_head *ele; -+ struct chan *chan; -+ -+ list_for_each(ele, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(chan->primary && chan->output) -+ return(chan->fd); -+ } -+ return(-1); -+} -+ -+void chan_interrupt(struct list_head *chans, struct tq_struct *task, -+ struct tty_struct *tty, int irq, void *dev) -+{ -+ struct list_head *ele, *next; -+ struct chan *chan; -+ int err; -+ char c; -+ -+ list_for_each_safe(ele, next, chans){ -+ chan = list_entry(ele, struct chan, list); -+ if(!chan->input || (chan->ops->read == NULL)) continue; -+ do { -+ if((tty != NULL) && -+ (tty->flip.count >= TTY_FLIPBUF_SIZE)){ -+ queue_task(task, &tq_timer); -+ goto out; -+ } -+ err = chan->ops->read(chan->fd, &c, chan->data); -+ if(err > 0) -+ tty_receive_char(tty, c); -+ } while(err > 0); -+ -+ if(err == 0) reactivate_fd(chan->fd, irq); -+ if(err == -EIO){ -+ if(chan->primary){ -+ if(tty != NULL) -+ tty_hangup(tty); -+ line_disable(dev, irq); -+ close_chan(chans); -+ free_chan(chans); -+ return; -+ } -+ else { -+ if(chan->ops->close != NULL) -+ chan->ops->close(chan->fd, chan->data); -+ free_one_chan(chan); -+ } -+ } -+ } -+ out: -+ if(tty) tty_flip_buffer_push(tty); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/chan_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/chan_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/chan_user.c 2005-05-03 22:28:14.197451872 +0300 -@@ -0,0 +1,172 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdlib.h> -+#include <errno.h> -+#include <termios.h> -+#include <string.h> -+#include <signal.h> -+#include <sys/stat.h> -+#include <sys/ioctl.h> -+#include <sys/socket.h> -+#include "kern_util.h" -+#include "user_util.h" -+#include "chan_user.h" -+#include "user.h" -+#include "helper.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+static void winch_handler(int sig) -+{ -+} -+ -+struct winch_data { -+ int pty_fd; -+ int pipe_fd; -+ int close_me; -+}; -+ -+/* XXX This breaks horribly (by hanging UML) when moved to chan_kern.c - -+ * needs investigation -+ */ -+int generic_console_write(int fd, const char *buf, int n, void *unused) -+{ -+ struct termios save, new; -+ int err; -+ -+ if(isatty(fd)){ -+ tcgetattr(fd, &save); -+ new = save; -+ new.c_oflag |= OPOST; -+ tcsetattr(fd, TCSAFLUSH, &new); -+ } -+ err = generic_write(fd, buf, n, NULL); -+ if(isatty(fd)) tcsetattr(fd, TCSAFLUSH, &save); -+ return(err); -+} -+ -+static int winch_thread(void *arg) -+{ -+ struct winch_data *data = arg; -+ sigset_t sigs; -+ int pty_fd, pipe_fd; -+ int count, err; -+ char c = 1; -+ -+ os_close_file(data->close_me); -+ pty_fd = data->pty_fd; -+ pipe_fd = data->pipe_fd; -+ count = os_write_file(pipe_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("winch_thread : failed to write synchronization " -+ "byte, err = %d\n", -count); -+ -+ signal(SIGWINCH, winch_handler); -+ sigfillset(&sigs); -+ sigdelset(&sigs, SIGWINCH); -+ if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){ -+ printk("winch_thread : sigprocmask failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ if(setsid() < 0){ -+ printk("winch_thread : setsid failed, errno = %d\n", errno); -+ exit(1); -+ } -+ -+ err = os_new_tty_pgrp(pty_fd, os_getpid()); -+ if(err < 0){ -+ printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err); -+ exit(1); -+ } -+ -+ count = os_read_file(pipe_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("winch_thread : failed to read synchronization byte, " -+ "err = %d\n", -count); -+ -+ while(1){ -+ pause(); -+ -+ count = os_write_file(pipe_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("winch_thread : write failed, err = %d\n", -+ -count); -+ } -+} -+ -+static int winch_tramp(int fd, void *device_data, int *fd_out) -+{ -+ struct winch_data data; -+ unsigned long stack; -+ int fds[2], pid, n, err; -+ char c; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err < 0){ -+ printk("winch_tramp : os_pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ -+ data = ((struct winch_data) { .pty_fd = fd, -+ .pipe_fd = fds[1], -+ .close_me = fds[0] } ); -+ pid = run_helper_thread(winch_thread, &data, 0, &stack, 0); -+ if(pid < 0){ -+ printk("fork of winch_thread failed - errno = %d\n", errno); -+ return(pid); -+ } -+ -+ os_close_file(fds[1]); -+ *fd_out = fds[0]; -+ n = os_read_file(fds[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("winch_tramp : failed to read synchronization byte\n"); -+ printk("read failed, err = %d\n", -n); -+ printk("fd %d will not support SIGWINCH\n", fd); -+ *fd_out = -1; -+ } -+ return(pid); -+} -+ -+void register_winch(int fd, void *device_data) -+{ -+ int pid, thread, thread_fd; -+ int count; -+ char c = 1; -+ -+ if(!isatty(fd)) -+ return; -+ -+ pid = tcgetpgrp(fd); -+ if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, -+ device_data) && (pid == -1)){ -+ thread = winch_tramp(fd, device_data, &thread_fd); -+ if(fd != -1){ -+ register_winch_irq(thread_fd, fd, thread, device_data); -+ -+ count = os_write_file(thread_fd, &c, sizeof(c)); -+ if(count != sizeof(c)) -+ printk("register_winch : failed to write " -+ "synchronization byte, err = %d\n", -+ -count); -+ } -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/cow.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/cow.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/cow.h 2005-05-03 22:43:32.718815400 +0300 -@@ -0,0 +1,41 @@ -+#ifndef __COW_H__ -+#define __COW_H__ -+ -+#include <asm/types.h> -+ -+#if __BYTE_ORDER == __BIG_ENDIAN -+# define ntohll(x) (x) -+# define htonll(x) (x) -+#elif __BYTE_ORDER == __LITTLE_ENDIAN -+# define ntohll(x) bswap_64(x) -+# define htonll(x) bswap_64(x) -+#else -+#error "__BYTE_ORDER not defined" -+#endif -+ -+extern int init_cow_file(int fd, char *cow_file, char *backing_file, -+ int sectorsize, int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out); -+ -+extern int file_reader(__u64 offset, char *buf, int len, void *arg); -+extern int read_cow_header(int (*reader)(__u64, char *, int, void *), -+ void *arg, __u32 *version_out, -+ char **backing_file_out, time_t *mtime_out, -+ __u64 *size_out, int *sectorsize_out, -+ __u32 *align_out, int *bitmap_offset_out); -+ -+extern int write_cow_header(char *cow_file, int fd, char *backing_file, -+ int sectorsize, int alignment, long long *size); -+ -+extern void cow_sizes(int version, __u64 size, int sectorsize, int align, -+ int bitmap_offset, unsigned long *bitmap_len_out, -+ int *data_offset_out); -+ -+#endif -+ -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/cow_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/cow_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/cow_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,630 @@ -+#define COW_MAJOR 60 -+#define MAJOR_NR COW_MAJOR -+ -+#include <linux/stddef.h> -+#include <linux/kernel.h> -+#include <linux/ctype.h> -+#include <linux/stat.h> -+#include <linux/vmalloc.h> -+#include <linux/blkdev.h> -+#include <linux/blk.h> -+#include <linux/fs.h> -+#include <linux/genhd.h> -+#include <linux/devfs_fs.h> -+#include <asm/uaccess.h> -+#include "2_5compat.h" -+#include "cow.h" -+#include "ubd_user.h" -+ -+#define COW_SHIFT 4 -+ -+struct cow { -+ int count; -+ char *cow_path; -+ dev_t cow_dev; -+ struct block_device *cow_bdev; -+ char *backing_path; -+ dev_t backing_dev; -+ struct block_device *backing_bdev; -+ int sectorsize; -+ unsigned long *bitmap; -+ unsigned long bitmap_len; -+ int bitmap_offset; -+ int data_offset; -+ devfs_handle_t devfs; -+ struct semaphore sem; -+ struct semaphore io_sem; -+ atomic_t working; -+ spinlock_t io_lock; -+ struct buffer_head *bh; -+ struct buffer_head *bhtail; -+ void *end_io; -+}; -+ -+#define DEFAULT_COW { \ -+ .count = 0, \ -+ .cow_path = NULL, \ -+ .cow_dev = 0, \ -+ .backing_path = NULL, \ -+ .backing_dev = 0, \ -+ .bitmap = NULL, \ -+ .bitmap_len = 0, \ -+ .bitmap_offset = 0, \ -+ .data_offset = 0, \ -+ .devfs = NULL, \ -+ .working = ATOMIC_INIT(0), \ -+ .io_lock = SPIN_LOCK_UNLOCKED, \ -+} -+ -+#define MAX_DEV (8) -+#define MAX_MINOR (MAX_DEV << COW_SHIFT) -+ -+struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW }; -+ -+/* Not modified by this driver */ -+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE }; -+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 }; -+ -+/* Protected by cow_lock */ -+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 }; -+ -+static struct hd_struct cow_part[MAX_MINOR] = -+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } }; -+ -+/* Protected by io_request_lock */ -+static request_queue_t *cow_queue; -+ -+static int cow_open(struct inode *inode, struct file *filp); -+static int cow_release(struct inode * inode, struct file * file); -+static int cow_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg); -+static int cow_revalidate(kdev_t rdev); -+ -+static struct block_device_operations cow_blops = { -+ .open = cow_open, -+ .release = cow_release, -+ .ioctl = cow_ioctl, -+ .revalidate = cow_revalidate, -+}; -+ -+/* Initialized in an initcall, and unchanged thereafter */ -+devfs_handle_t cow_dir_handle; -+ -+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \ -+{ \ -+ .major = maj, \ -+ .major_name = name, \ -+ .minor_shift = shift, \ -+ .max_p = 1 << shift, \ -+ .part = parts, \ -+ .sizes = bsizes, \ -+ .nr_real = max, \ -+ .real_devices = NULL, \ -+ .next = NULL, \ -+ .fops = blops, \ -+ .de_arr = NULL, \ -+ .flags = 0 \ -+} -+ -+static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED; -+ -+static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part, -+ COW_SHIFT, sizes, MAX_DEV, -+ &cow_blops); -+ -+static int cow_add(int n) -+{ -+ struct cow *dev = &cow_dev[n]; -+ char name[sizeof("nnnnnn\0")]; -+ int err = -ENODEV; -+ -+ if(dev->cow_path == NULL) -+ goto out; -+ -+ sprintf(name, "%d", n); -+ dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE, -+ MAJOR_NR, n << COW_SHIFT, S_IFBLK | -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, -+ &cow_blops, NULL); -+ -+ init_MUTEX_LOCKED(&dev->sem); -+ init_MUTEX(&dev->io_sem); -+ -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+/* -+ * Add buffer_head to back of pending list -+ */ -+static void cow_add_bh(struct cow *cow, struct buffer_head *bh) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&cow->io_lock, flags); -+ if(cow->bhtail != NULL){ -+ cow->bhtail->b_reqnext = bh; -+ cow->bhtail = bh; -+ } -+ else { -+ cow->bh = bh; -+ cow->bhtail = bh; -+ } -+ spin_unlock_irqrestore(&cow->io_lock, flags); -+} -+ -+/* -+ * Grab first pending buffer -+ */ -+static struct buffer_head *cow_get_bh(struct cow *cow) -+{ -+ struct buffer_head *bh; -+ -+ spin_lock_irq(&cow->io_lock); -+ bh = cow->bh; -+ if(bh != NULL){ -+ if(bh == cow->bhtail) -+ cow->bhtail = NULL; -+ cow->bh = bh->b_reqnext; -+ bh->b_reqnext = NULL; -+ } -+ spin_unlock_irq(&cow->io_lock); -+ -+ return(bh); -+} -+ -+static void cow_handle_bh(struct cow *cow, struct buffer_head *bh, -+ struct buffer_head **cow_bh, int ncow_bh) -+{ -+ int i; -+ -+ if(ncow_bh > 0) -+ ll_rw_block(WRITE, ncow_bh, cow_bh); -+ -+ for(i = 0; i < ncow_bh ; i++){ -+ wait_on_buffer(cow_bh[i]); -+ brelse(cow_bh[i]); -+ } -+ -+ ll_rw_block(WRITE, 1, &bh); -+ brelse(bh); -+} -+ -+static struct buffer_head *cow_new_bh(struct cow *dev, int sector) -+{ -+ struct buffer_head *bh; -+ -+ sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize; -+ bh = getblk(dev->cow_dev, sector, dev->sectorsize); -+ memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])), -+ dev->sectorsize); -+ return(bh); -+} -+ -+/* Copied from loop.c, needed to avoid deadlocking in make_request. */ -+ -+static int cow_thread(void *data) -+{ -+ struct cow *dev = data; -+ struct buffer_head *bh; -+ -+ daemonize(); -+ exit_files(current); -+ -+ sprintf(current->comm, "cow%d", dev - cow_dev); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ sigfillset(¤t->blocked); -+ flush_signals(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ atomic_inc(&dev->working); -+ -+ current->policy = SCHED_OTHER; -+ current->nice = -20; -+ -+ current->flags |= PF_NOIO; -+ -+ /* -+ * up sem, we are running -+ */ -+ up(&dev->sem); -+ -+ for(;;){ -+ int start, len, nbh, i, update_bitmap = 0; -+ struct buffer_head *cow_bh[2]; -+ -+ down_interruptible(&dev->io_sem); -+ /* -+ * could be upped because of tear-down, not because of -+ * pending work -+ */ -+ if(!atomic_read(&dev->working)) -+ break; -+ -+ bh = cow_get_bh(dev); -+ if(bh == NULL){ -+ printk(KERN_ERR "cow: missing bh\n"); -+ continue; -+ } -+ -+ start = bh->b_blocknr * bh->b_size / dev->sectorsize; -+ len = bh->b_size / dev->sectorsize; -+ for(i = 0; i < len ; i++){ -+ if(ubd_test_bit(start + i, -+ (unsigned char *) dev->bitmap)) -+ continue; -+ -+ update_bitmap = 1; -+ ubd_set_bit(start + i, (unsigned char *) dev->bitmap); -+ } -+ -+ cow_bh[0] = NULL; -+ cow_bh[1] = NULL; -+ nbh = 0; -+ if(update_bitmap){ -+ cow_bh[0] = cow_new_bh(dev, start); -+ nbh++; -+ if(start / dev->sectorsize != -+ (start + len) / dev->sectorsize){ -+ cow_bh[1] = cow_new_bh(dev, start + len); -+ nbh++; -+ } -+ } -+ -+ bh->b_dev = dev->cow_dev; -+ bh->b_blocknr += dev->data_offset / dev->sectorsize; -+ -+ cow_handle_bh(dev, bh, cow_bh, nbh); -+ -+ /* -+ * upped both for pending work and tear-down, lo_pending -+ * will hit zero then -+ */ -+ if(atomic_dec_and_test(&dev->working)) -+ break; -+ } -+ -+ up(&dev->sem); -+ return(0); -+} -+ -+static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh) -+{ -+ struct cow *dev; -+ int n, minor; -+ -+ minor = MINOR(bh->b_rdev); -+ n = minor >> COW_SHIFT; -+ dev = &cow_dev[n]; -+ -+ dev->end_io = NULL; -+ if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){ -+ bh->b_rdev = dev->cow_dev; -+ bh->b_rsector += dev->data_offset / dev->sectorsize; -+ } -+ else if(rw == WRITE){ -+ bh->b_dev = dev->cow_dev; -+ bh->b_blocknr += dev->data_offset / dev->sectorsize; -+ -+ cow_add_bh(dev, bh); -+ up(&dev->io_sem); -+ return(0); -+ } -+ else { -+ bh->b_rdev = dev->backing_dev; -+ } -+ -+ return(1); -+} -+ -+int cow_init(void) -+{ -+ int i; -+ -+ cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL); -+ if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) { -+ printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR); -+ return -1; -+ } -+ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[MAJOR_NR] = blk_sizes; -+ blk_size[MAJOR_NR] = sizes; -+ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes); -+ -+ cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); -+ blk_init_queue(cow_queue, NULL); -+ INIT_ELV(cow_queue, &cow_queue->elevator); -+ blk_queue_make_request(cow_queue, cow_make_request); -+ -+ add_gendisk(&cow_gendisk); -+ -+ for(i=0;i<MAX_DEV;i++) -+ cow_add(i); -+ -+ return(0); -+} -+ -+__initcall(cow_init); -+ -+static int reader(__u64 start, char *buf, int count, void *arg) -+{ -+ dev_t dev = *((dev_t *) arg); -+ struct buffer_head *bh; -+ __u64 block; -+ int cur, offset, left, n, blocksize = get_hardsect_size(dev); -+ -+ if(blocksize == 0) -+ panic("Zero blocksize"); -+ -+ block = start / blocksize; -+ offset = start % blocksize; -+ left = count; -+ cur = 0; -+ while(left > 0){ -+ n = (left > blocksize) ? blocksize : left; -+ -+ bh = bread(dev, block, (n < 512) ? 512 : n); -+ if(bh == NULL) -+ return(-EIO); -+ -+ n -= offset; -+ memcpy(&buf[cur], bh->b_data + offset, n); -+ block++; -+ left -= n; -+ cur += n; -+ offset = 0; -+ brelse(bh); -+ } -+ -+ return(count); -+} -+ -+static int cow_open(struct inode *inode, struct file *filp) -+{ -+ int (*dev_ioctl)(struct inode *, struct file *, unsigned int, -+ unsigned long); -+ mm_segment_t fs; -+ struct cow *dev; -+ __u64 size; -+ __u32 version, align; -+ time_t mtime; -+ char *backing_file; -+ int n, offset, err = 0; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ if(n >= MAX_DEV) -+ return(-ENODEV); -+ dev = &cow_dev[n]; -+ offset = n << COW_SHIFT; -+ -+ spin_lock(&cow_lock); -+ -+ if(dev->count == 0){ -+ dev->cow_dev = name_to_kdev_t(dev->cow_path); -+ if(dev->cow_dev == 0){ -+ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") " -+ "failed\n", dev->cow_path); -+ err = -ENODEV; -+ } -+ -+ dev->backing_dev = name_to_kdev_t(dev->backing_path); -+ if(dev->backing_dev == 0){ -+ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") " -+ "failed\n", dev->backing_path); -+ err = -ENODEV; -+ } -+ -+ if(err) -+ goto out; -+ -+ dev->cow_bdev = bdget(dev->cow_dev); -+ if(dev->cow_bdev == NULL){ -+ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", -+ dev->cow_path); -+ err = -ENOMEM; -+ } -+ dev->backing_bdev = bdget(dev->backing_dev); -+ if(dev->backing_bdev == NULL){ -+ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n", -+ dev->backing_path); -+ err = -ENOMEM; -+ } -+ -+ if(err) -+ goto out; -+ -+ err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0, -+ BDEV_RAW); -+ if(err){ -+ printk("cow_open - blkdev_get of COW device failed, " -+ "error = %d\n", err); -+ goto out; -+ } -+ -+ err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW); -+ if(err){ -+ printk("cow_open - blkdev_get of backing device " -+ "failed, error = %d\n", err); -+ goto out; -+ } -+ -+ err = read_cow_header(reader, &dev->cow_dev, &version, -+ &backing_file, &mtime, &size, -+ &dev->sectorsize, &align, -+ &dev->bitmap_offset); -+ if(err){ -+ printk(KERN_ERR "cow_open - read_cow_header failed, " -+ "err = %d\n", err); -+ goto out; -+ } -+ -+ cow_sizes(version, size, dev->sectorsize, align, -+ dev->bitmap_offset, &dev->bitmap_len, -+ &dev->data_offset); -+ dev->bitmap = (void *) vmalloc(dev->bitmap_len); -+ if(dev->bitmap == NULL){ -+ err = -ENOMEM; -+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); -+ goto out; -+ } -+ flush_tlb_kernel_vm(); -+ -+ err = reader(dev->bitmap_offset, (char *) dev->bitmap, -+ dev->bitmap_len, &dev->cow_dev); -+ if(err < 0){ -+ printk(KERN_ERR "Failed to read COW bitmap\n"); -+ vfree(dev->bitmap); -+ goto out; -+ } -+ -+ dev_ioctl = dev->backing_bdev->bd_op->ioctl; -+ fs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = (*dev_ioctl)(inode, filp, BLKGETSIZE, -+ (unsigned long) &sizes[offset]); -+ set_fs(fs); -+ if(err){ -+ printk(KERN_ERR "cow_open - BLKGETSIZE failed, " -+ "error = %d\n", err); -+ goto out; -+ } -+ -+ kernel_thread(cow_thread, dev, -+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND); -+ down(&dev->sem); -+ } -+ dev->count++; -+ out: -+ spin_unlock(&cow_lock); -+ return(err); -+} -+ -+static int cow_release(struct inode * inode, struct file * file) -+{ -+ struct cow *dev; -+ int n, err; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ if(n >= MAX_DEV) -+ return(-ENODEV); -+ dev = &cow_dev[n]; -+ -+ spin_lock(&cow_lock); -+ -+ if(--dev->count > 0) -+ goto out; -+ -+ err = blkdev_put(dev->cow_bdev, BDEV_RAW); -+ if(err) -+ printk("cow_release - blkdev_put of cow device failed, " -+ "error = %d\n", err); -+ bdput(dev->cow_bdev); -+ dev->cow_bdev = 0; -+ -+ err = blkdev_put(dev->backing_bdev, BDEV_RAW); -+ if(err) -+ printk("cow_release - blkdev_put of backing device failed, " -+ "error = %d\n", err); -+ bdput(dev->backing_bdev); -+ dev->backing_bdev = 0; -+ -+ out: -+ spin_unlock(&cow_lock); -+ return(0); -+} -+ -+static int cow_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct cow *dev; -+ int (*dev_ioctl)(struct inode *, struct file *, unsigned int, -+ unsigned long); -+ int n; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ if(n >= MAX_DEV) -+ return(-ENODEV); -+ dev = &cow_dev[n]; -+ -+ dev_ioctl = dev->backing_bdev->bd_op->ioctl; -+ return((*dev_ioctl)(inode, file, cmd, arg)); -+} -+ -+static int cow_revalidate(kdev_t rdev) -+{ -+ printk(KERN_ERR "Need to implement cow_revalidate\n"); -+ return(0); -+} -+ -+static int parse_unit(char **ptr) -+{ -+ char *str = *ptr, *end; -+ int n = -1; -+ -+ if(isdigit(*str)) { -+ n = simple_strtoul(str, &end, 0); -+ if(end == str) -+ return(-1); -+ *ptr = end; -+ } -+ else if (('a' <= *str) && (*str <= 'h')) { -+ n = *str - 'a'; -+ str++; -+ *ptr = str; -+ } -+ return(n); -+} -+ -+static int cow_setup(char *str) -+{ -+ struct cow *dev; -+ char *cow_name, *backing_name; -+ int unit; -+ -+ unit = parse_unit(&str); -+ if(unit < 0){ -+ printk(KERN_ERR "cow_setup - Couldn't parse unit number\n"); -+ return(1); -+ } -+ -+ if(*str != '='){ -+ printk(KERN_ERR "cow_setup - Missing '=' after unit " -+ "number\n"); -+ return(1); -+ } -+ str++; -+ -+ cow_name = str; -+ backing_name = strchr(str, ','); -+ if(backing_name == NULL){ -+ printk(KERN_ERR "cow_setup - missing backing device name\n"); -+ return(0); -+ } -+ *backing_name = '\0'; -+ backing_name++; -+ -+ spin_lock(&cow_lock); -+ -+ dev = &cow_dev[unit]; -+ dev->cow_path = cow_name; -+ dev->backing_path = backing_name; -+ -+ spin_unlock(&cow_lock); -+ return(0); -+} -+ -+__setup("cow", cow_setup); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/cow_sys.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/cow_sys.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/cow_sys.h 2005-05-03 22:43:34.768503800 +0300 -@@ -0,0 +1,48 @@ -+#ifndef __COW_SYS_H__ -+#define __COW_SYS_H__ -+ -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "user.h" -+ -+static inline void *cow_malloc(int size) -+{ -+ return(um_kmalloc(size)); -+} -+ -+static inline void cow_free(void *ptr) -+{ -+ kfree(ptr); -+} -+ -+#define cow_printf printk -+ -+static inline char *cow_strdup(char *str) -+{ -+ return(uml_strdup(str)); -+} -+ -+static inline int cow_seek_file(int fd, __u64 offset) -+{ -+ return(os_seek_file(fd, offset)); -+} -+ -+static inline int cow_file_size(char *file, __u64 *size_out) -+{ -+ return(os_file_size(file, size_out)); -+} -+ -+static inline int cow_write_file(int fd, char *buf, int size) -+{ -+ return(os_write_file(fd, buf, size)); -+} -+ -+#endif -+ -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/cow_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/cow_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/cow_user.c 2005-05-03 22:28:14.203450960 +0300 -@@ -0,0 +1,375 @@ -+#include <stddef.h> -+#include <string.h> -+#include <errno.h> -+#include <unistd.h> -+#include <byteswap.h> -+#include <sys/time.h> -+#include <sys/param.h> -+#include <sys/user.h> -+#include <netinet/in.h> -+ -+#include "os.h" -+ -+#include "cow.h" -+#include "cow_sys.h" -+ -+#define PATH_LEN_V1 256 -+ -+struct cow_header_v1 { -+ int magic; -+ int version; -+ char backing_file[PATH_LEN_V1]; -+ time_t mtime; -+ __u64 size; -+ int sectorsize; -+}; -+ -+#define PATH_LEN_V2 MAXPATHLEN -+ -+struct cow_header_v2 { -+ __u32 magic; -+ __u32 version; -+ char backing_file[PATH_LEN_V2]; -+ time_t mtime; -+ __u64 size; -+ int sectorsize; -+}; -+ -+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in -+ * case other systems have different values for MAXPATHLEN -+ */ -+#define PATH_LEN_V3 4096 -+ -+/* Changes from V2 - -+ * PATH_LEN_V3 as described above -+ * Explicitly specify field bit lengths for systems with different -+ * lengths for the usual C types. Not sure whether char or -+ * time_t should be changed, this can be changed later without -+ * breaking compatibility -+ * Add alignment field so that different alignments can be used for the -+ * bitmap and data -+ * Add cow_format field to allow for the possibility of different ways -+ * of specifying the COW blocks. For now, the only value is 0, -+ * for the traditional COW bitmap. -+ * Move the backing_file field to the end of the header. This allows -+ * for the possibility of expanding it into the padding required -+ * by the bitmap alignment. -+ * The bitmap and data portions of the file will be aligned as specified -+ * by the alignment field. This is to allow COW files to be -+ * put on devices with restrictions on access alignments, such as -+ * /dev/raw, with a 512 byte alignment restriction. This also -+ * allows the data to be more aligned more strictly than on -+ * sector boundaries. This is needed for ubd-mmap, which needs -+ * the data to be page aligned. -+ * Fixed (finally!) the rounding bug -+ */ -+ -+struct cow_header_v3 { -+ __u32 magic; -+ __u32 version; -+ time_t mtime; -+ __u64 size; -+ __u32 sectorsize; -+ __u32 alignment; -+ __u32 cow_format; -+ char backing_file[PATH_LEN_V3]; -+}; -+ -+/* COW format definitions - for now, we have only the usual COW bitmap */ -+#define COW_BITMAP 0 -+ -+union cow_header { -+ struct cow_header_v1 v1; -+ struct cow_header_v2 v2; -+ struct cow_header_v3 v3; -+}; -+ -+#define COW_MAGIC 0x4f4f4f4d /* MOOO */ -+#define COW_VERSION 3 -+ -+#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) -+#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) -+ -+void cow_sizes(int version, __u64 size, int sectorsize, int align, -+ int bitmap_offset, unsigned long *bitmap_len_out, -+ int *data_offset_out) -+{ -+ if(version < 3){ -+ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); -+ -+ *data_offset_out = bitmap_offset + *bitmap_len_out; -+ *data_offset_out = (*data_offset_out + sectorsize - 1) / -+ sectorsize; -+ *data_offset_out *= sectorsize; -+ } -+ else { -+ *bitmap_len_out = DIV_ROUND(size, sectorsize); -+ *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8); -+ -+ *data_offset_out = bitmap_offset + *bitmap_len_out; -+ *data_offset_out = ROUND_UP(*data_offset_out, align); -+ } -+} -+ -+static int absolutize(char *to, int size, char *from) -+{ -+ char save_cwd[256], *slash; -+ int remaining; -+ -+ if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { -+ cow_printf("absolutize : unable to get cwd - errno = %d\n", -+ errno); -+ return(-1); -+ } -+ slash = strrchr(from, '/'); -+ if(slash != NULL){ -+ *slash = '\0'; -+ if(chdir(from)){ -+ *slash = '/'; -+ cow_printf("absolutize : Can't cd to '%s' - " -+ "errno = %d\n", from, errno); -+ return(-1); -+ } -+ *slash = '/'; -+ if(getcwd(to, size) == NULL){ -+ cow_printf("absolutize : unable to get cwd of '%s' - " -+ "errno = %d\n", from, errno); -+ return(-1); -+ } -+ remaining = size - strlen(to); -+ if(strlen(slash) + 1 > remaining){ -+ cow_printf("absolutize : unable to fit '%s' into %d " -+ "chars\n", from, size); -+ return(-1); -+ } -+ strcat(to, slash); -+ } -+ else { -+ if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ -+ cow_printf("absolutize : unable to fit '%s' into %d " -+ "chars\n", from, size); -+ return(-1); -+ } -+ strcpy(to, save_cwd); -+ strcat(to, "/"); -+ strcat(to, from); -+ } -+ chdir(save_cwd); -+ return(0); -+} -+ -+int write_cow_header(char *cow_file, int fd, char *backing_file, -+ int sectorsize, int alignment, long long *size) -+{ -+ struct cow_header_v3 *header; -+ unsigned long modtime; -+ int err; -+ -+ err = cow_seek_file(fd, 0); -+ if(err < 0){ -+ cow_printf("write_cow_header - lseek failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ header = cow_malloc(sizeof(*header)); -+ if(header == NULL){ -+ cow_printf("Failed to allocate COW V3 header\n"); -+ goto out; -+ } -+ header->magic = htonl(COW_MAGIC); -+ header->version = htonl(COW_VERSION); -+ -+ err = -EINVAL; -+ if(strlen(backing_file) > sizeof(header->backing_file) - 1){ -+ cow_printf("Backing file name \"%s\" is too long - names are " -+ "limited to %d characters\n", backing_file, -+ sizeof(header->backing_file) - 1); -+ goto out_free; -+ } -+ -+ if(absolutize(header->backing_file, sizeof(header->backing_file), -+ backing_file)) -+ goto out_free; -+ -+ err = os_file_modtime(header->backing_file, &modtime); -+ if(err < 0){ -+ cow_printf("Backing file '%s' mtime request failed, " -+ "err = %d\n", header->backing_file, -err); -+ goto out_free; -+ } -+ -+ err = cow_file_size(header->backing_file, size); -+ if(err < 0){ -+ cow_printf("Couldn't get size of backing file '%s', " -+ "err = %d\n", header->backing_file, -err); -+ goto out_free; -+ } -+ -+ header->mtime = htonl(modtime); -+ header->size = htonll(*size); -+ header->sectorsize = htonl(sectorsize); -+ header->alignment = htonl(alignment); -+ header->cow_format = COW_BITMAP; -+ -+ err = os_write_file(fd, header, sizeof(*header)); -+ if(err != sizeof(*header)){ -+ cow_printf("Write of header to new COW file '%s' failed, " -+ "err = %d\n", cow_file, -err); -+ goto out_free; -+ } -+ err = 0; -+ out_free: -+ cow_free(header); -+ out: -+ return(err); -+} -+ -+int file_reader(__u64 offset, char *buf, int len, void *arg) -+{ -+ int fd = *((int *) arg); -+ -+ return(pread(fd, buf, len, offset)); -+} -+ -+/* XXX Need to sanity-check the values read from the header */ -+ -+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, -+ __u32 *version_out, char **backing_file_out, -+ time_t *mtime_out, __u64 *size_out, -+ int *sectorsize_out, __u32 *align_out, -+ int *bitmap_offset_out) -+{ -+ union cow_header *header; -+ char *file; -+ int err, n; -+ unsigned long version, magic; -+ -+ header = cow_malloc(sizeof(*header)); -+ if(header == NULL){ -+ cow_printf("read_cow_header - Failed to allocate header\n"); -+ return(-ENOMEM); -+ } -+ err = -EINVAL; -+ n = (*reader)(0, (char *) header, sizeof(*header), arg); -+ if(n < offsetof(typeof(header->v1), backing_file)){ -+ cow_printf("read_cow_header - short header\n"); -+ goto out; -+ } -+ -+ magic = header->v1.magic; -+ if(magic == COW_MAGIC) { -+ version = header->v1.version; -+ } -+ else if(magic == ntohl(COW_MAGIC)){ -+ version = ntohl(header->v1.version); -+ } -+ /* No error printed because the non-COW case comes through here */ -+ else goto out; -+ -+ *version_out = version; -+ -+ if(version == 1){ -+ if(n < sizeof(header->v1)){ -+ cow_printf("read_cow_header - failed to read V1 " -+ "header\n"); -+ goto out; -+ } -+ *mtime_out = header->v1.mtime; -+ *size_out = header->v1.size; -+ *sectorsize_out = header->v1.sectorsize; -+ *bitmap_offset_out = sizeof(header->v1); -+ *align_out = *sectorsize_out; -+ file = header->v1.backing_file; -+ } -+ else if(version == 2){ -+ if(n < sizeof(header->v2)){ -+ cow_printf("read_cow_header - failed to read V2 " -+ "header\n"); -+ goto out; -+ } -+ *mtime_out = ntohl(header->v2.mtime); -+ *size_out = ntohll(header->v2.size); -+ *sectorsize_out = ntohl(header->v2.sectorsize); -+ *bitmap_offset_out = sizeof(header->v2); -+ *align_out = *sectorsize_out; -+ file = header->v2.backing_file; -+ } -+ else if(version == 3){ -+ if(n < sizeof(header->v3)){ -+ cow_printf("read_cow_header - failed to read V2 " -+ "header\n"); -+ goto out; -+ } -+ *mtime_out = ntohl(header->v3.mtime); -+ *size_out = ntohll(header->v3.size); -+ *sectorsize_out = ntohl(header->v3.sectorsize); -+ *align_out = ntohl(header->v3.alignment); -+ *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); -+ file = header->v3.backing_file; -+ } -+ else { -+ cow_printf("read_cow_header - invalid COW version\n"); -+ goto out; -+ } -+ err = -ENOMEM; -+ *backing_file_out = cow_strdup(file); -+ if(*backing_file_out == NULL){ -+ cow_printf("read_cow_header - failed to allocate backing " -+ "file\n"); -+ goto out; -+ } -+ err = 0; -+ out: -+ cow_free(header); -+ return(err); -+} -+ -+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, -+ int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out) -+{ -+ __u64 size, offset; -+ char zero = 0; -+ int err; -+ -+ err = write_cow_header(cow_file, fd, backing_file, sectorsize, -+ alignment, &size); -+ if(err) -+ goto out; -+ -+ *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); -+ cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, -+ bitmap_len_out, data_offset_out); -+ -+ offset = *data_offset_out + size - sizeof(zero); -+ err = cow_seek_file(fd, offset); -+ if(err < 0){ -+ cow_printf("cow bitmap lseek failed : err = %d\n", -err); -+ goto out; -+ } -+ -+ /* does not really matter how much we write it is just to set EOF -+ * this also sets the entire COW bitmap -+ * to zero without having to allocate it -+ */ -+ err = cow_write_file(fd, &zero, sizeof(zero)); -+ if(err != sizeof(zero)){ -+ cow_printf("Write of bitmap to new COW file '%s' failed, " -+ "err = %d\n", cow_file, -err); -+ err = -EINVAL; -+ goto out; -+ } -+ -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/daemon.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/daemon.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/daemon.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+#define SWITCH_VERSION 3 -+ -+struct daemon_data { -+ char *sock_type; -+ char *ctl_sock; -+ void *ctl_addr; -+ void *data_addr; -+ void *local_addr; -+ int fd; -+ int control; -+ void *dev; -+}; -+ -+extern struct net_user_info daemon_user_info; -+ -+extern int daemon_user_write(int fd, void *buf, int len, -+ struct daemon_data *pri); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/daemon_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/daemon_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/daemon_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "daemon.h" -+ -+struct daemon_init { -+ char *sock_type; -+ char *ctl_sock; -+}; -+ -+void daemon_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct daemon_data *dpri; -+ struct daemon_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ dpri = (struct daemon_data *) pri->user; -+ *dpri = ((struct daemon_data) -+ { .sock_type = init->sock_type, -+ .ctl_sock = init->ctl_sock, -+ .ctl_addr = NULL, -+ .data_addr = NULL, -+ .local_addr = NULL, -+ .fd = -1, -+ .control = -1, -+ .dev = dev }); -+ -+ printk("daemon backend (uml_switch version %d) - %s:%s", -+ SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); -+ printk("\n"); -+} -+ -+static int daemon_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int daemon_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(daemon_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct daemon_data *) &lp->user)); -+} -+ -+static struct net_kern_info daemon_kern_info = { -+ .init = daemon_init, -+ .protocol = eth_protocol, -+ .read = daemon_read, -+ .write = daemon_write, -+}; -+ -+int daemon_setup(char *str, char **mac_out, void *data) -+{ -+ struct daemon_init *init = data; -+ char *remain; -+ -+ *init = ((struct daemon_init) -+ { .sock_type = "unix", -+ .ctl_sock = "/tmp/uml.ctl" }); -+ -+ remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock, -+ NULL); -+ if(remain != NULL) -+ printk(KERN_WARNING "daemon_setup : Ignoring data socket " -+ "specification\n"); -+ -+ return(1); -+} -+ -+static struct transport daemon_transport = { -+ .list = LIST_HEAD_INIT(daemon_transport.list), -+ .name = "daemon", -+ .setup = daemon_setup, -+ .user = &daemon_user_info, -+ .kern = &daemon_kern_info, -+ .private_size = sizeof(struct daemon_data), -+ .setup_size = sizeof(struct daemon_init), -+}; -+ -+static int register_daemon(void) -+{ -+ register_transport(&daemon_transport); -+ return(1); -+} -+ -+__initcall(register_daemon); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/daemon_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/daemon_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/daemon_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,197 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include <errno.h> -+#include <unistd.h> -+#include <stdint.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/time.h> -+#include "net_user.h" -+#include "daemon.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+enum request_type { REQ_NEW_CONTROL }; -+ -+#define SWITCH_MAGIC 0xfeedface -+ -+struct request_v3 { -+ uint32_t magic; -+ uint32_t version; -+ enum request_type type; -+ struct sockaddr_un sock; -+}; -+ -+static struct sockaddr_un *new_addr(void *name, int len) -+{ -+ struct sockaddr_un *sun; -+ -+ sun = um_kmalloc(sizeof(struct sockaddr_un)); -+ if(sun == NULL){ -+ printk("new_addr: allocation of sockaddr_un failed\n"); -+ return(NULL); -+ } -+ sun->sun_family = AF_UNIX; -+ memcpy(sun->sun_path, name, len); -+ return(sun); -+} -+ -+static int connect_to_switch(struct daemon_data *pri) -+{ -+ struct sockaddr_un *ctl_addr = pri->ctl_addr; -+ struct sockaddr_un *local_addr = pri->local_addr; -+ struct sockaddr_un *sun; -+ struct request_v3 req; -+ int fd, n, err; -+ -+ pri->control = socket(AF_UNIX, SOCK_STREAM, 0); -+ if(pri->control < 0){ -+ printk("daemon_open : control socket failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ if(connect(pri->control, (struct sockaddr *) ctl_addr, -+ sizeof(*ctl_addr)) < 0){ -+ printk("daemon_open : control connect failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out; -+ } -+ -+ fd = socket(AF_UNIX, SOCK_DGRAM, 0); -+ if(fd < 0){ -+ printk("daemon_open : data socket failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out; -+ } -+ if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ -+ printk("daemon_open : data bind failed, errno = %d\n", -+ errno); -+ err = -errno; -+ goto out_close; -+ } -+ -+ sun = um_kmalloc(sizeof(struct sockaddr_un)); -+ if(sun == NULL){ -+ printk("new_addr: allocation of sockaddr_un failed\n"); -+ err = -ENOMEM; -+ goto out_close; -+ } -+ -+ req.magic = SWITCH_MAGIC; -+ req.version = SWITCH_VERSION; -+ req.type = REQ_NEW_CONTROL; -+ req.sock = *local_addr; -+ n = os_write_file(pri->control, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ printk("daemon_open : control setup request failed, err = %d\n", -+ -n); -+ err = -ENOTCONN; -+ goto out; -+ } -+ -+ n = os_read_file(pri->control, sun, sizeof(*sun)); -+ if(n != sizeof(*sun)){ -+ printk("daemon_open : read of data socket failed, err = %d\n", -+ -n); -+ err = -ENOTCONN; -+ goto out_close; -+ } -+ -+ pri->data_addr = sun; -+ return(fd); -+ -+ out_close: -+ os_close_file(fd); -+ out: -+ os_close_file(pri->control); -+ return(err); -+} -+ -+static void daemon_user_init(void *data, void *dev) -+{ -+ struct daemon_data *pri = data; -+ struct timeval tv; -+ struct { -+ char zero; -+ int pid; -+ int usecs; -+ } name; -+ -+ if(!strcmp(pri->sock_type, "unix")) -+ pri->ctl_addr = new_addr(pri->ctl_sock, -+ strlen(pri->ctl_sock) + 1); -+ name.zero = 0; -+ name.pid = os_getpid(); -+ gettimeofday(&tv, NULL); -+ name.usecs = tv.tv_usec; -+ pri->local_addr = new_addr(&name, sizeof(name)); -+ pri->dev = dev; -+ pri->fd = connect_to_switch(pri); -+ if(pri->fd < 0){ -+ kfree(pri->local_addr); -+ pri->local_addr = NULL; -+ } -+} -+ -+static int daemon_open(void *data) -+{ -+ struct daemon_data *pri = data; -+ return(pri->fd); -+} -+ -+static void daemon_remove(void *data) -+{ -+ struct daemon_data *pri = data; -+ -+ os_close_file(pri->fd); -+ os_close_file(pri->control); -+ if(pri->data_addr != NULL) kfree(pri->data_addr); -+ if(pri->ctl_addr != NULL) kfree(pri->ctl_addr); -+ if(pri->local_addr != NULL) kfree(pri->local_addr); -+} -+ -+int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) -+{ -+ struct sockaddr_un *data_addr = pri->data_addr; -+ -+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); -+} -+ -+static int daemon_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info daemon_user_info = { -+ .init = daemon_user_init, -+ .open = daemon_open, -+ .close = NULL, -+ .remove = daemon_remove, -+ .set_mtu = daemon_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/fd.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/fd.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/fd.c 2005-05-03 22:28:14.208450200 +0300 -@@ -0,0 +1,108 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <termios.h> -+#include <errno.h> -+#include "user.h" -+#include "user_util.h" -+#include "chan_user.h" -+ -+struct fd_chan { -+ int fd; -+ int raw; -+ struct termios tt; -+ char str[sizeof("1234567890\0")]; -+}; -+ -+void *fd_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct fd_chan *data; -+ char *end; -+ int n; -+ -+ if(*str != ':'){ -+ printk("fd_init : channel type 'fd' must specify a file " -+ "descriptor\n"); -+ return(NULL); -+ } -+ str++; -+ n = strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk("fd_init : couldn't parse file descriptor '%s'\n", str); -+ return(NULL); -+ } -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) return(NULL); -+ *data = ((struct fd_chan) { .fd = n, -+ .raw = opts->raw }); -+ return(data); -+} -+ -+int fd_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct fd_chan *data = d; -+ int err; -+ -+ if(data->raw && isatty(data->fd)){ -+ CATCH_EINTR(err = tcgetattr(data->fd, &data->tt)); -+ if(err) -+ return(err); -+ -+ err = raw(data->fd); -+ if(err) -+ return(err); -+ } -+ sprintf(data->str, "%d", data->fd); -+ *dev_out = data->str; -+ return(data->fd); -+} -+ -+void fd_close(int fd, void *d) -+{ -+ struct fd_chan *data = d; -+ int err; -+ -+ if(data->raw && isatty(fd)){ -+ CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt)); -+ if(err) -+ printk("Failed to restore terminal state - " -+ "errno = %d\n", -err); -+ data->raw = 0; -+ } -+} -+ -+int fd_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct fd_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops fd_ops = { -+ .type = "fd", -+ .init = fd_init, -+ .open = fd_open, -+ .close = fd_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = fd_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 1, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/harddog_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/harddog_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/harddog_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,194 @@ -+/* UML hardware watchdog, shamelessly stolen from: -+ * -+ * SoftDog 0.05: A Software Watchdog Device -+ * -+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved. -+ * http://www.redhat.com -+ * -+ * 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. -+ * -+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide -+ * warranty for any of this software. This material is provided -+ * "AS-IS" and at no charge. -+ * -+ * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk> -+ * -+ * Software only watchdog driver. Unlike its big brother the WDT501P -+ * driver this won't always recover a failed machine. -+ * -+ * 03/96: Angelo Haritsis <ah@doc.ic.ac.uk> : -+ * Modularised. -+ * Added soft_margin; use upon insmod to change the timer delay. -+ * NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate -+ * minors. -+ * -+ * 19980911 Alan Cox -+ * Made SMP safe for 2.3.x -+ * -+ * 20011127 Joel Becker (jlbec@evilplan.org> -+ * Added soft_noboot; Allows testing the softdog trigger without -+ * requiring a recompile. -+ * Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT. -+ */ -+ -+#include <linux/module.h> -+#include <linux/config.h> -+#include <linux/types.h> -+#include <linux/kernel.h> -+#include <linux/fs.h> -+#include <linux/mm.h> -+#include <linux/miscdevice.h> -+#include <linux/watchdog.h> -+#include <linux/reboot.h> -+#include <linux/smp_lock.h> -+#include <linux/init.h> -+#include <asm/uaccess.h> -+#include "helper.h" -+#include "mconsole.h" -+ -+MODULE_LICENSE("GPL"); -+ -+/* Locked by the BKL in harddog_open and harddog_release */ -+static int timer_alive; -+static int harddog_in_fd = -1; -+static int harddog_out_fd = -1; -+ -+/* -+ * Allow only one person to hold it open -+ */ -+ -+extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); -+ -+static int harddog_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ char *sock = NULL; -+ -+ lock_kernel(); -+ if(timer_alive) -+ return -EBUSY; -+#ifdef CONFIG_HARDDOG_NOWAYOUT -+ MOD_INC_USE_COUNT; -+#endif -+ -+#ifdef CONFIG_MCONSOLE -+ sock = mconsole_notify_socket(); -+#endif -+ err = start_watchdog(&harddog_in_fd, &harddog_out_fd, sock); -+ if(err) return(err); -+ -+ timer_alive = 1; -+ unlock_kernel(); -+ return 0; -+} -+ -+extern void stop_watchdog(int in_fd, int out_fd); -+ -+static int harddog_release(struct inode *inode, struct file *file) -+{ -+ /* -+ * Shut off the timer. -+ */ -+ lock_kernel(); -+ -+ stop_watchdog(harddog_in_fd, harddog_out_fd); -+ harddog_in_fd = -1; -+ harddog_out_fd = -1; -+ -+ timer_alive=0; -+ unlock_kernel(); -+ return 0; -+} -+ -+extern int ping_watchdog(int fd); -+ -+static ssize_t harddog_write(struct file *file, const char *data, size_t len, -+ loff_t *ppos) -+{ -+ /* Can't seek (pwrite) on this device */ -+ if (ppos != &file->f_pos) -+ return -ESPIPE; -+ -+ /* -+ * Refresh the timer. -+ */ -+ if(len) -+ return(ping_watchdog(harddog_out_fd)); -+ return 0; -+} -+ -+static int harddog_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ static struct watchdog_info ident = { -+ WDIOF_SETTIMEOUT, -+ 0, -+ "UML Hardware Watchdog" -+ }; -+ switch (cmd) { -+ default: -+ return -ENOTTY; -+ case WDIOC_GETSUPPORT: -+ if(copy_to_user((struct harddog_info *)arg, &ident, -+ sizeof(ident))) -+ return -EFAULT; -+ return 0; -+ case WDIOC_GETSTATUS: -+ case WDIOC_GETBOOTSTATUS: -+ return put_user(0,(int *)arg); -+ case WDIOC_KEEPALIVE: -+ return(ping_watchdog(harddog_out_fd)); -+ } -+} -+ -+static struct file_operations harddog_fops = { -+ .owner = THIS_MODULE, -+ .write = harddog_write, -+ .ioctl = harddog_ioctl, -+ .open = harddog_open, -+ .release = harddog_release, -+}; -+ -+static struct miscdevice harddog_miscdev = { -+ .minor = WATCHDOG_MINOR, -+ .name = "watchdog", -+ .fops = &harddog_fops, -+}; -+ -+static char banner[] __initdata = KERN_INFO "UML Watchdog Timer\n"; -+ -+static int __init harddog_init(void) -+{ -+ int ret; -+ -+ ret = misc_register(&harddog_miscdev); -+ -+ if (ret) -+ return ret; -+ -+ printk(banner); -+ -+ return(0); -+} -+ -+static void __exit harddog_exit(void) -+{ -+ misc_deregister(&harddog_miscdev); -+} -+ -+module_init(harddog_init); -+module_exit(harddog_exit); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/harddog_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/harddog_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/harddog_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <errno.h> -+#include "user_util.h" -+#include "user.h" -+#include "helper.h" -+#include "mconsole.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+struct dog_data { -+ int stdin; -+ int stdout; -+ int close_me[2]; -+}; -+ -+static void pre_exec(void *d) -+{ -+ struct dog_data *data = d; -+ -+ dup2(data->stdin, 0); -+ dup2(data->stdout, 1); -+ dup2(data->stdout, 2); -+ os_close_file(data->stdin); -+ os_close_file(data->stdout); -+ os_close_file(data->close_me[0]); -+ os_close_file(data->close_me[1]); -+} -+ -+int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) -+{ -+ struct dog_data data; -+ int in_fds[2], out_fds[2], pid, n, err; -+ char pid_buf[sizeof("nnnnn\0")], c; -+ char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; -+ char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, -+ NULL }; -+ char **args = NULL; -+ -+ err = os_pipe(in_fds, 1, 0); -+ if(err < 0){ -+ printk("harddog_open - os_pipe failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ err = os_pipe(out_fds, 1, 0); -+ if(err < 0){ -+ printk("harddog_open - os_pipe failed, err = %d\n", -err); -+ goto out_close_in; -+ } -+ -+ data.stdin = out_fds[0]; -+ data.stdout = in_fds[1]; -+ data.close_me[0] = out_fds[1]; -+ data.close_me[1] = in_fds[0]; -+ -+ if(sock != NULL){ -+ mconsole_args[2] = sock; -+ args = mconsole_args; -+ } -+ else { -+ /* XXX The os_getpid() is not SMP correct */ -+ sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid())); -+ args = pid_args; -+ } -+ -+ pid = run_helper(pre_exec, &data, args, NULL); -+ -+ os_close_file(out_fds[0]); -+ os_close_file(in_fds[1]); -+ -+ if(pid < 0){ -+ err = -pid; -+ printk("harddog_open - run_helper failed, errno = %d\n", -err); -+ goto out_close_out; -+ } -+ -+ n = os_read_file(in_fds[0], &c, sizeof(c)); -+ if(n == 0){ -+ printk("harddog_open - EOF on watchdog pipe\n"); -+ helper_wait(pid); -+ err = -EIO; -+ goto out_close_out; -+ } -+ else if(n < 0){ -+ printk("harddog_open - read of watchdog pipe failed, " -+ "err = %d\n", -n); -+ helper_wait(pid); -+ err = n; -+ goto out_close_out; -+ } -+ *in_fd_ret = in_fds[0]; -+ *out_fd_ret = out_fds[1]; -+ return(0); -+ -+ out_close_in: -+ os_close_file(in_fds[0]); -+ os_close_file(in_fds[1]); -+ out_close_out: -+ os_close_file(out_fds[0]); -+ os_close_file(out_fds[1]); -+ out: -+ return(err); -+} -+ -+void stop_watchdog(int in_fd, int out_fd) -+{ -+ os_close_file(in_fd); -+ os_close_file(out_fd); -+} -+ -+int ping_watchdog(int fd) -+{ -+ int n; -+ char c = '\n'; -+ -+ n = os_write_file(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("ping_watchdog - write failed, err = %d\n", -n); -+ if(n < 0) -+ return(n); -+ return(-EIO); -+ } -+ return 1; -+ -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/hostaudio_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/hostaudio_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/hostaudio_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,352 @@ -+/* -+ * Copyright (C) 2002 Steve Schmidtke -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/slab.h" -+#include "linux/fs.h" -+#include "linux/sound.h" -+#include "linux/soundcard.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+#include "init.h" -+#include "os.h" -+ -+struct hostaudio_state { -+ int fd; -+}; -+ -+struct hostmixer_state { -+ int fd; -+}; -+ -+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" -+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" -+ -+/* Only changed from linux_main at boot time */ -+char *dsp = HOSTAUDIO_DEV_DSP; -+char *mixer = HOSTAUDIO_DEV_MIXER; -+ -+#define DSP_HELP \ -+" This is used to specify the host dsp device to the hostaudio driver.\n" \ -+" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" -+ -+#define MIXER_HELP \ -+" This is used to specify the host mixer device to the hostaudio driver.\n"\ -+" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" -+ -+#ifndef MODULE -+static int set_dsp(char *name, int *add) -+{ -+ dsp = name; -+ return(0); -+} -+ -+__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP); -+ -+static int set_mixer(char *name, int *add) -+{ -+ mixer = name; -+ return(0); -+} -+ -+__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); -+ -+#else /*MODULE*/ -+ -+MODULE_PARM(dsp, "s"); -+MODULE_PARM_DESC(dsp, DSP_HELP); -+ -+MODULE_PARM(mixer, "s"); -+MODULE_PARM_DESC(mixer, MIXER_HELP); -+ -+#endif -+ -+/* /dev/dsp file operations */ -+ -+static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ struct hostaudio_state *state = file->private_data; -+ void *kbuf; -+ int err; -+ -+#ifdef DEBUG -+ printk("hostaudio: read called, count = %d\n", count); -+#endif -+ -+ kbuf = kmalloc(count, GFP_KERNEL); -+ if(kbuf == NULL) -+ return(-ENOMEM); -+ -+ err = os_read_file(state->fd, kbuf, count); -+ if(err < 0) -+ goto out; -+ -+ if(copy_to_user(buffer, kbuf, err)) -+ err = -EFAULT; -+ -+ out: -+ kfree(kbuf); -+ return(err); -+} -+ -+static ssize_t hostaudio_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct hostaudio_state *state = file->private_data; -+ void *kbuf; -+ int err; -+ -+#ifdef DEBUG -+ printk("hostaudio: write called, count = %d\n", count); -+#endif -+ -+ kbuf = kmalloc(count, GFP_KERNEL); -+ if(kbuf == NULL) -+ return(-ENOMEM); -+ -+ err = -EFAULT; -+ if(copy_from_user(kbuf, buffer, count)) -+ goto out; -+ -+ err = os_write_file(state->fd, kbuf, count); -+ if(err < 0) -+ goto out; -+ *ppos += err; -+ -+ out: -+ kfree(kbuf); -+ return(err); -+} -+ -+static unsigned int hostaudio_poll(struct file *file, -+ struct poll_table_struct *wait) -+{ -+ unsigned int mask = 0; -+ -+#ifdef DEBUG -+ printk("hostaudio: poll called (unimplemented)\n"); -+#endif -+ -+ return(mask); -+} -+ -+static int hostaudio_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hostaudio_state *state = file->private_data; -+ unsigned long data = 0; -+ int err; -+ -+#ifdef DEBUG -+ printk("hostaudio: ioctl called, cmd = %u\n", cmd); -+#endif -+ switch(cmd){ -+ case SNDCTL_DSP_SPEED: -+ case SNDCTL_DSP_STEREO: -+ case SNDCTL_DSP_GETBLKSIZE: -+ case SNDCTL_DSP_CHANNELS: -+ case SNDCTL_DSP_SUBDIVIDE: -+ case SNDCTL_DSP_SETFRAGMENT: -+ if(get_user(data, (int *) arg)) -+ return(-EFAULT); -+ break; -+ default: -+ break; -+ } -+ -+ err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data); -+ -+ switch(cmd){ -+ case SNDCTL_DSP_SPEED: -+ case SNDCTL_DSP_STEREO: -+ case SNDCTL_DSP_GETBLKSIZE: -+ case SNDCTL_DSP_CHANNELS: -+ case SNDCTL_DSP_SUBDIVIDE: -+ case SNDCTL_DSP_SETFRAGMENT: -+ if(put_user(data, (int *) arg)) -+ return(-EFAULT); -+ break; -+ default: -+ break; -+ } -+ -+ return(err); -+} -+ -+static int hostaudio_open(struct inode *inode, struct file *file) -+{ -+ struct hostaudio_state *state; -+ int r = 0, w = 0; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostaudio: open called (host: %s)\n", dsp); -+#endif -+ -+ state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL); -+ if(state == NULL) -+ return(-ENOMEM); -+ -+ if(file->f_mode & FMODE_READ) r = 1; -+ if(file->f_mode & FMODE_WRITE) w = 1; -+ -+ ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); -+ if(ret < 0){ -+ kfree(state); -+ return(ret); -+ } -+ -+ state->fd = ret; -+ file->private_data = state; -+ return(0); -+} -+ -+static int hostaudio_release(struct inode *inode, struct file *file) -+{ -+ struct hostaudio_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostaudio: release called\n"); -+#endif -+ -+ os_close_file(state->fd); -+ kfree(state); -+ -+ return(0); -+} -+ -+/* /dev/mixer file operations */ -+ -+static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hostmixer_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostmixer: ioctl called\n"); -+#endif -+ -+ return(os_ioctl_generic(state->fd, cmd, arg)); -+} -+ -+static int hostmixer_open_mixdev(struct inode *inode, struct file *file) -+{ -+ struct hostmixer_state *state; -+ int r = 0, w = 0; -+ int ret; -+ -+#ifdef DEBUG -+ printk("hostmixer: open called (host: %s)\n", mixer); -+#endif -+ -+ state = kmalloc(sizeof(struct hostmixer_state), GFP_KERNEL); -+ if(state == NULL) return(-ENOMEM); -+ -+ if(file->f_mode & FMODE_READ) r = 1; -+ if(file->f_mode & FMODE_WRITE) w = 1; -+ -+ ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); -+ -+ if(ret < 0){ -+ printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", -+ dsp, -ret); -+ kfree(state); -+ return(ret); -+ } -+ -+ file->private_data = state; -+ return(0); -+} -+ -+static int hostmixer_release(struct inode *inode, struct file *file) -+{ -+ struct hostmixer_state *state = file->private_data; -+ -+#ifdef DEBUG -+ printk("hostmixer: release called\n"); -+#endif -+ -+ os_close_file(state->fd); -+ kfree(state); -+ -+ return(0); -+} -+ -+ -+/* kernel module operations */ -+ -+static struct file_operations hostaudio_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = hostaudio_read, -+ .write = hostaudio_write, -+ .poll = hostaudio_poll, -+ .ioctl = hostaudio_ioctl, -+ .mmap = NULL, -+ .open = hostaudio_open, -+ .release = hostaudio_release, -+}; -+ -+static struct file_operations hostmixer_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .ioctl = hostmixer_ioctl_mixdev, -+ .open = hostmixer_open_mixdev, -+ .release = hostmixer_release, -+}; -+ -+struct { -+ int dev_audio; -+ int dev_mixer; -+} module_data; -+ -+MODULE_AUTHOR("Steve Schmidtke"); -+MODULE_DESCRIPTION("UML Audio Relay"); -+MODULE_LICENSE("GPL"); -+ -+static int __init hostaudio_init_module(void) -+{ -+ printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", -+ dsp, mixer); -+ -+ module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); -+ if(module_data.dev_audio < 0){ -+ printk(KERN_ERR "hostaudio: couldn't register DSP device!\n"); -+ return -ENODEV; -+ } -+ -+ module_data.dev_mixer = register_sound_mixer(&hostmixer_fops, -1); -+ if(module_data.dev_mixer < 0){ -+ printk(KERN_ERR "hostmixer: couldn't register mixer " -+ "device!\n"); -+ unregister_sound_dsp(module_data.dev_audio); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit hostaudio_cleanup_module (void) -+{ -+ unregister_sound_mixer(module_data.dev_mixer); -+ unregister_sound_dsp(module_data.dev_audio); -+} -+ -+module_init(hostaudio_init_module); -+module_exit(hostaudio_cleanup_module); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/line.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/line.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/line.c 2005-05-03 22:28:14.214449288 +0300 -@@ -0,0 +1,610 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "linux/list.h" -+#include "linux/devfs_fs_kernel.h" -+#include "asm/irq.h" -+#include "asm/uaccess.h" -+#include "chan_kern.h" -+#include "irq_user.h" -+#include "line.h" -+#include "kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "os.h" -+#include "irq_kern.h" -+ -+#define LINE_BUFSIZE 4096 -+ -+static void line_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct line *dev = data; -+ -+ if(dev->count > 0) -+ chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, -+ dev); -+} -+ -+static void line_timer_cb(void *arg) -+{ -+ struct line *dev = arg; -+ -+ line_interrupt(dev->driver->read_irq, dev, NULL); -+} -+ -+static int write_room(struct line *dev) -+{ -+ int n; -+ -+ if(dev->buffer == NULL) return(LINE_BUFSIZE - 1); -+ -+ n = dev->head - dev->tail; -+ if(n <= 0) n = LINE_BUFSIZE + n; -+ return(n - 1); -+} -+ -+static int buffer_data(struct line *line, const char *buf, int len) -+{ -+ int end, room; -+ -+ if(line->buffer == NULL){ -+ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); -+ if(line->buffer == NULL){ -+ printk("buffer_data - atomic allocation failed\n"); -+ return(0); -+ } -+ line->head = line->buffer; -+ line->tail = line->buffer; -+ } -+ -+ room = write_room(line); -+ len = (len > room) ? room : len; -+ -+ end = line->buffer + LINE_BUFSIZE - line->tail; -+ if(len < end){ -+ memcpy(line->tail, buf, len); -+ line->tail += len; -+ } -+ else { -+ memcpy(line->tail, buf, end); -+ buf += end; -+ len -= end; -+ memcpy(line->buffer, buf, len); -+ line->tail = line->buffer + len; -+ } -+ -+ return(len); -+} -+ -+static int flush_buffer(struct line *line) -+{ -+ int n, count; -+ -+ if((line->buffer == NULL) || (line->head == line->tail)) return(1); -+ -+ if(line->tail < line->head){ -+ count = line->buffer + LINE_BUFSIZE - line->head; -+ n = write_chan(&line->chan_list, line->head, count, -+ line->driver->write_irq); -+ if(n < 0) return(n); -+ if(n == count) line->head = line->buffer; -+ else { -+ line->head += n; -+ return(0); -+ } -+ } -+ -+ count = line->tail - line->head; -+ n = write_chan(&line->chan_list, line->head, count, -+ line->driver->write_irq); -+ if(n < 0) return(n); -+ -+ line->head += n; -+ return(line->head == line->tail); -+} -+ -+int line_write(struct line *lines, struct tty_struct *tty, int from_user, -+ const char *buf, int len) -+{ -+ struct line *line; -+ char *new; -+ unsigned long flags; -+ int n, err, i, ret = 0; -+ -+ if(tty->stopped) return 0; -+ -+ if(from_user){ -+ new = kmalloc(len, GFP_KERNEL); -+ if(new == NULL) -+ return(0); -+ n = copy_from_user(new, buf, len); -+ buf = new; -+ if(n == len){ -+ len = -EFAULT; -+ goto out_free; -+ } -+ -+ len -= n; -+ } -+ -+ i = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[i]; -+ -+ down(&line->sem); -+ if(line->head != line->tail){ -+ local_irq_save(flags); -+ ret += buffer_data(line, buf, len); -+ err = flush_buffer(line); -+ local_irq_restore(flags); -+ if(err <= 0) -+ goto out_up; -+ } -+ else { -+ n = write_chan(&line->chan_list, buf, len, -+ line->driver->write_irq); -+ if(n < 0){ -+ ret = n; -+ goto out_up; -+ } -+ -+ len -= n; -+ ret += n; -+ if(len > 0) -+ ret += buffer_data(line, buf + n, len); -+ } -+ out_up: -+ up(&line->sem); -+ -+ out_free: -+ if(from_user) -+ kfree(buf); -+ return(ret); -+} -+ -+static void line_write_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct line *dev = data; -+ struct tty_struct *tty = dev->tty; -+ int err; -+ -+ err = flush_buffer(dev); -+ if(err == 0) return; -+ else if(err < 0){ -+ dev->head = dev->buffer; -+ dev->tail = dev->buffer; -+ } -+ -+ if(tty == NULL) return; -+ -+ if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && -+ (tty->ldisc.write_wakeup != NULL)) -+ (tty->ldisc.write_wakeup)(tty); -+ -+ /* BLOCKING mode -+ * In blocking mode, everything sleeps on tty->write_wait. -+ * Sleeping in the console driver would break non-blocking -+ * writes. -+ */ -+ -+ if (waitqueue_active(&tty->write_wait)) -+ wake_up_interruptible(&tty->write_wait); -+ -+} -+ -+int line_setup_irq(int fd, int input, int output, void *data) -+{ -+ struct line *line = data; -+ struct line_driver *driver = line->driver; -+ int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; -+ -+ if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, -+ line_interrupt, flags, -+ driver->read_irq_name, line); -+ if(err) return(err); -+ if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, -+ line_write_interrupt, flags, -+ driver->write_irq_name, line); -+ line->have_irq = 1; -+ return(err); -+} -+ -+void line_disable(struct line *line, int current_irq) -+{ -+ if(!line->have_irq) return; -+ -+ if(line->driver->read_irq == current_irq) -+ free_irq_later(line->driver->read_irq, line); -+ else -+ free_irq(line->driver->read_irq, line); -+ -+ if(line->driver->write_irq == current_irq) -+ free_irq_later(line->driver->write_irq, line); -+ else -+ free_irq(line->driver->write_irq, line); -+ -+ line->have_irq = 0; -+} -+ -+int line_open(struct line *lines, struct tty_struct *tty, -+ struct chan_opts *opts) -+{ -+ struct line *line; -+ int n, err = 0; -+ -+ if(tty == NULL) n = 0; -+ else n = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[n]; -+ -+ down(&line->sem); -+ if(line->count == 0){ -+ if(!line->valid){ -+ err = -ENODEV; -+ goto out; -+ } -+ if(list_empty(&line->chan_list)){ -+ err = parse_chan_pair(line->init_str, &line->chan_list, -+ line->init_pri, n, opts); -+ if(err) goto out; -+ err = open_chan(&line->chan_list); -+ if(err) goto out; -+ } -+ enable_chan(&line->chan_list, line); -+ INIT_TQUEUE(&line->task, line_timer_cb, line); -+ } -+ -+ if(!line->sigio){ -+ chan_enable_winch(&line->chan_list, line); -+ line->sigio = 1; -+ } -+ -+ /* This is outside the if because the initial console is opened -+ * with tty == NULL -+ */ -+ line->tty = tty; -+ -+ if(tty != NULL){ -+ tty->driver_data = line; -+ chan_window_size(&line->chan_list, &tty->winsize.ws_row, -+ &tty->winsize.ws_col); -+ } -+ -+ line->count++; -+ out: -+ up(&line->sem); -+ return(err); -+} -+ -+void line_close(struct line *lines, struct tty_struct *tty) -+{ -+ struct line *line; -+ int n; -+ -+ if(tty == NULL) n = 0; -+ else n = minor(tty->device) - tty->driver.minor_start; -+ line = &lines[n]; -+ -+ down(&line->sem); -+ line->count--; -+ -+ /* I don't like this, but I can't think of anything better. What's -+ * going on is that the tty is in the process of being closed for -+ * the last time. Its count hasn't been dropped yet, so it's still -+ * at 1. This may happen when line->count != 0 because of the initial -+ * console open (without a tty) bumping it up to 1. -+ */ -+ if((line->tty != NULL) && (line->tty->count == 1)) -+ line->tty = NULL; -+ if(line->count == 0) -+ line_disable(line, -1); -+ up(&line->sem); -+} -+ -+void close_lines(struct line *lines, int nlines) -+{ -+ int i; -+ -+ for(i = 0; i < nlines; i++) -+ close_chan(&lines[i].chan_list); -+} -+ -+int line_setup(struct line *lines, int num, char *init, int all_allowed) -+{ -+ int i, n; -+ char *end; -+ -+ if(*init == '=') n = -1; -+ else { -+ n = simple_strtoul(init, &end, 0); -+ if(*end != '='){ -+ printk(KERN_ERR "line_setup failed to parse \"%s\"\n", -+ init); -+ return(0); -+ } -+ init = end; -+ } -+ init++; -+ if((n >= 0) && (n >= num)){ -+ printk("line_setup - %d out of range ((0 ... %d) allowed)\n", -+ n, num); -+ return(0); -+ } -+ else if(n >= 0){ -+ if(lines[n].count > 0){ -+ printk("line_setup - device %d is open\n", n); -+ return(0); -+ } -+ if(lines[n].init_pri <= INIT_ONE){ -+ lines[n].init_pri = INIT_ONE; -+ if(!strcmp(init, "none")) lines[n].valid = 0; -+ else { -+ lines[n].init_str = init; -+ lines[n].valid = 1; -+ } -+ } -+ } -+ else if(!all_allowed){ -+ printk("line_setup - can't configure all devices from " -+ "mconsole\n"); -+ return(0); -+ } -+ else { -+ for(i = 0; i < num; i++){ -+ if(lines[i].init_pri <= INIT_ALL){ -+ lines[i].init_pri = INIT_ALL; -+ if(!strcmp(init, "none")) lines[i].valid = 0; -+ else { -+ lines[i].init_str = init; -+ lines[i].valid = 1; -+ } -+ } -+ } -+ } -+ return(1); -+} -+ -+int line_config(struct line *lines, int num, char *str) -+{ -+ char *new = uml_strdup(str); -+ -+ if(new == NULL){ -+ printk("line_config - uml_strdup failed\n"); -+ return(-ENOMEM); -+ } -+ return(!line_setup(lines, num, new, 0)); -+} -+ -+int line_get_config(char *name, struct line *lines, int num, char *str, -+ int size, char **error_out) -+{ -+ struct line *line; -+ char *end; -+ int dev, n = 0; -+ -+ dev = simple_strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ *error_out = "line_get_config failed to parse device number"; -+ return(0); -+ } -+ -+ if((dev < 0) || (dev >= num)){ -+ *error_out = "device number of of range"; -+ return(0); -+ } -+ -+ line = &lines[dev]; -+ -+ down(&line->sem); -+ if(!line->valid) -+ CONFIG_CHUNK(str, size, n, "none", 1); -+ else if(line->count == 0) -+ CONFIG_CHUNK(str, size, n, line->init_str, 1); -+ else n = chan_config_string(&line->chan_list, str, size, error_out); -+ up(&line->sem); -+ -+ return(n); -+} -+ -+int line_remove(struct line *lines, int num, char *str) -+{ -+ char config[sizeof("conxxxx=none\0")]; -+ -+ sprintf(config, "%s=none", str); -+ return(!line_setup(lines, num, config, 0)); -+} -+ -+static int line_write_room(struct tty_struct *tty) -+{ -+ struct line *dev = tty->driver_data; -+ -+ return(write_room(dev)); -+} -+ -+void line_register_devfs(struct lines *set, struct line_driver *line_driver, -+ struct tty_driver *driver, struct line *lines, -+ int nlines) -+{ -+ int err, i, n; -+ char *from, *to; -+ -+ driver->driver_name = line_driver->name; -+ driver->name = line_driver->devfs_name; -+ driver->major = line_driver->major; -+ driver->minor_start = line_driver->minor_start; -+ driver->type = line_driver->type; -+ driver->subtype = line_driver->subtype; -+ driver->magic = TTY_DRIVER_MAGIC; -+ driver->flags = TTY_DRIVER_REAL_RAW; -+ -+ n = set->num; -+ driver->num = n; -+ driver->table = kmalloc(n * sizeof(driver->table[0]), GFP_KERNEL); -+ driver->termios = kmalloc(n * sizeof(driver->termios[0]), GFP_KERNEL); -+ driver->termios_locked = kmalloc(n * sizeof(driver->termios_locked[0]), -+ GFP_KERNEL); -+ if((driver->table == NULL) || (driver->termios == NULL) || -+ (driver->termios_locked == NULL)) -+ panic("Failed to allocate driver table"); -+ -+ memset(driver->table, 0, n * sizeof(driver->table[0])); -+ memset(driver->termios, 0, n * sizeof(driver->termios[0])); -+ memset(driver->termios_locked, 0, -+ n * sizeof(driver->termios_locked[0])); -+ -+ driver->write_room = line_write_room; -+ driver->init_termios = tty_std_termios; -+ -+ if (tty_register_driver(driver)) -+ panic("line_register_devfs : Couldn't register driver\n"); -+ -+ from = line_driver->symlink_from; -+ to = line_driver->symlink_to; -+ err = devfs_mk_symlink(NULL, from, 0, to, NULL, NULL); -+ if(err) printk("Symlink creation from /dev/%s to /dev/%s " -+ "returned %d\n", from, to, err); -+ -+ for(i = 0; i < nlines; i++){ -+ if(!lines[i].valid) -+ tty_unregister_devfs(driver, driver->minor_start + i); -+ } -+ -+ mconsole_register_dev(&line_driver->mc); -+} -+ -+void lines_init(struct line *lines, int nlines) -+{ -+ struct line *line; -+ int i; -+ -+ for(i = 0; i < nlines; i++){ -+ line = &lines[i]; -+ INIT_LIST_HEAD(&line->chan_list); -+ sema_init(&line->sem, 1); -+ if(line->init_str != NULL){ -+ line->init_str = uml_strdup(line->init_str); -+ if(line->init_str == NULL) -+ printk("lines_init - uml_strdup returned " -+ "NULL\n"); -+ } -+ } -+} -+ -+struct winch { -+ struct list_head list; -+ int fd; -+ int tty_fd; -+ int pid; -+ struct line *line; -+}; -+ -+void winch_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ struct winch *winch = data; -+ struct tty_struct *tty; -+ int err; -+ char c; -+ -+ if(winch->fd != -1){ -+ err = generic_read(winch->fd, &c, NULL); -+ if(err < 0){ -+ if(err != -EAGAIN){ -+ printk("winch_interrupt : read failed, " -+ "errno = %d\n", -err); -+ printk("fd %d is losing SIGWINCH support\n", -+ winch->tty_fd); -+ return; -+ } -+ goto out; -+ } -+ } -+ tty = winch->line->tty; -+ if(tty != NULL){ -+ chan_window_size(&winch->line->chan_list, -+ &tty->winsize.ws_row, -+ &tty->winsize.ws_col); -+ kill_pg(tty->pgrp, SIGWINCH, 1); -+ } -+ out: -+ if(winch->fd != -1) -+ reactivate_fd(winch->fd, WINCH_IRQ); -+} -+ -+DECLARE_MUTEX(winch_handler_sem); -+LIST_HEAD(winch_handlers); -+ -+void register_winch_irq(int fd, int tty_fd, int pid, void *line) -+{ -+ struct winch *winch; -+ -+ down(&winch_handler_sem); -+ winch = kmalloc(sizeof(*winch), GFP_KERNEL); -+ if(winch == NULL){ -+ printk("register_winch_irq - kmalloc failed\n"); -+ goto out; -+ } -+ *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), -+ .fd = fd, -+ .tty_fd = tty_fd, -+ .pid = pid, -+ .line = line }); -+ list_add(&winch->list, &winch_handlers); -+ if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "winch", winch) < 0) -+ printk("register_winch_irq - failed to register IRQ\n"); -+ out: -+ up(&winch_handler_sem); -+} -+ -+static void winch_cleanup(void) -+{ -+ struct list_head *ele; -+ struct winch *winch; -+ -+ list_for_each(ele, &winch_handlers){ -+ winch = list_entry(ele, struct winch, list); -+ if(winch->fd != -1){ -+ deactivate_fd(winch->fd, WINCH_IRQ); -+ os_close_file(winch->fd); -+ } -+ if(winch->pid != -1) -+ os_kill_process(winch->pid, 1); -+ } -+} -+ -+__uml_exitcall(winch_cleanup); -+ -+char *add_xterm_umid(char *base) -+{ -+ char *umid, *title; -+ int len; -+ -+ umid = get_umid(1); -+ if(umid == NULL) return(base); -+ -+ len = strlen(base) + strlen(" ()") + strlen(umid) + 1; -+ title = kmalloc(len, GFP_KERNEL); -+ if(title == NULL){ -+ printk("Failed to allocate buffer for xterm title\n"); -+ return(base); -+ } -+ -+ strncpy(title, base, len); -+ len -= strlen(title); -+ snprintf(&title[strlen(title)], len, " (%s)", umid); -+ return(title); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/Makefile 2005-05-03 22:28:14.215449136 +0300 -@@ -0,0 +1,97 @@ -+# -+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := built-in.o -+ -+CHAN_OBJS := chan_kern.o chan_user.o line.o -+ -+list-multi := slip.o slirp.o daemon.o mcast.o mconsole.o net.o ubd.o \ -+ hostaudio.o pcap.o port.o harddog.o -+ -+slip-objs := slip_kern.o slip_user.o -+slirp-objs := slirp_kern.o slirp_user.o -+daemon-objs := daemon_kern.o daemon_user.o -+mcast-objs := mcast_kern.o mcast_user.o -+pcap-objs := pcap_kern.o pcap_user.o -+pcap-libs := -lpcap -L/usr/lib -+net-objs := net_kern.o net_user.o -+mconsole-objs := mconsole_kern.o mconsole_user.o -+hostaudio-objs := hostaudio_kern.o -+ubd-objs := ubd_kern.o ubd_user.o -+port-objs := port_kern.o port_user.o -+harddog-objs := harddog_kern.o harddog_user.o -+ -+export-objs := mconsole_kern.o -+ -+obj-y = -+obj-$(CONFIG_SSL) += ssl.o -+obj-$(CONFIG_UML_NET_SLIP) += slip.o -+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o -+obj-$(CONFIG_UML_NET_DAEMON) += daemon.o -+obj-$(CONFIG_UML_NET_MCAST) += mcast.o -+obj-$(CONFIG_UML_NET_PCAP) += pcap.o -+obj-$(CONFIG_UML_NET) += net.o -+obj-$(CONFIG_MCONSOLE) += mconsole.o -+obj-$(CONFIG_MMAPPER) += mmapper_kern.o -+obj-$(CONFIG_BLK_DEV_UBD) += ubd.o -+obj-$(CONFIG_HOSTAUDIO) += hostaudio.o -+obj-$(CONFIG_FD_CHAN) += fd.o -+obj-$(CONFIG_NULL_CHAN) += null.o -+obj-$(CONFIG_PORT_CHAN) += port.o -+obj-$(CONFIG_PTY_CHAN) += pty.o -+obj-$(CONFIG_TTY_CHAN) += tty.o -+obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o -+obj-$(CONFIG_UML_WATCHDOG) += harddog.o -+obj-$(CONFIG_COW) += cow_kern.o -+obj-$(CONFIG_COW_COMMON) += cow_user.o -+ -+CFLAGS_pcap_user.o = -I/usr/include/pcap -+ -+obj-y += stdio_console.o $(CHAN_OBJS) -+ -+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \ -+ null.o pty.o tty.o xterm.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean: -+ -+modules: -+ -+fastdep: -+ -+dep: -+ -+archmrproper: -+ -+daemon.o : $(daemon-objs) -+ -+slip.o : $(slip-objs) -+ -+slirp.o : $(slirp-objs) -+ -+mcast.o : $(mcast-objs) -+ -+pcap.o : $(pcap-objs) -+ -+mconsole.o : $(mconsole-objs) -+ -+net.o : $(net-objs) -+ -+hostaudio.o : $(hostaudio-objs) -+ -+ubd.o : $(ubd-objs) -+ -+port.o : $(port-objs) -+ -+harddog.o : $(harddog-objs) -+ -+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)' -+ $(LD) -r -o $@ $($(patsubst %.o,%,$@)-objs) $($(patsubst %.o,%,$@)-libs) -Index: linux-2.4.29/arch/um/drivers/mcast.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/mcast.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/mcast.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct mcast_data { -+ char *addr; -+ unsigned short port; -+ void *mcast_addr; -+ int ttl; -+ void *dev; -+}; -+ -+extern struct net_user_info mcast_user_info; -+ -+extern int mcast_user_write(int fd, void *buf, int len, -+ struct mcast_data *pri); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/mcast_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/mcast_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/mcast_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,145 @@ -+/* -+ * user-mode-linux networking multicast transport -+ * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> -+ * -+ * based on the existing uml-networking code, which is -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/in.h" -+#include "linux/inet.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "mcast.h" -+ -+struct mcast_init { -+ char *addr; -+ int port; -+ int ttl; -+}; -+ -+void mcast_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct mcast_data *dpri; -+ struct mcast_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ dpri = (struct mcast_data *) pri->user; -+ *dpri = ((struct mcast_data) -+ { .addr = init->addr, -+ .port = init->port, -+ .ttl = init->ttl, -+ .mcast_addr = NULL, -+ .dev = dev }); -+ printk("mcast backend "); -+ printk("multicast adddress: %s:%u, TTL:%u ", -+ dpri->addr, dpri->port, dpri->ttl); -+ -+ printk("\n"); -+} -+ -+static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int mcast_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return mcast_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct mcast_data *) &lp->user); -+} -+ -+static struct net_kern_info mcast_kern_info = { -+ .init = mcast_init, -+ .protocol = eth_protocol, -+ .read = mcast_read, -+ .write = mcast_write, -+}; -+ -+int mcast_setup(char *str, char **mac_out, void *data) -+{ -+ struct mcast_init *init = data; -+ char *port_str = NULL, *ttl_str = NULL, *remain; -+ char *last; -+ int n; -+ -+ *init = ((struct mcast_init) -+ { .addr = "239.192.168.1", -+ .port = 1102, -+ .ttl = 1 }); -+ -+ remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, -+ NULL); -+ if(remain != NULL){ -+ printk(KERN_ERR "mcast_setup - Extra garbage on " -+ "specification : '%s'\n", remain); -+ return(0); -+ } -+ -+ if(port_str != NULL){ -+ n = simple_strtoul(port_str, &last, 10); -+ if((*last != '\0') || (last == port_str)){ -+ printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", -+ port_str); -+ return(0); -+ } -+ init->port = htons(n); -+ } -+ -+ if(ttl_str != NULL){ -+ init->ttl = simple_strtoul(ttl_str, &last, 10); -+ if((*last != '\0') || (last == ttl_str)){ -+ printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", -+ ttl_str); -+ return(0); -+ } -+ } -+ -+ printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, -+ init->port, init->ttl); -+ -+ return(1); -+} -+ -+static struct transport mcast_transport = { -+ .list = LIST_HEAD_INIT(mcast_transport.list), -+ .name = "mcast", -+ .setup = mcast_setup, -+ .user = &mcast_user_info, -+ .kern = &mcast_kern_info, -+ .private_size = sizeof(struct mcast_data), -+ .setup_size = sizeof(struct mcast_init), -+}; -+ -+static int register_mcast(void) -+{ -+ register_transport(&mcast_transport); -+ return(1); -+} -+ -+__initcall(register_mcast); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/mcast_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/mcast_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/mcast_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,177 @@ -+/* -+ * user-mode-linux networking multicast transport -+ * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> -+ * -+ * based on the existing uml-networking code, which is -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * -+ * Licensed under the GPL. -+ * -+ */ -+ -+#include <errno.h> -+#include <unistd.h> -+#include <linux/inet.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/time.h> -+#include <netinet/in.h> -+#include "net_user.h" -+#include "mcast.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+static struct sockaddr_in *new_addr(char *addr, unsigned short port) -+{ -+ struct sockaddr_in *sin; -+ -+ sin = um_kmalloc(sizeof(struct sockaddr_in)); -+ if(sin == NULL){ -+ printk("new_addr: allocation of sockaddr_in failed\n"); -+ return(NULL); -+ } -+ sin->sin_family = AF_INET; -+ sin->sin_addr.s_addr = in_aton(addr); -+ sin->sin_port = port; -+ return(sin); -+} -+ -+static void mcast_user_init(void *data, void *dev) -+{ -+ struct mcast_data *pri = data; -+ -+ pri->mcast_addr = new_addr(pri->addr, pri->port); -+ pri->dev = dev; -+} -+ -+static int mcast_open(void *data) -+{ -+ struct mcast_data *pri = data; -+ struct sockaddr_in *sin = pri->mcast_addr; -+ struct ip_mreq mreq; -+ int fd, yes = 1; -+ -+ -+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) { -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ fd = socket(AF_INET, SOCK_DGRAM, 0); -+ if (fd < 0){ -+ printk("mcast_open : data socket failed, errno = %d\n", -+ errno); -+ fd = -ENOMEM; -+ goto out; -+ } -+ -+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { -+ printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", -+ errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* set ttl according to config */ -+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, -+ sizeof(pri->ttl)) < 0) { -+ printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", -+ errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* set LOOP, so data does get fed back to local sockets */ -+ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { -+ printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", -+ errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* bind socket to mcast address */ -+ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { -+ printk("mcast_open : data bind failed, errno = %d\n", errno); -+ os_close_file(fd); -+ fd = -EINVAL; -+ goto out; -+ } -+ -+ /* subscribe to the multicast group */ -+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; -+ mreq.imr_interface.s_addr = 0; -+ if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, -+ &mreq, sizeof(mreq)) < 0) { -+ printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", -+ errno); -+ printk("There appears not to be a multicast-capable network " -+ "interface on the host.\n"); -+ printk("eth0 should be configured in order to use the " -+ "multicast transport.\n"); -+ os_close_file(fd); -+ fd = -EINVAL; -+ } -+ -+ out: -+ return(fd); -+} -+ -+static void mcast_close(int fd, void *data) -+{ -+ struct ip_mreq mreq; -+ struct mcast_data *pri = data; -+ struct sockaddr_in *sin = pri->mcast_addr; -+ -+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; -+ mreq.imr_interface.s_addr = 0; -+ if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, -+ &mreq, sizeof(mreq)) < 0) { -+ printk("mcast_open: IP_DROP_MEMBERSHIP failed, error = %d\n", -+ errno); -+ } -+ -+ os_close_file(fd); -+} -+ -+int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) -+{ -+ struct sockaddr_in *data_addr = pri->mcast_addr; -+ -+ return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); -+} -+ -+static int mcast_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info mcast_user_info = { -+ .init = mcast_user_init, -+ .open = mcast_open, -+ .close = mcast_close, -+ .remove = NULL, -+ .set_mtu = mcast_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/mconsole_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/mconsole_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/mconsole_kern.c 2005-05-03 22:28:14.222448072 +0300 -@@ -0,0 +1,560 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/slab.h" -+#include "linux/init.h" -+#include "linux/notifier.h" -+#include "linux/reboot.h" -+#include "linux/utsname.h" -+#include "linux/ctype.h" -+#include "linux/interrupt.h" -+#include "linux/sysrq.h" -+#include "linux/tqueue.h" -+#include "linux/module.h" -+#include "linux/file.h" -+#include "linux/fs.h" -+#include "linux/proc_fs.h" -+#include "asm/irq.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mconsole.h" -+#include "mconsole_kern.h" -+#include "irq_user.h" -+#include "init.h" -+#include "os.h" -+#include "umid.h" -+#include "irq_kern.h" -+ -+static int do_unlink_socket(struct notifier_block *notifier, -+ unsigned long what, void *data) -+{ -+ return(mconsole_unlink_socket()); -+} -+ -+ -+static struct notifier_block reboot_notifier = { -+ .notifier_call = do_unlink_socket, -+ .priority = 0, -+}; -+ -+/* Safe without explicit locking for now. Tasklets provide their own -+ * locking, and the interrupt handler is safe because it can't interrupt -+ * itself and it can only happen on CPU 0. -+ */ -+ -+LIST_HEAD(mc_requests); -+ -+static void mc_task_proc(void *unused) -+{ -+ struct mconsole_entry *req; -+ unsigned long flags; -+ -+ while(!list_empty(&mc_requests)){ -+ local_irq_save(flags); -+ req = list_entry(mc_requests.next, struct mconsole_entry, -+ list); -+ list_del(&req->list); -+ local_irq_restore(flags); -+ req->request.cmd->handler(&req->request); -+ kfree(req); -+ } -+} -+ -+struct tq_struct mconsole_task = { -+ .routine = mc_task_proc, -+ .data = NULL -+}; -+ -+static void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ int fd; -+ struct mconsole_entry *new; -+ struct mc_request req; -+ -+ fd = (int) dev_id; -+ while (mconsole_get_request(fd, &req)){ -+ if(req.cmd->context == MCONSOLE_INTR) -+ (*req.cmd->handler)(&req); -+ else { -+ new = kmalloc(sizeof(*new), GFP_ATOMIC); -+ if(new == NULL) -+ mconsole_reply(&req, "Out of memory", 1, 0); -+ else { -+ new->request = req; -+ list_add(&new->list, &mc_requests); -+ } -+ } -+ } -+ -+ if(!list_empty(&mc_requests)) -+ schedule_task(&mconsole_task); -+ reactivate_fd(fd, MCONSOLE_IRQ); -+} -+ -+void mconsole_version(struct mc_request *req) -+{ -+ char version[256]; -+ -+ sprintf(version, "%s %s %s %s %s", system_utsname.sysname, -+ system_utsname.nodename, system_utsname.release, -+ system_utsname.version, system_utsname.machine); -+ mconsole_reply(req, version, 0, 0); -+} -+ -+void mconsole_log(struct mc_request *req) -+{ -+ int len; -+ char *ptr = req->request.data; -+ -+ ptr += strlen("log "); -+ -+ len = req->len - (ptr - req->request.data); -+ printk("%.*s", len, ptr); -+ mconsole_reply(req, "", 0, 0); -+} -+ -+void mconsole_proc(struct mc_request *req) -+{ -+ struct nameidata nd; -+ struct file_system_type *proc; -+ struct super_block *super; -+ struct file *file; -+ int n, err; -+ char *ptr = req->request.data, *buf; -+ -+ ptr += strlen("proc"); -+ while(isspace(*ptr)) ptr++; -+ -+ proc = get_fs_type("proc"); -+ if(proc == NULL){ -+ mconsole_reply(req, "procfs not registered", 1, 0); -+ goto out; -+ } -+ -+ super = get_anon_super(proc, NULL, NULL); -+ if(super == NULL){ -+ mconsole_reply(req, "Failed to get procfs superblock", 1, 0); -+ goto out_put; -+ } -+ -+ if(super->s_root == NULL){ -+ super = (*proc->read_super)(super, NULL, 0); -+ if(super == NULL){ -+ mconsole_reply(req, "Failed to read superblock", 1, 0); -+ goto out_put; -+ } -+ } -+ up_write(&super->s_umount); -+ -+ nd.dentry = super->s_root; -+ nd.mnt = NULL; -+ nd.flags = O_RDONLY + 1; -+ nd.last_type = LAST_ROOT; -+ -+ err = link_path_walk(ptr, &nd); -+ if(err){ -+ mconsole_reply(req, "Failed to look up file", 1, 0); -+ goto out_kill; -+ } -+ -+ file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ if(IS_ERR(file)){ -+ mconsole_reply(req, "Failed to open file", 1, 0); -+ goto out_kill; -+ } -+ -+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ if(buf == NULL){ -+ mconsole_reply(req, "Failed to allocate buffer", 1, 0); -+ goto out_fput; -+ } -+ -+ if((file->f_op != NULL) && (file->f_op->read != NULL)){ -+ do { -+ n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, -+ &file->f_pos); -+ if(n >= 0){ -+ buf[n] = '\0'; -+ mconsole_reply(req, buf, 0, (n > 0)); -+ } -+ else { -+ mconsole_reply(req, "Read of file failed", -+ 1, 0); -+ goto out_free; -+ } -+ } while(n > 0); -+ } -+ else mconsole_reply(req, "", 0, 0); -+ -+ out_free: -+ kfree(buf); -+ out_fput: -+ fput(file); -+ out_kill: -+ kill_super(super); -+ out_put: -+ /* put_filesystem(proc); */ -+ out: ; -+} -+ -+#define UML_MCONSOLE_HELPTEXT \ -+"Commands: \n\ -+ version - Get kernel version \n\ -+ help - Print this message \n\ -+ halt - Halt UML \n\ -+ reboot - Reboot UML \n\ -+ config <dev>=<config> - Add a new device to UML; \n\ -+ same syntax as command line \n\ -+ config <dev> - Query the configuration of a device \n\ -+ remove <dev> - Remove a device from UML \n\ -+ sysrq <letter> - Performs the SysRq action controlled by the letter \n\ -+ cad - invoke the Ctl-Alt-Del handler \n\ -+ stop - pause the UML; it will do nothing until it receives a 'go' \n\ -+ go - continue the UML after a 'stop' \n\ -+ log <string> - make UML enter <string> into the kernel log\n\ -+ proc <file> - returns the contents of the UML's /proc/<file>\n\ -+" -+ -+void mconsole_help(struct mc_request *req) -+{ -+ mconsole_reply(req, UML_MCONSOLE_HELPTEXT, 0, 0); -+} -+ -+void mconsole_halt(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ machine_halt(); -+} -+ -+void mconsole_reboot(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ machine_restart(NULL); -+} -+ -+extern void ctrl_alt_del(void); -+ -+void mconsole_cad(struct mc_request *req) -+{ -+ mconsole_reply(req, "", 0, 0); -+ ctrl_alt_del(); -+} -+ -+void mconsole_go(struct mc_request *req) -+{ -+ mconsole_reply(req, "Not stopped", 1, 0); -+} -+ -+void mconsole_stop(struct mc_request *req) -+{ -+ deactivate_fd(req->originating_fd, MCONSOLE_IRQ); -+ os_set_fd_block(req->originating_fd, 1); -+ mconsole_reply(req, "", 0, 0); -+ while(mconsole_get_request(req->originating_fd, req)){ -+ if(req->cmd->handler == mconsole_go) break; -+ (*req->cmd->handler)(req); -+ } -+ os_set_fd_block(req->originating_fd, 0); -+ reactivate_fd(req->originating_fd, MCONSOLE_IRQ); -+ mconsole_reply(req, "", 0, 0); -+} -+ -+/* This list is populated by __initcall routines. */ -+ -+LIST_HEAD(mconsole_devices); -+ -+void mconsole_register_dev(struct mc_device *new) -+{ -+ list_add(&new->list, &mconsole_devices); -+} -+ -+static struct mc_device *mconsole_find_dev(char *name) -+{ -+ struct list_head *ele; -+ struct mc_device *dev; -+ -+ list_for_each(ele, &mconsole_devices){ -+ dev = list_entry(ele, struct mc_device, list); -+ if(!strncmp(name, dev->name, strlen(dev->name))) -+ return(dev); -+ } -+ return(NULL); -+} -+ -+#define CONFIG_BUF_SIZE 64 -+ -+static void mconsole_get_config(int (*get_config)(char *, char *, int, -+ char **), -+ struct mc_request *req, char *name) -+{ -+ char default_buf[CONFIG_BUF_SIZE], *error, *buf; -+ int n, size; -+ -+ if(get_config == NULL){ -+ mconsole_reply(req, "No get_config routine defined", 1, 0); -+ return; -+ } -+ -+ error = NULL; -+ size = sizeof(default_buf)/sizeof(default_buf[0]); -+ buf = default_buf; -+ -+ while(1){ -+ n = (*get_config)(name, buf, size, &error); -+ if(error != NULL){ -+ mconsole_reply(req, error, 1, 0); -+ goto out; -+ } -+ -+ if(n <= size){ -+ mconsole_reply(req, buf, 0, 0); -+ goto out; -+ } -+ -+ if(buf != default_buf) -+ kfree(buf); -+ -+ size = n; -+ buf = kmalloc(size, GFP_KERNEL); -+ if(buf == NULL){ -+ mconsole_reply(req, "Failed to allocate buffer", 1, 0); -+ return; -+ } -+ } -+ out: -+ if(buf != default_buf) -+ kfree(buf); -+ -+} -+ -+void mconsole_config(struct mc_request *req) -+{ -+ struct mc_device *dev; -+ char *ptr = req->request.data, *name; -+ int err; -+ -+ ptr += strlen("config"); -+ while(isspace(*ptr)) ptr++; -+ dev = mconsole_find_dev(ptr); -+ if(dev == NULL){ -+ mconsole_reply(req, "Bad configuration option", 1, 0); -+ return; -+ } -+ -+ name = &ptr[strlen(dev->name)]; -+ ptr = name; -+ while((*ptr != '=') && (*ptr != '\0')) -+ ptr++; -+ -+ if(*ptr == '='){ -+ err = (*dev->config)(name); -+ mconsole_reply(req, "", err, 0); -+ } -+ else mconsole_get_config(dev->get_config, req, name); -+} -+ -+void mconsole_remove(struct mc_request *req) -+{ -+ struct mc_device *dev; -+ char *ptr = req->request.data; -+ int err; -+ -+ ptr += strlen("remove"); -+ while(isspace(*ptr)) ptr++; -+ dev = mconsole_find_dev(ptr); -+ if(dev == NULL){ -+ mconsole_reply(req, "Bad remove option", 1, 0); -+ return; -+ } -+ err = (*dev->remove)(&ptr[strlen(dev->name)]); -+ mconsole_reply(req, "", err, 0); -+} -+ -+#ifdef CONFIG_MAGIC_SYSRQ -+void mconsole_sysrq(struct mc_request *req) -+{ -+ char *ptr = req->request.data; -+ -+ ptr += strlen("sysrq"); -+ while(isspace(*ptr)) ptr++; -+ -+ mconsole_reply(req, "", 0, 0); -+ handle_sysrq(*ptr, ¤t->thread.regs, NULL, NULL); -+} -+#else -+void mconsole_sysrq(struct mc_request *req) -+{ -+ mconsole_reply(req, "Sysrq not compiled in", 1, 0); -+} -+#endif -+ -+/* Changed by mconsole_setup, which is __setup, and called before SMP is -+ * active. -+ */ -+static char *notify_socket = NULL; -+ -+int mconsole_init(void) -+{ -+ int err, sock; -+ char file[256]; -+ -+ if(umid_file_name("mconsole", file, sizeof(file))) return(-1); -+ snprintf(mconsole_socket_name, sizeof(file), "%s", file); -+ -+ sock = os_create_unix_socket(file, sizeof(file), 1); -+ if (sock < 0){ -+ printk("Failed to initialize management console\n"); -+ return(1); -+ } -+ -+ register_reboot_notifier(&reboot_notifier); -+ -+ err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "mconsole", (void *)sock); -+ if (err){ -+ printk("Failed to get IRQ for management console\n"); -+ return(1); -+ } -+ -+ if(notify_socket != NULL){ -+ notify_socket = uml_strdup(notify_socket); -+ if(notify_socket != NULL) -+ mconsole_notify(notify_socket, MCONSOLE_SOCKET, -+ mconsole_socket_name, -+ strlen(mconsole_socket_name) + 1); -+ else printk(KERN_ERR "mconsole_setup failed to strdup " -+ "string\n"); -+ } -+ -+ printk("mconsole (version %d) initialized on %s\n", -+ MCONSOLE_VERSION, mconsole_socket_name); -+ return(0); -+} -+ -+__initcall(mconsole_init); -+ -+static int write_proc_mconsole(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char *buf; -+ -+ buf = kmalloc(count + 1, GFP_KERNEL); -+ if(buf == NULL) -+ return(-ENOMEM); -+ -+ if(copy_from_user(buf, buffer, count)){ -+ count = -EFAULT; -+ goto out; -+ } -+ -+ buf[count] = '\0'; -+ -+ mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); -+ out: -+ kfree(buf); -+ return(count); -+} -+ -+static int create_proc_mconsole(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ if(notify_socket == NULL) return(0); -+ -+ ent = create_proc_entry("mconsole", S_IFREG | 0200, NULL); -+ if(ent == NULL){ -+ printk("create_proc_mconsole : create_proc_entry failed\n"); -+ return(0); -+ } -+ -+ ent->read_proc = NULL; -+ ent->write_proc = write_proc_mconsole; -+ return(0); -+} -+ -+static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED; -+ -+void lock_notify(void) -+{ -+ spin_lock(¬ify_spinlock); -+} -+ -+void unlock_notify(void) -+{ -+ spin_unlock(¬ify_spinlock); -+} -+ -+__initcall(create_proc_mconsole); -+ -+#define NOTIFY "=notify:" -+ -+static int mconsole_setup(char *str) -+{ -+ if(!strncmp(str, NOTIFY, strlen(NOTIFY))){ -+ str += strlen(NOTIFY); -+ notify_socket = str; -+ } -+ else printk(KERN_ERR "mconsole_setup : Unknown option - '%s'\n", str); -+ return(1); -+} -+ -+__setup("mconsole", mconsole_setup); -+ -+__uml_help(mconsole_setup, -+"mconsole=notify:<socket>\n" -+" Requests that the mconsole driver send a message to the named Unix\n" -+" socket containing the name of the mconsole socket. This also serves\n" -+" to notify outside processes when UML has booted far enough to respond\n" -+" to mconsole requests.\n\n" -+); -+ -+static int notify_panic(struct notifier_block *self, unsigned long unused1, -+ void *ptr) -+{ -+ char *message = ptr; -+ -+ if(notify_socket == NULL) return(0); -+ -+ mconsole_notify(notify_socket, MCONSOLE_PANIC, message, -+ strlen(message) + 1); -+ return(0); -+} -+ -+static struct notifier_block panic_exit_notifier = { -+ .notifier_call = notify_panic, -+ .next = NULL, -+ .priority = 1 -+}; -+ -+static int add_notifier(void) -+{ -+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); -+ return(0); -+} -+ -+__initcall(add_notifier); -+ -+char *mconsole_notify_socket(void) -+{ -+ return(notify_socket); -+} -+ -+EXPORT_SYMBOL(mconsole_notify_socket); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/mconsole_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/mconsole_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/mconsole_user.c 2005-05-03 22:28:14.223447920 +0300 -@@ -0,0 +1,215 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <sys/socket.h> -+#include <sys/types.h> -+#include <sys/uio.h> -+#include <sys/un.h> -+#include <unistd.h> -+#include "user.h" -+#include "mconsole.h" -+#include "umid.h" -+ -+static struct mconsole_command commands[] = { -+ { "version", mconsole_version, MCONSOLE_INTR }, -+ { "halt", mconsole_halt, MCONSOLE_PROC }, -+ { "reboot", mconsole_reboot, MCONSOLE_PROC }, -+ { "config", mconsole_config, MCONSOLE_PROC }, -+ { "remove", mconsole_remove, MCONSOLE_PROC }, -+ { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, -+ { "help", mconsole_help, MCONSOLE_INTR }, -+ { "cad", mconsole_cad, MCONSOLE_INTR }, -+ { "stop", mconsole_stop, MCONSOLE_PROC }, -+ { "go", mconsole_go, MCONSOLE_INTR }, -+ { "log", mconsole_log, MCONSOLE_INTR }, -+ { "proc", mconsole_proc, MCONSOLE_PROC }, -+}; -+ -+/* Initialized in mconsole_init, which is an initcall */ -+char mconsole_socket_name[256]; -+ -+int mconsole_reply_v0(struct mc_request *req, char *reply) -+{ -+ struct iovec iov; -+ struct msghdr msg; -+ -+ iov.iov_base = reply; -+ iov.iov_len = strlen(reply); -+ -+ msg.msg_name = &(req->origin); -+ msg.msg_namelen = req->originlen; -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ -+ return sendmsg(req->originating_fd, &msg, 0); -+} -+ -+static struct mconsole_command *mconsole_parse(struct mc_request *req) -+{ -+ struct mconsole_command *cmd; -+ int i; -+ -+ for(i=0;i<sizeof(commands)/sizeof(commands[0]);i++){ -+ cmd = &commands[i]; -+ if(!strncmp(req->request.data, cmd->command, -+ strlen(cmd->command))){ -+ return(cmd); -+ } -+ } -+ return(NULL); -+} -+ -+#define MIN(a,b) ((a)<(b) ? (a):(b)) -+ -+#define STRINGX(x) #x -+#define STRING(x) STRINGX(x) -+ -+int mconsole_get_request(int fd, struct mc_request *req) -+{ -+ int len; -+ -+ req->originlen = sizeof(req->origin); -+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0, -+ (struct sockaddr *) req->origin, &req->originlen); -+ if (req->len < 0) -+ return 0; -+ -+ req->originating_fd = fd; -+ -+ if(req->request.magic != MCONSOLE_MAGIC){ -+ /* Unversioned request */ -+ len = MIN(sizeof(req->request.data) - 1, -+ strlen((char *) &req->request)); -+ memmove(req->request.data, &req->request, len); -+ req->request.data[len] = '\0'; -+ -+ req->request.magic = MCONSOLE_MAGIC; -+ req->request.version = 0; -+ req->request.len = len; -+ -+ mconsole_reply_v0(req, "ERR Version 0 mconsole clients are " -+ "not supported by this driver"); -+ return(0); -+ } -+ -+ if(req->request.len >= MCONSOLE_MAX_DATA){ -+ mconsole_reply(req, "Request too large", 1, 0); -+ return(0); -+ } -+ if(req->request.version != MCONSOLE_VERSION){ -+ mconsole_reply(req, "This driver only supports version " -+ STRING(MCONSOLE_VERSION) " clients", 1, 0); -+ } -+ -+ req->request.data[req->request.len] = '\0'; -+ req->cmd = mconsole_parse(req); -+ if(req->cmd == NULL){ -+ mconsole_reply(req, "Unknown command", 1, 0); -+ return(0); -+ } -+ -+ return(1); -+} -+ -+int mconsole_reply(struct mc_request *req, char *str, int err, int more) -+{ -+ struct mconsole_reply reply; -+ int total, len, n; -+ -+ total = strlen(str); -+ do { -+ reply.err = err; -+ -+ /* err can only be true on the first packet */ -+ err = 0; -+ -+ len = MIN(total, MCONSOLE_MAX_DATA - 1); -+ -+ if(len == total) reply.more = more; -+ else reply.more = 1; -+ -+ memcpy(reply.data, str, len); -+ reply.data[len] = '\0'; -+ total -= len; -+ str += len; -+ reply.len = len + 1; -+ -+ len = sizeof(reply) + reply.len - sizeof(reply.data); -+ -+ n = sendto(req->originating_fd, &reply, len, 0, -+ (struct sockaddr *) req->origin, req->originlen); -+ -+ if(n < 0) return(-errno); -+ } while(total > 0); -+ return(0); -+} -+ -+int mconsole_unlink_socket(void) -+{ -+ unlink(mconsole_socket_name); -+ return 0; -+} -+ -+static int notify_sock = -1; -+ -+int mconsole_notify(char *sock_name, int type, const void *data, int len) -+{ -+ struct sockaddr_un target; -+ struct mconsole_notify packet; -+ int n, err = 0; -+ -+ lock_notify(); -+ if(notify_sock < 0){ -+ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); -+ if(notify_sock < 0){ -+ printk("mconsole_notify - socket failed, errno = %d\n", -+ errno); -+ err = -errno; -+ } -+ } -+ unlock_notify(); -+ -+ if(err) -+ return(err); -+ -+ target.sun_family = AF_UNIX; -+ strcpy(target.sun_path, sock_name); -+ -+ packet.magic = MCONSOLE_MAGIC; -+ packet.version = MCONSOLE_VERSION; -+ packet.type = type; -+ len = (len > sizeof(packet.data)) ? sizeof(packet.data) : len; -+ packet.len = len; -+ memcpy(packet.data, data, len); -+ -+ err = 0; -+ len = sizeof(packet) + packet.len - sizeof(packet.data); -+ n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, -+ sizeof(target)); -+ if(n < 0){ -+ printk("mconsole_notify - sendto failed, errno = %d\n", errno); -+ err = -errno; -+ } -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/mmapper_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/mmapper_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/mmapper_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,151 @@ -+/* -+ * arch/um/drivers/mmapper_kern.c -+ * -+ * BRIEF MODULE DESCRIPTION -+ * -+ * Copyright (C) 2000 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ */ -+#include <linux/kdev_t.h> -+#include <linux/time.h> -+#include <linux/devfs_fs_kernel.h> -+#include <linux/module.h> -+#include <linux/mm.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <asm/uaccess.h> -+#include <asm/irq.h> -+#include <asm/smplock.h> -+#include <asm/pgtable.h> -+#include "mem_user.h" -+#include "user_util.h" -+ -+/* These are set in mmapper_init, which is called at boot time */ -+static unsigned long mmapper_size; -+static unsigned long p_buf = 0; -+static char *v_buf = NULL; -+ -+static ssize_t -+mmapper_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ if(*ppos > mmapper_size) -+ return -EINVAL; -+ -+ if(count + *ppos > mmapper_size) -+ count = count + *ppos - mmapper_size; -+ -+ if(count < 0) -+ return -EINVAL; -+ -+ copy_to_user(buf,&v_buf[*ppos],count); -+ -+ return count; -+} -+ -+static ssize_t -+mmapper_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -+{ -+ if(*ppos > mmapper_size) -+ return -EINVAL; -+ -+ if(count + *ppos > mmapper_size) -+ count = count + *ppos - mmapper_size; -+ -+ if(count < 0) -+ return -EINVAL; -+ -+ copy_from_user(&v_buf[*ppos],buf,count); -+ -+ return count; -+} -+ -+static int -+mmapper_ioctl(struct inode *inode, struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ return(-ENOIOCTLCMD); -+} -+ -+static int -+mmapper_mmap(struct file *file, struct vm_area_struct * vma) -+{ -+ int ret = -EINVAL; -+ int size; -+ -+ lock_kernel(); -+ if (vma->vm_pgoff != 0) -+ goto out; -+ -+ size = vma->vm_end - vma->vm_start; -+ if(size > mmapper_size) return(-EFAULT); -+ -+ /* XXX A comment above remap_page_range says it should only be -+ * called when the mm semaphore is held -+ */ -+ if (remap_page_range(vma->vm_start, p_buf, size, vma->vm_page_prot)) -+ goto out; -+ ret = 0; -+out: -+ unlock_kernel(); -+ return ret; -+} -+ -+static int -+mmapper_open(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static int -+mmapper_release(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static struct file_operations mmapper_fops = { -+ .owner = THIS_MODULE, -+ .read = mmapper_read, -+ .write = mmapper_write, -+ .ioctl = mmapper_ioctl, -+ .mmap = mmapper_mmap, -+ .open = mmapper_open, -+ .release = mmapper_release, -+}; -+ -+static int __init mmapper_init(void) -+{ -+ printk(KERN_INFO "Mapper v0.1\n"); -+ -+ v_buf = (char *) find_iomem("mmapper", &mmapper_size); -+ if(mmapper_size == 0){ -+ printk(KERN_ERR "mmapper_init - find_iomem failed\n"); -+ return(0); -+ } -+ -+ p_buf = __pa(v_buf); -+ -+ devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, -+ 30, 0, S_IFCHR | S_IRUGO | S_IWUGO, -+ &mmapper_fops, NULL); -+ devfs_mk_symlink(NULL, "mmapper0", DEVFS_FL_DEFAULT, "mmapper", -+ NULL, NULL); -+ return(0); -+} -+ -+static void mmapper_exit(void) -+{ -+} -+ -+module_init(mmapper_init); -+module_exit(mmapper_exit); -+ -+MODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>"); -+MODULE_DESCRIPTION("DSPLinux simulator mmapper driver"); -+/* -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/net_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/net_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/net_kern.c 2005-05-03 22:28:14.228447160 +0300 -@@ -0,0 +1,903 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/netdevice.h" -+#include "linux/rtnetlink.h" -+#include "linux/skbuff.h" -+#include "linux/socket.h" -+#include "linux/spinlock.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/etherdevice.h" -+#include "linux/list.h" -+#include "linux/inetdevice.h" -+#include "linux/ctype.h" -+#include "linux/bootmem.h" -+#include "linux/ethtool.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+ -+static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED; -+LIST_HEAD(opened); -+ -+static int uml_net_rx(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ int pkt_len; -+ struct sk_buff *skb; -+ -+ /* If we can't allocate memory, try again next round. */ -+ skb = dev_alloc_skb(dev->mtu); -+ if (skb == NULL) { -+ lp->stats.rx_dropped++; -+ return 0; -+ } -+ -+ skb->dev = dev; -+ skb_put(skb, dev->mtu); -+ skb->mac.raw = skb->data; -+ pkt_len = (*lp->read)(lp->fd, &skb, lp); -+ -+ if (pkt_len > 0) { -+ skb_trim(skb, pkt_len); -+ skb->protocol = (*lp->protocol)(skb); -+ netif_rx(skb); -+ -+ lp->stats.rx_bytes += skb->len; -+ lp->stats.rx_packets++; -+ return pkt_len; -+ } -+ -+ kfree_skb(skb); -+ return pkt_len; -+} -+ -+void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ struct net_device *dev = dev_id; -+ struct uml_net_private *lp = dev->priv; -+ int err; -+ -+ if(!netif_running(dev)) -+ return; -+ -+ spin_lock(&lp->lock); -+ while((err = uml_net_rx(dev)) > 0) ; -+ if(err < 0) { -+ printk(KERN_ERR -+ "Device '%s' read returned %d, shutting it down\n", -+ dev->name, err); -+ dev_close(dev); -+ goto out; -+ } -+ reactivate_fd(lp->fd, UM_ETH_IRQ); -+ -+ out: -+ spin_unlock(&lp->lock); -+} -+ -+static int uml_net_open(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ char addr[sizeof("255.255.255.255\0")]; -+ int err; -+ -+ spin_lock(&lp->lock); -+ -+ if(lp->fd >= 0){ -+ err = -ENXIO; -+ goto out; -+ } -+ -+ if(!lp->have_mac){ -+ dev_ip_addr(dev, addr, &lp->mac[2]); -+ set_ether_mac(dev, lp->mac); -+ } -+ -+ lp->fd = (*lp->open)(&lp->user); -+ if(lp->fd < 0){ -+ err = lp->fd; -+ goto out; -+ } -+ -+ err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, -+ SA_INTERRUPT | SA_SHIRQ, dev->name, dev); -+ if(err != 0){ -+ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ lp->fd = -1; -+ err = -ENETUNREACH; -+ } -+ -+ lp->tl.data = (unsigned long) &lp->user; -+ netif_start_queue(dev); -+ -+ spin_lock(&opened_lock); -+ list_add(&lp->list, &opened); -+ spin_unlock(&opened_lock); -+ /* clear buffer - it can happen that the host side of the interface -+ * is full when we get here. In this case, new data is never queued, -+ * SIGIOs never arrive, and the net never works. -+ */ -+ while((err = uml_net_rx(dev)) > 0) ; -+ -+ MOD_INC_USE_COUNT; -+ out: -+ spin_unlock(&lp->lock); -+ return(err); -+} -+ -+static int uml_net_close(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ -+ netif_stop_queue(dev); -+ spin_lock(&lp->lock); -+ -+ free_irq(dev->irq, dev); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ lp->fd = -1; -+ spin_lock(&opened_lock); -+ list_del(&lp->list); -+ spin_unlock(&opened_lock); -+ -+ MOD_DEC_USE_COUNT; -+ spin_unlock(&lp->lock); -+ return 0; -+} -+ -+static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ unsigned long flags; -+ int len; -+ -+ netif_stop_queue(dev); -+ -+ spin_lock_irqsave(&lp->lock, flags); -+ -+ len = (*lp->write)(lp->fd, &skb, lp); -+ -+ if(len == skb->len) { -+ lp->stats.tx_packets++; -+ lp->stats.tx_bytes += skb->len; -+ dev->trans_start = jiffies; -+ netif_start_queue(dev); -+ -+ /* this is normally done in the interrupt when tx finishes */ -+ netif_wake_queue(dev); -+ } -+ else if(len == 0){ -+ netif_start_queue(dev); -+ lp->stats.tx_dropped++; -+ } -+ else { -+ netif_start_queue(dev); -+ printk(KERN_ERR "uml_net_start_xmit: failed(%d)\n", len); -+ } -+ -+ spin_unlock_irqrestore(&lp->lock, flags); -+ -+ dev_kfree_skb(skb); -+ -+ return 0; -+} -+ -+static struct net_device_stats *uml_net_get_stats(struct net_device *dev) -+{ -+ struct uml_net_private *lp = dev->priv; -+ return &lp->stats; -+} -+ -+static void uml_net_set_multicast_list(struct net_device *dev) -+{ -+ if (dev->flags & IFF_PROMISC) return; -+ else if (dev->mc_count) dev->flags |= IFF_ALLMULTI; -+ else dev->flags &= ~IFF_ALLMULTI; -+} -+ -+static void uml_net_tx_timeout(struct net_device *dev) -+{ -+ dev->trans_start = jiffies; -+ netif_wake_queue(dev); -+} -+ -+static int uml_net_set_mac(struct net_device *dev, void *addr) -+{ -+ struct uml_net_private *lp = dev->priv; -+ struct sockaddr *hwaddr = addr; -+ -+ spin_lock(&lp->lock); -+ memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); -+ spin_unlock(&lp->lock); -+ -+ return(0); -+} -+ -+static int uml_net_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ struct uml_net_private *lp = dev->priv; -+ int err = 0; -+ -+ spin_lock(&lp->lock); -+ -+ new_mtu = (*lp->set_mtu)(new_mtu, &lp->user); -+ if(new_mtu < 0){ -+ err = new_mtu; -+ goto out; -+ } -+ -+ dev->mtu = new_mtu; -+ -+ out: -+ spin_unlock(&lp->lock); -+ return err; -+} -+ -+static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ static const struct ethtool_drvinfo info = { -+ .cmd = ETHTOOL_GDRVINFO, -+ .driver = "uml virtual ethernet", -+ .version = "42", -+ }; -+ void *useraddr; -+ u32 ethcmd; -+ -+ switch (cmd) { -+ case SIOCETHTOOL: -+ useraddr = ifr->ifr_data; -+ if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) -+ return -EFAULT; -+ switch (ethcmd) { -+ case ETHTOOL_GDRVINFO: -+ if (copy_to_user(useraddr, &info, sizeof(info))) -+ return -EFAULT; -+ return 0; -+ default: -+ return -EOPNOTSUPP; -+ } -+ default: -+ return -EINVAL; -+ } -+} -+ -+void uml_net_user_timer_expire(unsigned long _conn) -+{ -+#ifdef undef -+ struct connection *conn = (struct connection *)_conn; -+ -+ dprintk(KERN_INFO "uml_net_user_timer_expire [%p]\n", conn); -+ do_connect(conn); -+#endif -+} -+ -+/* -+ * default do nothing hard header packet routines for struct net_device init. -+ * real ethernet transports will overwrite with real routines. -+ */ -+static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev, -+ unsigned short type, void *daddr, void *saddr, unsigned len) -+{ -+ return(0); /* no change */ -+} -+ -+static int uml_net_rebuild_header(struct sk_buff *skb) -+{ -+ return(0); /* ignore */ -+} -+ -+static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh) -+{ -+ return(-1); /* fail */ -+} -+ -+static void uml_net_header_cache_update(struct hh_cache *hh, -+ struct net_device *dev, unsigned char * haddr) -+{ -+ /* ignore */ -+} -+ -+static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr) -+{ -+ return(0); /* nothing */ -+} -+ -+static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED; -+static struct list_head devices = LIST_HEAD_INIT(devices); -+ -+static int eth_configure(int n, void *init, char *mac, -+ struct transport *transport) -+{ -+ struct uml_net *device; -+ struct net_device *dev; -+ struct uml_net_private *lp; -+ int save, err, size; -+ -+ size = transport->private_size + sizeof(struct uml_net_private) + -+ sizeof(((struct uml_net_private *) 0)->user); -+ -+ device = kmalloc(sizeof(*device), GFP_KERNEL); -+ if(device == NULL){ -+ printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); -+ return(1); -+ } -+ -+ *device = ((struct uml_net) { .list = LIST_HEAD_INIT(device->list), -+ .dev = NULL, -+ .index = n, -+ .mac = { [ 0 ... 5 ] = 0 }, -+ .have_mac = 0 }); -+ -+ spin_lock(&devices_lock); -+ list_add(&device->list, &devices); -+ spin_unlock(&devices_lock); -+ -+ if(setup_etheraddr(mac, device->mac)) -+ device->have_mac = 1; -+ -+ printk(KERN_INFO "Netdevice %d ", n); -+ if(device->have_mac) printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", -+ device->mac[0], device->mac[1], -+ device->mac[2], device->mac[3], -+ device->mac[4], device->mac[5]); -+ printk(": "); -+ dev = kmalloc(sizeof(*dev) + size, GFP_KERNEL); -+ if(dev == NULL){ -+ printk(KERN_ERR "eth_configure: failed to allocate device\n"); -+ return(1); -+ } -+ memset(dev, 0, sizeof(*dev) + size); -+ -+ snprintf(dev->name, sizeof(dev->name), "eth%d", n); -+ dev->priv = (void *) &dev[1]; -+ device->dev = dev; -+ -+ dev->hard_header = uml_net_hard_header; -+ dev->rebuild_header = uml_net_rebuild_header; -+ dev->hard_header_cache = uml_net_header_cache; -+ dev->header_cache_update= uml_net_header_cache_update; -+ dev->hard_header_parse = uml_net_header_parse; -+ -+ (*transport->kern->init)(dev, init); -+ -+ dev->mtu = transport->user->max_packet; -+ dev->open = uml_net_open; -+ dev->hard_start_xmit = uml_net_start_xmit; -+ dev->stop = uml_net_close; -+ dev->get_stats = uml_net_get_stats; -+ dev->set_multicast_list = uml_net_set_multicast_list; -+ dev->tx_timeout = uml_net_tx_timeout; -+ dev->set_mac_address = uml_net_set_mac; -+ dev->change_mtu = uml_net_change_mtu; -+ dev->do_ioctl = uml_net_ioctl; -+ dev->watchdog_timeo = (HZ >> 1); -+ dev->irq = UM_ETH_IRQ; -+ -+ rtnl_lock(); -+ err = register_netdevice(dev); -+ rtnl_unlock(); -+ if(err) -+ return(1); -+ lp = dev->priv; -+ -+ /* lp.user is the first four bytes of the transport data, which -+ * has already been initialized. This structure assignment will -+ * overwrite that, so we make sure that .user gets overwritten with -+ * what it already has. -+ */ -+ save = lp->user[0]; -+ *lp = ((struct uml_net_private) -+ { .list = LIST_HEAD_INIT(lp->list), -+ .lock = SPIN_LOCK_UNLOCKED, -+ .dev = dev, -+ .fd = -1, -+ .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, -+ .have_mac = device->have_mac, -+ .protocol = transport->kern->protocol, -+ .open = transport->user->open, -+ .close = transport->user->close, -+ .remove = transport->user->remove, -+ .read = transport->kern->read, -+ .write = transport->kern->write, -+ .add_address = transport->user->add_address, -+ .delete_address = transport->user->delete_address, -+ .set_mtu = transport->user->set_mtu, -+ .user = { save } }); -+ init_timer(&lp->tl); -+ lp->tl.function = uml_net_user_timer_expire; -+ memset(&lp->stats, 0, sizeof(lp->stats)); -+ if(lp->have_mac) memcpy(lp->mac, device->mac, sizeof(lp->mac)); -+ -+ if(transport->user->init) -+ (*transport->user->init)(&lp->user, dev); -+ -+ if(device->have_mac) -+ set_ether_mac(dev, device->mac); -+ return(0); -+} -+ -+static struct uml_net *find_device(int n) -+{ -+ struct uml_net *device; -+ struct list_head *ele; -+ -+ spin_lock(&devices_lock); -+ list_for_each(ele, &devices){ -+ device = list_entry(ele, struct uml_net, list); -+ if(device->index == n) -+ goto out; -+ } -+ device = NULL; -+ out: -+ spin_unlock(&devices_lock); -+ return(device); -+} -+ -+static int eth_parse(char *str, int *index_out, char **str_out) -+{ -+ char *end; -+ int n; -+ -+ n = simple_strtoul(str, &end, 0); -+ if(end == str){ -+ printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); -+ return(1); -+ } -+ if(n < 0){ -+ printk(KERN_ERR "eth_setup: device %d is negative\n", n); -+ return(1); -+ } -+ str = end; -+ if(*str != '='){ -+ printk(KERN_ERR -+ "eth_setup: expected '=' after device number\n"); -+ return(1); -+ } -+ str++; -+ if(find_device(n)){ -+ printk(KERN_ERR "eth_setup: Device %d already configured\n", -+ n); -+ return(1); -+ } -+ if(index_out) *index_out = n; -+ *str_out = str; -+ return(0); -+} -+ -+struct eth_init { -+ struct list_head list; -+ char *init; -+ int index; -+}; -+ -+/* Filled in at boot time. Will need locking if the transports become -+ * modular. -+ */ -+struct list_head transports = LIST_HEAD_INIT(transports); -+ -+/* Filled in during early boot */ -+struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); -+ -+static int check_transport(struct transport *transport, char *eth, int n, -+ void **init_out, char **mac_out) -+{ -+ int len; -+ -+ len = strlen(transport->name); -+ if(strncmp(eth, transport->name, len)) -+ return(0); -+ -+ eth += len; -+ if(*eth == ',') -+ eth++; -+ else if(*eth != '\0') -+ return(0); -+ -+ *init_out = kmalloc(transport->setup_size, GFP_KERNEL); -+ if(*init_out == NULL) -+ return(1); -+ -+ if(!transport->setup(eth, mac_out, *init_out)){ -+ kfree(*init_out); -+ *init_out = NULL; -+ } -+ return(1); -+} -+ -+void register_transport(struct transport *new) -+{ -+ struct list_head *ele, *next; -+ struct eth_init *eth; -+ void *init; -+ char *mac = NULL; -+ int match; -+ -+ list_add(&new->list, &transports); -+ -+ list_for_each_safe(ele, next, ð_cmd_line){ -+ eth = list_entry(ele, struct eth_init, list); -+ match = check_transport(new, eth->init, eth->index, &init, -+ &mac); -+ if(!match) -+ continue; -+ else if(init != NULL){ -+ eth_configure(eth->index, init, mac, new); -+ kfree(init); -+ } -+ list_del(ð->list); -+ } -+} -+ -+static int eth_setup_common(char *str, int index) -+{ -+ struct list_head *ele; -+ struct transport *transport; -+ void *init; -+ char *mac = NULL; -+ -+ list_for_each(ele, &transports){ -+ transport = list_entry(ele, struct transport, list); -+ if(!check_transport(transport, str, index, &init, &mac)) -+ continue; -+ if(init != NULL){ -+ eth_configure(index, init, mac, transport); -+ kfree(init); -+ } -+ return(1); -+ } -+ return(0); -+} -+ -+static int eth_setup(char *str) -+{ -+ struct eth_init *new; -+ int n, err; -+ -+ err = eth_parse(str, &n, &str); -+ if(err) return(1); -+ -+ new = alloc_bootmem(sizeof(new)); -+ if(new == NULL){ -+ printk("eth_init : alloc_bootmem failed\n"); -+ return(1); -+ } -+ *new = ((struct eth_init) { .list = LIST_HEAD_INIT(new->list), -+ .index = n, -+ .init = str }); -+ list_add_tail(&new->list, ð_cmd_line); -+ return(1); -+} -+ -+__setup("eth", eth_setup); -+__uml_help(eth_setup, -+"eth[0-9]+=<transport>,<options>\n" -+" Configure a network device.\n\n" -+); -+ -+static int eth_init(void) -+{ -+ struct list_head *ele, *next; -+ struct eth_init *eth; -+ -+ list_for_each_safe(ele, next, ð_cmd_line){ -+ eth = list_entry(ele, struct eth_init, list); -+ -+ if(eth_setup_common(eth->init, eth->index)) -+ list_del(ð->list); -+ } -+ -+ return(1); -+} -+ -+__initcall(eth_init); -+ -+static int net_config(char *str) -+{ -+ int n, err; -+ -+ err = eth_parse(str, &n, &str); -+ if(err) return(err); -+ -+ str = uml_strdup(str); -+ if(str == NULL){ -+ printk(KERN_ERR "net_config failed to strdup string\n"); -+ return(-1); -+ } -+ err = !eth_setup_common(str, n); -+ if(err) -+ kfree(str); -+ return(err); -+} -+ -+static int net_remove(char *str) -+{ -+ struct uml_net *device; -+ struct net_device *dev; -+ struct uml_net_private *lp; -+ char *end; -+ int n; -+ -+ n = simple_strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)) -+ return(-1); -+ -+ device = find_device(n); -+ if(device == NULL) -+ return(0); -+ -+ dev = device->dev; -+ lp = dev->priv; -+ if(lp->fd > 0) return(-1); -+ if(lp->remove != NULL) (*lp->remove)(&lp->user); -+ unregister_netdev(dev); -+ -+ list_del(&device->list); -+ kfree(device); -+ return(0); -+} -+ -+static struct mc_device net_mc = { -+ .name = "eth", -+ .config = net_config, -+ .get_config = NULL, -+ .remove = net_remove, -+}; -+ -+static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, -+ void *ptr) -+{ -+ struct in_ifaddr *ifa = ptr; -+ u32 addr = ifa->ifa_address; -+ u32 netmask = ifa->ifa_mask; -+ struct net_device *dev = ifa->ifa_dev->dev; -+ struct uml_net_private *lp; -+ void (*proc)(unsigned char *, unsigned char *, void *); -+ unsigned char addr_buf[4], netmask_buf[4]; -+ -+ if(dev->open != uml_net_open) return(NOTIFY_DONE); -+ -+ lp = dev->priv; -+ -+ proc = NULL; -+ switch (event){ -+ case NETDEV_UP: -+ proc = lp->add_address; -+ break; -+ case NETDEV_DOWN: -+ proc = lp->delete_address; -+ break; -+ } -+ if(proc != NULL){ -+ addr_buf[0] = addr & 0xff; -+ addr_buf[1] = (addr >> 8) & 0xff; -+ addr_buf[2] = (addr >> 16) & 0xff; -+ addr_buf[3] = addr >> 24; -+ netmask_buf[0] = netmask & 0xff; -+ netmask_buf[1] = (netmask >> 8) & 0xff; -+ netmask_buf[2] = (netmask >> 16) & 0xff; -+ netmask_buf[3] = netmask >> 24; -+ (*proc)(addr_buf, netmask_buf, &lp->user); -+ } -+ return(NOTIFY_DONE); -+} -+ -+struct notifier_block uml_inetaddr_notifier = { -+ .notifier_call = uml_inetaddr_event, -+}; -+ -+static int uml_net_init(void) -+{ -+ struct list_head *ele; -+ struct uml_net_private *lp; -+ struct in_device *ip; -+ struct in_ifaddr *in; -+ -+ mconsole_register_dev(&net_mc); -+ register_inetaddr_notifier(¨_inetaddr_notifier); -+ -+ /* Devices may have been opened already, so the uml_inetaddr_notifier -+ * didn't get a chance to run for them. This fakes it so that -+ * addresses which have already been set up get handled properly. -+ */ -+ list_for_each(ele, &opened){ -+ lp = list_entry(ele, struct uml_net_private, list); -+ ip = lp->dev->ip_ptr; -+ if(ip == NULL) continue; -+ in = ip->ifa_list; -+ while(in != NULL){ -+ uml_inetaddr_event(NULL, NETDEV_UP, in); -+ in = in->ifa_next; -+ } -+ } -+ -+ return(0); -+} -+ -+__initcall(uml_net_init); -+ -+static void close_devices(void) -+{ -+ struct list_head *ele; -+ struct uml_net_private *lp; -+ -+ list_for_each(ele, &opened){ -+ lp = list_entry(ele, struct uml_net_private, list); -+ if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); -+ if(lp->remove != NULL) (*lp->remove)(&lp->user); -+ } -+} -+ -+__uml_exitcall(close_devices); -+ -+int setup_etheraddr(char *str, unsigned char *addr) -+{ -+ char *end; -+ int i; -+ -+ if(str == NULL) -+ return(0); -+ for(i=0;i<6;i++){ -+ addr[i] = simple_strtoul(str, &end, 16); -+ if((end == str) || -+ ((*end != ':') && (*end != ',') && (*end != '\0'))){ -+ printk(KERN_ERR -+ "setup_etheraddr: failed to parse '%s' " -+ "as an ethernet address\n", str); -+ return(0); -+ } -+ str = end + 1; -+ } -+ if(addr[0] & 1){ -+ printk(KERN_ERR -+ "Attempt to assign a broadcast ethernet address to a " -+ "device disallowed\n"); -+ return(0); -+ } -+ return(1); -+} -+ -+void dev_ip_addr(void *d, char *buf, char *bin_buf) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ u32 addr; -+ -+ if((ip == NULL) || ((in = ip->ifa_list) == NULL)){ -+ printk(KERN_WARNING "dev_ip_addr - device not assigned an " -+ "IP address\n"); -+ return; -+ } -+ addr = in->ifa_address; -+ sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff, -+ (addr >> 16) & 0xff, addr >> 24); -+ if(bin_buf){ -+ bin_buf[0] = addr & 0xff; -+ bin_buf[1] = (addr >> 8) & 0xff; -+ bin_buf[2] = (addr >> 16) & 0xff; -+ bin_buf[3] = addr >> 24; -+ } -+} -+ -+void set_ether_mac(void *d, unsigned char *addr) -+{ -+ struct net_device *dev = d; -+ -+ memcpy(dev->dev_addr, addr, ETH_ALEN); -+} -+ -+struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) -+{ -+ if((skb != NULL) && (skb_tailroom(skb) < extra)){ -+ struct sk_buff *skb2; -+ -+ skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC); -+ dev_kfree_skb(skb); -+ skb = skb2; -+ } -+ if(skb != NULL) skb_put(skb, extra); -+ return(skb); -+} -+ -+void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, -+ void *), -+ void *arg) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ unsigned char address[4], netmask[4]; -+ -+ if(ip == NULL) return; -+ in = ip->ifa_list; -+ while(in != NULL){ -+ address[0] = in->ifa_address & 0xff; -+ address[1] = (in->ifa_address >> 8) & 0xff; -+ address[2] = (in->ifa_address >> 16) & 0xff; -+ address[3] = in->ifa_address >> 24; -+ netmask[0] = in->ifa_mask & 0xff; -+ netmask[1] = (in->ifa_mask >> 8) & 0xff; -+ netmask[2] = (in->ifa_mask >> 16) & 0xff; -+ netmask[3] = in->ifa_mask >> 24; -+ (*cb)(address, netmask, arg); -+ in = in->ifa_next; -+ } -+} -+ -+int dev_netmask(void *d, void *m) -+{ -+ struct net_device *dev = d; -+ struct in_device *ip = dev->ip_ptr; -+ struct in_ifaddr *in; -+ __u32 *mask_out = m; -+ -+ if(ip == NULL) -+ return(1); -+ -+ in = ip->ifa_list; -+ if(in == NULL) -+ return(1); -+ -+ *mask_out = in->ifa_mask; -+ return(0); -+} -+ -+void *get_output_buffer(int *len_out) -+{ -+ void *ret; -+ -+ ret = (void *) __get_free_pages(GFP_KERNEL, 0); -+ if(ret) *len_out = PAGE_SIZE; -+ else *len_out = 0; -+ return(ret); -+} -+ -+void free_output_buffer(void *buffer) -+{ -+ free_pages((unsigned long) buffer, 0); -+} -+ -+int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, -+ char **gate_addr) -+{ -+ char *remain; -+ -+ remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL); -+ if(remain != NULL){ -+ printk("tap_setup_common - Extra garbage on specification : " -+ "'%s'\n", remain); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+unsigned short eth_protocol(struct sk_buff *skb) -+{ -+ return(eth_type_trans(skb, skb->dev)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/net_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/net_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/net_user.c 2005-05-03 22:28:14.229447008 +0300 -@@ -0,0 +1,253 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stddef.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <stdio.h> -+#include <errno.h> -+#include <stdlib.h> -+#include <string.h> -+#include <sys/socket.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "net_user.h" -+#include "helper.h" -+#include "os.h" -+ -+int tap_open_common(void *dev, char *gate_addr) -+{ -+ int tap_addr[4]; -+ -+ if(gate_addr == NULL) return(0); -+ if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], -+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ -+ printk("Invalid tap IP address - '%s'\n", gate_addr); -+ return(-EINVAL); -+ } -+ return(0); -+} -+ -+void tap_check_ips(char *gate_addr, char *eth_addr) -+{ -+ int tap_addr[4]; -+ -+ if((gate_addr != NULL) && -+ (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], -+ &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && -+ (eth_addr[0] == tap_addr[0]) && -+ (eth_addr[1] == tap_addr[1]) && -+ (eth_addr[2] == tap_addr[2]) && -+ (eth_addr[3] == tap_addr[3])){ -+ printk("The tap IP address and the UML eth IP address" -+ " must be different\n"); -+ } -+} -+ -+void read_output(int fd, char *output, int len) -+{ -+ int remain, n, actual; -+ char c; -+ -+ if(output == NULL){ -+ output = &c; -+ len = sizeof(c); -+ } -+ -+ *output = '\0'; -+ n = os_read_file(fd, &remain, sizeof(remain)); -+ if(n != sizeof(remain)){ -+ printk("read_output - read of length failed, err = %d\n", -n); -+ return; -+ } -+ -+ while(remain != 0){ -+ n = (remain < len) ? remain : len; -+ actual = os_read_file(fd, output, n); -+ if(actual != n){ -+ printk("read_output - read of data failed, " -+ "err = %d\n", -actual); -+ return; -+ } -+ remain -= actual; -+ } -+ return; -+} -+ -+int net_read(int fd, void *buf, int len) -+{ -+ int n; -+ -+ n = os_read_file(fd, buf, len); -+ -+ if(n == -EAGAIN) -+ return(0); -+ else if(n == 0) -+ return(-ENOTCONN); -+ return(n); -+} -+ -+int net_recvfrom(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) && -+ (errno == EINTR)) ; -+ -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+int net_write(int fd, void *buf, int len) -+{ -+ int n; -+ -+ n = os_write_file(fd, buf, len); -+ -+ if(n == -EAGAIN) -+ return(0); -+ else if(n == 0) -+ return(-ENOTCONN); -+ return(n); -+} -+ -+int net_send(int fd, void *buf, int len) -+{ -+ int n; -+ -+ while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ; -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+int net_sendto(int fd, void *buf, int len, void *to, int sock_len) -+{ -+ int n; -+ -+ while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to, -+ sock_len)) < 0) && (errno == EINTR)) ; -+ if(n < 0){ -+ if(errno == EAGAIN) return(0); -+ return(-errno); -+ } -+ else if(n == 0) return(-ENOTCONN); -+ return(n); -+} -+ -+struct change_pre_exec_data { -+ int close_me; -+ int stdout; -+}; -+ -+static void change_pre_exec(void *arg) -+{ -+ struct change_pre_exec_data *data = arg; -+ -+ os_close_file(data->close_me); -+ dup2(data->stdout, 1); -+} -+ -+static int change_tramp(char **argv, char *output, int output_len) -+{ -+ int pid, fds[2], err; -+ struct change_pre_exec_data pe_data; -+ -+ err = os_pipe(fds, 1, 0); -+ if(err < 0){ -+ printk("change_tramp - pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ pe_data.close_me = fds[0]; -+ pe_data.stdout = fds[1]; -+ pid = run_helper(change_pre_exec, &pe_data, argv, NULL); -+ -+ read_output(fds[0], output, output_len); -+ os_close_file(fds[0]); -+ os_close_file(fds[1]); -+ CATCH_EINTR(waitpid(pid, NULL, 0)); -+ return(pid); -+} -+ -+static void change(char *dev, char *what, unsigned char *addr, -+ unsigned char *netmask) -+{ -+ char addr_buf[sizeof("255.255.255.255\0")]; -+ char netmask_buf[sizeof("255.255.255.255\0")]; -+ char version[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version, what, dev, addr_buf, -+ netmask_buf, NULL }; -+ char *output; -+ int output_len, pid; -+ -+ sprintf(version, "%d", UML_NET_VERSION); -+ sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); -+ sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], -+ netmask[2], netmask[3]); -+ -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ if(output == NULL) -+ printk("change : failed to allocate output buffer\n"); -+ -+ pid = change_tramp(argv, output, output_len); -+ if(pid < 0) return; -+ -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+} -+ -+void open_addr(unsigned char *addr, unsigned char *netmask, void *arg) -+{ -+ change(arg, "add", addr, netmask); -+} -+ -+void close_addr(unsigned char *addr, unsigned char *netmask, void *arg) -+{ -+ change(arg, "del", addr, netmask); -+} -+ -+char *split_if_spec(char *str, ...) -+{ -+ char **arg, *end; -+ va_list ap; -+ -+ va_start(ap, str); -+ while((arg = va_arg(ap, char **)) != NULL){ -+ if(*str == '\0') -+ return(NULL); -+ end = strchr(str, ','); -+ if(end != str) -+ *arg = str; -+ if(end == NULL) -+ return(NULL); -+ *end++ = '\0'; -+ str = end; -+ } -+ va_end(ap); -+ return(str); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/null.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/null.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/null.c 2005-05-03 22:28:14.230446856 +0300 -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include "chan_user.h" -+#include "os.h" -+ -+static int null_chan; -+ -+void *null_init(char *str, int device, struct chan_opts *opts) -+{ -+ return(&null_chan); -+} -+ -+int null_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ *dev_out = NULL; -+ return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0)); -+} -+ -+int null_read(int fd, char *c_out, void *unused) -+{ -+ return(-ENODEV); -+} -+ -+void null_free(void *data) -+{ -+} -+ -+struct chan_ops null_ops = { -+ .type = "null", -+ .init = null_init, -+ .open = null_open, -+ .close = generic_close, -+ .read = null_read, -+ .write = generic_write, -+ .console_write = generic_console_write, -+ .window_size = generic_window_size, -+ .free = null_free, -+ .winch = 0, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/pcap_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/pcap_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/pcap_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "pcap_user.h" -+ -+struct pcap_init { -+ char *host_if; -+ int promisc; -+ int optimize; -+ char *filter; -+}; -+ -+void pcap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct pcap_data *ppri; -+ struct pcap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ ppri = (struct pcap_data *) pri->user; -+ *ppri = ((struct pcap_data) -+ { .host_if = init->host_if, -+ .promisc = init->promisc, -+ .optimize = init->optimize, -+ .filter = init->filter, -+ .compiled = NULL, -+ .pcap = NULL }); -+} -+ -+static int pcap_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(pcap_user_read(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER, -+ (struct pcap_data *) &lp->user)); -+} -+ -+static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ return(-EPERM); -+} -+ -+static struct net_kern_info pcap_kern_info = { -+ .init = pcap_init, -+ .protocol = eth_protocol, -+ .read = pcap_read, -+ .write = pcap_write, -+}; -+ -+int pcap_setup(char *str, char **mac_out, void *data) -+{ -+ struct pcap_init *init = data; -+ char *remain, *host_if = NULL, *options[2] = { NULL, NULL }; -+ int i; -+ -+ *init = ((struct pcap_init) -+ { .host_if = "eth0", -+ .promisc = 1, -+ .optimize = 0, -+ .filter = NULL }); -+ -+ remain = split_if_spec(str, &host_if, &init->filter, -+ &options[0], &options[1], NULL); -+ if(remain != NULL){ -+ printk(KERN_ERR "pcap_setup - Extra garbage on " -+ "specification : '%s'\n", remain); -+ return(0); -+ } -+ -+ if(host_if != NULL) -+ init->host_if = host_if; -+ -+ for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){ -+ if(options[i] == NULL) -+ continue; -+ if(!strcmp(options[i], "promisc")) -+ init->promisc = 1; -+ else if(!strcmp(options[i], "nopromisc")) -+ init->promisc = 0; -+ else if(!strcmp(options[i], "optimize")) -+ init->optimize = 1; -+ else if(!strcmp(options[i], "nooptimize")) -+ init->optimize = 0; -+ else printk("pcap_setup : bad option - '%s'\n", options[i]); -+ } -+ -+ return(1); -+} -+ -+static struct transport pcap_transport = { -+ .list = LIST_HEAD_INIT(pcap_transport.list), -+ .name = "pcap", -+ .setup = pcap_setup, -+ .user = &pcap_user_info, -+ .kern = &pcap_kern_info, -+ .private_size = sizeof(struct pcap_data), -+ .setup_size = sizeof(struct pcap_init), -+}; -+ -+static int register_pcap(void) -+{ -+ register_transport(&pcap_transport); -+ return(1); -+} -+ -+__initcall(register_pcap); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/pcap_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/pcap_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/pcap_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike <jdike@karaya.com> -+ * Licensed under the GPL. -+ */ -+ -+#include <unistd.h> -+#include <stdlib.h> -+#include <string.h> -+#include <errno.h> -+#include <pcap.h> -+#include <asm/types.h> -+#include "net_user.h" -+#include "pcap_user.h" -+#include "user.h" -+ -+#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) -+ -+#define PCAP_FD(p) (*(int *)(p)) -+ -+static void pcap_user_init(void *data, void *dev) -+{ -+ struct pcap_data *pri = data; -+ pcap_t *p; -+ char errors[PCAP_ERRBUF_SIZE]; -+ -+ p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors); -+ if(p == NULL){ -+ printk("pcap_user_init : pcap_open_live failed - '%s'\n", -+ errors); -+ return; -+ } -+ -+ pri->dev = dev; -+ pri->pcap = p; -+} -+ -+static int pcap_open(void *data) -+{ -+ struct pcap_data *pri = data; -+ __u32 netmask; -+ int err; -+ -+ if(pri->pcap == NULL) -+ return(-ENODEV); -+ -+ if(pri->filter != NULL){ -+ err = dev_netmask(pri->dev, &netmask); -+ if(err < 0){ -+ printk("pcap_open : dev_netmask failed\n"); -+ return(-EIO); -+ } -+ -+ pri->compiled = um_kmalloc(sizeof(struct bpf_program)); -+ if(pri->compiled == NULL){ -+ printk("pcap_open : kmalloc failed\n"); -+ return(-ENOMEM); -+ } -+ -+ err = pcap_compile(pri->pcap, -+ (struct bpf_program *) pri->compiled, -+ pri->filter, pri->optimize, netmask); -+ if(err < 0){ -+ printk("pcap_open : pcap_compile failed - '%s'\n", -+ pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ -+ err = pcap_setfilter(pri->pcap, pri->compiled); -+ if(err < 0){ -+ printk("pcap_open : pcap_setfilter failed - '%s'\n", -+ pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ } -+ -+ return(PCAP_FD(pri->pcap)); -+} -+ -+static void pcap_remove(void *data) -+{ -+ struct pcap_data *pri = data; -+ -+ if(pri->compiled != NULL) -+ pcap_freecode(pri->compiled); -+ -+ pcap_close(pri->pcap); -+} -+ -+struct pcap_handler_data { -+ char *buffer; -+ int len; -+}; -+ -+static void handler(u_char *data, const struct pcap_pkthdr *header, -+ const u_char *packet) -+{ -+ int len; -+ -+ struct pcap_handler_data *hdata = (struct pcap_handler_data *) data; -+ -+ len = hdata->len < header->caplen ? hdata->len : header->caplen; -+ memcpy(hdata->buffer, packet, len); -+ hdata->len = len; -+} -+ -+int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri) -+{ -+ struct pcap_handler_data hdata = ((struct pcap_handler_data) -+ { .buffer = buffer, -+ .len = len }); -+ int n; -+ -+ n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata); -+ if(n < 0){ -+ printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap)); -+ return(-EIO); -+ } -+ else if(n == 0) -+ return(0); -+ return(hdata.len); -+} -+ -+struct net_user_info pcap_user_info = { -+ .init = pcap_user_init, -+ .open = pcap_open, -+ .close = NULL, -+ .remove = pcap_remove, -+ .set_mtu = NULL, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = MAX_PACKET - ETH_HEADER_OTHER -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/pcap_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/pcap_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/pcap_user.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct pcap_data { -+ char *host_if; -+ int promisc; -+ int optimize; -+ char *filter; -+ void *compiled; -+ void *pcap; -+ void *dev; -+}; -+ -+extern struct net_user_info pcap_user_info; -+ -+extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/port.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/port.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/port.h 2005-05-03 22:28:14.234446248 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PORT_H__ -+#define __PORT_H__ -+ -+extern void *port_data(int port); -+extern int port_wait(void *data); -+extern void port_kern_close(void *d); -+extern int port_connection(int fd, int *socket_out, int *pid_out); -+extern int port_listen_fd(int port); -+extern void port_read(int fd, void *data); -+extern void port_kern_free(void *d); -+extern int port_rcv_fd(int fd); -+extern void port_remove_dev(void *d); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/port_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/port_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/port_kern.c 2005-05-03 22:28:14.235446096 +0300 -@@ -0,0 +1,303 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/list.h" -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "linux/irq.h" -+#include "linux/spinlock.h" -+#include "linux/errno.h" -+#include "asm/semaphore.h" -+#include "asm/errno.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "port.h" -+#include "init.h" -+#include "os.h" -+ -+struct port_list { -+ struct list_head list; -+ int has_connection; -+ struct semaphore sem; -+ int port; -+ int fd; -+ spinlock_t lock; -+ struct list_head pending; -+ struct list_head connections; -+}; -+ -+struct port_dev { -+ struct port_list *port; -+ int helper_pid; -+ int telnetd_pid; -+}; -+ -+struct connection { -+ struct list_head list; -+ int fd; -+ int helper_pid; -+ int socket[2]; -+ int telnetd_pid; -+ struct port_list *port; -+}; -+ -+static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct connection *conn = data; -+ int fd; -+ -+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); -+ if(fd < 0){ -+ if(fd == -EAGAIN) -+ return; -+ -+ printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -+ -fd); -+ os_close_file(conn->fd); -+ } -+ -+ list_del(&conn->list); -+ -+ conn->fd = fd; -+ list_add(&conn->list, &conn->port->connections); -+ -+ up(&conn->port->sem); -+} -+ -+static int port_accept(struct port_list *port) -+{ -+ struct connection *conn; -+ int fd, socket[2], pid, ret = 0; -+ -+ fd = port_connection(port->fd, socket, &pid); -+ if(fd < 0){ -+ if(fd != -EAGAIN) -+ printk(KERN_ERR "port_accept : port_connection " -+ "returned %d\n", -fd); -+ goto out; -+ } -+ -+ conn = kmalloc(sizeof(*conn), GFP_ATOMIC); -+ if(conn == NULL){ -+ printk(KERN_ERR "port_accept : failed to allocate " -+ "connection\n"); -+ goto out_close; -+ } -+ *conn = ((struct connection) -+ { .list = LIST_HEAD_INIT(conn->list), -+ .fd = fd, -+ .socket = { socket[0], socket[1] }, -+ .telnetd_pid = pid, -+ .port = port }); -+ -+ if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "telnetd", conn)){ -+ printk(KERN_ERR "port_accept : failed to get IRQ for " -+ "telnetd\n"); -+ goto out_free; -+ } -+ -+ list_add(&conn->list, &port->pending); -+ return(1); -+ -+ out_free: -+ kfree(conn); -+ out_close: -+ os_close_file(fd); -+ if(pid != -1) -+ os_kill_process(pid, 1); -+ out: -+ return(ret); -+} -+ -+DECLARE_MUTEX(ports_sem); -+struct list_head ports = LIST_HEAD_INIT(ports); -+ -+void port_task_proc(void *unused) -+{ -+ struct port_list *port; -+ struct list_head *ele; -+ unsigned long flags; -+ -+ save_flags(flags); -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ if(!port->has_connection) -+ continue; -+ reactivate_fd(port->fd, ACCEPT_IRQ); -+ while(port_accept(port)) ; -+ port->has_connection = 0; -+ } -+ restore_flags(flags); -+} -+ -+struct tq_struct port_task = { -+ .routine = port_task_proc, -+ .data = NULL -+}; -+ -+static void port_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct port_list *port = data; -+ -+ port->has_connection = 1; -+ schedule_task(&port_task); -+} -+ -+void *port_data(int port_num) -+{ -+ struct list_head *ele; -+ struct port_list *port; -+ struct port_dev *dev = NULL; -+ int fd; -+ -+ down(&ports_sem); -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ if(port->port == port_num) goto found; -+ } -+ port = kmalloc(sizeof(struct port_list), GFP_KERNEL); -+ if(port == NULL){ -+ printk(KERN_ERR "Allocation of port list failed\n"); -+ goto out; -+ } -+ -+ fd = port_listen_fd(port_num); -+ if(fd < 0){ -+ printk(KERN_ERR "binding to port %d failed, errno = %d\n", -+ port_num, -fd); -+ goto out_free; -+ } -+ if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port", -+ port)){ -+ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); -+ goto out_close; -+ } -+ -+ *port = ((struct port_list) -+ { .list = LIST_HEAD_INIT(port->list), -+ .has_connection = 0, -+ .sem = __SEMAPHORE_INITIALIZER(port->sem, -+ 0), -+ .lock = SPIN_LOCK_UNLOCKED, -+ .port = port_num, -+ .fd = fd, -+ .pending = LIST_HEAD_INIT(port->pending), -+ .connections = LIST_HEAD_INIT(port->connections) }); -+ list_add(&port->list, &ports); -+ -+ found: -+ dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL); -+ if(dev == NULL){ -+ printk(KERN_ERR "Allocation of port device entry failed\n"); -+ goto out; -+ } -+ -+ *dev = ((struct port_dev) { .port = port, -+ .helper_pid = -1, -+ .telnetd_pid = -1 }); -+ goto out; -+ -+ out_free: -+ kfree(port); -+ out_close: -+ os_close_file(fd); -+ out: -+ up(&ports_sem); -+ return(dev); -+} -+ -+int port_wait(void *data) -+{ -+ struct port_dev *dev = data; -+ struct connection *conn; -+ struct port_list *port = dev->port; -+ int fd; -+ -+ while(1){ -+ if(down_interruptible(&port->sem)) -+ return(-ERESTARTSYS); -+ -+ spin_lock(&port->lock); -+ -+ conn = list_entry(port->connections.next, struct connection, -+ list); -+ list_del(&conn->list); -+ spin_unlock(&port->lock); -+ -+ os_shutdown_socket(conn->socket[0], 1, 1); -+ os_close_file(conn->socket[0]); -+ os_shutdown_socket(conn->socket[1], 1, 1); -+ os_close_file(conn->socket[1]); -+ -+ /* This is done here because freeing an IRQ can't be done -+ * within the IRQ handler. So, pipe_interrupt always ups -+ * the semaphore regardless of whether it got a successful -+ * connection. Then we loop here throwing out failed -+ * connections until a good one is found. -+ */ -+ free_irq(TELNETD_IRQ, conn); -+ -+ if(conn->fd >= 0) break; -+ os_close_file(conn->fd); -+ kfree(conn); -+ } -+ -+ fd = conn->fd; -+ dev->helper_pid = conn->helper_pid; -+ dev->telnetd_pid = conn->telnetd_pid; -+ kfree(conn); -+ -+ return(fd); -+} -+ -+void port_remove_dev(void *d) -+{ -+ struct port_dev *dev = d; -+ -+ if(dev->helper_pid != -1) -+ os_kill_process(dev->helper_pid, 0); -+ if(dev->telnetd_pid != -1) -+ os_kill_process(dev->telnetd_pid, 1); -+ dev->helper_pid = -1; -+ dev->telnetd_pid = -1; -+} -+ -+void port_kern_free(void *d) -+{ -+ struct port_dev *dev = d; -+ -+ port_remove_dev(dev); -+ kfree(dev); -+} -+ -+static void free_port(void) -+{ -+ struct list_head *ele; -+ struct port_list *port; -+ -+ list_for_each(ele, &ports){ -+ port = list_entry(ele, struct port_list, list); -+ free_irq_by_fd(port->fd); -+ os_close_file(port->fd); -+ } -+} -+ -+__uml_exitcall(free_port); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/port_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/port_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/port_user.c 2005-05-03 22:28:14.237445792 +0300 -@@ -0,0 +1,224 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stddef.h> -+#include <stdlib.h> -+#include <string.h> -+#include <errno.h> -+#include <unistd.h> -+#include <termios.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <netinet/in.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "chan_user.h" -+#include "port.h" -+#include "helper.h" -+#include "os.h" -+ -+struct port_chan { -+ int raw; -+ struct termios tt; -+ void *kernel_data; -+ char dev[sizeof("32768\0")]; -+}; -+ -+void *port_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct port_chan *data; -+ void *kern_data; -+ char *end; -+ int port; -+ -+ if(*str != ':'){ -+ printk("port_init : channel type 'port' must specify a " -+ "port number\n"); -+ return(NULL); -+ } -+ str++; -+ port = strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk("port_init : couldn't parse port '%s'\n", str); -+ return(NULL); -+ } -+ -+ kern_data = port_data(port); -+ if(kern_data == NULL) -+ return(NULL); -+ -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) -+ goto err; -+ -+ *data = ((struct port_chan) { .raw = opts->raw, -+ .kernel_data = kern_data }); -+ sprintf(data->dev, "%d", port); -+ -+ return(data); -+ err: -+ port_kern_free(kern_data); -+ return(NULL); -+} -+ -+void port_free(void *d) -+{ -+ struct port_chan *data = d; -+ -+ port_kern_free(data->kernel_data); -+ kfree(data); -+} -+ -+int port_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct port_chan *data = d; -+ int fd, err; -+ -+ fd = port_wait(data->kernel_data); -+ if((fd >= 0) && data->raw){ -+ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); -+ if(err) -+ return(err); -+ -+ err = raw(fd); -+ if(err) -+ return(err); -+ } -+ *dev_out = data->dev; -+ return(fd); -+} -+ -+void port_close(int fd, void *d) -+{ -+ struct port_chan *data = d; -+ -+ port_remove_dev(data->kernel_data); -+ os_close_file(fd); -+} -+ -+int port_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct port_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops port_ops = { -+ .type = "port", -+ .init = port_init, -+ .open = port_open, -+ .close = port_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = port_console_write, -+ .window_size = generic_window_size, -+ .free = port_free, -+ .winch = 1, -+}; -+ -+int port_listen_fd(int port) -+{ -+ struct sockaddr_in addr; -+ int fd, err, arg; -+ -+ fd = socket(PF_INET, SOCK_STREAM, 0); -+ if(fd == -1) -+ return(-errno); -+ -+ arg = 1; -+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0){ -+ err = -errno; -+ goto out; -+ } -+ -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = htonl(INADDR_ANY); -+ if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ -+ err = -errno; -+ goto out; -+ } -+ -+ if(listen(fd, 1) < 0){ -+ err = -errno; -+ goto out; -+ } -+ -+ err = os_set_fd_block(fd, 0); -+ if(err < 0) -+ goto out; -+ -+ return(fd); -+ out: -+ os_close_file(fd); -+ return(err); -+} -+ -+struct port_pre_exec_data { -+ int sock_fd; -+ int pipe_fd; -+}; -+ -+void port_pre_exec(void *arg) -+{ -+ struct port_pre_exec_data *data = arg; -+ -+ dup2(data->sock_fd, 0); -+ dup2(data->sock_fd, 1); -+ dup2(data->sock_fd, 2); -+ os_close_file(data->sock_fd); -+ dup2(data->pipe_fd, 3); -+ os_shutdown_socket(3, 1, 0); -+ os_close_file(data->pipe_fd); -+} -+ -+int port_connection(int fd, int *socket, int *pid_out) -+{ -+ int new, err; -+ char *argv[] = { "/usr/sbin/in.telnetd", "-L", -+ "/usr/lib/uml/port-helper", NULL }; -+ struct port_pre_exec_data data; -+ -+ new = os_accept_connection(fd); -+ if(new < 0) -+ return(new); -+ -+ err = os_pipe(socket, 0, 0); -+ if(err < 0) -+ goto out_close; -+ -+ data = ((struct port_pre_exec_data) -+ { .sock_fd = new, -+ .pipe_fd = socket[1] }); -+ -+ err = run_helper(port_pre_exec, &data, argv, NULL); -+ if(err < 0) -+ goto out_shutdown; -+ -+ *pid_out = err; -+ return(new); -+ -+ out_shutdown: -+ os_shutdown_socket(socket[0], 1, 1); -+ os_close_file(socket[0]); -+ os_shutdown_socket(socket[1], 1, 1); -+ os_close_file(socket[1]); -+ out_close: -+ os_close_file(new); -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/pty.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/pty.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/pty.c 2005-05-03 22:28:14.238445640 +0300 -@@ -0,0 +1,159 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <termios.h> -+#include "chan_user.h" -+#include "user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "os.h" -+ -+struct pty_chan { -+ void (*announce)(char *dev_name, int dev); -+ int dev; -+ int raw; -+ struct termios tt; -+ char dev_name[sizeof("/dev/pts/0123456\0")]; -+}; -+ -+void *pty_chan_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct pty_chan *data; -+ -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) return(NULL); -+ *data = ((struct pty_chan) { .announce = opts->announce, -+ .dev = device, -+ .raw = opts->raw }); -+ return(data); -+} -+ -+int pts_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct pty_chan *data = d; -+ char *dev; -+ int fd, err; -+ -+ fd = get_pty(); -+ if(fd < 0){ -+ printk("open_pts : Failed to open pts\n"); -+ return(-errno); -+ } -+ if(data->raw){ -+ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); -+ if(err) -+ return(err); -+ -+ err = raw(fd); -+ if(err) -+ return(err); -+ } -+ -+ dev = ptsname(fd); -+ sprintf(data->dev_name, "%s", dev); -+ *dev_out = data->dev_name; -+ if(data->announce) (*data->announce)(dev, data->dev); -+ return(fd); -+} -+ -+int getmaster(char *line) -+{ -+ char *pty, *bank, *cp; -+ int master, err; -+ -+ pty = &line[strlen("/dev/ptyp")]; -+ for (bank = "pqrs"; *bank; bank++) { -+ line[strlen("/dev/pty")] = *bank; -+ *pty = '0'; -+ if (os_stat_file(line, NULL) < 0) -+ break; -+ for (cp = "0123456789abcdef"; *cp; cp++) { -+ *pty = *cp; -+ master = os_open_file(line, of_rdwr(OPENFLAGS()), 0); -+ if (master >= 0) { -+ char *tp = &line[strlen("/dev/")]; -+ -+ /* verify slave side is usable */ -+ *tp = 't'; -+ err = os_access(line, OS_ACC_RW_OK); -+ *tp = 'p'; -+ if(err == 0) return(master); -+ (void) os_close_file(master); -+ } -+ } -+ } -+ return(-1); -+} -+ -+int pty_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct pty_chan *data = d; -+ int fd, err; -+ char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx"; -+ -+ fd = getmaster(dev); -+ if(fd < 0) -+ return(-errno); -+ -+ if(data->raw){ -+ err = raw(fd); -+ if(err) -+ return(err); -+ } -+ -+ if(data->announce) (*data->announce)(dev, data->dev); -+ -+ sprintf(data->dev_name, "%s", dev); -+ *dev_out = data->dev_name; -+ return(fd); -+} -+ -+int pty_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct pty_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops pty_ops = { -+ .type = "pty", -+ .init = pty_chan_init, -+ .open = pty_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = pty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+struct chan_ops pts_ops = { -+ .type = "pts", -+ .init = pty_chan_init, -+ .open = pts_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = pty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slip.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slip.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slip.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,39 @@ -+#ifndef __UM_SLIP_H -+#define __UM_SLIP_H -+ -+#define BUF_SIZE 1500 -+ /* two bytes each for a (pathological) max packet of escaped chars + * -+ * terminating END char + initial END char */ -+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2) -+ -+struct slip_data { -+ void *dev; -+ char name[sizeof("slnnnnn\0")]; -+ char *addr; -+ char *gate_addr; -+ int slave; -+ char ibuf[ENC_BUF_SIZE]; -+ char obuf[ENC_BUF_SIZE]; -+ int more; /* more data: do not read fd until ibuf has been drained */ -+ int pos; -+ int esc; -+}; -+ -+extern struct net_user_info slip_user_info; -+ -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri); -+extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slip_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slip_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slip_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,109 @@ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/stddef.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/if_arp.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "kern.h" -+#include "slip.h" -+ -+struct slip_init { -+ char *gate_addr; -+}; -+ -+void slip_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *private; -+ struct slip_data *spri; -+ struct slip_init *init = data; -+ -+ private = dev->priv; -+ spri = (struct slip_data *) private->user; -+ *spri = ((struct slip_data) -+ { .name = { '\0' }, -+ .addr = NULL, -+ .gate_addr = init->gate_addr, -+ .slave = -1, -+ .ibuf = { '\0' }, -+ .obuf = { '\0' }, -+ .pos = 0, -+ .esc = 0, -+ .dev = dev }); -+ -+ dev->init = NULL; -+ dev->hard_header_len = 0; -+ dev->addr_len = 4; -+ dev->type = ARPHRD_ETHER; -+ dev->tx_queue_len = 256; -+ dev->flags = IFF_NOARP; -+ printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr); -+} -+ -+static unsigned short slip_protocol(struct sk_buff *skbuff) -+{ -+ return(htons(ETH_P_IP)); -+} -+ -+static int slip_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slip_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, -+ (struct slip_data *) &lp->user)); -+} -+ -+static int slip_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slip_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct slip_data *) &lp->user)); -+} -+ -+struct net_kern_info slip_kern_info = { -+ .init = slip_init, -+ .protocol = slip_protocol, -+ .read = slip_read, -+ .write = slip_write, -+}; -+ -+static int slip_setup(char *str, char **mac_out, void *data) -+{ -+ struct slip_init *init = data; -+ -+ *init = ((struct slip_init) -+ { .gate_addr = NULL }); -+ -+ if(str[0] != '\0') -+ init->gate_addr = str; -+ return(1); -+} -+ -+static struct transport slip_transport = { -+ .list = LIST_HEAD_INIT(slip_transport.list), -+ .name = "slip", -+ .setup = slip_setup, -+ .user = &slip_user_info, -+ .kern = &slip_kern_info, -+ .private_size = sizeof(struct slip_data), -+ .setup_size = sizeof(struct slip_init), -+}; -+ -+static int register_slip(void) -+{ -+ register_transport(&slip_transport); -+ return(1); -+} -+ -+__initcall(register_slip); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slip_proto.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slip_proto.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slip_proto.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,93 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SLIP_PROTO_H__ -+#define __UM_SLIP_PROTO_H__ -+ -+/* SLIP protocol characters. */ -+#define SLIP_END 0300 /* indicates end of frame */ -+#define SLIP_ESC 0333 /* indicates byte stuffing */ -+#define SLIP_ESC_END 0334 /* ESC ESC_END means END 'data' */ -+#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */ -+ -+static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc) -+{ -+ int ret; -+ -+ switch(c){ -+ case SLIP_END: -+ *esc = 0; -+ ret=*pos; -+ *pos=0; -+ return(ret); -+ case SLIP_ESC: -+ *esc = 1; -+ return(0); -+ case SLIP_ESC_ESC: -+ if(*esc){ -+ *esc = 0; -+ c = SLIP_ESC; -+ } -+ break; -+ case SLIP_ESC_END: -+ if(*esc){ -+ *esc = 0; -+ c = SLIP_END; -+ } -+ break; -+ } -+ buf[(*pos)++] = c; -+ return(0); -+} -+ -+static inline int slip_esc(unsigned char *s, unsigned char *d, int len) -+{ -+ unsigned char *ptr = d; -+ unsigned char c; -+ -+ /* -+ * Send an initial END character to flush out any -+ * data that may have accumulated in the receiver -+ * due to line noise. -+ */ -+ -+ *ptr++ = SLIP_END; -+ -+ /* -+ * For each byte in the packet, send the appropriate -+ * character sequence, according to the SLIP protocol. -+ */ -+ -+ while (len-- > 0) { -+ switch(c = *s++) { -+ case SLIP_END: -+ *ptr++ = SLIP_ESC; -+ *ptr++ = SLIP_ESC_END; -+ break; -+ case SLIP_ESC: -+ *ptr++ = SLIP_ESC; -+ *ptr++ = SLIP_ESC_ESC; -+ break; -+ default: -+ *ptr++ = c; -+ break; -+ } -+ } -+ *ptr++ = SLIP_END; -+ return (ptr - d); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slip_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slip_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slip_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,276 @@ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <stddef.h> -+#include <sched.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/termios.h> -+#include <sys/wait.h> -+#include <sys/signal.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "net_user.h" -+#include "slip.h" -+#include "slip_proto.h" -+#include "helper.h" -+#include "os.h" -+ -+void slip_user_init(void *data, void *dev) -+{ -+ struct slip_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+static int set_up_tty(int fd) -+{ -+ int i; -+ struct termios tios; -+ -+ if (tcgetattr(fd, &tios) < 0) { -+ printk("could not get initial terminal attributes\n"); -+ return(-1); -+ } -+ -+ tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; -+ tios.c_iflag = IGNBRK | IGNPAR; -+ tios.c_oflag = 0; -+ tios.c_lflag = 0; -+ for (i = 0; i < NCCS; i++) -+ tios.c_cc[i] = 0; -+ tios.c_cc[VMIN] = 1; -+ tios.c_cc[VTIME] = 0; -+ -+ cfsetospeed(&tios, B38400); -+ cfsetispeed(&tios, B38400); -+ -+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { -+ printk("failed to set terminal attributes\n"); -+ return(-1); -+ } -+ return(0); -+} -+ -+struct slip_pre_exec_data { -+ int stdin; -+ int stdout; -+ int close_me; -+}; -+ -+static void slip_pre_exec(void *arg) -+{ -+ struct slip_pre_exec_data *data = arg; -+ -+ if(data->stdin >= 0) dup2(data->stdin, 0); -+ dup2(data->stdout, 1); -+ if(data->close_me >= 0) os_close_file(data->close_me); -+} -+ -+static int slip_tramp(char **argv, int fd) -+{ -+ struct slip_pre_exec_data pe_data; -+ char *output; -+ int status, pid, fds[2], err, output_len; -+ -+ err = os_pipe(fds, 1, 0); -+ if(err < 0){ -+ printk("slip_tramp : pipe failed, err = %d\n", -err); -+ return(err); -+ } -+ -+ err = 0; -+ pe_data.stdin = fd; -+ pe_data.stdout = fds[1]; -+ pe_data.close_me = fds[0]; -+ pid = run_helper(slip_pre_exec, &pe_data, argv, NULL); -+ -+ if(pid < 0) err = pid; -+ else { -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ if(output == NULL) -+ printk("slip_tramp : failed to allocate output " -+ "buffer\n"); -+ -+ os_close_file(fds[1]); -+ read_output(fds[0], output, output_len); -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+ CATCH_EINTR(err = waitpid(pid, &status, 0)); -+ if(err < 0) -+ err = errno; -+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ -+ printk("'%s' didn't exit with status 0\n", argv[0]); -+ err = -EINVAL; -+ } -+ } -+ return(err); -+} -+ -+static int slip_open(void *data) -+{ -+ struct slip_data *pri = data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, -+ NULL }; -+ int sfd, mfd, err; -+ -+ mfd = get_pty(); -+ if(mfd < 0){ -+ printk("umn : Failed to open pty, err = %d\n", -mfd); -+ return(mfd); -+ } -+ sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); -+ if(sfd < 0){ -+ printk("Couldn't open tty for slip line, err = %d\n", -sfd); -+ return(sfd); -+ } -+ if(set_up_tty(sfd)) return(-1); -+ pri->slave = sfd; -+ pri->pos = 0; -+ pri->esc = 0; -+ if(pri->gate_addr != NULL){ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ strcpy(gate_buf, pri->gate_addr); -+ -+ err = slip_tramp(argv, sfd); -+ -+ if(err < 0){ -+ printk("slip_tramp failed - err = %d\n", -err); -+ return(err); -+ } -+ err = os_get_ifname(pri->slave, pri->name); -+ if(err < 0){ -+ printk("get_ifname failed, err = %d\n", -err); -+ return(err); -+ } -+ iter_addresses(pri->dev, open_addr, pri->name); -+ } -+ else { -+ err = os_set_slip(sfd); -+ if(err < 0){ -+ printk("Failed to set slip discipline encapsulation - " -+ "err = %d\n", -err); -+ return(err); -+ } -+ } -+ return(mfd); -+} -+ -+static void slip_close(int fd, void *data) -+{ -+ struct slip_data *pri = data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name, -+ NULL }; -+ int err; -+ -+ if(pri->gate_addr != NULL) -+ iter_addresses(pri->dev, close_addr, pri->name); -+ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ -+ err = slip_tramp(argv, -1); -+ -+ if(err != 0) -+ printk("slip_tramp failed - errno = %d\n", -err); -+ os_close_file(fd); -+ os_close_file(pri->slave); -+ pri->slave = -1; -+} -+ -+int slip_user_read(int fd, void *buf, int len, struct slip_data *pri) -+{ -+ int i, n, size, start; -+ -+ if(pri->more>0) { -+ i = 0; -+ while(i < pri->more) { -+ size = slip_unesc(pri->ibuf[i++], -+ pri->ibuf, &pri->pos, &pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); -+ pri->more=pri->more-i; -+ return(size); -+ } -+ } -+ pri->more=0; -+ } -+ -+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); -+ if(n <= 0) return(n); -+ -+ start = pri->pos; -+ for(i = 0; i < n; i++){ -+ size = slip_unesc(pri->ibuf[start + i], -+ pri->ibuf, &pri->pos, &pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); -+ pri->more=n-(i+1); -+ return(size); -+ } -+ } -+ return(0); -+} -+ -+int slip_user_write(int fd, void *buf, int len, struct slip_data *pri) -+{ -+ int actual, n; -+ -+ actual = slip_esc(buf, pri->obuf, len); -+ n = net_write(fd, pri->obuf, actual); -+ if(n < 0) return(n); -+ else return(len); -+} -+ -+static int slip_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+static void slip_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct slip_data *pri = data; -+ -+ if(pri->slave < 0) return; -+ open_addr(addr, netmask, pri->name); -+} -+ -+static void slip_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct slip_data *pri = data; -+ -+ if(pri->slave < 0) return; -+ close_addr(addr, netmask, pri->name); -+} -+ -+struct net_user_info slip_user_info = { -+ .init = slip_user_init, -+ .open = slip_open, -+ .close = slip_close, -+ .remove = NULL, -+ .set_mtu = slip_set_mtu, -+ .add_address = slip_add_addr, -+ .delete_address = slip_del_addr, -+ .max_packet = BUF_SIZE -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slirp.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slirp.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slirp.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,51 @@ -+#ifndef __UM_SLIRP_H -+#define __UM_SLIRP_H -+ -+#define BUF_SIZE 1500 -+ /* two bytes each for a (pathological) max packet of escaped chars + * -+ * terminating END char + initial END char */ -+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2) -+ -+#define SLIRP_MAX_ARGS 100 -+/* -+ * XXX this next definition is here because I don't understand why this -+ * initializer doesn't work in slirp_kern.c: -+ * -+ * argv : { init->argv[ 0 ... SLIRP_MAX_ARGS-1 ] }, -+ * -+ * or why I can't typecast like this: -+ * -+ * argv : (char* [SLIRP_MAX_ARGS])(init->argv), -+ */ -+struct arg_list_dummy_wrapper { char *argv[SLIRP_MAX_ARGS]; }; -+ -+struct slirp_data { -+ void *dev; -+ struct arg_list_dummy_wrapper argw; -+ int pid; -+ int slave; -+ char ibuf[ENC_BUF_SIZE]; -+ char obuf[ENC_BUF_SIZE]; -+ int more; /* more data: do not read fd until ibuf has been drained */ -+ int pos; -+ int esc; -+}; -+ -+extern struct net_user_info slirp_user_info; -+ -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri); -+extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slirp_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slirp_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slirp_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,132 @@ -+#include "linux/kernel.h" -+#include "linux/stddef.h" -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/if_arp.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "kern.h" -+#include "slirp.h" -+ -+struct slirp_init { -+ struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */ -+}; -+ -+void slirp_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *private; -+ struct slirp_data *spri; -+ struct slirp_init *init = data; -+ int i; -+ -+ private = dev->priv; -+ spri = (struct slirp_data *) private->user; -+ *spri = ((struct slirp_data) -+ { .argw = init->argw, -+ .pid = -1, -+ .slave = -1, -+ .ibuf = { '\0' }, -+ .obuf = { '\0' }, -+ .pos = 0, -+ .esc = 0, -+ .dev = dev }); -+ -+ dev->init = NULL; -+ dev->hard_header_len = 0; -+ dev->addr_len = 4; -+ dev->type = ARPHRD_ETHER; -+ dev->tx_queue_len = 256; -+ dev->flags = IFF_NOARP; -+ printk("SLIRP backend - command line:"); -+ for(i=0;spri->argw.argv[i]!=NULL;i++) { -+ printk(" '%s'",spri->argw.argv[i]); -+ } -+ printk("\n"); -+} -+ -+static unsigned short slirp_protocol(struct sk_buff *skbuff) -+{ -+ return(htons(ETH_P_IP)); -+} -+ -+static int slirp_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, -+ (struct slirp_data *) &lp->user)); -+} -+ -+static int slirp_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(slirp_user_write(fd, (*skb)->data, (*skb)->len, -+ (struct slirp_data *) &lp->user)); -+} -+ -+struct net_kern_info slirp_kern_info = { -+ .init = slirp_init, -+ .protocol = slirp_protocol, -+ .read = slirp_read, -+ .write = slirp_write, -+}; -+ -+static int slirp_setup(char *str, char **mac_out, void *data) -+{ -+ struct slirp_init *init = data; -+ int i=0; -+ -+ *init = ((struct slirp_init) -+ { argw : { { "slirp", NULL } } }); -+ -+ str = split_if_spec(str, mac_out, NULL); -+ -+ if(str == NULL) { /* no command line given after MAC addr */ -+ return(1); -+ } -+ -+ do { -+ if(i>=SLIRP_MAX_ARGS-1) { -+ printk("slirp_setup: truncating slirp arguments\n"); -+ break; -+ } -+ init->argw.argv[i++] = str; -+ while(*str && *str!=',') { -+ if(*str=='_') *str=' '; -+ str++; -+ } -+ if(*str!=',') -+ break; -+ *str++='\0'; -+ } while(1); -+ init->argw.argv[i]=NULL; -+ return(1); -+} -+ -+static struct transport slirp_transport = { -+ .list = LIST_HEAD_INIT(slirp_transport.list), -+ .name = "slirp", -+ .setup = slirp_setup, -+ .user = &slirp_user_info, -+ .kern = &slirp_kern_info, -+ .private_size = sizeof(struct slirp_data), -+ .setup_size = sizeof(struct slirp_init), -+}; -+ -+static int register_slirp(void) -+{ -+ register_transport(&slirp_transport); -+ return(1); -+} -+ -+__initcall(register_slirp); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/slirp_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/slirp_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/slirp_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,201 @@ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <stddef.h> -+#include <sched.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/wait.h> -+#include <sys/signal.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "net_user.h" -+#include "slirp.h" -+#include "slip_proto.h" -+#include "helper.h" -+#include "os.h" -+ -+void slirp_user_init(void *data, void *dev) -+{ -+ struct slirp_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+struct slirp_pre_exec_data { -+ int stdin; -+ int stdout; -+}; -+ -+static void slirp_pre_exec(void *arg) -+{ -+ struct slirp_pre_exec_data *data = arg; -+ -+ if(data->stdin != -1) dup2(data->stdin, 0); -+ if(data->stdout != -1) dup2(data->stdout, 1); -+} -+ -+static int slirp_tramp(char **argv, int fd) -+{ -+ struct slirp_pre_exec_data pe_data; -+ int pid; -+ -+ pe_data.stdin = fd; -+ pe_data.stdout = fd; -+ pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL); -+ -+ return(pid); -+} -+ -+/* XXX This is just a trivial wrapper around os_pipe */ -+static int slirp_datachan(int *mfd, int *sfd) -+{ -+ int fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err < 0){ -+ printk("slirp_datachan: Failed to open pipe, err = %d\n", -err); -+ return(err); -+ } -+ -+ *mfd = fds[0]; -+ *sfd = fds[1]; -+ return(0); -+} -+ -+static int slirp_open(void *data) -+{ -+ struct slirp_data *pri = data; -+ int sfd, mfd, pid, err; -+ -+ err = slirp_datachan(&mfd, &sfd); -+ if(err) -+ return(err); -+ -+ pid = slirp_tramp(pri->argw.argv, sfd); -+ -+ if(pid < 0){ -+ printk("slirp_tramp failed - errno = %d\n", -pid); -+ os_close_file(sfd); -+ os_close_file(mfd); -+ return(pid); -+ } -+ -+ pri->slave = sfd; -+ pri->pos = 0; -+ pri->esc = 0; -+ -+ pri->pid = pid; -+ -+ return(mfd); -+} -+ -+static void slirp_close(int fd, void *data) -+{ -+ struct slirp_data *pri = data; -+ int status,err; -+ -+ os_close_file(fd); -+ os_close_file(pri->slave); -+ -+ pri->slave = -1; -+ -+ if(pri->pid<1) { -+ printk("slirp_close: no child process to shut down\n"); -+ return; -+ } -+ -+#if 0 -+ if(kill(pri->pid, SIGHUP)<0) { -+ printk("slirp_close: sending hangup to %d failed (%d)\n", -+ pri->pid, errno); -+ } -+#endif -+ -+ CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); -+ if(err < 0) { -+ printk("slirp_close: waitpid returned %d\n", errno); -+ return; -+ } -+ -+ if(err == 0) { -+ printk("slirp_close: process %d has not exited\n"); -+ return; -+ } -+ -+ pri->pid = -1; -+} -+ -+int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) -+{ -+ int i, n, size, start; -+ -+ if(pri->more>0) { -+ i = 0; -+ while(i < pri->more) { -+ size = slip_unesc(pri->ibuf[i++], -+ pri->ibuf,&pri->pos,&pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); -+ pri->more=pri->more-i; -+ return(size); -+ } -+ } -+ pri->more=0; -+ } -+ -+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); -+ if(n <= 0) return(n); -+ -+ start = pri->pos; -+ for(i = 0; i < n; i++){ -+ size = slip_unesc(pri->ibuf[start + i], -+ pri->ibuf,&pri->pos,&pri->esc); -+ if(size){ -+ memcpy(buf, pri->ibuf, size); -+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); -+ pri->more=n-(i+1); -+ return(size); -+ } -+ } -+ return(0); -+} -+ -+int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) -+{ -+ int actual, n; -+ -+ actual = slip_esc(buf, pri->obuf, len); -+ n = net_write(fd, pri->obuf, actual); -+ if(n < 0) return(n); -+ else return(len); -+} -+ -+static int slirp_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info slirp_user_info = { -+ .init = slirp_user_init, -+ .open = slirp_open, -+ .close = slirp_close, -+ .remove = NULL, -+ .set_mtu = slirp_set_mtu, -+ .add_address = NULL, -+ .delete_address = NULL, -+ .max_packet = BUF_SIZE -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/ssl.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/ssl.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/ssl.c 2005-05-03 22:28:14.247444272 +0300 -@@ -0,0 +1,300 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/fs.h" -+#include "linux/tty.h" -+#include "linux/tty_driver.h" -+#include "linux/major.h" -+#include "linux/mm.h" -+#include "linux/init.h" -+#include "linux/console.h" -+#include "asm/termbits.h" -+#include "asm/irq.h" -+#include "line.h" -+#include "ssl.h" -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "mconsole_kern.h" -+#include "2_5compat.h" -+ -+static int ssl_version = 1; -+ -+/* Referenced only by tty_driver below - presumably it's locked correctly -+ * by the tty driver. -+ */ -+static int ssl_refcount = 0; -+ -+static struct tty_driver ssl_driver; -+ -+#define NR_PORTS 64 -+ -+void ssl_announce(char *dev_name, int dev) -+{ -+ printk(KERN_INFO "Serial line %d assigned device '%s'\n", dev, -+ dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = ssl_announce, -+ .xterm_title = "Serial Line #%d", -+ .raw = 1, -+ .tramp_stack = 0, -+ .in_kernel = 1, -+}; -+ -+static int ssl_config(char *str); -+static int ssl_get_config(char *dev, char *str, int size, char **error_out); -+static int ssl_remove(char *str); -+ -+static struct line_driver driver = { -+ .name = "UML serial line", -+ .devfs_name = "tts/%d", -+ .major = TTY_MAJOR, -+ .minor_start = 64, -+ .type = TTY_DRIVER_TYPE_SERIAL, -+ .subtype = 0, -+ .read_irq = SSL_IRQ, -+ .read_irq_name = "ssl", -+ .write_irq = SSL_WRITE_IRQ, -+ .write_irq_name = "ssl-write", -+ .symlink_from = "serial", -+ .symlink_to = "tts", -+ .mc = { -+ .name = "ssl", -+ .config = ssl_config, -+ .get_config = ssl_get_config, -+ .remove = ssl_remove, -+ }, -+}; -+ -+/* The array is initialized by line_init, which is an initcall. The -+ * individual elements are protected by individual semaphores. -+ */ -+static struct line serial_lines[NR_PORTS] = -+ { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; -+ -+static struct lines lines = LINES_INIT(NR_PORTS); -+ -+static int ssl_config(char *str) -+{ -+ return(line_config(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), str)); -+} -+ -+static int ssl_get_config(char *dev, char *str, int size, char **error_out) -+{ -+ return(line_get_config(dev, serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), -+ str, size, error_out)); -+} -+ -+static int ssl_remove(char *str) -+{ -+ return(line_remove(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), str)); -+} -+ -+int ssl_open(struct tty_struct *tty, struct file *filp) -+{ -+ return(line_open(serial_lines, tty, &opts)); -+} -+ -+static void ssl_close(struct tty_struct *tty, struct file * filp) -+{ -+ line_close(serial_lines, tty); -+} -+ -+static int ssl_write(struct tty_struct * tty, int from_user, -+ const unsigned char *buf, int count) -+{ -+ return(line_write(serial_lines, tty, from_user, buf, count)); -+} -+ -+static void ssl_put_char(struct tty_struct *tty, unsigned char ch) -+{ -+ line_write(serial_lines, tty, 0, &ch, sizeof(ch)); -+} -+ -+static void ssl_flush_chars(struct tty_struct *tty) -+{ -+ return; -+} -+ -+static int ssl_chars_in_buffer(struct tty_struct *tty) -+{ -+ return(0); -+} -+ -+static void ssl_flush_buffer(struct tty_struct *tty) -+{ -+ return; -+} -+ -+static int ssl_ioctl(struct tty_struct *tty, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ int ret; -+ -+ ret = 0; -+ switch(cmd){ -+ case TCGETS: -+ case TCSETS: -+ case TCFLSH: -+ case TCSETSF: -+ case TCSETSW: -+ case TCGETA: -+ case TIOCMGET: -+ case TCSBRK: -+ case TCSBRKP: -+ case TIOCMSET: -+ ret = -ENOIOCTLCMD; -+ break; -+ default: -+ printk(KERN_ERR -+ "Unimplemented ioctl in ssl_ioctl : 0x%x\n", cmd); -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return(ret); -+} -+ -+static void ssl_throttle(struct tty_struct * tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_throttle\n"); -+} -+ -+static void ssl_unthrottle(struct tty_struct * tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_unthrottle\n"); -+} -+ -+static void ssl_set_termios(struct tty_struct *tty, -+ struct termios *old_termios) -+{ -+} -+ -+static void ssl_stop(struct tty_struct *tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_stop\n"); -+} -+ -+static void ssl_start(struct tty_struct *tty) -+{ -+ printk(KERN_ERR "Someone should implement ssl_start\n"); -+} -+ -+void ssl_hangup(struct tty_struct *tty) -+{ -+} -+ -+static struct tty_driver ssl_driver = { -+ .refcount = &ssl_refcount, -+ .open = ssl_open, -+ .close = ssl_close, -+ .write = ssl_write, -+ .put_char = ssl_put_char, -+ .flush_chars = ssl_flush_chars, -+ .chars_in_buffer = ssl_chars_in_buffer, -+ .flush_buffer = ssl_flush_buffer, -+ .ioctl = ssl_ioctl, -+ .throttle = ssl_throttle, -+ .unthrottle = ssl_unthrottle, -+ .set_termios = ssl_set_termios, -+ .stop = ssl_stop, -+ .start = ssl_start, -+ .hangup = ssl_hangup -+}; -+ -+/* Changed by ssl_init and referenced by ssl_exit, which are both serialized -+ * by being an initcall and exitcall, respectively. -+ */ -+static int ssl_init_done = 0; -+ -+static void ssl_console_write(struct console *c, const char *string, -+ unsigned len) -+{ -+ struct line *line = &serial_lines[c->index]; -+ if(ssl_init_done) -+ down(&line->sem); -+ console_write_chan(&line->chan_list, string, len); -+ if(ssl_init_done) -+ up(&line->sem); -+} -+ -+static kdev_t ssl_console_device(struct console *c) -+{ -+ return mk_kdev(TTY_MAJOR, c->index); -+} -+ -+static int ssl_console_setup(struct console *co, char *options) -+{ -+ return(0); -+} -+ -+static struct console ssl_cons = { -+ name: "ttyS", -+ write: ssl_console_write, -+ device: ssl_console_device, -+ setup: ssl_console_setup, -+ flags: CON_PRINTBUFFER, -+ index: -1, -+}; -+ -+int ssl_init(void) -+{ -+ char *new_title; -+ -+ printk(KERN_INFO "Initializing software serial port version %d\n", -+ ssl_version); -+ -+ line_register_devfs(&lines, &driver, &ssl_driver, serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0])); -+ -+ lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); -+ -+ new_title = add_xterm_umid(opts.xterm_title); -+ if(new_title != NULL) opts.xterm_title = new_title; -+ -+ register_console(&ssl_cons); -+ ssl_init_done = 1; -+ return(0); -+} -+ -+__initcall(ssl_init); -+ -+static int ssl_chan_setup(char *str) -+{ -+ return(line_setup(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0]), -+ str, 1)); -+} -+ -+__setup("ssl", ssl_chan_setup); -+__channel_help(ssl_chan_setup, "ssl"); -+ -+static void ssl_exit(void) -+{ -+ if(!ssl_init_done) return; -+ close_lines(serial_lines, -+ sizeof(serial_lines)/sizeof(serial_lines[0])); -+} -+ -+__uml_exitcall(ssl_exit); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/ssl.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/ssl.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/ssl.h 2005-05-03 22:28:14.248444120 +0300 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SSL_H__ -+#define __SSL_H__ -+ -+extern int ssl_read(int fd, int line); -+extern void ssl_receive_char(int line, char ch); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/stdio_console.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/stdio_console.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/stdio_console.c 2005-05-03 22:28:14.249443968 +0300 -@@ -0,0 +1,258 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/posix_types.h" -+#include "linux/tty.h" -+#include "linux/tty_flip.h" -+#include "linux/types.h" -+#include "linux/major.h" -+#include "linux/kdev_t.h" -+#include "linux/console.h" -+#include "linux/string.h" -+#include "linux/sched.h" -+#include "linux/list.h" -+#include "linux/init.h" -+#include "linux/interrupt.h" -+#include "linux/slab.h" -+#include "asm/current.h" -+#include "asm/softirq.h" -+#include "asm/hardirq.h" -+#include "asm/irq.h" -+#include "stdio_console.h" -+#include "line.h" -+#include "chan_kern.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "2_5compat.h" -+ -+#define MAX_TTYS (8) -+ -+/* Referenced only by tty_driver below - presumably it's locked correctly -+ * by the tty driver. -+ */ -+ -+static struct tty_driver console_driver; -+ -+static int console_refcount = 0; -+ -+static struct chan_ops init_console_ops = { -+ .type = "you shouldn't see this", -+ .init = NULL, -+ .open = NULL, -+ .close = NULL, -+ .read = NULL, -+ .write = NULL, -+ .console_write = generic_write, -+ .window_size = NULL, -+ .free = NULL, -+ .winch = 0, -+}; -+ -+static struct chan init_console_chan = { -+ .list = { }, -+ .primary = 1, -+ .input = 0, -+ .output = 1, -+ .opened = 1, -+ .fd = 1, -+ .pri = INIT_STATIC, -+ .ops = &init_console_ops, -+ .data = NULL -+}; -+ -+void stdio_announce(char *dev_name, int dev) -+{ -+ printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, -+ dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = stdio_announce, -+ .xterm_title = "Virtual Console #%d", -+ .raw = 1, -+ .tramp_stack = 0, -+ .in_kernel = 1, -+}; -+ -+static int con_config(char *str); -+static int con_get_config(char *dev, char *str, int size, char **error_out); -+static int con_remove(char *str); -+ -+static struct line_driver driver = { -+ .name = "UML console", -+ .devfs_name = "vc/%d", -+ .major = TTY_MAJOR, -+ .minor_start = 0, -+ .type = TTY_DRIVER_TYPE_CONSOLE, -+ .subtype = SYSTEM_TYPE_CONSOLE, -+ .read_irq = CONSOLE_IRQ, -+ .read_irq_name = "console", -+ .write_irq = CONSOLE_WRITE_IRQ, -+ .write_irq_name = "console-write", -+ .symlink_from = "ttys", -+ .symlink_to = "vc", -+ .mc = { -+ .name = "con", -+ .config = con_config, -+ .get_config = con_get_config, -+ .remove = con_remove, -+ }, -+}; -+ -+static struct lines console_lines = LINES_INIT(MAX_TTYS); -+ -+/* The array is initialized by line_init, which is an initcall. The -+ * individual elements are protected by individual semaphores. -+ */ -+struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), -+ [ 1 ... MAX_TTYS - 1 ] = -+ LINE_INIT(CONFIG_CON_CHAN, &driver) }; -+ -+static int con_config(char *str) -+{ -+ return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); -+} -+ -+static int con_get_config(char *dev, char *str, int size, char **error_out) -+{ -+ return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, -+ size, error_out)); -+} -+ -+static int con_remove(char *str) -+{ -+ return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str)); -+} -+ -+static int open_console(struct tty_struct *tty) -+{ -+ return(line_open(vts, tty, &opts)); -+} -+ -+static int con_open(struct tty_struct *tty, struct file *filp) -+{ -+ return(open_console(tty)); -+} -+ -+static void con_close(struct tty_struct *tty, struct file *filp) -+{ -+ line_close(vts, tty); -+} -+ -+static int con_write(struct tty_struct *tty, int from_user, -+ const unsigned char *buf, int count) -+{ -+ return(line_write(vts, tty, from_user, buf, count)); -+} -+ -+static void set_termios(struct tty_struct *tty, struct termios * old) -+{ -+} -+ -+static int chars_in_buffer(struct tty_struct *tty) -+{ -+ return(0); -+} -+ -+static int con_init_done = 0; -+ -+int stdio_init(void) -+{ -+ char *new_title; -+ -+ printk(KERN_INFO "Initializing stdio console driver\n"); -+ -+ line_register_devfs(&console_lines, &driver, &console_driver, vts, -+ sizeof(vts)/sizeof(vts[0])); -+ -+ lines_init(vts, sizeof(vts)/sizeof(vts[0])); -+ -+ new_title = add_xterm_umid(opts.xterm_title); -+ if(new_title != NULL) opts.xterm_title = new_title; -+ -+ open_console(NULL); -+ con_init_done = 1; -+ return(0); -+} -+ -+__initcall(stdio_init); -+ -+static void console_write(struct console *console, const char *string, -+ unsigned len) -+{ -+ struct line *line = &vts[console->index]; -+ -+ if(con_init_done) -+ down(&line->sem); -+ console_write_chan(&line->chan_list, string, len); -+ if(con_init_done) -+ up(&line->sem); -+} -+ -+static struct tty_driver console_driver = { -+ .refcount = &console_refcount, -+ .open = con_open, -+ .close = con_close, -+ .write = con_write, -+ .chars_in_buffer = chars_in_buffer, -+ .set_termios = set_termios -+}; -+ -+static kdev_t console_device(struct console *c) -+{ -+ return mk_kdev(TTY_MAJOR, c->index); -+} -+ -+static int console_setup(struct console *co, char *options) -+{ -+ return(0); -+} -+ -+static struct console stdiocons = { -+ name: "tty", -+ write: console_write, -+ device: console_device, -+ setup: console_setup, -+ flags: CON_PRINTBUFFER, -+ index: -1, -+}; -+ -+void stdio_console_init(void) -+{ -+ INIT_LIST_HEAD(&vts[0].chan_list); -+ list_add(&init_console_chan.list, &vts[0].chan_list); -+ register_console(&stdiocons); -+} -+ -+static int console_chan_setup(char *str) -+{ -+ return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); -+} -+ -+__setup("con", console_chan_setup); -+__channel_help(console_chan_setup, "con"); -+ -+static void console_exit(void) -+{ -+ if(!con_init_done) return; -+ close_lines(vts, sizeof(vts)/sizeof(vts[0])); -+} -+ -+__uml_exitcall(console_exit); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/stdio_console.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/stdio_console.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/stdio_console.h 2005-05-03 22:28:14.250443816 +0300 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __STDIO_CONSOLE_H -+#define __STDIO_CONSOLE_H -+ -+extern void save_console_flags(void); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/tty.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/tty.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/tty.c 2005-05-03 22:28:14.251443664 +0300 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <termios.h> -+#include <errno.h> -+#include <unistd.h> -+#include "chan_user.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+ -+struct tty_chan { -+ char *dev; -+ int raw; -+ struct termios tt; -+}; -+ -+void *tty_chan_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct tty_chan *data; -+ -+ if(*str != ':'){ -+ printk("tty_init : channel type 'tty' must specify " -+ "a device\n"); -+ return(NULL); -+ } -+ str++; -+ -+ data = um_kmalloc(sizeof(*data)); -+ if(data == NULL) -+ return(NULL); -+ *data = ((struct tty_chan) { .dev = str, -+ .raw = opts->raw }); -+ -+ return(data); -+} -+ -+int tty_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct tty_chan *data = d; -+ int fd, err; -+ -+ fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0); -+ if(fd < 0) return(fd); -+ if(data->raw){ -+ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); -+ if(err) -+ return(err); -+ -+ err = raw(fd); -+ if(err) -+ return(err); -+ } -+ -+ *dev_out = data->dev; -+ return(fd); -+} -+ -+int tty_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct tty_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops tty_ops = { -+ .type = "tty", -+ .init = tty_chan_init, -+ .open = tty_open, -+ .close = generic_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = tty_console_write, -+ .window_size = generic_window_size, -+ .free = generic_free, -+ .winch = 0, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/ubd_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/ubd_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/ubd_kern.c 2005-05-03 22:28:14.257442752 +0300 -@@ -0,0 +1,1380 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+/* 2001-09-28...2002-04-17 -+ * Partition stuff by James_McMechan@hotmail.com -+ * old style ubd by setting UBD_SHIFT to 0 -+ */ -+ -+#define MAJOR_NR UBD_MAJOR -+#define UBD_SHIFT 4 -+ -+#include "linux/config.h" -+#include "linux/blk.h" -+#include "linux/blkdev.h" -+#include "linux/hdreg.h" -+#include "linux/init.h" -+#include "linux/devfs_fs_kernel.h" -+#include "linux/cdrom.h" -+#include "linux/proc_fs.h" -+#include "linux/ctype.h" -+#include "linux/capability.h" -+#include "linux/mm.h" -+#include "linux/vmalloc.h" -+#include "linux/blkpg.h" -+#include "linux/genhd.h" -+#include "linux/spinlock.h" -+#include "asm/segment.h" -+#include "asm/uaccess.h" -+#include "asm/irq.h" -+#include "asm/types.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mconsole_kern.h" -+#include "init.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "ubd_user.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "mem.h" -+#include "mem_kern.h" -+ -+static int ubd_open(struct inode * inode, struct file * filp); -+static int ubd_release(struct inode * inode, struct file * file); -+static int ubd_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg); -+static int ubd_revalidate(kdev_t rdev); -+static int ubd_revalidate1(kdev_t rdev); -+ -+#define MAX_DEV (8) -+#define MAX_MINOR (MAX_DEV << UBD_SHIFT) -+ -+/* Changed in early boot */ -+static int ubd_do_mmap = 0; -+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE -+ -+/* Not modified by this driver */ -+static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE }; -+static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 }; -+ -+/* Protected by ubd_lock */ -+static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 }; -+ -+static struct block_device_operations ubd_blops = { -+ .open = ubd_open, -+ .release = ubd_release, -+ .ioctl = ubd_ioctl, -+ .revalidate = ubd_revalidate, -+}; -+ -+/* Protected by ubd_lock, except in prepare_request and ubd_ioctl because -+ * the block layer should ensure that the device is idle before closing it. -+ */ -+static struct hd_struct ubd_part[MAX_MINOR] = -+ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } }; -+ -+/* Protected by io_request_lock */ -+static request_queue_t *ubd_queue; -+ -+/* Protected by ubd_lock */ -+static int fake_major = MAJOR_NR; -+ -+static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED; -+ -+#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \ -+{ \ -+ .major = maj, \ -+ .major_name = name, \ -+ .minor_shift = shift, \ -+ .max_p = 1 << shift, \ -+ .part = parts, \ -+ .sizes = bsizes, \ -+ .nr_real = max, \ -+ .real_devices = NULL, \ -+ .next = NULL, \ -+ .fops = blops, \ -+ .de_arr = NULL, \ -+ .flags = 0 \ -+} -+ -+static struct gendisk ubd_gendisk = INIT_GENDISK(MAJOR_NR, "ubd", ubd_part, -+ UBD_SHIFT, sizes, MAX_DEV, -+ &ubd_blops); -+static struct gendisk fake_gendisk = INIT_GENDISK(0, "ubd", ubd_part, -+ UBD_SHIFT, sizes, MAX_DEV, -+ &ubd_blops); -+ -+#ifdef CONFIG_BLK_DEV_UBD_SYNC -+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \ -+ .cl = 1 }) -+#else -+#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \ -+ .cl = 1 }) -+#endif -+ -+/* Not protected - changed only in ubd_setup_common and then only to -+ * to enable O_SYNC. -+ */ -+static struct openflags global_openflags = OPEN_FLAGS; -+ -+struct cow { -+ char *file; -+ int fd; -+ unsigned long *bitmap; -+ unsigned long bitmap_len; -+ int bitmap_offset; -+ int data_offset; -+}; -+ -+struct ubd { -+ char *file; -+ int count; -+ int fd; -+ __u64 size; -+ struct openflags boot_openflags; -+ struct openflags openflags; -+ devfs_handle_t devfs; -+ int no_cow; -+ struct cow cow; -+ -+ int map_writes; -+ int map_reads; -+ int nomap_writes; -+ int nomap_reads; -+ int write_maps; -+}; -+ -+#define DEFAULT_COW { \ -+ .file = NULL, \ -+ .fd = -1, \ -+ .bitmap = NULL, \ -+ .bitmap_offset = 0, \ -+ .data_offset = 0, \ -+} -+ -+#define DEFAULT_UBD { \ -+ .file = NULL, \ -+ .count = 0, \ -+ .fd = -1, \ -+ .size = -1, \ -+ .boot_openflags = OPEN_FLAGS, \ -+ .openflags = OPEN_FLAGS, \ -+ .devfs = NULL, \ -+ .no_cow = 0, \ -+ .cow = DEFAULT_COW, \ -+ .map_writes = 0, \ -+ .map_reads = 0, \ -+ .nomap_writes = 0, \ -+ .nomap_reads = 0, \ -+ .write_maps = 0, \ -+} -+ -+struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; -+ -+static int ubd0_init(void) -+{ -+ struct ubd *dev = &ubd_dev[0]; -+ -+ if(dev->file == NULL) -+ dev->file = "root_fs"; -+ return(0); -+} -+ -+__initcall(ubd0_init); -+ -+/* Only changed by fake_ide_setup which is a setup */ -+static int fake_ide = 0; -+static struct proc_dir_entry *proc_ide_root = NULL; -+static struct proc_dir_entry *proc_ide = NULL; -+ -+static void make_proc_ide(void) -+{ -+ proc_ide_root = proc_mkdir("ide", 0); -+ proc_ide = proc_mkdir("ide0", proc_ide_root); -+} -+ -+static int proc_ide_read_media(char *page, char **start, off_t off, int count, -+ int *eof, void *data) -+{ -+ int len; -+ -+ strcpy(page, "disk\n"); -+ len = strlen("disk\n"); -+ len -= off; -+ if (len < count){ -+ *eof = 1; -+ if (len <= 0) return 0; -+ } -+ else len = count; -+ *start = page + off; -+ return len; -+} -+ -+static void make_ide_entries(char *dev_name) -+{ -+ struct proc_dir_entry *dir, *ent; -+ char name[64]; -+ -+ if(!fake_ide) return; -+ -+ /* Without locking this could race if a UML was booted with no -+ * disks and then two mconsole requests which add disks came in -+ * at the same time. -+ */ -+ spin_lock(&ubd_lock); -+ if(proc_ide_root == NULL) make_proc_ide(); -+ spin_unlock(&ubd_lock); -+ -+ dir = proc_mkdir(dev_name, proc_ide); -+ if(!dir) return; -+ -+ ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir); -+ if(!ent) return; -+ ent->nlink = 1; -+ ent->data = NULL; -+ ent->read_proc = proc_ide_read_media; -+ ent->write_proc = NULL; -+ sprintf(name,"ide0/%s", dev_name); -+ proc_symlink(dev_name, proc_ide_root, name); -+} -+ -+static int fake_ide_setup(char *str) -+{ -+ fake_ide = 1; -+ return(1); -+} -+ -+__setup("fake_ide", fake_ide_setup); -+ -+__uml_help(fake_ide_setup, -+"fake_ide\n" -+" Create ide0 entries that map onto ubd devices.\n\n" -+); -+ -+static int parse_unit(char **ptr) -+{ -+ char *str = *ptr, *end; -+ int n = -1; -+ -+ if(isdigit(*str)) { -+ n = simple_strtoul(str, &end, 0); -+ if(end == str) -+ return(-1); -+ *ptr = end; -+ } -+ else if (('a' <= *str) && (*str <= 'h')) { -+ n = *str - 'a'; -+ str++; -+ *ptr = str; -+ } -+ return(n); -+} -+ -+static int ubd_setup_common(char *str, int *index_out) -+{ -+ struct openflags flags = global_openflags; -+ struct ubd *dev; -+ char *backing_file; -+ int n, err; -+ -+ if(index_out) *index_out = -1; -+ n = *str; -+ if(n == '='){ -+ char *end; -+ int major; -+ -+ str++; -+ if(!strcmp(str, "mmap")){ -+ CHOOSE_MODE(printk("mmap not supported by the ubd " -+ "driver in tt mode\n"), -+ ubd_do_mmap = 1); -+ return(0); -+ } -+ -+ if(!strcmp(str, "sync")){ -+ global_openflags.s = 1; -+ return(0); -+ } -+ major = simple_strtoul(str, &end, 0); -+ if((*end != '\0') || (end == str)){ -+ printk(KERN_ERR -+ "ubd_setup : didn't parse major number\n"); -+ return(1); -+ } -+ -+ err = 1; -+ spin_lock(&ubd_lock); -+ if(fake_major != MAJOR_NR){ -+ printk(KERN_ERR "Can't assign a fake major twice\n"); -+ goto out1; -+ } -+ -+ fake_gendisk.major = major; -+ fake_major = major; -+ -+ printk(KERN_INFO "Setting extra ubd major number to %d\n", -+ major); -+ err = 0; -+ out1: -+ spin_unlock(&ubd_lock); -+ return(err); -+ } -+ -+ n = parse_unit(&str); -+ if(n < 0){ -+ printk(KERN_ERR "ubd_setup : couldn't parse unit number " -+ "'%s'\n", str); -+ return(1); -+ } -+ -+ if(n >= MAX_DEV){ -+ printk(KERN_ERR "ubd_setup : index %d out of range " -+ "(%d devices)\n", n, MAX_DEV); -+ return(1); -+ } -+ -+ err = 1; -+ spin_lock(&ubd_lock); -+ -+ dev = &ubd_dev[n]; -+ if(dev->file != NULL){ -+ printk(KERN_ERR "ubd_setup : device already configured\n"); -+ goto out2; -+ } -+ -+ if(index_out) *index_out = n; -+ -+ if(*str == 'r'){ -+ flags.w = 0; -+ str++; -+ } -+ if(*str == 's'){ -+ flags.s = 1; -+ str++; -+ } -+ if(*str == 'd'){ -+ dev->no_cow = 1; -+ str++; -+ } -+ -+ if(*str++ != '='){ -+ printk(KERN_ERR "ubd_setup : Expected '='\n"); -+ goto out2; -+ } -+ -+ err = 0; -+ backing_file = strchr(str, ','); -+ if(backing_file){ -+ if(dev->no_cow) -+ printk(KERN_ERR "Can't specify both 'd' and a " -+ "cow file\n"); -+ else { -+ *backing_file = '\0'; -+ backing_file++; -+ } -+ } -+ dev->file = str; -+ dev->cow.file = backing_file; -+ dev->boot_openflags = flags; -+ out2: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_setup(char *str) -+{ -+ ubd_setup_common(str, NULL); -+ return(1); -+} -+ -+__setup("ubd", ubd_setup); -+__uml_help(ubd_setup, -+"ubd<n>=<filename>\n" -+" This is used to associate a device with a file in the underlying\n" -+" filesystem. Usually, there is a filesystem in the file, but \n" -+" that's not required. Swap devices containing swap files can be\n" -+" specified like this. Also, a file which doesn't contain a\n" -+" filesystem can have its contents read in the virtual \n" -+" machine by running dd on the device. n must be in the range\n" -+" 0 to 7. Appending an 'r' to the number will cause that device\n" -+" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n" -+" an 's' (has to be _after_ 'r', if there is one) will cause data\n" -+" to be written to disk on the host immediately.\n\n" -+); -+ -+static int fakehd(char *str) -+{ -+ printk(KERN_INFO -+ "fakehd : Changing ubd_gendisk.major_name to \"hd\".\n"); -+ ubd_gendisk.major_name = "hd"; -+ return(1); -+} -+ -+__setup("fakehd", fakehd); -+__uml_help(fakehd, -+"fakehd\n" -+" Change the ubd device name to \"hd\".\n\n" -+); -+ -+static void do_ubd_request(request_queue_t * q); -+ -+/* Only changed by ubd_init, which is an initcall. */ -+int thread_fd = -1; -+ -+/* Changed by ubd_handler, which is serialized because interrupts only -+ * happen on CPU 0. -+ */ -+int intr_count = 0; -+ -+static void ubd_finish(int error) -+{ -+ int nsect; -+ -+ if(error){ -+ end_request(0); -+ return; -+ } -+ nsect = CURRENT->current_nr_sectors; -+ CURRENT->sector += nsect; -+ CURRENT->buffer += nsect << 9; -+ CURRENT->errors = 0; -+ CURRENT->nr_sectors -= nsect; -+ CURRENT->current_nr_sectors = 0; -+ end_request(1); -+} -+ -+static void ubd_handler(void) -+{ -+ struct io_thread_req req; -+ int n, err; -+ -+ DEVICE_INTR = NULL; -+ intr_count++; -+ n = read_ubd_fs(thread_fd, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " -+ "err = %d\n", os_getpid(), -n); -+ spin_lock(&io_request_lock); -+ end_request(0); -+ spin_unlock(&io_request_lock); -+ return; -+ } -+ -+ if((req.op != UBD_MMAP) && -+ ((req.offset != ((__u64) (CURRENT->sector)) << 9) || -+ (req.length != (CURRENT->current_nr_sectors) << 9))) -+ panic("I/O op mismatch"); -+ -+ if(req.map_fd != -1){ -+ err = physmem_subst_mapping(req.buffer, req.map_fd, -+ req.map_offset, 1); -+ if(err) -+ printk("ubd_handler - physmem_subst_mapping failed, " -+ "err = %d\n", -err); -+ } -+ -+ spin_lock(&io_request_lock); -+ ubd_finish(req.error); -+ reactivate_fd(thread_fd, UBD_IRQ); -+ do_ubd_request(ubd_queue); -+ spin_unlock(&io_request_lock); -+} -+ -+static void ubd_intr(int irq, void *dev, struct pt_regs *unused) -+{ -+ ubd_handler(); -+} -+ -+/* Only changed by ubd_init, which is an initcall. */ -+static int io_pid = -1; -+ -+void kill_io_thread(void) -+{ -+ if(io_pid != -1) -+ os_kill_process(io_pid, 1); -+} -+ -+__uml_exitcall(kill_io_thread); -+ -+/* Initialized in an initcall, and unchanged thereafter */ -+devfs_handle_t ubd_dir_handle; -+ -+static int ubd_add(int n) -+{ -+ struct ubd *dev = &ubd_dev[n]; -+ char name[sizeof("nnnnnn\0")], dev_name[sizeof("ubd0x")]; -+ int err = -EISDIR; -+ -+ if(dev->file == NULL) -+ goto out; -+ -+ err = ubd_revalidate1(MKDEV(MAJOR_NR, n << UBD_SHIFT)); -+ if(err) -+ goto out; -+ -+ if(dev->cow.file == NULL) -+ blk_sizes[n] = UBD_MMAP_BLOCK_SIZE; -+ -+ sprintf(name, "%d", n); -+ dev->devfs = devfs_register(ubd_dir_handle, name, DEVFS_FL_REMOVABLE, -+ MAJOR_NR, n << UBD_SHIFT, S_IFBLK | -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, -+ &ubd_blops, NULL); -+ -+#if 0 /* 2.5 ... */ -+ sprintf(disk->disk_name, "ubd%c", 'a' + unit); -+#endif -+ -+ sprintf(dev_name, "%s%c", ubd_gendisk.major_name, -+ n + 'a'); -+ -+ make_ide_entries(dev_name); -+ return(0); -+ -+ out: -+ return(err); -+} -+ -+static int ubd_config(char *str) -+{ -+ int n, err; -+ -+ str = uml_strdup(str); -+ if(str == NULL){ -+ printk(KERN_ERR "ubd_config failed to strdup string\n"); -+ return(1); -+ } -+ err = ubd_setup_common(str, &n); -+ if(err){ -+ kfree(str); -+ return(-1); -+ } -+ if(n == -1) return(0); -+ -+ spin_lock(&ubd_lock); -+ err = ubd_add(n); -+ if(err) -+ ubd_dev[n].file = NULL; -+ spin_unlock(&ubd_lock); -+ -+ return(err); -+} -+ -+static int ubd_get_config(char *name, char *str, int size, char **error_out) -+{ -+ struct ubd *dev; -+ char *end; -+ int n, len = 0; -+ -+ n = simple_strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ *error_out = "ubd_get_config : didn't parse device number"; -+ return(-1); -+ } -+ -+ if((n >= MAX_DEV) || (n < 0)){ -+ *error_out = "ubd_get_config : device number out of range"; -+ return(-1); -+ } -+ -+ dev = &ubd_dev[n]; -+ spin_lock(&ubd_lock); -+ -+ if(dev->file == NULL){ -+ CONFIG_CHUNK(str, size, len, "", 1); -+ goto out; -+ } -+ -+ CONFIG_CHUNK(str, size, len, dev->file, 0); -+ -+ if(dev->cow.file != NULL){ -+ CONFIG_CHUNK(str, size, len, ",", 0); -+ CONFIG_CHUNK(str, size, len, dev->cow.file, 1); -+ } -+ else CONFIG_CHUNK(str, size, len, "", 1); -+ -+ out: -+ spin_unlock(&ubd_lock); -+ return(len); -+} -+ -+static int ubd_remove(char *str) -+{ -+ struct ubd *dev; -+ int n, err = -ENODEV; -+ -+ if(isdigit(*str)){ -+ char *end; -+ n = simple_strtoul(str, &end, 0); -+ if ((*end != '\0') || (end == str)) -+ return(err); -+ } -+ else if (('a' <= *str) && (*str <= 'h')) -+ n = *str - 'a'; -+ else -+ return(err); /* it should be a number 0-7/a-h */ -+ -+ if((n < 0) || (n >= MAX_DEV)) -+ return(err); -+ -+ dev = &ubd_dev[n]; -+ -+ spin_lock(&ubd_lock); -+ err = 0; -+ if(dev->file == NULL) -+ goto out; -+ err = -1; -+ if(dev->count > 0) -+ goto out; -+ if(dev->devfs != NULL) -+ devfs_unregister(dev->devfs); -+ -+ *dev = ((struct ubd) DEFAULT_UBD); -+ err = 0; -+ out: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static struct mc_device ubd_mc = { -+ .name = "ubd", -+ .config = ubd_config, -+ .get_config = ubd_get_config, -+ .remove = ubd_remove, -+}; -+ -+static int ubd_mc_init(void) -+{ -+ mconsole_register_dev(&ubd_mc); -+ return(0); -+} -+ -+__initcall(ubd_mc_init); -+ -+static request_queue_t *ubd_get_queue(kdev_t device) -+{ -+ return(ubd_queue); -+} -+ -+int ubd_init(void) -+{ -+ unsigned long stack; -+ int i, err; -+ -+ ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); -+ if (devfs_register_blkdev(MAJOR_NR, "ubd", &ubd_blops)) { -+ printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR); -+ return -1; -+ } -+ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[MAJOR_NR] = blk_sizes; -+ blk_size[MAJOR_NR] = sizes; -+ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes); -+ -+ ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR); -+ blk_init_queue(ubd_queue, DEVICE_REQUEST); -+ INIT_ELV(ubd_queue, &ubd_queue->elevator); -+ -+ add_gendisk(&ubd_gendisk); -+ if (fake_major != MAJOR_NR){ -+ /* major number 0 is used to auto select */ -+ err = devfs_register_blkdev(fake_major, "fake", &ubd_blops); -+ if(fake_major == 0){ -+ /* auto device number case */ -+ fake_major = err; -+ if(err == 0) -+ return(-ENODEV); -+ } -+ else if (err){ -+ /* not auto so normal error */ -+ printk(KERN_ERR "ubd: error %d getting major %d\n", -+ -err, fake_major); -+ return(-ENODEV); -+ } -+ -+ blk_dev[fake_major].queue = ubd_get_queue; -+ read_ahead[fake_major] = 8; /* 8 sector (4kB) read-ahead */ -+ blksize_size[fake_major] = blk_sizes; -+ blk_size[fake_major] = sizes; -+ INIT_HARDSECT(hardsect_size, fake_major, hardsect_sizes); -+ add_gendisk(&fake_gendisk); -+ } -+ -+ for(i=0;i<MAX_DEV;i++) -+ ubd_add(i); -+ -+ if(global_openflags.s){ -+ printk(KERN_INFO "ubd : Synchronous mode\n"); -+ return(0); -+ } -+ stack = alloc_stack(0, 0); -+ io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), -+ &thread_fd); -+ if(io_pid < 0){ -+ io_pid = -1; -+ printk(KERN_ERR -+ "ubd : Failed to start I/O thread (errno = %d) - " -+ "falling back to synchronous I/O\n", -io_pid); -+ return(0); -+ } -+ err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, -+ SA_INTERRUPT, "ubd", ubd_dev); -+ if(err != 0) -+ printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); -+ return(err); -+} -+ -+__initcall(ubd_init); -+ -+static void ubd_close(struct ubd *dev) -+{ -+ if(ubd_do_mmap) -+ physmem_forget_descriptor(dev->fd); -+ os_close_file(dev->fd); -+ if(dev->cow.file != NULL) -+ return; -+ -+ if(ubd_do_mmap) -+ physmem_forget_descriptor(dev->cow.fd); -+ os_close_file(dev->cow.fd); -+ vfree(dev->cow.bitmap); -+ dev->cow.bitmap = NULL; -+} -+ -+static int ubd_open_dev(struct ubd *dev) -+{ -+ struct openflags flags; -+ char **back_ptr; -+ int err, create_cow, *create_ptr; -+ -+ dev->openflags = dev->boot_openflags; -+ create_cow = 0; -+ create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; -+ back_ptr = dev->no_cow ? NULL : &dev->cow.file; -+ dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr, -+ &dev->cow.bitmap_offset, &dev->cow.bitmap_len, -+ &dev->cow.data_offset, create_ptr); -+ -+ if((dev->fd == -ENOENT) && create_cow){ -+ dev->fd = create_cow_file(dev->file, dev->cow.file, -+ dev->openflags, 1 << 9, PAGE_SIZE, -+ &dev->cow.bitmap_offset, -+ &dev->cow.bitmap_len, -+ &dev->cow.data_offset); -+ if(dev->fd >= 0){ -+ printk(KERN_INFO "Creating \"%s\" as COW file for " -+ "\"%s\"\n", dev->file, dev->cow.file); -+ } -+ } -+ -+ if(dev->fd < 0) return(dev->fd); -+ -+ if(dev->cow.file != NULL){ -+ err = -ENOMEM; -+ dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); -+ if(dev->cow.bitmap == NULL){ -+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); -+ goto error; -+ } -+ flush_tlb_kernel_vm(); -+ -+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap, -+ dev->cow.bitmap_offset, -+ dev->cow.bitmap_len); -+ if(err < 0) -+ goto error; -+ -+ flags = dev->openflags; -+ flags.w = 0; -+ err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, -+ NULL, NULL); -+ if(err < 0) goto error; -+ dev->cow.fd = err; -+ } -+ return(0); -+ error: -+ os_close_file(dev->fd); -+ return(err); -+} -+ -+static int ubd_file_size(struct ubd *dev, __u64 *size_out) -+{ -+ char *file; -+ -+ file = dev->cow.file ? dev->cow.file : dev->file; -+ return(os_file_size(file, size_out)); -+} -+ -+static int ubd_open(struct inode *inode, struct file *filp) -+{ -+ struct ubd *dev; -+ int n, offset, err = 0; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ dev = &ubd_dev[n]; -+ if(n >= MAX_DEV) -+ return -ENODEV; -+ -+ spin_lock(&ubd_lock); -+ offset = n << UBD_SHIFT; -+ -+ if(dev->count == 0){ -+ err = ubd_open_dev(dev); -+ if(err){ -+ printk(KERN_ERR "ubd%d: Can't open \"%s\": " -+ "errno = %d\n", n, dev->file, -err); -+ goto out; -+ } -+ err = ubd_file_size(dev, &dev->size); -+ if(err < 0) -+ goto out; -+ sizes[offset] = dev->size / BLOCK_SIZE; -+ ubd_part[offset].nr_sects = dev->size / hardsect_sizes[offset]; -+ } -+ dev->count++; -+ if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ -+ if(--dev->count == 0) ubd_close(dev); -+ err = -EROFS; -+ } -+ out: -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_release(struct inode * inode, struct file * file) -+{ -+ int n, offset; -+ -+ n = DEVICE_NR(inode->i_rdev); -+ offset = n << UBD_SHIFT; -+ if(n >= MAX_DEV) -+ return -ENODEV; -+ -+ spin_lock(&ubd_lock); -+ if(--ubd_dev[n].count == 0) -+ ubd_close(&ubd_dev[n]); -+ spin_unlock(&ubd_lock); -+ -+ return(0); -+} -+ -+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, -+ __u64 *cow_offset, unsigned long *bitmap, -+ __u64 bitmap_offset, unsigned long *bitmap_words, -+ __u64 bitmap_len) -+{ -+ __u64 sector = io_offset >> 9; -+ int i, update_bitmap = 0; -+ -+ for(i = 0; i < length >> 9; i++){ -+ if(cow_mask != NULL) -+ ubd_set_bit(i, (unsigned char *) cow_mask); -+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) -+ continue; -+ -+ update_bitmap = 1; -+ ubd_set_bit(sector + i, (unsigned char *) bitmap); -+ } -+ -+ if(!update_bitmap) -+ return; -+ -+ *cow_offset = sector / (sizeof(unsigned long) * 8); -+ -+ /* This takes care of the case where we're exactly at the end of the -+ * device, and *cow_offset + 1 is off the end. So, just back it up -+ * by one word. Thanks to Lynn Kerby for the fix and James McMechan -+ * for the original diagnosis. -+ */ -+ if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / -+ sizeof(unsigned long) - 1)) -+ (*cow_offset)--; -+ -+ bitmap_words[0] = bitmap[*cow_offset]; -+ bitmap_words[1] = bitmap[*cow_offset + 1]; -+ -+ *cow_offset *= sizeof(unsigned long); -+ *cow_offset += bitmap_offset; -+} -+ -+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, -+ __u64 bitmap_offset, __u64 bitmap_len) -+{ -+ __u64 sector = req->offset >> 9; -+ int i; -+ -+ if(req->length > (sizeof(req->sector_mask) * 8) << 9) -+ panic("Operation too long"); -+ -+ if(req->op == UBD_READ) { -+ for(i = 0; i < req->length >> 9; i++){ -+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap)){ -+ ubd_set_bit(i, (unsigned char *) -+ &req->sector_mask); -+ } -+ } -+ } -+ else cowify_bitmap(req->offset, req->length, &req->sector_mask, -+ &req->cow_offset, bitmap, bitmap_offset, -+ req->bitmap_words, bitmap_len); -+} -+ -+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset) -+{ -+ __u64 sector; -+ unsigned char *bitmap; -+ int bit, i; -+ -+ /* mmap must have been requested on the command line */ -+ if(!ubd_do_mmap) -+ return(-1); -+ -+ /* The buffer must be page aligned */ -+ if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0) -+ return(-1); -+ -+ /* The request must be a page long */ -+ if((req->current_nr_sectors << 9) != PAGE_SIZE) -+ return(-1); -+ -+ if(dev->cow.file == NULL) -+ return(dev->fd); -+ -+ sector = offset >> 9; -+ bitmap = (unsigned char *) dev->cow.bitmap; -+ bit = ubd_test_bit(sector, bitmap); -+ -+ for(i = 1; i < req->current_nr_sectors; i++){ -+ if(ubd_test_bit(sector + i, bitmap) != bit) -+ return(-1); -+ } -+ -+ if(bit || (req->cmd == WRITE)) -+ offset += dev->cow.data_offset; -+ -+ /* The data on disk must be page aligned */ -+ if((offset % UBD_MMAP_BLOCK_SIZE) != 0) -+ return(-1); -+ -+ return(bit ? dev->fd : dev->cow.fd); -+} -+ -+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset, -+ struct request *req, -+ struct io_thread_req *io_req) -+{ -+ int err; -+ -+ if(req->cmd == WRITE){ -+ /* Writes are almost no-ops since the new data is already in the -+ * host page cache -+ */ -+ dev->map_writes++; -+ if(dev->cow.file != NULL) -+ cowify_bitmap(io_req->offset, io_req->length, -+ &io_req->sector_mask, &io_req->cow_offset, -+ dev->cow.bitmap, dev->cow.bitmap_offset, -+ io_req->bitmap_words, -+ dev->cow.bitmap_len); -+ } -+ else { -+ int w; -+ -+ if((dev->cow.file != NULL) && (fd == dev->cow.fd)) -+ w = 0; -+ else w = dev->openflags.w; -+ -+ if((dev->cow.file != NULL) && (fd == dev->fd)) -+ offset += dev->cow.data_offset; -+ -+ err = physmem_subst_mapping(req->buffer, fd, offset, w); -+ if(err){ -+ printk("physmem_subst_mapping failed, err = %d\n", -+ -err); -+ return(1); -+ } -+ dev->map_reads++; -+ } -+ io_req->op = UBD_MMAP; -+ io_req->buffer = req->buffer; -+ return(0); -+} -+ -+static int prepare_request(struct request *req, struct io_thread_req *io_req) -+{ -+ struct ubd *dev; -+ __u64 offset; -+ int minor, n, len, fd; -+ -+ if(req->rq_status == RQ_INACTIVE) return(1); -+ -+ minor = MINOR(req->rq_dev); -+ n = minor >> UBD_SHIFT; -+ dev = &ubd_dev[n]; -+ -+ if(IS_WRITE(req) && !dev->openflags.w){ -+ printk("Write attempted on readonly ubd device %d\n", n); -+ end_request(0); -+ return(1); -+ } -+ -+ req->sector += ubd_part[minor].start_sect; -+ offset = ((__u64) req->sector) << 9; -+ len = req->current_nr_sectors << 9; -+ -+ io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; -+ io_req->fds[1] = dev->fd; -+ io_req->map_fd = -1; -+ io_req->cow_offset = -1; -+ io_req->offset = offset; -+ io_req->length = len; -+ io_req->error = 0; -+ io_req->sector_mask = 0; -+ -+ fd = mmap_fd(req, dev, io_req->offset); -+ if(fd > 0){ -+ /* If mmapping is otherwise OK, but the first access to the -+ * page is a write, then it's not mapped in yet. So we have -+ * to write the data to disk first, then we can map the disk -+ * page in and continue normally from there. -+ */ -+ if((req->cmd == WRITE) && !is_remapped(req->buffer, dev->fd, io_req->offset + dev->cow.data_offset)){ -+ io_req->map_fd = dev->fd; -+ io_req->map_offset = io_req->offset + -+ dev->cow.data_offset; -+ dev->write_maps++; -+ } -+ else return(prepare_mmap_request(dev, fd, io_req->offset, req, -+ io_req)); -+ } -+ -+ if(req->cmd == READ) -+ dev->nomap_reads++; -+ else dev->nomap_writes++; -+ -+ io_req->op = (req->cmd == READ) ? UBD_READ : UBD_WRITE; -+ io_req->offsets[0] = 0; -+ io_req->offsets[1] = dev->cow.data_offset; -+ io_req->buffer = req->buffer; -+ io_req->sectorsize = 1 << 9; -+ -+ if(dev->cow.file != NULL) -+ cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, -+ dev->cow.bitmap_len); -+ return(0); -+} -+ -+static void do_ubd_request(request_queue_t *q) -+{ -+ struct io_thread_req io_req; -+ struct request *req; -+ int err, n; -+ -+ if(thread_fd == -1){ -+ while(!list_empty(&q->queue_head)){ -+ req = blkdev_entry_next_request(&q->queue_head); -+ err = prepare_request(req, &io_req); -+ if(!err){ -+ do_io(&io_req); -+ ubd_finish(io_req.error); -+ } -+ } -+ } -+ else { -+ if(DEVICE_INTR || list_empty(&q->queue_head)) return; -+ req = blkdev_entry_next_request(&q->queue_head); -+ err = prepare_request(req, &io_req); -+ if(!err){ -+ SET_INTR(ubd_handler); -+ n = write_ubd_fs(thread_fd, (char *) &io_req, -+ sizeof(io_req)); -+ if(n != sizeof(io_req)) -+ printk("write to io thread failed, " -+ "errno = %d\n", -n); -+ } -+ } -+} -+ -+static int ubd_ioctl(struct inode * inode, struct file * file, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct hd_geometry *loc = (struct hd_geometry *) arg; -+ struct ubd *dev; -+ int n, minor, err; -+ struct hd_driveid ubd_id = { -+ .cyls = 0, -+ .heads = 128, -+ .sectors = 32, -+ }; -+ -+ if(!inode) return(-EINVAL); -+ minor = MINOR(inode->i_rdev); -+ n = minor >> UBD_SHIFT; -+ if(n >= MAX_DEV) -+ return(-EINVAL); -+ dev = &ubd_dev[n]; -+ switch (cmd) { -+ struct hd_geometry g; -+ struct cdrom_volctrl volume; -+ case HDIO_GETGEO: -+ if(!loc) return(-EINVAL); -+ g.heads = 128; -+ g.sectors = 32; -+ g.cylinders = dev->size / (128 * 32 * hardsect_sizes[minor]); -+ g.start = ubd_part[minor].start_sect; -+ return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0); -+ case BLKGETSIZE: /* Return device size */ -+ if(!arg) return(-EINVAL); -+ err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); -+ if(err) -+ return(err); -+ put_user(ubd_part[minor].nr_sects, (long *) arg); -+ return(0); -+ case BLKRRPART: /* Re-read partition tables */ -+ return(ubd_revalidate(inode->i_rdev)); -+ -+ case HDIO_GET_IDENTITY: -+ ubd_id.cyls = dev->size / (128 * 32 * hardsect_sizes[minor]); -+ if(copy_to_user((char *) arg, (char *) &ubd_id, -+ sizeof(ubd_id))) -+ return(-EFAULT); -+ return(0); -+ -+ case CDROMVOLREAD: -+ if(copy_from_user(&volume, (char *) arg, sizeof(volume))) -+ return(-EFAULT); -+ volume.channel0 = 255; -+ volume.channel1 = 255; -+ volume.channel2 = 255; -+ volume.channel3 = 255; -+ if(copy_to_user((char *) arg, &volume, sizeof(volume))) -+ return(-EFAULT); -+ return(0); -+ -+ default: -+ return blk_ioctl(inode->i_rdev, cmd, arg); -+ } -+} -+ -+static int ubd_revalidate1(kdev_t rdev) -+{ -+ int i, n, offset, err = 0, pcount = 1 << UBD_SHIFT; -+ struct ubd *dev; -+ struct hd_struct *part; -+ -+ n = DEVICE_NR(rdev); -+ offset = n << UBD_SHIFT; -+ dev = &ubd_dev[n]; -+ -+ part = &ubd_part[offset]; -+ -+ /* clear all old partition counts */ -+ for(i = 1; i < pcount; i++) { -+ part[i].start_sect = 0; -+ part[i].nr_sects = 0; -+ } -+ -+ /* If it already has been opened we can check the partitions -+ * directly -+ */ -+ if(dev->count){ -+ part->start_sect = 0; -+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount, -+ &ubd_blops, part->nr_sects); -+ } -+ else if(dev->file){ -+ err = ubd_open_dev(dev); -+ if(err){ -+ printk(KERN_ERR "unable to open %s for validation\n", -+ dev->file); -+ goto out; -+ } -+ -+ /* have to recompute sizes since we opened it */ -+ err = ubd_file_size(dev, &dev->size); -+ if(err < 0) { -+ ubd_close(dev); -+ goto out; -+ } -+ part->start_sect = 0; -+ part->nr_sects = dev->size / hardsect_sizes[offset]; -+ register_disk(&ubd_gendisk, MKDEV(MAJOR_NR, offset), pcount, -+ &ubd_blops, part->nr_sects); -+ -+ /* we are done so close it */ -+ ubd_close(dev); -+ } -+ else err = -ENODEV; -+ out: -+ return(err); -+} -+ -+static int ubd_revalidate(kdev_t rdev) -+{ -+ int err; -+ -+ spin_lock(&ubd_lock); -+ err = ubd_revalidate1(rdev); -+ spin_unlock(&ubd_lock); -+ return(err); -+} -+ -+static int ubd_check_remapped(int fd, unsigned long address, int is_write, -+ __u64 offset, int is_user) -+{ -+ __u64 bitmap_offset; -+ unsigned long new_bitmap[2]; -+ int i, err, n; -+ -+ /* This can only fix kernelspace faults */ -+ if(is_user) -+ return(0); -+ -+ /* ubd-mmap is only enabled in skas mode */ -+ if(CHOOSE_MODE(1, 0)) -+ return(0); -+ -+ /* If it's not a write access, we can't do anything about it */ -+ if(!is_write) -+ return(0); -+ -+ /* We have a write */ -+ for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){ -+ struct ubd *dev = &ubd_dev[i]; -+ -+ if((dev->fd != fd) && (dev->cow.fd != fd)) -+ continue; -+ -+ /* It's a write to a ubd device */ -+ -+ if(!dev->openflags.w){ -+ /* It's a write access on a read-only device - probably -+ * shouldn't happen. If the kernel is trying to change -+ * something with no intention of writing it back out, -+ * then this message will clue us in that this needs -+ * fixing -+ */ -+ printk("Write access to mapped page from readonly ubd " -+ "device %d\n", i); -+ return(0); -+ } -+ -+ /* It's a write to a writeable ubd device - it must be COWed -+ * because, otherwise, the page would have been mapped in -+ * writeable -+ */ -+ -+ if(!dev->cow.file) -+ panic("Write fault on writeable non-COW ubd device %d", -+ i); -+ -+ /* It should also be an access to the backing file since the -+ * COW pages should be mapped in read-write -+ */ -+ -+ if(fd == dev->fd) -+ panic("Write fault on a backing page of ubd " -+ "device %d\n", i); -+ -+ /* So, we do the write, copying the backing data to the COW -+ * file... -+ */ -+ -+ err = os_seek_file(dev->fd, offset + dev->cow.data_offset); -+ if(err < 0) -+ panic("Couldn't seek to %lld in COW file of ubd " -+ "device %d, err = %d", -+ offset + dev->cow.data_offset, i, -err); -+ -+ n = os_write_file(dev->fd, (void *) address, PAGE_SIZE); -+ if(n != PAGE_SIZE) -+ panic("Couldn't copy data to COW file of ubd " -+ "device %d, err = %d", i, -n); -+ -+ /* ... updating the COW bitmap... */ -+ -+ cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset, -+ dev->cow.bitmap, dev->cow.bitmap_offset, -+ new_bitmap, dev->cow.bitmap_len); -+ -+ err = os_seek_file(dev->fd, bitmap_offset); -+ if(err < 0) -+ panic("Couldn't seek to %lld in COW file of ubd " -+ "device %d, err = %d", bitmap_offset, i, -err); -+ -+ n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap)); -+ if(n != sizeof(new_bitmap)) -+ panic("Couldn't update bitmap of ubd device %d, " -+ "err = %d", i, -n); -+ -+ /* Maybe we can map the COW page in, and maybe we can't. If -+ * it is a pre-V3 COW file, we can't, since the alignment will -+ * be wrong. If it is a V3 or later COW file which has been -+ * moved to a system with a larger page size, then maybe we -+ * can't, depending on the exact location of the page. -+ */ -+ -+ offset += dev->cow.data_offset; -+ -+ /* Remove the remapping, putting the original anonymous page -+ * back. If the COW file can be mapped in, that is done. -+ * Otherwise, the COW page is read in. -+ */ -+ -+ if(!physmem_remove_mapping((void *) address)) -+ panic("Address 0x%lx not remapped by ubd device %d", -+ address, i); -+ if((offset % UBD_MMAP_BLOCK_SIZE) == 0) -+ physmem_subst_mapping((void *) address, dev->fd, -+ offset, 1); -+ else { -+ err = os_seek_file(dev->fd, offset); -+ if(err < 0) -+ panic("Couldn't seek to %lld in COW file of " -+ "ubd device %d, err = %d", offset, i, -+ -err); -+ -+ n = os_read_file(dev->fd, (void *) address, PAGE_SIZE); -+ if(n != PAGE_SIZE) -+ panic("Failed to read page from offset %llx of " -+ "COW file of ubd device %d, err = %d", -+ offset, i, -n); -+ } -+ -+ return(1); -+ } -+ -+ /* It's not a write on a ubd device */ -+ return(0); -+} -+ -+static struct remapper ubd_remapper = { -+ .list = LIST_HEAD_INIT(ubd_remapper.list), -+ .proc = ubd_check_remapped, -+}; -+ -+static int ubd_remapper_setup(void) -+{ -+ if(ubd_do_mmap) -+ register_remapper(&ubd_remapper); -+ -+ return(0); -+} -+ -+__initcall(ubd_remapper_setup); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/ubd_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/ubd_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/ubd_user.c 2005-05-03 22:28:14.259442448 +0300 -@@ -0,0 +1,379 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stddef.h> -+#include <unistd.h> -+#include <errno.h> -+#include <sched.h> -+#include <signal.h> -+#include <string.h> -+#include <netinet/in.h> -+#include <sys/time.h> -+#include <sys/socket.h> -+#include <sys/mman.h> -+#include <sys/param.h> -+#include "asm/types.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "ubd_user.h" -+#include "os.h" -+#include "cow.h" -+ -+#include <endian.h> -+#include <byteswap.h> -+ -+static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) -+{ -+ struct uml_stat buf1, buf2; -+ int err; -+ -+ if(from_cmdline == NULL) return(1); -+ if(!strcmp(from_cmdline, from_cow)) return(1); -+ -+ err = os_stat_file(from_cmdline, &buf1); -+ if(err < 0){ -+ printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); -+ return(1); -+ } -+ err = os_stat_file(from_cow, &buf2); -+ if(err < 0){ -+ printk("Couldn't stat '%s', err = %d\n", from_cow, -err); -+ return(1); -+ } -+ if((buf1.ust_major == buf2.ust_major) && -+ (buf1.ust_minor == buf2.ust_minor) && -+ (buf1.ust_ino == buf2.ust_ino)) -+ return(1); -+ -+ printk("Backing file mismatch - \"%s\" requested,\n" -+ "\"%s\" specified in COW header of \"%s\"\n", -+ from_cmdline, from_cow, cow); -+ return(0); -+} -+ -+static int backing_file_mismatch(char *file, __u64 size, time_t mtime) -+{ -+ unsigned long modtime; -+ long long actual; -+ int err; -+ -+ err = os_file_modtime(file, &modtime); -+ if(err < 0){ -+ printk("Failed to get modification time of backing file " -+ "\"%s\", err = %d\n", file, -err); -+ return(err); -+ } -+ -+ err = os_file_size(file, &actual); -+ if(err < 0){ -+ printk("Failed to get size of backing file \"%s\", " -+ "err = %d\n", file, -err); -+ return(err); -+ } -+ -+ if(actual != size){ -+ printk("Size mismatch (%ld vs %ld) of COW header vs backing " -+ "file\n", size, actual); -+ return(-EINVAL); -+ } -+ if(modtime != mtime){ -+ printk("mtime mismatch (%ld vs %ld) of COW header vs backing " -+ "file\n", mtime, modtime); -+ return(-EINVAL); -+ } -+ return(0); -+} -+ -+int read_cow_bitmap(int fd, void *buf, int offset, int len) -+{ -+ int err; -+ -+ err = os_seek_file(fd, offset); -+ if(err < 0) -+ return(err); -+ -+ err = os_read_file(fd, buf, len); -+ if(err < 0) -+ return(err); -+ -+ return(0); -+} -+ -+int open_ubd_file(char *file, struct openflags *openflags, -+ char **backing_file_out, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out, -+ int *create_cow_out) -+{ -+ time_t mtime; -+ __u64 size; -+ __u32 version, align; -+ char *backing_file; -+ int fd, err, sectorsize, same, mode = 0644; -+ -+ fd = os_open_file(file, *openflags, mode); -+ if(fd < 0){ -+ if((fd == -ENOENT) && (create_cow_out != NULL)) -+ *create_cow_out = 1; -+ if(!openflags->w || -+ ((errno != EROFS) && (errno != EACCES))) return(-errno); -+ openflags->w = 0; -+ fd = os_open_file(file, *openflags, mode); -+ if(fd < 0) -+ return(fd); -+ } -+ -+ err = os_lock_file(fd, openflags->w); -+ if(err < 0){ -+ printk("Failed to lock '%s', err = %d\n", file, -err); -+ goto out_close; -+ } -+ -+ if(backing_file_out == NULL) return(fd); -+ -+ err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, -+ &size, §orsize, &align, bitmap_offset_out); -+ if(err && (*backing_file_out != NULL)){ -+ printk("Failed to read COW header from COW file \"%s\", " -+ "errno = %d\n", file, -err); -+ goto out_close; -+ } -+ if(err) return(fd); -+ -+ if(backing_file_out == NULL) return(fd); -+ -+ same = same_backing_files(*backing_file_out, backing_file, file); -+ -+ if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ -+ printk("Switching backing file to '%s'\n", *backing_file_out); -+ err = write_cow_header(file, fd, *backing_file_out, -+ sectorsize, align, &size); -+ if(err){ -+ printk("Switch failed, errno = %d\n", -err); -+ return(err); -+ } -+ } -+ else { -+ *backing_file_out = backing_file; -+ err = backing_file_mismatch(*backing_file_out, size, mtime); -+ if(err) goto out_close; -+ } -+ -+ cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, -+ bitmap_len_out, data_offset_out); -+ -+ return(fd); -+ out_close: -+ os_close_file(fd); -+ return(err); -+} -+ -+int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, -+ int sectorsize, int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out) -+{ -+ int err, fd; -+ -+ flags.c = 1; -+ fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL); -+ if(fd < 0){ -+ err = fd; -+ printk("Open of COW file '%s' failed, errno = %d\n", cow_file, -+ -err); -+ goto out; -+ } -+ -+ err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment, -+ bitmap_offset_out, bitmap_len_out, -+ data_offset_out); -+ if(!err) -+ return(fd); -+ -+ os_close_file(fd); -+ out: -+ return(err); -+} -+ -+/* XXX Just trivial wrappers around os_read_file and os_write_file */ -+int read_ubd_fs(int fd, void *buffer, int len) -+{ -+ return(os_read_file(fd, buffer, len)); -+} -+ -+int write_ubd_fs(int fd, char *buffer, int len) -+{ -+ return(os_write_file(fd, buffer, len)); -+} -+ -+static int update_bitmap(struct io_thread_req *req) -+{ -+ int n; -+ -+ if(req->cow_offset == -1) -+ return(0); -+ -+ n = os_seek_file(req->fds[1], req->cow_offset); -+ if(n < 0){ -+ printk("do_io - bitmap lseek failed : err = %d\n", -n); -+ return(1); -+ } -+ -+ n = os_write_file(req->fds[1], &req->bitmap_words, -+ sizeof(req->bitmap_words)); -+ if(n != sizeof(req->bitmap_words)){ -+ printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, -+ req->fds[1]); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+void do_io(struct io_thread_req *req) -+{ -+ char *buf; -+ unsigned long len; -+ int n, nsectors, start, end, bit; -+ int err; -+ __u64 off; -+ -+ if(req->op == UBD_MMAP){ -+ /* Touch the page to force the host to do any necessary IO to -+ * get it into memory -+ */ -+ n = *((volatile int *) req->buffer); -+ req->error = update_bitmap(req); -+ return; -+ } -+ -+ nsectors = req->length / req->sectorsize; -+ start = 0; -+ do { -+ bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask); -+ end = start; -+ while((end < nsectors) && -+ (ubd_test_bit(end, (unsigned char *) -+ &req->sector_mask) == bit)) -+ end++; -+ -+ off = req->offset + req->offsets[bit] + -+ start * req->sectorsize; -+ len = (end - start) * req->sectorsize; -+ buf = &req->buffer[start * req->sectorsize]; -+ -+ err = os_seek_file(req->fds[bit], off); -+ if(err < 0){ -+ printk("do_io - lseek failed : err = %d\n", -err); -+ req->error = 1; -+ return; -+ } -+ if(req->op == UBD_READ){ -+ n = 0; -+ do { -+ buf = &buf[n]; -+ len -= n; -+ n = os_read_file(req->fds[bit], buf, len); -+ if (n < 0) { -+ printk("do_io - read failed, err = %d " -+ "fd = %d\n", -n, req->fds[bit]); -+ req->error = 1; -+ return; -+ } -+ } while((n < len) && (n != 0)); -+ if (n < len) memset(&buf[n], 0, len - n); -+ } -+ else { -+ n = os_write_file(req->fds[bit], buf, len); -+ if(n != len){ -+ printk("do_io - write failed err = %d " -+ "fd = %d\n", -n, req->fds[bit]); -+ req->error = 1; -+ return; -+ } -+ } -+ -+ start = end; -+ } while(start < nsectors); -+ -+ req->error = update_bitmap(req); -+} -+ -+/* Changed in start_io_thread, which is serialized by being called only -+ * from ubd_init, which is an initcall. -+ */ -+int kernel_fd = -1; -+ -+/* Only changed by the io thread */ -+int io_count = 0; -+ -+int io_thread(void *arg) -+{ -+ struct io_thread_req req; -+ int n; -+ -+ signal(SIGWINCH, SIG_IGN); -+ while(1){ -+ n = os_read_file(kernel_fd, &req, sizeof(req)); -+ if(n != sizeof(req)){ -+ if(n < 0) -+ printk("io_thread - read failed, fd = %d, " -+ "err = %d\n", kernel_fd, -n); -+ else { -+ printk("io_thread - short read, fd = %d, " -+ "length = %d\n", kernel_fd, n); -+ } -+ continue; -+ } -+ io_count++; -+ do_io(&req); -+ n = os_write_file(kernel_fd, &req, sizeof(req)); -+ if(n != sizeof(req)) -+ printk("io_thread - write failed, fd = %d, err = %d\n", -+ kernel_fd, -n); -+ } -+} -+ -+int start_io_thread(unsigned long sp, int *fd_out) -+{ -+ int pid, fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err < 0){ -+ printk("start_io_thread - os_pipe failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ kernel_fd = fds[0]; -+ *fd_out = fds[1]; -+ -+ pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, -+ NULL); -+ if(pid < 0){ -+ printk("start_io_thread - clone failed : errno = %d\n", errno); -+ goto out_close; -+ } -+ -+ return(pid); -+ -+ out_close: -+ os_close_file(fds[0]); -+ os_close_file(fds[1]); -+ kernel_fd = -1; -+ *fd_out = -1; -+ out: -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/xterm.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/xterm.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/xterm.c 2005-05-03 22:28:14.260442296 +0300 -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <termios.h> -+#include <signal.h> -+#include <sched.h> -+#include <sys/socket.h> -+#include "kern_util.h" -+#include "chan_user.h" -+#include "helper.h" -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+#include "xterm.h" -+ -+struct xterm_chan { -+ int pid; -+ int helper_pid; -+ char *title; -+ int device; -+ int raw; -+ struct termios tt; -+ unsigned long stack; -+ int direct_rcv; -+}; -+ -+void *xterm_init(char *str, int device, struct chan_opts *opts) -+{ -+ struct xterm_chan *data; -+ -+ data = malloc(sizeof(*data)); -+ if(data == NULL) return(NULL); -+ *data = ((struct xterm_chan) { .pid = -1, -+ .helper_pid = -1, -+ .device = device, -+ .title = opts->xterm_title, -+ .raw = opts->raw, -+ .stack = opts->tramp_stack, -+ .direct_rcv = !opts->in_kernel } ); -+ return(data); -+} -+ -+/* Only changed by xterm_setup, which is a setup */ -+static char *terminal_emulator = "xterm"; -+static char *title_switch = "-T"; -+static char *exec_switch = "-e"; -+ -+static int __init xterm_setup(char *line, int *add) -+{ -+ *add = 0; -+ terminal_emulator = line; -+ -+ line = strchr(line, ','); -+ if(line == NULL) return(0); -+ *line++ = '\0'; -+ if(*line) title_switch = line; -+ -+ line = strchr(line, ','); -+ if(line == NULL) return(0); -+ *line++ = '\0'; -+ if(*line) exec_switch = line; -+ -+ return(0); -+} -+ -+__uml_setup("xterm=", xterm_setup, -+"xterm=<terminal emulator>,<title switch>,<exec switch>\n" -+" Specifies an alternate terminal emulator to use for the debugger,\n" -+" consoles, and serial lines when they are attached to the xterm channel.\n" -+" The values are the terminal emulator binary, the switch it uses to set\n" -+" its title, and the switch it uses to execute a subprocess,\n" -+" respectively. The title switch must have the form '<switch> title',\n" -+" not '<switch>=title'. Similarly, the exec switch must have the form\n" -+" '<switch> command arg1 arg2 ...'.\n" -+" The default values are 'xterm=xterm,-T,-e'. Values for gnome-terminal\n" -+" are 'xterm=gnome-terminal,-t,-x'.\n\n" -+); -+ -+/* XXX This badly needs some cleaning up in the error paths */ -+int xterm_open(int input, int output, int primary, void *d, char **dev_out) -+{ -+ struct xterm_chan *data = d; -+ unsigned long stack; -+ int pid, fd, new, err; -+ char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; -+ char *argv[] = { terminal_emulator, title_switch, title, exec_switch, -+ "/usr/lib/uml/port-helper", "-uml-socket", -+ file, NULL }; -+ -+ if(os_access(argv[4], OS_ACC_X_OK) < 0) -+ argv[4] = "port-helper"; -+ -+ fd = mkstemp(file); -+ if(fd < 0){ -+ printk("xterm_open : mkstemp failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(unlink(file)){ -+ printk("xterm_open : unlink failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ os_close_file(fd); -+ -+ fd = os_create_unix_socket(file, sizeof(file), 1); -+ if(fd < 0){ -+ printk("xterm_open : create_unix_socket failed, errno = %d\n", -+ -fd); -+ return(fd); -+ } -+ -+ sprintf(title, data->title, data->device); -+ stack = data->stack; -+ pid = run_helper(NULL, NULL, argv, &stack); -+ if(pid < 0){ -+ printk("xterm_open : run_helper failed, errno = %d\n", -pid); -+ return(pid); -+ } -+ -+ if(data->stack == 0) free_stack(stack, 0); -+ -+ if(data->direct_rcv) -+ new = os_rcv_fd(fd, &data->helper_pid); -+ else { -+ err = os_set_fd_block(fd, 0); -+ if(err < 0){ -+ printk("xterm_open : failed to set descriptor " -+ "non-blocking, err = %d\n", -err); -+ return(err); -+ } -+ new = xterm_fd(fd, &data->helper_pid); -+ } -+ if(new < 0){ -+ printk("xterm_open : os_rcv_fd failed, err = %d\n", -new); -+ goto out; -+ } -+ -+ CATCH_EINTR(err = tcgetattr(new, &data->tt)); -+ if(err){ -+ new = err; -+ goto out; -+ } -+ -+ if(data->raw){ -+ err = raw(new); -+ if(err){ -+ new = err; -+ goto out; -+ } -+ } -+ -+ data->pid = pid; -+ *dev_out = NULL; -+ out: -+ unlink(file); -+ return(new); -+} -+ -+void xterm_close(int fd, void *d) -+{ -+ struct xterm_chan *data = d; -+ -+ if(data->pid != -1) -+ os_kill_process(data->pid, 1); -+ data->pid = -1; -+ if(data->helper_pid != -1) -+ os_kill_process(data->helper_pid, 0); -+ data->helper_pid = -1; -+ os_close_file(fd); -+} -+ -+void xterm_free(void *d) -+{ -+ free(d); -+} -+ -+int xterm_console_write(int fd, const char *buf, int n, void *d) -+{ -+ struct xterm_chan *data = d; -+ -+ return(generic_console_write(fd, buf, n, &data->tt)); -+} -+ -+struct chan_ops xterm_ops = { -+ .type = "xterm", -+ .init = xterm_init, -+ .open = xterm_open, -+ .close = xterm_close, -+ .read = generic_read, -+ .write = generic_write, -+ .console_write = xterm_console_write, -+ .window_size = generic_window_size, -+ .free = xterm_free, -+ .winch = 1, -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/xterm.h -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/xterm.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/xterm.h 2005-05-03 22:28:14.261442144 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __XTERM_H__ -+#define __XTERM_H__ -+ -+extern int xterm_fd(int socket, int *pid_out); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/drivers/xterm_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/drivers/xterm_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/drivers/xterm_kern.c 2005-05-03 22:28:14.262441992 +0300 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/errno.h" -+#include "linux/slab.h" -+#include "asm/semaphore.h" -+#include "asm/irq.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "kern_util.h" -+#include "os.h" -+#include "xterm.h" -+ -+struct xterm_wait { -+ struct semaphore sem; -+ int fd; -+ int pid; -+ int new_fd; -+}; -+ -+static void xterm_interrupt(int irq, void *data, struct pt_regs *regs) -+{ -+ struct xterm_wait *xterm = data; -+ int fd; -+ -+ fd = os_rcv_fd(xterm->fd, &xterm->pid); -+ if(fd == -EAGAIN) -+ return; -+ -+ xterm->new_fd = fd; -+ up(&xterm->sem); -+} -+ -+int xterm_fd(int socket, int *pid_out) -+{ -+ struct xterm_wait *data; -+ int err, ret; -+ -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL){ -+ printk(KERN_ERR "xterm_fd : failed to allocate xterm_wait\n"); -+ return(-ENOMEM); -+ } -+ *data = ((struct xterm_wait) -+ { .sem = __SEMAPHORE_INITIALIZER(data->sem, 0), -+ .fd = socket, -+ .pid = -1, -+ .new_fd = -1 }); -+ -+ err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, -+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, -+ "xterm", data); -+ if(err){ -+ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " -+ "err = %d\n", err); -+ ret = err; -+ goto out; -+ } -+ down(&data->sem); -+ -+ free_irq(XTERM_IRQ, data); -+ -+ ret = data->new_fd; -+ *pid_out = data->pid; -+ out: -+ kfree(data); -+ -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/externfs.c -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/externfs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/externfs.c 2005-05-03 22:28:14.269440928 +0300 -@@ -0,0 +1,1283 @@ -+/* -+ * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/stddef.h> -+#include <linux/fs.h> -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/pagemap.h> -+#include <linux/blkdev.h> -+#include <asm/uaccess.h> -+#include "hostfs.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "user_util.h" -+#include "2_5compat.h" -+#include "mem.h" -+#include "filehandle.h" -+ -+struct externfs { -+ struct list_head list; -+ struct externfs_mount_ops *mount_ops; -+ struct file_system_type type; -+}; -+ -+static inline struct externfs_inode *EXTERNFS_I(struct inode *inode) -+{ -+ return(inode->u.generic_ip); -+} -+ -+#define file_externfs_i(file) EXTERNFS_I((file)->f_dentry->d_inode) -+ -+int externfs_d_delete(struct dentry *dentry) -+{ -+ return(1); -+} -+ -+struct dentry_operations externfs_dentry_ops = { -+}; -+ -+#define EXTERNFS_SUPER_MAGIC 0x00c0ffee -+ -+static struct inode_operations externfs_iops; -+static struct inode_operations externfs_dir_iops; -+static struct address_space_operations externfs_link_aops; -+ -+static char *dentry_name(struct dentry *dentry, int extra) -+{ -+ struct dentry *parent; -+ char *name; -+ int len; -+ -+ len = 0; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ len += parent->d_name.len + 1; -+ parent = parent->d_parent; -+ } -+ -+ name = kmalloc(len + extra + 1, GFP_KERNEL); -+ if(name == NULL) return(NULL); -+ -+ name[len] = '\0'; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ len -= parent->d_name.len + 1; -+ name[len] = '/'; -+ strncpy(&name[len + 1], parent->d_name.name, -+ parent->d_name.len); -+ parent = parent->d_parent; -+ } -+ -+ return(name); -+} -+ -+char *inode_name(struct inode *ino, int extra) -+{ -+ struct dentry *dentry; -+ -+ dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias); -+ return(dentry_name(dentry, extra)); -+} -+ -+char *inode_name_prefix(struct inode *inode, char *prefix) -+{ -+ int len; -+ char *name; -+ -+ len = strlen(prefix); -+ name = inode_name(inode, len); -+ if(name == NULL) -+ return(name); -+ -+ memmove(&name[len], name, strlen(name) + 1); -+ memcpy(name, prefix, strlen(prefix)); -+ return(name); -+} -+ -+static int read_name(struct inode *ino, char *name) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ /* The non-int inode fields are copied into ints by stat_file and -+ * then copied into the inode because passing the actual pointers -+ * in and having them treated as int * breaks on big-endian machines -+ */ -+ int err; -+ int i_dev, i_mode, i_nlink, i_blksize; -+ unsigned long long i_size; -+ unsigned long long i_ino; -+ unsigned long long i_blocks; -+ -+ err = (*ops->stat_file)(name, ino->i_sb->u.generic_sbp, -+ (dev_t *) &i_dev, &i_ino, &i_mode, &i_nlink, -+ &ino->i_uid, &ino->i_gid, &i_size, -+ &ino->i_atime, &ino->i_mtime, &ino->i_ctime, -+ &i_blksize, &i_blocks); -+ if(err) return(err); -+ ino->i_ino = i_ino; -+ ino->i_dev = i_dev; -+ ino->i_mode = i_mode; -+ ino->i_nlink = i_nlink; -+ ino->i_size = i_size; -+ ino->i_blksize = i_blksize; -+ ino->i_blocks = i_blocks; -+ return(0); -+} -+ -+static char *follow_link(char *link, -+ int (*do_read_link)(char *path, int uid, int gid, -+ char *buf, int size, -+ struct externfs_data *ed), -+ int uid, int gid, struct externfs_data *ed) -+{ -+ int len, n; -+ char *name, *resolved, *end; -+ -+ len = 64; -+ while(1){ -+ n = -ENOMEM; -+ name = kmalloc(len, GFP_KERNEL); -+ if(name == NULL) -+ goto out; -+ -+ n = (*do_read_link)(link, uid, gid, name, len, ed); -+ if(n < len) -+ break; -+ len *= 2; -+ kfree(name); -+ } -+ if(n < 0) -+ goto out_free; -+ -+ if(*name == '/') -+ return(name); -+ -+ end = strrchr(link, '/'); -+ if(end == NULL) -+ return(name); -+ -+ *(end + 1) = '\0'; -+ len = strlen(link) + strlen(name) + 1; -+ -+ resolved = kmalloc(len, GFP_KERNEL); -+ if(resolved == NULL){ -+ n = -ENOMEM; -+ goto out_free; -+ } -+ -+ sprintf(resolved, "%s%s", link, name); -+ kfree(name); -+ return(resolved); -+ -+ out_free: -+ kfree(name); -+ out: -+ return(ERR_PTR(n)); -+} -+ -+static int read_inode(struct inode *ino) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ char *name, *new; -+ int err, type; -+ -+ err = -ENOMEM; -+ name = inode_name(ino, 0); -+ if(name == NULL) -+ goto out; -+ -+ type = (*ops->file_type)(name, NULL, ed); -+ if(type < 0){ -+ err = type; -+ goto out_free; -+ } -+ -+ if(type == OS_TYPE_SYMLINK){ -+ new = follow_link(name, ops->read_link, current->fsuid, -+ current->fsgid, ed); -+ if(IS_ERR(new)){ -+ err = PTR_ERR(new); -+ goto out_free; -+ } -+ kfree(name); -+ name = new; -+ } -+ -+ err = read_name(ino, name); -+ out_free: -+ kfree(name); -+ out: -+ return(err); -+} -+ -+void externfs_delete_inode(struct inode *ino) -+{ -+ struct externfs_inode *ext = EXTERNFS_I(ino); -+ struct externfs_file_ops *ops = ext->ops; -+ -+ (*ops->close_file)(ext, ino->i_size); -+ -+ clear_inode(ino); -+} -+ -+int externfs_statfs(struct super_block *sb, struct statfs *sf) -+{ -+ /* do_statfs uses struct statfs64 internally, but the linux kernel -+ * struct statfs still has 32-bit versions for most of these fields, -+ * so we convert them here -+ */ -+ int err; -+ long long f_blocks; -+ long long f_bfree; -+ long long f_bavail; -+ long long f_files; -+ long long f_ffree; -+ struct externfs_data *ed = sb->u.generic_sbp; -+ -+ err = (*ed->file_ops->statfs)(&sf->f_bsize, &f_blocks, &f_bfree, -+ &f_bavail, &f_files, &f_ffree, -+ &sf->f_fsid, sizeof(sf->f_fsid), -+ &sf->f_namelen, sf->f_spare, ed); -+ if(err) -+ return(err); -+ -+ sf->f_blocks = f_blocks; -+ sf->f_bfree = f_bfree; -+ sf->f_bavail = f_bavail; -+ sf->f_files = f_files; -+ sf->f_ffree = f_ffree; -+ sf->f_type = EXTERNFS_SUPER_MAGIC; -+ return(0); -+} -+ -+static struct super_operations externfs_sbops = { -+ .delete_inode = externfs_delete_inode, -+ .statfs = externfs_statfs, -+}; -+ -+int externfs_readdir(struct file *file, void *ent, filldir_t filldir) -+{ -+ void *dir; -+ char *name; -+ unsigned long long next, ino; -+ int error, len; -+ struct externfs_file_ops *ops = file_externfs_i(file)->ops; -+ struct externfs_data *ed = -+ file->f_dentry->d_inode->i_sb->u.generic_sbp; -+ -+ name = dentry_name(file->f_dentry, 0); -+ if(name == NULL) -+ return(-ENOMEM); -+ -+ dir = (*ops->open_dir)(name, current->fsuid, current->fsgid, ed); -+ kfree(name); -+ if(IS_ERR(dir)) -+ return(PTR_ERR(dir)); -+ -+ next = file->f_pos; -+ while((name = (*ops->read_dir)(dir, &next, &ino, &len, ed)) != NULL){ -+ error = (*filldir)(ent, name, len, file->f_pos, ino, -+ DT_UNKNOWN); -+ if(error) -+ break; -+ file->f_pos = next; -+ } -+ (*ops->close_dir)(dir, ed); -+ return(0); -+} -+ -+int externfs_file_open(struct inode *ino, struct file *file) -+{ -+ ino->i_nlink++; -+ return(0); -+} -+ -+int externfs_dir_open(struct inode *ino, struct file *file) -+{ -+ return(0); -+} -+ -+int externfs_dir_release(struct inode *ino, struct file *file) -+{ -+ return(0); -+} -+ -+int externfs_fsync(struct file *file, struct dentry *dentry, int datasync) -+{ -+ struct externfs_file_ops *ops = file_externfs_i(file)->ops; -+ struct inode *inode = dentry->d_inode; -+ struct externfs_data *ed = inode->i_sb->u.generic_sbp; -+ -+ return((*ops->truncate_file)(EXTERNFS_I(inode), inode->i_size, ed)); -+} -+ -+static struct file_operations externfs_file_fops = { -+ .owner = NULL, -+ .read = generic_file_read, -+ .write = generic_file_write, -+ .mmap = generic_file_mmap, -+ .open = externfs_file_open, -+ .release = NULL, -+ .fsync = externfs_fsync, -+}; -+ -+static struct file_operations externfs_dir_fops = { -+ .owner = NULL, -+ .readdir = externfs_readdir, -+ .open = externfs_dir_open, -+ .release = externfs_dir_release, -+ .fsync = externfs_fsync, -+}; -+ -+struct wp_info { -+ struct page *page; -+ int count; -+ unsigned long long start; -+ unsigned long long size; -+ int (*truncate)(struct externfs_inode *ei, __u64 size, -+ struct externfs_data *ed); -+ struct externfs_inode *ei; -+ struct externfs_data *ed; -+}; -+ -+static void externfs_finish_writepage(char *buffer, int res, void *arg) -+{ -+ struct wp_info *wp = arg; -+ -+ if(res == wp->count){ -+ ClearPageError(wp->page); -+ if(wp->start + res > wp->size) -+ (*wp->truncate)(wp->ei, wp->size, wp->ed); -+ } -+ else { -+ SetPageError(wp->page); -+ ClearPageUptodate(wp->page); -+ } -+ -+ kunmap(wp->page); -+ unlock_page(wp->page); -+ kfree(wp); -+} -+ -+static int externfs_writepage(struct page *page) -+{ -+ struct address_space *mapping = page->mapping; -+ struct inode *inode = mapping->host; -+ struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops; -+ struct wp_info *wp; -+ struct externfs_data *ed = inode->i_sb->u.generic_sbp; -+ char *buffer; -+ unsigned long long base; -+ int count = PAGE_CACHE_SIZE; -+ int end_index = inode->i_size >> PAGE_CACHE_SHIFT; -+ int err, offset; -+ -+ base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT; -+ -+ /* If we are entirely outside the file, then return an error */ -+ err = -EIO; -+ offset = inode->i_size & (PAGE_CACHE_SIZE-1); -+ if (page->index > end_index || -+ ((page->index == end_index) && !offset)) -+ goto out_unlock; -+ -+ err = -ENOMEM; -+ wp = kmalloc(sizeof(*wp), GFP_KERNEL); -+ if(wp == NULL) -+ goto out_unlock; -+ -+ *wp = ((struct wp_info) { .page = page, -+ .count = count, -+ .start = base, -+ .size = inode->i_size, -+ .truncate = ops->truncate_file, -+ .ei = EXTERNFS_I(inode), -+ .ed = ed }); -+ -+ buffer = kmap(page); -+ err = (*ops->write_file)(EXTERNFS_I(inode), base, buffer, 0, -+ count, externfs_finish_writepage, wp, ed); -+ -+ return err; -+ -+ out_unlock: -+ unlock_page(page); -+ return(err); -+} -+ -+static void externfs_finish_readpage(char *buffer, int res, void *arg) -+{ -+ struct page *page = arg; -+ struct inode *inode; -+ -+ if(res < 0){ -+ SetPageError(page); -+ goto out; -+ } -+ -+ inode = page->mapping->host; -+ if(inode->i_size >> PAGE_CACHE_SHIFT == page->index) -+ res = inode->i_size % PAGE_CACHE_SIZE; -+ -+ memset(&buffer[res], 0, PAGE_CACHE_SIZE - res); -+ -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ if (PageError(page)) -+ ClearPageError(page); -+ out: -+ kunmap(page); -+ unlock_page(page); -+} -+ -+static int externfs_readpage(struct file *file, struct page *page) -+{ -+ struct inode *ino = page->mapping->host; -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ char *buffer; -+ long long start; -+ int err = 0; -+ -+ start = (long long) page->index << PAGE_CACHE_SHIFT; -+ buffer = kmap(page); -+ -+ if(ops->map_file_page != NULL){ -+ /* XXX What happens when PAGE_SIZE != PAGE_CACHE_SIZE? */ -+ err = (*ops->map_file_page)(file_externfs_i(file), start, -+ buffer, file->f_mode & FMODE_WRITE, -+ ed); -+ if(!err) -+ err = PAGE_CACHE_SIZE; -+ } -+ else err = (*ops->read_file)(file_externfs_i(file), start, buffer, -+ PAGE_CACHE_SIZE, 0, 0, -+ externfs_finish_readpage, page, ed); -+ -+ if(err > 0) -+ err = 0; -+ return(err); -+} -+ -+struct writepage_info { -+ struct semaphore sem; -+ int res; -+}; -+ -+static void externfs_finish_prepare(char *buffer, int res, void *arg) -+{ -+ struct writepage_info *wp = arg; -+ -+ wp->res = res; -+ up(&wp->sem); -+} -+ -+int externfs_prepare_write(struct file *file, struct page *page, -+ unsigned int from, unsigned int to) -+{ -+ struct address_space *mapping = page->mapping; -+ struct inode *inode = mapping->host; -+ struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops; -+ struct externfs_data *ed = inode->i_sb->u.generic_sbp; -+ char *buffer; -+ long long start; -+ int err; -+ struct writepage_info wp; -+ -+ if(Page_Uptodate(page)) -+ return(0); -+ -+ start = (long long) page->index << PAGE_CACHE_SHIFT; -+ buffer = kmap(page); -+ -+ if(ops->map_file_page != NULL){ -+ err = (*ops->map_file_page)(file_externfs_i(file), start, -+ buffer, file->f_mode & FMODE_WRITE, -+ ed); -+ goto out; -+ } -+ -+ init_MUTEX_LOCKED(&wp.sem); -+ err = (*ops->read_file)(file_externfs_i(file), start, buffer, -+ PAGE_CACHE_SIZE, from, to, -+ externfs_finish_prepare, &wp, ed); -+ down(&wp.sem); -+ if(err < 0) -+ goto out; -+ -+ err = wp.res; -+ if(err < 0) -+ goto out; -+ -+ if(from > 0) -+ memset(buffer, 0, from); -+ if(to < PAGE_CACHE_SIZE) -+ memset(buffer + to, 0, PAGE_CACHE_SIZE - to); -+ -+ SetPageUptodate(page); -+ err = 0; -+ out: -+ kunmap(page); -+ return(err); -+} -+ -+static int externfs_commit_write(struct file *file, struct page *page, -+ unsigned from, unsigned to) -+{ -+ struct address_space *mapping = page->mapping; -+ struct inode *inode = mapping->host; -+ struct externfs_file_ops *ops = EXTERNFS_I(inode)->ops; -+ unsigned long long size; -+ long long start; -+ int err; -+ -+ start = (long long) (page->index << PAGE_CACHE_SHIFT); -+ -+ if(ops->map_file_page != NULL) -+ err = to - from; -+ else { -+ size = start + to; -+ if(size > inode->i_size){ -+ inode->i_size = size; -+ mark_inode_dirty(inode); -+ } -+ } -+ -+ set_page_dirty(page); -+ return(to - from); -+} -+ -+static void externfs_removepage(struct page *page) -+{ -+ physmem_remove_mapping(page_address(page)); -+} -+ -+static struct address_space_operations externfs_aops = { -+ .writepage = externfs_writepage, -+ .readpage = externfs_readpage, -+ .removepage = externfs_removepage, -+/* .set_page_dirty = __set_page_dirty_nobuffers, */ -+ .prepare_write = externfs_prepare_write, -+ .commit_write = externfs_commit_write -+}; -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int need_fh) -+{ -+ struct inode *inode; -+ struct externfs_data *ed = sb->u.generic_sbp; -+ struct externfs_mount_ops *ops = ed->mount_ops; -+ char *name = NULL; -+ int type, err = -ENOMEM, rdev; -+ -+ if(dentry){ -+ name = dentry_name(dentry, 0); -+ if(name == NULL) -+ goto out; -+ type = (*ed->file_ops->file_type)(name, &rdev, ed); -+ } -+ else type = OS_TYPE_DIR; -+ -+ inode = new_inode(sb); -+ if(inode == NULL) -+ goto out_free; -+ -+ insert_inode_hash(inode); -+ -+ if(type == OS_TYPE_SYMLINK) -+ inode->i_op = &page_symlink_inode_operations; -+ else if(type == OS_TYPE_DIR) -+ inode->i_op = &externfs_dir_iops; -+ else inode->i_op = &externfs_iops; -+ -+ if(type == OS_TYPE_DIR) inode->i_fop = &externfs_dir_fops; -+ else inode->i_fop = &externfs_file_fops; -+ -+ if(type == OS_TYPE_SYMLINK) -+ inode->i_mapping->a_ops = &externfs_link_aops; -+ else inode->i_mapping->a_ops = &externfs_aops; -+ -+ switch (type) { -+ case OS_TYPE_CHARDEV: -+ init_special_inode(inode, S_IFCHR, rdev); -+ break; -+ case OS_TYPE_BLOCKDEV: -+ init_special_inode(inode, S_IFBLK, rdev); -+ break; -+ case OS_TYPE_FIFO: -+ init_special_inode(inode, S_IFIFO, 0); -+ break; -+ case OS_TYPE_SOCK: -+ init_special_inode(inode, S_IFSOCK, 0); -+ break; -+ case OS_TYPE_SYMLINK: -+ inode->i_mode = S_IFLNK | S_IRWXUGO; -+ } -+ -+ if(need_fh){ -+ struct externfs_inode *ei; -+ -+ err = -ENOMEM; -+ ei = (*ops->init_file)(ed); -+ if(ei == NULL) -+ goto out_put; -+ -+ *ei = ((struct externfs_inode) { .ops = ed->file_ops }); -+ inode->u.generic_ip = ei; -+ -+ err = (*ed->file_ops->open_file)(ei, name, current->fsuid, -+ current->fsgid, inode, ed); -+ if(err && ((err != -ENOENT) && (err != -EISDIR))) -+ goto out_put; -+ } -+ -+ return(inode); -+ -+ out_put: -+ iput(inode); -+ out_free: -+ kfree(name); -+ out: -+ return(ERR_PTR(err)); -+} -+ -+int externfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(dir)->ops; -+ struct inode *inode; -+ struct externfs_data *ed = dir->i_sb->u.generic_sbp; -+ struct externfs_inode *ei; -+ char *name; -+ int err = -ENOMEM; -+ -+ name = dentry_name(dentry, 0); -+ if(name == NULL) -+ goto out; -+ -+ inode = get_inode(dir->i_sb, dentry, 0); -+ if(IS_ERR(inode)){ -+ err = PTR_ERR(inode); -+ goto out_free; -+ } -+ -+ ei = (*ed->mount_ops->init_file)(ed); -+ if(ei == NULL) -+ /* XXX need a free_file() */ -+ goto out_put; -+ -+ *ei = ((struct externfs_inode) { .ops = ed->file_ops }); -+ inode->u.generic_ip = ei; -+ -+ err = (*ops->create_file)(ei, name, mode, current->fsuid, -+ current->fsuid, inode, ed); -+ if(err) -+ goto out_put; -+ -+ err = read_name(inode, name); -+ if(err) -+ goto out_rm; -+ -+ inode->i_nlink++; -+ d_instantiate(dentry, inode); -+ out_free: -+ kfree(name); -+ out: -+ return(err); -+ -+ out_rm: -+ (*ops->unlink_file)(name, ed); -+ out_put: -+ inode->i_nlink = 0; -+ iput(inode); -+ goto out_free; -+} -+ -+struct dentry *externfs_lookup(struct inode *ino, struct dentry *dentry) -+{ -+ struct inode *inode; -+ char *name; -+ int err; -+ -+ inode = get_inode(ino->i_sb, dentry, 1); -+ if(IS_ERR(inode)){ -+ err = PTR_ERR(inode); -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ name = dentry_name(dentry, 0); -+ if(name == NULL) -+ goto out_put; -+ -+ err = read_name(inode, name); -+ kfree(name); -+ if(err){ -+ if(err != -ENOENT) -+ goto out_put; -+ -+ inode->i_nlink = 0; -+ iput(inode); -+ inode = NULL; -+ } -+ d_add(dentry, inode); -+ dentry->d_op = &externfs_dentry_ops; -+ return(NULL); -+ -+ out_put: -+ inode->i_nlink = 0; -+ iput(inode); -+ out: -+ return(ERR_PTR(err)); -+} -+ -+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry) -+{ -+ char *file; -+ int len; -+ -+ file = inode_name(ino, dentry->d_name.len + 1); -+ if(file == NULL) return(NULL); -+ strcat(file, "/"); -+ len = strlen(file); -+ strncat(file, dentry->d_name.name, dentry->d_name.len); -+ file[len + dentry->d_name.len] = '\0'; -+ return(file); -+} -+ -+int externfs_link(struct dentry *to, struct inode *ino, struct dentry *from) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ char *from_name, *to_name; -+ int err = -ENOMEM; -+ -+ from_name = inode_dentry_name(ino, from); -+ if(from_name == NULL) -+ goto out; -+ -+ to_name = dentry_name(to, 0); -+ if(to_name == NULL) -+ goto out_free_from; -+ -+ err = (*ops->link_file)(to_name, from_name, current->fsuid, -+ current->fsgid, ed); -+ if(err) -+ goto out_free_to; -+ -+ d_instantiate(from, to->d_inode); -+ to->d_inode->i_nlink++; -+ atomic_inc(&to->d_inode->i_count); -+ -+ out_free_to: -+ kfree(to_name); -+ out_free_from: -+ kfree(from_name); -+ out: -+ return(err); -+} -+ -+int externfs_unlink(struct inode *ino, struct dentry *dentry) -+{ -+ struct inode *inode; -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) -+ return(-ENOMEM); -+ -+ inode = dentry->d_inode; -+ if((inode->i_nlink == 1) && (ops->invisible != NULL)) -+ (*ops->invisible)(EXTERNFS_I(inode)); -+ -+ err = (*ops->unlink_file)(file, ed); -+ kfree(file); -+ -+ inode->i_nlink--; -+ -+ return(err); -+} -+ -+int externfs_symlink(struct inode *ino, struct dentry *dentry, const char *to) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ struct inode *inode; -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) -+ return(-ENOMEM); -+ err = (*ops->make_symlink)(file, to, current->fsuid, current->fsgid, -+ ed); -+ kfree(file); -+ -+ inode = get_inode(ino->i_sb, dentry, 1); -+ if(IS_ERR(inode)){ -+ err = PTR_ERR(inode); -+ goto out; -+ } -+ -+ d_instantiate(dentry, inode); -+ inode->i_nlink++; -+ iput(inode); -+ out: -+ return(err); -+} -+ -+int externfs_make_dir(struct inode *ino, struct dentry *dentry, int mode) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ struct inode *inode; -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) -+ return(-ENOMEM); -+ err = (*ops->make_dir)(file, mode, current->fsuid, current->fsgid, ed); -+ -+ inode = get_inode(ino->i_sb, dentry, 1); -+ if(IS_ERR(inode)){ -+ err = PTR_ERR(inode); -+ goto out_free; -+ } -+ -+ err = read_name(inode, file); -+ kfree(file); -+ if(err) -+ goto out_put; -+ -+ d_instantiate(dentry, inode); -+ inode->i_nlink = 2; -+ inode->i_mode = S_IFDIR | mode; -+ iput(inode); -+ -+ ino->i_nlink++; -+ out: -+ return(err); -+ out_free: -+ kfree(file); -+ out_put: -+ inode->i_nlink = 0; -+ iput(inode); -+ goto out; -+} -+ -+int externfs_remove_dir(struct inode *ino, struct dentry *dentry) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ void *mount = ino->i_sb->u.generic_sbp; -+ char *file; -+ int err; -+ -+ file = inode_dentry_name(ino, dentry); -+ if(file == NULL) -+ return(-ENOMEM); -+ err = (*ops->remove_dir)(file, current->fsuid, current->fsgid, mount); -+ kfree(file); -+ -+ dentry->d_inode->i_nlink = 0; -+ ino->i_nlink--; -+ return(err); -+} -+ -+int externfs_make_node(struct inode *dir, struct dentry *dentry, int mode, -+ int dev) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(dir)->ops; -+ struct externfs_data *ed = dir->i_sb->u.generic_sbp; -+ struct inode *inode; -+ char *name; -+ int err = -ENOMEM; -+ -+ name = dentry_name(dentry, 0); -+ if(name == NULL) -+ goto out; -+ -+ inode = get_inode(dir->i_sb, dentry, 1); -+ if(IS_ERR(inode)){ -+ err = PTR_ERR(inode); -+ goto out_free; -+ } -+ -+ init_special_inode(inode, mode, dev); -+ err = (*ops->make_node)(name, mode & S_IRWXUGO, current->fsuid, -+ current->fsgid, mode & S_IFMT, major(dev), -+ minor(dev), ed); -+ if(err) -+ goto out_put; -+ -+ err = read_name(inode, name); -+ if(err) -+ goto out_rm; -+ -+ d_instantiate(dentry, inode); -+ out_free: -+ kfree(name); -+ out: -+ return(err); -+ -+ out_rm: -+ (*ops->unlink_file)(name, ed); -+ out_put: -+ inode->i_nlink = 0; -+ iput(inode); -+ goto out_free; -+} -+ -+int externfs_rename(struct inode *from_ino, struct dentry *from, -+ struct inode *to_ino, struct dentry *to) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(from_ino)->ops; -+ struct externfs_data *ed = from_ino->i_sb->u.generic_sbp; -+ char *from_name, *to_name; -+ int err; -+ -+ from_name = inode_dentry_name(from_ino, from); -+ if(from_name == NULL) -+ return(-ENOMEM); -+ to_name = inode_dentry_name(to_ino, to); -+ if(to_name == NULL){ -+ kfree(from_name); -+ return(-ENOMEM); -+ } -+ err = (*ops->rename_file)(from_name, to_name, ed); -+ kfree(from_name); -+ kfree(to_name); -+ -+ from_ino->i_nlink--; -+ to_ino->i_nlink++; -+ return(err); -+} -+ -+void externfs_truncate(struct inode *ino) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ -+ (*ops->truncate_file)(EXTERNFS_I(ino), ino->i_size, ed); -+} -+ -+int externfs_permission(struct inode *ino, int desired) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ char *name; -+ int r = 0, w = 0, x = 0, err; -+ -+ if(ops->access_file == NULL) -+ return(vfs_permission(ino, desired)); -+ -+ if(desired & MAY_READ) r = 1; -+ if(desired & MAY_WRITE) w = 1; -+ if(desired & MAY_EXEC) x = 1; -+ name = inode_name(ino, 0); -+ if(name == NULL) -+ return(-ENOMEM); -+ -+ err = (*ops->access_file)(name, r, w, x, current->fsuid, -+ current->fsgid, ed); -+ kfree(name); -+ -+ if(!err) -+ err = vfs_permission(ino, desired); -+ return(err); -+} -+ -+int externfs_setattr(struct dentry *dentry, struct iattr *attr) -+{ -+ struct externfs_file_ops *ops = EXTERNFS_I(dentry->d_inode)->ops; -+ struct externfs_data *ed = dentry->d_inode->i_sb->u.generic_sbp; -+ struct externfs_iattr attrs; -+ char *name; -+ int err; -+ -+ attrs.ia_valid = 0; -+ if(attr->ia_valid & ATTR_MODE){ -+ attrs.ia_valid |= EXTERNFS_ATTR_MODE; -+ attrs.ia_mode = attr->ia_mode; -+ } -+ if(attr->ia_valid & ATTR_UID){ -+ attrs.ia_valid |= EXTERNFS_ATTR_UID; -+ attrs.ia_uid = attr->ia_uid; -+ } -+ if(attr->ia_valid & ATTR_GID){ -+ attrs.ia_valid |= EXTERNFS_ATTR_GID; -+ attrs.ia_gid = attr->ia_gid; -+ } -+ if(attr->ia_valid & ATTR_SIZE){ -+ attrs.ia_valid |= EXTERNFS_ATTR_SIZE; -+ attrs.ia_size = attr->ia_size; -+ } -+ if(attr->ia_valid & ATTR_ATIME){ -+ attrs.ia_valid |= EXTERNFS_ATTR_ATIME; -+ attrs.ia_atime = attr->ia_atime; -+ } -+ if(attr->ia_valid & ATTR_MTIME){ -+ attrs.ia_valid |= EXTERNFS_ATTR_MTIME; -+ attrs.ia_mtime = attr->ia_mtime; -+ } -+ if(attr->ia_valid & ATTR_CTIME){ -+ attrs.ia_valid |= EXTERNFS_ATTR_CTIME; -+ attrs.ia_ctime = attr->ia_ctime; -+ } -+ if(attr->ia_valid & ATTR_ATIME_SET){ -+ attrs.ia_valid |= EXTERNFS_ATTR_ATIME_SET; -+ } -+ if(attr->ia_valid & ATTR_MTIME_SET){ -+ attrs.ia_valid |= EXTERNFS_ATTR_MTIME_SET; -+ } -+ name = dentry_name(dentry, 0); -+ if(name == NULL) -+ return(-ENOMEM); -+ err = (*ops->set_attr)(name, &attrs, ed); -+ kfree(name); -+ if(err) -+ return(err); -+ -+ return(inode_setattr(dentry->d_inode, attr)); -+} -+ -+int externfs_getattr(struct dentry *dentry, struct iattr *attr) -+{ -+ not_implemented(); -+ return(-EINVAL); -+} -+ -+static struct inode_operations externfs_iops = { -+ .create = externfs_create, -+ .link = externfs_link, -+ .unlink = externfs_unlink, -+ .symlink = externfs_symlink, -+ .mkdir = externfs_make_dir, -+ .rmdir = externfs_remove_dir, -+ .mknod = externfs_make_node, -+ .rename = externfs_rename, -+ .truncate = externfs_truncate, -+ .permission = externfs_permission, -+ .setattr = externfs_setattr, -+ .getattr = externfs_getattr, -+}; -+ -+static struct inode_operations externfs_dir_iops = { -+ .create = externfs_create, -+ .lookup = externfs_lookup, -+ .link = externfs_link, -+ .unlink = externfs_unlink, -+ .symlink = externfs_symlink, -+ .mkdir = externfs_make_dir, -+ .rmdir = externfs_remove_dir, -+ .mknod = externfs_make_node, -+ .rename = externfs_rename, -+ .truncate = externfs_truncate, -+ .permission = externfs_permission, -+ .setattr = externfs_setattr, -+ .getattr = externfs_getattr, -+}; -+ -+int externfs_link_readpage(struct file *file, struct page *page) -+{ -+ struct inode *ino = page->mapping->host; -+ struct externfs_file_ops *ops = EXTERNFS_I(ino)->ops; -+ struct externfs_data *ed = ino->i_sb->u.generic_sbp; -+ char *buffer, *name; -+ long long start; -+ int err; -+ -+ start = page->index << PAGE_CACHE_SHIFT; -+ buffer = kmap(page); -+ name = inode_name(ino, 0); -+ if(name == NULL) -+ return(-ENOMEM); -+ -+ err = (*ops->read_link)(name, current->fsuid, current->fsgid, buffer, -+ PAGE_CACHE_SIZE, ed); -+ -+ kfree(name); -+ if(err == PAGE_CACHE_SIZE) -+ err = -E2BIG; -+ else if(err > 0){ -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ if (PageError(page)) ClearPageError(page); -+ err = 0; -+ } -+ kunmap(page); -+ UnlockPage(page); -+ return(err); -+} -+ -+static int externfs_flushpage(struct page *page, unsigned long offset) -+{ -+ return(externfs_writepage(page)); -+} -+ -+struct externfs_data *inode_externfs_info(struct inode *inode) -+{ -+ return(inode->i_sb->u.generic_sbp); -+} -+ -+static struct address_space_operations externfs_link_aops = { -+ .readpage = externfs_link_readpage, -+ .removepage = externfs_removepage, -+ .flushpage = externfs_flushpage, -+}; -+ -+DECLARE_MUTEX(externfs_sem); -+struct list_head externfses = LIST_HEAD_INIT(externfses); -+ -+static struct externfs *find_externfs(struct file_system_type *type) -+{ -+ struct list_head *ele; -+ struct externfs *fs; -+ -+ down(&externfs_sem); -+ list_for_each(ele, &externfses){ -+ fs = list_entry(ele, struct externfs, list); -+ if(&fs->type == type) -+ goto out; -+ } -+ fs = NULL; -+ out: -+ up(&externfs_sem); -+ return(fs); -+} -+ -+#define DEFAULT_ROOT "/" -+ -+char *host_root_filename(char *mount_arg) -+{ -+ char *root = DEFAULT_ROOT; -+ -+ if((mount_arg != NULL) && (*mount_arg != '\0')) -+ root = mount_arg; -+ -+ return(uml_strdup(root)); -+} -+ -+struct super_block *externfs_read_super(struct super_block *sb, void *data, -+ int silent) -+{ -+ struct externfs *fs; -+ struct inode *root_inode; -+ struct externfs_data *sb_data; -+ int err = -EINVAL; -+ -+ sb->s_blocksize = 1024; -+ sb->s_blocksize_bits = 10; -+ sb->s_magic = EXTERNFS_SUPER_MAGIC; -+ sb->s_op = &externfs_sbops; -+ -+ fs = find_externfs(sb->s_type); -+ if(fs == NULL){ -+ printk("Couldn't find externfs for filesystem '%s'\n", -+ sb->s_type->name); -+ goto out; -+ } -+ -+ sb_data = (*fs->mount_ops->mount)(data); -+ if(IS_ERR(sb_data)){ -+ err = PTR_ERR(sb_data); -+ goto out; -+ } -+ -+ sb->u.generic_sbp = sb_data; -+ sb_data->mount_ops = fs->mount_ops; -+ -+ root_inode = get_inode(sb, NULL, 1); -+ if(IS_ERR(root_inode)) -+ goto out; -+ -+ sb->s_root = d_alloc_root(root_inode); -+ if(sb->s_root == NULL) -+ goto out_put; -+ -+ if(read_inode(root_inode)) -+ goto out_dput; -+ return(sb); -+ -+ out_dput: -+ /* dput frees the inode */ -+ dput(sb->s_root); -+ return(NULL); -+ out_put: -+ root_inode->i_nlink = 0; -+ make_bad_inode(root_inode); -+ iput(root_inode); -+ out: -+ return(NULL); -+} -+ -+void init_externfs(struct externfs_data *ed, struct externfs_file_ops *ops) -+{ -+ ed->file_ops = ops; -+} -+ -+int register_externfs(char *name, struct externfs_mount_ops *mount_ops) -+{ -+ struct externfs *new; -+ int err = -ENOMEM; -+ -+ new = kmalloc(sizeof(*new), GFP_KERNEL); -+ if(new == NULL) -+ goto out; -+ -+ memset(new, 0, sizeof(*new)); -+ *new = ((struct externfs) { .list = LIST_HEAD_INIT(new->list), -+ .mount_ops = mount_ops, -+ .type = { .name = name, -+ .read_super = externfs_read_super, -+ .fs_flags = 0, -+ .owner = THIS_MODULE } }); -+ list_add(&new->list, &externfses); -+ -+ err = register_filesystem(&new->type); -+ if(err) -+ goto out_del; -+ return(0); -+ -+ out_del: -+ list_del(&new->list); -+ kfree(new); -+ out: -+ return(err); -+} -+ -+void unregister_externfs(char *name) -+{ -+ struct list_head *ele; -+ struct externfs *fs; -+ -+ down(&externfs_sem); -+ list_for_each(ele, &externfses){ -+ fs = list_entry(ele, struct externfs, list); -+ if(!strcmp(fs->type.name, name)){ -+ list_del(ele); -+ up(&externfs_sem); -+ return; -+ } -+ } -+ up(&externfs_sem); -+ printk("Unregister_externfs - filesystem '%s' not found\n", name); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/host_file.c -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/host_file.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/host_file.c 2005-05-03 22:28:14.271440624 +0300 -@@ -0,0 +1,441 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/string.h" -+#include "linux/errno.h" -+#include "linux/types.h" -+#include "linux/slab.h" -+#include "linux/blkdev.h" -+#include "asm/fcntl.h" -+#include "hostfs.h" -+ -+extern int append; -+ -+char *get_path(const char *path[], char *buf, int size) -+{ -+ const char **s; -+ char *p; -+ int new = 1; -+ -+ for(s = path; *s != NULL; s++){ -+ new += strlen(*s); -+ if((*(s + 1) != NULL) && (strlen(*s) > 0) && -+ ((*s)[strlen(*s) - 1] != '/')) -+ new++; -+ } -+ -+ if(new > size){ -+ buf = kmalloc(new, GFP_KERNEL); -+ if(buf == NULL) -+ return(NULL); -+ } -+ -+ p = buf; -+ for(s = path; *s != NULL; s++){ -+ strcpy(p, *s); -+ p += strlen(*s); -+ if((*(s + 1) != NULL) && (strlen(*s) > 0) && -+ ((*s)[strlen(*s) - 1] != '/')) -+ strcpy(p++, "/"); -+ } -+ -+ return(buf); -+} -+ -+void free_path(const char *buf, char *tmp) -+{ -+ if((buf != tmp) && (buf != NULL)) -+ kfree((char *) buf); -+} -+ -+int host_open_file(const char *path[], int r, int w, struct file_handle *fh) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int mode = 0, err; -+ struct openflags flags = OPENFLAGS(); -+ -+ if (r) -+ flags = of_read(flags); -+ if (w) -+ flags = of_write(flags); -+ if(append) -+ flags = of_append(flags); -+ -+ err = -ENOMEM; -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = open_filehandle(file, flags, mode, fh); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+void *host_open_dir(const char *path[]) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ void *dir = ERR_PTR(-ENOMEM); -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ dir = open_dir(file); -+ out: -+ free_path(file, tmp); -+ return(dir); -+} -+ -+char *host_read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out) -+{ -+ int err; -+ char *name; -+ -+ err = os_seek_dir(stream, *pos); -+ if(err) -+ return(ERR_PTR(err)); -+ -+ err = os_read_dir(stream, ino_out, &name); -+ if(err) -+ return(ERR_PTR(err)); -+ -+ if(name == NULL) -+ return(NULL); -+ -+ *len_out = strlen(name); -+ *pos = os_tell_dir(stream); -+ return(name); -+} -+ -+int host_file_type(const char *path[], int *rdev) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ struct uml_stat buf; -+ int ret; -+ -+ ret = -ENOMEM; -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ if(rdev != NULL){ -+ ret = os_lstat_file(file, &buf); -+ if(ret) -+ goto out; -+ *rdev = MKDEV(buf.ust_rmajor, buf.ust_rminor); -+ } -+ -+ ret = os_file_type(file); -+ out: -+ free_path(file, tmp); -+ return(ret); -+} -+ -+int host_create_file(const char *path[], int mode, struct file_handle *fh) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = open_filehandle(file, of_create(of_rdwr(OPENFLAGS())), mode, fh); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+static int do_stat_file(const char *path, dev_t *dev_out, -+ unsigned long long *inode_out, int *mode_out, -+ int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, unsigned long *atime_out, -+ unsigned long *mtime_out, unsigned long *ctime_out, -+ int *blksize_out, unsigned long long *blocks_out) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_lstat_file(path, &buf); -+ if(err < 0) -+ return(err); -+ -+ if(dev_out != NULL) *dev_out = MKDEV(buf.ust_major, buf.ust_minor); -+ if(inode_out != NULL) *inode_out = buf.ust_ino; -+ if(mode_out != NULL) *mode_out = buf.ust_mode; -+ if(nlink_out != NULL) *nlink_out = buf.ust_nlink; -+ if(uid_out != NULL) *uid_out = buf.ust_uid; -+ if(gid_out != NULL) *gid_out = buf.ust_gid; -+ if(size_out != NULL) *size_out = buf.ust_size; -+ if(atime_out != NULL) *atime_out = buf.ust_atime; -+ if(mtime_out != NULL) *mtime_out = buf.ust_mtime; -+ if(ctime_out != NULL) *ctime_out = buf.ust_ctime; -+ if(blksize_out != NULL) *blksize_out = buf.ust_blksize; -+ if(blocks_out != NULL) *blocks_out = buf.ust_blocks; -+ -+ return(0); -+} -+ -+int host_stat_file(const char *path[], dev_t *dev_out, -+ unsigned long long *inode_out, int *mode_out, -+ int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, unsigned long *atime_out, -+ unsigned long *mtime_out, unsigned long *ctime_out, -+ int *blksize_out, unsigned long long *blocks_out) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err; -+ -+ err = -ENOMEM; -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = do_stat_file(file, dev_out, inode_out, mode_out, nlink_out, -+ uid_out, gid_out, size_out, atime_out, mtime_out, -+ ctime_out, blksize_out, blocks_out); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+int host_set_attr(const char *path[], struct externfs_iattr *attrs) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ unsigned long time; -+ int err = 0, ma; -+ -+ if(append && (attrs->ia_valid & EXTERNFS_ATTR_SIZE)) -+ return(-EPERM); -+ -+ err = -ENOMEM; -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ if(attrs->ia_valid & EXTERNFS_ATTR_MODE){ -+ err = os_set_file_perms(file, attrs->ia_mode); -+ if(err < 0) -+ goto out; -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_UID){ -+ err = os_set_file_owner(file, attrs->ia_uid, -1); -+ if(err < 0) -+ goto out; -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_GID){ -+ err = os_set_file_owner(file, -1, attrs->ia_gid); -+ if(err < 0) -+ goto out; -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_SIZE){ -+ err = os_truncate_file(file, attrs->ia_size); -+ if(err < 0) -+ goto out; -+ } -+ ma = EXTERNFS_ATTR_ATIME_SET | EXTERNFS_ATTR_MTIME_SET; -+ if((attrs->ia_valid & ma) == ma){ -+ err = os_set_file_time(file, attrs->ia_atime, attrs->ia_mtime); -+ if(err) -+ goto out; -+ } -+ else { -+ if(attrs->ia_valid & EXTERNFS_ATTR_ATIME_SET){ -+ err = do_stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, &time, -+ NULL, NULL, NULL); -+ if(err != 0) -+ goto out; -+ -+ err = os_set_file_time(file, attrs->ia_atime, time); -+ if(err) -+ goto out; -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_MTIME_SET){ -+ err = do_stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, &time, NULL, -+ NULL, NULL, NULL); -+ if(err != 0) -+ goto out; -+ -+ err = os_set_file_time(file, time, attrs->ia_mtime); -+ if(err) -+ goto out; -+ } -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_CTIME) ; -+ if(attrs->ia_valid & (EXTERNFS_ATTR_ATIME | EXTERNFS_ATTR_MTIME)){ -+ err = do_stat_file(file, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, &attrs->ia_atime, -+ &attrs->ia_mtime, NULL, NULL, NULL); -+ if(err != 0) -+ goto out; -+ } -+ -+ err = 0; -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+int host_make_symlink(const char *from[], const char *to) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ file = get_path(from, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_make_symlink(to, file); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+int host_unlink_file(const char *path[]) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ if(append) -+ return(-EPERM); -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_remove_file(file); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+int host_make_dir(const char *path[], int mode) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_make_dir(file, mode); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+int host_remove_dir(const char *path[]) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_remove_dir(file); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+int host_link_file(const char *to[], const char *from[]) -+{ -+ char from_tmp[HOSTFS_BUFSIZE], *f, to_tmp[HOSTFS_BUFSIZE], *t; -+ int err = -ENOMEM; -+ -+ f = get_path(from, from_tmp, sizeof(from_tmp)); -+ t = get_path(to, to_tmp, sizeof(to_tmp)); -+ if((f == NULL) || (t == NULL)) -+ goto out; -+ -+ err = os_link_file(t, f); -+ out: -+ free_path(f, from_tmp); -+ free_path(t, to_tmp); -+ return(err); -+} -+ -+int host_read_link(const char *path[], char *buf, int size) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int n = -ENOMEM; -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ n = os_read_symlink(file, buf, size); -+ if(n < size) -+ buf[n] = '\0'; -+ out: -+ free_path(file, tmp); -+ return(n); -+} -+ -+int host_rename_file(const char *from[], const char *to[]) -+{ -+ char from_tmp[HOSTFS_BUFSIZE], *f, to_tmp[HOSTFS_BUFSIZE], *t; -+ int err = -ENOMEM; -+ -+ f = get_path(from, from_tmp, sizeof(from_tmp)); -+ t = get_path(to, to_tmp, sizeof(to_tmp)); -+ if((f == NULL) || (t == NULL)) -+ goto out; -+ -+ err = os_move_file(f, t); -+ out: -+ free_path(f, from_tmp); -+ free_path(t, to_tmp); -+ return(err); -+} -+ -+int host_stat_fs(const char *path[], long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, void *fsid_out, -+ int fsid_size, long *namelen_out, long *spare_out) -+{ -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_stat_filesystem(file, bsize_out, blocks_out, bfree_out, -+ bavail_out, files_out, ffree_out, fsid_out, -+ fsid_size, namelen_out, spare_out); -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+char *generic_host_read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out, -+ void *mount) -+{ -+ return(host_read_dir(stream, pos, ino_out, len_out)); -+} -+ -+int generic_host_truncate_file(struct file_handle *fh, __u64 size, void *m) -+{ -+ return(truncate_file(fh, size)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/host_fs.c -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/host_fs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/host_fs.c 2005-05-03 22:28:14.273440320 +0300 -@@ -0,0 +1,465 @@ -+/* -+ * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/string.h" -+#include "linux/types.h" -+#include "linux/errno.h" -+#include "linux/slab.h" -+#include "linux/init.h" -+#include "linux/fs.h" -+#include "linux/stat.h" -+#include "hostfs.h" -+#include "kern.h" -+#include "init.h" -+#include "kern_util.h" -+#include "filehandle.h" -+#include "os.h" -+ -+/* Changed in hostfs_args before the kernel starts running */ -+static char *jail_dir = "/"; -+int append = 0; -+ -+static int __init hostfs_args(char *options, int *add) -+{ -+ char *ptr; -+ -+ ptr = strchr(options, ','); -+ if(ptr != NULL) -+ *ptr++ = '\0'; -+ if(*options != '\0') -+ jail_dir = options; -+ -+ options = ptr; -+ while(options){ -+ ptr = strchr(options, ','); -+ if(ptr != NULL) -+ *ptr++ = '\0'; -+ if(*options != '\0'){ -+ if(!strcmp(options, "append")) -+ append = 1; -+ else printf("hostfs_args - unsupported option - %s\n", -+ options); -+ } -+ options = ptr; -+ } -+ return(0); -+} -+ -+__uml_setup("hostfs=", hostfs_args, -+"hostfs=<root dir>,<flags>,...\n" -+" This is used to set hostfs parameters. The root directory argument\n" -+" is used to confine all hostfs mounts to within the specified directory\n" -+" tree on the host. If this isn't specified, then a user inside UML can\n" -+" mount anything on the host that's accessible to the user that's running\n" -+" it.\n" -+" The only flag currently supported is 'append', which specifies that all\n" -+" files opened by hostfs will be opened in append mode.\n\n" -+); -+ -+struct hostfs_data { -+ struct externfs_data ext; -+ char *mount; -+}; -+ -+struct hostfs_file { -+ struct externfs_inode ext; -+ struct file_handle fh; -+}; -+ -+static int hostfs_access_file(char *file, int r, int w, int x, int uid, -+ int gid, struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ char tmp[HOSTFS_BUFSIZE]; -+ int err, mode = 0; -+ -+ if(r) mode = OS_ACC_R_OK; -+ if(w) mode |= OS_ACC_W_OK; -+ if(x) mode |= OS_ACC_X_OK; -+ -+ err = -ENOMEM; -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_access(file, mode); -+ free_path(file, tmp); -+ out: -+ return(err); -+} -+ -+static int hostfs_make_node(const char *file, int mode, int uid, int gid, -+ int type, int major, int minor, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ char tmp[HOSTFS_BUFSIZE]; -+ int err = -ENOMEM; -+ -+ file = get_path(path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ /* XXX Pass type in an OS-independent way */ -+ mode |= type; -+ -+ err = os_make_dev(file, mode, major, minor); -+ free_path(file, tmp); -+ out: -+ return(err); -+} -+ -+static int hostfs_stat_file(const char *file, struct externfs_data *ed, -+ dev_t *dev_out, unsigned long long *inode_out, -+ int *mode_out, int *nlink_out, int *uid_out, -+ int *gid_out, unsigned long long *size_out, -+ unsigned long *atime_out, unsigned long *mtime_out, -+ unsigned long *ctime_out, int *blksize_out, -+ unsigned long long *blocks_out) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ /* XXX Why pretend everything is owned by root? */ -+ *uid_out = 0; -+ *gid_out = 0; -+ return(host_stat_file(path, dev_out, inode_out, mode_out, nlink_out, -+ NULL, NULL, size_out, atime_out, mtime_out, -+ ctime_out, blksize_out, blocks_out)); -+} -+ -+static int hostfs_file_type(const char *file, int *rdev, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_file_type(path, rdev)); -+} -+ -+static char *hostfs_name(struct inode *inode) -+{ -+ struct externfs_data *ed = inode_externfs_info(inode); -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ -+ return(inode_name_prefix(inode, mount)); -+} -+ -+static struct externfs_inode *hostfs_init_file(struct externfs_data *ed) -+{ -+ struct hostfs_file *hf; -+ -+ hf = kmalloc(sizeof(*hf), GFP_KERNEL); -+ if(hf == NULL) -+ return(NULL); -+ -+ hf->fh.fd = -1; -+ return(&hf->ext); -+} -+ -+static int hostfs_open_file(struct externfs_inode *ext, char *file, -+ int uid, int gid, struct inode *inode, -+ struct externfs_data *ed) -+{ -+ struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext); -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ int err; -+ -+ err = host_open_file(path, 1, 1, &hf->fh); -+ if(err == -EISDIR) -+ goto out; -+ -+ if(err == -EACCES) -+ err = host_open_file(path, 1, 0, &hf->fh); -+ -+ if(err) -+ goto out; -+ -+ is_reclaimable(&hf->fh, hostfs_name, inode); -+ out: -+ return(err); -+} -+ -+static void *hostfs_open_dir(char *file, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_open_dir(path)); -+} -+ -+static void hostfs_close_dir(void *stream, struct externfs_data *ed) -+{ -+ os_close_dir(stream); -+} -+ -+static char *hostfs_read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ -+ return(generic_host_read_dir(stream, pos, ino_out, len_out, mount)); -+} -+ -+static int hostfs_read_file(struct externfs_inode *ext, -+ unsigned long long offset, char *buf, int len, -+ int ignore_start, int ignore_end, -+ void (*completion)(char *, int, void *), void *arg, -+ struct externfs_data *ed) -+{ -+ struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext); -+ int err = 0; -+ -+ if(ignore_start != 0){ -+ err = read_file(&hf->fh, offset, buf, ignore_start); -+ if(err < 0) -+ goto out; -+ } -+ -+ if(ignore_end != len) -+ err = read_file(&hf->fh, offset + ignore_end, buf + ignore_end, -+ len - ignore_end); -+ -+ out: -+ -+ (*completion)(buf, err, arg); -+ if (err > 0) -+ err = 0; -+ return(err); -+} -+ -+static int hostfs_write_file(struct externfs_inode *ext, -+ unsigned long long offset, const char *buf, -+ int start, int len, -+ void (*completion)(char *, int, void *), -+ void *arg, struct externfs_data *ed) -+{ -+ struct file_handle *fh; -+ int err; -+ -+ fh = &container_of(ext, struct hostfs_file, ext)->fh; -+ err = write_file(fh, offset + start, buf + start, len); -+ -+ (*completion)((char *) buf, err, arg); -+ if (err > 0) -+ err = 0; -+ -+ return(err); -+} -+ -+static int hostfs_create_file(struct externfs_inode *ext, char *file, int mode, -+ int uid, int gid, struct inode *inode, -+ struct externfs_data *ed) -+{ -+ struct hostfs_file *hf = container_of(ext, struct hostfs_file, -+ ext); -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ int err = -ENOMEM; -+ -+ err = host_create_file(path, mode, &hf->fh); -+ if(err) -+ goto out; -+ -+ is_reclaimable(&hf->fh, hostfs_name, inode); -+ out: -+ return(err); -+} -+ -+static int hostfs_set_attr(const char *file, struct externfs_iattr *attrs, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_set_attr(path, attrs)); -+} -+ -+static int hostfs_make_symlink(const char *from, const char *to, int uid, -+ int gid, struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, from, NULL }; -+ -+ return(host_make_symlink(path, to)); -+} -+ -+static int hostfs_link_file(const char *to, const char *from, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *to_path[] = { jail_dir, mount, to, NULL }; -+ const char *from_path[] = { jail_dir, mount, from, NULL }; -+ -+ return(host_link_file(to_path, from_path)); -+} -+ -+static int hostfs_unlink_file(const char *file, struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_unlink_file(path)); -+} -+ -+static int hostfs_make_dir(const char *file, int mode, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_make_dir(path, mode)); -+} -+ -+static int hostfs_remove_dir(const char *file, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_remove_dir(path)); -+} -+ -+static int hostfs_read_link(char *file, int uid, int gid, char *buf, int size, -+ struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, file, NULL }; -+ -+ return(host_read_link(path, buf, size)); -+} -+ -+static int hostfs_rename_file(char *from, char *to, struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *to_path[] = { jail_dir, mount, to, NULL }; -+ const char *from_path[] = { jail_dir, mount, from, NULL }; -+ -+ return(host_rename_file(from_path, to_path)); -+} -+ -+static int hostfs_stat_fs(long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, -+ void *fsid_out, int fsid_size, long *namelen_out, -+ long *spare_out, struct externfs_data *ed) -+{ -+ char *mount = container_of(ed, struct hostfs_data, ext)->mount; -+ const char *path[] = { jail_dir, mount, NULL }; -+ -+ return(host_stat_fs(path, bsize_out, blocks_out, bfree_out, bavail_out, -+ files_out, ffree_out, fsid_out, fsid_size, -+ namelen_out, spare_out)); -+} -+ -+static void hostfs_close_file(struct externfs_inode *ext, -+ unsigned long long size) -+{ -+ struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext); -+ -+ if(hf->fh.fd == -1) -+ return; -+ -+ truncate_file(&hf->fh, size); -+ close_file(&hf->fh); -+} -+ -+static int hostfs_truncate_file(struct externfs_inode *ext, __u64 size, -+ struct externfs_data *ed) -+{ -+ struct hostfs_file *hf = container_of(ext, struct hostfs_file, ext); -+ -+ return(truncate_file(&hf->fh, size)); -+} -+ -+static struct externfs_file_ops hostfs_file_ops = { -+ .stat_file = hostfs_stat_file, -+ .file_type = hostfs_file_type, -+ .access_file = hostfs_access_file, -+ .open_file = hostfs_open_file, -+ .open_dir = hostfs_open_dir, -+ .read_dir = hostfs_read_dir, -+ .read_file = hostfs_read_file, -+ .write_file = hostfs_write_file, -+ .map_file_page = NULL, -+ .close_file = hostfs_close_file, -+ .close_dir = hostfs_close_dir, -+ .invisible = NULL, -+ .create_file = hostfs_create_file, -+ .set_attr = hostfs_set_attr, -+ .make_symlink = hostfs_make_symlink, -+ .unlink_file = hostfs_unlink_file, -+ .make_dir = hostfs_make_dir, -+ .remove_dir = hostfs_remove_dir, -+ .make_node = hostfs_make_node, -+ .link_file = hostfs_link_file, -+ .read_link = hostfs_read_link, -+ .rename_file = hostfs_rename_file, -+ .statfs = hostfs_stat_fs, -+ .truncate_file = hostfs_truncate_file -+}; -+ -+static struct externfs_data *mount_fs(char *mount_arg) -+{ -+ struct hostfs_data *hd; -+ int err = -ENOMEM; -+ -+ hd = kmalloc(sizeof(*hd), GFP_KERNEL); -+ if(hd == NULL) -+ goto out; -+ -+ hd->mount = host_root_filename(mount_arg); -+ if(hd->mount == NULL) -+ goto out_free; -+ -+ init_externfs(&hd->ext, &hostfs_file_ops); -+ -+ return(&hd->ext); -+ out_free: -+ kfree(hd); -+ out: -+ return(ERR_PTR(err)); -+} -+ -+static struct externfs_mount_ops hostfs_mount_ops = { -+ .init_file = hostfs_init_file, -+ .mount = mount_fs, -+}; -+ -+static int __init init_hostfs(void) -+{ -+ return(register_externfs("hostfs", &hostfs_mount_ops)); -+} -+ -+static void __exit exit_hostfs(void) -+{ -+ unregister_externfs("hostfs"); -+} -+ -+__initcall(init_hostfs); -+__exitcall(exit_hostfs); -+ -+#if 0 -+module_init(init_hostfs) -+module_exit(exit_hostfs) -+MODULE_LICENSE("GPL"); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/hostfs.h -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/hostfs.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/hostfs.h 2005-05-03 23:46:13.801043992 +0300 -@@ -0,0 +1,200 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_FS_HOSTFS -+#define __UM_FS_HOSTFS -+ -+#include "linux/fs.h" -+#include "linux/blkdev.h" -+#include "filehandle.h" -+#include "os.h" -+ -+/* These are exactly the same definitions as in fs.h, but the names are -+ * changed so that this file can be included in both kernel and user files. -+ */ -+ -+#define EXTERNFS_ATTR_MODE 1 -+#define EXTERNFS_ATTR_UID 2 -+#define EXTERNFS_ATTR_GID 4 -+#define EXTERNFS_ATTR_SIZE 8 -+#define EXTERNFS_ATTR_ATIME 16 -+#define EXTERNFS_ATTR_MTIME 32 -+#define EXTERNFS_ATTR_CTIME 64 -+#define EXTERNFS_ATTR_ATIME_SET 128 -+#define EXTERNFS_ATTR_MTIME_SET 256 -+#define EXTERNFS_ATTR_FORCE 512 /* Not a change, but a change it */ -+#define EXTERNFS_ATTR_ATTR_FLAG 1024 -+ -+/** -+ * container_of - cast a member of a structure out to the containing structure -+ * -+ * @ptr: the pointer to the member. -+ * @type: the type of the container struct this is embedded in. -+ * @member: the name of the member within the struct. -+ * -+ */ -+#define container_of(ptr, type, member) ({ \ -+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ -+ (type *)( (char *)__mptr - offsetof(type,member) );}) -+ -+struct externfs_iattr { -+ unsigned int ia_valid; -+ mode_t ia_mode; -+ uid_t ia_uid; -+ gid_t ia_gid; -+ loff_t ia_size; -+ time_t ia_atime; -+ time_t ia_mtime; -+ time_t ia_ctime; -+ unsigned int ia_attr_flags; -+}; -+ -+struct externfs_data { -+ struct externfs_file_ops *file_ops; -+ struct externfs_mount_ops *mount_ops; -+}; -+ -+struct externfs_inode { -+ struct externfs_file_ops *ops; -+}; -+ -+struct externfs_mount_ops { -+ struct externfs_data *(*mount)(char *mount_arg); -+ struct externfs_inode *(*init_file)(struct externfs_data *ed); -+}; -+ -+struct externfs_file_ops { -+ int (*stat_file)(const char *path, struct externfs_data *ed, -+ dev_t *dev_out, unsigned long long *inode_out, -+ int *mode_out, int *nlink_out, int *uid_out, -+ int *gid_out, unsigned long long *size_out, -+ unsigned long *atime_out, unsigned long *mtime_out, -+ unsigned long *ctime_out, int *blksize_out, -+ unsigned long long *blocks_out); -+ int (*file_type)(const char *path, int *rdev, -+ struct externfs_data *ed); -+ int (*access_file)(char *path, int r, int w, int x, int uid, int gid, -+ struct externfs_data *ed); -+ int (*open_file)(struct externfs_inode *ext, char *file, -+ int uid, int gid, struct inode *inode, -+ struct externfs_data *ed); -+ void (*close_file)(struct externfs_inode *ext, -+ unsigned long long size); -+ void *(*open_dir)(char *path, int uid, int gid, -+ struct externfs_data *ed); -+ char *(*read_dir)(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out, -+ struct externfs_data *ed); -+ int (*read_file)(struct externfs_inode *ext, -+ unsigned long long offset, char *buf, int len, -+ int ignore_start, int ignore_end, -+ void (*completion)(char *, int, void *), void *arg, -+ struct externfs_data *ed); -+ int (*write_file)(struct externfs_inode *ext, -+ unsigned long long offset, const char *buf, -+ int start, int len, -+ void (*completion)(char *, int, void *), void *arg, -+ struct externfs_data *ed); -+ int (*map_file_page)(struct externfs_inode *ext, -+ unsigned long long offset, char *buf, int w, -+ struct externfs_data *ed); -+ void (*close_dir)(void *stream, struct externfs_data *ed); -+ void (*invisible)(struct externfs_inode *ext); -+ int (*create_file)(struct externfs_inode *ext, char *path, -+ int mode, int uid, int gid, struct inode *inode, -+ struct externfs_data *ed); -+ int (*set_attr)(const char *path, struct externfs_iattr *attrs, -+ struct externfs_data *ed); -+ int (*make_symlink)(const char *from, const char *to, int uid, int gid, -+ struct externfs_data *ed); -+ int (*unlink_file)(const char *path, struct externfs_data *ed); -+ int (*make_dir)(const char *path, int mode, int uid, int gid, -+ struct externfs_data *ed); -+ int (*remove_dir)(const char *path, int uid, int gid, -+ struct externfs_data *ed); -+ int (*make_node)(const char *path, int mode, int uid, int gid, -+ int type, int maj, int min, struct externfs_data *ed); -+ int (*link_file)(const char *to, const char *from, int uid, int gid, -+ struct externfs_data *ed); -+ int (*read_link)(char *path, int uid, int gid, char *buf, int size, -+ struct externfs_data *ed); -+ int (*rename_file)(char *from, char *to, struct externfs_data *ed); -+ int (*statfs)(long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, -+ void *fsid_out, int fsid_size, long *namelen_out, -+ long *spare_out, struct externfs_data *ed); -+ int (*truncate_file)(struct externfs_inode *ext, __u64 size, -+ struct externfs_data *ed); -+}; -+ -+#define HOSTFS_BUFSIZE 64 -+ -+extern int register_externfs(char *name, struct externfs_mount_ops *mount_ops); -+extern void unregister_externfs(char *name); -+extern void init_externfs(struct externfs_data *ed, -+ struct externfs_file_ops *ops); -+struct externfs_data *inode_externfs_info(struct inode *inode); -+ -+extern char *generic_root_filename(char *mount_arg); -+extern void host_close_file(void *stream); -+extern int host_read_file(int fd, unsigned long long offset, char *buf, -+ int len); -+extern int host_open_file(const char *path[], int r, int w, -+ struct file_handle *fh); -+extern void *host_open_dir(const char *path[]); -+extern char *host_read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out); -+extern int host_file_type(const char *path[], int *rdev); -+extern char *host_root_filename(char *mount_arg); -+extern char *get_path(const char *path[], char *buf, int size); -+extern void free_path(const char *buf, char *tmp); -+extern int host_create_file(const char *path[], int mode, -+ struct file_handle *fh); -+extern int host_set_attr(const char *path[], struct externfs_iattr *attrs); -+extern int host_make_symlink(const char *from[], const char *to); -+extern int host_unlink_file(const char *path[]); -+extern int host_make_dir(const char *path[], int mode); -+extern int host_remove_dir(const char *path[]); -+extern int host_link_file(const char *to[], const char *from[]); -+extern int host_read_link(const char *path[], char *buf, int size); -+extern int host_rename_file(const char *from[], const char *to[]); -+extern int host_stat_fs(const char *path[], long *bsize_out, -+ long long *blocks_out, long long *bfree_out, -+ long long *bavail_out, long long *files_out, -+ long long *ffree_out, void *fsid_out, int fsid_size, -+ long *namelen_out, long *spare_out); -+extern int host_stat_file(const char *path[], dev_t *dev_out, -+ unsigned long long *inode_out, int *mode_out, -+ int *nlink_out, int *uid_out, int *gid_out, -+ unsigned long long *size_out, -+ unsigned long *atime_out, unsigned long *mtime_out, -+ unsigned long *ctime_out, int *blksize_out, -+ unsigned long long *blocks_out); -+ -+extern char *generic_host_read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out, -+ void *mount); -+extern int generic_host_read_file(int fd, unsigned long long offset, char *buf, -+ int len, void *mount); -+extern void generic_host_close_file(void *stream, unsigned long long size, -+ void *mount); -+extern int generic_host_truncate_file(struct file_handle *fh, __u64 size, -+ void *m); -+ -+extern char *inode_name_prefix(struct inode *inode, char *prefix); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/humfs.c -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/humfs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/humfs.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,1024 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/list.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/stat.h> -+#include <linux/tqueue.h> -+#include <linux/types.h> -+#include <linux/errno.h> -+#include <linux/string.h> -+#include <linux/kdev_t.h> -+#include <asm/irq.h> -+#include "hostfs.h" -+#include "mem.h" -+#include "os.h" -+#include "mode.h" -+#include "aio.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+#include "filehandle.h" -+#include "metadata.h" -+ -+#define HUMFS_VERSION 2 -+ -+static int humfs_stat_file(const char *path, struct externfs_data *ed, -+ dev_t *dev_out, unsigned long long *inode_out, -+ int *mode_out, int *nlink_out, int *uid_out, -+ int *gid_out, unsigned long long *size_out, -+ unsigned long *atime_out, unsigned long *mtime_out, -+ unsigned long *ctime_out, int *blksize_out, -+ unsigned long long *blocks_out) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int err, mode, perms, major, minor; -+ char type; -+ -+ err = host_stat_file(data_path, dev_out, inode_out, mode_out, -+ nlink_out, NULL, NULL, size_out, atime_out, -+ mtime_out, ctime_out, blksize_out, blocks_out); -+ if(err) -+ return(err); -+ -+ err = (*mount->meta->ownerships)(path, &perms, uid_out, gid_out, -+ &type, &major, &minor, mount); -+ if(err) -+ return(err); -+ -+ *mode_out = (*mode_out & ~S_IRWXUGO) | perms; -+ -+ mode = 0; -+ switch(type){ -+ case 'c': -+ mode = S_IFCHR; -+ break; -+ case 'b': -+ mode = S_IFBLK; -+ break; -+ case 's': -+ mode = S_IFSOCK; -+ break; -+ default: -+ break; -+ } -+ -+ if(mode != 0) -+ *mode_out = (*mode_out & ~S_IFMT) | mode; -+ -+ return(0); -+} -+ -+static int meta_type(const char *path, int *dev_out, void *m) -+{ -+ struct humfs *mount = m; -+ int err, type, maj, min; -+ char c; -+ -+ err = (*mount->meta->ownerships)(path, NULL, NULL, NULL, &c, &maj, -+ &min, mount); -+ if(err) -+ return(err); -+ -+ if(c == 0) -+ return(0); -+ -+ if(dev_out) -+ *dev_out = MKDEV(maj, min); -+ -+ switch(c){ -+ case 'c': -+ type = OS_TYPE_CHARDEV; -+ break; -+ case 'b': -+ type = OS_TYPE_BLOCKDEV; -+ break; -+ case 'p': -+ type = OS_TYPE_FIFO; -+ break; -+ case 's': -+ type = OS_TYPE_SOCK; -+ break; -+ default: -+ type = -EINVAL; -+ break; -+ } -+ -+ return(type); -+} -+ -+static int humfs_file_type(const char *path, int *dev_out, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int type; -+ -+ type = meta_type(path, dev_out, mount); -+ if(type != 0) -+ return(type); -+ -+ return(host_file_type(data_path, dev_out)); -+} -+ -+static char *humfs_data_name(struct inode *inode) -+{ -+ struct externfs_data *ed = inode_externfs_info(inode); -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ -+ return(inode_name_prefix(inode, mount->data)); -+} -+ -+static struct externfs_inode *humfs_init_file(struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ struct humfs_file *hf; -+ -+ hf = (*mount->meta->init_file)(); -+ if(IS_ERR(hf)) -+ return((struct externfs_inode *) hf); -+ -+ hf->data.fd = -1; -+ return(&hf->ext); -+} -+ -+static int humfs_open_file(struct externfs_inode *ext, char *path, int uid, -+ int gid, struct inode *inode, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ struct openflags flags; -+ char tmp[HOSTFS_BUFSIZE], *file; -+ int err = -ENOMEM; -+ -+ file = get_path(data_path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ flags = of_rdwr(OPENFLAGS()); -+ if(mount->direct) -+ flags = of_direct(flags); -+ -+ if(path == NULL) -+ path = ""; -+ err = (*mount->meta->open_file)(hf, path, inode, mount); -+ if(err) -+ goto out_free; -+ -+ err = open_filehandle(file, flags, 0, &hf->data); -+ if(err == -EISDIR) -+ goto out; -+ else if(err == -EPERM){ -+ flags = of_set_rw(flags, 1, 0); -+ err = open_filehandle(file, flags, 0, &hf->data); -+ } -+ -+ if(err) -+ goto out_close; -+ -+ hf->mount = mount; -+ is_reclaimable(&hf->data, humfs_data_name, inode); -+ -+ out_free: -+ free_path(file, tmp); -+ out: -+ return(err); -+ -+ out_close: -+ (*mount->meta->close_file)(hf); -+ goto out_free; -+} -+ -+static void *humfs_open_dir(char *path, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ -+ return(host_open_dir(data_path)); -+} -+ -+static void humfs_close_dir(void *stream, struct externfs_data *ed) -+{ -+ os_close_dir(stream); -+} -+ -+static char *humfs_read_dir(void *stream, unsigned long long *pos, -+ unsigned long long *ino_out, int *len_out, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ -+ return(generic_host_read_dir(stream, pos, ino_out, len_out, mount)); -+} -+ -+LIST_HEAD(humfs_replies); -+ -+struct humfs_aio { -+ struct aio_context aio; -+ struct list_head list; -+ void (*completion)(char *, int, void *); -+ char *buf; -+ int real_len; -+ int err; -+ void *data; -+}; -+ -+static int humfs_reply_fd = -1; -+ -+struct humfs_aio last_task_aio, last_intr_aio; -+struct humfs_aio *last_task_aio_ptr, *last_intr_aio_ptr; -+ -+void humfs_task_proc(void *unused) -+{ -+ struct humfs_aio *aio; -+ unsigned long flags; -+ -+ while(!list_empty(&humfs_replies)){ -+ local_irq_save(flags); -+ aio = list_entry(humfs_replies.next, struct humfs_aio, list); -+ -+ last_task_aio = *aio; -+ last_task_aio_ptr = aio; -+ -+ list_del(&aio->list); -+ local_irq_restore(flags); -+ -+ if(aio->err >= 0) -+ aio->err = aio->real_len; -+ (*aio->completion)(aio->buf, aio->err, aio->data); -+ kfree(aio); -+ } -+} -+ -+struct tq_struct humfs_task = { -+ .routine = humfs_task_proc, -+ .data = NULL -+}; -+ -+static void humfs_interrupt(int irq, void *dev_id, struct pt_regs *unused) -+{ -+ struct aio_thread_reply reply; -+ struct humfs_aio *aio; -+ int err, fd = (int) dev_id; -+ -+ while(1){ -+ err = os_read_file(fd, &reply, sizeof(reply)); -+ if(err < 0){ -+ if(err == -EAGAIN) -+ break; -+ printk("humfs_interrupt - read returned err %d\n", -+ -err); -+ return; -+ } -+ aio = reply.data; -+ aio->err = reply.err; -+ list_add(&aio->list, &humfs_replies); -+ last_intr_aio = *aio; -+ last_intr_aio_ptr = aio; -+ } -+ -+ if(!list_empty(&humfs_replies)) -+ schedule_task(&humfs_task); -+ reactivate_fd(fd, HUMFS_IRQ); -+} -+ -+static int init_humfs_aio(void) -+{ -+ int fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err){ -+ printk("init_humfs_aio - pipe failed, err = %d\n", -err); -+ goto out; -+ } -+ -+ err = um_request_irq(HUMFS_IRQ, fds[0], IRQ_READ, humfs_interrupt, -+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "humfs", -+ (void *) fds[0]); -+ if(err){ -+ printk("init_humfs_aio - : um_request_irq failed, err = %d\n", -+ err); -+ goto out_close; -+ } -+ -+ humfs_reply_fd = fds[1]; -+ goto out; -+ -+ out_close: -+ os_close_file(fds[0]); -+ os_close_file(fds[1]); -+ out: -+ return(0); -+} -+ -+__initcall(init_humfs_aio); -+ -+static int humfs_aio(enum aio_type type, int fd, unsigned long long offset, -+ char *buf, int len, int real_len, -+ void (*completion)(char *, int, void *), void *arg) -+{ -+ struct humfs_aio *aio; -+ int err = -ENOMEM; -+ -+ aio = kmalloc(sizeof(*aio), GFP_KERNEL); -+ if(aio == NULL) -+ goto out; -+ *aio = ((struct humfs_aio) { .aio = INIT_AIO_CONTEXT, -+ .list = LIST_HEAD_INIT(aio->list), -+ .completion= completion, -+ .buf = buf, -+ .err = 0, -+ .real_len = real_len, -+ .data = arg }); -+ -+ err = submit_aio(type, fd, buf, len, offset, humfs_reply_fd, aio); -+ if(err) -+ (*completion)(buf, err, arg); -+ -+ out: -+ return(err); -+} -+ -+static int humfs_read_file(struct externfs_inode *ext, -+ unsigned long long offset, char *buf, int len, -+ int ignore_start, int ignore_end, -+ void (*completion)(char *, int, void *), void *arg, -+ struct externfs_data *ed) -+{ -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ int fd = filehandle_fd(&hf->data); -+ -+ if(fd < 0){ -+ (*completion)(buf, fd, arg); -+ return(fd); -+ } -+ -+ return(humfs_aio(AIO_READ, fd, offset, buf, len, len, completion, -+ arg)); -+} -+ -+static int humfs_write_file(struct externfs_inode *ext, -+ unsigned long long offset, const char *buf, -+ int start, int len, -+ void (*completion)(char *, int, void *), void *arg, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ int err, orig_len = len, fd = filehandle_fd(&hf->data); -+ -+ if(fd < 0){ -+ (*completion)((char *) buf, fd, arg); -+ return(fd); -+ } -+ -+ if(mount->direct) -+ len = PAGE_SIZE; -+ else { -+ offset += start; -+ buf += start; -+ } -+ -+ err = humfs_aio(AIO_WRITE, fd, offset, (char *) buf, len, orig_len, -+ completion, arg); -+ -+ if(err < 0) -+ return(err); -+ -+ if(mount->direct) -+ err = orig_len; -+ -+ return(err); -+} -+ -+static int humfs_map_file_page(struct externfs_inode *ext, -+ unsigned long long offset, char *buf, int w, -+ struct externfs_data *ed) -+{ -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ unsigned long long size, need; -+ int err, fd = filehandle_fd(&hf->data); -+ -+ if(fd < 0) -+ return(fd); -+ -+ err = os_fd_size(fd, &size); -+ if(err) -+ return(err); -+ -+ need = offset + PAGE_SIZE; -+ if(size < need){ -+ err = os_truncate_fd(fd, need); -+ if(err) -+ return(err); -+ } -+ -+ return(physmem_subst_mapping(buf, fd, offset, w)); -+} -+ -+static void humfs_close_file(struct externfs_inode *ext, -+ unsigned long long size) -+{ -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ int fd; -+ -+ if(hf->data.fd == -1) -+ return; -+ -+ fd = filehandle_fd(&hf->data); -+ physmem_forget_descriptor(fd); -+ truncate_file(&hf->data, size); -+ close_file(&hf->data); -+ -+ (*hf->mount->meta->close_file)(hf); -+} -+ -+/* XXX Assumes that you can't make a normal file */ -+ -+static int humfs_make_node(const char *path, int mode, int uid, int gid, -+ int type, int major, int minor, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ struct file_handle fh; -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int err; -+ char t; -+ -+ err = host_create_file(data_path, S_IRWXUGO, &fh); -+ if(err) -+ goto out; -+ -+ close_file(&fh); -+ -+ switch(type){ -+ case S_IFCHR: -+ t = 'c'; -+ break; -+ case S_IFBLK: -+ t = 'b'; -+ break; -+ case S_IFIFO: -+ t = 'p'; -+ break; -+ case S_IFSOCK: -+ t = 's'; -+ break; -+ default: -+ err = -EINVAL; -+ printk("humfs_make_node - bad node type : %d\n", type); -+ goto out_rm; -+ } -+ -+ err = (*mount->meta->make_node)(path, mode, uid, gid, t, major, minor, -+ mount); -+ if(err) -+ goto out_rm; -+ -+ out: -+ return(err); -+ -+ out_rm: -+ host_unlink_file(data_path); -+ goto out; -+} -+ -+static int humfs_create_file(struct externfs_inode *ext, char *path, int mode, -+ int uid, int gid, struct inode *inode, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int err; -+ -+ err = (*mount->meta->create_file)(hf, path, mode, uid, gid, inode, -+ mount); -+ if(err) -+ goto out; -+ -+ err = host_create_file(data_path, S_IRWXUGO, &hf->data); -+ if(err) -+ goto out_rm; -+ -+ -+ is_reclaimable(&hf->data, humfs_data_name, inode); -+ -+ return(0); -+ -+ out_rm: -+ (*mount->meta->remove_file)(path, mount); -+ (*mount->meta->close_file)(hf); -+ out: -+ return(err); -+} -+ -+static int humfs_set_attr(const char *path, struct externfs_iattr *attrs, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int (*chown)(const char *, int, int, int, struct humfs *); -+ int err; -+ -+ chown = mount->meta->change_ownerships; -+ if(attrs->ia_valid & EXTERNFS_ATTR_MODE){ -+ err = (*chown)(path, attrs->ia_mode, -1, -1, mount); -+ if(err) -+ return(err); -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_UID){ -+ err = (*chown)(path, -1, attrs->ia_uid, -1, mount); -+ if(err) -+ return(err); -+ } -+ if(attrs->ia_valid & EXTERNFS_ATTR_GID){ -+ err = (*chown)(path, -1, -1, attrs->ia_gid, mount); -+ if(err) -+ return(err); -+ } -+ -+ attrs->ia_valid &= ~(EXTERNFS_ATTR_MODE | EXTERNFS_ATTR_UID | -+ EXTERNFS_ATTR_GID); -+ -+ return(host_set_attr(data_path, attrs)); -+} -+ -+static int humfs_make_symlink(const char *from, const char *to, int uid, -+ int gid, struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ struct humfs_file *hf; -+ const char *data_path[3] = { mount->data, from, NULL }; -+ int err = -ENOMEM; -+ -+ hf = (*mount->meta->init_file)(); -+ if(hf == NULL) -+ goto out; -+ -+ err = (*mount->meta->create_file)(hf, from, S_IRWXUGO, uid, gid, NULL, -+ mount); -+ if(err) -+ goto out_close; -+ -+ err = host_make_symlink(data_path, to); -+ if(err) -+ (*mount->meta->remove_file)(from, mount); -+ -+ out_close: -+ (*mount->meta->close_file)(hf); -+ out: -+ return(err); -+} -+ -+static int humfs_link_file(const char *to, const char *from, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path_from[3] = { mount->data, from, NULL }; -+ const char *data_path_to[3] = { mount->data, to, NULL }; -+ int err; -+ -+ err = (*mount->meta->create_link)(to, from, mount); -+ if(err) -+ return(err); -+ -+ err = host_link_file(data_path_to, data_path_from); -+ if(err) -+ (*mount->meta->remove_file)(from, mount); -+ -+ return(err); -+} -+ -+static int humfs_unlink_file(const char *path, struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int err; -+ -+ err = (*mount->meta->remove_file)(path, mount); -+ if (err) -+ return err; -+ -+ (*mount->meta->remove_file)(path, mount); -+ return(host_unlink_file(data_path)); -+} -+ -+static void humfs_invisible(struct externfs_inode *ext) -+{ -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ struct humfs *mount = hf->mount; -+ -+ (*mount->meta->invisible)(hf); -+ not_reclaimable(&hf->data); -+} -+ -+static int humfs_make_dir(const char *path, int mode, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int err; -+ -+ err = (*mount->meta->create_dir)(path, mode, uid, gid, mount); -+ if(err) -+ return(err); -+ -+ err = host_make_dir(data_path, S_IRWXUGO); -+ if(err) -+ (*mount->meta->remove_dir)(path, mount); -+ -+ return(err); -+} -+ -+static int humfs_remove_dir(const char *path, int uid, int gid, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, path, NULL }; -+ int err; -+ -+ err = host_remove_dir(data_path); -+ if (err) -+ return err; -+ -+ (*mount->meta->remove_dir)(path, mount); -+ -+ return(err); -+} -+ -+static int humfs_read_link(char *file, int uid, int gid, char *buf, int size, -+ struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, file, NULL }; -+ -+ return(host_read_link(data_path, buf, size)); -+} -+ -+struct humfs *inode_humfs_info(struct inode *inode) -+{ -+ return(container_of(inode_externfs_info(inode), struct humfs, ext)); -+} -+ -+static int humfs_rename_file(char *from, char *to, struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path_from[3] = { mount->data, from, NULL }; -+ const char *data_path_to[3] = { mount->data, to, NULL }; -+ int err; -+ -+ err = (*mount->meta->rename_file)(from, to, mount); -+ if(err) -+ return(err); -+ -+ err = host_rename_file(data_path_from, data_path_to); -+ if(err) -+ (*mount->meta->rename_file)(to, from, mount); -+ -+ return(err); -+} -+ -+static int humfs_stat_fs(long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, -+ void *fsid_out, int fsid_size, long *namelen_out, -+ long *spare_out, struct externfs_data *ed) -+{ -+ struct humfs *mount = container_of(ed, struct humfs, ext); -+ const char *data_path[3] = { mount->data, NULL }; -+ int err; -+ -+ /* XXX Needs to maintain this info as metadata */ -+ err = host_stat_fs(data_path, bsize_out, blocks_out, bfree_out, -+ bavail_out, files_out, ffree_out, fsid_out, -+ fsid_size, namelen_out, spare_out); -+ if(err) -+ return(err); -+ -+ *blocks_out = mount->total / *bsize_out; -+ *bfree_out = (mount->total - mount->used) / *bsize_out; -+ *bavail_out = (mount->total - mount->used) / *bsize_out; -+ return(0); -+} -+ -+int humfs_truncate_file(struct externfs_inode *ext, __u64 size, -+ struct externfs_data *ed) -+{ -+ struct humfs_file *hf = container_of(ext, struct humfs_file, ext); -+ -+ return(truncate_file(&hf->data, size)); -+} -+ -+char *humfs_path(char *dir, char *file) -+{ -+ int need_slash, len = strlen(dir) + strlen(file); -+ char *new; -+ -+ need_slash = (dir[strlen(dir) - 1] != '/'); -+ if(need_slash) -+ len++; -+ -+ new = kmalloc(len + 1, GFP_KERNEL); -+ if(new == NULL) -+ return(NULL); -+ -+ strcpy(new, dir); -+ if(need_slash) -+ strcat(new, "/"); -+ strcat(new, file); -+ -+ return(new); -+} -+ -+DECLARE_MUTEX(meta_sem); -+struct list_head metas = LIST_HEAD_INIT(metas); -+ -+static struct humfs_meta_ops *find_meta(const char *name) -+{ -+ struct list_head *ele; -+ struct humfs_meta_ops *m; -+ -+ down(&meta_sem); -+ list_for_each(ele, &metas){ -+ m = list_entry(ele, struct humfs_meta_ops, list); -+ if(!strcmp(m->name, name)) -+ goto out; -+ } -+ m = NULL; -+ out: -+ up(&meta_sem); -+ return(m); -+} -+ -+void register_meta(struct humfs_meta_ops *ops) -+{ -+ down(&meta_sem); -+ list_add(&ops->list, &metas); -+ up(&meta_sem); -+} -+ -+void unregister_meta(struct humfs_meta_ops *ops) -+{ -+ down(&meta_sem); -+ list_del(&ops->list); -+ up(&meta_sem); -+} -+ -+static struct humfs *read_superblock(char *root) -+{ -+ struct humfs *mount; -+ struct humfs_meta_ops *meta = NULL; -+ struct file_handle *fh; -+ const char *path[] = { root, "superblock", NULL }; -+ u64 used, total; -+ char meta_buf[33], line[HOSTFS_BUFSIZE], *newline; -+ unsigned long long pos; -+ int version, i, n, err; -+ -+ fh = kmalloc(sizeof(*fh), GFP_KERNEL); -+ if(fh == NULL) -+ return(ERR_PTR(-ENOMEM)); -+ -+ err = host_open_file(path, 1, 0, fh); -+ if(err){ -+ printk("Failed to open %s/%s, errno = %d\n", path[0], -+ path[1], err); -+ return(ERR_PTR(err)); -+ } -+ -+ used = 0; -+ total = 0; -+ pos = 0; -+ i = 0; -+ while(1){ -+ n = read_file(fh, pos, &line[i], sizeof(line) - i - 1); -+ if((n == 0) && (i == 0)) -+ break; -+ if(n < 0) -+ return(ERR_PTR(n)); -+ -+ pos += n; -+ if(n > 0) -+ line[n + i] = '\0'; -+ -+ newline = strchr(line, '\n'); -+ if(newline == NULL){ -+ printk("read_superblock - line too long : '%s'\n", -+ line); -+ return(ERR_PTR(-EINVAL)); -+ } -+ newline++; -+ -+ if(sscanf(line, "version %d\n", &version) == 1){ -+ if(version != HUMFS_VERSION){ -+ printk("humfs version mismatch - want version " -+ "%d, got version %d.\n", HUMFS_VERSION, -+ version); -+ return(ERR_PTR(-EINVAL)); -+ } -+ } -+ else if(sscanf(line, "used %Lu\n", &used) == 1) ; -+ else if(sscanf(line, "total %Lu\n", &total) == 1) ; -+ else if(sscanf(line, "metadata %32s\n", meta_buf) == 1){ -+ meta = find_meta(meta_buf); -+ if(meta == NULL){ -+ printk("read_superblock - meta api \"%s\" not " -+ "registered\n", meta_buf); -+ return(ERR_PTR(-EINVAL)); -+ } -+ } -+ -+ else { -+ printk("read_superblock - bogus line : '%s'\n", line); -+ return(ERR_PTR(-EINVAL)); -+ } -+ -+ i = newline - line; -+ memmove(line, newline, sizeof(line) - i); -+ i = strlen(line); -+ } -+ -+ if(used == 0){ -+ printk("read_superblock - used not specified or set to " -+ "zero\n"); -+ return(ERR_PTR(-EINVAL)); -+ } -+ if(total == 0){ -+ printk("read_superblock - total not specified or set to " -+ "zero\n"); -+ return(ERR_PTR(-EINVAL)); -+ } -+ if(used > total){ -+ printk("read_superblock - used is greater than total\n"); -+ return(ERR_PTR(-EINVAL)); -+ } -+ -+ if(meta == NULL){ -+ meta = find_meta("shadow_fs"); -+ } -+ -+ if(meta == NULL){ -+ printk("read_superblock - valid meta api was not specified\n"); -+ return(ERR_PTR(-EINVAL)); -+ } -+ -+ mount = (*meta->init_mount)(root); -+ if(IS_ERR(mount)) -+ return(mount); -+ -+ *mount = ((struct humfs) { .total = total, -+ .used = used, -+ .meta = meta }); -+ return(mount); -+} -+ -+struct externfs_file_ops humfs_no_mmap_file_ops = { -+ .stat_file = humfs_stat_file, -+ .file_type = humfs_file_type, -+ .access_file = NULL, -+ .open_file = humfs_open_file, -+ .open_dir = humfs_open_dir, -+ .read_dir = humfs_read_dir, -+ .read_file = humfs_read_file, -+ .write_file = humfs_write_file, -+ .map_file_page = NULL, -+ .close_file = humfs_close_file, -+ .close_dir = humfs_close_dir, -+ .invisible = humfs_invisible, -+ .create_file = humfs_create_file, -+ .set_attr = humfs_set_attr, -+ .make_symlink = humfs_make_symlink, -+ .unlink_file = humfs_unlink_file, -+ .make_dir = humfs_make_dir, -+ .remove_dir = humfs_remove_dir, -+ .make_node = humfs_make_node, -+ .link_file = humfs_link_file, -+ .read_link = humfs_read_link, -+ .rename_file = humfs_rename_file, -+ .statfs = humfs_stat_fs, -+ .truncate_file = humfs_truncate_file -+}; -+ -+struct externfs_file_ops humfs_mmap_file_ops = { -+ .stat_file = humfs_stat_file, -+ .file_type = humfs_file_type, -+ .access_file = NULL, -+ .open_file = humfs_open_file, -+ .open_dir = humfs_open_dir, -+ .read_dir = humfs_read_dir, -+ .read_file = humfs_read_file, -+ .write_file = humfs_write_file, -+ .map_file_page = humfs_map_file_page, -+ .close_file = humfs_close_file, -+ .close_dir = humfs_close_dir, -+ .invisible = humfs_invisible, -+ .create_file = humfs_create_file, -+ .set_attr = humfs_set_attr, -+ .make_symlink = humfs_make_symlink, -+ .unlink_file = humfs_unlink_file, -+ .make_dir = humfs_make_dir, -+ .remove_dir = humfs_remove_dir, -+ .make_node = humfs_make_node, -+ .link_file = humfs_link_file, -+ .read_link = humfs_read_link, -+ .rename_file = humfs_rename_file, -+ .statfs = humfs_stat_fs, -+ .truncate_file = humfs_truncate_file -+}; -+ -+static struct externfs_data *mount_fs(char *mount_arg) -+{ -+ char *root, *data, *flags; -+ struct humfs *mount; -+ struct externfs_file_ops *file_ops; -+ int err, do_mmap = 0; -+ -+ if(mount_arg == NULL){ -+ printk("humfs - no host directory specified\n"); -+ return(NULL); -+ } -+ -+ flags = strchr((char *) mount_arg, ','); -+ if(flags != NULL){ -+ do { -+ *flags++ = '\0'; -+ -+ if(!strcmp(flags, "mmap")) -+ do_mmap = 1; -+ -+ flags = strchr(flags, ','); -+ } while(flags != NULL); -+ } -+ -+ err = -ENOMEM; -+ root = host_root_filename(mount_arg); -+ if(root == NULL) -+ goto err; -+ -+ mount = read_superblock(root); -+ if(IS_ERR(mount)){ -+ err = PTR_ERR(mount); -+ goto err_free_root; -+ } -+ -+ data = humfs_path(root, "data/"); -+ if(data == NULL) -+ goto err_free_mount; -+ -+ if(CHOOSE_MODE(do_mmap, 0)){ -+ printk("humfs doesn't support mmap in tt mode\n"); -+ do_mmap = 0; -+ } -+ -+ mount->data = data; -+ mount->mmap = do_mmap; -+ -+ file_ops = do_mmap ? &humfs_mmap_file_ops : &humfs_no_mmap_file_ops; -+ init_externfs(&mount->ext, file_ops); -+ -+ return(&mount->ext); -+ -+ err_free_mount: -+ kfree(mount); -+ err_free_root: -+ kfree(root); -+ err: -+ return(NULL); -+} -+ -+struct externfs_mount_ops humfs_mount_ops = { -+ .init_file = humfs_init_file, -+ .mount = mount_fs, -+}; -+ -+static int __init init_humfs(void) -+{ -+ return(register_externfs("humfs", &humfs_mount_ops)); -+} -+ -+static void __exit exit_humfs(void) -+{ -+ unregister_externfs("humfs"); -+} -+ -+__initcall(init_humfs); -+__exitcall(exit_humfs); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/Makefile 2005-05-03 22:28:14.284438648 +0300 -@@ -0,0 +1,14 @@ -+# -+# Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := hostfs.o -+ -+obj-$(CONFIG_EXTERNFS) += externfs.o -+obj-$(CONFIG_HOSTFS) += host_fs.o host_file.o -+obj-$(CONFIG_HUMFS) += humfs.o host_file.o meta_fs.o -+ -+obj-m = $(O_TARGET) -+ -+include $(TOPDIR)/Rules.make -Index: linux-2.4.29/arch/um/fs/hostfs/metadata.h -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/metadata.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/metadata.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,84 @@ -+/* -+ * Copyright (C) 2004 Piotr Neuman (sikkh@wp.pl) and -+ * Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_FS_METADATA -+#define __UM_FS_METADATA -+ -+#include "linux/fs.h" -+#include "linux/list.h" -+#include "os.h" -+#include "hostfs.h" -+#include "filehandle.h" -+ -+#define container_of(ptr, type, member) ({ \ -+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ -+ (type *)( (char *)__mptr - offsetof(type,member) );}) -+ -+struct humfs { -+ struct externfs_data ext; -+ __u64 used; -+ __u64 total; -+ char *data; -+ int mmap; -+ int direct; -+ struct humfs_meta_ops *meta; -+}; -+ -+struct humfs_file { -+ struct humfs *mount; -+ struct file_handle data; -+ struct externfs_inode ext; -+}; -+ -+struct humfs_meta_ops { -+ struct list_head list; -+ char *name; -+ struct humfs_file *(*init_file)(void); -+ int (*open_file)(struct humfs_file *hf, const char *path, -+ struct inode *inode, struct humfs *humfs); -+ int (*create_file)(struct humfs_file *hf, const char *path, int mode, -+ int uid, int gid, struct inode *inode, -+ struct humfs *humfs); -+ void (*close_file)(struct humfs_file *humfs); -+ int (*ownerships)(const char *path, int *mode_out, int *uid_out, -+ int *gid_out, char *type_out, int *maj_out, -+ int *min_out, struct humfs *humfs); -+ int (*make_node)(const char *path, int mode, int uid, int gid, -+ int type, int major, int minor, struct humfs *humfs); -+ int (*create_link)(const char *to, const char *from, -+ struct humfs *humfs); -+ int (*remove_file)(const char *path, struct humfs *humfs); -+ int (*create_dir)(const char *path, int mode, int uid, int gid, -+ struct humfs *humfs); -+ int (*remove_dir)(const char *path, struct humfs *humfs); -+ int (*change_ownerships)(const char *path, int mode, int uid, int gid, -+ struct humfs *humfs); -+ int (*rename_file)(const char *from, const char *to, -+ struct humfs *humfs); -+ void (*invisible)(struct humfs_file *hf); -+ struct humfs *(*init_mount)(char *root); -+ void (*free_mount)(struct humfs *humfs); -+}; -+ -+void register_meta(struct humfs_meta_ops *ops); -+void unregister_meta(struct humfs_meta_ops *ops); -+ -+char *humfs_path(char *dir, char *file); -+char *humfs_name(struct inode *inode, char *prefix); -+extern struct humfs *inode_humfs_info(struct inode *inode); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hostfs/meta_fs.c -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hostfs/meta_fs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hostfs/meta_fs.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,519 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/slab.h> -+#include "hostfs.h" -+#include "metadata.h" -+#include "kern_util.h" -+ -+#define METADATA_FILE_PATH(meta) (meta)->root, "file_metadata" -+#define METADATA_DIR_PATH(meta) (meta)->root, "dir_metadata" -+ -+struct meta_fs { -+ struct humfs humfs; -+ char *root; -+}; -+ -+struct meta_file { -+ struct humfs_file humfs; -+ struct file_handle fh; -+}; -+ -+static int meta_file_path(const char *path, struct meta_fs *meta, -+ const char *path_out[]) -+{ -+ const char *data_path[] = { meta->root, "data", path, NULL }; -+ char data_tmp[HOSTFS_BUFSIZE]; -+ char *data_file = get_path(data_path, data_tmp, sizeof(data_tmp)); -+ -+ if(data_file == NULL) -+ return(-ENOMEM); -+ -+ path_out[0] = meta->root; -+ path_out[2] = path; -+ if(os_file_type(data_file) == OS_TYPE_DIR){ -+ path_out[1] = "dir_metadata"; -+ path_out[3] = "metadata"; -+ path_out[4] = NULL; -+ } -+ else { -+ path_out[1] = "file_metadata"; -+ path_out[3] = NULL; -+ } -+ -+ return(0); -+} -+ -+static int open_meta_file(const char *path, struct humfs *humfs, -+ struct file_handle *fh) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ const char *meta_path[5]; -+ char meta_tmp[HOSTFS_BUFSIZE]; -+ char *meta_file; -+ int err; -+ -+ err = meta_file_path(path, meta, meta_path); -+ if(err) -+ goto out; -+ -+ meta_file = get_path(meta_path, meta_tmp, sizeof(meta_tmp)); -+ if(meta_file == NULL) -+ goto out; -+ -+ err = open_filehandle(meta_file, of_rdwr(OPENFLAGS()), 0, fh); -+ -+ out: -+ return(err); -+} -+ -+static char *meta_fs_name(struct inode *inode) -+{ -+ struct humfs *mount = inode->i_sb->u.generic_sbp; -+ struct meta_fs *meta = container_of(mount, struct meta_fs, humfs); -+ const char *metadata_path[5]; -+ char tmp[HOSTFS_BUFSIZE], *name, *file; -+ -+ if(meta_file_path("", meta, metadata_path)) -+ return(NULL); -+ -+ file = get_path(metadata_path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ return(NULL); -+ -+ name = inode_name_prefix(inode, file); -+ -+ free_path(file, tmp); -+ return(name); -+} -+ -+static void metafs_invisible(struct humfs_file *hf) -+{ -+ struct meta_file *mf = container_of(hf, struct meta_file, humfs); -+ -+ not_reclaimable(&mf->fh); -+} -+ -+static struct humfs_file *metafs_init_file(void) -+{ -+ struct meta_file *mf; -+ int err = -ENOMEM; -+ -+ mf = kmalloc(sizeof(*mf), GFP_KERNEL); -+ if(mf == NULL) -+ return(ERR_PTR(err)); -+ -+ return(&mf->humfs); -+} -+ -+static int metafs_open_file(struct humfs_file *hf, const char *path, -+ struct inode *inode, struct humfs *humfs) -+{ -+ struct meta_file *mf = container_of(hf, struct meta_file, humfs); -+ int err; -+ -+ err = open_meta_file(path, humfs, &mf->fh); -+ if(err) -+ return(err); -+ -+ is_reclaimable(&mf->fh, meta_fs_name, inode); -+ -+ return(0); -+} -+ -+static void metafs_close_file(struct humfs_file *hf) -+{ -+ struct meta_file *meta = container_of(hf, struct meta_file, humfs); -+ -+ close_file(&meta->fh); -+ kfree(meta); -+} -+ -+static int metafs_create_file(struct humfs_file *hf, const char *path, -+ int mode, int uid, int gid, struct inode *inode, -+ struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ struct meta_file *mf = container_of(hf, struct meta_file, humfs); -+ char tmp[HOSTFS_BUFSIZE]; -+ const char *metadata_path[] = { METADATA_FILE_PATH(meta), path, NULL }; -+ char *file = get_path(metadata_path, tmp, sizeof(tmp)); -+ char buf[sizeof("mmmm uuuuuuuuuu gggggggggg")]; -+ int err = -ENOMEM; -+ -+ if(file == NULL) -+ goto out; -+ -+ err = open_filehandle(file, of_write(of_create(OPENFLAGS())), 0644, -+ &mf->fh); -+ if(err) -+ goto out_free_path; -+ -+ if(inode != NULL) -+ is_reclaimable(&mf->fh, meta_fs_name, inode); -+ -+ sprintf(buf, "%d %d %d\n", mode & S_IRWXUGO, uid, gid); -+ err = write_file(&mf->fh, 0, buf, strlen(buf)); -+ if(err < 0) -+ goto out_rm; -+ -+ free_path(file, tmp); -+ return(0); -+ -+ out_rm: -+ close_file(&mf->fh); -+ os_remove_file(file); -+ out_free_path: -+ free_path(file, tmp); -+ out: -+ return(err); -+} -+ -+static int metafs_create_link(const char *to, const char *from, -+ struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ const char *path_to[] = { METADATA_FILE_PATH(meta), to, NULL }; -+ const char *path_from[] = { METADATA_FILE_PATH(meta), from, NULL }; -+ -+ return(host_link_file(path_to, path_from)); -+} -+ -+static int metafs_remove_file(const char *path, struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ char tmp[HOSTFS_BUFSIZE]; -+ const char *metadata_path[] = { METADATA_FILE_PATH(meta), path, NULL }; -+ char *file = get_path(metadata_path, tmp, sizeof(tmp)); -+ int err = -ENOMEM; -+ -+ if(file == NULL) -+ goto out; -+ -+ err = os_remove_file(file); -+ -+ out: -+ free_path(file, tmp); -+ return(err); -+} -+ -+static int metafs_create_directory(const char *path, int mode, int uid, -+ int gid, struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ char tmp[HOSTFS_BUFSIZE]; -+ const char *dir_path[] = { METADATA_DIR_PATH(meta), path, NULL, NULL }; -+ const char *file_path[] = { METADATA_FILE_PATH(meta), path, NULL, -+ NULL }; -+ char *file, dir_meta[sizeof("mmmm uuuuuuuuuu gggggggggg\n")]; -+ int err, fd; -+ -+ err = host_make_dir(dir_path, 0755); -+ if(err) -+ goto out; -+ -+ err = host_make_dir(file_path, 0755); -+ if(err) -+ goto out_rm; -+ -+ /* This to make the index independent of the number of elements in -+ * METADATA_DIR_PATH(). -+ */ -+ dir_path[sizeof(dir_path) / sizeof(dir_path[0]) - 2] = "metadata"; -+ -+ err = -ENOMEM; -+ file = get_path(dir_path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ fd = os_open_file(file, of_create(of_rdwr(OPENFLAGS())), 0644); -+ if(fd < 0){ -+ err = fd; -+ goto out_free; -+ } -+ -+ sprintf(dir_meta, "%d %d %d\n", mode & S_IRWXUGO, uid, gid); -+ err = os_write_file(fd, dir_meta, strlen(dir_meta)); -+ if(err > 0) -+ err = 0; -+ -+ os_close_file(fd); -+ -+ out_free: -+ free_path(file, tmp); -+ out_rm: -+ host_remove_dir(dir_path); -+ out: -+ return(err); -+} -+ -+static int metafs_remove_directory(const char *path, struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ char tmp[HOSTFS_BUFSIZE], *file; -+ const char *dir_path[] = { METADATA_DIR_PATH(meta), path, "metadata", -+ NULL }; -+ const char *file_path[] = { METADATA_FILE_PATH(meta), path, NULL }; -+ char *slash; -+ int err; -+ -+ err = -ENOMEM; -+ file = get_path(dir_path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_remove_file(file); -+ if(err) -+ goto out_free; -+ -+ slash = strrchr(file, '/'); -+ if(slash == NULL){ -+ printk("remove_shadow_directory failed to find last slash\n"); -+ goto out_free; -+ } -+ *slash = '\0'; -+ err = os_remove_dir(file); -+ free_path(file, tmp); -+ -+ file = get_path(file_path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = os_remove_dir(file); -+ if(err) -+ goto out_free; -+ -+ out: -+ return(err); -+ out_free: -+ free_path(file, tmp); -+ goto out; -+} -+ -+static int metafs_make_node(const char *path, int mode, int uid, int gid, -+ int type, int maj, int min, struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ struct file_handle fh; -+ char tmp[HOSTFS_BUFSIZE]; -+ const char *metadata_path[] = { METADATA_FILE_PATH(meta), path, NULL }; -+ int err; -+ char buf[sizeof("mmmm uuuuuuuuuu gggggggggg x nnn mmm\n")], *file; -+ -+ sprintf(buf, "%d %d %d %c %d %d\n", mode & S_IRWXUGO, uid, gid, type, -+ maj, min); -+ -+ err = -ENOMEM; -+ file = get_path(metadata_path, tmp, sizeof(tmp)); -+ if(file == NULL) -+ goto out; -+ -+ err = open_filehandle(file, -+ of_create(of_rdwr(OPENFLAGS())), 0644, &fh); -+ if(err) -+ goto out_free; -+ -+ err = write_file(&fh, 0, buf, strlen(buf)); -+ if(err > 0) -+ err = 0; -+ -+ close_file(&fh); -+ -+ out_free: -+ free_path(file, tmp); -+ out: -+ return(err); -+} -+ -+static int metafs_ownerships(const char *path, int *mode_out, int *uid_out, -+ int *gid_out, char *type_out, int *maj_out, -+ int *min_out, struct humfs *humfs) -+{ -+ struct file_handle fh; -+ char buf[sizeof("mmmm uuuuuuuuuu gggggggggg x nnn mmm\n")]; -+ int err, n, mode, uid, gid, maj, min; -+ char type; -+ -+ err = open_meta_file(path, humfs, &fh); -+ if(err) -+ goto out; -+ -+ err = os_read_file(fh.fd, buf, sizeof(buf) - 1); -+ if(err < 0) -+ goto out_close; -+ -+ buf[err] = '\0'; -+ err = 0; -+ -+ n = sscanf(buf, "%d %d %d %c %d %d", &mode, &uid, &gid, &type, &maj, -+ &min); -+ if(n == 3){ -+ maj = -1; -+ min = -1; -+ type = 0; -+ err = 0; -+ } -+ else if(n != 6) -+ err = -EINVAL; -+ -+ if(mode_out != NULL) -+ *mode_out = mode; -+ if(uid_out != NULL) -+ *uid_out = uid; -+ if(gid_out != NULL) -+ *gid_out = uid; -+ if(type_out != NULL) -+ *type_out = type; -+ if(maj_out != NULL) -+ *maj_out = maj; -+ if(min_out != NULL) -+ *min_out = min; -+ -+ out_close: -+ close_file(&fh); -+ out: -+ return(err); -+} -+ -+static int metafs_change_ownerships(const char *path, int mode, int uid, -+ int gid, struct humfs *humfs) -+{ -+ struct file_handle fh; -+ char type; -+ char buf[sizeof("mmmm uuuuuuuuuu gggggggggg x nnn mmm\n")]; -+ int err = -ENOMEM, old_mode, old_uid, old_gid, n, maj, min; -+ -+ err = open_meta_file(path, humfs, &fh); -+ if(err) -+ goto out; -+ -+ err = read_file(&fh, 0, buf, sizeof(buf) - 1); -+ if(err < 0) -+ goto out_close; -+ -+ buf[err] = '\0'; -+ -+ n = sscanf(buf, "%d %d %d %c %d %d\n", &old_mode, &old_uid, &old_gid, -+ &type, &maj, &min); -+ if((n != 3) && (n != 6)){ -+ err = -EINVAL; -+ goto out_close; -+ } -+ -+ if(mode == -1) -+ mode = old_mode; -+ if(uid == -1) -+ uid = old_uid; -+ if(gid == -1) -+ gid = old_gid; -+ -+ if(n == 3) -+ sprintf(buf, "%d %d %d\n", mode & S_IRWXUGO, uid, gid); -+ else -+ sprintf(buf, "%d %d %d %c %d %d\n", mode & S_IRWXUGO, uid, gid, -+ type, maj, min); -+ -+ err = write_file(&fh, 0, buf, strlen(buf)); -+ if(err > 0) -+ err = 0; -+ -+ err = truncate_file(&fh, strlen(buf)); -+ -+ out_close: -+ close_file(&fh); -+ out: -+ return(err); -+} -+ -+static int metafs_rename_file(const char *from, const char *to, -+ struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ const char *metadata_path_from[5], *metadata_path_to[5]; -+ int err; -+ -+ err = meta_file_path(from, meta, metadata_path_from); -+ if(err) -+ return(err); -+ -+ err = meta_file_path(to, meta, metadata_path_to); -+ if(err) -+ return(err); -+ -+ return(host_rename_file(metadata_path_from, metadata_path_to)); -+} -+ -+static struct humfs *metafs_init_mount(char *root) -+{ -+ struct meta_fs *meta; -+ int err = -ENOMEM; -+ -+ meta = kmalloc(sizeof(*meta), GFP_KERNEL); -+ if(meta == NULL) -+ goto out; -+ -+ meta->root = uml_strdup(root); -+ if(meta->root == NULL) -+ goto out_free_meta; -+ -+ return(&meta->humfs); -+ -+ out_free_meta: -+ kfree(meta); -+ out: -+ return(ERR_PTR(err)); -+} -+ -+static void metafs_free_mount(struct humfs *humfs) -+{ -+ struct meta_fs *meta = container_of(humfs, struct meta_fs, humfs); -+ -+ kfree(meta); -+} -+ -+struct humfs_meta_ops hum_fs_meta_fs_ops = { -+ .list = LIST_HEAD_INIT(hum_fs_meta_fs_ops.list), -+ .name = "shadow_fs", -+ .init_file = metafs_init_file, -+ .open_file = metafs_open_file, -+ .close_file = metafs_close_file, -+ .ownerships = metafs_ownerships, -+ .make_node = metafs_make_node, -+ .create_file = metafs_create_file, -+ .create_link = metafs_create_link, -+ .remove_file = metafs_remove_file, -+ .create_dir = metafs_create_directory, -+ .remove_dir = metafs_remove_directory, -+ .change_ownerships = metafs_change_ownerships, -+ .rename_file = metafs_rename_file, -+ .invisible = metafs_invisible, -+ .init_mount = metafs_init_mount, -+ .free_mount = metafs_free_mount, -+}; -+ -+static int __init init_meta_fs(void) -+{ -+ register_meta(&hum_fs_meta_fs_ops); -+ return(0); -+} -+ -+static void __exit exit_meta_fs(void) -+{ -+ unregister_meta(&hum_fs_meta_fs_ops); -+} -+ -+__initcall(init_meta_fs); -+__exitcall(exit_meta_fs); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hppfs/hppfs_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hppfs/hppfs_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hppfs/hppfs_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,737 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <linux/fs.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/list.h> -+#include <linux/kernel.h> -+#include <linux/ctype.h> -+#include <asm/uaccess.h> -+#include "os.h" -+ -+struct hppfs_data { -+ struct list_head list; -+ char contents[PAGE_SIZE - sizeof(struct list_head)]; -+}; -+ -+struct hppfs_private { -+ struct file proc_file; -+ int host_fd; -+ loff_t len; -+ struct hppfs_data *contents; -+}; -+ -+#define HPPFS_SUPER_MAGIC 0xb00000ee -+ -+static struct super_operations hppfs_sbops; -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error); -+ -+static int is_pid(struct dentry *dentry) -+{ -+ struct super_block *sb; -+ int i; -+ -+ sb = dentry->d_sb; -+ if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) -+ return(0); -+ -+ for(i = 0; i < dentry->d_name.len; i++){ -+ if(!isdigit(dentry->d_name.name[i])) -+ return(0); -+ } -+ return(1); -+} -+ -+static char *dentry_name(struct dentry *dentry, int extra) -+{ -+ struct dentry *parent; -+ char *root, *name; -+ const char *seg_name; -+ int len, seg_len; -+ -+ len = 0; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ if(is_pid(parent)) -+ len += strlen("pid") + 1; -+ else len += parent->d_name.len + 1; -+ parent = parent->d_parent; -+ } -+ -+ root = "proc"; -+ len += strlen(root); -+ name = kmalloc(len + extra + 1, GFP_KERNEL); -+ if(name == NULL) return(NULL); -+ -+ name[len] = '\0'; -+ parent = dentry; -+ while(parent->d_parent != parent){ -+ if(is_pid(parent)){ -+ seg_name = "pid"; -+ seg_len = strlen("pid"); -+ } -+ else { -+ seg_name = parent->d_name.name; -+ seg_len = parent->d_name.len; -+ } -+ -+ len -= seg_len + 1; -+ name[len] = '/'; -+ strncpy(&name[len + 1], seg_name, seg_len); -+ parent = parent->d_parent; -+ } -+ strncpy(name, root, strlen(root)); -+ return(name); -+} -+ -+struct dentry_operations hppfs_dentry_ops = { -+}; -+ -+static int file_removed(struct dentry *dentry, const char *file) -+{ -+ char *host_file; -+ int extra, fd; -+ -+ extra = 0; -+ if(file != NULL) extra += strlen(file) + 1; -+ -+ host_file = dentry_name(dentry, extra + strlen("/remove")); -+ if(host_file == NULL){ -+ printk("file_removed : allocation failed\n"); -+ return(-ENOMEM); -+ } -+ -+ if(file != NULL){ -+ strcat(host_file, "/"); -+ strcat(host_file, file); -+ } -+ strcat(host_file, "/remove"); -+ -+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); -+ kfree(host_file); -+ if(fd >= 0){ -+ os_close_file(fd); -+ return(1); -+ } -+ return(0); -+} -+ -+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry) -+{ -+ struct dentry *proc_dentry; -+ struct inode *inode; -+ int err, deleted; -+ -+ deleted = file_removed(dentry, NULL); -+ if(deleted < 0) -+ return(ERR_PTR(deleted)); -+ else if(deleted) -+ return(ERR_PTR(-ENOENT)); -+ -+ proc_dentry = lookup_hash(&dentry->d_name, ino->u.hppfs_i.proc_dentry); -+ if(IS_ERR(proc_dentry)) -+ return(proc_dentry); -+ -+ inode = get_inode(ino->i_sb, proc_dentry, &err); -+ if(err != 0) -+ return(ERR_PTR(err)); -+ -+ d_add(dentry, inode); -+ dentry->d_op = &hppfs_dentry_ops; -+ return(NULL); -+} -+ -+static struct inode_operations hppfs_file_iops = { -+}; -+ -+static struct inode_operations hppfs_dir_iops = { -+ .lookup = hppfs_lookup, -+}; -+ -+static ssize_t read_proc(struct file *file, char *buf, ssize_t count, -+ loff_t *ppos, int is_user) -+{ -+ ssize_t (*read)(struct file *, char *, size_t, loff_t *); -+ ssize_t n; -+ -+ read = file->f_dentry->d_inode->i_fop->read; -+ if(read == NULL) -+ return(-EOPNOTSUPP); -+ -+ if(!is_user) -+ set_fs(KERNEL_DS); -+ -+ n = (*read)(file, buf, count, &file->f_pos); -+ -+ if(!is_user) -+ set_fs(USER_DS); -+ -+ if(ppos) *ppos = file->f_pos; -+ return(n); -+} -+ -+static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count) -+{ -+ ssize_t n; -+ int cur, err; -+ char *new_buf; -+ -+ n = -ENOMEM; -+ new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); -+ if(new_buf == NULL){ -+ printk("hppfs_read_file : kmalloc failed\n"); -+ goto out; -+ } -+ n = 0; -+ while(count > 0){ -+ cur = min_t(ssize_t, count, PAGE_SIZE); -+ err = os_read_file(fd, new_buf, cur); -+ if(err < 0){ -+ printk("hppfs_read : read failed, err = %d\n", -err); -+ n = err; -+ goto out_free; -+ } -+ else if(err == 0) -+ break; -+ -+ if(copy_to_user(buf, new_buf, err)){ -+ n = -EFAULT; -+ goto out_free; -+ } -+ n += err; -+ count -= err; -+ } -+ out_free: -+ kfree(new_buf); -+ out: -+ return(n); -+} -+ -+static ssize_t hppfs_read(struct file *file, char *buf, size_t count, -+ loff_t *ppos) -+{ -+ struct hppfs_private *hppfs = file->private_data; -+ struct hppfs_data *data; -+ loff_t off; -+ int err; -+ -+ if(hppfs->contents != NULL){ -+ if(*ppos >= hppfs->len) return(0); -+ -+ data = hppfs->contents; -+ off = *ppos; -+ while(off >= sizeof(data->contents)){ -+ data = list_entry(data->list.next, struct hppfs_data, -+ list); -+ off -= sizeof(data->contents); -+ } -+ -+ if(off + count > hppfs->len) -+ count = hppfs->len - off; -+ copy_to_user(buf, &data->contents[off], count); -+ *ppos += count; -+ } -+ else if(hppfs->host_fd != -1){ -+ err = os_seek_file(hppfs->host_fd, *ppos); -+ if(err < 0){ -+ printk("hppfs_read : seek failed, err = %d\n", -err); -+ return(err); -+ } -+ count = hppfs_read_file(hppfs->host_fd, buf, count); -+ if(count > 0) -+ *ppos += count; -+ } -+ else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1); -+ -+ return(count); -+} -+ -+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, -+ loff_t *ppos) -+{ -+ struct hppfs_private *data = file->private_data; -+ struct file *proc_file = &data->proc_file; -+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *); -+ int err; -+ -+ write = proc_file->f_dentry->d_inode->i_fop->write; -+ if(write == NULL) -+ return(-EOPNOTSUPP); -+ -+ proc_file->f_pos = file->f_pos; -+ err = (*write)(proc_file, buf, len, &proc_file->f_pos); -+ file->f_pos = proc_file->f_pos; -+ -+ return(err); -+} -+ -+static int open_host_sock(char *host_file, int *filter_out) -+{ -+ char *end; -+ int fd; -+ -+ end = &host_file[strlen(host_file)]; -+ strcpy(end, "/rw"); -+ *filter_out = 1; -+ fd = os_connect_socket(host_file); -+ if(fd >= 0) -+ return(fd); -+ -+ strcpy(end, "/r"); -+ *filter_out = 0; -+ fd = os_connect_socket(host_file); -+ return(fd); -+} -+ -+static void free_contents(struct hppfs_data *head) -+{ -+ struct hppfs_data *data; -+ struct list_head *ele, *next; -+ -+ if(head == NULL) return; -+ -+ list_for_each_safe(ele, next, &head->list){ -+ data = list_entry(ele, struct hppfs_data, list); -+ kfree(data); -+ } -+ kfree(head); -+} -+ -+static struct hppfs_data *hppfs_get_data(int fd, int filter, -+ struct file *proc_file, -+ struct file *hppfs_file, -+ loff_t *size_out) -+{ -+ struct hppfs_data *data, *new, *head; -+ int n, err; -+ -+ err = -ENOMEM; -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL){ -+ printk("hppfs_get_data : head allocation failed\n"); -+ goto failed; -+ } -+ -+ INIT_LIST_HEAD(&data->list); -+ -+ head = data; -+ *size_out = 0; -+ -+ if(filter){ -+ while((n = read_proc(proc_file, data->contents, -+ sizeof(data->contents), NULL, 0)) > 0) { -+ err = os_write_file(fd, data->contents, n); -+ if(err != n) -+ printk("hppfs_get_data : failed to write out " -+ "%d bytes, err = %d\n", n, -err); -+ } -+ err = os_shutdown_socket(fd, 0, 1); -+ if(err < 0){ -+ printk("hppfs_get_data : failed to shut down " -+ "socket\n"); -+ goto failed_free; -+ } -+ } -+ while(1){ -+ n = os_read_file(fd, data->contents, sizeof(data->contents)); -+ if(n < 0){ -+ err = n; -+ printk("hppfs_get_data : read failed, err = %d\n", -n); -+ goto failed_free; -+ } -+ else if(n == 0) -+ break; -+ -+ *size_out += n; -+ -+ if(n < sizeof(data->contents)) -+ break; -+ -+ new = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(new == 0){ -+ printk("hppfs_get_data : data allocation failed\n"); -+ err = -ENOMEM; -+ goto failed_free; -+ } -+ -+ INIT_LIST_HEAD(&new->list); -+ list_add(&new->list, &data->list); -+ data = new; -+ } -+ return(head); -+ -+ failed_free: -+ free_contents(head); -+ failed: -+ return(ERR_PTR(err)); -+} -+ -+static struct hppfs_private *hppfs_data(void) -+{ -+ struct hppfs_private *data; -+ -+ data = kmalloc(sizeof(*data), GFP_KERNEL); -+ if(data == NULL) -+ return(data); -+ -+ *data = ((struct hppfs_private ) { .host_fd = -1, -+ .len = -1, -+ .contents = NULL } ); -+ return(data); -+} -+ -+static int hppfs_open(struct inode *inode, struct file *file) -+{ -+ struct hppfs_private *data; -+ struct dentry *proc_dentry; -+ char *host_file; -+ int err, fd, type, filter; -+ -+ err = -ENOMEM; -+ data = hppfs_data(); -+ if(data == NULL) -+ goto out; -+ -+ host_file = dentry_name(file->f_dentry, strlen("/rw")); -+ if(host_file == NULL) -+ goto out_free2; -+ -+ proc_dentry = inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&data->proc_file, proc_dentry, file->f_mode); -+ if(err) -+ goto out_free1; -+ -+ type = os_file_type(host_file); -+ if(type == OS_TYPE_FILE){ -+ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); -+ if(fd >= 0) -+ data->host_fd = fd; -+ else printk("hppfs_open : failed to open '%s', err = %d\n", -+ host_file, -fd); -+ -+ data->contents = NULL; -+ } -+ else if(type == OS_TYPE_DIR){ -+ fd = open_host_sock(host_file, &filter); -+ if(fd >= 0){ -+ data->contents = hppfs_get_data(fd, filter, -+ &data->proc_file, -+ file, &data->len); -+ if(!IS_ERR(data->contents)) -+ data->host_fd = fd; -+ } -+ else printk("hppfs_open : failed to open a socket in " -+ "'%s', err = %d\n", host_file, -fd); -+ } -+ kfree(host_file); -+ -+ file->private_data = data; -+ return(0); -+ -+ out_free1: -+ kfree(host_file); -+ out_free2: -+ free_contents(data->contents); -+ kfree(data); -+ out: -+ return(err); -+} -+ -+static int hppfs_dir_open(struct inode *inode, struct file *file) -+{ -+ struct hppfs_private *data; -+ struct dentry *proc_dentry; -+ int err; -+ -+ err = -ENOMEM; -+ data = hppfs_data(); -+ if(data == NULL) -+ goto out; -+ -+ proc_dentry = inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&data->proc_file, proc_dentry, file->f_mode); -+ if(err) -+ goto out_free; -+ -+ file->private_data = data; -+ return(0); -+ -+ out_free: -+ kfree(data); -+ out: -+ return(err); -+} -+ -+static loff_t hppfs_llseek(struct file *file, loff_t off, int where) -+{ -+ struct hppfs_private *data = file->private_data; -+ struct file *proc_file = &data->proc_file; -+ loff_t (*llseek)(struct file *, loff_t, int); -+ loff_t ret; -+ -+ llseek = proc_file->f_dentry->d_inode->i_fop->llseek; -+ if(llseek != NULL){ -+ ret = (*llseek)(proc_file, off, where); -+ if(ret < 0) -+ return(ret); -+ } -+ -+ return(default_llseek(file, off, where)); -+} -+ -+struct hppfs_dirent { -+ void *vfs_dirent; -+ filldir_t filldir; -+ struct dentry *dentry; -+}; -+ -+static int hppfs_filldir(void *d, const char *name, int size, -+ loff_t offset, ino_t inode, unsigned int type) -+{ -+ struct hppfs_dirent *dirent = d; -+ -+ if(file_removed(dirent->dentry, name)) -+ return(0); -+ -+ return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, -+ inode, type)); -+} -+ -+static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) -+{ -+ struct hppfs_private *data = file->private_data; -+ struct file *proc_file = &data->proc_file; -+ int (*readdir)(struct file *, void *, filldir_t); -+ struct hppfs_dirent dirent = ((struct hppfs_dirent) -+ { .vfs_dirent = ent, -+ .filldir = filldir, -+ .dentry = file->f_dentry } ); -+ int err; -+ -+ readdir = proc_file->f_dentry->d_inode->i_fop->readdir; -+ if(readdir == NULL) -+ return(-EOPNOTSUPP); -+ -+ proc_file->f_pos = file->f_pos; -+ err = (*readdir)(proc_file, &dirent, hppfs_filldir); -+ file->f_pos = proc_file->f_pos; -+ -+ return(err); -+} -+ -+static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) -+{ -+ return(0); -+} -+ -+static struct file_operations hppfs_file_fops = { -+ .owner = NULL, -+ .llseek = hppfs_llseek, -+ .read = hppfs_read, -+ .write = hppfs_write, -+ .open = hppfs_open, -+}; -+ -+static struct file_operations hppfs_dir_fops = { -+ .owner = NULL, -+ .readdir = hppfs_readdir, -+ .open = hppfs_dir_open, -+ .fsync = hppfs_fsync, -+}; -+ -+static int hppfs_statfs(struct super_block *sb, struct statfs *sf) -+{ -+ sf->f_blocks = 0; -+ sf->f_bfree = 0; -+ sf->f_bavail = 0; -+ sf->f_files = 0; -+ sf->f_ffree = 0; -+ sf->f_type = HPPFS_SUPER_MAGIC; -+ return(0); -+} -+ -+static struct super_operations hppfs_sbops = { -+ .put_inode = force_delete, -+ .delete_inode = NULL, -+ .statfs = hppfs_statfs, -+}; -+ -+static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen) -+{ -+ struct file proc_file; -+ struct dentry *proc_dentry; -+ int (*readlink)(struct dentry *, char *, int); -+ int err, n; -+ -+ proc_dentry = dentry->d_inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ); -+ if(err) -+ return(err); -+ -+ readlink = proc_dentry->d_inode->i_op->readlink; -+ if(readlink == NULL) -+ return(-EOPNOTSUPP); -+ n = (*readlink)(proc_dentry, buffer, buflen); -+ -+ if(proc_file.f_op->release) -+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file); -+ -+ return(n); -+} -+ -+static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) -+{ -+ struct file proc_file; -+ struct dentry *proc_dentry; -+ int (*follow_link)(struct dentry *, struct nameidata *); -+ int err, n; -+ -+ proc_dentry = dentry->d_inode->u.hppfs_i.proc_dentry; -+ err = init_private_file(&proc_file, proc_dentry, FMODE_READ); -+ if(err) -+ return(err); -+ -+ follow_link = proc_dentry->d_inode->i_op->follow_link; -+ if(follow_link == NULL) -+ return(-EOPNOTSUPP); -+ n = (*follow_link)(proc_dentry, nd); -+ -+ if(proc_file.f_op->release) -+ (*proc_file.f_op->release)(proc_dentry->d_inode, &proc_file); -+ -+ return(n); -+} -+ -+static struct inode_operations hppfs_link_iops = { -+ .readlink = hppfs_readlink, -+ .follow_link = hppfs_follow_link, -+}; -+ -+static void read_inode(struct inode *ino) -+{ -+ struct inode *proc_ino; -+ -+ proc_ino = ino->u.hppfs_i.proc_dentry->d_inode; -+ ino->i_uid = proc_ino->i_uid; -+ ino->i_gid = proc_ino->i_gid; -+ ino->i_atime = proc_ino->i_atime; -+ ino->i_mtime = proc_ino->i_mtime; -+ ino->i_ctime = proc_ino->i_ctime; -+ ino->i_ino = proc_ino->i_ino; -+ ino->i_dev = proc_ino->i_dev; -+ ino->i_mode = proc_ino->i_mode; -+ ino->i_nlink = proc_ino->i_nlink; -+ ino->i_size = proc_ino->i_size; -+ ino->i_blksize = proc_ino->i_blksize; -+ ino->i_blocks = proc_ino->i_blocks; -+} -+ -+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry, -+ int *error) -+{ -+ struct inode *inode; -+ int err = -ENOMEM; -+ -+ inode = new_inode(sb); -+ if(inode == NULL) -+ goto out; -+ -+ insert_inode_hash(inode); -+ if(S_ISDIR(dentry->d_inode->i_mode)){ -+ inode->i_op = &hppfs_dir_iops; -+ inode->i_fop = &hppfs_dir_fops; -+ } -+ else if(S_ISLNK(dentry->d_inode->i_mode)){ -+ inode->i_op = &hppfs_link_iops; -+ inode->i_fop = &hppfs_file_fops; -+ } -+ else { -+ inode->i_op = &hppfs_file_iops; -+ inode->i_fop = &hppfs_file_fops; -+ } -+ -+ inode->i_sb = sb; -+ inode->u.hppfs_i.proc_dentry = dentry; -+ -+ read_inode(inode); -+ err = 0; -+ -+ if(error) *error = err; -+ return(inode); -+ out: -+ if(error) *error = err; -+ return(NULL); -+} -+ -+static struct super_block *hppfs_read_super(struct super_block *sb, void *d, -+ int silent) -+{ -+ struct inode *root_inode; -+ struct file_system_type *procfs; -+ struct super_block *proc_sb; -+ -+ procfs = get_fs_type("proc"); -+ if(procfs == NULL) -+ goto out; -+ -+ if(list_empty(&procfs->fs_supers)) -+ goto out; -+ -+ proc_sb = list_entry(procfs->fs_supers.next, struct super_block, -+ s_instances); -+ -+ sb->s_blocksize = 1024; -+ sb->s_blocksize_bits = 10; -+ sb->s_magic = HPPFS_SUPER_MAGIC; -+ sb->s_op = &hppfs_sbops; -+ -+ dget(proc_sb->s_root); -+ root_inode = get_inode(sb, proc_sb->s_root, NULL); -+ if(root_inode == NULL) -+ goto out_dput; -+ -+ sb->s_root = d_alloc_root(root_inode); -+ if(sb->s_root == NULL) -+ goto out_put; -+ -+ return(sb); -+ -+ out_put: -+ iput(root_inode); -+ out_dput: -+ dput(proc_sb->s_root); -+ out: -+ return(NULL); -+} -+ -+DECLARE_FSTYPE(hppfs_type, "hppfs", hppfs_read_super, 0); -+ -+static int __init init_hppfs(void) -+{ -+ return(register_filesystem(&hppfs_type)); -+} -+ -+static void __exit exit_hppfs(void) -+{ -+ unregister_filesystem(&hppfs_type); -+} -+ -+module_init(init_hppfs) -+module_exit(exit_hppfs) -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/fs/hppfs/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/hppfs/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/hppfs/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,10 @@ -+O_TARGET := hppfs.o -+obj-y = hppfs_kern.o #hppfs_user.o -+obj-m = $(O_TARGET) -+ -+CFLAGS_hppfs_kern.o := $(CFLAGS) -+#CFLAGS_hppfs_user.o := $(USER_CFLAGS) -+ -+override CFLAGS = -+ -+include $(TOPDIR)/Rules.make -Index: linux-2.4.29/arch/um/fs/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/fs/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/fs/Makefile 2005-05-03 22:28:14.291437584 +0300 -@@ -0,0 +1,23 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := built-in.o -+ -+subdir-y = -+subdir-m = -+ -+subdir-$(CONFIG_HOSTFS) += hostfs -+subdir-$(CONFIG_HPPFS) += hppfs -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+obj-m += $(join $(subdir-m),$(subdir-m:%=/%.o)) -+ -+include $(TOPDIR)/Rules.make -+ -+dep: -+ -+clean: -+ -+archmrproper: -Index: linux-2.4.29/arch/um/include/2_5compat.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/2_5compat.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/2_5compat.h 2005-05-03 22:28:14.292437432 +0300 -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __2_5_COMPAT_H__ -+#define __2_5_COMPAT_H__ -+ -+#include "linux/version.h" -+ -+#define INIT_ELV(queue, elv) elevator_init(elv, ELV_NOOP) -+ -+#define ELV_NOOP ELEVATOR_NOOP -+ -+#define INIT_HARDSECT(arr, maj, sizes) arr[maj] = sizes -+ -+#define IS_WRITE(req) ((req)->cmd == WRITE) -+ -+#define SET_PRI(task) \ -+ do { (task)->nice = 20; (task)->counter = -100; } while(0); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/aio.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/aio.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/aio.h 2005-05-03 22:28:14.293437280 +0300 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef AIO_H__ -+#define AIO_H__ -+ -+enum aio_type { AIO_READ, AIO_WRITE, AIO_MMAP }; -+ -+struct aio_thread_reply { -+ void *data; -+ int err; -+}; -+ -+struct aio_context { -+ int reply_fd; -+}; -+ -+#define INIT_AIO_CONTEXT { .reply_fd = -1 } -+ -+extern int submit_aio(enum aio_type type, int fd, char *buf, int len, -+ unsigned long long offset, int reply_fd, void *data); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/chan_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/chan_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/chan_kern.h 2005-05-03 22:28:14.294437128 +0300 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHAN_KERN_H__ -+#define __CHAN_KERN_H__ -+ -+#include "linux/tty.h" -+#include "linux/list.h" -+#include "chan_user.h" -+ -+struct chan { -+ struct list_head list; -+ char *dev; -+ unsigned int primary:1; -+ unsigned int input:1; -+ unsigned int output:1; -+ unsigned int opened:1; -+ int fd; -+ enum chan_init_pri pri; -+ struct chan_ops *ops; -+ void *data; -+}; -+ -+extern void chan_interrupt(struct list_head *chans, struct tq_struct *task, -+ struct tty_struct *tty, int irq, void *dev); -+extern int parse_chan_pair(char *str, struct list_head *chans, int pri, -+ int device, struct chan_opts *opts); -+extern int open_chan(struct list_head *chans); -+extern int write_chan(struct list_head *chans, const char *buf, int len, -+ int write_irq); -+extern int console_write_chan(struct list_head *chans, const char *buf, -+ int len); -+extern void close_chan(struct list_head *chans); -+extern void chan_enable_winch(struct list_head *chans, void *line); -+extern void enable_chan(struct list_head *chans, void *data); -+extern int chan_window_size(struct list_head *chans, -+ unsigned short *rows_out, -+ unsigned short *cols_out); -+extern int chan_out_fd(struct list_head *chans); -+extern int chan_config_string(struct list_head *chans, char *str, int size, -+ char **error_out); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/chan_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/chan_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/chan_user.h 2005-05-03 22:28:14.295436976 +0300 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHAN_USER_H__ -+#define __CHAN_USER_H__ -+ -+#include "init.h" -+ -+struct chan_opts { -+ void (*announce)(char *dev_name, int dev); -+ char *xterm_title; -+ int raw; -+ unsigned long tramp_stack; -+ int in_kernel; -+}; -+ -+enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; -+ -+struct chan_ops { -+ char *type; -+ void *(*init)(char *, int, struct chan_opts *); -+ int (*open)(int, int, int, void *, char **); -+ void (*close)(int, void *); -+ int (*read)(int, char *, void *); -+ int (*write)(int, const char *, int, void *); -+ int (*console_write)(int, const char *, int, void *); -+ int (*window_size)(int, void *, unsigned short *, unsigned short *); -+ void (*free)(void *); -+ int winch; -+}; -+ -+extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, -+ xterm_ops; -+ -+extern void generic_close(int fd, void *unused); -+extern int generic_read(int fd, char *c_out, void *unused); -+extern int generic_write(int fd, const char *buf, int n, void *unused); -+extern int generic_console_write(int fd, const char *buf, int n, void *state); -+extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, -+ unsigned short *cols_out); -+extern void generic_free(void *data); -+ -+extern void register_winch(int fd, void *device_data); -+extern void register_winch_irq(int fd, int tty_fd, int pid, void *line); -+ -+#define __channel_help(fn, prefix) \ -+__uml_help(fn, prefix "[0-9]*=<channel description>\n" \ -+" Attach a console or serial line to a host channel. See\n" \ -+" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \ -+" description of this switch.\n\n" \ -+); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/choose-mode.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/choose-mode.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/choose-mode.h 2005-05-03 22:28:14.295436976 +0300 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __CHOOSE_MODE_H__ -+#define __CHOOSE_MODE_H__ -+ -+#include "uml-config.h" -+ -+#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS) -+#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas)) -+ -+#elif defined(UML_CONFIG_MODE_SKAS) -+#define CHOOSE_MODE(tt, skas) (skas) -+ -+#elif defined(UML_CONFIG_MODE_TT) -+#define CHOOSE_MODE(tt, skas) (tt) -+#endif -+ -+#define CHOOSE_MODE_PROC(tt, skas, args...) \ -+ CHOOSE_MODE(tt(args), skas(args)) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/filehandle.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/filehandle.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/filehandle.h 2005-05-03 22:28:14.296436824 +0300 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FILEHANDLE_H__ -+#define __FILEHANDLE_H__ -+ -+#include "linux/list.h" -+#include "linux/fs.h" -+#include "os.h" -+ -+struct file_handle { -+ struct list_head list; -+ int fd; -+ char *(*get_name)(struct inode *); -+ struct inode *inode; -+ struct openflags flags; -+}; -+ -+extern struct file_handle bad_filehandle; -+ -+extern int open_file(char *name, struct openflags flags, int mode); -+extern void *open_dir(char *file); -+extern int open_filehandle(char *name, struct openflags flags, int mode, -+ struct file_handle *fh); -+extern int read_file(struct file_handle *fh, unsigned long long offset, -+ char *buf, int len); -+extern int write_file(struct file_handle *fh, unsigned long long offset, -+ const char *buf, int len); -+extern int truncate_file(struct file_handle *fh, unsigned long long size); -+extern int close_file(struct file_handle *fh); -+extern void not_reclaimable(struct file_handle *fh); -+extern void is_reclaimable(struct file_handle *fh, -+ char *(name_proc)(struct inode *), -+ struct inode *inode); -+extern int filehandle_fd(struct file_handle *fh); -+extern int make_pipe(struct file_handle *fhs); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/frame.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/frame.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/frame.h 2005-05-03 22:28:14.297436672 +0300 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_H_ -+#define __FRAME_H_ -+ -+#include "sysdep/frame.h" -+ -+struct frame_common { -+ void *data; -+ int len; -+ int sig_index; -+ int sr_index; -+ int sr_relative; -+ int sp_index; -+ struct arch_frame_data arch; -+}; -+ -+struct sc_frame { -+ struct frame_common common; -+ int sc_index; -+}; -+ -+extern struct sc_frame signal_frame_sc; -+ -+extern struct sc_frame signal_frame_sc_sr; -+ -+struct si_frame { -+ struct frame_common common; -+ int sip_index; -+ int si_index; -+ int ucp_index; -+ int uc_index; -+}; -+ -+extern struct si_frame signal_frame_si; -+ -+extern void capture_signal_stack(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/frame_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/frame_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/frame_kern.h 2005-05-03 22:28:14.298436520 +0300 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_KERN_H_ -+#define __FRAME_KERN_H_ -+ -+#include "frame.h" -+#include "sysdep/frame_kern.h" -+ -+extern int setup_signal_stack_sc(unsigned long stack_top, int sig, -+ unsigned long handler, -+ void (*restorer)(void), -+ struct pt_regs *regs, -+ sigset_t *mask); -+extern int setup_signal_stack_si(unsigned long stack_top, int sig, -+ unsigned long handler, -+ void (*restorer)(void), -+ struct pt_regs *regs, siginfo_t *info, -+ sigset_t *mask); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/frame_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/frame_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/frame_user.h 2005-05-03 22:28:14.299436368 +0300 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_USER_H_ -+#define __FRAME_USER_H_ -+ -+#include "sysdep/frame_user.h" -+#include "frame.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/helper.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/helper.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/helper.h 2005-05-03 22:28:14.300436216 +0300 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __HELPER_H__ -+#define __HELPER_H__ -+ -+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, -+ unsigned long *stack_out); -+extern int run_helper_thread(int (*proc)(void *), void *arg, -+ unsigned int flags, unsigned long *stack_out, -+ int stack_order); -+extern int helper_wait(int pid); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/init.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/init.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/init.h 2005-05-03 22:28:14.301436064 +0300 -@@ -0,0 +1,124 @@ -+#ifndef _LINUX_UML_INIT_H -+#define _LINUX_UML_INIT_H -+ -+/* These macros are used to mark some functions or -+ * initialized data (doesn't apply to uninitialized data) -+ * as `initialization' functions. The kernel can take this -+ * as hint that the function is used only during the initialization -+ * phase and free up used memory resources after -+ * -+ * Usage: -+ * For functions: -+ * -+ * You should add __init immediately before the function name, like: -+ * -+ * static void __init initme(int x, int y) -+ * { -+ * extern int z; z = x * y; -+ * } -+ * -+ * If the function has a prototype somewhere, you can also add -+ * __init between closing brace of the prototype and semicolon: -+ * -+ * extern int initialize_foobar_device(int, int, int) __init; -+ * -+ * For initialized data: -+ * You should insert __initdata between the variable name and equal -+ * sign followed by value, e.g.: -+ * -+ * static int init_variable __initdata = 0; -+ * static char linux_logo[] __initdata = { 0x32, 0x36, ... }; -+ * -+ * Don't forget to initialize data not at file scope, i.e. within a function, -+ * as gcc otherwise puts the data into the bss section and not into the init -+ * section. -+ * -+ * Also note, that this data cannot be "const". -+ */ -+ -+#ifndef _LINUX_INIT_H -+typedef int (*initcall_t)(void); -+typedef void (*exitcall_t)(void); -+ -+#define __init __attribute__ ((__section__ (".text.init"))) -+#define __exit __attribute__ ((unused, __section__(".text.exit"))) -+#define __initdata __attribute__ ((__section__ (".data.init"))) -+ -+#endif -+ -+#ifndef MODULE -+struct uml_param { -+ const char *str; -+ int (*setup_func)(char *, int *); -+}; -+ -+extern initcall_t __uml_initcall_start, __uml_initcall_end; -+extern initcall_t __uml_postsetup_start, __uml_postsetup_end; -+extern const char *__uml_help_start, *__uml_help_end; -+#endif -+ -+#define __uml_initcall(fn) \ -+ static initcall_t __uml_initcall_##fn __uml_init_call = fn -+ -+#define __uml_exitcall(fn) \ -+ static exitcall_t __uml_exitcall_##fn __uml_exit_call = fn -+ -+extern struct uml_param __uml_setup_start, __uml_setup_end; -+ -+#define __uml_postsetup(fn) \ -+ static initcall_t __uml_postsetup_##fn __uml_postsetup_call = fn -+ -+#define __non_empty_string(dummyname,string) \ -+ struct __uml_non_empty_string_struct_##dummyname \ -+ { \ -+ char _string[sizeof(string)-2]; \ -+ } -+ -+#ifndef MODULE -+#define __uml_setup(str, fn, help...) \ -+ __non_empty_string(fn ##_setup, str); \ -+ __uml_help(fn, help); \ -+ static char __uml_setup_str_##fn[] __initdata = str; \ -+ static struct uml_param __uml_setup_##fn __uml_init_setup = { __uml_setup_str_##fn, fn } -+#else -+#define __uml_setup(str, fn, help...) \ -+ -+#endif -+ -+#define __uml_help(fn, help...) \ -+ __non_empty_string(fn ##__help, help); \ -+ static char __uml_help_str_##fn[] __initdata = help; \ -+ static const char *__uml_help_##fn __uml_setup_help = __uml_help_str_##fn -+ -+/* -+ * Mark functions and data as being only used at initialization -+ * or exit time. -+ */ -+#define __uml_init_setup __attribute__ ((unused,__section__ (".uml.setup.init"))) -+#define __uml_setup_help __attribute__ ((unused,__section__ (".uml.help.init"))) -+#define __uml_init_call __attribute__ ((unused,__section__ (".uml.initcall.init"))) -+#define __uml_postsetup_call __attribute__ ((unused,__section__ (".uml.postsetup.init"))) -+#define __uml_exit_call __attribute__ ((unused,__section__ (".uml.exitcall.exit"))) -+ -+#ifndef __KERNEL__ -+ -+#define __initcall(fn) static initcall_t __initcall_##fn __init_call = fn -+#define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn -+ -+#define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) -+#define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit"))) -+ -+#endif -+ -+#endif /* _LINUX_UML_INIT_H */ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/initrd.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/initrd.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/initrd.h 2005-05-03 22:28:14.301436064 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __INITRD_USER_H__ -+#define __INITRD_USER_H__ -+ -+extern int load_initrd(char *filename, void *buf, int size); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/irq_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/irq_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/irq_kern.h 2005-05-03 22:28:14.303435760 +0300 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __IRQ_KERN_H__ -+#define __IRQ_KERN_H__ -+ -+#include "linux/interrupt.h" -+ -+extern int um_request_irq(unsigned int irq, int fd, int type, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, const char * devname, -+ void *dev_id); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/irq_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/irq_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/irq_user.h 2005-05-03 22:28:14.304435608 +0300 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __IRQ_USER_H__ -+#define __IRQ_USER_H__ -+ -+enum { IRQ_READ, IRQ_WRITE }; -+ -+extern void sigio_handler(int sig, union uml_pt_regs *regs); -+extern int activate_fd(int irq, int fd, int type, void *dev_id); -+extern void free_irq_by_irq_and_dev(int irq, void *dev_id); -+extern void free_irq_by_fd(int fd); -+extern void reactivate_fd(int fd, int irqnum); -+extern void deactivate_fd(int fd, int irqnum); -+extern int deactivate_all_fds(void); -+extern void forward_interrupts(int pid); -+extern void init_irq_signals(int on_sigstack); -+extern void forward_ipi(int fd, int pid); -+extern void free_irq_later(int irq, void *dev_id); -+extern int activate_ipi(int fd, int pid); -+extern unsigned long irq_lock(void); -+extern void irq_unlock(unsigned long flags); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/kern.h 2005-05-03 22:28:14.304435608 +0300 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __KERN_H__ -+#define __KERN_H__ -+ -+/* These are all user-mode things which are convenient to call directly -+ * from kernel code and for which writing a wrapper is too much of a pain. -+ * The regular include files can't be included because this file is included -+ * only into kernel code, and user-space includes conflict with kernel -+ * includes. -+ */ -+ -+extern int errno; -+ -+extern int clone(int (*proc)(void *), void *sp, int flags, void *data); -+extern int sleep(int); -+extern int printf(char *fmt, ...); -+extern char *strerror(int errnum); -+extern char *ptsname(int __fd); -+extern int munmap(void *, int); -+extern void *sbrk(int increment); -+extern void *malloc(int size); -+extern void perror(char *err); -+extern int kill(int pid, int sig); -+extern int getuid(void); -+extern int pause(void); -+extern int write(int, const void *, int); -+extern int exit(int); -+extern int close(int); -+extern int read(unsigned int, char *, int); -+extern int pipe(int *); -+extern int sched_yield(void); -+extern int ptrace(int op, int pid, long addr, long data); -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/kern_util.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/kern_util.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/kern_util.h 2005-05-03 22:28:14.306435304 +0300 -@@ -0,0 +1,123 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __KERN_UTIL_H__ -+#define __KERN_UTIL_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int ncpus; -+extern char *linux_prog; -+extern char *gdb_init; -+extern int kmalloc_ok; -+extern int timer_irq_inited; -+extern int jail; -+extern int nsyscalls; -+ -+#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) -+#define UML_ROUND_UP(addr) \ -+ UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) -+ -+extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg); -+extern unsigned long stack_sp(unsigned long page); -+extern int kernel_thread_proc(void *data); -+extern void syscall_segv(int sig); -+extern int current_pid(void); -+extern unsigned long alloc_stack(int order, int atomic); -+extern int do_signal(int error); -+extern int is_stack_fault(unsigned long sp); -+extern unsigned long segv(unsigned long address, unsigned long ip, -+ int is_write, int is_user, void *sc); -+extern unsigned long handle_page_fault(unsigned long address, unsigned long ip, -+ int is_write, int is_user, -+ int *code_out); -+extern void syscall_ready(void); -+extern int segv_syscall(void); -+extern void kern_finish_exec(void *task, int new_pid, unsigned long stack); -+extern int page_size(void); -+extern int page_mask(void); -+extern int need_finish_fork(void); -+extern void free_stack(unsigned long stack, int order); -+extern void add_input_request(int op, void (*proc)(int), void *arg); -+extern int sys_execve(char *file, char **argv, char **env); -+extern char *current_cmd(void); -+extern void timer_handler(int sig, union uml_pt_regs *regs); -+extern int set_signals(int enable); -+extern void force_sigbus(void); -+extern int pid_to_processor_id(int pid); -+extern void block_signals(void); -+extern void unblock_signals(void); -+extern void deliver_signals(void *t); -+extern int next_syscall_index(int max); -+extern int next_trap_index(int max); -+extern void cpu_idle(void); -+extern void finish_fork(void); -+extern void paging_init(void); -+extern void init_flush_vm(void); -+extern void *syscall_sp(void *t); -+extern void syscall_trace(void); -+extern int hz(void); -+extern void idle_timer(void); -+extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); -+extern int external_pid(void *t); -+extern void boot_timer_handler(int sig); -+extern void interrupt_end(void); -+extern void initial_thread_cb(void (*proc)(void *), void *arg); -+extern int debugger_signal(int status, int pid); -+extern void debugger_parent_signal(int status, int pid); -+extern void child_signal(int pid, int status); -+extern int init_ptrace_proxy(int idle_pid, int startup, int stop); -+extern int init_parent_proxy(int pid); -+extern void check_stack_overflow(void *ptr); -+extern void relay_signal(int sig, union uml_pt_regs *regs); -+extern void not_implemented(void); -+extern int user_context(unsigned long sp); -+extern void timer_irq(union uml_pt_regs *regs); -+extern void unprotect_stack(unsigned long stack); -+extern void do_uml_exitcalls(void); -+extern int attach_debugger(int idle_pid, int pid, int stop); -+extern void bad_segv(unsigned long address, unsigned long ip, int is_write); -+extern int config_gdb(char *str); -+extern int remove_gdb(void); -+extern char *uml_strdup(char *string); -+extern void unprotect_kernel_mem(void); -+extern void protect_kernel_mem(void); -+extern void set_kmem_end(unsigned long); -+extern void uml_cleanup(void); -+extern void set_current(void *t); -+extern void lock_signalled_task(void *t); -+extern void IPI_handler(int cpu); -+extern int jail_setup(char *line, int *add); -+extern void *get_init_task(void); -+extern int clear_user_proc(void *buf, int size); -+extern int copy_to_user_proc(void *to, void *from, int size); -+extern int copy_from_user_proc(void *to, void *from, int size); -+extern int strlen_user_proc(char *str); -+extern void bus_handler(int sig, union uml_pt_regs *regs); -+extern void winch(int sig, union uml_pt_regs *regs); -+extern long execute_syscall(void *r); -+extern int smp_sigio_handler(void); -+extern void *get_current(void); -+extern struct task_struct *get_task(int pid, int require); -+extern void machine_halt(void); -+extern int is_syscall(unsigned long addr); -+extern void arch_switch(void); -+extern void free_irq(unsigned int, void *); -+extern int um_in_interrupt(void); -+extern int cpu(void); -+extern unsigned long long time_stamp(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/line.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/line.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/line.h 2005-05-03 22:28:14.307435152 +0300 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __LINE_H__ -+#define __LINE_H__ -+ -+#include "linux/list.h" -+#include "linux/tqueue.h" -+#include "linux/tty.h" -+#include "asm/semaphore.h" -+#include "chan_user.h" -+#include "mconsole_kern.h" -+ -+struct line_driver { -+ char *name; -+ char *devfs_name; -+ short major; -+ short minor_start; -+ short type; -+ short subtype; -+ int read_irq; -+ char *read_irq_name; -+ int write_irq; -+ char *write_irq_name; -+ char *symlink_from; -+ char *symlink_to; -+ struct mc_device mc; -+}; -+ -+struct line { -+ char *init_str; -+ int init_pri; -+ struct list_head chan_list; -+ int valid; -+ int count; -+ struct tty_struct *tty; -+ struct semaphore sem; -+ char *buffer; -+ char *head; -+ char *tail; -+ int sigio; -+ struct tq_struct task; -+ struct line_driver *driver; -+ int have_irq; -+}; -+ -+#define LINE_INIT(str, d) \ -+ { init_str : str, \ -+ init_pri : INIT_STATIC, \ -+ chan_list : { }, \ -+ valid : 1, \ -+ count : 0, \ -+ tty : NULL, \ -+ sem : { }, \ -+ buffer : NULL, \ -+ head : NULL, \ -+ tail : NULL, \ -+ sigio : 0, \ -+ driver : d, \ -+ have_irq : 0 } -+ -+struct lines { -+ int num; -+}; -+ -+#define LINES_INIT(n) { num : n } -+ -+extern void line_close(struct line *lines, struct tty_struct *tty); -+extern int line_open(struct line *lines, struct tty_struct *tty, -+ struct chan_opts *opts); -+extern int line_setup(struct line *lines, int num, char *init, -+ int all_allowed); -+extern int line_write(struct line *line, struct tty_struct *tty, int from_user, -+ const char *buf, int len); -+extern char *add_xterm_umid(char *base); -+extern int line_setup_irq(int fd, int input, int output, void *data); -+extern void line_close_chan(struct line *line); -+extern void line_disable(struct line *line, int current_irq); -+extern void line_register_devfs(struct lines *set, -+ struct line_driver *line_driver, -+ struct tty_driver *driver, struct line *lines, -+ int nlines); -+extern void lines_init(struct line *lines, int nlines); -+extern void close_lines(struct line *lines, int nlines); -+extern int line_config(struct line *lines, int num, char *str); -+extern int line_remove(struct line *lines, int num, char *str); -+extern int line_get_config(char *dev, struct line *lines, int num, char *str, -+ int size, char **error_out); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/include/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,7 @@ -+all : sc.h -+ -+sc.h : ../util/mk_sc -+ ../util/mk_sc > $@ -+ -+../util/mk_sc : -+ $(MAKE) -C ../util mk_sc -Index: linux-2.4.29/arch/um/include/mconsole.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mconsole.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mconsole.h 2005-05-03 22:28:14.309434848 +0300 -@@ -0,0 +1,103 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MCONSOLE_H__ -+#define __MCONSOLE_H__ -+ -+#ifndef __KERNEL__ -+#include <stdint.h> -+#define u32 uint32_t -+#endif -+ -+#define MCONSOLE_MAGIC (0xcafebabe) -+#define MCONSOLE_MAX_DATA (512) -+#define MCONSOLE_VERSION 2 -+ -+struct mconsole_request { -+ u32 magic; -+ u32 version; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mconsole_reply { -+ u32 err; -+ u32 more; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mconsole_notify { -+ u32 magic; -+ u32 version; -+ enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, -+ MCONSOLE_USER_NOTIFY } type; -+ u32 len; -+ char data[MCONSOLE_MAX_DATA]; -+}; -+ -+struct mc_request; -+ -+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC }; -+ -+struct mconsole_command -+{ -+ char *command; -+ void (*handler)(struct mc_request *req); -+ enum mc_context context; -+}; -+ -+struct mc_request -+{ -+ int len; -+ int as_interrupt; -+ -+ int originating_fd; -+ int originlen; -+ unsigned char origin[128]; /* sockaddr_un */ -+ -+ struct mconsole_request request; -+ struct mconsole_command *cmd; -+}; -+ -+extern char mconsole_socket_name[]; -+ -+extern int mconsole_unlink_socket(void); -+extern int mconsole_reply(struct mc_request *req, char *reply, int err, -+ int more); -+ -+extern void mconsole_version(struct mc_request *req); -+extern void mconsole_help(struct mc_request *req); -+extern void mconsole_halt(struct mc_request *req); -+extern void mconsole_reboot(struct mc_request *req); -+extern void mconsole_config(struct mc_request *req); -+extern void mconsole_remove(struct mc_request *req); -+extern void mconsole_sysrq(struct mc_request *req); -+extern void mconsole_cad(struct mc_request *req); -+extern void mconsole_stop(struct mc_request *req); -+extern void mconsole_go(struct mc_request *req); -+extern void mconsole_log(struct mc_request *req); -+extern void mconsole_proc(struct mc_request *req); -+ -+extern int mconsole_get_request(int fd, struct mc_request *req); -+extern int mconsole_notify(char *sock_name, int type, const void *data, -+ int len); -+extern char *mconsole_notify_socket(void); -+extern void lock_notify(void); -+extern void unlock_notify(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/mconsole_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mconsole_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mconsole_kern.h 2005-05-03 22:28:14.310434696 +0300 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MCONSOLE_KERN_H__ -+#define __MCONSOLE_KERN_H__ -+ -+#include "linux/config.h" -+#include "linux/list.h" -+#include "mconsole.h" -+ -+struct mconsole_entry { -+ struct list_head list; -+ struct mc_request request; -+}; -+ -+struct mc_device { -+ struct list_head list; -+ char *name; -+ int (*config)(char *); -+ int (*get_config)(char *, char *, int, char **); -+ int (*remove)(char *); -+}; -+ -+#define CONFIG_CHUNK(str, size, current, chunk, end) \ -+do { \ -+ current += strlen(chunk); \ -+ if(current >= size) \ -+ str = NULL; \ -+ if(str != NULL){ \ -+ strcpy(str, chunk); \ -+ str += strlen(chunk); \ -+ } \ -+ if(end) \ -+ current++; \ -+} while(0) -+ -+#ifdef CONFIG_MCONSOLE -+ -+extern void mconsole_register_dev(struct mc_device *new); -+ -+#else -+ -+static inline void mconsole_register_dev(struct mc_device *new) -+{ -+} -+ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/mem.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mem.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mem.h 2005-05-03 22:28:14.310434696 +0300 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MEM_H__ -+#define __MEM_H__ -+ -+#include "linux/types.h" -+ -+extern void set_kmem_end(unsigned long new); -+extern int phys_mapping(unsigned long phys, __u64 *offset_out); -+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); -+extern int is_remapped(const void *virt, int fd, __u64 offset); -+extern int physmem_remove_mapping(void *virt); -+extern void physmem_forget_descriptor(int fd); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/mem_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mem_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mem_kern.h 2005-05-03 22:28:14.311434544 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MEM_KERN_H__ -+#define __MEM_KERN_H__ -+ -+#include "linux/list.h" -+#include "linux/types.h" -+ -+struct remapper { -+ struct list_head list; -+ int (*proc)(int, unsigned long, int, __u64, int); -+}; -+ -+extern void register_remapper(struct remapper *info); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/mem_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mem_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mem_user.h 2005-05-03 22:28:14.313434240 +0300 -@@ -0,0 +1,82 @@ -+/* -+ * arch/um/include/mem_user.h -+ * -+ * BRIEF MODULE DESCRIPTION -+ * user side memory interface for support IO memory inside user mode linux -+ * -+ * Copyright (C) 2001 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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. -+ */ -+ -+#ifndef _MEM_USER_H -+#define _MEM_USER_H -+ -+struct iomem_region { -+ struct iomem_region *next; -+ char *driver; -+ int fd; -+ int size; -+ unsigned long phys; -+ unsigned long virt; -+}; -+ -+extern struct iomem_region *iomem_regions; -+extern int iomem_size; -+ -+#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) -+ -+extern unsigned long host_task_size; -+extern unsigned long task_size; -+ -+extern int init_mem_user(void); -+extern int create_mem_file(unsigned long len); -+extern void setup_memory(void *entry); -+extern unsigned long find_iomem(char *driver, unsigned long *len_out); -+extern int init_maps(unsigned long physmem, unsigned long iomem, -+ unsigned long highmem); -+extern unsigned long get_vm(unsigned long len); -+extern void setup_physmem(unsigned long start, unsigned long usable, -+ unsigned long len, unsigned long highmem); -+extern void add_iomem(char *name, int fd, unsigned long size); -+extern unsigned long phys_offset(unsigned long phys); -+extern void unmap_physmem(void); -+extern void map_memory(unsigned long virt, unsigned long phys, -+ unsigned long len, int r, int w, int x); -+extern int protect_memory(unsigned long addr, unsigned long len, -+ int r, int w, int x, int must_succeed); -+extern unsigned long get_kmem_end(void); -+extern void check_tmpexec(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/mode.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mode.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mode.h 2005-05-03 22:28:14.313434240 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_H__ -+#define __MODE_H__ -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "../kernel/tt/include/mode.h" -+#endif -+ -+#ifdef UML_CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mode.h" -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/mode_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/mode_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/mode_kern.h 2005-05-03 22:28:14.314434088 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_KERN_H__ -+#define __MODE_KERN_H__ -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/mode_kern.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mode_kern.h" -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/net_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/net_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/net_kern.h 2005-05-03 22:28:14.315433936 +0300 -@@ -0,0 +1,81 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_NET_KERN_H -+#define __UM_NET_KERN_H -+ -+#include "linux/netdevice.h" -+#include "linux/skbuff.h" -+#include "linux/socket.h" -+#include "linux/list.h" -+ -+struct uml_net { -+ struct list_head list; -+ struct net_device *dev; -+ int index; -+ unsigned char mac[ETH_ALEN]; -+ int have_mac; -+}; -+ -+struct uml_net_private { -+ struct list_head list; -+ spinlock_t lock; -+ struct net_device *dev; -+ struct timer_list tl; -+ struct net_device_stats stats; -+ int fd; -+ unsigned char mac[ETH_ALEN]; -+ int have_mac; -+ unsigned short (*protocol)(struct sk_buff *); -+ int (*open)(void *); -+ void (*close)(int, void *); -+ void (*remove)(void *); -+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *); -+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *); -+ -+ void (*add_address)(unsigned char *, unsigned char *, void *); -+ void (*delete_address)(unsigned char *, unsigned char *, void *); -+ int (*set_mtu)(int mtu, void *); -+ int user[1]; -+}; -+ -+struct net_kern_info { -+ void (*init)(struct net_device *, void *); -+ unsigned short (*protocol)(struct sk_buff *); -+ int (*read)(int, struct sk_buff **skb, struct uml_net_private *); -+ int (*write)(int, struct sk_buff **skb, struct uml_net_private *); -+}; -+ -+struct transport { -+ struct list_head list; -+ char *name; -+ int (*setup)(char *, char **, void *); -+ struct net_user_info *user; -+ struct net_kern_info *kern; -+ int private_size; -+ int setup_size; -+}; -+ -+extern struct net_device *ether_init(int); -+extern unsigned short ether_protocol(struct sk_buff *); -+extern int setup_etheraddr(char *str, unsigned char *addr); -+extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); -+extern int tap_setup_common(char *str, char *type, char **dev_name, -+ char **mac_out, char **gate_addr); -+extern void register_transport(struct transport *new); -+extern unsigned short eth_protocol(struct sk_buff *skb); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/net_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/net_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/net_user.h 2005-05-03 22:28:14.316433784 +0300 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_NET_USER_H__ -+#define __UM_NET_USER_H__ -+ -+#define ETH_ADDR_LEN (6) -+#define ETH_HEADER_ETHERTAP (16) -+#define ETH_HEADER_OTHER (14) -+#define ETH_MAX_PACKET (1500) -+ -+#define UML_NET_VERSION (4) -+ -+struct net_user_info { -+ void (*init)(void *, void *); -+ int (*open)(void *); -+ void (*close)(int, void *); -+ void (*remove)(void *); -+ int (*set_mtu)(int mtu, void *); -+ void (*add_address)(unsigned char *, unsigned char *, void *); -+ void (*delete_address)(unsigned char *, unsigned char *, void *); -+ int max_packet; -+}; -+ -+extern void ether_user_init(void *data, void *dev); -+extern void dev_ip_addr(void *d, char *buf, char *bin_buf); -+extern void set_ether_mac(void *d, unsigned char *addr); -+extern void iter_addresses(void *d, void (*cb)(unsigned char *, -+ unsigned char *, void *), -+ void *arg); -+ -+extern void *get_output_buffer(int *len_out); -+extern void free_output_buffer(void *buffer); -+ -+extern int tap_open_common(void *dev, char *gate_addr); -+extern void tap_check_ips(char *gate_addr, char *eth_addr); -+ -+extern void read_output(int fd, char *output_out, int len); -+ -+extern int net_read(int fd, void *buf, int len); -+extern int net_recvfrom(int fd, void *buf, int len); -+extern int net_write(int fd, void *buf, int len); -+extern int net_send(int fd, void *buf, int len); -+extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len); -+ -+extern void open_addr(unsigned char *addr, unsigned char *netmask, void *arg); -+extern void close_addr(unsigned char *addr, unsigned char *netmask, void *arg); -+ -+extern char *split_if_spec(char *str, ...); -+ -+extern int dev_netmask(void *d, void *m); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/os.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/os.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/os.h 2005-05-03 22:28:14.318433480 +0300 -@@ -0,0 +1,221 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __OS_H__ -+#define __OS_H__ -+ -+#include "asm/types.h" -+#include "../os/include/file.h" -+ -+#define OS_TYPE_FILE 1 -+#define OS_TYPE_DIR 2 -+#define OS_TYPE_SYMLINK 3 -+#define OS_TYPE_CHARDEV 4 -+#define OS_TYPE_BLOCKDEV 5 -+#define OS_TYPE_FIFO 6 -+#define OS_TYPE_SOCK 7 -+ -+/* os_access() flags */ -+#define OS_ACC_F_OK 0 /* Test for existence. */ -+#define OS_ACC_X_OK 1 /* Test for execute permission. */ -+#define OS_ACC_W_OK 2 /* Test for write permission. */ -+#define OS_ACC_R_OK 4 /* Test for read permission. */ -+#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ -+ -+/* -+ * types taken from stat_file() in hostfs_user.c -+ * (if they are wrong here, they are wrong there...). -+ */ -+struct uml_stat { -+ int ust_major; /* device */ -+ int ust_minor; -+ unsigned long long ust_ino; /* inode */ -+ int ust_mode; /* protection */ -+ int ust_nlink; /* number of hard links */ -+ int ust_uid; /* user ID of owner */ -+ int ust_gid; /* group ID of owner */ -+ unsigned long long ust_size; /* total size, in bytes */ -+ int ust_blksize; /* blocksize for filesystem I/O */ -+ unsigned long long ust_blocks; /* number of blocks allocated */ -+ unsigned long ust_atime; /* time of last access */ -+ unsigned long ust_mtime; /* time of last modification */ -+ unsigned long ust_ctime; /* time of last change */ -+ int ust_rmajor; -+ int ust_rminor; -+}; -+ -+struct openflags { -+ unsigned int r : 1; -+ unsigned int w : 1; -+ unsigned int s : 1; /* O_SYNC */ -+ unsigned int c : 1; /* O_CREAT */ -+ unsigned int t : 1; /* O_TRUNC */ -+ unsigned int a : 1; /* O_APPEND */ -+ unsigned int e : 1; /* O_EXCL */ -+ unsigned int cl : 1; /* FD_CLOEXEC */ -+ unsigned int d : 1; /* O_DIRECT */ -+}; -+ -+#define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \ -+ .t = 0, .a = 0, .e = 0, .cl = 0, \ -+ .d = 0 }) -+ -+static inline struct openflags of_read(struct openflags flags) -+{ -+ flags.r = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_write(struct openflags flags) -+{ -+ flags.w = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_rdwr(struct openflags flags) -+{ -+ return(of_read(of_write(flags))); -+} -+ -+static inline struct openflags of_set_rw(struct openflags flags, int r, int w) -+{ -+ flags.r = r; -+ flags.w = w; -+ return(flags); -+} -+ -+static inline struct openflags of_sync(struct openflags flags) -+{ -+ flags.s = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_create(struct openflags flags) -+{ -+ flags.c = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_trunc(struct openflags flags) -+{ -+ flags.t = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_append(struct openflags flags) -+{ -+ flags.a = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_excl(struct openflags flags) -+{ -+ flags.e = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_cloexec(struct openflags flags) -+{ -+ flags.cl = 1; -+ return(flags); -+} -+ -+static inline struct openflags of_direct(struct openflags flags) -+{ -+ flags.d = 1; -+ return(flags); -+} -+ -+extern int os_stat_file(const char *file_name, struct uml_stat *buf); -+extern int os_lstat_file(const char *file_name, struct uml_stat *ubuf); -+extern int os_stat_fd(const int fd, struct uml_stat *buf); -+extern int os_access(const char *file, int mode); -+extern int os_set_file_time(const char *file, unsigned long access, -+ unsigned long mod); -+extern int os_set_file_perms(const char *file, int mode); -+extern int os_set_file_owner(const char *file, int owner, int group); -+extern void os_print_error(int error, const char* str); -+extern int os_get_exec_close(int fd, int *close_on_exec); -+extern int os_set_exec_close(int fd, int close_on_exec); -+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); -+extern int os_window_size(int fd, int *rows, int *cols); -+extern int os_new_tty_pgrp(int fd, int pid); -+extern int os_get_ifname(int fd, char *namebuf); -+extern int os_set_slip(int fd); -+extern int os_set_owner(int fd, int pid); -+extern int os_sigio_async(int master, int slave); -+extern int os_mode_fd(int fd, int mode); -+ -+extern int os_seek_file(int fd, __u64 offset); -+extern int os_open_file(char *file, struct openflags flags, int mode); -+extern void *os_open_dir(char *dir, int *err_out); -+extern int os_seek_dir(void *stream, unsigned long long pos); -+extern int os_read_dir(void *stream, unsigned long long *ino_out, -+ char **name_out); -+extern int os_tell_dir(void *stream); -+extern int os_close_dir(void *stream); -+extern int os_remove_file(const char *file); -+extern int os_move_file(const char *from, const char *to); -+extern int os_truncate_file(const char *file, unsigned long long len); -+extern int os_truncate_fd(int fd, unsigned long long len); -+extern int os_read_file(int fd, void *buf, int len); -+extern int os_write_file(int fd, const void *buf, int count); -+extern int os_file_size(char *file, long long *size_out); -+extern int os_fd_size(int fd, long long *size_out); -+extern int os_file_modtime(char *file, unsigned long *modtime); -+extern int os_pipe(int *fd, int stream, int close_on_exec); -+extern int os_set_fd_async(int fd, int owner); -+extern int os_clear_fd_async(int fd); -+extern int os_set_fd_block(int fd, int blocking); -+extern int os_accept_connection(int fd); -+extern int os_create_unix_socket(char *file, int len, int close_on_exec); -+extern int os_make_symlink(const char *to, const char *from); -+extern int os_read_symlink(const char *file, char *buf, int size); -+extern int os_link_file(const char *to, const char *from); -+extern int os_make_dir(const char *dir, int mode); -+extern int os_remove_dir(const char *dir); -+extern int os_make_dev(const char *name, int mode, int major, int minor); -+extern int os_shutdown_socket(int fd, int r, int w); -+extern void os_close_file(int fd); -+extern int os_rcv_fd(int fd, int *helper_pid_out); -+extern int create_unix_socket(char *file, int len, int close_on_exec); -+extern int os_connect_socket(char *name); -+extern int os_file_type(char *file); -+extern int os_file_mode(char *file, struct openflags *mode_out); -+extern int os_lock_file(int fd, int excl); -+ -+extern unsigned long os_process_pc(int pid); -+extern int os_process_parent(int pid); -+extern void os_stop_process(int pid); -+extern void os_kill_process(int pid, int reap_child); -+extern void os_usr1_process(int pid); -+extern int os_getpid(void); -+ -+extern int os_map_memory(void *virt, int fd, unsigned long long off, -+ unsigned long len, int r, int w, int x); -+extern int os_protect_memory(void *addr, unsigned long len, -+ int r, int w, int x); -+extern int os_unmap_memory(void *addr, int len); -+extern void os_flush_stdout(void); -+extern int os_stat_filesystem(char *path, long *bsize_out, -+ long long *blocks_out, long long *bfree_out, -+ long long *bavail_out, long long *files_out, -+ long long *ffree_out, void *fsid_out, -+ int fsid_size, long *namelen_out, -+ long *spare_out); -+extern unsigned long long os_usecs(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/process.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/process.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/process.h 2005-05-03 22:28:14.319433328 +0300 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROCESS_H__ -+#define __PROCESS_H__ -+ -+#include <asm/sigcontext.h> -+ -+extern void sig_handler(int sig, struct sigcontext sc); -+extern void alarm_handler(int sig, struct sigcontext sc); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/ptrace_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/ptrace_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/ptrace_user.h 2005-05-03 22:28:14.319433328 +0300 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_USER_H__ -+#define __PTRACE_USER_H__ -+ -+#include "sysdep/ptrace_user.h" -+ -+/* syscall emulation path in ptrace */ -+#ifndef PTRACE_SYSEMU -+#define PTRACE_SYSEMU 31 -+#endif -+ -+extern int use_sysemu; -+ -+extern int ptrace_getregs(long pid, unsigned long *regs_out); -+extern int ptrace_setregs(long pid, unsigned long *regs_in); -+extern int ptrace_getfpregs(long pid, unsigned long *regs_out); -+extern void arch_enter_kernel(void *task, int pid); -+extern void arch_leave_kernel(void *task, int pid); -+extern void ptrace_pokeuser(unsigned long addr, unsigned long data); -+ -+#endif -Index: linux-2.4.29/arch/um/include/sigcontext.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sigcontext.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sigcontext.h 2005-05-03 22:28:14.320433176 +0300 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UML_SIGCONTEXT_H__ -+#define __UML_SIGCONTEXT_H__ -+ -+#include "sysdep/sigcontext.h" -+ -+extern int sc_size(void *data); -+extern void sc_to_sc(void *to_ptr, void *from_ptr); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sigio.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sigio.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sigio.h 2005-05-03 22:28:14.321433024 +0300 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGIO_H__ -+#define __SIGIO_H__ -+ -+extern int write_sigio_irq(int fd); -+extern int register_sigio_fd(int fd); -+extern int read_sigio_fd(int fd); -+extern int add_sigio_fd(int fd, int read); -+extern int ignore_sigio_fd(int fd); -+extern void sigio_lock(void); -+extern void sigio_unlock(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/signal_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/signal_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/signal_kern.h 2005-05-03 22:28:14.322432872 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGNAL_KERN_H__ -+#define __SIGNAL_KERN_H__ -+ -+extern int have_signals(void *t); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/signal_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/signal_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/signal_user.h 2005-05-03 22:28:14.323432720 +0300 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SIGNAL_USER_H__ -+#define __SIGNAL_USER_H__ -+ -+extern int signal_stack_size; -+ -+extern int change_sig(int signal, int on); -+extern void set_sigstack(void *stack, int size); -+extern void set_handler(int sig, void (*handler)(int), int flags, ...); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/skas_ptrace.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/skas_ptrace.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/skas_ptrace.h 2005-05-03 22:28:14.323432720 +0300 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_PTRACE_H -+#define __SKAS_PTRACE_H -+ -+struct ptrace_faultinfo { -+ int is_write; -+ unsigned long addr; -+}; -+ -+struct ptrace_ldt { -+ int func; -+ void *ptr; -+ unsigned long bytecount; -+}; -+ -+#define PTRACE_FAULTINFO 52 -+#define PTRACE_SIGPENDING 53 -+#define PTRACE_LDT 54 -+#define PTRACE_SWITCH_MM 55 -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/syscall_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/syscall_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/syscall_user.h 2005-05-03 22:28:14.324432568 +0300 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSCALL_USER_H -+#define __SYSCALL_USER_H -+ -+extern int record_syscall_start(int syscall); -+extern void record_syscall_end(int index, int result); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/checksum.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/checksum.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/checksum.h 2005-05-03 22:28:14.326432264 +0300 -@@ -0,0 +1,218 @@ -+/* -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SYSDEP_CHECKSUM_H -+#define __UM_SYSDEP_CHECKSUM_H -+ -+#include "linux/string.h" -+#include "asm/uaccess.h" -+ -+/* -+ * computes the checksum of a memory block at buff, length len, -+ * and adds in "sum" (32-bit) -+ * -+ * returns a 32-bit number suitable for feeding into itself -+ * or csum_tcpudp_magic -+ * -+ * this function must be called with even lengths, except -+ * for the last fragment, which may be odd -+ * -+ * it's best to have buff aligned on a 32-bit boundary -+ */ -+unsigned int csum_partial(const unsigned char * buff, int len, -+ unsigned int sum); -+ -+/* -+ * the same as csum_partial, but copies from src while it -+ * checksums, and handles user-space pointer exceptions correctly, when needed. -+ * -+ * here even more important to align src and dst on a 32-bit (or even -+ * better 64-bit) boundary -+ */ -+ -+unsigned int csum_partial_copy_to(const char *src, char *dst, int len, -+ int sum, int *err_ptr); -+unsigned int csum_partial_copy_from(const char *src, char *dst, int len, -+ int sum, int *err_ptr); -+ -+/* -+ * Note: when you get a NULL pointer exception here this means someone -+ * passed in an incorrect kernel address to one of these functions. -+ * -+ * If you use these functions directly please don't forget the -+ * verify_area(). -+ */ -+ -+static __inline__ -+unsigned int csum_partial_copy_nocheck(const char *src, char *dst, -+ int len, int sum) -+{ -+ memcpy(dst, src, len); -+ return(csum_partial(dst, len, sum)); -+} -+ -+static __inline__ -+unsigned int csum_partial_copy_from_user(const char *src, char *dst, -+ int len, int sum, int *err_ptr) -+{ -+ return csum_partial_copy_from(src, dst, len, sum, err_ptr); -+} -+ -+/* -+ * These are the old (and unsafe) way of doing checksums, a warning message -+ * will be printed if they are used and an exception occurs. -+ * -+ * these functions should go away after some time. -+ */ -+ -+#define csum_partial_copy_fromuser csum_partial_copy_from_user -+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); -+ -+/* -+ * This is a version of ip_compute_csum() optimized for IP headers, -+ * which always checksum on 4 octet boundaries. -+ * -+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by -+ * Arnt Gulbrandsen. -+ */ -+static inline unsigned short ip_fast_csum(unsigned char * iph, -+ unsigned int ihl) -+{ -+ unsigned int sum; -+ -+ __asm__ __volatile__( -+ "movl (%1), %0 ;\n" -+ "subl $4, %2 ;\n" -+ "jbe 2f ;\n" -+ "addl 4(%1), %0 ;\n" -+ "adcl 8(%1), %0 ;\n" -+ "adcl 12(%1), %0 ;\n" -+"1: adcl 16(%1), %0 ;\n" -+ "lea 4(%1), %1 ;\n" -+ "decl %2 ;\n" -+ "jne 1b ;\n" -+ "adcl $0, %0 ;\n" -+ "movl %0, %2 ;\n" -+ "shrl $16, %0 ;\n" -+ "addw %w2, %w0 ;\n" -+ "adcl $0, %0 ;\n" -+ "notl %0 ;\n" -+"2: ;\n" -+ /* Since the input registers which are loaded with iph and ipl -+ are modified, we must also specify them as outputs, or gcc -+ will assume they contain their original values. */ -+ : "=r" (sum), "=r" (iph), "=r" (ihl) -+ : "1" (iph), "2" (ihl)); -+ return(sum); -+} -+ -+/* -+ * Fold a partial checksum -+ */ -+ -+static inline unsigned int csum_fold(unsigned int sum) -+{ -+ __asm__( -+ "addl %1, %0 ;\n" -+ "adcl $0xffff, %0 ;\n" -+ : "=r" (sum) -+ : "r" (sum << 16), "0" (sum & 0xffff0000) -+ ); -+ return (~sum) >> 16; -+} -+ -+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr, -+ unsigned long daddr, -+ unsigned short len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ __asm__( -+ "addl %1, %0 ;\n" -+ "adcl %2, %0 ;\n" -+ "adcl %3, %0 ;\n" -+ "adcl $0, %0 ;\n" -+ : "=r" (sum) -+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum)); -+ return sum; -+} -+ -+/* -+ * computes the checksum of the TCP/UDP pseudo-header -+ * returns a 16-bit checksum, already complemented -+ */ -+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, -+ unsigned long daddr, -+ unsigned short len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -+} -+ -+/* -+ * this routine is used for miscellaneous IP-like checksums, mainly -+ * in icmp.c -+ */ -+ -+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) -+{ -+ return csum_fold (csum_partial(buff, len, 0)); -+} -+ -+#define _HAVE_ARCH_IPV6_CSUM -+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr, -+ struct in6_addr *daddr, -+ __u32 len, -+ unsigned short proto, -+ unsigned int sum) -+{ -+ __asm__( -+ "addl 0(%1), %0 ;\n" -+ "adcl 4(%1), %0 ;\n" -+ "adcl 8(%1), %0 ;\n" -+ "adcl 12(%1), %0 ;\n" -+ "adcl 0(%2), %0 ;\n" -+ "adcl 4(%2), %0 ;\n" -+ "adcl 8(%2), %0 ;\n" -+ "adcl 12(%2), %0 ;\n" -+ "adcl %3, %0 ;\n" -+ "adcl %4, %0 ;\n" -+ "adcl $0, %0 ;\n" -+ : "=&r" (sum) -+ : "r" (saddr), "r" (daddr), -+ "r"(htonl(len)), "r"(htonl(proto)), "0"(sum)); -+ -+ return csum_fold(sum); -+} -+ -+/* -+ * Copy and checksum to user -+ */ -+#define HAVE_CSUM_COPY_USER -+static __inline__ unsigned int csum_and_copy_to_user(const char *src, -+ char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if (access_ok(VERIFY_WRITE, dst, len)) -+ return(csum_partial_copy_to(src, dst, len, sum, err_ptr)); -+ -+ if (len) -+ *err_ptr = -EFAULT; -+ -+ return -1; /* invalid checksum */ -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/frame.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/frame.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/frame.h 2005-05-03 22:28:14.351428464 +0300 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_I386_H -+#define __FRAME_I386_H -+ -+struct arch_frame_data_raw { -+ unsigned long fp_start; -+ unsigned long sr; -+}; -+ -+struct arch_frame_data { -+ int fpstate_size; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/frame_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/frame_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/frame_kern.h 2005-05-03 22:28:14.352428312 +0300 -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_KERN_I386_H -+#define __FRAME_KERN_I386_H -+ -+/* This is called from sys_sigreturn. It takes the sp at the point of the -+ * sigreturn system call and returns the address of the sigcontext struct -+ * on the stack. -+ */ -+ -+static inline void *sp_to_sc(unsigned long sp) -+{ -+ return((void *) sp); -+} -+ -+static inline void *sp_to_uc(unsigned long sp) -+{ -+ unsigned long uc; -+ -+ uc = sp + signal_frame_si.uc_index - -+ signal_frame_si.common.sp_index - 4; -+ return((void *) uc); -+} -+ -+static inline void *sp_to_rt_sc(unsigned long sp) -+{ -+ unsigned long sc; -+ -+ sc = sp - signal_frame_si.common.sp_index + -+ signal_frame_si.common.len - 4; -+ return((void *) sc); -+} -+ -+static inline void *sp_to_mask(unsigned long sp) -+{ -+ unsigned long mask; -+ -+ mask = sp - signal_frame_sc.common.sp_index + -+ signal_frame_sc.common.len - 8; -+ return((void *) mask); -+} -+ -+extern int sc_size(void *data); -+ -+static inline void *sp_to_rt_mask(unsigned long sp) -+{ -+ unsigned long mask; -+ -+ mask = sp - signal_frame_si.common.sp_index + -+ signal_frame_si.common.len + -+ sc_size(&signal_frame_si.common.arch) - 4; -+ return((void *) mask); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/frame_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/frame_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/frame_user.h 2005-05-03 22:28:14.353428160 +0300 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __FRAME_USER_I386_H -+#define __FRAME_USER_I386_H -+ -+#include <asm/page.h> -+#include "sysdep/frame.h" -+ -+/* This stuff is to calculate the size of the fp state struct at runtime -+ * because it has changed between 2.2 and 2.4 and it would be good for a -+ * UML compiled on one to work on the other. -+ * So, setup_arch_frame_raw fills in the arch struct with the raw data, which -+ * just contains the address of the end of the sigcontext. This is invoked -+ * from the signal handler. -+ * setup_arch_frame uses that data to figure out what -+ * arch_frame_data.fpstate_size should be. It really has no idea, since it's -+ * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's -+ * everything from the end of the sigcontext up to the top of the stack. So, -+ * it masks off the page number to get the offset within the page and subtracts -+ * that from the page size, and that's how big the fpstate struct will be -+ * considered to be. -+ */ -+ -+static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data, -+ void *end, unsigned long srp) -+{ -+ unsigned long sr = *((unsigned long *) srp); -+ -+ data->fp_start = (unsigned long) end; -+ if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK)) -+ data->sr = sr; -+ else data->sr = 0; -+} -+ -+static inline void setup_arch_frame(struct arch_frame_data_raw *in, -+ struct arch_frame_data *out) -+{ -+ unsigned long fpstate_start = in->fp_start; -+ -+ if(in->sr == 0){ -+ fpstate_start &= ~PAGE_MASK; -+ out->fpstate_size = PAGE_SIZE - fpstate_start; -+ } -+ else { -+ out->fpstate_size = in->sr - fpstate_start; -+ } -+} -+ -+/* This figures out where on the stack the SA_RESTORER function address -+ * is stored. For i386, it's the signal handler return address, so it's -+ * located next to the frame pointer. -+ * This is inlined, so __builtin_frame_address(0) is correct. Otherwise, -+ * it would have to be __builtin_frame_address(1). -+ */ -+ -+#define frame_restorer() \ -+({ \ -+ unsigned long *fp; \ -+\ -+ fp = __builtin_frame_address(0); \ -+ ((unsigned long) (fp + 1)); \ -+}) -+ -+/* Similarly, this returns the value of sp when the handler was first -+ * entered. This is used to calculate the proper sp when delivering -+ * signals. -+ */ -+ -+#define frame_sp() \ -+({ \ -+ unsigned long *fp; \ -+\ -+ fp = __builtin_frame_address(0); \ -+ ((unsigned long) (fp + 1)); \ -+}) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/ptrace.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/ptrace.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/ptrace.h 2005-05-03 22:28:14.355427856 +0300 -@@ -0,0 +1,193 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_I386_PTRACE_H -+#define __SYSDEP_I386_PTRACE_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "ptrace-tt.h" -+#endif -+ -+#ifdef UML_CONFIG_MODE_SKAS -+#include "ptrace-skas.h" -+#endif -+ -+#include "choose-mode.h" -+ -+union uml_pt_regs { -+#ifdef UML_CONFIG_MODE_TT -+ struct tt_regs { -+ long syscall; -+ void *sc; -+ } tt; -+#endif -+#ifdef UML_CONFIG_MODE_SKAS -+ struct skas_regs { -+ unsigned long regs[HOST_FRAME_SIZE]; -+ unsigned long fp[HOST_FP_SIZE]; -+ unsigned long xfp[HOST_XFP_SIZE]; -+ unsigned long fault_addr; -+ unsigned long fault_type; -+ unsigned long trap_type; -+ long syscall; -+ int is_user; -+ } skas; -+#endif -+}; -+ -+#define EMPTY_UML_PT_REGS { } -+ -+extern int mode_tt; -+ -+#define UPT_SC(r) ((r)->tt.sc) -+#define UPT_IP(r) \ -+ CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) -+#define UPT_SP(r) \ -+ CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs)) -+#define UPT_EFLAGS(r) \ -+ CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs)) -+#define UPT_EAX(r) \ -+ CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs)) -+#define UPT_EBX(r) \ -+ CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs)) -+#define UPT_ECX(r) \ -+ CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs)) -+#define UPT_EDX(r) \ -+ CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs)) -+#define UPT_ESI(r) \ -+ CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs)) -+#define UPT_EDI(r) \ -+ CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs)) -+#define UPT_EBP(r) \ -+ CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs)) -+#define UPT_ORIG_EAX(r) \ -+ CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) -+#define UPT_CS(r) \ -+ CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs)) -+#define UPT_SS(r) \ -+ CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs)) -+#define UPT_DS(r) \ -+ CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs)) -+#define UPT_ES(r) \ -+ CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs)) -+#define UPT_FS(r) \ -+ CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs)) -+#define UPT_GS(r) \ -+ CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs)) -+ -+#define UPT_SYSCALL_ARG1(r) UPT_EBX(r) -+#define UPT_SYSCALL_ARG2(r) UPT_ECX(r) -+#define UPT_SYSCALL_ARG3(r) UPT_EDX(r) -+#define UPT_SYSCALL_ARG4(r) UPT_ESI(r) -+#define UPT_SYSCALL_ARG5(r) UPT_EDI(r) -+#define UPT_SYSCALL_ARG6(r) UPT_EBP(r) -+ -+extern int user_context(unsigned long sp); -+ -+#define UPT_IS_USER(r) \ -+ CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) -+ -+struct syscall_args { -+ unsigned long args[6]; -+}; -+ -+#define SYSCALL_ARGS(r) ((struct syscall_args) \ -+ { .args = { UPT_SYSCALL_ARG1(r), \ -+ UPT_SYSCALL_ARG2(r), \ -+ UPT_SYSCALL_ARG3(r), \ -+ UPT_SYSCALL_ARG4(r), \ -+ UPT_SYSCALL_ARG5(r), \ -+ UPT_SYSCALL_ARG6(r) } } ) -+ -+#define UPT_REG(regs, reg) \ -+ ({ unsigned long val; \ -+ switch(reg){ \ -+ case EIP: val = UPT_IP(regs); break; \ -+ case UESP: val = UPT_SP(regs); break; \ -+ case EAX: val = UPT_EAX(regs); break; \ -+ case EBX: val = UPT_EBX(regs); break; \ -+ case ECX: val = UPT_ECX(regs); break; \ -+ case EDX: val = UPT_EDX(regs); break; \ -+ case ESI: val = UPT_ESI(regs); break; \ -+ case EDI: val = UPT_EDI(regs); break; \ -+ case EBP: val = UPT_EBP(regs); break; \ -+ case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \ -+ case CS: val = UPT_CS(regs); break; \ -+ case SS: val = UPT_SS(regs); break; \ -+ case DS: val = UPT_DS(regs); break; \ -+ case ES: val = UPT_ES(regs); break; \ -+ case FS: val = UPT_FS(regs); break; \ -+ case GS: val = UPT_GS(regs); break; \ -+ case EFL: val = UPT_EFLAGS(regs); break; \ -+ default : \ -+ panic("Bad register in UPT_REG : %d\n", reg); \ -+ val = -1; \ -+ } \ -+ val; \ -+ }) -+ -+ -+#define UPT_SET(regs, reg, val) \ -+ do { \ -+ switch(reg){ \ -+ case EIP: UPT_IP(regs) = val; break; \ -+ case UESP: UPT_SP(regs) = val; break; \ -+ case EAX: UPT_EAX(regs) = val; break; \ -+ case EBX: UPT_EBX(regs) = val; break; \ -+ case ECX: UPT_ECX(regs) = val; break; \ -+ case EDX: UPT_EDX(regs) = val; break; \ -+ case ESI: UPT_ESI(regs) = val; break; \ -+ case EDI: UPT_EDI(regs) = val; break; \ -+ case EBP: UPT_EBP(regs) = val; break; \ -+ case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \ -+ case CS: UPT_CS(regs) = val; break; \ -+ case SS: UPT_SS(regs) = val; break; \ -+ case DS: UPT_DS(regs) = val; break; \ -+ case ES: UPT_ES(regs) = val; break; \ -+ case FS: UPT_FS(regs) = val; break; \ -+ case GS: UPT_GS(regs) = val; break; \ -+ case EFL: UPT_EFLAGS(regs) = val; break; \ -+ default : \ -+ panic("Bad register in UPT_SET : %d\n", reg); \ -+ break; \ -+ } \ -+ } while (0) -+ -+#define UPT_SET_SYSCALL_RETURN(r, res) \ -+ CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ -+ REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) -+ -+#define UPT_RESTART_SYSCALL(r) \ -+ CHOOSE_MODE(SC_RESTART_SYSCALL(UPT_SC(r)), \ -+ REGS_RESTART_SYSCALL((r)->skas.regs)) -+ -+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r) -+#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) -+#define UPT_SYSCALL_RET(r) UPT_EAX(r) -+ -+#define UPT_SEGV_IS_FIXABLE(r) \ -+ CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \ -+ REGS_SEGV_IS_FIXABLE(&r->skas)) -+ -+#define UPT_FAULT_ADDR(r) \ -+ CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas)) -+ -+#define UPT_FAULT_WRITE(r) \ -+ CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas)) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/ptrace_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/ptrace_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/ptrace_user.h 2005-05-03 22:28:14.356427704 +0300 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_I386_PTRACE_USER_H__ -+#define __SYSDEP_I386_PTRACE_USER_H__ -+ -+#include <asm/ptrace.h> -+ -+#define PT_OFFSET(r) ((r) * sizeof(long)) -+ -+#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX]) -+#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX) -+ -+#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX) -+#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX) -+#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX) -+#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI) -+#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI) -+ -+#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX) -+ -+#define PT_IP_OFFSET PT_OFFSET(EIP) -+#define PT_IP(regs) ((regs)[EIP]) -+#define PT_SP(regs) ((regs)[UESP]) -+ -+#ifndef FRAME_SIZE -+#define FRAME_SIZE (17) -+#endif -+#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long)) -+ -+#define FP_FRAME_SIZE (27) -+#define FPX_FRAME_SIZE (128) -+ -+#ifdef PTRACE_GETREGS -+#define UM_HAVE_GETREGS -+#endif -+ -+#ifdef PTRACE_SETREGS -+#define UM_HAVE_SETREGS -+#endif -+ -+#ifdef PTRACE_GETFPREGS -+#define UM_HAVE_GETFPREGS -+#endif -+ -+#ifdef PTRACE_SETFPREGS -+#define UM_HAVE_SETFPREGS -+#endif -+ -+#ifdef PTRACE_GETFPXREGS -+#define UM_HAVE_GETFPXREGS -+#endif -+ -+#ifdef PTRACE_SETFPXREGS -+#define UM_HAVE_SETFPXREGS -+#endif -+ -+extern void update_debugregs(int seq); -+ -+#endif -Index: linux-2.4.29/arch/um/include/sysdep-i386/sigcontext.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/sigcontext.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/sigcontext.h 2005-05-03 22:28:14.357427552 +0300 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_SIGCONTEXT_I386_H -+#define __SYS_SIGCONTEXT_I386_H -+ -+#include "sc.h" -+ -+#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -+ -+#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) -+#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result) -+ -+#define SC_FAULT_ADDR(sc) SC_CR2(sc) -+#define SC_FAULT_TYPE(sc) SC_ERR(sc) -+ -+#define FAULT_WRITE(err) (err & 2) -+#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0) -+ -+#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc))) -+ -+#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc) -+ -+/* ptrace expects that, at the start of a system call, %eax contains -+ * -ENOSYS, so this makes it so. -+ */ -+#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) -+ -+/* This is Page Fault */ -+#define SEGV_IS_FIXABLE(trap) (trap == 14) -+ -+#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc))) -+ -+extern unsigned long *sc_sigmask(void *sc_ptr); -+extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-i386/syscalls.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-i386/syscalls.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-i386/syscalls.h 2005-05-03 22:28:14.358427400 +0300 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/unistd.h" -+#include "sysdep/ptrace.h" -+ -+typedef long syscall_handler_t(struct pt_regs); -+ -+#define EXECUTE_SYSCALL(syscall, regs) \ -+ ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) -+ -+extern syscall_handler_t sys_modify_ldt; -+extern syscall_handler_t old_mmap_i386; -+extern syscall_handler_t old_select; -+extern syscall_handler_t sys_ni_syscall; -+ -+#define ARCH_SYSCALLS \ -+ [ __NR_mmap ] = old_mmap_i386, \ -+ [ __NR_select ] = old_select, \ -+ [ __NR_vm86old ] = sys_ni_syscall, \ -+ [ __NR_modify_ldt ] = sys_modify_ldt, \ -+ [ __NR_lchown32 ] = sys_lchown, \ -+ [ __NR_getuid32 ] = sys_getuid, \ -+ [ __NR_getgid32 ] = sys_getgid, \ -+ [ __NR_geteuid32 ] = sys_geteuid, \ -+ [ __NR_getegid32 ] = sys_getegid, \ -+ [ __NR_setreuid32 ] = sys_setreuid, \ -+ [ __NR_setregid32 ] = sys_setregid, \ -+ [ __NR_getgroups32 ] = sys_getgroups, \ -+ [ __NR_setgroups32 ] = sys_setgroups, \ -+ [ __NR_fchown32 ] = sys_fchown, \ -+ [ __NR_setresuid32 ] = sys_setresuid, \ -+ [ __NR_getresuid32 ] = sys_getresuid, \ -+ [ __NR_setresgid32 ] = sys_setresgid, \ -+ [ __NR_getresgid32 ] = sys_getresgid, \ -+ [ __NR_chown32 ] = sys_chown, \ -+ [ __NR_setuid32 ] = sys_setuid, \ -+ [ __NR_setgid32 ] = sys_setgid, \ -+ [ __NR_setfsuid32 ] = sys_setfsuid, \ -+ [ __NR_setfsgid32 ] = sys_setfsgid, \ -+ [ __NR_pivot_root ] = sys_pivot_root, \ -+ [ __NR_mincore ] = sys_mincore, \ -+ [ __NR_madvise ] = sys_madvise, \ -+ [ 222 ] = sys_ni_syscall, -+ -+/* 222 doesn't yet have a name in include/asm-i386/unistd.h */ -+ -+#define LAST_ARCH_SYSCALL 222 -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-ia64/ptrace.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-ia64/ptrace.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-ia64/ptrace.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_PTRACE_H -+#define __SYSDEP_IA64_PTRACE_H -+ -+struct sys_pt_regs { -+ int foo; -+}; -+ -+#define EMPTY_REGS { 0 } -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-ia64/sigcontext.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-ia64/sigcontext.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-ia64/sigcontext.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_SIGCONTEXT_H -+#define __SYSDEP_IA64_SIGCONTEXT_H -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-ia64/syscalls.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-ia64/syscalls.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-ia64/syscalls.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYSDEP_IA64_SYSCALLS_H -+#define __SYSDEP_IA64_SYSCALLS_H -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-ppc/ptrace.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-ppc/ptrace.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-ppc/ptrace.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,104 @@ -+/* -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_PTRACE_PPC_H -+#define __SYS_PTRACE_PPC_H -+ -+#include "linux/config.h" -+#include "linux/types.h" -+ -+/* the following taken from <asm-ppc/ptrace.h> */ -+ -+#ifdef CONFIG_PPC64 -+#define PPC_REG unsigned long /*long*/ -+#else -+#define PPC_REG unsigned long -+#endif -+struct sys_pt_regs_s { -+ PPC_REG gpr[32]; -+ PPC_REG nip; -+ PPC_REG msr; -+ PPC_REG orig_gpr3; /* Used for restarting system calls */ -+ PPC_REG ctr; -+ PPC_REG link; -+ PPC_REG xer; -+ PPC_REG ccr; -+ PPC_REG mq; /* 601 only (not used at present) */ -+ /* Used on APUS to hold IPL value. */ -+ PPC_REG trap; /* Reason for being here */ -+ PPC_REG dar; /* Fault registers */ -+ PPC_REG dsisr; -+ PPC_REG result; /* Result of a system call */ -+}; -+ -+#define NUM_REGS (sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)) -+ -+struct sys_pt_regs { -+ PPC_REG regs[sizeof(struct sys_pt_regs_s) / sizeof(PPC_REG)]; -+}; -+ -+#define UM_MAX_REG (PT_FPR0) -+#define UM_MAX_REG_OFFSET (UM_MAX_REG * sizeof(PPC_REG)) -+ -+#define EMPTY_REGS { { [ 0 ... NUM_REGS - 1] = 0 } } -+ -+#define UM_REG(r, n) ((r)->regs[n]) -+ -+#define UM_SYSCALL_RET(r) UM_REG(r, PT_R3) -+#define UM_SP(r) UM_REG(r, PT_R1) -+#define UM_IP(r) UM_REG(r, PT_NIP) -+#define UM_ELF_ZERO(r) UM_REG(r, PT_FPSCR) -+#define UM_SYSCALL_NR(r) UM_REG(r, PT_R0) -+#define UM_SYSCALL_ARG1(r) UM_REG(r, PT_ORIG_R3) -+#define UM_SYSCALL_ARG2(r) UM_REG(r, PT_R4) -+#define UM_SYSCALL_ARG3(r) UM_REG(r, PT_R5) -+#define UM_SYSCALL_ARG4(r) UM_REG(r, PT_R6) -+#define UM_SYSCALL_ARG5(r) UM_REG(r, PT_R7) -+#define UM_SYSCALL_ARG6(r) UM_REG(r, PT_R8) -+ -+#define UM_SYSCALL_NR_OFFSET (PT_R0 * sizeof(PPC_REG)) -+#define UM_SYSCALL_RET_OFFSET (PT_R3 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG1_OFFSET (PT_R3 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG2_OFFSET (PT_R4 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG3_OFFSET (PT_R5 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG4_OFFSET (PT_R6 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG5_OFFSET (PT_R7 * sizeof(PPC_REG)) -+#define UM_SYSCALL_ARG6_OFFSET (PT_R8 * sizeof(PPC_REG)) -+#define UM_SP_OFFSET (PT_R1 * sizeof(PPC_REG)) -+#define UM_IP_OFFSET (PT_NIP * sizeof(PPC_REG)) -+#define UM_ELF_ZERO_OFFSET (PT_R3 * sizeof(PPC_REG)) -+ -+#define UM_SET_SYSCALL_RETURN(_regs, result) \ -+do { \ -+ if (result < 0) { \ -+ (_regs)->regs[PT_CCR] |= 0x10000000; \ -+ UM_SYSCALL_RET((_regs)) = -result; \ -+ } else { \ -+ UM_SYSCALL_RET((_regs)) = result; \ -+ } \ -+} while(0) -+ -+extern void shove_aux_table(unsigned long sp); -+#define UM_FIX_EXEC_STACK(sp) shove_aux_table(sp); -+ -+/* These aren't actually defined. The undefs are just to make sure -+ * everyone's clear on the concept. -+ */ -+#undef UML_HAVE_GETREGS -+#undef UML_HAVE_GETFPREGS -+#undef UML_HAVE_SETREGS -+#undef UML_HAVE_SETFPREGS -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-ppc/sigcontext.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-ppc/sigcontext.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-ppc/sigcontext.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SYS_SIGCONTEXT_PPC_H -+#define __SYS_SIGCONTEXT_PPC_H -+ -+#define DSISR_WRITE 0x02000000 -+ -+#define SC_FAULT_ADDR(sc) ({ \ -+ struct sigcontext *_sc = (sc); \ -+ long retval = -1; \ -+ switch (_sc->regs->trap) { \ -+ case 0x300: \ -+ /* data exception */ \ -+ retval = _sc->regs->dar; \ -+ break; \ -+ case 0x400: \ -+ /* instruction exception */ \ -+ retval = _sc->regs->nip; \ -+ break; \ -+ default: \ -+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \ -+ } \ -+ retval; \ -+ }) -+ -+#define SC_FAULT_WRITE(sc) ({ \ -+ struct sigcontext *_sc = (sc); \ -+ long retval = -1; \ -+ switch (_sc->regs->trap) { \ -+ case 0x300: \ -+ /* data exception */ \ -+ retval = !!(_sc->regs->dsisr & DSISR_WRITE); \ -+ break; \ -+ case 0x400: \ -+ /* instruction exception: not a write */ \ -+ retval = 0; \ -+ break; \ -+ default: \ -+ panic("SC_FAULT_ADDR: unhandled trap type\n"); \ -+ } \ -+ retval; \ -+ }) -+ -+#define SC_IP(sc) ((sc)->regs->nip) -+#define SC_SP(sc) ((sc)->regs->gpr[1]) -+#define SEGV_IS_FIXABLE(sc) (1) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysdep-ppc/syscalls.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysdep-ppc/syscalls.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysdep-ppc/syscalls.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+typedef long syscall_handler_t(unsigned long arg1, unsigned long arg2, -+ unsigned long arg3, unsigned long arg4, -+ unsigned long arg5, unsigned long arg6); -+ -+#define EXECUTE_SYSCALL(syscall, regs) \ -+ (*sys_call_table[syscall])(UM_SYSCALL_ARG1(®s), \ -+ UM_SYSCALL_ARG2(®s), \ -+ UM_SYSCALL_ARG3(®s), \ -+ UM_SYSCALL_ARG4(®s), \ -+ UM_SYSCALL_ARG5(®s), \ -+ UM_SYSCALL_ARG6(®s)) -+ -+extern syscall_handler_t sys_mincore; -+extern syscall_handler_t sys_madvise; -+ -+/* old_mmap needs the correct prototype since syscall_kern.c includes -+ * this file. -+ */ -+int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset); -+ -+#define ARCH_SYSCALLS \ -+ [ __NR_modify_ldt ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_read ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_write ] = sys_ni_syscall, \ -+ [ __NR_pciconfig_iobase ] = sys_ni_syscall, \ -+ [ __NR_pivot_root ] = sys_ni_syscall, \ -+ [ __NR_multiplexer ] = sys_ni_syscall, \ -+ [ __NR_mmap ] = old_mmap, \ -+ [ __NR_madvise ] = sys_madvise, \ -+ [ __NR_mincore ] = sys_mincore, -+ -+#define LAST_ARCH_SYSCALL __NR_mincore -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/sysrq.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/sysrq.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/sysrq.h 2005-05-03 22:28:14.364426488 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SYSRQ_H -+#define __UM_SYSRQ_H -+ -+extern void show_trace(unsigned long *stack); -+ -+#endif -Index: linux-2.4.29/arch/um/include/tempfile.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/tempfile.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/tempfile.h 2005-05-03 22:28:14.365426336 +0300 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TEMPFILE_H__ -+#define __TEMPFILE_H__ -+ -+extern int make_tempfile(const char *template, char **tempname, int do_unlink); -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/time_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/time_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/time_user.h 2005-05-03 22:28:14.366426184 +0300 -@@ -0,0 +1,18 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TIME_USER_H__ -+#define __TIME_USER_H__ -+ -+extern void timer(void); -+extern void switch_timers(int to_real); -+extern void set_interval(int timer_type); -+extern void idle_sleep(int secs); -+extern void enable_timer(void); -+extern void disable_timer(void); -+extern unsigned long time_lock(void); -+extern void time_unlock(unsigned long); -+ -+#endif -Index: linux-2.4.29/arch/um/include/tlb.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/tlb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/tlb.h 2005-05-03 22:28:14.367426032 +0300 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TLB_H__ -+#define __TLB_H__ -+ -+extern void mprotect_kernel_vm(int w); -+extern void force_flush_all(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/ubd_user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/ubd_user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/ubd_user.h 2005-05-03 22:28:14.368425880 +0300 -@@ -0,0 +1,79 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_UBD_USER_H -+#define __UM_UBD_USER_H -+ -+#include "os.h" -+ -+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; -+ -+struct io_thread_req { -+ enum ubd_req op; -+ int fds[2]; -+ unsigned long offsets[2]; -+ unsigned long long offset; -+ unsigned long length; -+ char *buffer; -+ int sectorsize; -+ unsigned long sector_mask; -+ unsigned long long cow_offset; -+ unsigned long bitmap_words[2]; -+ int map_fd; -+ unsigned long long map_offset; -+ int error; -+}; -+ -+extern int open_ubd_file(char *file, struct openflags *openflags, -+ char **backing_file_out, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, int *data_offset_out, -+ int *create_cow_out); -+extern int create_cow_file(char *cow_file, char *backing_file, -+ struct openflags flags, int sectorsize, -+ int alignment, int *bitmap_offset_out, -+ unsigned long *bitmap_len_out, -+ int *data_offset_out); -+extern int read_cow_bitmap(int fd, void *buf, int offset, int len); -+extern int read_ubd_fs(int fd, void *buffer, int len); -+extern int write_ubd_fs(int fd, char *buffer, int len); -+extern int start_io_thread(unsigned long sp, int *fds_out); -+extern void do_io(struct io_thread_req *req); -+ -+static inline int ubd_test_bit(__u64 bit, unsigned char *data) -+{ -+ __u64 n; -+ int bits, off; -+ -+ bits = sizeof(data[0]) * 8; -+ n = bit / bits; -+ off = bit % bits; -+ return((data[n] & (1 << off)) != 0); -+} -+ -+static inline void ubd_set_bit(__u64 bit, unsigned char *data) -+{ -+ __u64 n; -+ int bits, off; -+ -+ bits = sizeof(data[0]) * 8; -+ n = bit / bits; -+ off = bit % bits; -+ data[n] |= (1 << off); -+} -+ -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/umid.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/umid.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/umid.h 2005-05-03 22:28:14.368425880 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UMID_H__ -+#define __UMID_H__ -+ -+extern int umid_file_name(char *name, char *buf, int len); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/uml_uaccess.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/uml_uaccess.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/uml_uaccess.h 2005-05-03 22:28:14.369425728 +0300 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UML_UACCESS_H__ -+#define __UML_UACCESS_H__ -+ -+extern int __do_copy_to_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher); -+extern unsigned long __do_user_copy(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher, -+ void (*op)(void *to, const void *from, -+ int n), int *faulted_out); -+void __do_copy(void *to, const void *from, int n); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/um_mmu.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/um_mmu.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/um_mmu.h 2005-05-03 22:28:14.370425576 +0300 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __ARCH_UM_MMU_H -+#define __ARCH_UM_MMU_H -+ -+#include "linux/config.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/mmu.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/mmu.h" -+#endif -+ -+typedef union { -+#ifdef CONFIG_MODE_TT -+ struct mmu_context_tt tt; -+#endif -+#ifdef CONFIG_MODE_SKAS -+ struct mmu_context_skas skas; -+#endif -+} mm_context_t; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/umn.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/umn.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/umn.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UMN_H -+#define __UMN_H -+ -+extern int open_umn_tty(int *slave_out, int *slipno_out); -+extern void close_umn_tty(int master, int slave); -+extern int umn_send_packet(int fd, void *data, int len); -+extern int set_umn_addr(int fd, char *addr, char *ptp_addr); -+extern void slip_unesc(unsigned char s); -+extern void umn_read(int fd); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/um_uaccess.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/um_uaccess.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/um_uaccess.h 2005-05-03 22:28:14.372425272 +0300 -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __ARCH_UM_UACCESS_H -+#define __ARCH_UM_UACCESS_H -+ -+#include "linux/config.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_MODE_TT -+#include "../kernel/tt/include/uaccess.h" -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+#include "../kernel/skas/include/uaccess.h" -+#endif -+ -+#define access_ok(type, addr, size) \ -+ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size) -+ -+static inline int verify_area(int type, const void * addr, unsigned long size) -+{ -+ return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr, -+ size)); -+} -+ -+static inline int copy_from_user(void *to, const void *from, int n) -+{ -+ return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to, -+ from, n)); -+} -+ -+static inline int copy_to_user(void *to, const void *from, int n) -+{ -+ return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to, -+ from, n)); -+} -+ -+/* -+ * strncpy_from_user: - Copy a NUL terminated string from userspace. -+ * @dst: Destination address, in kernel space. This buffer must be at -+ * least @count bytes long. -+ * @src: Source address, in user space. -+ * @count: Maximum number of bytes to copy, including the trailing NUL. -+ * -+ * Copies a NUL-terminated string from userspace to kernel space. -+ * -+ * On success, returns the length of the string (not including the trailing -+ * NUL). -+ * -+ * If access to userspace fails, returns -EFAULT (some data may have been -+ * copied). -+ * -+ * If @count is smaller than the length of the string, copies @count bytes -+ * and returns @count. -+ */ -+ -+static inline int strncpy_from_user(char *dst, const char *src, int count) -+{ -+ return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, -+ dst, src, count)); -+} -+ -+/* -+ * __clear_user: - Zero a block of memory in user space, with less checking. -+ * @to: Destination address, in user space. -+ * @n: Number of bytes to zero. -+ * -+ * Zero a block of memory in user space. Caller must check -+ * the specified block with access_ok() before calling this function. -+ * -+ * Returns number of bytes that could not be cleared. -+ * On success, this will be zero. -+ */ -+static inline int __clear_user(void *mem, int len) -+{ -+ return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); -+} -+ -+/* -+ * clear_user: - Zero a block of memory in user space. -+ * @to: Destination address, in user space. -+ * @n: Number of bytes to zero. -+ * -+ * Zero a block of memory in user space. -+ * -+ * Returns number of bytes that could not be cleared. -+ * On success, this will be zero. -+ */ -+static inline int clear_user(void *mem, int len) -+{ -+ return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); -+} -+ -+/* -+ * strlen_user: - Get the size of a string in user space. -+ * @str: The string to measure. -+ * @n: The maximum valid length -+ * -+ * Get the size of a NUL-terminated string in user space. -+ * -+ * Returns the size of the string INCLUDING the terminating NUL. -+ * On exception, returns 0. -+ * If the string is too long, returns a value greater than @n. -+ */ -+static inline int strnlen_user(const void *str, int len) -+{ -+ return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/user.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/user.h 2005-05-03 22:28:14.373425120 +0300 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __USER_H__ -+#define __USER_H__ -+ -+extern void panic(const char *fmt, ...); -+extern int printk(const char *fmt, ...); -+extern void schedule(void); -+extern void *um_kmalloc(int size); -+extern void *um_kmalloc_atomic(int size); -+extern void kfree(void *ptr); -+extern int in_aton(char *str); -+extern int open_gdb_chan(void); -+extern void *um_vmalloc(int size); -+extern void vfree(void *ptr); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/include/user_util.h -=================================================================== ---- linux-2.4.29.orig/arch/um/include/user_util.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/include/user_util.h 2005-05-03 22:28:14.374424968 +0300 -@@ -0,0 +1,105 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __USER_UTIL_H__ -+#define __USER_UTIL_H__ -+ -+#include "sysdep/ptrace.h" -+ -+#define CATCH_EINTR(expr) while (((expr) < 0) && (errno == EINTR)) -+ -+extern int mode_tt; -+ -+extern int grantpt(int __fd); -+extern int unlockpt(int __fd); -+extern char *ptsname(int __fd); -+ -+struct cpu_task { -+ int pid; -+ void *task; -+}; -+ -+extern struct cpu_task cpu_tasks[]; -+ -+struct signal_info { -+ void (*handler)(int, union uml_pt_regs *); -+ int is_irq; -+}; -+ -+extern struct signal_info sig_info[]; -+ -+extern unsigned long low_physmem; -+extern unsigned long high_physmem; -+extern unsigned long uml_physmem; -+extern unsigned long uml_reserved; -+extern unsigned long end_vm; -+extern unsigned long start_vm; -+extern unsigned long highmem; -+ -+extern char host_info[]; -+ -+extern char saved_command_line[]; -+extern char command_line[]; -+ -+extern char *tempdir; -+ -+extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; -+extern unsigned long _unprotected_end; -+extern unsigned long brk_start; -+ -+extern int pty_output_sigio; -+extern int pty_close_sigio; -+ -+extern void stop(void); -+extern void stack_protections(unsigned long address); -+extern void task_protections(unsigned long address); -+extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); -+extern void *add_signal_handler(int sig, void (*handler)(int)); -+extern int start_fork_tramp(void *arg, unsigned long temp_stack, -+ int clone_flags, int (*tramp)(void *)); -+extern int linux_main(int argc, char **argv); -+extern void set_cmdline(char *cmd); -+extern void input_cb(void (*proc)(void *), void *arg, int arg_len); -+extern int get_pty(void); -+extern void *um_kmalloc(int size); -+extern int switcheroo(int fd, int prot, void *from, void *to, int size); -+extern void setup_machinename(char *machine_out); -+extern void setup_hostinfo(void); -+extern void add_arg(char *cmd_line, char *arg); -+extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); -+extern void init_new_thread_signals(int altstack); -+extern void do_exec(int old_pid, int new_pid); -+extern void tracer_panic(char *msg, ...); -+extern char *get_umid(int only_if_set); -+extern void do_longjmp(void *p, int val); -+extern int detach(int pid, int sig); -+extern int attach(int pid); -+extern void kill_child_dead(int pid); -+extern int cont(int pid); -+extern void check_ptrace(void); -+extern void check_sigio(void); -+extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); -+extern void write_sigio_workaround(void); -+extern void arch_check_bugs(void); -+extern int cpu_feature(char *what, char *buf, int len); -+extern int arch_handle_signal(int sig, union uml_pt_regs *regs); -+extern int arch_fixup(unsigned long address, void *sc_ptr); -+extern int can_do_skas(void); -+extern void arch_init_thread(void); -+extern int setjmp_wrapper(void (*proc)(void *, void *), ...); -+extern int raw(int fd); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/checksum.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/checksum.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/checksum.c 2005-05-03 22:28:14.375424816 +0300 -@@ -0,0 +1,42 @@ -+#include "asm/uaccess.h" -+#include "linux/errno.h" -+ -+extern unsigned int arch_csum_partial(const char *buff, int len, int sum); -+ -+extern unsigned int csum_partial(char *buff, int len, int sum) -+{ -+ return(arch_csum_partial(buff, len, sum)); -+} -+ -+unsigned int csum_partial_copy_to(const char *src, char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if(copy_to_user(dst, src, len)){ -+ *err_ptr = -EFAULT; -+ return(-1); -+ } -+ -+ return(arch_csum_partial(src, len, sum)); -+} -+ -+unsigned int csum_partial_copy_from(const char *src, char *dst, int len, -+ int sum, int *err_ptr) -+{ -+ if(copy_from_user(dst, src, len)){ -+ *err_ptr = -EFAULT; -+ return(-1); -+ } -+ -+ return(arch_csum_partial(dst, len, sum)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/common.ld.in -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/common.ld.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/common.ld.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,53 @@ -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ .unprotected : { *(.unprotected) } -+ . = ALIGN(4096); -+ PROVIDE (_unprotected_end = .); -+ -+ . = ALIGN(4096); -+ __uml_setup_start = .; -+ .uml.setup.init : { *(.uml.setup.init) } -+ __uml_setup_end = .; -+ __uml_help_start = .; -+ .uml.help.init : { *(.uml.help.init) } -+ __uml_help_end = .; -+ __uml_postsetup_start = .; -+ .uml.postsetup.init : { *(.uml.postsetup.init) } -+ __uml_postsetup_end = .; -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ __uml_initcall_start = .; -+ .uml.initcall.init : { *(.uml.initcall.init) } -+ __uml_initcall_end = .; -+ __init_end = .; -+ __exitcall_begin = .; -+ .exitcall : { *(.exitcall.exit) } -+ __exitcall_end = .; -+ __uml_exitcall_begin = .; -+ .uml.exitcall : { *(.uml.exitcall.exit) } -+ __uml_exitcall_end = .; -+ -+ __preinit_array_start = .; -+ .preinit_array : { *(.preinit_array) } -+ __preinit_array_end = .; -+ __init_array_start = .; -+ .init_array : { *(.init_array) } -+ __init_array_end = .; -+ __fini_array_start = .; -+ .fini_array : { *(.fini_array) } -+ __fini_array_end = .; -+ -+ .data.init : { *(.data.init) } -Index: linux-2.4.29/arch/um/kernel/config.c.in -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/config.c.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/config.c.in 2005-05-03 22:28:14.406420104 +0300 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include "init.h" -+ -+static __initdata char *config = "CONFIG"; -+ -+static int __init print_config(char *line, int *add) -+{ -+ printf("%s", config); -+ exit(0); -+} -+ -+__uml_setup("--showconfig", print_config, -+"--showconfig\n" -+" Prints the config file that this UML binary was generated from.\n\n" -+); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/dyn_link.ld.in -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/dyn_link.ld.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/dyn_link.ld.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,169 @@ -+OUTPUT_FORMAT("ELF_FORMAT") -+OUTPUT_ARCH(ELF_ARCH) -+ENTRY(_start) -+ -+SECTIONS -+{ -+ . = START() + SIZEOF_HEADERS; -+ .interp : { *(.interp) } -+ __binary_start = .; -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ -+ . = ALIGN(4096); -+ -+ /* Read-only sections, merged into text segment: */ -+ .hash : { *(.hash) } -+ .dynsym : { *(.dynsym) } -+ .dynstr : { *(.dynstr) } -+ .gnu.version : { *(.gnu.version) } -+ .gnu.version_d : { *(.gnu.version_d) } -+ .gnu.version_r : { *(.gnu.version_r) } -+ .rel.init : { *(.rel.init) } -+ .rela.init : { *(.rela.init) } -+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } -+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } -+ .rel.fini : { *(.rel.fini) } -+ .rela.fini : { *(.rela.fini) } -+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } -+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } -+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } -+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } -+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } -+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } -+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } -+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } -+ .rel.ctors : { *(.rel.ctors) } -+ .rela.ctors : { *(.rela.ctors) } -+ .rel.dtors : { *(.rel.dtors) } -+ .rela.dtors : { *(.rela.dtors) } -+ .rel.got : { *(.rel.got) } -+ .rela.got : { *(.rela.got) } -+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } -+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } -+ .rel.plt : { *(.rel.plt) } -+ .rela.plt : { *(.rela.plt) } -+ .init : { -+ KEEP (*(.init)) -+ } =0x90909090 -+ .plt : { *(.plt) } -+ .text : { -+ *(.text .stub .text.* .gnu.linkonce.t.*) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ } =0x90909090 -+ .fini : { -+ KEEP (*(.fini)) -+ } =0x90909090 -+ -+ PROVIDE (__etext = .); -+ PROVIDE (_etext = .); -+ PROVIDE (etext = .); -+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } -+ .rodata1 : { *(.rodata1) } -+ .eh_frame_hdr : { *(.eh_frame_hdr) } -+ -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+include(`arch/um/kernel/common.ld.in') -+ -+ /* Ensure the __preinit_array_start label is properly aligned. We -+ could instead move the label definition inside the section, but -+ the linker would then create the section even if it turns out to -+ be empty, which isn't pretty. */ -+ . = ALIGN(32 / 8); -+ .preinit_array : { *(.preinit_array) } -+ .init_array : { *(.init_array) } -+ .fini_array : { *(.fini_array) } -+ .data : { -+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ -+ *(.data.init_task) -+ *(.data .data.* .gnu.linkonce.d.*) -+ SORT(CONSTRUCTORS) -+ } -+ .data1 : { *(.data1) } -+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } -+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } -+ .eh_frame : { KEEP (*(.eh_frame)) } -+ .gcc_except_table : { *(.gcc_except_table) } -+ .dynamic : { *(.dynamic) } -+ .ctors : { -+ /* gcc uses crtbegin.o to find the start of -+ the constructors, so we make sure it is -+ first. Because this is a wildcard, it -+ doesn't matter if the user does not -+ actually link against crtbegin.o; the -+ linker won't look for a file to match a -+ wildcard. The wildcard also means that it -+ doesn't matter which directory crtbegin.o -+ is in. */ -+ KEEP (*crtbegin.o(.ctors)) -+ /* We don't want to include the .ctor section from -+ from the crtend.o file until after the sorted ctors. -+ The .ctor section from the crtend file contains the -+ end of ctors marker and it must be last */ -+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) -+ KEEP (*(SORT(.ctors.*))) -+ KEEP (*(.ctors)) -+ } -+ .dtors : { -+ KEEP (*crtbegin.o(.dtors)) -+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) -+ KEEP (*(SORT(.dtors.*))) -+ KEEP (*(.dtors)) -+ } -+ .jcr : { KEEP (*(.jcr)) } -+ .got : { *(.got.plt) *(.got) } -+ _edata = .; -+ PROVIDE (edata = .); -+ __bss_start = .; -+ .bss : { -+ *(.dynbss) -+ *(.bss .bss.* .gnu.linkonce.b.*) -+ *(COMMON) -+ /* Align here to ensure that the .bss section occupies space up to -+ _end. Align after .bss to ensure correct alignment even if the -+ .bss section disappears because there are no input sections. */ -+ . = ALIGN(32 / 8); -+ . = ALIGN(32 / 8); -+ } -+ _end = .; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+ /* DWARF debug sections. -+ Symbols in the DWARF debugging sections are relative to the beginning -+ of the section so we begin them at 0. */ -+ /* DWARF 1 */ -+ .debug 0 : { *(.debug) } -+ .line 0 : { *(.line) } -+ /* GNU DWARF 1 extensions */ -+ .debug_srcinfo 0 : { *(.debug_srcinfo) } -+ .debug_sfnames 0 : { *(.debug_sfnames) } -+ /* DWARF 1.1 and DWARF 2 */ -+ .debug_aranges 0 : { *(.debug_aranges) } -+ .debug_pubnames 0 : { *(.debug_pubnames) } -+ /* DWARF 2 */ -+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } -+ .debug_abbrev 0 : { *(.debug_abbrev) } -+ .debug_line 0 : { *(.debug_line) } -+ .debug_frame 0 : { *(.debug_frame) } -+ .debug_str 0 : { *(.debug_str) } -+ .debug_loc 0 : { *(.debug_loc) } -+ .debug_macinfo 0 : { *(.debug_macinfo) } -+ /* SGI/MIPS DWARF 2 extensions */ -+ .debug_weaknames 0 : { *(.debug_weaknames) } -+ .debug_funcnames 0 : { *(.debug_funcnames) } -+ .debug_typenames 0 : { *(.debug_typenames) } -+ .debug_varnames 0 : { *(.debug_varnames) } -+} -Index: linux-2.4.29/arch/um/kernel/exec_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/exec_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/exec_kern.c 2005-05-03 22:28:14.408419800 +0300 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/slab.h" -+#include "linux/smp_lock.h" -+#include "asm/ptrace.h" -+#include "asm/pgtable.h" -+#include "asm/pgalloc.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "mem_user.h" -+#include "kern.h" -+#include "irq_user.h" -+#include "tlb.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "time_user.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+ -+void flush_thread(void) -+{ -+ CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); -+} -+ -+void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) -+{ -+ CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); -+} -+ -+extern void log_exec(char **argv, void *tty); -+ -+static int execve1(char *file, char **argv, char **env) -+{ -+ int error; -+ -+#ifdef CONFIG_TTY_LOG -+ log_exec(argv, current->tty); -+#endif -+ error = do_execve(file, argv, env, ¤t->thread.regs); -+ if (error == 0){ -+ current->ptrace &= ~PT_DTRACE; -+ set_cmdline(current_cmd()); -+ } -+ return(error); -+} -+ -+int um_execve(char *file, char **argv, char **env) -+{ -+ int err; -+ -+ err = execve1(file, argv, env); -+ if(!err) -+ do_longjmp(current->thread.exec_buf, 1); -+ return(err); -+} -+ -+int sys_execve(char *file, char **argv, char **env) -+{ -+ int error; -+ char *filename; -+ -+ lock_kernel(); -+ filename = getname((char *) file); -+ error = PTR_ERR(filename); -+ if (IS_ERR(filename)) goto out; -+ error = execve1(filename, argv, env); -+ putname(filename); -+ out: -+ unlock_kernel(); -+ return(error); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/exitcode.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/exitcode.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/exitcode.c 2005-05-03 22:28:14.409419648 +0300 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/ctype.h" -+#include "linux/proc_fs.h" -+#include "asm/uaccess.h" -+ -+/* If read and write race, the read will still atomically read a valid -+ * value. -+ */ -+int uml_exitcode = 0; -+ -+static int read_proc_exitcode(char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ int len; -+ -+ len = sprintf(page, "%d\n", uml_exitcode); -+ len -= off; -+ if(len <= off+count) *eof = 1; -+ *start = page + off; -+ if(len > count) len = count; -+ if(len < 0) len = 0; -+ return(len); -+} -+ -+static int write_proc_exitcode(struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ char *end, buf[sizeof("nnnnn\0")]; -+ int tmp; -+ -+ if(copy_from_user(buf, buffer, count)) -+ return(-EFAULT); -+ tmp = simple_strtol(buf, &end, 0); -+ if((*end != '\0') && !isspace(*end)) -+ return(-EINVAL); -+ uml_exitcode = tmp; -+ return(count); -+} -+ -+static int make_proc_exitcode(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ ent = create_proc_entry("exitcode", 0600, &proc_root); -+ if(ent == NULL){ -+ printk("make_proc_exitcode : Failed to register " -+ "/proc/exitcode\n"); -+ return(0); -+ } -+ -+ ent->read_proc = read_proc_exitcode; -+ ent->write_proc = write_proc_exitcode; -+ -+ return(0); -+} -+ -+__initcall(make_proc_exitcode); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/filehandle.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/filehandle.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/filehandle.c 2005-05-03 22:28:14.410419496 +0300 -@@ -0,0 +1,250 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/slab.h" -+#include "linux/list.h" -+#include "linux/spinlock.h" -+#include "linux/fs.h" -+#include "linux/errno.h" -+#include "filehandle.h" -+#include "os.h" -+#include "kern_util.h" -+ -+static spinlock_t open_files_lock = SPIN_LOCK_UNLOCKED; -+static struct list_head open_files = LIST_HEAD_INIT(open_files); -+ -+#define NUM_RECLAIM 128 -+ -+static void reclaim_fds(void) -+{ -+ struct file_handle *victim; -+ int closed = NUM_RECLAIM; -+ -+ spin_lock(&open_files_lock); -+ while(!list_empty(&open_files) && closed--){ -+ victim = list_entry(open_files.prev, struct file_handle, list); -+ os_close_file(victim->fd); -+ victim->fd = -1; -+ list_del_init(&victim->list); -+ } -+ spin_unlock(&open_files_lock); -+} -+ -+int open_file(char *name, struct openflags flags, int mode) -+{ -+ int fd; -+ -+ fd = os_open_file(name, flags, mode); -+ if(fd != -EMFILE) -+ return(fd); -+ -+ reclaim_fds(); -+ fd = os_open_file(name, flags, mode); -+ -+ return(fd); -+} -+ -+void *open_dir(char *file) -+{ -+ void *dir; -+ int err; -+ -+ dir = os_open_dir(file, &err); -+ if(dir != NULL) -+ return(dir); -+ if(err != -EMFILE) -+ return(ERR_PTR(err)); -+ -+ reclaim_fds(); -+ -+ dir = os_open_dir(file, &err); -+ if(dir == NULL) -+ dir = ERR_PTR(err); -+ -+ return(dir); -+} -+ -+void not_reclaimable(struct file_handle *fh) -+{ -+ char *name; -+ -+ if(fh->get_name == NULL) -+ return; -+ -+ if(list_empty(&fh->list)){ -+ name = (*fh->get_name)(fh->inode); -+ if(name != NULL){ -+ fh->fd = open_file(name, fh->flags, 0); -+ kfree(name); -+ } -+ else printk("File descriptor %d has no name\n", fh->fd); -+ } -+ else { -+ spin_lock(&open_files_lock); -+ list_del_init(&fh->list); -+ spin_unlock(&open_files_lock); -+ } -+} -+ -+void is_reclaimable(struct file_handle *fh, char *(name_proc)(struct inode *), -+ struct inode *inode) -+{ -+ fh->get_name = name_proc; -+ fh->inode = inode; -+ -+ spin_lock(&open_files_lock); -+ list_add(&fh->list, &open_files); -+ spin_unlock(&open_files_lock); -+} -+ -+static int active_handle(struct file_handle *fh) -+{ -+ int fd; -+ char *name; -+ -+ if(!list_empty(&fh->list)) -+ list_move(&fh->list, &open_files); -+ -+ if(fh->fd != -1) -+ return(0); -+ -+ if(fh->inode == NULL) -+ return(-ENOENT); -+ -+ name = (*fh->get_name)(fh->inode); -+ if(name == NULL) -+ return(-ENOMEM); -+ -+ fd = open_file(name, fh->flags, 0); -+ kfree(name); -+ if(fd < 0) -+ return(fd); -+ -+ fh->fd = fd; -+ is_reclaimable(fh, fh->get_name, fh->inode); -+ -+ return(0); -+} -+ -+int filehandle_fd(struct file_handle *fh) -+{ -+ int err; -+ -+ err = active_handle(fh); -+ if(err) -+ return(err); -+ -+ return(fh->fd); -+} -+ -+static void init_fh(struct file_handle *fh, int fd, struct openflags flags) -+{ -+ flags.c = 0; -+ *fh = ((struct file_handle) { .list = LIST_HEAD_INIT(fh->list), -+ .fd = fd, -+ .get_name = NULL, -+ .inode = NULL, -+ .flags = flags }); -+} -+ -+int open_filehandle(char *name, struct openflags flags, int mode, -+ struct file_handle *fh) -+{ -+ int fd; -+ -+ fd = open_file(name, flags, mode); -+ if(fd < 0) -+ return(fd); -+ -+ init_fh(fh, fd, flags); -+ return(0); -+} -+ -+int close_file(struct file_handle *fh) -+{ -+ spin_lock(&open_files_lock); -+ list_del(&fh->list); -+ spin_unlock(&open_files_lock); -+ -+ os_close_file(fh->fd); -+ -+ fh->fd = -1; -+ return(0); -+} -+ -+int read_file(struct file_handle *fh, unsigned long long offset, char *buf, -+ int len) -+{ -+ int err; -+ -+ err = active_handle(fh); -+ if(err) -+ return(err); -+ -+ err = os_seek_file(fh->fd, offset); -+ if(err) -+ return(err); -+ -+ return(os_read_file(fh->fd, buf, len)); -+} -+ -+int write_file(struct file_handle *fh, unsigned long long offset, -+ const char *buf, int len) -+{ -+ int err; -+ -+ err = active_handle(fh); -+ if(err) -+ return(err); -+ -+ if(offset != -1) -+ err = os_seek_file(fh->fd, offset); -+ if(err) -+ return(err); -+ -+ return(os_write_file(fh->fd, buf, len)); -+} -+ -+int truncate_file(struct file_handle *fh, unsigned long long size) -+{ -+ int err; -+ -+ err = active_handle(fh); -+ if(err) -+ return(err); -+ -+ return(os_truncate_fd(fh->fd, size)); -+} -+ -+int make_pipe(struct file_handle *fhs) -+{ -+ int fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err && (err != -EMFILE)) -+ return(err); -+ -+ if(err){ -+ reclaim_fds(); -+ err = os_pipe(fds, 1, 1); -+ } -+ if(err) -+ return(err); -+ -+ init_fh(&fhs[0], fds[0], OPENFLAGS()); -+ init_fh(&fhs[1], fds[1], OPENFLAGS()); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/frame.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/frame.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/frame.c 2005-05-03 22:28:14.412419192 +0300 -@@ -0,0 +1,343 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <signal.h> -+#include <wait.h> -+#include <sched.h> -+#include <errno.h> -+#include <sys/ptrace.h> -+#include <sys/syscall.h> -+#include <sys/mman.h> -+#include <asm/page.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+#include "frame_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "ptrace_user.h" -+#include "os.h" -+ -+static int capture_stack(int (*child)(void *arg), void *arg, void *sp, -+ unsigned long top, void **data_out) -+{ -+ unsigned long regs[FRAME_SIZE]; -+ int pid, status, n, len; -+ -+ /* Start the child as a thread */ -+ pid = clone(child, sp, CLONE_VM | SIGCHLD, arg); -+ if(pid < 0){ -+ printf("capture_stack : clone failed - errno = %d\n", errno); -+ exit(1); -+ } -+ -+ /* Wait for it to stop itself and continue it with a SIGUSR1 to force -+ * it into the signal handler. -+ */ -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ fprintf(stderr, "capture_stack : Expected SIGSTOP, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ if(ptrace(PTRACE_CONT, pid, 0, SIGUSR1) < 0){ -+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ /* Wait for it to stop itself again and grab its registers again. -+ * At this point, the handler has stuffed the addresses of -+ * sig, sc, and SA_RESTORER in raw. -+ */ -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ fprintf(stderr, "capture_stack : Expected SIGSTOP, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0){ -+ printf("capture_stack : PTRACE_GETREGS failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ /* It has outlived its usefulness, so continue it so it can exit */ -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0){ -+ printf("capture_stack : PTRACE_CONT failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ CATCH_EINTR(n = waitpid(pid, &status, 0)); -+ if(n < 0){ -+ printf("capture_stack : waitpid failed - errno = %d\n", errno); -+ exit(1); -+ } -+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){ -+ printf("capture_stack : Expected exit signal 9, " -+ "got status = 0x%x\n", status); -+ exit(1); -+ } -+ -+ /* The frame that we want is the top of the signal stack */ -+ -+ len = top - PT_SP(regs); -+ *data_out = malloc(len); -+ if(*data_out == NULL){ -+ printf("capture_stack : malloc failed - errno = %d\n", errno); -+ exit(1); -+ } -+ memcpy(*data_out, (void *) PT_SP(regs), len); -+ -+ return(len); -+} -+ -+struct common_raw { -+ void *stack; -+ int size; -+ unsigned long sig; -+ unsigned long sr; -+ unsigned long sp; -+ struct arch_frame_data_raw arch; -+}; -+ -+#define SA_RESTORER (0x04000000) -+ -+typedef unsigned long old_sigset_t; -+ -+struct old_sigaction { -+ __sighandler_t handler; -+ old_sigset_t sa_mask; -+ unsigned long sa_flags; -+ void (*sa_restorer)(void); -+}; -+ -+static void child_common(struct common_raw *common, sighandler_t handler, -+ int restorer, int flags) -+{ -+ stack_t ss = ((stack_t) { .ss_sp = common->stack, -+ .ss_flags = 0, -+ .ss_size = common->size }); -+ int err; -+ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ printf("PTRACE_TRACEME failed, errno = %d\n", errno); -+ } -+ if(sigaltstack(&ss, NULL) < 0){ -+ printf("sigaltstack failed - errno = %d\n", errno); -+ kill(getpid(), SIGKILL); -+ } -+ -+ if(restorer){ -+ struct sigaction sa; -+ -+ sa.sa_handler = handler; -+ sigemptyset(&sa.sa_mask); -+ sa.sa_flags = SA_ONSTACK | flags; -+ err = sigaction(SIGUSR1, &sa, NULL); -+ } -+ else { -+ struct old_sigaction sa; -+ -+ sa.handler = handler; -+ sa.sa_mask = 0; -+ sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER; -+ err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL); -+ } -+ -+ if(err < 0){ -+ printf("sigaction failed - errno = %d\n", errno); -+ kill(getpid(), SIGKILL); -+ } -+ -+ os_stop_process(os_getpid()); -+} -+ -+/* Changed only during early boot */ -+struct sc_frame signal_frame_sc; -+ -+struct sc_frame signal_frame_sc_sr; -+ -+struct sc_frame_raw { -+ struct common_raw common; -+ unsigned long sc; -+ int restorer; -+}; -+ -+/* Changed only during early boot */ -+static struct sc_frame_raw *raw_sc = NULL; -+ -+static void sc_handler(int sig, struct sigcontext sc) -+{ -+ raw_sc->common.sig = (unsigned long) &sig; -+ raw_sc->common.sr = frame_restorer(); -+ raw_sc->common.sp = frame_sp(); -+ raw_sc->sc = (unsigned long) ≻ -+ setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr); -+ -+ os_stop_process(os_getpid()); -+ kill(getpid(), SIGKILL); -+} -+ -+static int sc_child(void *arg) -+{ -+ raw_sc = arg; -+ child_common(&raw_sc->common, (sighandler_t) sc_handler, -+ raw_sc->restorer, 0); -+ return(-1); -+} -+ -+/* Changed only during early boot */ -+struct si_frame signal_frame_si; -+ -+struct si_frame_raw { -+ struct common_raw common; -+ unsigned long sip; -+ unsigned long si; -+ unsigned long ucp; -+ unsigned long uc; -+}; -+ -+/* Changed only during early boot */ -+static struct si_frame_raw *raw_si = NULL; -+ -+static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext) -+{ -+ raw_si->common.sig = (unsigned long) &sig; -+ raw_si->common.sr = frame_restorer(); -+ raw_si->common.sp = frame_sp(); -+ raw_si->sip = (unsigned long) &si; -+ raw_si->si = (unsigned long) si; -+ raw_si->ucp = (unsigned long) &ucontext; -+ raw_si->uc = (unsigned long) ucontext; -+ setup_arch_frame_raw(&raw_si->common.arch, -+ ucontext->uc_mcontext.fpregs, raw_si->common.sr); -+ -+ os_stop_process(os_getpid()); -+ kill(getpid(), SIGKILL); -+} -+ -+static int si_child(void *arg) -+{ -+ raw_si = arg; -+ child_common(&raw_si->common, (sighandler_t) si_handler, 1, -+ SA_SIGINFO); -+ return(-1); -+} -+ -+static int relative_sr(unsigned long sr, int sr_index, void *stack, -+ void *framep) -+{ -+ unsigned long *srp = (unsigned long *) sr; -+ unsigned long frame = (unsigned long) framep; -+ -+ if((*srp & PAGE_MASK) == (unsigned long) stack){ -+ *srp -= sr; -+ *((unsigned long *) (frame + sr_index)) = *srp; -+ return(1); -+ } -+ else return(0); -+} -+ -+static unsigned long capture_stack_common(int (*proc)(void *), void *arg, -+ struct common_raw *common_in, -+ void *top, void *sigstack, -+ int stack_len, -+ struct frame_common *common_out) -+{ -+ unsigned long sig_top = (unsigned long) sigstack + stack_len, base; -+ -+ common_in->stack = (void *) sigstack; -+ common_in->size = stack_len; -+ common_out->len = capture_stack(proc, arg, top, sig_top, -+ &common_out->data); -+ base = sig_top - common_out->len; -+ common_out->sig_index = common_in->sig - base; -+ common_out->sp_index = common_in->sp - base; -+ common_out->sr_index = common_in->sr - base; -+ common_out->sr_relative = relative_sr(common_in->sr, -+ common_out->sr_index, sigstack, -+ common_out->data); -+ return(base); -+} -+ -+void capture_signal_stack(void) -+{ -+ struct sc_frame_raw raw_sc; -+ struct si_frame_raw raw_si; -+ void *stack, *sigstack; -+ unsigned long top, base; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ sigstack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if((stack == MAP_FAILED) || (sigstack == MAP_FAILED)){ -+ printf("capture_signal_stack : mmap failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+ -+ top = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ -+ /* Get the sigcontext, no sigrestorer layout */ -+ raw_sc.restorer = 0; -+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_sc.common); -+ -+ signal_frame_sc.sc_index = raw_sc.sc - base; -+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc.common.arch); -+ -+ /* Ditto for the sigcontext, sigrestorer layout */ -+ raw_sc.restorer = 1; -+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_sc_sr.common); -+ signal_frame_sc_sr.sc_index = raw_sc.sc - base; -+ setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc_sr.common.arch); -+ -+ /* And the siginfo layout */ -+ -+ base = capture_stack_common(si_child, &raw_si, &raw_si.common, -+ (void *) top, sigstack, PAGE_SIZE, -+ &signal_frame_si.common); -+ signal_frame_si.sip_index = raw_si.sip - base; -+ signal_frame_si.si_index = raw_si.si - base; -+ signal_frame_si.ucp_index = raw_si.ucp - base; -+ signal_frame_si.uc_index = raw_si.uc - base; -+ setup_arch_frame(&raw_si.common.arch, &signal_frame_si.common.arch); -+ -+ if((munmap(stack, PAGE_SIZE) < 0) || -+ (munmap(sigstack, PAGE_SIZE) < 0)){ -+ printf("capture_signal_stack : munmap failed - errno = %d\n", -+ errno); -+ exit(1); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/frame_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/frame_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/frame_kern.c 2005-05-03 22:28:14.413419040 +0300 -@@ -0,0 +1,173 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/signal.h" -+#include "asm/ucontext.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "sysdep/ptrace.h" -+#include "choose-mode.h" -+#include "mode.h" -+ -+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) -+{ -+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) -+ return -EFAULT; -+ if (from->si_code < 0) -+ return __copy_to_user(to, from, sizeof(siginfo_t)); -+ else { -+ int err; -+ -+ /* If you change siginfo_t structure, please be sure -+ this code is fixed accordingly. -+ It should never copy any pad contained in the structure -+ to avoid security leaks, but must copy the generic -+ 3 ints plus the relevant union member. */ -+ err = __put_user(from->si_signo, &to->si_signo); -+ err |= __put_user(from->si_errno, &to->si_errno); -+ err |= __put_user((short)from->si_code, &to->si_code); -+ /* First 32bits of unions are always present. */ -+ err |= __put_user(from->si_pid, &to->si_pid); -+ switch (from->si_code >> 16) { -+ case __SI_FAULT >> 16: -+ break; -+ case __SI_CHLD >> 16: -+ err |= __put_user(from->si_utime, &to->si_utime); -+ err |= __put_user(from->si_stime, &to->si_stime); -+ err |= __put_user(from->si_status, &to->si_status); -+ default: -+ err |= __put_user(from->si_uid, &to->si_uid); -+ break; -+ } -+ return err; -+ } -+} -+ -+static int copy_restorer(void (*restorer)(void), unsigned long start, -+ unsigned long sr_index, int sr_relative) -+{ -+ unsigned long sr; -+ -+ if(sr_relative){ -+ sr = (unsigned long) restorer; -+ sr += start + sr_index; -+ restorer = (void (*)(void)) sr; -+ } -+ -+ return(copy_to_user((void *) (start + sr_index), &restorer, -+ sizeof(restorer))); -+} -+ -+extern int userspace_pid[]; -+ -+static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, -+ struct arch_frame_data *arch) -+{ -+ return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), -+ arch), -+ copy_sc_to_user_skas(userspace_pid[0], to, fp, -+ &from->regs, -+ current->thread.cr2, -+ current->thread.err))); -+} -+ -+static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set, -+ unsigned long sp) -+{ -+ int err = 0; -+ -+ err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); -+ err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); -+ err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); -+ err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, -+ &signal_frame_si.common.arch); -+ err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); -+ return(err); -+} -+ -+int setup_signal_stack_si(unsigned long stack_top, int sig, -+ unsigned long handler, void (*restorer)(void), -+ struct pt_regs *regs, siginfo_t *info, -+ sigset_t *mask) -+{ -+ unsigned long start; -+ void *sip, *ucp, *fp; -+ -+ start = stack_top - signal_frame_si.common.len; -+ sip = (void *) (start + signal_frame_si.si_index); -+ ucp = (void *) (start + signal_frame_si.uc_index); -+ fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext)); -+ -+ if(restorer == NULL) -+ panic("setup_signal_stack_si - no restorer"); -+ -+ if(copy_to_user((void *) start, signal_frame_si.common.data, -+ signal_frame_si.common.len) || -+ copy_to_user((void *) (start + signal_frame_si.common.sig_index), -+ &sig, sizeof(sig)) || -+ copy_siginfo_to_user(sip, info) || -+ copy_to_user((void *) (start + signal_frame_si.sip_index), &sip, -+ sizeof(sip)) || -+ copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) || -+ copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp, -+ sizeof(ucp)) || -+ copy_restorer(restorer, start, signal_frame_si.common.sr_index, -+ signal_frame_si.common.sr_relative)) -+ return(1); -+ -+ PT_REGS_IP(regs) = handler; -+ PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index; -+ return(0); -+} -+ -+int setup_signal_stack_sc(unsigned long stack_top, int sig, -+ unsigned long handler, void (*restorer)(void), -+ struct pt_regs *regs, sigset_t *mask) -+{ -+ struct frame_common *frame = &signal_frame_sc_sr.common; -+ void *user_sc; -+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); -+ unsigned long sigs, sr; -+ unsigned long start = stack_top - frame->len - sig_size; -+ -+ user_sc = (void *) (start + signal_frame_sc_sr.sc_index); -+ if(restorer == NULL){ -+ frame = &signal_frame_sc.common; -+ user_sc = (void *) (start + signal_frame_sc.sc_index); -+ sr = (unsigned long) frame->data; -+ sr += frame->sr_index; -+ sr = *((unsigned long *) sr); -+ restorer = ((void (*)(void)) sr); -+ } -+ -+ sigs = start + frame->len; -+ if(copy_to_user((void *) start, frame->data, frame->len) || -+ copy_to_user((void *) (start + frame->sig_index), &sig, -+ sizeof(sig)) || -+ copy_sc_to_user(user_sc, NULL, regs, -+ &signal_frame_sc.common.arch) || -+ copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) || -+ copy_to_user((void *) sigs, &mask->sig[1], sig_size) || -+ copy_restorer(restorer, start, frame->sr_index, frame->sr_relative)) -+ return(1); -+ -+ PT_REGS_IP(regs) = handler; -+ PT_REGS_SP(regs) = start + frame->sp_index; -+ -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/gmon_syms.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/gmon_syms.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/gmon_syms.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+ -+extern void __bb_init_func(void *); -+EXPORT_SYMBOL(__bb_init_func); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/gprof_syms.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/gprof_syms.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/gprof_syms.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+ -+extern void mcount(void); -+EXPORT_SYMBOL(mcount); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/helper.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/helper.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/helper.c 2005-05-03 22:28:14.416418584 +0300 -@@ -0,0 +1,167 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <sched.h> -+#include <sys/signal.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+ -+struct helper_data { -+ void (*pre_exec)(void*); -+ void *pre_data; -+ char **argv; -+ int fd; -+}; -+ -+/* Debugging aid, changed only from gdb */ -+int helper_pause = 0; -+ -+static void helper_hup(int sig) -+{ -+} -+ -+static int helper_child(void *arg) -+{ -+ struct helper_data *data = arg; -+ char **argv = data->argv; -+ int errval; -+ -+ if(helper_pause){ -+ signal(SIGHUP, helper_hup); -+ pause(); -+ } -+ if(data->pre_exec != NULL) -+ (*data->pre_exec)(data->pre_data); -+ execvp(argv[0], argv); -+ errval = errno; -+ printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); -+ os_write_file(data->fd, &errval, sizeof(errval)); -+ os_kill_process(os_getpid(), 0); -+ return(0); -+} -+ -+/* XXX The alloc_stack here breaks if this is called in the tracing thread */ -+ -+int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, -+ unsigned long *stack_out) -+{ -+ struct helper_data data; -+ unsigned long stack, sp; -+ int pid, fds[2], err, n; -+ -+ if((stack_out != NULL) && (*stack_out != 0)) -+ stack = *stack_out; -+ else stack = alloc_stack(0, um_in_interrupt()); -+ if(stack == 0) -+ return(-ENOMEM); -+ -+ err = os_pipe(fds, 1, 0); -+ if(err < 0){ -+ printk("run_helper : pipe failed, err = %d\n", -err); -+ goto out_free; -+ } -+ -+ err = os_set_exec_close(fds[1], 1); -+ if(err < 0){ -+ printk("run_helper : setting FD_CLOEXEC failed, err = %d\n", -+ -err); -+ goto out_close; -+ } -+ -+ sp = stack + page_size() - sizeof(void *); -+ data.pre_exec = pre_exec; -+ data.pre_data = pre_data; -+ data.argv = argv; -+ data.fd = fds[1]; -+ pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); -+ if(pid < 0){ -+ printk("run_helper : clone failed, errno = %d\n", errno); -+ err = -errno; -+ goto out_close; -+ } -+ -+ os_close_file(fds[1]); -+ n = os_read_file(fds[0], &err, sizeof(err)); -+ if(n < 0){ -+ printk("run_helper : read on pipe failed, err = %d\n", -n); -+ err = n; -+ os_kill_process(pid, 1); -+ } -+ else if(n != 0){ -+ CATCH_EINTR(n = waitpid(pid, NULL, 0)); -+ pid = -errno; -+ } -+ err = pid; -+ -+ out_close: -+ os_close_file(fds[0]); -+ out_free: -+ if(stack_out == NULL) -+ free_stack(stack, 0); -+ else *stack_out = stack; -+ return(err); -+} -+ -+int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, -+ unsigned long *stack_out, int stack_order) -+{ -+ unsigned long stack, sp; -+ int pid, status; -+ -+ stack = alloc_stack(stack_order, um_in_interrupt()); -+ if(stack == 0) return(-ENOMEM); -+ -+ sp = stack + (page_size() << stack_order) - sizeof(void *); -+ pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); -+ if(pid < 0){ -+ printk("run_helper_thread : clone failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ if(stack_out == NULL){ -+ CATCH_EINTR(pid = waitpid(pid, &status, 0)); -+ if(pid < 0){ -+ printk("run_helper_thread - wait failed, errno = %d\n", -+ errno); -+ pid = -errno; -+ } -+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) -+ printk("run_helper_thread - thread returned status " -+ "0x%x\n", status); -+ free_stack(stack, stack_order); -+ } -+ else *stack_out = stack; -+ return(pid); -+} -+ -+int helper_wait(int pid, int block) -+{ -+ int ret; -+ -+ CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); -+ if(ret < 0){ -+ printk("helper_wait : waitpid failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/initrd_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/initrd_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/initrd_kern.c 2005-05-03 22:28:14.417418432 +0300 -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/bootmem.h" -+#include "linux/blk.h" -+#include "asm/types.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "initrd.h" -+#include "init.h" -+#include "os.h" -+ -+/* Changed by uml_initrd_setup, which is a setup */ -+static char *initrd __initdata = NULL; -+ -+static int __init read_initrd(void) -+{ -+ void *area; -+ long long size; -+ int err; -+ -+ if(initrd == NULL) return 0; -+ err = os_file_size(initrd, &size); -+ if(err) return 0; -+ area = alloc_bootmem(size); -+ if(area == NULL) return 0; -+ if(load_initrd(initrd, area, size) == -1) return 0; -+ initrd_start = (unsigned long) area; -+ initrd_end = initrd_start + size; -+ return 0; -+} -+ -+__uml_postsetup(read_initrd); -+ -+static int __init uml_initrd_setup(char *line, int *add) -+{ -+ initrd = line; -+ return 0; -+} -+ -+__uml_setup("initrd=", uml_initrd_setup, -+"initrd=<initrd image>\n" -+" This is used to boot UML from an initrd image. The argument is the\n" -+" name of the file containing the image.\n\n" -+); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/initrd_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/initrd_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/initrd_user.c 2005-05-03 22:28:14.418418280 +0300 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <errno.h> -+ -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "initrd.h" -+#include "os.h" -+ -+int load_initrd(char *filename, void *buf, int size) -+{ -+ int fd, n; -+ -+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Opening '%s' failed - err = %d\n", filename, -fd); -+ return(-1); -+ } -+ n = os_read_file(fd, buf, size); -+ if(n != size){ -+ printk("Read of %d bytes from '%s' failed, err = %d\n", size, -+ filename, -n); -+ return(-1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/init_task.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/init_task.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/init_task.c 2005-05-03 22:28:14.419418128 +0300 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "linux/sched.h" -+#include "linux/version.h" -+#include "asm/uaccess.h" -+#include "asm/pgtable.h" -+#include "user_util.h" -+#include "mem_user.h" -+ -+static struct fs_struct init_fs = INIT_FS; -+static struct files_struct init_files = INIT_FILES; -+static struct signal_struct init_signals = INIT_SIGNALS; -+struct mm_struct init_mm = INIT_MM(init_mm); -+ -+/* -+ * Initial task structure. -+ * -+ * We need to make sure that this is 16384-byte aligned due to the -+ * way process stacks are handled. This is done by having a special -+ * "init_task" linker map entry.. -+ */ -+ -+union task_union init_task_union -+__attribute__((__section__(".data.init_task"))) = -+{ INIT_TASK(init_task_union.task) }; -+ -+struct task_struct *alloc_task_struct(void) -+{ -+ return((struct task_struct *) -+ __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER)); -+} -+ -+void unprotect_stack(unsigned long stack) -+{ -+ protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, -+ 1, 1, 0, 1); -+} -+ -+void free_task_struct(struct task_struct *task) -+{ -+ /* free_pages decrements the page counter and only actually frees -+ * the pages if they are now not accessed by anything. -+ */ -+ free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/irq.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/irq.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/irq.c 2005-05-03 22:28:14.422417672 +0300 -@@ -0,0 +1,840 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: -+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "linux/irq.h" -+#include "linux/kernel_stat.h" -+#include "linux/interrupt.h" -+#include "linux/random.h" -+#include "linux/slab.h" -+#include "linux/file.h" -+#include "linux/proc_fs.h" -+#include "linux/init.h" -+#include "linux/seq_file.h" -+#include "asm/irq.h" -+#include "asm/hw_irq.h" -+#include "asm/hardirq.h" -+#include "asm/atomic.h" -+#include "asm/signal.h" -+#include "asm/system.h" -+#include "asm/errno.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+ -+static void register_irq_proc (unsigned int irq); -+ -+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = -+ { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; -+ -+/* -+ * Generic no controller code -+ */ -+ -+static void enable_none(unsigned int irq) { } -+static unsigned int startup_none(unsigned int irq) { return 0; } -+static void disable_none(unsigned int irq) { } -+static void ack_none(unsigned int irq) -+{ -+/* -+ * 'what should we do if we get a hw irq event on an illegal vector'. -+ * each architecture has to answer this themselves, it doesnt deserve -+ * a generic callback i think. -+ */ -+#if CONFIG_X86 -+ printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); -+#ifdef CONFIG_X86_LOCAL_APIC -+ /* -+ * 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. -+ */ -+ ack_APIC_irq(); -+#endif -+#endif -+} -+ -+/* startup is the same as "enable", shutdown is same as "disable" */ -+#define shutdown_none disable_none -+#define end_none enable_none -+ -+struct hw_interrupt_type no_irq_type = { -+ "none", -+ startup_none, -+ shutdown_none, -+ enable_none, -+ disable_none, -+ ack_none, -+ end_none -+}; -+ -+/* -+ * Generic, controller-independent functions: -+ */ -+ -+int get_irq_list(char *buf) -+{ -+ int i, j; -+ unsigned long flags; -+ struct irqaction * action; -+ char *p = buf; -+ -+ p += sprintf(p, " "); -+ for (j=0; j<smp_num_cpus; j++) -+ p += sprintf(p, "CPU%d ",j); -+ *p++ = '\n'; -+ -+ for (i = 0 ; i < NR_IRQS ; i++) { -+ spin_lock_irqsave(&irq_desc[i].lock, flags); -+ action = irq_desc[i].action; -+ if (!action) -+ goto end; -+ p += sprintf(p, "%3d: ",i); -+#ifndef CONFIG_SMP -+ p += sprintf(p, "%10u ", kstat_irqs(i)); -+#else -+ for (j = 0; j < smp_num_cpus; j++) -+ p += sprintf(p, "%10u ", -+ kstat.irqs[cpu_logical_map(j)][i]); -+#endif -+ p += sprintf(p, " %14s", irq_desc[i].handler->typename); -+ p += sprintf(p, " %s", action->name); -+ -+ for (action=action->next; action; action = action->next) -+ p += sprintf(p, ", %s", action->name); -+ *p++ = '\n'; -+ end: -+ spin_unlock_irqrestore(&irq_desc[i].lock, flags); -+ } -+ p += sprintf(p, "\n"); -+#ifdef notdef -+#if CONFIG_SMP -+ p += sprintf(p, "LOC: "); -+ for (j = 0; j < smp_num_cpus; j++) -+ p += sprintf(p, "%10u ", -+ apic_timer_irqs[cpu_logical_map(j)]); -+ p += sprintf(p, "\n"); -+#endif -+#endif -+ p += sprintf(p, "ERR: %10lu\n", 0L); -+ return p - buf; -+} -+ -+/* -+ * This should really return information about whether -+ * we should do bottom half handling etc. Right now we -+ * end up _always_ checking the bottom half, which is a -+ * waste of time and is not what some drivers would -+ * prefer. -+ */ -+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, -+ struct irqaction * action) -+{ -+ int status; -+ int cpu = smp_processor_id(); -+ -+ irq_enter(cpu, irq); -+ -+ status = 1; /* Force the "do bottom halves" bit */ -+ -+ if (!(action->flags & SA_INTERRUPT)) -+ __sti(); -+ -+ do { -+ status |= action->flags; -+ action->handler(irq, action->dev_id, regs); -+ action = action->next; -+ } while (action); -+ if (status & SA_SAMPLE_RANDOM) -+ add_interrupt_randomness(irq); -+ __cli(); -+ -+ irq_exit(cpu, irq); -+ -+ return status; -+} -+ -+/* -+ * Generic enable/disable code: this just calls -+ * down into the PIC-specific version for the actual -+ * hardware disable after having gotten the irq -+ * controller lock. -+ */ -+ -+/** -+ * disable_irq_nosync - disable an irq without waiting -+ * @irq: Interrupt to disable -+ * -+ * Disable the selected interrupt line. Disables of an interrupt -+ * stack. Unlike disable_irq(), this function does not ensure existing -+ * instances of the IRQ handler have completed before returning. -+ * -+ * This function may be called from IRQ context. -+ */ -+ -+void inline disable_irq_nosync(unsigned int irq) -+{ -+ irq_desc_t *desc = irq_desc + irq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&desc->lock, flags); -+ if (!desc->depth++) { -+ desc->status |= IRQ_DISABLED; -+ desc->handler->disable(irq); -+ } -+ spin_unlock_irqrestore(&desc->lock, flags); -+} -+ -+/** -+ * disable_irq - disable an irq and wait for completion -+ * @irq: Interrupt to disable -+ * -+ * Disable the selected interrupt line. Disables of an interrupt -+ * stack. That is for two disables you need two enables. This -+ * function waits for any pending IRQ handlers for this interrupt -+ * to complete before returning. If you use this function while -+ * holding a resource the IRQ handler may need you will deadlock. -+ * -+ * This function may be called - with care - from IRQ context. -+ */ -+ -+void disable_irq(unsigned int irq) -+{ -+ disable_irq_nosync(irq); -+ -+ if (!local_irq_count(smp_processor_id())) { -+ do { -+ barrier(); -+ } while (irq_desc[irq].status & IRQ_INPROGRESS); -+ } -+} -+ -+/** -+ * enable_irq - enable interrupt handling on an irq -+ * @irq: Interrupt to enable -+ * -+ * Re-enables the processing of interrupts on this IRQ line -+ * providing no disable_irq calls are now in effect. -+ * -+ * This function may be called from IRQ context. -+ */ -+ -+void enable_irq(unsigned int irq) -+{ -+ irq_desc_t *desc = irq_desc + irq; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&desc->lock, flags); -+ switch (desc->depth) { -+ case 1: { -+ unsigned int status = desc->status & ~IRQ_DISABLED; -+ desc->status = status; -+ if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { -+ desc->status = status | IRQ_REPLAY; -+ hw_resend_irq(desc->handler,irq); -+ } -+ desc->handler->enable(irq); -+ /* fall-through */ -+ } -+ default: -+ desc->depth--; -+ break; -+ case 0: -+ printk(KERN_ERR "enable_irq() unbalanced from %p\n", -+ __builtin_return_address(0)); -+ } -+ spin_unlock_irqrestore(&desc->lock, flags); -+} -+ -+/* -+ * do_IRQ handles all normal device IRQ's (the special -+ * SMP cross-CPU interrupts have their own specific -+ * handlers). -+ */ -+unsigned int do_IRQ(int irq, union uml_pt_regs *regs) -+{ -+ /* -+ * 0 return value means that this irq is already being -+ * handled by some other CPU. (or is disabled) -+ */ -+ int cpu = smp_processor_id(); -+ irq_desc_t *desc = irq_desc + irq; -+ struct irqaction * action; -+ unsigned int status; -+ -+ kstat.irqs[cpu][irq]++; -+ spin_lock(&desc->lock); -+ desc->handler->ack(irq); -+ /* -+ REPLAY is when Linux resends an IRQ that was dropped earlier -+ WAITING is used by probe to mark irqs that are being tested -+ */ -+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); -+ status |= IRQ_PENDING; /* we _want_ to handle it */ -+ -+ /* -+ * If the IRQ is disabled for whatever reason, we cannot -+ * use the action we have. -+ */ -+ action = NULL; -+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { -+ action = desc->action; -+ status &= ~IRQ_PENDING; /* we commit to handling */ -+ status |= IRQ_INPROGRESS; /* we are handling it */ -+ } -+ desc->status = status; -+ -+ /* -+ * If there is no IRQ handler or it was disabled, exit early. -+ Since we set PENDING, if another processor is handling -+ a different instance of this same irq, the other processor -+ will take care of it. -+ */ -+ if (!action) -+ goto out; -+ -+ /* -+ * Edge triggered interrupts need to remember -+ * pending events. -+ * This applies to any hw interrupts that allow a second -+ * instance of the same irq to arrive while we are in do_IRQ -+ * or in the handler. But the code here only handles the _second_ -+ * instance of the irq, not the third or fourth. So it is mostly -+ * useful for irq hardware that does not mask cleanly in an -+ * SMP environment. -+ */ -+ for (;;) { -+ spin_unlock(&desc->lock); -+ handle_IRQ_event(irq, (struct pt_regs *) regs, action); -+ spin_lock(&desc->lock); -+ -+ if (!(desc->status & IRQ_PENDING)) -+ break; -+ desc->status &= ~IRQ_PENDING; -+ } -+ desc->status &= ~IRQ_INPROGRESS; -+out: -+ /* -+ * The ->end() handler has to deal with interrupts which got -+ * disabled while the handler was running. -+ */ -+ desc->handler->end(irq); -+ spin_unlock(&desc->lock); -+ -+ if (softirq_pending(cpu)) -+ do_softirq(); -+ return 1; -+} -+ -+/** -+ * request_irq - allocate an interrupt line -+ * @irq: Interrupt line to allocate -+ * @handler: Function to be called when the IRQ occurs -+ * @irqflags: Interrupt type flags -+ * @devname: An ascii name for the claiming device -+ * @dev_id: A cookie passed back to the handler function -+ * -+ * This call allocates interrupt resources and enables the -+ * interrupt line and IRQ handling. From the point this -+ * call is made your handler function may be invoked. Since -+ * your handler function must clear any interrupt the board -+ * raises, you must take care both to initialise your hardware -+ * and to set up the interrupt handler in the right order. -+ * -+ * Dev_id must be globally unique. Normally the address of the -+ * device data structure is used as the cookie. Since the handler -+ * receives this value it makes sense to use it. -+ * -+ * If your interrupt is shared you must pass a non NULL dev_id -+ * as this is required when freeing the interrupt. -+ * -+ * Flags: -+ * -+ * SA_SHIRQ Interrupt is shared -+ * -+ * SA_INTERRUPT Disable local interrupts while processing -+ * -+ * SA_SAMPLE_RANDOM The interrupt can be used for entropy -+ * -+ */ -+ -+int request_irq(unsigned int irq, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, -+ const char * devname, -+ void *dev_id) -+{ -+ int retval; -+ struct irqaction * action; -+ -+#if 1 -+ /* -+ * Sanity-check: shared interrupts should REALLY pass in -+ * a real dev-ID, otherwise we'll have trouble later trying -+ * to figure out which interrupt is which (messes up the -+ * interrupt freeing logic etc). -+ */ -+ if (irqflags & SA_SHIRQ) { -+ if (!dev_id) -+ printk(KERN_ERR "Bad boy: %s (at 0x%x) called us " -+ "without a dev_id!\n", devname, (&irq)[-1]); -+ } -+#endif -+ -+ if (irq >= NR_IRQS) -+ return -EINVAL; -+ if (!handler) -+ return -EINVAL; -+ -+ action = (struct irqaction *) -+ kmalloc(sizeof(struct irqaction), GFP_KERNEL); -+ if (!action) -+ return -ENOMEM; -+ -+ action->handler = handler; -+ action->flags = irqflags; -+ action->mask = 0; -+ action->name = devname; -+ action->next = NULL; -+ action->dev_id = dev_id; -+ -+ retval = setup_irq(irq, action); -+ if (retval) -+ kfree(action); -+ return retval; -+} -+ -+int um_request_irq(unsigned int irq, int fd, int type, -+ void (*handler)(int, void *, struct pt_regs *), -+ unsigned long irqflags, const char * devname, -+ void *dev_id) -+{ -+ int err; -+ -+ err = request_irq(irq, handler, irqflags, devname, dev_id); -+ if(err) -+ return(err); -+ -+ if(fd != -1) -+ err = activate_fd(irq, fd, type, dev_id); -+ return(err); -+} -+ -+/* this was setup_x86_irq but it seems pretty generic */ -+int setup_irq(unsigned int irq, struct irqaction * new) -+{ -+ int shared = 0; -+ unsigned long flags; -+ struct irqaction *old, **p; -+ irq_desc_t *desc = irq_desc + irq; -+ -+ /* -+ * Some drivers like serial.c use request_irq() heavily, -+ * so we have to be careful not to interfere with a -+ * running system. -+ */ -+ if (new->flags & SA_SAMPLE_RANDOM) { -+ /* -+ * This function might sleep, we want to call it first, -+ * outside of the atomic block. -+ * Yes, this might clear the entropy pool if the wrong -+ * driver is attempted to be loaded, without actually -+ * installing a new handler, but is this really a problem, -+ * only the sysadmin is able to do this. -+ */ -+ rand_initialize_irq(irq); -+ } -+ -+ /* -+ * The following block of code has to be executed atomically -+ */ -+ spin_lock_irqsave(&desc->lock,flags); -+ p = &desc->action; -+ old = *p; -+ if (old != NULL) { -+ /* Can't share interrupts unless both agree to */ -+ if (!(old->flags & new->flags & SA_SHIRQ)) { -+ spin_unlock_irqrestore(&desc->lock,flags); -+ return -EBUSY; -+ } -+ -+ /* add new interrupt at end of irq queue */ -+ do { -+ p = &old->next; -+ old = *p; -+ } while (old); -+ shared = 1; -+ } -+ -+ *p = new; -+ -+ if (!shared) { -+ desc->depth = 0; -+ desc->status &= ~IRQ_DISABLED; -+ desc->handler->startup(irq); -+ } -+ spin_unlock_irqrestore(&desc->lock,flags); -+ -+ register_irq_proc(irq); -+ return 0; -+} -+ -+/** -+ * free_irq - free an interrupt -+ * @irq: Interrupt line to free -+ * @dev_id: Device identity to free -+ * -+ * Remove an interrupt handler. The handler is removed and if the -+ * interrupt line is no longer in use by any driver it is disabled. -+ * On a shared IRQ the caller must ensure the interrupt is disabled -+ * on the card it drives before calling this function. The function -+ * does not return until any executing interrupts for this IRQ -+ * have completed. -+ * -+ * This function may be called from interrupt context. -+ * -+ * Bugs: Attempting to free an irq in a handler for the same irq hangs -+ * the machine. -+ */ -+ -+void free_irq(unsigned int irq, void *dev_id) -+{ -+ irq_desc_t *desc; -+ struct irqaction **p; -+ unsigned long flags; -+ -+ if (irq >= NR_IRQS) -+ return; -+ -+ desc = irq_desc + irq; -+ spin_lock_irqsave(&desc->lock,flags); -+ p = &desc->action; -+ for (;;) { -+ struct irqaction * action = *p; -+ if (action) { -+ struct irqaction **pp = p; -+ p = &action->next; -+ if (action->dev_id != dev_id) -+ continue; -+ -+ /* Found it - now remove it from the list of entries */ -+ *pp = action->next; -+ if (!desc->action) { -+ desc->status |= IRQ_DISABLED; -+ desc->handler->shutdown(irq); -+ } -+ free_irq_by_irq_and_dev(irq, dev_id); -+ spin_unlock_irqrestore(&desc->lock,flags); -+ -+#ifdef CONFIG_SMP -+ /* Wait to make sure it's not being used on another CPU */ -+ while (desc->status & IRQ_INPROGRESS) -+ barrier(); -+#endif -+ kfree(action); -+ return; -+ } -+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq); -+ spin_unlock_irqrestore(&desc->lock,flags); -+ return; -+ } -+} -+ -+/* These are initialized by sysctl_init, which is called from init/main.c */ -+static struct proc_dir_entry * root_irq_dir; -+static struct proc_dir_entry * irq_dir [NR_IRQS]; -+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; -+ -+/* These are read and written as longs, so a read won't see a partial write -+ * even during a race. -+ */ -+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; -+ -+#define HEX_DIGITS 8 -+ -+static int irq_affinity_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ if (count < HEX_DIGITS+1) -+ return -EINVAL; -+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]); -+} -+ -+static unsigned int parse_hex_value (const char *buffer, -+ unsigned long count, unsigned long *ret) -+{ -+ unsigned char hexnum [HEX_DIGITS]; -+ unsigned long value; -+ int i; -+ -+ if (!count) -+ return -EINVAL; -+ if (count > HEX_DIGITS) -+ count = HEX_DIGITS; -+ if (copy_from_user(hexnum, buffer, count)) -+ return -EFAULT; -+ -+ /* -+ * Parse the first HEX_DIGITS characters as a hex string, any non-hex -+ * char is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. -+ */ -+ value = 0; -+ -+ for (i = 0; i < count; i++) { -+ unsigned int c = hexnum[i]; -+ -+ switch (c) { -+ case '0' ... '9': c -= '0'; break; -+ case 'a' ... 'f': c -= 'a'-10; break; -+ case 'A' ... 'F': c -= 'A'-10; break; -+ default: -+ goto out; -+ } -+ value = (value << 4) | c; -+ } -+out: -+ *ret = value; -+ return 0; -+} -+ -+static int irq_affinity_write_proc (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ int irq = (long) data, full_count = count, err; -+ unsigned long new_value; -+ -+ if (!irq_desc[irq].handler->set_affinity) -+ return -EIO; -+ -+ err = parse_hex_value(buffer, count, &new_value); -+ -+#if CONFIG_SMP -+ /* -+ * Do not allow disabling IRQs completely - it's a too easy -+ * way to make the system unusable accidentally :-) At least -+ * one online CPU still has to be targeted. -+ */ -+ if (!(new_value & cpu_online_map)) -+ return -EINVAL; -+#endif -+ -+ irq_affinity[irq] = new_value; -+ irq_desc[irq].handler->set_affinity(irq, new_value); -+ -+ return full_count; -+} -+ -+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, -+ int count, int *eof, void *data) -+{ -+ unsigned long *mask = (unsigned long *) data; -+ if (count < HEX_DIGITS+1) -+ return -EINVAL; -+ return sprintf (page, "%08lx\n", *mask); -+} -+ -+static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, -+ unsigned long count, void *data) -+{ -+ unsigned long *mask = (unsigned long *) data, full_count = count, err; -+ unsigned long new_value; -+ -+ err = parse_hex_value(buffer, count, &new_value); -+ if (err) -+ return err; -+ -+ *mask = new_value; -+ return full_count; -+} -+ -+#define MAX_NAMELEN 10 -+ -+static void register_irq_proc (unsigned int irq) -+{ -+ struct proc_dir_entry *entry; -+ char name [MAX_NAMELEN]; -+ -+ if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || -+ irq_dir[irq]) -+ return; -+ -+ memset(name, 0, MAX_NAMELEN); -+ sprintf(name, "%d", irq); -+ -+ /* create /proc/irq/1234 */ -+ irq_dir[irq] = proc_mkdir(name, root_irq_dir); -+ -+ /* create /proc/irq/1234/smp_affinity */ -+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); -+ -+ entry->nlink = 1; -+ entry->data = (void *)(long)irq; -+ entry->read_proc = irq_affinity_read_proc; -+ entry->write_proc = irq_affinity_write_proc; -+ -+ smp_affinity_entry[irq] = entry; -+} -+ -+/* Read and written as a long */ -+unsigned long prof_cpu_mask = -1; -+ -+void __init init_irq_proc (void) -+{ -+ struct proc_dir_entry *entry; -+ int i; -+ -+ /* create /proc/irq */ -+ root_irq_dir = proc_mkdir("irq", 0); -+ -+ /* create /proc/irq/prof_cpu_mask */ -+ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); -+ -+ entry->nlink = 1; -+ entry->data = (void *)&prof_cpu_mask; -+ entry->read_proc = prof_cpu_mask_read_proc; -+ entry->write_proc = prof_cpu_mask_write_proc; -+ -+ /* -+ * Create entries for all existing IRQs. -+ */ -+ for (i = 0; i < NR_IRQS; i++) -+ register_irq_proc(i); -+} -+ -+static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED; -+ -+unsigned long irq_lock(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&irq_spinlock, flags); -+ return(flags); -+} -+ -+void irq_unlock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&irq_spinlock, flags); -+} -+ -+unsigned long probe_irq_on(void) -+{ -+ return(0); -+} -+ -+int probe_irq_off(unsigned long val) -+{ -+ return(0); -+} -+ -+static unsigned int startup_SIGIO_irq(unsigned int irq) -+{ -+ return(0); -+} -+ -+static void shutdown_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void enable_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void disable_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static void mask_and_ack_SIGIO(unsigned int irq) -+{ -+} -+ -+static void end_SIGIO_irq(unsigned int irq) -+{ -+} -+ -+static unsigned int startup_SIGVTALRM_irq(unsigned int irq) -+{ -+ return(0); -+} -+ -+static void shutdown_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void enable_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void disable_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static void mask_and_ack_SIGVTALRM(unsigned int irq) -+{ -+} -+ -+static void end_SIGVTALRM_irq(unsigned int irq) -+{ -+} -+ -+static struct hw_interrupt_type SIGIO_irq_type = { -+ "SIGIO", -+ startup_SIGIO_irq, -+ shutdown_SIGIO_irq, -+ enable_SIGIO_irq, -+ disable_SIGIO_irq, -+ mask_and_ack_SIGIO, -+ end_SIGIO_irq, -+ NULL -+}; -+ -+static struct hw_interrupt_type SIGVTALRM_irq_type = { -+ "SIGVTALRM", -+ startup_SIGVTALRM_irq, -+ shutdown_SIGVTALRM_irq, -+ enable_SIGVTALRM_irq, -+ disable_SIGVTALRM_irq, -+ mask_and_ack_SIGVTALRM, -+ end_SIGVTALRM_irq, -+ NULL -+}; -+ -+void __init init_IRQ(void) -+{ -+ int i; -+ -+ irq_desc[TIMER_IRQ].status = IRQ_DISABLED; -+ irq_desc[TIMER_IRQ].action = 0; -+ irq_desc[TIMER_IRQ].depth = 1; -+ irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type; -+ enable_irq(TIMER_IRQ); -+ for(i=1;i<NR_IRQS;i++){ -+ irq_desc[i].status = IRQ_DISABLED; -+ irq_desc[i].action = 0; -+ irq_desc[i].depth = 1; -+ irq_desc[i].handler = &SIGIO_irq_type; -+ enable_irq(i); -+ } -+ init_irq_signals(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/irq_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/irq_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/irq_user.c 2005-05-03 22:28:14.424417368 +0300 -@@ -0,0 +1,438 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <signal.h> -+#include <string.h> -+#include <sys/poll.h> -+#include <sys/types.h> -+#include <sys/time.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_user.h" -+#include "sigio.h" -+#include "irq_user.h" -+#include "os.h" -+ -+struct irq_fd { -+ struct irq_fd *next; -+ void *id; -+ int fd; -+ int type; -+ int irq; -+ int pid; -+ int events; -+ int current_events; -+ int freed; -+}; -+ -+static struct irq_fd *active_fds = NULL; -+static struct irq_fd **last_irq_ptr = &active_fds; -+ -+static struct pollfd *pollfds = NULL; -+static int pollfds_num = 0; -+static int pollfds_size = 0; -+ -+extern int io_count, intr_count; -+ -+void sigio_handler(int sig, union uml_pt_regs *regs) -+{ -+ struct irq_fd *irq_fd, *next; -+ int i, n; -+ -+ if(smp_sigio_handler()) return; -+ while(1){ -+ n = poll(pollfds, pollfds_num, 0); -+ if(n < 0){ -+ if(errno == EINTR) continue; -+ printk("sigio_handler : poll returned %d, " -+ "errno = %d\n", n, errno); -+ break; -+ } -+ if(n == 0) break; -+ -+ irq_fd = active_fds; -+ for(i = 0; i < pollfds_num; i++){ -+ if(pollfds[i].revents != 0){ -+ irq_fd->current_events = pollfds[i].revents; -+ pollfds[i].fd = -1; -+ } -+ irq_fd = irq_fd->next; -+ } -+ -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ -+ next = irq_fd->next; -+ if(irq_fd->current_events != 0){ -+ irq_fd->current_events = 0; -+ do_IRQ(irq_fd->irq, regs); -+ -+ /* This is here because the next irq may be -+ * freed in the handler. If a console goes -+ * away, both the read and write irqs will be -+ * freed. After do_IRQ, ->next will point to -+ * a good IRQ. -+ * Irqs can't be freed inside their handlers, -+ * so the next best thing is to have them -+ * marked as needing freeing, so that they -+ * can be freed here. -+ */ -+ next = irq_fd->next; -+ if(irq_fd->freed) -+ free_irq(irq_fd->irq, irq_fd->id); -+ } -+ } -+ } -+} -+ -+int activate_ipi(int fd, int pid) -+{ -+ return(os_set_fd_async(fd, pid)); -+} -+ -+static void maybe_sigio_broken(int fd, int type) -+{ -+ if(isatty(fd)){ -+ if((type == IRQ_WRITE) && !pty_output_sigio){ -+ write_sigio_workaround(); -+ add_sigio_fd(fd, 0); -+ } -+ else if((type == IRQ_READ) && !pty_close_sigio){ -+ write_sigio_workaround(); -+ add_sigio_fd(fd, 1); -+ } -+ } -+} -+ -+int activate_fd(int irq, int fd, int type, void *dev_id) -+{ -+ struct pollfd *tmp_pfd; -+ struct irq_fd *new_fd, *irq_fd; -+ unsigned long flags; -+ int pid, events, err, n, size; -+ -+ pid = os_getpid(); -+ err = os_set_fd_async(fd, pid); -+ if(err < 0) -+ goto out; -+ -+ new_fd = um_kmalloc(sizeof(*new_fd)); -+ err = -ENOMEM; -+ if(new_fd == NULL) -+ goto out; -+ -+ if(type == IRQ_READ) events = POLLIN | POLLPRI; -+ else events = POLLOUT; -+ *new_fd = ((struct irq_fd) { .next = NULL, -+ .id = dev_id, -+ .fd = fd, -+ .type = type, -+ .irq = irq, -+ .pid = pid, -+ .events = events, -+ .current_events = 0, -+ .freed = 0 } ); -+ -+ /* Critical section - locked by a spinlock because this stuff can -+ * be changed from interrupt handlers. The stuff above is done -+ * outside the lock because it allocates memory. -+ */ -+ -+ /* Actually, it only looks like it can be called from interrupt -+ * context. The culprit is reactivate_fd, which calls -+ * maybe_sigio_broken, which calls write_sigio_workaround, -+ * which calls activate_fd. However, write_sigio_workaround should -+ * only be called once, at boot time. That would make it clear that -+ * this is called only from process context, and can be locked with -+ * a semaphore. -+ */ -+ flags = irq_lock(); -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ -+ if((irq_fd->fd == fd) && (irq_fd->type == type)){ -+ printk("Registering fd %d twice\n", fd); -+ printk("Irqs : %d, %d\n", irq_fd->irq, irq); -+ printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id); -+ goto out_unlock; -+ } -+ } -+ -+ n = pollfds_num; -+ if(n == pollfds_size){ -+ while(1){ -+ /* Here we have to drop the lock in order to call -+ * kmalloc, which might sleep. If something else -+ * came in and changed the pollfds array, we free -+ * the buffer and try again. -+ */ -+ irq_unlock(flags); -+ size = (pollfds_num + 1) * sizeof(pollfds[0]); -+ tmp_pfd = um_kmalloc(size); -+ flags = irq_lock(); -+ if(tmp_pfd == NULL) -+ goto out_unlock; -+ if(n == pollfds_size) -+ break; -+ kfree(tmp_pfd); -+ } -+ if(pollfds != NULL){ -+ memcpy(tmp_pfd, pollfds, -+ sizeof(pollfds[0]) * pollfds_size); -+ kfree(pollfds); -+ } -+ pollfds = tmp_pfd; -+ pollfds_size++; -+ } -+ -+ if(type == IRQ_WRITE) -+ fd = -1; -+ -+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, -+ .events = events, -+ .revents = 0 }); -+ pollfds_num++; -+ -+ *last_irq_ptr = new_fd; -+ last_irq_ptr = &new_fd->next; -+ -+ irq_unlock(flags); -+ -+ /* This calls activate_fd, so it has to be outside the critical -+ * section. -+ */ -+ maybe_sigio_broken(fd, type); -+ -+ return(0); -+ -+ out_unlock: -+ irq_unlock(flags); -+ kfree(new_fd); -+ out: -+ return(err); -+} -+ -+static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) -+{ -+ struct irq_fd **prev; -+ unsigned long flags; -+ int i = 0; -+ -+ flags = irq_lock(); -+ prev = &active_fds; -+ while(*prev != NULL){ -+ if((*test)(*prev, arg)){ -+ struct irq_fd *old_fd = *prev; -+ if((pollfds[i].fd != -1) && -+ (pollfds[i].fd != (*prev)->fd)){ -+ printk("free_irq_by_cb - mismatch between " -+ "active_fds and pollfds, fd %d vs %d\n", -+ (*prev)->fd, pollfds[i].fd); -+ goto out; -+ } -+ memcpy(&pollfds[i], &pollfds[i + 1], -+ (pollfds_num - i - 1) * sizeof(pollfds[0])); -+ pollfds_num--; -+ if(last_irq_ptr == &old_fd->next) -+ last_irq_ptr = prev; -+ *prev = (*prev)->next; -+ if(old_fd->type == IRQ_WRITE) -+ ignore_sigio_fd(old_fd->fd); -+ kfree(old_fd); -+ continue; -+ } -+ prev = &(*prev)->next; -+ i++; -+ } -+ out: -+ irq_unlock(flags); -+} -+ -+struct irq_and_dev { -+ int irq; -+ void *dev; -+}; -+ -+static int same_irq_and_dev(struct irq_fd *irq, void *d) -+{ -+ struct irq_and_dev *data = d; -+ -+ return((irq->irq == data->irq) && (irq->id == data->dev)); -+} -+ -+void free_irq_by_irq_and_dev(int irq, void *dev) -+{ -+ struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, -+ .dev = dev }); -+ -+ free_irq_by_cb(same_irq_and_dev, &data); -+} -+ -+static int same_fd(struct irq_fd *irq, void *fd) -+{ -+ return(irq->fd == *((int *) fd)); -+} -+ -+void free_irq_by_fd(int fd) -+{ -+ free_irq_by_cb(same_fd, &fd); -+} -+ -+static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) -+{ -+ struct irq_fd *irq; -+ int i = 0; -+ -+ for(irq=active_fds; irq != NULL; irq = irq->next){ -+ if((irq->fd == fd) && (irq->irq == irqnum)) break; -+ i++; -+ } -+ if(irq == NULL){ -+ printk("find_irq_by_fd doesn't have descriptor %d\n", fd); -+ goto out; -+ } -+ if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){ -+ printk("find_irq_by_fd - mismatch between active_fds and " -+ "pollfds, fd %d vs %d, need %d\n", irq->fd, -+ pollfds[i].fd, fd); -+ irq = NULL; -+ goto out; -+ } -+ *index_out = i; -+ out: -+ return(irq); -+} -+ -+void free_irq_later(int irq, void *dev_id) -+{ -+ struct irq_fd *irq_fd; -+ unsigned long flags; -+ -+ flags = irq_lock(); -+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ -+ if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) -+ break; -+ } -+ if(irq_fd == NULL){ -+ printk("free_irq_later found no irq, irq = %d, " -+ "dev_id = 0x%p\n", irq, dev_id); -+ goto out; -+ } -+ irq_fd->freed = 1; -+ out: -+ irq_unlock(flags); -+} -+ -+void reactivate_fd(int fd, int irqnum) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int i; -+ -+ flags = irq_lock(); -+ irq = find_irq_by_fd(fd, irqnum, &i); -+ if(irq == NULL){ -+ irq_unlock(flags); -+ return; -+ } -+ -+ pollfds[i].fd = irq->fd; -+ -+ irq_unlock(flags); -+ -+ /* This calls activate_fd, so it has to be outside the critical -+ * section. -+ */ -+ maybe_sigio_broken(fd, irq->type); -+} -+ -+void deactivate_fd(int fd, int irqnum) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int i; -+ -+ flags = irq_lock(); -+ irq = find_irq_by_fd(fd, irqnum, &i); -+ if(irq == NULL) -+ goto out; -+ pollfds[i].fd = -1; -+ out: -+ irq_unlock(flags); -+} -+ -+int deactivate_all_fds(void) -+{ -+ struct irq_fd *irq; -+ int err; -+ -+ for(irq=active_fds;irq != NULL;irq = irq->next){ -+ err = os_clear_fd_async(irq->fd); -+ if(err) -+ return(err); -+ } -+ -+ return(0); -+} -+ -+void forward_ipi(int fd, int pid) -+{ -+ int err; -+ -+ err = os_set_owner(fd, pid); -+ if(err < 0) -+ printk("forward_ipi: set_owner failed, fd = %d, me = %d, " -+ "target = %d, err = %d\n", fd, os_getpid(), pid, -err); -+} -+ -+void forward_interrupts(int pid) -+{ -+ struct irq_fd *irq; -+ unsigned long flags; -+ int err; -+ -+ flags = irq_lock(); -+ for(irq=active_fds;irq != NULL;irq = irq->next){ -+ err = os_set_owner(irq->fd, pid); -+ if(err < 0){ -+ /* XXX Just remove the irq rather than -+ * print out an infinite stream of these -+ */ -+ printk("Failed to forward %d to pid %d, err = %d\n", -+ irq->fd, pid, -err); -+ } -+ -+ irq->pid = pid; -+ } -+ irq_unlock(flags); -+} -+ -+void init_irq_signals(int on_sigstack) -+{ -+ __sighandler_t h; -+ int flags; -+ -+ flags = on_sigstack ? SA_ONSTACK : 0; -+ if(timer_irq_inited) h = (__sighandler_t) alarm_handler; -+ else h = boot_timer_handler; -+ -+ set_handler(SIGVTALRM, h, flags | SA_RESTART, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); -+ set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ signal(SIGWINCH, SIG_IGN); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/ksyms.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/ksyms.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/ksyms.c 2005-05-03 23:56:02.752509760 +0300 -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/module.h" -+#include "linux/string.h" -+#include "linux/smp_lock.h" -+#include "linux/spinlock.h" -+#include "asm/current.h" -+#include "asm/delay.h" -+#include "asm/processor.h" -+#include "asm/unistd.h" -+#include "asm/pgalloc.h" -+#include "asm/pgtable.h" -+#include "asm/page.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "os.h" -+#include "helper.h" -+ -+EXPORT_SYMBOL(stop); -+EXPORT_SYMBOL(strtok); -+EXPORT_SYMBOL(uml_physmem); -+EXPORT_SYMBOL(set_signals); -+EXPORT_SYMBOL(get_signals); -+EXPORT_SYMBOL(kernel_thread); -+EXPORT_SYMBOL(__const_udelay); -+EXPORT_SYMBOL(__udelay); -+EXPORT_SYMBOL(sys_waitpid); -+EXPORT_SYMBOL(task_size); -+EXPORT_SYMBOL(flush_tlb_range); -+EXPORT_SYMBOL(host_task_size); -+EXPORT_SYMBOL(arch_validate); -+EXPORT_SYMBOL(get_kmem_end); -+ -+EXPORT_SYMBOL(high_physmem); -+EXPORT_SYMBOL(empty_zero_page); -+EXPORT_SYMBOL(um_virt_to_phys); -+EXPORT_SYMBOL(__virt_to_page); -+EXPORT_SYMBOL(to_phys); -+EXPORT_SYMBOL(to_virt); -+EXPORT_SYMBOL(mode_tt); -+EXPORT_SYMBOL(handle_page_fault); -+EXPORT_SYMBOL(find_iomem); -+ -+#ifdef CONFIG_MODE_TT -+EXPORT_SYMBOL(strncpy_from_user_tt); -+EXPORT_SYMBOL(copy_from_user_tt); -+EXPORT_SYMBOL(copy_to_user_tt); -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+EXPORT_SYMBOL(strncpy_from_user_skas); -+EXPORT_SYMBOL(copy_to_user_skas); -+EXPORT_SYMBOL(copy_from_user_skas); -+#endif -+ -+EXPORT_SYMBOL(os_stat_fd); -+EXPORT_SYMBOL(os_stat_file); -+EXPORT_SYMBOL(os_access); -+EXPORT_SYMBOL(os_print_error); -+EXPORT_SYMBOL(os_get_exec_close); -+EXPORT_SYMBOL(os_set_exec_close); -+EXPORT_SYMBOL(os_getpid); -+EXPORT_SYMBOL(os_open_file); -+EXPORT_SYMBOL(os_read_file); -+EXPORT_SYMBOL(os_write_file); -+EXPORT_SYMBOL(os_seek_file); -+EXPORT_SYMBOL(os_lock_file); -+EXPORT_SYMBOL(os_pipe); -+EXPORT_SYMBOL(os_file_type); -+EXPORT_SYMBOL(os_file_mode); -+EXPORT_SYMBOL(os_file_size); -+EXPORT_SYMBOL(os_flush_stdout); -+EXPORT_SYMBOL(os_close_file); -+EXPORT_SYMBOL(os_set_fd_async); -+EXPORT_SYMBOL(os_set_fd_block); -+EXPORT_SYMBOL(helper_wait); -+EXPORT_SYMBOL(os_shutdown_socket); -+EXPORT_SYMBOL(os_create_unix_socket); -+EXPORT_SYMBOL(os_connect_socket); -+EXPORT_SYMBOL(os_accept_connection); -+EXPORT_SYMBOL(os_ioctl_generic); -+EXPORT_SYMBOL(os_rcv_fd); -+EXPORT_SYMBOL(run_helper); -+EXPORT_SYMBOL(start_thread); -+EXPORT_SYMBOL(dump_thread); -+ -+/* This is here because UML expands open to sys_open, not to a system -+ * call instruction. -+ */ -+EXPORT_SYMBOL(sys_open); -+EXPORT_SYMBOL(sys_lseek); -+EXPORT_SYMBOL(sys_read); -+EXPORT_SYMBOL(sys_wait4); -+ -+#ifdef CONFIG_SMP -+ -+/* required for SMP */ -+ -+extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); -+EXPORT_SYMBOL_NOVERS(__write_lock_failed); -+ -+extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); -+EXPORT_SYMBOL_NOVERS(__read_lock_failed); -+ -+EXPORT_SYMBOL(kernel_flag_cacheline); -+EXPORT_SYMBOL(smp_num_cpus); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/link.ld -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/link.ld 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/link.ld 2005-05-03 22:43:46.000000000 +0300 -@@ -0,0 +1,147 @@ -+OUTPUT_FORMAT("elf32-i386") -+OUTPUT_ARCH(i386) -+ENTRY(_start) -+ -+SECTIONS -+{ -+ . = 2684354560 + SIZEOF_HEADERS; -+ -+ __binary_start = .; -+ -+ .thread_private : { -+ __start_thread_private = .; -+ errno = .; -+ . += 4; -+ arch/um/kernel/tt/unmap_fin.o (.data) -+ __end_thread_private = .; -+ } -+ . = ALIGN(4096); -+ .remap : { arch/um/kernel/tt/unmap_fin.o (.text) } -+ -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ . = ALIGN(4096); -+ .text : -+ { -+ *(.text) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ *(.gnu.linkonce.t*) -+ } -+ .fini : { *(.fini) } =0x9090 -+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) } -+ .rodata1 : { *(.rodata1) } -+ _etext = .; -+ PROVIDE (etext = .); -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+ .kstrtab : { *(.kstrtab) } -+ -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ __start___ksymtab = .; /* Kernel symbol table */ -+ __ksymtab : { *(__ksymtab) } -+ __stop___ksymtab = .; -+ -+ .unprotected : { *(.unprotected) } -+ . = ALIGN(4096); -+ PROVIDE (_unprotected_end = .); -+ -+ . = ALIGN(4096); -+ __uml_setup_start = .; -+ .uml.setup.init : { *(.uml.setup.init) } -+ __uml_setup_end = .; -+ __uml_help_start = .; -+ .uml.help.init : { *(.uml.help.init) } -+ __uml_help_end = .; -+ __uml_postsetup_start = .; -+ .uml.postsetup.init : { *(.uml.postsetup.init) } -+ __uml_postsetup_end = .; -+ __setup_start = .; -+ .setup.init : { *(.setup.init) } -+ __setup_end = .; -+ __initcall_start = .; -+ .initcall.init : { *(.initcall.init) } -+ __initcall_end = .; -+ __uml_initcall_start = .; -+ .uml.initcall.init : { *(.uml.initcall.init) } -+ __uml_initcall_end = .; -+ __init_end = .; -+ __exitcall_begin = .; -+ .exitcall : { *(.exitcall.exit) } -+ __exitcall_end = .; -+ __uml_exitcall_begin = .; -+ .uml.exitcall : { *(.uml.exitcall.exit) } -+ __uml_exitcall_end = .; -+ -+ __preinit_array_start = .; -+ .preinit_array : { *(.preinit_array) } -+ __preinit_array_end = .; -+ __init_array_start = .; -+ .init_array : { *(.init_array) } -+ __init_array_end = .; -+ __fini_array_start = .; -+ .fini_array : { *(.fini_array) } -+ __fini_array_end = .; -+ -+ .data.init : { *(.data.init) } -+ -+ -+ .data : -+ { -+ . = ALIGN(32768); /* init_task */ -+ *(.data.init_task) -+ *(.data) -+ *(.gnu.linkonce.d*) -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ .ctors : -+ { -+ *(.ctors) -+ } -+ .dtors : -+ { -+ *(.dtors) -+ } -+ -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ _edata = .; -+ PROVIDE (edata = .); -+ . = ALIGN(0x1000); -+ .sbss : -+ { -+ __bss_start = .; -+ PROVIDE(_bss_start = .); -+ *(.sbss) -+ *(.scommon) -+ } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ } -+ _end = . ; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+} -Index: linux-2.4.29/arch/um/kernel/link.ld.in -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/link.ld.in 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/link.ld.in 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,94 @@ -+OUTPUT_FORMAT("ELF_FORMAT") -+OUTPUT_ARCH(ELF_ARCH) -+ENTRY(_start) -+ -+SECTIONS -+{ -+ . = START() + SIZEOF_HEADERS; -+ -+ __binary_start = .; -+ifdef(`MODE_TT', ` -+ .thread_private : { -+ __start_thread_private = .; -+ errno = .; -+ . += 4; -+ arch/um/kernel/tt/unmap_fin.o (.data) -+ __end_thread_private = .; -+ } -+ . = ALIGN(4096); -+ .remap : { arch/um/kernel/tt/unmap_fin.o (.text) } -+') -+ . = ALIGN(4096); /* Init code and data */ -+ _stext = .; -+ __init_begin = .; -+ .text.init : { *(.text.init) } -+ . = ALIGN(4096); -+ .text : -+ { -+ *(.text) -+ /* .gnu.warning sections are handled specially by elf32.em. */ -+ *(.gnu.warning) -+ *(.gnu.linkonce.t*) -+ } -+ .fini : { *(.fini) } =0x9090 -+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) } -+ .rodata1 : { *(.rodata1) } -+ _etext = .; -+ PROVIDE (etext = .); -+ -+ . = ALIGN(4096); -+ PROVIDE (_sdata = .); -+ -+include(`arch/um/kernel/common.ld.in') -+ -+ .data : -+ { -+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ -+ *(.data.init_task) -+ *(.data) -+ *(.gnu.linkonce.d*) -+ CONSTRUCTORS -+ } -+ .data1 : { *(.data1) } -+ .ctors : -+ { -+ *(.ctors) -+ } -+ .dtors : -+ { -+ *(.dtors) -+ } -+ -+ .got : { *(.got.plt) *(.got) } -+ .dynamic : { *(.dynamic) } -+ /* We want the small data sections together, so single-instruction offsets -+ can access them all, and initialized data all before uninitialized, so -+ we can shorten the on-disk segment size. */ -+ .sdata : { *(.sdata) } -+ _edata = .; -+ PROVIDE (edata = .); -+ . = ALIGN(0x1000); -+ .sbss : -+ { -+ __bss_start = .; -+ PROVIDE(_bss_start = .); -+ *(.sbss) -+ *(.scommon) -+ } -+ .bss : -+ { -+ *(.dynbss) -+ *(.bss) -+ *(COMMON) -+ } -+ _end = . ; -+ PROVIDE (end = .); -+ /* Stabs debugging sections. */ -+ .stab 0 : { *(.stab) } -+ .stabstr 0 : { *(.stabstr) } -+ .stab.excl 0 : { *(.stab.excl) } -+ .stab.exclstr 0 : { *(.stab.exclstr) } -+ .stab.index 0 : { *(.stab.index) } -+ .stab.indexstr 0 : { *(.stab.indexstr) } -+ .comment 0 : { *(.comment) } -+} -Index: linux-2.4.29/arch/um/kernel/main.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/main.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/main.c 2005-05-03 22:28:14.429416608 +0300 -@@ -0,0 +1,250 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/resource.h> -+#include <sys/mman.h> -+#include <sys/user.h> -+#include <asm/page.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "mem_user.h" -+#include "signal_user.h" -+#include "time_user.h" -+#include "irq_user.h" -+#include "user.h" -+#include "init.h" -+#include "mode.h" -+#include "choose-mode.h" -+#include "uml-config.h" -+ -+/* Set in set_stklim, which is called from main and __wrap_malloc. -+ * __wrap_malloc only calls it if main hasn't started. -+ */ -+unsigned long stacksizelim; -+ -+/* Set in main */ -+char *linux_prog; -+ -+#define PGD_BOUND (4 * 1024 * 1024) -+#define STACKSIZE (8 * 1024 * 1024) -+#define THREAD_NAME_LEN (256) -+ -+static void set_stklim(void) -+{ -+ struct rlimit lim; -+ -+ if(getrlimit(RLIMIT_STACK, &lim) < 0){ -+ perror("getrlimit"); -+ exit(1); -+ } -+ if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ -+ lim.rlim_cur = STACKSIZE; -+ if(setrlimit(RLIMIT_STACK, &lim) < 0){ -+ perror("setrlimit"); -+ exit(1); -+ } -+ } -+ stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); -+} -+ -+static __init void do_uml_initcalls(void) -+{ -+ initcall_t *call; -+ -+ call = &__uml_initcall_start; -+ while (call < &__uml_initcall_end){; -+ (*call)(); -+ call++; -+ } -+} -+ -+static void last_ditch_exit(int sig) -+{ -+ CHOOSE_MODE(kmalloc_ok = 0, (void) 0); -+ signal(SIGINT, SIG_DFL); -+ signal(SIGTERM, SIG_DFL); -+ signal(SIGHUP, SIG_DFL); -+ uml_cleanup(); -+ exit(1); -+} -+ -+extern int uml_exitcode; -+ -+int main(int argc, char **argv, char **envp) -+{ -+ char **new_argv; -+ sigset_t mask; -+ int ret, i; -+ -+ /* Enable all signals except SIGIO - in some environments, we can -+ * enter with some signals blocked -+ */ -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, SIGIO); -+ if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ -+ perror("sigprocmask"); -+ exit(1); -+ } -+ -+#ifdef UML_CONFIG_MODE_TT -+ /* Allocate memory for thread command lines */ -+ if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ -+ -+ char padding[THREAD_NAME_LEN] = { -+ [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' -+ }; -+ -+ new_argv = malloc((argc + 2) * sizeof(char*)); -+ if(!new_argv) { -+ perror("Allocating extended argv"); -+ exit(1); -+ } -+ -+ new_argv[0] = argv[0]; -+ new_argv[1] = padding; -+ -+ for(i = 2; i <= argc; i++) -+ new_argv[i] = argv[i - 1]; -+ new_argv[argc + 1] = NULL; -+ -+ execvp(new_argv[0], new_argv); -+ perror("execing with extended args"); -+ exit(1); -+ } -+#endif -+ -+ linux_prog = argv[0]; -+ -+ set_stklim(); -+ -+ new_argv = malloc((argc + 1) * sizeof(char *)); -+ if(new_argv == NULL){ -+ perror("Mallocing argv"); -+ exit(1); -+ } -+ for(i=0;i<argc;i++){ -+ new_argv[i] = strdup(argv[i]); -+ if(new_argv[i] == NULL){ -+ perror("Mallocing an arg"); -+ exit(1); -+ } -+ } -+ new_argv[argc] = NULL; -+ -+ set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); -+ -+ do_uml_initcalls(); -+ ret = linux_main(argc, argv); -+ -+ /* Reboot */ -+ if(ret){ -+ int err; -+ -+ printf("\n"); -+ -+ /* Let any pending signals fire, then disable them. This -+ * ensures that they won't be delivered after the exec, when -+ * they are definitely not expected. -+ */ -+ unblock_signals(); -+ disable_timer(); -+ err = deactivate_all_fds(); -+ if(err) -+ printf("deactivate_all_fds failed, errno = %d\n", -err); -+ -+ execvp(new_argv[0], new_argv); -+ perror("Failed to exec kernel"); -+ ret = 1; -+ } -+ printf("\n"); -+ return(uml_exitcode); -+} -+ -+#define CAN_KMALLOC() \ -+ (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1)) -+ -+extern void *__real_malloc(int); -+ -+void *__wrap_malloc(int size) -+{ -+ void *ret; -+ -+ if(!CAN_KMALLOC()) -+ return(__real_malloc(size)); -+ else if(size <= PAGE_SIZE) /* finding contiguos pages is hard */ -+ ret = um_kmalloc(size); -+ else ret = um_vmalloc(size); -+ -+ /* glibc people insist that if malloc fails, errno should be -+ * set by malloc as well. So we do. -+ */ -+ if(ret == NULL) -+ errno = ENOMEM; -+ -+ return(ret); -+} -+ -+void *__wrap_calloc(int n, int size) -+{ -+ void *ptr = __wrap_malloc(n * size); -+ -+ if(ptr == NULL) return(NULL); -+ memset(ptr, 0, n * size); -+ return(ptr); -+} -+ -+extern void __real_free(void *); -+ -+extern unsigned long high_physmem; -+ -+void __wrap_free(void *ptr) -+{ -+ unsigned long addr = (unsigned long) ptr; -+ -+ /* We need to know how the allocation happened, so it can be correctly -+ * freed. This is done by seeing what region of memory the pointer is -+ * in - -+ * physical memory - kmalloc/kfree -+ * kernel virtual memory - vmalloc/vfree -+ * anywhere else - malloc/free -+ * If kmalloc is not yet possible, then the kernel memory regions -+ * may not be set up yet, and the variables not set up. So, -+ * free is called. -+ * -+ * CAN_KMALLOC is checked because it would be bad to free a buffer -+ * with kmalloc/vmalloc after they have been turned off during -+ * shutdown. -+ */ -+ -+ if((addr >= uml_physmem) && (addr < high_physmem)){ -+ if(CAN_KMALLOC()) -+ kfree(ptr); -+ } -+ else if((addr >= start_vm) && (addr < end_vm)){ -+ if(CAN_KMALLOC()) -+ vfree(ptr); -+ } -+ else __real_free(ptr); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/Makefile 2005-05-03 22:28:14.430416456 +0300 -@@ -0,0 +1,73 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = config.o checksum.o exec_kern.o exitcode.o filehandle.o frame_kern.o \ -+ frame.o helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o \ -+ mem_user.o physmem.o process.o process_kern.o ptrace.o reboot.o \ -+ resource.o sigio_user.o sigio_kern.o signal_kern.o signal_user.o \ -+ smp.o syscall_kern.o syscall_user.o sysrq.o sys_call_table.o \ -+ tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \ -+ uaccess_user.o um_arch.o umid.o user_syms.o user_util.o -+ -+obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o -+obj-$(CONFIG_GPROF) += gprof_syms.o -+obj-$(CONFIG_GCOV) += gmon_syms.o -+obj-$(CONFIG_TTY_LOG) += tty_log.o -+ -+subdir-$(CONFIG_MODE_TT) += tt -+subdir-$(CONFIG_MODE_SKAS) += skas -+ -+user-objs-$(CONFIG_TTY_LOG) += tty_log.o -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+# user_syms.o not included here because Rules.make has its own ideas about -+# building anything in export-objs -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \ -+ main.o process.o tempfile.o time.o umid.o user_util.o -+ -+DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__ -+DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__ -+ -+export-objs-$(CONFIG_GPROF) += gprof_syms.o -+export-objs-$(CONFIG_GCOV) += gmon_syms.o -+ -+export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o $(export-objs-y) -+ -+CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \ -+ -I/usr/include -I../include -+ -+CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+# This has to be separate because it needs be compiled with frame pointers -+# regardless of how the rest of the kernel is built. -+ -+frame.o: frame.c -+ $(CC) $(CFLAGS_$@) -c -o $@ $< -+ -+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }' -+ -+config.c : config.c.in $(TOPDIR)/.config -+ $(PERL) -e $(QUOTE) < config.c.in > $@ -+ -+clean: -+ $(RM) config.c -+ for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done -+ -+modules: -+ -+fastdep: -+ -+dep: -+ -+archmrproper: clean -Index: linux-2.4.29/arch/um/kernel/mem.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/mem.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/mem.c 2005-05-03 22:28:14.431416304 +0300 -@@ -0,0 +1,336 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/mm.h" -+#include "linux/bootmem.h" -+#include "linux/highmem.h" -+#include "asm/page.h" -+#include "asm/fixmap.h" -+#include "asm/pgalloc.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mem_user.h" -+#include "uml_uaccess.h" -+#include "os.h" -+ -+extern char __binary_start; -+ -+/* Changed during early boot */ -+unsigned long *empty_zero_page = NULL; -+unsigned long *empty_bad_page = NULL; -+pgd_t swapper_pg_dir[1024]; -+unsigned long highmem; -+int kmalloc_ok = 0; -+ -+static unsigned long brk_end; -+static unsigned long totalram_pages = 0; -+ -+void unmap_physmem(void) -+{ -+ os_unmap_memory((void *) brk_end, uml_reserved - brk_end); -+} -+ -+static void map_cb(void *unused) -+{ -+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); -+} -+ -+#ifdef CONFIG_HIGHMEM -+static void setup_highmem(unsigned long highmem_start, -+ unsigned long highmem_len) -+{ -+ struct page *page; -+ unsigned long highmem_pfn; -+ int i; -+ -+ highmem_start_page = virt_to_page(highmem_start); -+ -+ highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; -+ for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ -+ page = &mem_map[highmem_pfn + i]; -+ ClearPageReserved(page); -+ set_bit(PG_highmem, &page->flags); -+ atomic_set(&page->count, 1); -+ __free_page(page); -+ } -+} -+#endif -+ -+void mem_init(void) -+{ -+ unsigned long start; -+ -+ /* clear the zero-page */ -+ memset((void *) empty_zero_page, 0, PAGE_SIZE); -+ -+ /* Map in the area just after the brk now that kmalloc is about -+ * to be turned on. -+ */ -+ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0)); -+ map_cb(NULL); -+ initial_thread_cb(map_cb, NULL); -+ free_bootmem(__pa(brk_end), uml_reserved - brk_end); -+ uml_reserved = brk_end; -+ -+ /* Fill in any hole at the start of the binary */ -+ start = (unsigned long) &__binary_start; -+ if(uml_physmem != start){ -+ map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem, -+ 1, 1, 0); -+ } -+ -+ /* this will put all low memory onto the freelists */ -+ totalram_pages = free_all_bootmem(); -+ totalram_pages += highmem >> PAGE_SHIFT; -+ num_physpages = totalram_pages; -+ printk(KERN_INFO "Memory: %luk available\n", -+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); -+ kmalloc_ok = 1; -+ -+#ifdef CONFIG_HIGHMEM -+ setup_highmem(end_iomem, highmem); -+#endif -+} -+ -+static void __init fixrange_init(unsigned long start, unsigned long end, -+ pgd_t *pgd_base) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ int i, j; -+ unsigned long vaddr; -+ -+ vaddr = start; -+ i = __pgd_offset(vaddr); -+ j = __pmd_offset(vaddr); -+ pgd = pgd_base + i; -+ -+ for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { -+ pmd = (pmd_t *)pgd; -+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { -+ if (pmd_none(*pmd)) { -+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); -+ set_pmd(pmd, __pmd(_KERNPG_TABLE + -+ (unsigned long) __pa(pte))); -+ if (pte != pte_offset(pmd, 0)) -+ BUG(); -+ } -+ vaddr += PMD_SIZE; -+ } -+ j = 0; -+ } -+} -+ -+#ifdef CONFIG_HIGHMEM -+pte_t *kmap_pte; -+pgprot_t kmap_prot; -+ -+#define kmap_get_fixmap_pte(vaddr) \ -+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) -+ -+void __init kmap_init(void) -+{ -+ unsigned long kmap_vstart; -+ -+ /* cache the first kmap pte */ -+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); -+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart); -+ -+ kmap_prot = PAGE_KERNEL; -+} -+ -+static void init_highmem(void) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long vaddr; -+ -+ /* -+ * Permanent kmaps: -+ */ -+ vaddr = PKMAP_BASE; -+ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir); -+ -+ pgd = swapper_pg_dir + __pgd_offset(vaddr); -+ pmd = pmd_offset(pgd, vaddr); -+ pte = pte_offset(pmd, vaddr); -+ pkmap_page_table = pte; -+ -+ kmap_init(); -+} -+ -+#endif /* CONFIG_HIGHMEM */ -+ -+void paging_init(void) -+{ -+ unsigned long zones_size[MAX_NR_ZONES], vaddr; -+ int i; -+ -+ empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); -+ empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); -+ for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) -+ zones_size[i] = 0; -+ zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); -+ zones_size[2] = highmem >> PAGE_SHIFT; -+ free_area_init(zones_size); -+ -+ /* -+ * Fixed mappings, only the page table structure has to be -+ * created - mappings will be set by set_fixmap(): -+ */ -+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; -+ fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir); -+ -+#if CONFIG_HIGHMEM -+ init_highmem(); -+#endif -+} -+ -+struct page *arch_validate(struct page *page, int mask, int order) -+{ -+ unsigned long addr, zero = 0; -+ int i; -+ -+ again: -+ if(page == NULL) return(page); -+ if(PageHighMem(page)) return(page); -+ -+ addr = (unsigned long) page_address(page); -+ for(i = 0; i < (1 << order); i++){ -+ current->thread.fault_addr = (void *) addr; -+ if(__do_copy_to_user((void *) addr, &zero, -+ sizeof(zero), -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)){ -+ if(!(mask & __GFP_WAIT)) return(NULL); -+ else break; -+ } -+ addr += PAGE_SIZE; -+ } -+ if(i == (1 << order)) return(page); -+ page = _alloc_pages(mask, order); -+ goto again; -+} -+ -+/* This can't do anything because nothing in the kernel image can be freed -+ * since it's not in kernel physical memory. -+ */ -+ -+void free_initmem(void) -+{ -+} -+ -+#ifdef CONFIG_BLK_DEV_INITRD -+ -+void free_initrd_mem(unsigned long start, unsigned long end) -+{ -+ if (start < end) -+ printk ("Freeing initrd memory: %ldk freed\n", -+ (end - start) >> 10); -+ for (; start < end; start += PAGE_SIZE) { -+ ClearPageReserved(virt_to_page(start)); -+ set_page_count(virt_to_page(start), 1); -+ free_page(start); -+ totalram_pages++; -+ } -+} -+ -+#endif -+ -+int do_check_pgt_cache(int low, int high) -+{ -+ int freed = 0; -+ if(pgtable_cache_size > high) { -+ do { -+ if (pgd_quicklist) { -+ free_pgd_slow(get_pgd_fast()); -+ freed++; -+ } -+ if (pmd_quicklist) { -+ pmd_free_slow(pmd_alloc_one_fast(NULL, 0)); -+ freed++; -+ } -+ if (pte_quicklist) { -+ pte_free_slow(pte_alloc_one_fast(NULL, 0)); -+ freed++; -+ } -+ } while(pgtable_cache_size > low); -+ } -+ return freed; -+} -+ -+void show_mem(void) -+{ -+ int i, total = 0, reserved = 0; -+ int shared = 0, cached = 0; -+ int highmem = 0; -+ -+ printk("Mem-info:\n"); -+ show_free_areas(); -+ printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); -+ i = max_mapnr; -+ while(i-- > 0) { -+ total++; -+ if(PageHighMem(mem_map + i)) -+ highmem++; -+ if(PageReserved(mem_map + i)) -+ reserved++; -+ else if(PageSwapCache(mem_map + i)) -+ cached++; -+ else if(page_count(mem_map + i)) -+ shared += page_count(mem_map + i) - 1; -+ } -+ printk("%d pages of RAM\n", total); -+ printk("%d pages of HIGHMEM\n", highmem); -+ printk("%d reserved pages\n", reserved); -+ printk("%d pages shared\n", shared); -+ printk("%d pages swap cached\n", cached); -+ printk("%ld pages in page table cache\n", pgtable_cache_size); -+ show_buffers(); -+} -+ -+/* Changed by meminfo_compat, which is a setup */ -+static int meminfo_22 = 0; -+ -+static int meminfo_compat(char *str) -+{ -+ meminfo_22 = 1; -+ return(1); -+} -+ -+__setup("22_meminfo", meminfo_compat); -+ -+void si_meminfo(struct sysinfo *val) -+{ -+ val->totalram = totalram_pages; -+ val->sharedram = 0; -+ val->freeram = nr_free_pages(); -+ val->bufferram = atomic_read(&buffermem_pages); -+ val->totalhigh = highmem >> PAGE_SHIFT; -+ val->freehigh = nr_free_highpages(); -+ val->mem_unit = PAGE_SIZE; -+ if(meminfo_22){ -+ val->freeram <<= PAGE_SHIFT; -+ val->bufferram <<= PAGE_SHIFT; -+ val->totalram <<= PAGE_SHIFT; -+ val->sharedram <<= PAGE_SHIFT; -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/mem_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/mem_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/mem_user.c 2005-05-03 22:28:14.433416000 +0300 -@@ -0,0 +1,271 @@ -+/* -+ * arch/um/kernel/mem_user.c -+ * -+ * BRIEF MODULE DESCRIPTION -+ * user side memory routines for supporting IO memory inside user mode linux -+ * -+ * Copyright (C) 2001 RidgeRun, Inc. -+ * Author: RidgeRun, Inc. -+ * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com -+ * -+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * 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. -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stddef.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <errno.h> -+#include <string.h> -+#include <fcntl.h> -+#include <sys/types.h> -+#include <sys/mman.h> -+#include "kern_util.h" -+#include "user.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "init.h" -+#include "os.h" -+#include "tempfile.h" -+#include "kern_constants.h" -+ -+extern struct mem_region physmem_region; -+ -+#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" -+ -+static int create_tmp_file(unsigned long len) -+{ -+ int fd, err; -+ char zero; -+ -+ fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); -+ if(fd < 0) { -+ os_print_error(fd, "make_tempfile"); -+ exit(1); -+ } -+ -+ err = os_mode_fd(fd, 0777); -+ if(err < 0){ -+ os_print_error(err, "os_mode_fd"); -+ exit(1); -+ } -+ err = os_seek_file(fd, len); -+ if(err < 0){ -+ os_print_error(err, "os_seek_file"); -+ exit(1); -+ } -+ zero = 0; -+ err = os_write_file(fd, &zero, 1); -+ if(err != 1){ -+ os_print_error(err, "os_write_file"); -+ exit(1); -+ } -+ -+ return(fd); -+} -+ -+void check_tmpexec(void) -+{ -+ void *addr; -+ int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); -+ -+ addr = mmap(NULL, UM_KERN_PAGE_SIZE, -+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); -+ printf("Checking PROT_EXEC mmap in /tmp..."); -+ fflush(stdout); -+ if(addr == MAP_FAILED){ -+ err = errno; -+ perror("failed"); -+ if(err == EPERM) -+ printf("/tmp must be not mounted noexec\n"); -+ exit(1); -+ } -+ printf("OK\n"); -+ munmap(addr, UM_KERN_PAGE_SIZE); -+} -+ -+static int have_devanon(void) -+{ -+ int fd; -+ -+ printk("Checking for /dev/anon on the host..."); -+ fd = open("/dev/anon", O_RDWR); -+ if(fd < 0){ -+ printk("Not available (open failed with errno %d)\n", errno); -+ return(0); -+ } -+ -+ printk("OK\n"); -+ return(1); -+} -+ -+static int create_anon_file(unsigned long len) -+{ -+ void *addr; -+ int fd; -+ -+ fd = open("/dev/anon", O_RDWR); -+ if(fd < 0) { -+ os_print_error(fd, "opening /dev/anon"); -+ exit(1); -+ } -+ -+ addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); -+ if(addr == MAP_FAILED){ -+ os_print_error((int) addr, "mapping physmem file"); -+ exit(1); -+ } -+ munmap(addr, len); -+ -+ return(fd); -+} -+ -+int create_mem_file(unsigned long len) -+{ -+ int err, fd; -+ -+ if(have_devanon()) -+ fd = create_anon_file(len); -+ else fd = create_tmp_file(len); -+ -+ err = os_set_exec_close(fd, 1); -+ if(err < 0) -+ os_print_error(err, "exec_close"); -+ return(fd); -+} -+ -+struct iomem_region *iomem_regions = NULL; -+int iomem_size = 0; -+ -+static int __init parse_iomem(char *str, int *add) -+{ -+ struct iomem_region *new; -+ struct uml_stat buf; -+ char *file, *driver; -+ int fd, err, size; -+ -+ driver = str; -+ file = strchr(str,','); -+ if(file == NULL){ -+ printf("parse_iomem : failed to parse iomem\n"); -+ goto out; -+ } -+ *file = '\0'; -+ file++; -+ fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); -+ if(fd < 0){ -+ os_print_error(fd, "parse_iomem - Couldn't open io file"); -+ goto out; -+ } -+ -+ err = os_stat_fd(fd, &buf); -+ if(err < 0){ -+ os_print_error(err, "parse_iomem - cannot stat_fd file"); -+ goto out_close; -+ } -+ -+ new = malloc(sizeof(*new)); -+ if(new == NULL){ -+ perror("Couldn't allocate iomem_region struct"); -+ goto out_close; -+ } -+ -+ size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); -+ -+ *new = ((struct iomem_region) { .next = iomem_regions, -+ .driver = driver, -+ .fd = fd, -+ .size = size, -+ .phys = 0, -+ .virt = 0 }); -+ iomem_regions = new; -+ iomem_size += new->size + UM_KERN_PAGE_SIZE; -+ -+ return(0); -+ out_close: -+ os_close_file(fd); -+ out: -+ return(1); -+} -+ -+__uml_setup("iomem=", parse_iomem, -+"iomem=<name>,<file>\n" -+" Configure <file> as an IO memory region named <name>.\n\n" -+); -+ -+int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, -+ int must_succeed) -+{ -+ int err; -+ -+ err = os_protect_memory((void *) addr, len, r, w, x); -+ if(err < 0){ -+ if(must_succeed) -+ panic("protect failed, err = %d", -err); -+ else return(err); -+ } -+ return(0); -+} -+ -+#if 0 -+/* Debugging facility for dumping stuff out to the host, avoiding the timing -+ * problems that come with printf and breakpoints. -+ * Enable in case of emergency. -+ */ -+ -+int logging = 1; -+int logging_fd = -1; -+ -+int logging_line = 0; -+char logging_buf[512]; -+ -+void log(char *fmt, ...) -+{ -+ va_list ap; -+ struct timeval tv; -+ struct openflags flags; -+ -+ if(logging == 0) return; -+ if(logging_fd < 0){ -+ flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); -+ logging_fd = os_open_file("log", flags, 0644); -+ } -+ gettimeofday(&tv, NULL); -+ sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, -+ tv.tv_usec); -+ va_start(ap, fmt); -+ vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); -+ va_end(ap); -+ write(logging_fd, logging_buf, strlen(logging_buf)); -+} -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/physmem.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/physmem.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/physmem.c 2005-05-03 22:28:14.436415544 +0300 -@@ -0,0 +1,480 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/mm.h" -+#include "linux/rbtree.h" -+#include "linux/slab.h" -+#include "linux/vmalloc.h" -+#include "linux/bootmem.h" -+#include "asm/types.h" -+#include "asm/pgtable.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "mode_kern.h" -+#include "mem.h" -+#include "mem_user.h" -+#include "os.h" -+#include "kern.h" -+#include "init.h" -+ -+struct phys_desc { -+ struct rb_node_s rb; -+ int fd; -+ __u64 offset; -+ void *virt; -+ unsigned long phys; -+ struct list_head list; -+}; -+ -+static struct rb_root_s phys_mappings = RB_ROOT; -+ -+static struct rb_node_s **find_rb(void *virt) -+{ -+ struct rb_node_s **n = &phys_mappings.rb_node; -+ struct phys_desc *d; -+ -+ while(*n != NULL){ -+ d = rb_entry(n, struct phys_desc, rb); -+ if(d->virt == virt) -+ return(n); -+ -+ if(d->virt > virt) -+ n = &(*n)->rb_left; -+ else -+ n = &(*n)->rb_right; -+ } -+ -+ return(n); -+} -+ -+static struct phys_desc *find_phys_mapping(void *virt) -+{ -+ struct rb_node_s **n = find_rb(virt); -+ -+ if(*n == NULL) -+ return(NULL); -+ -+ return(rb_entry(n, struct phys_desc, rb)); -+} -+ -+static void insert_phys_mapping(struct phys_desc *desc) -+{ -+ struct rb_node_s **n = find_rb(desc->virt); -+ -+ if(*n != NULL) -+ panic("Physical remapping for %p already present", -+ desc->virt); -+ -+ rb_link_node(&desc->rb, (*n)->rb_parent, n); -+ rb_insert_color(&desc->rb, &phys_mappings); -+} -+ -+LIST_HEAD(descriptor_mappings); -+ -+struct desc_mapping { -+ int fd; -+ struct list_head list; -+ struct list_head pages; -+}; -+ -+static struct desc_mapping *find_mapping(int fd) -+{ -+ struct desc_mapping *desc; -+ struct list_head *ele; -+ -+ list_for_each(ele, &descriptor_mappings){ -+ desc = list_entry(ele, struct desc_mapping, list); -+ if(desc->fd == fd) -+ return(desc); -+ } -+ -+ return(NULL); -+} -+ -+static struct desc_mapping *descriptor_mapping(int fd) -+{ -+ struct desc_mapping *desc; -+ -+ desc = find_mapping(fd); -+ if(desc != NULL) -+ return(desc); -+ -+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC); -+ if(desc == NULL) -+ return(NULL); -+ -+ *desc = ((struct desc_mapping) -+ { .fd = fd, -+ .list = LIST_HEAD_INIT(desc->list), -+ .pages = LIST_HEAD_INIT(desc->pages) }); -+ list_add(&desc->list, &descriptor_mappings); -+ -+ return(desc); -+} -+ -+int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) -+{ -+ struct desc_mapping *fd_maps; -+ struct phys_desc *desc; -+ unsigned long phys; -+ int err; -+ -+ phys = __pa(virt); -+ desc = find_phys_mapping(virt); -+ if(desc != NULL){ -+ if((virt != desc->virt) || (fd != desc->fd) || -+ (offset != desc->offset)) -+ panic("Address 0x%p is already substituted\n", virt); -+ return(0); -+ } -+ -+ fd_maps = descriptor_mapping(fd); -+ if(fd_maps == NULL) -+ return(-ENOMEM); -+ -+ err = -ENOMEM; -+ desc = kmalloc(sizeof(*desc), GFP_ATOMIC); -+ if(desc == NULL) -+ goto out; -+ -+ *desc = ((struct phys_desc) -+ { .fd = fd, -+ .offset = offset, -+ .virt = virt, -+ .phys = __pa(virt), -+ .list = LIST_HEAD_INIT(desc->list) }); -+ insert_phys_mapping(desc); -+ -+ list_add(&desc->list, &fd_maps->pages); -+ -+ virt = (void *) ((unsigned long) virt & PAGE_MASK); -+ err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0); -+ if(!err) -+ goto out; -+ -+ rb_erase(&desc->rb, &phys_mappings); -+ kfree(desc); -+ out: -+ return(err); -+} -+ -+static int physmem_fd = -1; -+ -+static void remove_mapping(struct phys_desc *desc) -+{ -+ void *virt = desc->virt; -+ int err; -+ -+ rb_erase(&desc->rb, &phys_mappings); -+ list_del(&desc->list); -+ kfree(desc); -+ -+ err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0); -+ if(err) -+ panic("Failed to unmap block device page from physical memory, " -+ "errno = %d", -err); -+} -+ -+int physmem_remove_mapping(void *virt) -+{ -+ struct phys_desc *desc; -+ -+ virt = (void *) ((unsigned long) virt & PAGE_MASK); -+ desc = find_phys_mapping(virt); -+ if(desc == NULL) -+ return(0); -+ -+ remove_mapping(desc); -+ return(1); -+} -+ -+void physmem_forget_descriptor(int fd) -+{ -+ struct desc_mapping *desc; -+ struct phys_desc *page; -+ struct list_head *ele, *next; -+ __u64 offset; -+ void *addr; -+ int err; -+ -+ desc = find_mapping(fd); -+ if(desc == NULL) -+ return; -+ -+ if(!list_empty(&desc->pages)) -+ printk("Still have mapped pages on fd %d\n", fd); -+ -+ list_for_each_safe(ele, next, &desc->pages){ -+ page = list_entry(ele, struct phys_desc, list); -+ offset = page->offset; -+ addr = page->virt; -+ remove_mapping(page); -+ err = os_seek_file(fd, offset); -+ if(err) -+ panic("physmem_forget_descriptor - failed to seek " -+ "to %lld in fd %d, error = %d\n", -+ offset, fd, -err); -+ err = os_read_file(fd, addr, PAGE_SIZE); -+ if(err < 0) -+ panic("physmem_forget_descriptor - failed to read " -+ "from fd %d to 0x%p, error = %d\n", -+ fd, addr, -err); -+ } -+ -+ list_del(&desc->list); -+ kfree(desc); -+} -+ -+void arch_free_page(struct page *page, int order) -+{ -+ void *virt; -+ int i; -+ -+ for(i = 0; i < (1 << order); i++){ -+ virt = __va(page_to_phys(page + i)); -+ physmem_remove_mapping(virt); -+ } -+} -+ -+int is_remapped(const void *virt, int fd, __u64 offset) -+{ -+ struct phys_desc *desc; -+ -+ desc = find_phys_mapping((void *) virt); -+ if(desc == NULL) -+ return(0); -+ if(offset != desc->offset) -+ printk("offset mismatch\n"); -+ return(find_phys_mapping((void *) virt) != NULL); -+} -+ -+/* Changed during early boot */ -+unsigned long high_physmem; -+ -+extern unsigned long physmem_size; -+ -+void *to_virt(unsigned long phys) -+{ -+ return((void *) uml_physmem + phys); -+} -+ -+unsigned long to_phys(void *virt) -+{ -+ return(((unsigned long) virt) - uml_physmem); -+} -+ -+int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) -+{ -+ struct page *p, *map; -+ unsigned long phys_len, phys_pages, highmem_len, highmem_pages; -+ unsigned long iomem_len, iomem_pages, total_len, total_pages; -+ int i; -+ -+ phys_pages = physmem >> PAGE_SHIFT; -+ phys_len = phys_pages * sizeof(struct page); -+ -+ iomem_pages = iomem >> PAGE_SHIFT; -+ iomem_len = iomem_pages * sizeof(struct page); -+ -+ highmem_pages = highmem >> PAGE_SHIFT; -+ highmem_len = highmem_pages * sizeof(struct page); -+ -+ total_pages = phys_pages + iomem_pages + highmem_pages; -+ total_len = phys_len + iomem_pages + highmem_len; -+ -+ if(kmalloc_ok){ -+ map = kmalloc(total_len, GFP_KERNEL); -+ if(map == NULL) -+ map = vmalloc(total_len); -+ } -+ else map = alloc_bootmem_low_pages(total_len); -+ -+ if(map == NULL) -+ return(-ENOMEM); -+ -+ for(i = 0; i < total_pages; i++){ -+ p = &map[i]; -+ set_page_count(p, 0); -+ SetPageReserved(p); -+ INIT_LIST_HEAD(&p->list); -+ } -+ -+ mem_map = map; -+ max_mapnr = total_pages; -+ return(0); -+} -+ -+struct page *phys_to_page(const unsigned long phys) -+{ -+ return(&mem_map[phys >> PAGE_SHIFT]); -+} -+ -+struct page *__virt_to_page(const unsigned long virt) -+{ -+ return(&mem_map[__pa(virt) >> PAGE_SHIFT]); -+} -+ -+unsigned long page_to_phys(struct page *page) -+{ -+ return((page - mem_map) << PAGE_SHIFT); -+} -+ -+pte_t mk_pte(struct page *page, pgprot_t pgprot) -+{ -+ pte_t pte; -+ -+ pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot); -+ if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte)); -+ return(pte); -+} -+ -+/* Changed during early boot */ -+static unsigned long kmem_top = 0; -+ -+unsigned long get_kmem_end(void) -+{ -+ if(kmem_top == 0) -+ kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); -+ return(kmem_top); -+} -+ -+void map_memory(unsigned long virt, unsigned long phys, unsigned long len, -+ int r, int w, int x) -+{ -+ __u64 offset; -+ int fd, err; -+ -+ fd = phys_mapping(phys, &offset); -+ err = os_map_memory((void *) virt, fd, offset, len, r, w, x); -+ if(err) -+ panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " -+ "err = %d\n", virt, fd, offset, len, r, w, x, err); -+} -+ -+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -+ -+void setup_physmem(unsigned long start, unsigned long reserve_end, -+ unsigned long len, unsigned long highmem) -+{ -+ unsigned long reserve = reserve_end - start; -+ int pfn = PFN_UP(__pa(reserve_end)); -+ int delta = (len - reserve) >> PAGE_SHIFT; -+ int err, offset, bootmap_size; -+ -+ physmem_fd = create_mem_file(len + highmem); -+ -+ offset = uml_reserved - uml_physmem; -+ err = os_map_memory((void *) uml_reserved, physmem_fd, offset, -+ len - offset, 1, 1, 0); -+ if(err < 0){ -+ os_print_error(err, "Mapping memory"); -+ exit(1); -+ } -+ -+ bootmap_size = init_bootmem(pfn, pfn + delta); -+ free_bootmem(__pa(reserve_end) + bootmap_size, -+ len - bootmap_size - reserve); -+} -+ -+int phys_mapping(unsigned long phys, __u64 *offset_out) -+{ -+ struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK)); -+ int fd = -1; -+ -+ if(desc != NULL){ -+ fd = desc->fd; -+ *offset_out = desc->offset; -+ } -+ else if(phys < physmem_size){ -+ fd = physmem_fd; -+ *offset_out = phys; -+ } -+ else if(phys < __pa(end_iomem)){ -+ struct iomem_region *region = iomem_regions; -+ -+ while(region != NULL){ -+ if((phys >= region->phys) && -+ (phys < region->phys + region->size)){ -+ fd = region->fd; -+ *offset_out = phys - region->phys; -+ break; -+ } -+ region = region->next; -+ } -+ } -+ else if(phys < __pa(end_iomem) + highmem){ -+ fd = physmem_fd; -+ *offset_out = phys - iomem_size; -+ } -+ -+ return(fd); -+} -+ -+static int __init uml_mem_setup(char *line, int *add) -+{ -+ char *retptr; -+ physmem_size = memparse(line,&retptr); -+ return 0; -+} -+__uml_setup("mem=", uml_mem_setup, -+"mem=<Amount of desired ram>\n" -+" This controls how much \"physical\" memory the kernel allocates\n" -+" for the system. The size is specified as a number followed by\n" -+" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" -+" This is not related to the amount of memory in the host. It can\n" -+" be more, and the excess, if it's ever used, will just be swapped out.\n" -+" Example: mem=64M\n\n" -+); -+ -+unsigned long find_iomem(char *driver, unsigned long *len_out) -+{ -+ struct iomem_region *region = iomem_regions; -+ -+ while(region != NULL){ -+ if(!strcmp(region->driver, driver)){ -+ *len_out = region->size; -+ return(region->virt); -+ } -+ } -+ -+ return(0); -+} -+ -+int setup_iomem(void) -+{ -+ struct iomem_region *region = iomem_regions; -+ unsigned long iomem_start = high_physmem + PAGE_SIZE; -+ int err; -+ -+ while(region != NULL){ -+ err = os_map_memory((void *) iomem_start, region->fd, 0, -+ region->size, 1, 1, 0); -+ if(err) -+ printk("Mapping iomem region for driver '%s' failed, " -+ "errno = %d\n", region->driver, -err); -+ else { -+ region->virt = iomem_start; -+ region->phys = __pa(region->virt); -+ } -+ -+ iomem_start += region->size + PAGE_SIZE; -+ region = region->next; -+ } -+ -+ return(0); -+} -+ -+__initcall(setup_iomem); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/process.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/process.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/process.c 2005-05-03 22:28:14.437415392 +0300 -@@ -0,0 +1,310 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <signal.h> -+#include <sched.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <stdlib.h> -+#include <setjmp.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <sys/mman.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include <asm/unistd.h> -+#include <asm/page.h> -+#include <asm/user.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+#include "irq_user.h" -+#include "ptrace_user.h" -+#include "time_user.h" -+#include "init.h" -+#include "os.h" -+#include "uml-config.h" -+#include "choose-mode.h" -+#include "mode.h" -+#ifdef UML_CONFIG_MODE_SKAS -+#include "skas.h" -+#include "skas_ptrace.h" -+#endif -+ -+void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) -+{ -+ int flags = 0, pages; -+ -+ if(sig_stack != NULL){ -+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER); -+ set_sigstack(sig_stack, pages * page_size()); -+ flags = SA_ONSTACK; -+ } -+ if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1); -+} -+ -+void init_new_thread_signals(int altstack) -+{ -+ int flags = altstack ? SA_ONSTACK : 0; -+ -+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGFPE, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGILL, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, -+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ set_handler(SIGUSR2, (__sighandler_t) sig_handler, -+ flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); -+ signal(SIGHUP, SIG_IGN); -+ -+ init_irq_signals(altstack); -+} -+ -+struct tramp { -+ int (*tramp)(void *); -+ void *tramp_data; -+ unsigned long temp_stack; -+ int flags; -+ int pid; -+}; -+ -+/* See above for why sigkill is here */ -+ -+int sigkill = SIGKILL; -+ -+int outer_tramp(void *arg) -+{ -+ struct tramp *t; -+ int sig = sigkill; -+ -+ t = arg; -+ t->pid = clone(t->tramp, (void *) t->temp_stack + page_size()/2, -+ t->flags, t->tramp_data); -+ if(t->pid > 0) wait_for_stop(t->pid, SIGSTOP, PTRACE_CONT, NULL); -+ kill(os_getpid(), sig); -+ _exit(0); -+} -+ -+int start_fork_tramp(void *thread_arg, unsigned long temp_stack, -+ int clone_flags, int (*tramp)(void *)) -+{ -+ struct tramp arg; -+ unsigned long sp; -+ int new_pid, status, err; -+ -+ /* The trampoline will run on the temporary stack */ -+ sp = stack_sp(temp_stack); -+ -+ clone_flags |= CLONE_FILES | SIGCHLD; -+ -+ arg.tramp = tramp; -+ arg.tramp_data = thread_arg; -+ arg.temp_stack = temp_stack; -+ arg.flags = clone_flags; -+ -+ /* Start the process and wait for it to kill itself */ -+ new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); -+ if(new_pid < 0) -+ return(new_pid); -+ -+ CATCH_EINTR(err = waitpid(new_pid, &status, 0)); -+ if(err < 0) -+ panic("Waiting for outer trampoline failed - errno = %d", -+ errno); -+ -+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) -+ panic("outer trampoline didn't exit with SIGKILL, " -+ "status = %d", status); -+ -+ return(arg.pid); -+} -+ -+static int ptrace_child(void *arg) -+{ -+ int pid = os_getpid(); -+ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ perror("ptrace"); -+ os_kill_process(pid, 0); -+ } -+ os_stop_process(pid); -+ _exit(os_getpid() == pid); -+} -+ -+static int start_ptraced_child(void **stack_out) -+{ -+ void *stack; -+ unsigned long sp; -+ int pid, n, status; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if(stack == MAP_FAILED) -+ panic("check_ptrace : mmap failed, errno = %d", errno); -+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); -+ if(pid < 0) -+ panic("check_ptrace : clone failed, errno = %d", errno); -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) -+ panic("check_ptrace : expected SIGSTOP, got status = %d", -+ status); -+ -+ *stack_out = stack; -+ return(pid); -+} -+ -+static void stop_ptraced_child(int pid, void *stack, int exitcode) -+{ -+ int status, n; -+ -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) -+ panic("check_ptrace : ptrace failed, errno = %d", errno); -+ CATCH_EINTR(n = waitpid(pid, &status, 0)); -+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) -+ panic("check_ptrace : child exited with status 0x%x", status); -+ -+ if(munmap(stack, PAGE_SIZE) < 0) -+ panic("check_ptrace : munmap failed, errno = %d", errno); -+} -+ -+int use_sysemu = 0; -+ -+void __init check_ptrace(void) -+{ -+ void *stack; -+ int pid, syscall, n, status; -+ -+ printk("Checking that ptrace can change system call numbers..."); -+ pid = start_ptraced_child(&stack); -+ -+ while(1){ -+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) -+ panic("check_ptrace : ptrace failed, errno = %d", -+ errno); -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -+ panic("check_ptrace : expected SIGTRAP, " -+ "got status = %d", status); -+ -+ syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, -+ 0); -+ if(syscall == __NR_getpid){ -+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getppid); -+ if(n < 0) -+ panic("check_ptrace : failed to modify system " -+ "call, errno = %d", errno); -+ break; -+ } -+ } -+ stop_ptraced_child(pid, stack, 0); -+ printk("OK\n"); -+ -+ printk("Checking syscall emulation patch for ptrace..."); -+ pid = start_ptraced_child(&stack); -+ if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) { -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0) -+ panic("check_ptrace : wait failed, errno = %d", errno); -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -+ panic("check_ptrace : expected SIGTRAP, " -+ "got status = %d", status); -+ -+ -+ n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, -+ os_getpid()); -+ if(n < 0) -+ panic("check_ptrace : failed to modify system " -+ "call return, errno = %d", errno); -+ -+ stop_ptraced_child(pid, stack, 0); -+ -+ printk("OK\n"); -+ use_sysemu = 1; -+ } -+ else { -+ printk("missing\n"); -+ stop_ptraced_child(pid, stack, 1); -+ } -+} -+ -+int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) -+{ -+ sigjmp_buf buf; -+ int n; -+ -+ *jmp_ptr = &buf; -+ n = sigsetjmp(buf, 1); -+ if(n != 0) -+ return(n); -+ (*fn)(arg); -+ return(0); -+} -+ -+int can_do_skas(void) -+{ -+#ifdef UML_CONFIG_MODE_SKAS -+ struct ptrace_faultinfo fi; -+ void *stack; -+ int pid, n, ret = 1; -+ -+ printf("Checking for the skas3 patch in the host..."); -+ pid = start_ptraced_child(&stack); -+ -+ n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); -+ if(n < 0){ -+ if(errno == EIO) -+ printf("not found\n"); -+ else printf("No (unexpected errno - %d)\n", errno); -+ ret = 0; -+ } -+ else printf("found\n"); -+ -+ init_registers(pid); -+ stop_ptraced_child(pid, stack, 1); -+ -+ printf("Checking for /proc/mm..."); -+ if(os_access("/proc/mm", OS_ACC_W_OK) < 0){ -+ printf("not found\n"); -+ ret = 0; -+ } -+ else printf("found\n"); -+ -+ return(ret); -+#else -+ return(0); -+#endif -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/process_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/process_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/process_kern.c 2005-05-03 22:28:14.439415088 +0300 -@@ -0,0 +1,413 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/interrupt.h" -+#include "linux/mm.h" -+#include "linux/slab.h" -+#include "linux/utsname.h" -+#include "linux/fs.h" -+#include "linux/utime.h" -+#include "linux/smp_lock.h" -+#include "linux/module.h" -+#include "linux/init.h" -+#include "linux/capability.h" -+#include "linux/vmalloc.h" -+#include "linux/ptrace.h" -+#include "asm/unistd.h" -+#include "asm/mman.h" -+#include "asm/segment.h" -+#include "asm/stat.h" -+#include "asm/pgtable.h" -+#include "asm/processor.h" -+#include "asm/pgalloc.h" -+#include "asm/spinlock.h" -+#include "asm/uaccess.h" -+#include "asm/user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "init.h" -+#include "irq_user.h" -+#include "mem_user.h" -+#include "time_user.h" -+#include "tlb.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "2_5compat.h" -+#include "os.h" -+#include "mode.h" -+#include "mode_kern.h" -+#include "choose-mode.h" -+ -+/* This is a per-cpu array. A processor only modifies its entry and it only -+ * cares about its entry, so it's OK if another processor is modifying its -+ * entry. -+ */ -+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; -+ -+struct task_struct *get_task(int pid, int require) -+{ -+ struct task_struct *ret; -+ -+ read_lock(&tasklist_lock); -+ ret = find_task_by_pid(pid); -+ read_unlock(&tasklist_lock); -+ -+ if(require && (ret == NULL)) panic("get_task couldn't find a task\n"); -+ return(ret); -+} -+ -+int external_pid(void *t) -+{ -+ struct task_struct *task = t ? t : current; -+ -+ return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task)); -+} -+ -+int pid_to_processor_id(int pid) -+{ -+ int i; -+ -+ for(i = 0; i < smp_num_cpus; i++){ -+ if(cpu_tasks[i].pid == pid) return(i); -+ } -+ return(-1); -+} -+ -+void free_stack(unsigned long stack, int order) -+{ -+ free_pages(stack, order); -+} -+ -+unsigned long alloc_stack(int order, int atomic) -+{ -+ unsigned long page; -+ int flags = GFP_KERNEL; -+ -+ if(atomic) flags |= GFP_ATOMIC; -+ page = __get_free_pages(flags, order); -+ if(page == 0) -+ return(0); -+ stack_protections(page); -+ return(page); -+} -+ -+int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -+{ -+ int pid; -+ -+ current->thread.request.u.thread.proc = fn; -+ current->thread.request.u.thread.arg = arg; -+ pid = do_fork(CLONE_VM | flags, 0, NULL, 0); -+#if 0 /* CLONE_UNTRACED for 2.6 */ -+ pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0); -+#endif -+ if(pid < 0) -+ panic("do_fork failed in kernel_thread, errno = %d", pid); -+ return(pid); -+} -+ -+void switch_mm(struct mm_struct *prev, struct mm_struct *next, -+ struct task_struct *tsk, unsigned cpu) -+{ -+ if (prev != next) -+ clear_bit(cpu, &prev->cpu_vm_mask); -+ set_bit(cpu, &next->cpu_vm_mask); -+} -+ -+void set_current(void *t) -+{ -+ struct task_struct *task = t; -+ -+ cpu_tasks[task->processor] = ((struct cpu_task) -+ { external_pid(task), task }); -+} -+ -+void *_switch_to(void *prev, void *next) -+{ -+ return(CHOOSE_MODE(_switch_to_tt(prev, next), -+ _switch_to_skas(prev, next))); -+} -+ -+void interrupt_end(void) -+{ -+ if(current->need_resched) schedule(); -+ if(current->sigpending != 0) do_signal(0); -+} -+ -+void release_thread(struct task_struct *task) -+{ -+ CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task)); -+} -+ -+void exit_thread(void) -+{ -+ CHOOSE_MODE(exit_thread_tt(), exit_thread_skas()); -+ unprotect_stack((unsigned long) current); -+} -+ -+void *get_current(void) -+{ -+ return(current); -+} -+ -+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ p->thread = (struct thread_struct) INIT_THREAD; -+ return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, -+ clone_flags, sp, stack_top, p, regs)); -+} -+ -+void initial_thread_cb(void (*proc)(void *), void *arg) -+{ -+ int save_kmalloc_ok = kmalloc_ok; -+ -+ kmalloc_ok = 0; -+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, -+ arg); -+ kmalloc_ok = save_kmalloc_ok; -+} -+ -+unsigned long stack_sp(unsigned long page) -+{ -+ return(page + PAGE_SIZE - sizeof(void *)); -+} -+ -+int current_pid(void) -+{ -+ return(current->pid); -+} -+ -+void cpu_idle(void) -+{ -+ CHOOSE_MODE(init_idle_tt(), init_idle_skas()); -+ -+ atomic_inc(&init_mm.mm_count); -+ current->mm = &init_mm; -+ current->active_mm = &init_mm; -+ -+ while(1){ -+ /* endless idle loop with no priority at all */ -+ SET_PRI(current); -+ -+ /* -+ * although we are an idle CPU, we do not want to -+ * get into the scheduler unnecessarily. -+ */ -+ if (current->need_resched) { -+ schedule(); -+ check_pgt_cache(); -+ } -+ idle_sleep(10); -+ } -+} -+ -+int page_size(void) -+{ -+ return(PAGE_SIZE); -+} -+ -+int page_mask(void) -+{ -+ return(PAGE_MASK); -+} -+ -+void *um_virt_to_phys(struct task_struct *task, unsigned long addr, -+ pte_t *pte_out) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ -+ if(task->mm == NULL) -+ return(ERR_PTR(-EINVAL)); -+ pgd = pgd_offset(task->mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(!pmd_present(*pmd)) -+ return(ERR_PTR(-EINVAL)); -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte)) -+ return(ERR_PTR(-EINVAL)); -+ if(pte_out != NULL) -+ *pte_out = *pte; -+ return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); -+} -+ -+char *current_cmd(void) -+{ -+#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM) -+ return("(Unknown)"); -+#else -+ void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL); -+ return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr); -+#endif -+} -+ -+void force_sigbus(void) -+{ -+ printk(KERN_ERR "Killing pid %d because of a lack of memory\n", -+ current->pid); -+ lock_kernel(); -+ sigaddset(¤t->pending.signal, SIGBUS); -+ recalc_sigpending(current); -+ current->flags |= PF_SIGNALED; -+ do_exit(SIGBUS | 0x80); -+} -+ -+void dump_thread(struct pt_regs *regs, struct user *u) -+{ -+} -+ -+void enable_hlt(void) -+{ -+ panic("enable_hlt"); -+} -+ -+void disable_hlt(void) -+{ -+ panic("disable_hlt"); -+} -+ -+extern int signal_frame_size; -+ -+void *um_kmalloc(int size) -+{ -+ return(kmalloc(size, GFP_KERNEL)); -+} -+ -+void *um_kmalloc_atomic(int size) -+{ -+ return(kmalloc(size, GFP_ATOMIC)); -+} -+ -+void *um_vmalloc(int size) -+{ -+ return(vmalloc(size)); -+} -+ -+unsigned long get_fault_addr(void) -+{ -+ return((unsigned long) current->thread.fault_addr); -+} -+ -+EXPORT_SYMBOL(get_fault_addr); -+ -+void not_implemented(void) -+{ -+ printk(KERN_DEBUG "Something isn't implemented in here\n"); -+} -+ -+EXPORT_SYMBOL(not_implemented); -+ -+int user_context(unsigned long sp) -+{ -+ unsigned long stack; -+ -+ stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER); -+ return(stack != current); -+} -+ -+extern void remove_umid_dir(void); -+ -+__uml_exitcall(remove_umid_dir); -+ -+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; -+ -+void do_uml_exitcalls(void) -+{ -+ exitcall_t *call; -+ -+ call = &__uml_exitcall_end; -+ while (--call >= &__uml_exitcall_begin) -+ (*call)(); -+} -+ -+char *uml_strdup(char *string) -+{ -+ char *new; -+ -+ new = kmalloc(strlen(string) + 1, GFP_KERNEL); -+ if(new == NULL) return(NULL); -+ strcpy(new, string); -+ return(new); -+} -+ -+void *get_init_task(void) -+{ -+ return(&init_task_union.task); -+} -+ -+int copy_to_user_proc(void *to, void *from, int size) -+{ -+ return(copy_to_user(to, from, size)); -+} -+ -+int copy_from_user_proc(void *to, void *from, int size) -+{ -+ return(copy_from_user(to, from, size)); -+} -+ -+int clear_user_proc(void *buf, int size) -+{ -+ return(clear_user(buf, size)); -+} -+ -+int strlen_user_proc(char *str) -+{ -+ return(strlen_user(str)); -+} -+ -+int smp_sigio_handler(void) -+{ -+#ifdef CONFIG_SMP -+ int cpu = current->processor; -+ -+ IPI_handler(cpu); -+ if(cpu != 0) -+ return(1); -+#endif -+ return(0); -+} -+ -+int um_in_interrupt(void) -+{ -+ return(in_interrupt()); -+} -+ -+int cpu(void) -+{ -+ return(current->processor); -+} -+ -+int singlestepping(void * t) -+{ -+ struct task_struct *task = t ? t : current; -+ -+ if ( ! (task->ptrace & PT_DTRACE) ) -+ return(0); -+ -+ if (task->thread.singlestep_syscall) -+ return(0); -+ -+ return 1; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/ptrace.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/ptrace.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/ptrace.c 2005-05-03 22:28:14.441414784 +0300 -@@ -0,0 +1,341 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/mm.h" -+#include "linux/errno.h" -+#include "linux/smp_lock.h" -+#ifdef CONFIG_PROC_MM -+#include "linux/proc_mm.h" -+#endif -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+ -+/* -+ * Called by kernel/ptrace.c when detaching.. -+ */ -+void ptrace_disable(struct task_struct *child) -+{ -+ child->ptrace &= ~PT_DTRACE; -+ child->thread.singlestep_syscall = 0; -+} -+ -+extern long do_mmap2(struct task_struct *task, unsigned long addr, -+ unsigned long len, unsigned long prot, -+ unsigned long flags, unsigned long fd, -+ unsigned long pgoff); -+ -+int sys_ptrace(long request, long pid, long addr, long data) -+{ -+ struct task_struct *child; -+ int i, ret; -+ -+ lock_kernel(); -+ ret = -EPERM; -+ if (request == PTRACE_TRACEME) { -+ /* are we already being traced? */ -+ if (current->ptrace & PT_PTRACED) -+ goto out; -+ /* set the ptrace bit in the process flags. */ -+ current->ptrace |= PT_PTRACED; -+ ret = 0; -+ goto out; -+ } -+ ret = -ESRCH; -+ read_lock(&tasklist_lock); -+ child = find_task_by_pid(pid); -+ if (child) -+ get_task_struct(child); -+ read_unlock(&tasklist_lock); -+ if (!child) -+ goto out; -+ -+ ret = -EPERM; -+ if (pid == 1) /* you may not mess with init */ -+ goto out_tsk; -+ -+ if (request == PTRACE_ATTACH) { -+ ret = ptrace_attach(child); -+ goto out_tsk; -+ } -+ -+ ret = ptrace_check_attach(child, request == PTRACE_KILL); -+ if (ret < 0) -+ goto out_tsk; -+ -+ switch (request) { -+ /* when I and D space are separate, these will need to be fixed. */ -+ case PTRACE_PEEKTEXT: /* read word at location addr. */ -+ case PTRACE_PEEKDATA: { -+ unsigned long tmp; -+ int copied; -+ -+ ret = -EIO; -+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); -+ if (copied != sizeof(tmp)) -+ break; -+ ret = put_user(tmp,(unsigned long *) data); -+ break; -+ } -+ -+ /* read the word at location addr in the USER area. */ -+ case PTRACE_PEEKUSR: { -+ unsigned long tmp; -+ -+ ret = -EIO; -+ if ((addr & 3) || addr < 0) -+ break; -+ -+ tmp = 0; /* Default return condition */ -+ if(addr < FRAME_SIZE_OFFSET){ -+ tmp = getreg(child, addr); -+ } -+ else if((addr >= offsetof(struct user, u_debugreg[0])) && -+ (addr <= offsetof(struct user, u_debugreg[7]))){ -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ tmp = child->thread.arch.debugregs[addr]; -+ } -+ ret = put_user(tmp, (unsigned long *) data); -+ break; -+ } -+ -+ /* when I and D space are separate, this will have to be fixed. */ -+ case PTRACE_POKETEXT: /* write the word at location addr. */ -+ case PTRACE_POKEDATA: -+ ret = -EIO; -+ if (access_process_vm(child, addr, &data, sizeof(data), -+ 1) != sizeof(data)) -+ break; -+ ret = 0; -+ break; -+ -+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ -+ ret = -EIO; -+ if ((addr & 3) || addr < 0) -+ break; -+ -+ if (addr < FRAME_SIZE_OFFSET) { -+ ret = putreg(child, addr, data); -+ break; -+ } -+ else if((addr >= offsetof(struct user, u_debugreg[0])) && -+ (addr <= offsetof(struct user, u_debugreg[7]))){ -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ if((addr == 4) || (addr == 5)) break; -+ child->thread.arch.debugregs[addr] = data; -+ ret = 0; -+ } -+ -+ break; -+ -+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ -+ case PTRACE_CONT: { /* restart after signal. */ -+ ret = -EIO; -+ if ((unsigned long) data > _NSIG) -+ break; -+ -+ child->ptrace &= ~PT_DTRACE; -+ child->thread.singlestep_syscall = 0; -+ -+ if (request == PTRACE_SYSCALL) -+ child->ptrace |= PT_TRACESYS; -+ else -+ child->ptrace &= ~PT_TRACESYS; -+ child->exit_code = data; -+ wake_up_process(child); -+ ret = 0; -+ break; -+ } -+ -+/* -+ * make the child exit. Best I can do is send it a sigkill. -+ * perhaps it should be put in the status that it wants to -+ * exit. -+ */ -+ case PTRACE_KILL: { -+ ret = 0; -+ if (child->state == TASK_ZOMBIE) /* already dead */ -+ break; -+ -+ child->ptrace &= ~PT_DTRACE; -+ child->thread.singlestep_syscall = 0; -+ child->exit_code = SIGKILL; -+ wake_up_process(child); -+ break; -+ } -+ -+ case PTRACE_SINGLESTEP: { /* set the trap flag. */ -+ ret = -EIO; -+ if ((unsigned long) data > _NSIG) -+ break; -+ child->ptrace &= ~PT_TRACESYS; -+ child->ptrace |= PT_DTRACE; -+ child->thread.singlestep_syscall = 0; -+ child->exit_code = data; -+ /* give it a chance to run. */ -+ wake_up_process(child); -+ ret = 0; -+ break; -+ } -+ -+ case PTRACE_DETACH: -+ /* detach a process that was attached. */ -+ ret = ptrace_detach(child, data); -+ break; -+ -+#ifdef PTRACE_GETREGS -+ case PTRACE_GETREGS: { /* Get all gp regs from the child. */ -+ if (!access_ok(VERIFY_WRITE, (unsigned long *)data, -+ FRAME_SIZE_OFFSET)) { -+ ret = -EIO; -+ break; -+ } -+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { -+ __put_user(getreg(child, i), (unsigned long *) data); -+ data += sizeof(long); -+ } -+ ret = 0; -+ break; -+ } -+#endif -+#ifdef PTRACE_SETREGS -+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */ -+ unsigned long tmp = 0; -+ if (!access_ok(VERIFY_READ, (unsigned *)data, -+ FRAME_SIZE_OFFSET)) { -+ ret = -EIO; -+ break; -+ } -+ for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) { -+ __get_user(tmp, (unsigned long *) data); -+ putreg(child, i, tmp); -+ data += sizeof(long); -+ } -+ ret = 0; -+ break; -+ } -+#endif -+#ifdef PTRACE_GETFPREGS -+ case PTRACE_GETFPREGS: /* Get the child FPU state. */ -+ ret = get_fpregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_SETFPREGS -+ case PTRACE_SETFPREGS: /* Set the child FPU state. */ -+ ret = set_fpregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_GETFPXREGS -+ case PTRACE_GETFPXREGS: /* Get the child FPU state. */ -+ ret = get_fpxregs(data, child); -+ break; -+#endif -+#ifdef PTRACE_SETFPXREGS -+ case PTRACE_SETFPXREGS: /* Set the child FPU state. */ -+ ret = set_fpxregs(data, child); -+ break; -+#endif -+ case PTRACE_FAULTINFO: { -+ struct ptrace_faultinfo fault; -+ -+ fault = ((struct ptrace_faultinfo) -+ { .is_write = child->thread.err, -+ .addr = child->thread.cr2 }); -+ ret = copy_to_user((unsigned long *) data, &fault, -+ sizeof(fault)); -+ if(ret) -+ break; -+ break; -+ } -+ case PTRACE_SIGPENDING: -+ ret = copy_to_user((unsigned long *) data, -+ &child->pending.signal, -+ sizeof(child->pending.signal)); -+ break; -+ -+ case PTRACE_LDT: { -+ struct ptrace_ldt ldt; -+ -+ if(copy_from_user(&ldt, (unsigned long *) data, -+ sizeof(ldt))){ -+ ret = -EIO; -+ break; -+ } -+ -+ /* This one is confusing, so just punt and return -EIO for -+ * now -+ */ -+ ret = -EIO; -+ break; -+ } -+#ifdef CONFIG_PROC_MM -+ case PTRACE_SWITCH_MM: { -+ struct mm_struct *old = child->mm; -+ struct mm_struct *new = proc_mm_get_mm(data); -+ -+ if(IS_ERR(new)){ -+ ret = PTR_ERR(new); -+ break; -+ } -+ -+ atomic_inc(&new->mm_users); -+ child->mm = new; -+ child->active_mm = new; -+ mmput(old); -+ ret = 0; -+ break; -+ } -+#endif -+ default: -+ ret = -EIO; -+ break; -+ } -+ out_tsk: -+ free_task_struct(child); -+ out: -+ unlock_kernel(); -+ return ret; -+} -+ -+void syscall_trace(void) -+{ -+ int is_singlestep = (current->ptrace & PT_DTRACE); -+ -+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) -+ != (PT_PTRACED|PT_TRACESYS) && !is_singlestep) -+ return; -+ current->exit_code = SIGTRAP; -+ current->state = TASK_STOPPED; -+ notify_parent(current, SIGCHLD); -+ -+ schedule(); -+ /* -+ * this isn't the same as continuing with a signal, but it will do -+ * for normal use. strace only continues with a signal if the -+ * stopping signal is not SIGTRAP. -brl -+ */ -+ if (current->exit_code) { -+ send_sig(current->exit_code, current, 1); -+ current->exit_code = 0; -+ } -+ -+ if(is_syscall(PT_REGS_IP(¤t->thread.regs))) -+ current->thread.singlestep_syscall = 1; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/reboot.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/reboot.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/reboot.c 2005-05-03 22:28:14.441414784 +0300 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "os.h" -+#include "mode.h" -+#include "choose-mode.h" -+ -+#ifdef CONFIG_SMP -+static void kill_idlers(int me) -+{ -+#ifdef CONFIG_MODE_TT -+ struct task_struct *p; -+ int i; -+ -+ for(i = 0; i < sizeof(init_tasks)/sizeof(init_tasks[0]); i++){ -+ p = init_tasks[i]; -+ if((p != NULL) && (p->thread.mode.tt.extern_pid != me) && -+ (p->thread.mode.tt.extern_pid != -1)) -+ os_kill_process(p->thread.mode.tt.extern_pid, 0); -+ } -+#endif -+} -+#endif -+ -+static void kill_off_processes(void) -+{ -+ CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas()); -+#ifdef CONFIG_SMP -+ kill_idlers(os_getpid()); -+#endif -+} -+ -+void uml_cleanup(void) -+{ -+ kill_off_processes(); -+ do_uml_exitcalls(); -+} -+ -+void machine_restart(char * __unused) -+{ -+ do_uml_exitcalls(); -+ kill_off_processes(); -+ CHOOSE_MODE(reboot_tt(), reboot_skas()); -+} -+ -+void machine_power_off(void) -+{ -+ do_uml_exitcalls(); -+ kill_off_processes(); -+ CHOOSE_MODE(halt_tt(), halt_skas()); -+} -+ -+void machine_halt(void) -+{ -+ machine_power_off(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/resource.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/resource.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/resource.c 2005-05-03 22:28:14.442414632 +0300 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/pci.h" -+ -+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, -+ unsigned long start, unsigned long size) -+{ -+ return start; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/sigio_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/sigio_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/sigio_kern.c 2005-05-03 22:28:14.443414480 +0300 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/list.h" -+#include "linux/slab.h" -+#include "asm/irq.h" -+#include "init.h" -+#include "sigio.h" -+#include "irq_user.h" -+#include "irq_kern.h" -+ -+/* Protected by sigio_lock() called from write_sigio_workaround */ -+static int sigio_irq_fd = -1; -+ -+static void sigio_interrupt(int irq, void *data, struct pt_regs *unused) -+{ -+ read_sigio_fd(sigio_irq_fd); -+ reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); -+} -+ -+int write_sigio_irq(int fd) -+{ -+ int err; -+ -+ err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, -+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", -+ NULL); -+ if(err){ -+ printk("write_sigio_irq : um_request_irq failed, err = %d\n", -+ err); -+ return(-1); -+ } -+ sigio_irq_fd = fd; -+ return(0); -+} -+ -+static spinlock_t sigio_spinlock = SPIN_LOCK_UNLOCKED; -+ -+void sigio_lock(void) -+{ -+ spin_lock(&sigio_spinlock); -+} -+ -+void sigio_unlock(void) -+{ -+ spin_unlock(&sigio_spinlock); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/sigio_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/sigio_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/sigio_user.c 2005-05-03 22:28:14.445414176 +0300 -@@ -0,0 +1,436 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdlib.h> -+#include <termios.h> -+#include <pty.h> -+#include <signal.h> -+#include <errno.h> -+#include <string.h> -+#include <sched.h> -+#include <sys/socket.h> -+#include <sys/poll.h> -+#include "init.h" -+#include "user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "sigio.h" -+#include "helper.h" -+#include "os.h" -+ -+/* Changed during early boot */ -+int pty_output_sigio = 0; -+int pty_close_sigio = 0; -+ -+/* Used as a flag during SIGIO testing early in boot */ -+static volatile int got_sigio = 0; -+ -+void __init handler(int sig) -+{ -+ got_sigio = 1; -+} -+ -+struct openpty_arg { -+ int master; -+ int slave; -+ int err; -+}; -+ -+static void openpty_cb(void *arg) -+{ -+ struct openpty_arg *info = arg; -+ -+ info->err = 0; -+ if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) -+ info->err = -errno; -+} -+ -+void __init check_one_sigio(void (*proc)(int, int)) -+{ -+ struct sigaction old, new; -+ struct openpty_arg pty = { .master = -1, .slave = -1 }; -+ int master, slave, err; -+ -+ initial_thread_cb(openpty_cb, &pty); -+ if(pty.err){ -+ printk("openpty failed, errno = %d\n", -pty.err); -+ return; -+ } -+ -+ master = pty.master; -+ slave = pty.slave; -+ -+ if((master == -1) || (slave == -1)){ -+ printk("openpty failed to allocate a pty\n"); -+ return; -+ } -+ -+ /* Not now, but complain so we now where we failed. */ -+ err = raw(master); -+ if (err < 0) -+ panic("check_sigio : __raw failed, errno = %d\n", -err); -+ -+ err = os_sigio_async(master, slave); -+ if(err < 0) -+ panic("tty_fds : sigio_async failed, err = %d\n", -err); -+ -+ if(sigaction(SIGIO, NULL, &old) < 0) -+ panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); -+ new = old; -+ new.sa_handler = handler; -+ if(sigaction(SIGIO, &new, NULL) < 0) -+ panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); -+ -+ got_sigio = 0; -+ (*proc)(master, slave); -+ -+ os_close_file(master); -+ os_close_file(slave); -+ -+ if(sigaction(SIGIO, &old, NULL) < 0) -+ panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); -+} -+ -+static void tty_output(int master, int slave) -+{ -+ int n; -+ char buf[512]; -+ -+ printk("Checking that host ptys support output SIGIO..."); -+ -+ memset(buf, 0, sizeof(buf)); -+ -+ while(os_write_file(master, buf, sizeof(buf)) > 0) ; -+ if(errno != EAGAIN) -+ panic("check_sigio : write failed, errno = %d\n", errno); -+ while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; -+ -+ if(got_sigio){ -+ printk("Yes\n"); -+ pty_output_sigio = 1; -+ } -+ else if(n == -EAGAIN) printk("No, enabling workaround\n"); -+ else panic("check_sigio : read failed, err = %d\n", n); -+} -+ -+static void tty_close(int master, int slave) -+{ -+ printk("Checking that host ptys support SIGIO on close..."); -+ -+ os_close_file(slave); -+ if(got_sigio){ -+ printk("Yes\n"); -+ pty_close_sigio = 1; -+ } -+ else printk("No, enabling workaround\n"); -+} -+ -+void __init check_sigio(void) -+{ -+ if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && -+ (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ -+ printk("No pseudo-terminals available - skipping pty SIGIO " -+ "check\n"); -+ return; -+ } -+ check_one_sigio(tty_output); -+ check_one_sigio(tty_close); -+} -+ -+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an -+ * exitcall. -+ */ -+static int write_sigio_pid = -1; -+ -+/* These arrays are initialized before the sigio thread is started, and -+ * the descriptors closed after it is killed. So, it can't see them change. -+ * On the UML side, they are changed under the sigio_lock. -+ */ -+static int write_sigio_fds[2] = { -1, -1 }; -+static int sigio_private[2] = { -1, -1 }; -+ -+struct pollfds { -+ struct pollfd *poll; -+ int size; -+ int used; -+}; -+ -+/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread -+ * synchronizes with it. -+ */ -+struct pollfds current_poll = { -+ .poll = NULL, -+ .size = 0, -+ .used = 0 -+}; -+ -+struct pollfds next_poll = { -+ .poll = NULL, -+ .size = 0, -+ .used = 0 -+}; -+ -+static int write_sigio_thread(void *unused) -+{ -+ struct pollfds *fds, tmp; -+ struct pollfd *p; -+ int i, n, respond_fd; -+ char c; -+ -+ fds = ¤t_poll; -+ while(1){ -+ n = poll(fds->poll, fds->used, -1); -+ if(n < 0){ -+ if(errno == EINTR) continue; -+ printk("write_sigio_thread : poll returned %d, " -+ "errno = %d\n", n, errno); -+ } -+ for(i = 0; i < fds->used; i++){ -+ p = &fds->poll[i]; -+ if(p->revents == 0) continue; -+ if(p->fd == sigio_private[1]){ -+ n = os_read_file(sigio_private[1], &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("write_sigio_thread : " -+ "read failed, err = %d\n", -n); -+ tmp = current_poll; -+ current_poll = next_poll; -+ next_poll = tmp; -+ respond_fd = sigio_private[1]; -+ } -+ else { -+ respond_fd = write_sigio_fds[1]; -+ fds->used--; -+ memmove(&fds->poll[i], &fds->poll[i + 1], -+ (fds->used - i) * sizeof(*fds->poll)); -+ } -+ -+ n = os_write_file(respond_fd, &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("write_sigio_thread : write failed, " -+ "err = %d\n", -n); -+ } -+ } -+} -+ -+static int need_poll(int n) -+{ -+ if(n <= next_poll.size){ -+ next_poll.used = n; -+ return(0); -+ } -+ if(next_poll.poll != NULL) kfree(next_poll.poll); -+ next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); -+ if(next_poll.poll == NULL){ -+ printk("need_poll : failed to allocate new pollfds\n"); -+ next_poll.size = 0; -+ next_poll.used = 0; -+ return(-1); -+ } -+ next_poll.size = n; -+ next_poll.used = n; -+ return(0); -+} -+ -+static void update_thread(void) -+{ -+ unsigned long flags; -+ int n; -+ char c; -+ -+ flags = set_signals(0); -+ n = os_write_file(sigio_private[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("update_thread : write failed, err = %d\n", -n); -+ goto fail; -+ } -+ -+ n = os_read_file(sigio_private[0], &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("update_thread : read failed, err = %d\n", -n); -+ goto fail; -+ } -+ -+ set_signals(flags); -+ return; -+ fail: -+ sigio_lock(); -+ if(write_sigio_pid != -1) -+ os_kill_process(write_sigio_pid, 1); -+ write_sigio_pid = -1; -+ os_close_file(sigio_private[0]); -+ os_close_file(sigio_private[1]); -+ os_close_file(write_sigio_fds[0]); -+ os_close_file(write_sigio_fds[1]); -+ sigio_unlock(); -+ set_signals(flags); -+} -+ -+int add_sigio_fd(int fd, int read) -+{ -+ int err = 0, i, n, events; -+ -+ sigio_lock(); -+ for(i = 0; i < current_poll.used; i++){ -+ if(current_poll.poll[i].fd == fd) -+ goto out; -+ } -+ -+ n = current_poll.used + 1; -+ err = need_poll(n); -+ if(err) -+ goto out; -+ -+ for(i = 0; i < current_poll.used; i++) -+ next_poll.poll[i] = current_poll.poll[i]; -+ -+ if(read) events = POLLIN; -+ else events = POLLOUT; -+ -+ next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd, -+ .events = events, -+ .revents = 0 }); -+ update_thread(); -+ out: -+ sigio_unlock(); -+ return(err); -+} -+ -+int ignore_sigio_fd(int fd) -+{ -+ struct pollfd *p; -+ int err = 0, i, n = 0; -+ -+ sigio_lock(); -+ for(i = 0; i < current_poll.used; i++){ -+ if(current_poll.poll[i].fd == fd) break; -+ } -+ if(i == current_poll.used) -+ goto out; -+ -+ err = need_poll(current_poll.used - 1); -+ if(err) -+ goto out; -+ -+ for(i = 0; i < current_poll.used; i++){ -+ p = ¤t_poll.poll[i]; -+ if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; -+ } -+ if(n == i){ -+ printk("ignore_sigio_fd : fd %d not found\n", fd); -+ err = -1; -+ goto out; -+ } -+ -+ update_thread(); -+ out: -+ sigio_unlock(); -+ return(err); -+} -+ -+static int setup_initial_poll(int fd) -+{ -+ struct pollfd *p; -+ -+ p = um_kmalloc(sizeof(struct pollfd)); -+ if(p == NULL){ -+ printk("setup_initial_poll : failed to allocate poll\n"); -+ return(-1); -+ } -+ *p = ((struct pollfd) { .fd = fd, -+ .events = POLLIN, -+ .revents = 0 }); -+ current_poll = ((struct pollfds) { .poll = p, -+ .used = 1, -+ .size = 1 }); -+ return(0); -+} -+ -+void write_sigio_workaround(void) -+{ -+ unsigned long stack; -+ int err; -+ -+ sigio_lock(); -+ if(write_sigio_pid != -1) -+ goto out; -+ -+ err = os_pipe(write_sigio_fds, 1, 1); -+ if(err < 0){ -+ printk("write_sigio_workaround - os_pipe 1 failed, " -+ "err = %d\n", -err); -+ goto out; -+ } -+ err = os_pipe(sigio_private, 1, 1); -+ if(err < 0){ -+ printk("write_sigio_workaround - os_pipe 2 failed, " -+ "err = %d\n", -err); -+ goto out_close1; -+ } -+ if(setup_initial_poll(sigio_private[1])) -+ goto out_close2; -+ -+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, -+ CLONE_FILES | CLONE_VM, &stack, 0); -+ -+ if(write_sigio_pid < 0) goto out_close2; -+ -+ if(write_sigio_irq(write_sigio_fds[0])) -+ goto out_kill; -+ -+ out: -+ sigio_unlock(); -+ return; -+ -+ out_kill: -+ os_kill_process(write_sigio_pid, 1); -+ write_sigio_pid = -1; -+ out_close2: -+ os_close_file(sigio_private[0]); -+ os_close_file(sigio_private[1]); -+ out_close1: -+ os_close_file(write_sigio_fds[0]); -+ os_close_file(write_sigio_fds[1]); -+ sigio_unlock(); -+} -+ -+int read_sigio_fd(int fd) -+{ -+ int n; -+ char c; -+ -+ n = os_read_file(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ if(n < 0) { -+ printk("read_sigio_fd - read failed, err = %d\n", -n); -+ return(n); -+ } -+ else { -+ printk("read_sigio_fd - short read, bytes = %d\n", n); -+ return(-EIO); -+ } -+ } -+ return(n); -+} -+ -+static void sigio_cleanup(void) -+{ -+ if(write_sigio_pid != -1) -+ os_kill_process(write_sigio_pid, 1); -+} -+ -+__uml_exitcall(sigio_cleanup); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/signal_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/signal_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/signal_kern.c 2005-05-03 22:28:14.447413872 +0300 -@@ -0,0 +1,368 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/stddef.h" -+#include "linux/sys.h" -+#include "linux/sched.h" -+#include "linux/wait.h" -+#include "linux/kernel.h" -+#include "linux/smp_lock.h" -+#include "linux/module.h" -+#include "linux/slab.h" -+#include "asm/signal.h" -+#include "asm/uaccess.h" -+#include "asm/ucontext.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "signal_kern.h" -+#include "signal_user.h" -+#include "kern.h" -+#include "frame_kern.h" -+#include "sigcontext.h" -+#include "mode.h" -+ -+EXPORT_SYMBOL(block_signals); -+EXPORT_SYMBOL(unblock_signals); -+ -+static void force_segv(int sig) -+{ -+ if(sig == SIGSEGV){ -+ struct k_sigaction *ka; -+ -+ ka = ¤t->sig->action[SIGSEGV - 1]; -+ ka->sa.sa_handler = SIG_DFL; -+ } -+ force_sig(SIGSEGV, current); -+} -+ -+#define _S(nr) (1<<((nr)-1)) -+ -+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) -+ -+/* -+ * OK, we're invoking a handler -+ */ -+static void handle_signal(struct pt_regs *regs, unsigned long signr, -+ struct k_sigaction *ka, siginfo_t *info, -+ sigset_t *oldset, int error) -+{ -+ __sighandler_t handler; -+ void (*restorer)(void); -+ unsigned long sp; -+ sigset_t save; -+ int err, ret; -+ -+ err = PT_REGS_SYSCALL_RET(¤t->thread.regs); -+ ret = 0; -+ switch(err){ -+ case -ERESTARTNOHAND: -+ ret = -EINTR; -+ break; -+ -+ case -ERESTARTSYS: -+ if (!(ka->sa.sa_flags & SA_RESTART)) { -+ ret = -EINTR; -+ break; -+ } -+ /* fallthrough */ -+ case -ERESTARTNOINTR: -+ PT_REGS_RESTART_SYSCALL(regs); -+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); -+ -+ /* This is because of the UM_SET_SYSCALL_RETURN and the fact -+ * that on i386 the system call number and return value are -+ * in the same register. When the system call restarts, %eax -+ * had better have the system call number in it. Since the -+ * return value doesn't matter (except that it shouldn't be -+ * -ERESTART*), we'll stick the system call number there. -+ */ -+ ret = PT_REGS_SYSCALL_NR(regs); -+ break; -+ } -+ -+ handler = ka->sa.sa_handler; -+ save = *oldset; -+ -+ if (ka->sa.sa_flags & SA_ONESHOT) -+ ka->sa.sa_handler = SIG_DFL; -+ -+ if (!(ka->sa.sa_flags & SA_NODEFER)) { -+ spin_lock_irq(¤t->sigmask_lock); -+ sigorsets(¤t->blocked, ¤t->blocked, -+ &ka->sa.sa_mask); -+ sigaddset(¤t->blocked, signr); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ } -+ -+ sp = PT_REGS_SP(regs); -+ -+ if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) -+ sp = current->sas_ss_sp + current->sas_ss_size; -+ -+ if(error != 0) -+ PT_REGS_SET_SYSCALL_RETURN(regs, ret); -+ -+ if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; -+ else restorer = NULL; -+ -+ if(ka->sa.sa_flags & SA_SIGINFO) -+ err = setup_signal_stack_si(sp, signr, (unsigned long) handler, -+ restorer, regs, info, &save); -+ else -+ err = setup_signal_stack_sc(sp, signr, (unsigned long) handler, -+ restorer, regs, &save); -+ if(err) -+ force_segv(signr); -+} -+ -+/* -+ * Note that 'init' is a special process: it doesn't get signals it doesn't -+ * want to handle. Thus you cannot kill init even with a SIGKILL even by -+ * mistake. -+ */ -+ -+static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) -+{ -+ siginfo_t info; -+ struct k_sigaction *ka; -+ -+ if (!oldset) -+ oldset = ¤t->blocked; -+ -+ for (;;) { -+ unsigned long signr; -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ signr = dequeue_signal(¤t->blocked, &info); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ if (!signr) -+ break; -+ -+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { -+ /* Let the debugger run. */ -+ current->exit_code = signr; -+ current->state = TASK_STOPPED; -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ -+ /* We're back. Did the debugger cancel the sig? */ -+ signr = current->exit_code; -+ if (!signr) -+ continue; -+ current->exit_code = 0; -+ -+ /* The debugger continued. Ignore SIGSTOP. */ -+ if (signr == SIGSTOP) -+ continue; -+ -+ /* Update the siginfo structure. Is this good? */ -+ if (signr != info.si_signo) { -+ info.si_signo = signr; -+ info.si_errno = 0; -+ info.si_code = SI_USER; -+ info.si_pid = current->p_pptr->pid; -+ info.si_uid = current->p_pptr->uid; -+ } -+ -+ /* If the (new) signal is now blocked, requeue it. */ -+ if (sigismember(¤t->blocked, signr)) { -+ send_sig_info(signr, &info, current); -+ continue; -+ } -+ } -+ -+ ka = ¤t->sig->action[signr-1]; -+ if (ka->sa.sa_handler == SIG_IGN) { -+ if (signr != SIGCHLD) -+ continue; -+ /* Check for SIGCHLD: it's special. */ -+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) -+ /* nothing */; -+ continue; -+ } -+ -+ if (ka->sa.sa_handler == SIG_DFL) { -+ int exit_code = signr; -+ -+ /* Init gets no signals it doesn't want. */ -+ if (current->pid == 1) -+ continue; -+ -+ switch (signr) { -+ case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG: -+ continue; -+ -+ case SIGTSTP: case SIGTTIN: case SIGTTOU: -+ if (is_orphaned_pgrp(current->pgrp)) -+ continue; -+ /* FALLTHRU */ -+ -+ case SIGSTOP: { -+ struct signal_struct *sig; -+ current->state = TASK_STOPPED; -+ current->exit_code = signr; -+ sig = current->p_pptr->sig; -+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) -+ notify_parent(current, SIGCHLD); -+ schedule(); -+ continue; -+ } -+ case SIGQUIT: case SIGILL: case SIGTRAP: -+ case SIGABRT: case SIGFPE: case SIGSEGV: -+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: -+ if (do_coredump(signr, ¤t->thread.regs)) -+ exit_code |= 0x80; -+ /* FALLTHRU */ -+ -+ default: -+ sig_exit(signr, exit_code, &info); -+ /* NOTREACHED */ -+ } -+ } -+ -+ /* Whee! Actually deliver the signal. */ -+ handle_signal(regs, signr, ka, &info, oldset, error); -+ return(1); -+ } -+ -+ /* Did we come from a system call? */ -+ if(PT_REGS_SYSCALL_NR(regs) >= 0){ -+ /* Restart the system call - no handlers present */ -+ if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || -+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || -+ PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ -+ PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); -+ PT_REGS_RESTART_SYSCALL(regs); -+ } -+ } -+ -+ /* This closes a way to execute a system call on the host. If -+ * you set a breakpoint on a system call instruction and singlestep -+ * from it, the tracing thread used to PTRACE_SINGLESTEP the process -+ * rather than PTRACE_SYSCALL it, allowing the system call to execute -+ * on the host. The tracing thread will check this flag and -+ * PTRACE_SYSCALL if necessary. -+ */ -+ if((current->ptrace & PT_DTRACE) && -+ is_syscall(PT_REGS_IP(¤t->thread.regs))) -+ current->thread.singlestep_syscall = 1; -+ -+ return(0); -+} -+ -+int do_signal(int error) -+{ -+ return(kern_do_signal(¤t->thread.regs, NULL, error)); -+} -+ -+/* -+ * Atomically swap in the new signal mask, and wait for a signal. -+ */ -+int sys_sigsuspend(int history0, int history1, old_sigset_t mask) -+{ -+ sigset_t saveset; -+ -+ mask &= _BLOCKABLE; -+ spin_lock_irq(¤t->sigmask_lock); -+ saveset = current->blocked; -+ siginitset(¤t->blocked, mask); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if(kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) -+ return(-EINTR); -+ } -+} -+ -+int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) -+{ -+ sigset_t saveset, newset; -+ -+ /* XXX: Don't preclude handling different sized sigset_t's. */ -+ if (sigsetsize != sizeof(sigset_t)) -+ return -EINVAL; -+ -+ if (copy_from_user(&newset, unewset, sizeof(newset))) -+ return -EFAULT; -+ sigdelsetmask(&newset, ~_BLOCKABLE); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ saveset = current->blocked; -+ current->blocked = newset; -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ -+ PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; -+ while (1) { -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ if (kern_do_signal(¤t->thread.regs, &saveset, -EINTR)) -+ return(-EINTR); -+ } -+} -+ -+extern int userspace_pid[]; -+ -+static int copy_sc_from_user(struct pt_regs *to, void *from, -+ struct arch_frame_data *arch) -+{ -+ int ret; -+ -+ ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch), -+ copy_sc_from_user_skas(userspace_pid[0], -+ &to->regs, from)); -+ return(ret); -+} -+ -+int sys_sigreturn(struct pt_regs regs) -+{ -+ void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); -+ void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); -+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc), -+ sizeof(current->blocked.sig[0])); -+ copy_from_user(¤t->blocked.sig[1], mask, sig_size); -+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ copy_sc_from_user(¤t->thread.regs, sc, -+ &signal_frame_sc.common.arch); -+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); -+} -+ -+int sys_rt_sigreturn(struct pt_regs regs) -+{ -+ struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs)); -+ int sig_size = _NSIG_WORDS * sizeof(unsigned long); -+ -+ spin_lock_irq(¤t->sigmask_lock); -+ copy_from_user(¤t->blocked, &uc->uc_sigmask, sig_size); -+ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); -+ recalc_sigpending(current); -+ spin_unlock_irq(¤t->sigmask_lock); -+ copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, -+ &signal_frame_si.common.arch); -+ return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/signal_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/signal_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/signal_user.c 2005-05-03 22:28:14.448413720 +0300 -@@ -0,0 +1,142 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <signal.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <string.h> -+#include <sys/mman.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "signal_user.h" -+#include "signal_kern.h" -+#include "sysdep/sigcontext.h" -+#include "sigcontext.h" -+ -+void set_sigstack(void *sig_stack, int size) -+{ -+ stack_t stack = ((stack_t) { .ss_flags = 0, -+ .ss_sp = (__ptr_t) sig_stack, -+ .ss_size = size - sizeof(void *) }); -+ -+ if(sigaltstack(&stack, NULL) != 0) -+ panic("enabling signal stack failed, errno = %d\n", errno); -+} -+ -+void set_handler(int sig, void (*handler)(int), int flags, ...) -+{ -+ struct sigaction action; -+ va_list ap; -+ int mask; -+ -+ va_start(ap, flags); -+ action.sa_handler = handler; -+ sigemptyset(&action.sa_mask); -+ while((mask = va_arg(ap, int)) != -1){ -+ sigaddset(&action.sa_mask, mask); -+ } -+ action.sa_flags = flags; -+ action.sa_restorer = NULL; -+ if(sigaction(sig, &action, NULL) < 0) -+ panic("sigaction failed"); -+} -+ -+int change_sig(int signal, int on) -+{ -+ sigset_t sigset, old; -+ -+ sigemptyset(&sigset); -+ sigaddset(&sigset, signal); -+ sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); -+ return(!sigismember(&old, signal)); -+} -+ -+static void change_signals(int type) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ sigaddset(&mask, SIGIO); -+ sigaddset(&mask, SIGPROF); -+ if(sigprocmask(type, &mask, NULL) < 0) -+ panic("Failed to change signal mask - errno = %d", errno); -+} -+ -+void block_signals(void) -+{ -+ change_signals(SIG_BLOCK); -+} -+ -+void unblock_signals(void) -+{ -+ change_signals(SIG_UNBLOCK); -+} -+ -+#define SIGIO_BIT 0 -+#define SIGVTALRM_BIT 1 -+ -+static int enable_mask(sigset_t *mask) -+{ -+ int sigs; -+ -+ sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; -+ sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; -+ sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; -+ return(sigs); -+} -+ -+int get_signals(void) -+{ -+ sigset_t mask; -+ -+ if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) -+ panic("Failed to get signal mask"); -+ return(enable_mask(&mask)); -+} -+ -+int set_signals(int enable) -+{ -+ sigset_t mask; -+ int ret; -+ -+ sigemptyset(&mask); -+ if(enable & (1 << SIGIO_BIT)) -+ sigaddset(&mask, SIGIO); -+ if(enable & (1 << SIGVTALRM_BIT)){ -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ } -+ if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) -+ panic("Failed to enable signals"); -+ ret = enable_mask(&mask); -+ sigemptyset(&mask); -+ if((enable & (1 << SIGIO_BIT)) == 0) -+ sigaddset(&mask, SIGIO); -+ if((enable & (1 << SIGVTALRM_BIT)) == 0){ -+ sigaddset(&mask, SIGVTALRM); -+ sigaddset(&mask, SIGALRM); -+ } -+ if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) -+ panic("Failed to block signals"); -+ -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/exec_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/exec_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/exec_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "asm/current.h" -+#include "asm/page.h" -+#include "asm/signal.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/mmu_context.h" -+#include "tlb.h" -+#include "skas.h" -+#include "mmu.h" -+#include "os.h" -+ -+void flush_thread_skas(void) -+{ -+ force_flush_all(); -+ switch_mm_skas(current->mm->context.skas.mm_fd); -+} -+ -+void start_thread_skas(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp) -+{ -+ set_fs(USER_DS); -+ PT_REGS_IP(regs) = eip; -+ PT_REGS_SP(regs) = esp; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/exec_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/exec_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/exec_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,63 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <sched.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include "user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "time_user.h" -+ -+static int user_thread_tramp(void *arg) -+{ -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) -+ panic("user_thread_tramp - PTRACE_TRACEME failed, " -+ "errno = %d\n", errno); -+ enable_timer(); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+int user_thread(unsigned long stack, int flags) -+{ -+ int pid, status, err; -+ -+ pid = clone(user_thread_tramp, (void *) stack_sp(stack), -+ flags | CLONE_FILES | SIGCHLD, NULL); -+ if(pid < 0){ -+ printk("user_thread - clone failed, errno = %d\n", errno); -+ return(pid); -+ } -+ -+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); -+ if(err < 0){ -+ printk("user_thread - waitpid failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){ -+ printk("user_thread - trampoline didn't stop, status = %d\n", -+ status); -+ return(-EINVAL); -+ } -+ -+ return(pid); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/mmu.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/mmu.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/mmu.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_MMU_H -+#define __SKAS_MMU_H -+ -+#include "linux/list.h" -+#include "linux/spinlock.h" -+ -+struct mmu_context_skas { -+ int mm_fd; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/mode.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/mode.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/mode.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,39 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_SKAS_H__ -+#define __MODE_SKAS_H__ -+ -+#include <sysdep/ptrace.h> -+ -+extern unsigned long exec_regs[]; -+extern unsigned long exec_fp_regs[]; -+extern unsigned long exec_fpx_regs[]; -+extern int have_fpx_regs; -+ -+extern void user_time_init_skas(void); -+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, -+ void *from_ptr); -+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, -+ union uml_pt_regs *regs, -+ unsigned long fault_addr, int fault_type); -+extern void sig_handler_common_skas(int sig, void *sc_ptr); -+extern void halt_skas(void); -+extern void reboot_skas(void); -+extern void kill_off_processes_skas(void); -+extern int is_skas_winch(int pid, int fd, void *data); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/mode_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/mode_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/mode_kern.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_MODE_KERN_H__ -+#define __SKAS_MODE_KERN_H__ -+ -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/ptrace.h" -+ -+extern void flush_thread_skas(void); -+extern void *_switch_to_skas(void *prev, void *next); -+extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp); -+extern int copy_thread_skas(int nr, unsigned long clone_flags, -+ unsigned long sp, unsigned long stack_top, -+ struct task_struct *p, struct pt_regs *regs); -+extern void release_thread_skas(struct task_struct *task); -+extern void exit_thread_skas(void); -+extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); -+extern void init_idle_skas(void); -+extern void flush_tlb_kernel_vm_skas(void); -+extern void __flush_tlb_one_skas(unsigned long addr); -+extern void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_mm_skas(struct mm_struct *mm); -+extern void force_flush_all_skas(void); -+extern long execute_syscall_skas(void *r); -+extern void before_mem_skas(unsigned long unused); -+extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out); -+extern int start_uml_skas(void); -+extern int external_pid_skas(struct task_struct *task); -+extern int thread_pid_skas(struct thread_struct *thread); -+ -+#define kmem_end_skas (host_task_size - 1024 * 1024) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/proc_mm.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/proc_mm.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/proc_mm.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_PROC_MM_H -+#define __SKAS_PROC_MM_H -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/ptrace-skas.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/ptrace-skas.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/ptrace-skas.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_SKAS_H -+#define __PTRACE_SKAS_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_SKAS -+ -+#include "skas_ptregs.h" -+ -+#define HOST_FRAME_SIZE 17 -+ -+#define REGS_IP(r) ((r)[HOST_IP]) -+#define REGS_SP(r) ((r)[HOST_SP]) -+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -+#define REGS_EAX(r) ((r)[HOST_EAX]) -+#define REGS_EBX(r) ((r)[HOST_EBX]) -+#define REGS_ECX(r) ((r)[HOST_ECX]) -+#define REGS_EDX(r) ((r)[HOST_EDX]) -+#define REGS_ESI(r) ((r)[HOST_ESI]) -+#define REGS_EDI(r) ((r)[HOST_EDI]) -+#define REGS_EBP(r) ((r)[HOST_EBP]) -+#define REGS_CS(r) ((r)[HOST_CS]) -+#define REGS_SS(r) ((r)[HOST_SS]) -+#define REGS_DS(r) ((r)[HOST_DS]) -+#define REGS_ES(r) ((r)[HOST_ES]) -+#define REGS_FS(r) ((r)[HOST_FS]) -+#define REGS_GS(r) ((r)[HOST_GS]) -+ -+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) -+ -+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) -+ -+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) -+ -+#define REGS_FAULT_ADDR(r) ((r)->fault_addr) -+ -+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) -+ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/skas.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/skas.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/skas.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_H -+#define __SKAS_H -+ -+#include "sysdep/ptrace.h" -+ -+extern int userspace_pid[]; -+ -+extern void switch_threads(void *me, void *next); -+extern void thread_wait(void *sw, void *fb); -+extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, -+ void (*handler)(int)); -+extern int start_idle_thread(void *stack, void *switch_buf_ptr, -+ void **fork_buf_ptr); -+extern int user_thread(unsigned long stack, int flags); -+extern void userspace(union uml_pt_regs *regs); -+extern void new_thread_proc(void *stack, void (*handler)(int sig)); -+extern void remove_sigstack(void); -+extern void new_thread_handler(int sig); -+extern void handle_syscall(union uml_pt_regs *regs); -+extern void map(int fd, unsigned long virt, unsigned long phys, -+ unsigned long len, int r, int w, int x); -+extern int unmap(int fd, void *addr, int len); -+extern int protect(int fd, unsigned long addr, unsigned long len, -+ int r, int w, int x, int must_succeed); -+extern void user_signal(int sig, union uml_pt_regs *regs); -+extern int new_mm(int from); -+extern void save_registers(union uml_pt_regs *regs); -+extern void restore_registers(union uml_pt_regs *regs); -+extern void start_userspace(int cpu); -+extern void init_registers(int pid); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/include/uaccess.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/include/uaccess.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/include/uaccess.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __SKAS_UACCESS_H -+#define __SKAS_UACCESS_H -+ -+#include "asm/errno.h" -+ -+#define access_ok_skas(type, addr, size) \ -+ ((segment_eq(get_fs(), KERNEL_DS)) || \ -+ (((unsigned long) (addr) < TASK_SIZE) && \ -+ ((unsigned long) (addr) + (size) <= TASK_SIZE))) -+ -+static inline int verify_area_skas(int type, const void * addr, -+ unsigned long size) -+{ -+ return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); -+} -+ -+extern int copy_from_user_skas(void *to, const void *from, int n); -+extern int copy_to_user_skas(void *to, const void *from, int n); -+extern int strncpy_from_user_skas(char *dst, const char *src, int count); -+extern int __clear_user_skas(void *mem, int len); -+extern int clear_user_skas(void *mem, int len); -+extern int strnlen_user_skas(const void *str, int len); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,31 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = skas.o -+ -+obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \ -+ process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \ -+ uaccess.o -+ -+subdir-y = sys-$(SUBARCH) -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o -+ -+include $(TOPDIR)/Rules.make -+ -+include/skas_ptregs.h : util/mk_ptregs -+ util/mk_ptregs > $@ -+ -+util/mk_ptregs : -+ $(MAKE) -C util -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -+ $(MAKE) -C util clean -+ $(RM) -f include/skas_ptregs.h -Index: linux-2.4.29/arch/um/kernel/skas/mem.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/mem.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/mem.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "mem_user.h" -+ -+unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out) -+{ -+ /* Round up to the nearest 4M */ -+ unsigned long top = ROUND_4M((unsigned long) &arg); -+ -+ *host_size_out = top; -+ *task_size_out = top; -+ return(((unsigned long) set_task_sizes_skas) & ~0xffffff); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/mem_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/mem_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/mem_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,105 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <sys/mman.h> -+#include <sys/ptrace.h> -+#include "mem_user.h" -+#include "mem.h" -+#include "user.h" -+#include "os.h" -+#include "proc_mm.h" -+ -+void map(int fd, unsigned long virt, unsigned long phys, unsigned long len, -+ int r, int w, int x) -+{ -+ struct proc_mm_op map; -+ __u64 offset; -+ int prot, n, phys_fd; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ phys_fd = phys_mapping(phys, &offset); -+ -+ map = ((struct proc_mm_op) { .op = MM_MMAP, -+ .u = -+ { .mmap = -+ { .addr = virt, -+ .len = len, -+ .prot = prot, -+ .flags = MAP_SHARED | -+ MAP_FIXED, -+ .fd = phys_fd, -+ .offset = offset -+ } } } ); -+ n = os_write_file(fd, &map, sizeof(map)); -+ if(n != sizeof(map)) -+ printk("map : /proc/mm map failed, err = %d\n", -n); -+} -+ -+int unmap(int fd, void *addr, int len) -+{ -+ struct proc_mm_op unmap; -+ int n; -+ -+ unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, -+ .u = -+ { .munmap = -+ { .addr = (unsigned long) addr, -+ .len = len } } } ); -+ n = os_write_file(fd, &unmap, sizeof(unmap)); -+ if(n != sizeof(unmap)) { -+ if(n < 0) -+ return(n); -+ else if(n > 0) -+ return(-EIO); -+ } -+ -+ return(0); -+} -+ -+int protect(int fd, unsigned long addr, unsigned long len, int r, int w, -+ int x, int must_succeed) -+{ -+ struct proc_mm_op protect; -+ int prot, n; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ -+ protect = ((struct proc_mm_op) { .op = MM_MPROTECT, -+ .u = -+ { .mprotect = -+ { .addr = (unsigned long) addr, -+ .len = len, -+ .prot = prot } } } ); -+ -+ n = os_write_file(fd, &protect, sizeof(protect)); -+ if(n != sizeof(protect)) { -+ if(n == 0) return(0); -+ -+ if(must_succeed) -+ panic("protect failed, err = %d", -n); -+ -+ return(-EIO); -+ } -+ -+ return(0); -+} -+ -+void before_mem_skas(unsigned long unused) -+{ -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/mmu.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/mmu.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/mmu.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/list.h" -+#include "linux/spinlock.h" -+#include "linux/slab.h" -+#include "asm/segment.h" -+#include "asm/mmu.h" -+#include "os.h" -+#include "skas.h" -+ -+int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) -+{ -+ int from; -+ -+ if((current->mm != NULL) && (current->mm != &init_mm)) -+ from = current->mm->context.skas.mm_fd; -+ else from = -1; -+ -+ mm->context.skas.mm_fd = new_mm(from); -+ if(mm->context.skas.mm_fd < 0){ -+ printk("init_new_context_skas - new_mm failed, errno = %d\n", -+ mm->context.skas.mm_fd); -+ return(mm->context.skas.mm_fd); -+ } -+ -+ return(0); -+} -+ -+void destroy_context_skas(struct mm_struct *mm) -+{ -+ os_close_file(mm->context.skas.mm_fd); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/process.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/process.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/process.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,400 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <signal.h> -+#include <setjmp.h> -+#include <sched.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <sys/mman.h> -+#include <sys/user.h> -+#include <asm/unistd.h> -+#include "user.h" -+#include "ptrace_user.h" -+#include "time_user.h" -+#include "sysdep/ptrace.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "skas.h" -+#include "sysdep/sigcontext.h" -+#include "os.h" -+#include "proc_mm.h" -+#include "skas_ptrace.h" -+#include "chan_user.h" -+ -+int is_skas_winch(int pid, int fd, void *data) -+{ -+ if(pid != getpid()) -+ return(0); -+ -+ register_winch_irq(-1, fd, -1, data); -+ return(1); -+} -+ -+/* These are set once at boot time and not changed thereafter */ -+ -+unsigned long exec_regs[FRAME_SIZE]; -+unsigned long exec_fp_regs[HOST_FP_SIZE]; -+unsigned long exec_fpx_regs[HOST_XFP_SIZE]; -+int have_fpx_regs = 1; -+ -+static void handle_segv(int pid) -+{ -+ struct ptrace_faultinfo fault; -+ int err; -+ -+ err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault); -+ if(err) -+ panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n", -+ errno); -+ -+ segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); -+} -+ -+static void handle_trap(int pid, union uml_pt_regs *regs) -+{ -+ int err, syscall_nr, status; -+ -+ syscall_nr = PT_SYSCALL_NR(regs->skas.regs); -+ UPT_SYSCALL_NR(regs) = syscall_nr; -+ if(syscall_nr < 1){ -+ relay_signal(SIGTRAP, regs); -+ return; -+ } -+ -+ if(!use_sysemu){ -+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid); -+ if(err < 0) -+ panic("handle_trap - nullifying syscall failed, " -+ "errno = %d\n", errno); -+ -+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ if(err < 0) -+ panic("handle_trap - continuing to end of syscall " -+ "failed, errno = %d\n", errno); -+ -+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); -+ if((err < 0) || !WIFSTOPPED(status) || -+ (WSTOPSIG(status) != SIGTRAP)) -+ panic("handle_trap - failed to wait at end of " -+ "syscall, errno = %d, status = %d\n", errno, -+ status); -+ } -+ -+ handle_syscall(regs); -+} -+ -+static int userspace_tramp(void *arg) -+{ -+ init_new_thread_signals(0); -+ enable_timer(); -+ ptrace(PTRACE_TRACEME, 0, 0, 0); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+/* Each element set once, and only accessed by a single processor anyway */ -+#define NR_CPUS 1 -+int userspace_pid[NR_CPUS]; -+ -+void start_userspace(int cpu) -+{ -+ void *stack; -+ unsigned long sp; -+ int pid, status, n; -+ -+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, -+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -+ if(stack == MAP_FAILED) -+ panic("start_userspace : mmap failed, errno = %d", errno); -+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); -+ -+ pid = clone(userspace_tramp, (void *) sp, -+ CLONE_FILES | CLONE_VM | SIGCHLD, NULL); -+ if(pid < 0) -+ panic("start_userspace : clone failed, errno = %d", errno); -+ -+ do { -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0) -+ panic("start_userspace : wait failed, errno = %d", -+ errno); -+ } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM)); -+ -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) -+ panic("start_userspace : expected SIGSTOP, got status = %d", -+ status); -+ -+ if(munmap(stack, PAGE_SIZE) < 0) -+ panic("start_userspace : munmap failed, errno = %d\n", errno); -+ -+ userspace_pid[cpu] = pid; -+} -+ -+void userspace(union uml_pt_regs *regs) -+{ -+ int err, status, op, do_syscall, pid = userspace_pid[0]; -+ -+ do_syscall = use_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; -+ restore_registers(regs); -+ -+ err = ptrace(do_syscall, pid, 0, 0); -+ if(err) -+ panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", -+ errno); -+ while(1){ -+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); -+ if(err < 0) -+ panic("userspace - waitpid failed, errno = %d\n", -+ errno); -+ -+ regs->skas.is_user = 1; -+ save_registers(regs); -+ -+ if(WIFSTOPPED(status)){ -+ switch(WSTOPSIG(status)){ -+ case SIGSEGV: -+ handle_segv(pid); -+ break; -+ case SIGTRAP: -+ handle_trap(pid, regs); -+ break; -+ case SIGIO: -+ case SIGVTALRM: -+ case SIGILL: -+ case SIGBUS: -+ case SIGFPE: -+ case SIGWINCH: -+ user_signal(WSTOPSIG(status), regs); -+ break; -+ default: -+ printk("userspace - child stopped with signal " -+ "%d\n", WSTOPSIG(status)); -+ } -+ interrupt_end(); -+ } -+ -+ restore_registers(regs); -+ -+ op = singlestepping(NULL) ? PTRACE_SINGLESTEP : do_syscall; -+ err = ptrace(op, pid, 0, 0); -+ if(err) -+ panic("userspace - PTRACE_SYSCALL failed, " -+ "errno = %d\n", errno); -+ } -+} -+ -+void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, -+ void (*handler)(int)) -+{ -+ sigjmp_buf switch_buf, fork_buf; -+ -+ *switch_buf_ptr = &switch_buf; -+ *fork_buf_ptr = &fork_buf; -+ -+ if(sigsetjmp(fork_buf, 1) == 0) -+ new_thread_proc(stack, handler); -+ -+ remove_sigstack(); -+} -+ -+void thread_wait(void *sw, void *fb) -+{ -+ sigjmp_buf buf, **switch_buf = sw, *fork_buf; -+ -+ *switch_buf = &buf; -+ fork_buf = fb; -+ if(sigsetjmp(buf, 1) == 0) -+ siglongjmp(*fork_buf, 1); -+} -+ -+static int move_registers(int pid, int int_op, int fp_op, -+ union uml_pt_regs *regs, unsigned long *fp_regs) -+{ -+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) -+ return(-errno); -+ if(ptrace(fp_op, pid, 0, fp_regs) < 0) -+ return(-errno); -+ return(0); -+} -+ -+void save_registers(union uml_pt_regs *regs) -+{ -+ unsigned long *fp_regs; -+ int err, fp_op; -+ -+ if(have_fpx_regs){ -+ fp_op = PTRACE_GETFPXREGS; -+ fp_regs = regs->skas.xfp; -+ } -+ else { -+ fp_op = PTRACE_GETFPREGS; -+ fp_regs = regs->skas.fp; -+ } -+ -+ err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs, -+ fp_regs); -+ if(err) -+ panic("save_registers - saving registers failed, errno = %d\n", -+ -err); -+} -+ -+void restore_registers(union uml_pt_regs *regs) -+{ -+ unsigned long *fp_regs; -+ int err, fp_op; -+ -+ if(have_fpx_regs){ -+ fp_op = PTRACE_SETFPXREGS; -+ fp_regs = regs->skas.xfp; -+ } -+ else { -+ fp_op = PTRACE_SETFPREGS; -+ fp_regs = regs->skas.fp; -+ } -+ -+ err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs, -+ fp_regs); -+ if(err) -+ panic("restore_registers - saving registers failed, " -+ "errno = %d\n", -err); -+} -+ -+void switch_threads(void *me, void *next) -+{ -+ sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; -+ -+ *me_ptr = &my_buf; -+ if(sigsetjmp(my_buf, 1) == 0) -+ siglongjmp(*next_buf, 1); -+} -+ -+static sigjmp_buf initial_jmpbuf; -+ -+/* XXX Make these percpu */ -+static void (*cb_proc)(void *arg); -+static void *cb_arg; -+static sigjmp_buf *cb_back; -+ -+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) -+{ -+ sigjmp_buf **switch_buf = switch_buf_ptr; -+ int n; -+ -+ *fork_buf_ptr = &initial_jmpbuf; -+ n = sigsetjmp(initial_jmpbuf, 1); -+ if(n == 0) -+ new_thread_proc((void *) stack, new_thread_handler); -+ else if(n == 1) -+ remove_sigstack(); -+ else if(n == 2){ -+ (*cb_proc)(cb_arg); -+ siglongjmp(*cb_back, 1); -+ } -+ else if(n == 3){ -+ kmalloc_ok = 0; -+ return(0); -+ } -+ else if(n == 4){ -+ kmalloc_ok = 0; -+ return(1); -+ } -+ siglongjmp(**switch_buf, 1); -+} -+ -+void remove_sigstack(void) -+{ -+ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, -+ .ss_sp = NULL, -+ .ss_size = 0 }); -+ -+ if(sigaltstack(&stack, NULL) != 0) -+ panic("disabling signal stack failed, errno = %d\n", errno); -+} -+ -+void initial_thread_cb_skas(void (*proc)(void *), void *arg) -+{ -+ sigjmp_buf here; -+ -+ cb_proc = proc; -+ cb_arg = arg; -+ cb_back = &here; -+ -+ block_signals(); -+ if(sigsetjmp(here, 1) == 0) -+ siglongjmp(initial_jmpbuf, 2); -+ unblock_signals(); -+ -+ cb_proc = NULL; -+ cb_arg = NULL; -+ cb_back = NULL; -+} -+ -+void halt_skas(void) -+{ -+ block_signals(); -+ siglongjmp(initial_jmpbuf, 3); -+} -+ -+void reboot_skas(void) -+{ -+ block_signals(); -+ siglongjmp(initial_jmpbuf, 4); -+} -+ -+void switch_mm_skas(int mm_fd) -+{ -+ int err; -+ -+#warning need cpu pid in switch_mm_skas -+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); -+ if(err) -+ panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", -+ errno); -+} -+ -+void kill_off_processes_skas(void) -+{ -+#warning need to loop over userspace_pids in kill_off_processes_skas -+ os_kill_process(userspace_pid[0], 1); -+} -+ -+void init_registers(int pid) -+{ -+ int err; -+ -+ if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0) -+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", -+ errno); -+ -+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs); -+ if(!err) -+ return; -+ -+ have_fpx_regs = 0; -+ if(errno != EIO) -+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", -+ errno); -+ -+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs); -+ if(err) -+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", -+ errno); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/process_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/process_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/process_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,211 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/slab.h" -+#include "kern_util.h" -+#include "time_user.h" -+#include "signal_user.h" -+#include "skas.h" -+#include "os.h" -+#include "user_util.h" -+#include "tlb.h" -+#include "frame.h" -+#include "kern.h" -+#include "mode.h" -+#include "filehandle.h" -+#include "proc_mm.h" -+ -+void *_switch_to_skas(void *prev, void *next) -+{ -+ struct task_struct *from, *to; -+ -+ from = prev; -+ to = next; -+ -+ /* XXX need to check runqueues[cpu].idle */ -+ if(current->pid == 0) -+ switch_timers(0); -+ -+ to->thread.prev_sched = from; -+ set_current(to); -+ -+ switch_threads(&from->thread.mode.skas.switch_buf, -+ to->thread.mode.skas.switch_buf); -+ -+ if(current->pid == 0) -+ switch_timers(1); -+ -+ return(current->thread.prev_sched); -+} -+ -+extern void schedule_tail(struct task_struct *prev); -+ -+void new_thread_handler(int sig) -+{ -+ int (*fn)(void *), n; -+ void *arg; -+ -+ fn = current->thread.request.u.thread.proc; -+ arg = current->thread.request.u.thread.arg; -+ change_sig(SIGUSR1, 1); -+ thread_wait(¤t->thread.mode.skas.switch_buf, -+ current->thread.mode.skas.fork_buf); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ /* The return value is 1 if the kernel thread execs a process, -+ * 0 if it just exits -+ */ -+ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); -+ if(n == 1) -+ userspace(¤t->thread.regs.regs); -+ else do_exit(0); -+} -+ -+void new_thread_proc(void *stack, void (*handler)(int sig)) -+{ -+ init_new_thread_stack(stack, handler); -+ os_usr1_process(os_getpid()); -+} -+ -+void release_thread_skas(struct task_struct *task) -+{ -+} -+ -+void exit_thread_skas(void) -+{ -+} -+ -+void fork_handler(int sig) -+{ -+ change_sig(SIGUSR1, 1); -+ thread_wait(¤t->thread.mode.skas.switch_buf, -+ current->thread.mode.skas.fork_buf); -+ -+ force_flush_all(); -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ unblock_signals(); -+ -+ userspace(¤t->thread.regs.regs); -+} -+ -+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ void (*handler)(int); -+ -+ if(current->thread.forking){ -+ memcpy(&p->thread.regs.regs.skas, -+ ¤t->thread.regs.regs.skas, -+ sizeof(p->thread.regs.regs.skas)); -+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); -+ if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; -+ -+ handler = fork_handler; -+ } -+ else { -+ memcpy(p->thread.regs.regs.skas.regs, exec_regs, -+ sizeof(p->thread.regs.regs.skas.regs)); -+ memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, -+ sizeof(p->thread.regs.regs.skas.fp)); -+ memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, -+ sizeof(p->thread.regs.regs.skas.xfp)); -+ p->thread.request.u.thread = current->thread.request.u.thread; -+ handler = new_thread_handler; -+ } -+ -+ new_thread(p, &p->thread.mode.skas.switch_buf, -+ &p->thread.mode.skas.fork_buf, handler); -+ return(0); -+} -+ -+int new_mm(int from) -+{ -+ struct proc_mm_op copy; -+ int n; -+ int fd = open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); -+ -+ if(fd < 0) -+ return(fd); -+ -+ if(from != -1){ -+ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, -+ .u = -+ { .copy_segments = from } } ); -+ n = os_write_file(fd, ©, sizeof(copy)); -+ if(n != sizeof(copy)) -+ printk("new_mm : /proc/mm copy_segments failed, " -+ "err = %d\n", -n); -+ } -+ -+ return(fd); -+} -+ -+void init_idle_skas(void) -+{ -+ cpu_tasks[current->processor].pid = os_getpid(); -+} -+ -+extern void start_kernel(void); -+ -+static int start_kernel_proc(void *unused) -+{ -+ int pid; -+ -+ block_signals(); -+ pid = os_getpid(); -+ -+ cpu_tasks[0].pid = pid; -+ cpu_tasks[0].task = current; -+#ifdef CONFIG_SMP -+ cpu_online_map = 1; -+#endif -+ start_kernel(); -+ return(0); -+} -+ -+int start_uml_skas(void) -+{ -+ start_userspace(0); -+ capture_signal_stack(); -+ -+ init_new_thread_signals(1); -+ idle_timer(); -+ -+ init_task.thread.request.u.thread.proc = start_kernel_proc; -+ init_task.thread.request.u.thread.arg = NULL; -+ return(start_idle_thread(&init_task, -+ &init_task.thread.mode.skas.switch_buf, -+ &init_task.thread.mode.skas.fork_buf)); -+} -+ -+int external_pid_skas(struct task_struct *task) -+{ -+#warning Need to look up userspace_pid by cpu -+ return(userspace_pid[0]); -+} -+ -+int thread_pid_skas(struct thread_struct *thread) -+{ -+#warning Need to look up userspace_pid by cpu -+ return(userspace_pid[0]); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/syscall_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/syscall_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/syscall_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sys.h" -+#include "linux/ptrace.h" -+#include "asm/errno.h" -+#include "asm/unistd.h" -+#include "asm/ptrace.h" -+#include "asm/current.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+extern syscall_handler_t *sys_call_table[]; -+ -+long execute_syscall_skas(void *r) -+{ -+ struct pt_regs *regs = r; -+ long res; -+ int syscall; -+ -+ current->thread.nsyscalls++; -+ nsyscalls++; -+ syscall = UPT_SYSCALL_NR(®s->regs); -+ -+ if((syscall >= NR_syscalls) || (syscall < 1)) -+ res = -ENOSYS; -+ else res = EXECUTE_SYSCALL(syscall, regs); -+ -+ return(res); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/syscall_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/syscall_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/syscall_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <signal.h> -+#include "kern_util.h" -+#include "syscall_user.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+ -+/* XXX Bogus */ -+#define ERESTARTSYS 512 -+#define ERESTARTNOINTR 513 -+#define ERESTARTNOHAND 514 -+ -+void handle_syscall(union uml_pt_regs *regs) -+{ -+ long result; -+ int index; -+ -+ index = record_syscall_start(UPT_SYSCALL_NR(regs)); -+ -+ syscall_trace(); -+ result = execute_syscall(regs); -+ -+ REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); -+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || -+ (result == -ERESTARTNOINTR)) -+ do_signal(result); -+ -+ syscall_trace(); -+ record_syscall_end(index, result); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/sys-i386/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/sys-i386/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/sys-i386/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = sys-i386.o -+ -+obj-y = sigcontext.o -+ -+USER_OBJS = sigcontext.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -Index: linux-2.4.29/arch/um/kernel/skas/sys-i386/sigcontext.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/sys-i386/sigcontext.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/sys-i386/sigcontext.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,114 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <asm/sigcontext.h> -+#include <sys/ptrace.h> -+#include <linux/ptrace.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/ptrace_user.h" -+#include "kern_util.h" -+#include "user.h" -+#include "sigcontext.h" -+#include "mode.h" -+ -+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr) -+{ -+ struct sigcontext sc, *from = from_ptr; -+ unsigned long fpregs[FP_FRAME_SIZE]; -+ int err; -+ -+ err = copy_from_user_proc(&sc, from, sizeof(sc)); -+ err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs)); -+ if(err) -+ return(err); -+ -+ regs->skas.regs[GS] = sc.gs; -+ regs->skas.regs[FS] = sc.fs; -+ regs->skas.regs[ES] = sc.es; -+ regs->skas.regs[DS] = sc.ds; -+ regs->skas.regs[EDI] = sc.edi; -+ regs->skas.regs[ESI] = sc.esi; -+ regs->skas.regs[EBP] = sc.ebp; -+ regs->skas.regs[UESP] = sc.esp; -+ regs->skas.regs[EBX] = sc.ebx; -+ regs->skas.regs[EDX] = sc.edx; -+ regs->skas.regs[ECX] = sc.ecx; -+ regs->skas.regs[EAX] = sc.eax; -+ regs->skas.regs[EIP] = sc.eip; -+ regs->skas.regs[CS] = sc.cs; -+ regs->skas.regs[EFL] = sc.eflags; -+ regs->skas.regs[SS] = sc.ss; -+ regs->skas.fault_addr = sc.cr2; -+ regs->skas.fault_type = FAULT_WRITE(sc.err); -+ regs->skas.trap_type = sc.trapno; -+ -+ err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs); -+ if(err < 0){ -+ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, " -+ "errno = %d\n", errno); -+ return(1); -+ } -+ -+ return(0); -+} -+ -+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, -+ union uml_pt_regs *regs, unsigned long fault_addr, -+ int fault_type) -+{ -+ struct sigcontext sc, *to = to_ptr; -+ struct _fpstate *to_fp; -+ unsigned long fpregs[FP_FRAME_SIZE]; -+ int err; -+ -+ sc.gs = regs->skas.regs[GS]; -+ sc.fs = regs->skas.regs[FS]; -+ sc.es = regs->skas.regs[ES]; -+ sc.ds = regs->skas.regs[DS]; -+ sc.edi = regs->skas.regs[EDI]; -+ sc.esi = regs->skas.regs[ESI]; -+ sc.ebp = regs->skas.regs[EBP]; -+ sc.esp = regs->skas.regs[UESP]; -+ sc.ebx = regs->skas.regs[EBX]; -+ sc.edx = regs->skas.regs[EDX]; -+ sc.ecx = regs->skas.regs[ECX]; -+ sc.eax = regs->skas.regs[EAX]; -+ sc.eip = regs->skas.regs[EIP]; -+ sc.cs = regs->skas.regs[CS]; -+ sc.eflags = regs->skas.regs[EFL]; -+ sc.esp_at_signal = regs->skas.regs[UESP]; -+ sc.ss = regs->skas.regs[SS]; -+ sc.cr2 = fault_addr; -+ sc.err = TO_SC_ERR(fault_type); -+ sc.trapno = regs->skas.trap_type; -+ -+ err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs); -+ if(err < 0){ -+ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, " -+ "errno = %d\n", errno); -+ return(1); -+ } -+ to_fp = (struct _fpstate *) -+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -+ sc.fpstate = to_fp; -+ -+ if(err) -+ return(err); -+ -+ return(copy_to_user_proc(to, &sc, sizeof(sc)) || -+ copy_to_user_proc(to_fp, fpregs, sizeof(fpregs))); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/time.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/time.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/time.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <sys/signal.h> -+#include <sys/time.h> -+#include "time_user.h" -+#include "process.h" -+#include "user.h" -+ -+void user_time_init_skas(void) -+{ -+ if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGALRM handler"); -+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/tlb.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/tlb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/tlb.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,153 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/mmu.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "skas.h" -+#include "os.h" -+ -+static void fix_range(struct mm_struct *mm, unsigned long start_addr, -+ unsigned long end_addr, int force) -+{ -+ pgd_t *npgd; -+ pmd_t *npmd; -+ pte_t *npte; -+ unsigned long addr; -+ int r, w, x, err, fd; -+ -+ if(mm == NULL) return; -+ fd = mm->context.skas.mm_fd; -+ for(addr = start_addr; addr < end_addr;){ -+ npgd = pgd_offset(mm, addr); -+ npmd = pmd_offset(npgd, addr); -+ if(pmd_present(*npmd)){ -+ npte = pte_offset(npmd, addr); -+ r = pte_read(*npte); -+ w = pte_write(*npte); -+ x = pte_exec(*npte); -+ if(!pte_dirty(*npte)) w = 0; -+ if(!pte_young(*npte)){ -+ r = 0; -+ w = 0; -+ } -+ if(force || pte_newpage(*npte)){ -+ err = unmap(fd, (void *) addr, PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*npte)) -+ map(fd, addr, -+ pte_val(*npte) & PAGE_MASK, -+ PAGE_SIZE, r, w, x); -+ } -+ else if(pte_newprot(*npte)){ -+ protect(fd, addr, PAGE_SIZE, r, w, x, 1); -+ } -+ *npte = pte_mkuptodate(*npte); -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(force || pmd_newpage(*npmd)){ -+ err = unmap(fd, (void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ pmd_mkuptodate(*npmd); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+static void flush_kernel_vm_range(unsigned long start, unsigned long end) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ int updated = 0, err; -+ -+ mm = &init_mm; -+ for(addr = start; addr < end;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte) || pte_newpage(*pte)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*pte)) -+ map_memory(addr, -+ pte_val(*pte) & PAGE_MASK, -+ PAGE_SIZE, 1, 1, 1); -+ } -+ else if(pte_newprot(*pte)){ -+ updated = 1; -+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); -+ } -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(pmd_newpage(*pmd)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+void flush_tlb_kernel_vm_skas(void) -+{ -+ flush_kernel_vm_range(start_vm, end_vm); -+} -+ -+void __flush_tlb_one_skas(unsigned long addr) -+{ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE); -+} -+ -+void flush_tlb_range_skas(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ if(mm == NULL) -+ flush_kernel_vm_range(start, end); -+ else fix_range(mm, start, end, 0); -+} -+ -+void flush_tlb_mm_skas(struct mm_struct *mm) -+{ -+ flush_tlb_kernel_vm_skas(); -+ fix_range(mm, 0, host_task_size, 0); -+} -+ -+void force_flush_all_skas(void) -+{ -+ fix_range(current->mm, 0, host_task_size, 1); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/trap_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/trap_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/trap_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include <errno.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "task.h" -+#include "sigcontext.h" -+ -+void sig_handler_common_skas(int sig, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct skas_regs *r; -+ struct signal_info *info; -+ int save_errno = errno; -+ int save_user; -+ -+ r = &TASK_REGS(get_current())->skas; -+ save_user = r->is_user; -+ r->is_user = 0; -+ r->fault_addr = SC_FAULT_ADDR(sc); -+ r->fault_type = SC_FAULT_TYPE(sc); -+ r->trap_type = SC_TRAP_TYPE(sc); -+ -+ change_sig(SIGUSR1, 1); -+ info = &sig_info[sig]; -+ if(!info->is_irq) unblock_signals(); -+ -+ (*info->handler)(sig, (union uml_pt_regs *) r); -+ -+ errno = save_errno; -+ r->is_user = save_user; -+} -+ -+extern int missed_ticks[]; -+ -+void user_signal(int sig, union uml_pt_regs *regs) -+{ -+ struct signal_info *info; -+ -+ regs->skas.is_user = 1; -+ regs->skas.fault_addr = 0; -+ regs->skas.fault_type = 0; -+ regs->skas.trap_type = 0; -+ info = &sig_info[sig]; -+ (*info->handler)(sig, regs); -+ -+ unblock_signals(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/uaccess.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/uaccess.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/uaccess.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,248 @@ -+/* -+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/string.h" -+#include "linux/fs.h" -+#include "linux/highmem.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/uaccess.h" -+#include "kern_util.h" -+#include "user_util.h" -+ -+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, -+ pte_t *pte_out); -+ -+static unsigned long maybe_map(unsigned long virt, int is_write) -+{ -+ pte_t pte; -+ -+ void *phys = um_virt_to_phys(current, virt, &pte); -+ int dummy_code; -+ -+ if(IS_ERR(phys) || (is_write && !pte_write(pte))){ -+ if(!handle_page_fault(virt, 0, is_write, 1, &dummy_code)) -+ return(0); -+ phys = um_virt_to_phys(current, virt, NULL); -+ } -+ return((unsigned long) phys); -+} -+ -+static int do_op(unsigned long addr, int len, int is_write, -+ int (*op)(unsigned long addr, int len, void *arg), void *arg) -+{ -+ struct page *page; -+ int n; -+ -+ addr = maybe_map(addr, is_write); -+ if(addr == -1) -+ return(-1); -+ -+ page = phys_to_page(addr); -+ addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); -+ n = (*op)(addr, len, arg); -+ kunmap(page); -+ -+ return(n); -+} -+ -+static void do_buffer_op(void *jmpbuf, void *arg_ptr) -+{ -+ va_list args = *((va_list *) arg_ptr); -+ unsigned long addr = va_arg(args, unsigned long); -+ int len = va_arg(args, int); -+ int is_write = va_arg(args, int); -+ int (*op)(unsigned long, int, void *) = va_arg(args, void *); -+ void *arg = va_arg(args, void *); -+ int *res = va_arg(args, int *); -+ int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); -+ int remain = len, n; -+ -+ current->thread.fault_catcher = jmpbuf; -+ n = do_op(addr, size, is_write, op, arg); -+ if(n != 0){ -+ *res = (n < 0 ? remain : 0); -+ goto out; -+ } -+ -+ addr += size; -+ remain -= size; -+ if(remain == 0){ -+ *res = 0; -+ goto out; -+ } -+ -+ while(addr < ((addr + remain) & PAGE_MASK)){ -+ n = do_op(addr, PAGE_SIZE, is_write, op, arg); -+ if(n != 0){ -+ *res = (n < 0 ? remain : 0); -+ goto out; -+ } -+ -+ addr += PAGE_SIZE; -+ remain -= PAGE_SIZE; -+ } -+ if(remain == 0){ -+ *res = 0; -+ goto out; -+ } -+ -+ n = do_op(addr, remain, is_write, op, arg); -+ if(n != 0) -+ *res = (n < 0 ? remain : 0); -+ else *res = 0; -+ out: -+ current->thread.fault_catcher = NULL; -+} -+ -+static int buffer_op(unsigned long addr, int len, int is_write, -+ int (*op)(unsigned long addr, int len, void *arg), -+ void *arg) -+{ -+ int faulted, res; -+ -+ faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg, -+ &res); -+ if(!faulted) -+ return(res); -+ -+ return(addr + len - (unsigned long) current->thread.fault_addr); -+} -+ -+static int copy_chunk_from_user(unsigned long from, int len, void *arg) -+{ -+ unsigned long *to_ptr = arg, to = *to_ptr; -+ -+ memcpy((void *) to, (void *) from, len); -+ *to_ptr += len; -+ return(0); -+} -+ -+int copy_from_user_skas(void *to, const void *from, int n) -+{ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ memcpy(to, from, n); -+ return(0); -+ } -+ -+ return(access_ok_skas(VERIFY_READ, from, n) ? -+ buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): -+ n); -+} -+ -+static int copy_chunk_to_user(unsigned long to, int len, void *arg) -+{ -+ unsigned long *from_ptr = arg, from = *from_ptr; -+ -+ memcpy((void *) to, (void *) from, len); -+ *from_ptr += len; -+ return(0); -+} -+ -+int copy_to_user_skas(void *to, const void *from, int n) -+{ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ memcpy(to, from, n); -+ return(0); -+ } -+ -+ return(access_ok_skas(VERIFY_WRITE, to, n) ? -+ buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : -+ n); -+} -+ -+static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) -+{ -+ char **to_ptr = arg, *to = *to_ptr; -+ int n; -+ -+ strncpy(to, (void *) from, len); -+ n = strnlen(to, len); -+ *to_ptr += n; -+ -+ if(n < len) -+ return(1); -+ return(0); -+} -+ -+int strncpy_from_user_skas(char *dst, const char *src, int count) -+{ -+ int n; -+ char *ptr = dst; -+ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ strncpy(dst, src, count); -+ return(strnlen(dst, count)); -+ } -+ -+ if(!access_ok_skas(VERIFY_READ, src, 1)) -+ return(-EFAULT); -+ -+ n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, -+ &ptr); -+ if(n != 0) -+ return(-EFAULT); -+ return(strnlen(dst, count)); -+} -+ -+static int clear_chunk(unsigned long addr, int len, void *unused) -+{ -+ memset((void *) addr, 0, len); -+ return(0); -+} -+ -+int __clear_user_skas(void *mem, int len) -+{ -+ return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); -+} -+ -+int clear_user_skas(void *mem, int len) -+{ -+ if(segment_eq(get_fs(), KERNEL_DS)){ -+ memset(mem, 0, len); -+ return(0); -+ } -+ -+ return(access_ok_skas(VERIFY_WRITE, mem, len) ? -+ buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); -+} -+ -+static int strnlen_chunk(unsigned long str, int len, void *arg) -+{ -+ int *len_ptr = arg, n; -+ -+ n = strnlen((void *) str, len); -+ *len_ptr += n; -+ -+ if(n < len) -+ return(1); -+ return(0); -+} -+ -+int strnlen_user_skas(const void *str, int len) -+{ -+ int count = 0, n; -+ -+ if(segment_eq(get_fs(), KERNEL_DS)) -+ return(strnlen(str, len) + 1); -+ -+ n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); -+ if(n == 0) -+ return(count + 1); -+ return(-EFAULT); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/skas/util/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/util/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/util/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,10 @@ -+all: mk_ptregs -+ -+mk_ptregs : mk_ptregs.o -+ $(HOSTCC) -o mk_ptregs mk_ptregs.o -+ -+mk_ptregs.o : mk_ptregs.c -+ $(HOSTCC) -c $< -+ -+clean : -+ $(RM) -f mk_ptregs *.o *~ -Index: linux-2.4.29/arch/um/kernel/skas/util/mk_ptregs.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/skas/util/mk_ptregs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/skas/util/mk_ptregs.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,51 @@ -+#include <stdio.h> -+#include <asm/ptrace.h> -+#include <asm/user.h> -+ -+#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val)) -+ -+int main(int argc, char **argv) -+{ -+ printf("/* Automatically generated by " -+ "arch/um/kernel/skas/util/mk_ptregs */\n"); -+ printf("\n"); -+ printf("#ifndef __SKAS_PT_REGS_\n"); -+ printf("#define __SKAS_PT_REGS_\n"); -+ printf("\n"); -+ printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE); -+ printf("#define HOST_FP_SIZE %d\n", -+ sizeof(struct user_i387_struct) / sizeof(unsigned long)); -+ printf("#define HOST_XFP_SIZE %d\n", -+ sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); -+ -+ PRINT_REG("IP", EIP); -+ PRINT_REG("SP", UESP); -+ PRINT_REG("EFLAGS", EFL); -+ PRINT_REG("EAX", EAX); -+ PRINT_REG("EBX", EBX); -+ PRINT_REG("ECX", ECX); -+ PRINT_REG("EDX", EDX); -+ PRINT_REG("ESI", ESI); -+ PRINT_REG("EDI", EDI); -+ PRINT_REG("EBP", EBP); -+ PRINT_REG("CS", CS); -+ PRINT_REG("SS", SS); -+ PRINT_REG("DS", DS); -+ PRINT_REG("FS", FS); -+ PRINT_REG("ES", ES); -+ PRINT_REG("GS", GS); -+ printf("\n"); -+ printf("#endif\n"); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/smp.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/smp.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/smp.c 2005-05-03 22:28:14.476409464 +0300 -@@ -0,0 +1,329 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_SMP -+ -+#include "linux/sched.h" -+#include "linux/threads.h" -+#include "linux/interrupt.h" -+#include "asm/smp.h" -+#include "asm/processor.h" -+#include "asm/spinlock.h" -+#include "asm/softirq.h" -+#include "asm/hardirq.h" -+#include "asm/tlb.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "kern.h" -+#include "os.h" -+ -+/* Total count of live CPUs, set by smp_boot_cpus */ -+int smp_num_cpus = 1; -+ -+/* The 'big kernel lock' */ -+spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED}; -+ -+/* Per CPU bogomips and other parameters */ -+ -+/* The only piece used here is the ipi pipe, which is set before SMP is -+ * started and never changed. -+ */ -+struct cpuinfo_um cpu_data[NR_CPUS]; -+ -+/* CPU online map, set by smp_boot_cpus */ -+unsigned long cpu_online_map; -+ -+atomic_t global_bh_count; -+ -+/* Set when the idlers are all forked */ -+int smp_threads_ready = 0; -+ -+/* Not used by UML */ -+unsigned char global_irq_holder = 0; -+unsigned volatile long global_irq_lock; -+ -+/* A statistic, can be a little off */ -+static int num_reschedules_sent = 0; -+ -+mmu_gather_t mmu_gathers[NR_CPUS]; -+ -+void smp_send_reschedule(int cpu) -+{ -+ os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1); -+ num_reschedules_sent++; -+} -+ -+static void show(char * str) -+{ -+ int cpu = smp_processor_id(); -+ -+ printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu); -+} -+ -+#define MAXCOUNT 100000000 -+ -+static inline void wait_on_bh(void) -+{ -+ int count = MAXCOUNT; -+ do { -+ if (!--count) { -+ show("wait_on_bh"); -+ count = ~0; -+ } -+ /* nothing .. wait for the other bh's to go away */ -+ } while (atomic_read(&global_bh_count) != 0); -+} -+ -+/* -+ * This is called when we want to synchronize with -+ * bottom half handlers. We need to wait until -+ * no other CPU is executing any bottom half handler. -+ * -+ * Don't wait if we're already running in an interrupt -+ * context or are inside a bh handler. -+ */ -+void synchronize_bh(void) -+{ -+ if (atomic_read(&global_bh_count) && !in_interrupt()) -+ wait_on_bh(); -+} -+ -+void smp_send_stop(void) -+{ -+ int i; -+ -+ printk(KERN_INFO "Stopping all CPUs..."); -+ for(i = 0; i < ncpus; i++){ -+ if(i == current->processor) -+ continue; -+ os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); -+ } -+ printk("done\n"); -+} -+ -+ -+static atomic_t smp_commenced = ATOMIC_INIT(0); -+static volatile unsigned long smp_callin_map = 0; -+ -+void smp_commence(void) -+{ -+ printk("All CPUs are go!\n"); -+ -+ wmb(); -+ atomic_set(&smp_commenced, 1); -+} -+ -+static int idle_proc(void *unused) -+{ -+ int cpu, err; -+ -+ set_current(current); -+ del_from_runqueue(current); -+ unhash_process(current); -+ -+ cpu = current->processor; -+ err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); -+ if(err < 0) -+ panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); -+ -+ activate_ipi(cpu_data[cpu].ipi_pipe[0], -+ current->thread.mode.tt.extern_pid); -+ -+ wmb(); -+ if (test_and_set_bit(current->processor, &smp_callin_map)) { -+ printk("huh, CPU#%d already present??\n", current->processor); -+ BUG(); -+ } -+ -+ while (!atomic_read(&smp_commenced)) -+ cpu_relax(); -+ -+ init_idle(); -+ cpu_idle(); -+ return(0); -+} -+ -+static int idle_thread(int (*fn)(void *), int cpu) -+{ -+ struct task_struct *new_task; -+ int pid; -+ unsigned char c; -+ -+ current->thread.request.u.thread.proc = fn; -+ current->thread.request.u.thread.arg = NULL; -+ pid = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0); -+ if(pid < 0) -+ panic("do_fork failed in idle_thread"); -+ new_task = get_task(pid, 1); -+ -+ cpu_tasks[cpu] = ((struct cpu_task) -+ { .pid = new_task->thread.mode.tt.extern_pid, -+ .task = new_task } ); -+ init_tasks[cpu] = new_task; -+ new_task->processor = cpu; -+ new_task->cpus_allowed = 1 << cpu; -+ new_task->cpus_runnable = new_task->cpus_allowed; -+ CHOOSE_MODE(({ struct file_handle *pipe; -+ pipe = new_task->thread.mode.tt.switch_pipe; -+ write_file(&pipe[1], -1, &c, sizeof(c)); }), -+ ({ panic("skas mode doesn't support SMP"); })); -+ return(new_task->thread.mode.tt.extern_pid); -+} -+ -+void smp_boot_cpus(void) -+{ -+ int err; -+ -+ set_bit(0, &cpu_online_map); -+ set_bit(0, &smp_callin_map); -+ -+ err = os_pipe(cpu_data[0].ipi_pipe, 1, 1); -+ if(err < 0) -+ panic("CPU#0 failed to create IPI pipe, err = %d", -err); -+ -+ activate_ipi(cpu_data[0].ipi_pipe[0], -+ current->thread.mode.tt.extern_pid); -+ -+ if(ncpus < 1){ -+ printk(KERN_INFO "ncpus set to 1\n"); -+ ncpus = 1; -+ } -+ else if(ncpus > NR_CPUS){ -+ printk(KERN_INFO -+ "ncpus can't be greater than NR_CPUS, set to %d\n", -+ NR_CPUS); -+ ncpus = NR_CPUS; -+ } -+ -+ if(ncpus > 1){ -+ int i, pid; -+ -+ printk(KERN_INFO "Starting up other processors:\n"); -+ for(i=1;i<ncpus;i++){ -+ int waittime; -+ -+ /* Do this early, for hard_smp_processor_id() */ -+ cpu_tasks[i].pid = -1; -+ set_bit(i, &cpu_online_map); -+ smp_num_cpus++; -+ -+ pid = idle_thread(idle_proc, i); -+ printk(KERN_INFO "\t#%d - idle thread pid = %d.. ", -+ i, pid); -+ -+ waittime = 200000000; -+ while (waittime-- && !test_bit(i, &smp_callin_map)) -+ cpu_relax(); -+ -+ if (test_bit(i, &smp_callin_map)) -+ printk("online\n"); -+ else { -+ printk("failed\n"); -+ clear_bit(i, &cpu_online_map); -+ } -+ } -+ } -+} -+ -+int setup_profiling_timer(unsigned int multiplier) -+{ -+ printk(KERN_INFO "setup_profiling_timer\n"); -+ return(0); -+} -+ -+void smp_call_function_slave(int cpu); -+ -+void IPI_handler(int cpu) -+{ -+ unsigned char c; -+ int fd; -+ -+ fd = cpu_data[cpu].ipi_pipe[0]; -+ while (os_read_file(fd, &c, 1) == 1) { -+ switch (c) { -+ case 'C': -+ smp_call_function_slave(cpu); -+ break; -+ -+ case 'R': -+ current->need_resched = 1; -+ break; -+ -+ case 'S': -+ printk("CPU#%d stopping\n", cpu); -+ while(1) -+ pause(); -+ break; -+ -+ default: -+ printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); -+ break; -+ } -+ } -+} -+ -+int hard_smp_processor_id(void) -+{ -+ return(pid_to_processor_id(os_getpid())); -+} -+ -+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; -+static atomic_t scf_started; -+static atomic_t scf_finished; -+static void (*func)(void *info); -+static void *info; -+ -+void smp_call_function_slave(int cpu) -+{ -+ atomic_inc(&scf_started); -+ (*func)(info); -+ atomic_inc(&scf_finished); -+} -+ -+int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, -+ int wait) -+{ -+ int cpus = smp_num_cpus - 1; -+ int i; -+ -+ if (!cpus) -+ return 0; -+ -+ spin_lock_bh(&call_lock); -+ atomic_set(&scf_started, 0); -+ atomic_set(&scf_finished, 0); -+ func = _func; -+ info = _info; -+ -+ for (i=0;i<NR_CPUS;i++) -+ if (i != current->processor && test_bit(i, &cpu_online_map)) -+ os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); -+ -+ while (atomic_read(&scf_started) != cpus) -+ barrier(); -+ -+ if (wait) -+ while (atomic_read(&scf_finished) != cpus) -+ barrier(); -+ -+ spin_unlock_bh(&call_lock); -+ return 0; -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/syscall_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/syscall_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/syscall_kern.c 2005-05-03 22:28:14.477409312 +0300 -@@ -0,0 +1,343 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/file.h" -+#include "linux/smp_lock.h" -+#include "linux/mm.h" -+#include "linux/utsname.h" -+#include "linux/msg.h" -+#include "linux/shm.h" -+#include "linux/sys.h" -+#include "linux/unistd.h" -+#include "linux/slab.h" -+#include "linux/utime.h" -+#include "asm/mman.h" -+#include "asm/uaccess.h" -+#include "asm/ipc.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "sysdep/syscalls.h" -+#include "mode_kern.h" -+#include "choose-mode.h" -+ -+/* Unlocked, I don't care if this is a bit off */ -+int nsyscalls = 0; -+ -+long um_mount(char * dev_name, char * dir_name, char * type, -+ unsigned long new_flags, void * data) -+{ -+ if(type == NULL) type = ""; -+ return(sys_mount(dev_name, dir_name, type, new_flags, data)); -+} -+ -+long sys_fork(void) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(SIGCHLD, 0, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+long sys_clone(unsigned long clone_flags, unsigned long newsp) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(clone_flags, newsp, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+long sys_vfork(void) -+{ -+ long ret; -+ -+ current->thread.forking = 1; -+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0); -+ current->thread.forking = 0; -+ return(ret); -+} -+ -+/* common code for old and new mmaps */ -+long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, unsigned long fd, -+ unsigned long pgoff) -+{ -+ int error = -EBADF; -+ struct file * file = NULL; -+ -+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); -+ if (!(flags & MAP_ANONYMOUS)) { -+ file = fget(fd); -+ if (!file) -+ goto out; -+ } -+ -+ down_write(&mm->mmap_sem); -+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); -+ up_write(&mm->mmap_sem); -+ -+ if (file) -+ fput(file); -+ out: -+ return error; -+} -+ -+long sys_mmap2(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long pgoff) -+{ -+ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); -+} -+ -+/* -+ * Perform the select(nd, in, out, ex, tv) and mmap() system -+ * calls. Linux/i386 didn't use to be able to handle more than -+ * 4 system call parameters, so these system calls used a memory -+ * block for parameter passing.. -+ */ -+ -+struct mmap_arg_struct { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset) -+{ -+ int err = -EINVAL; -+ if (offset & ~PAGE_MASK) -+ goto out; -+ -+ err = do_mmap2(current->mm, addr, len, prot, flags, fd, -+ offset >> PAGE_SHIFT); -+ out: -+ return err; -+} -+/* -+ * sys_pipe() is the normal C calling standard for creating -+ * a pipe. It's not the way unix traditionally does this, though. -+ */ -+int sys_pipe(unsigned long * fildes) -+{ -+ int fd[2]; -+ int error; -+ -+ error = do_pipe(fd); -+ if (!error) { -+ if (copy_to_user(fildes, fd, sizeof(fd))) -+ error = -EFAULT; -+ } -+ return error; -+} -+ -+int sys_pause(void) -+{ -+ current->state = TASK_INTERRUPTIBLE; -+ schedule(); -+ return -ERESTARTNOHAND; -+} -+ -+int sys_sigaction(int sig, const struct old_sigaction *act, -+ struct old_sigaction *oact) -+{ -+ struct k_sigaction new_ka, old_ka; -+ int ret; -+ -+ if (act) { -+ old_sigset_t mask; -+ if (verify_area(VERIFY_READ, act, sizeof(*act)) || -+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) || -+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) -+ return -EFAULT; -+ __get_user(new_ka.sa.sa_flags, &act->sa_flags); -+ __get_user(mask, &act->sa_mask); -+ siginitset(&new_ka.sa.sa_mask, mask); -+ } -+ -+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); -+ -+ if (!ret && oact) { -+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || -+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || -+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) -+ return -EFAULT; -+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags); -+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); -+ } -+ -+ return ret; -+} -+ -+/* -+ * sys_ipc() is the de-multiplexer for the SysV IPC calls.. -+ * -+ * This is really horribly ugly. -+ */ -+int sys_ipc (uint call, int first, int second, -+ int third, void *ptr, long fifth) -+{ -+ int version, ret; -+ -+ version = call >> 16; /* hack for backward compatibility */ -+ call &= 0xffff; -+ -+ switch (call) { -+ case SEMOP: -+ return sys_semop (first, (struct sembuf *)ptr, second); -+ case SEMGET: -+ return sys_semget (first, second, third); -+ case SEMCTL: { -+ union semun fourth; -+ if (!ptr) -+ return -EINVAL; -+ if (get_user(fourth.__pad, (void **) ptr)) -+ return -EFAULT; -+ return sys_semctl (first, second, third, fourth); -+ } -+ -+ case MSGSND: -+ return sys_msgsnd (first, (struct msgbuf *) ptr, -+ second, third); -+ case MSGRCV: -+ switch (version) { -+ case 0: { -+ struct ipc_kludge tmp; -+ if (!ptr) -+ return -EINVAL; -+ -+ if (copy_from_user(&tmp, -+ (struct ipc_kludge *) ptr, -+ sizeof (tmp))) -+ return -EFAULT; -+ return sys_msgrcv (first, tmp.msgp, second, -+ tmp.msgtyp, third); -+ } -+ default: -+ panic("msgrcv with version != 0"); -+ return sys_msgrcv (first, -+ (struct msgbuf *) ptr, -+ second, fifth, third); -+ } -+ case MSGGET: -+ return sys_msgget ((key_t) first, second); -+ case MSGCTL: -+ return sys_msgctl (first, second, (struct msqid_ds *) ptr); -+ -+ case SHMAT: -+ switch (version) { -+ default: { -+ ulong raddr; -+ ret = sys_shmat (first, (char *) ptr, second, &raddr); -+ if (ret) -+ return ret; -+ return put_user (raddr, (ulong *) third); -+ } -+ case 1: /* iBCS2 emulator entry point */ -+ if (!segment_eq(get_fs(), get_ds())) -+ return -EINVAL; -+ return sys_shmat (first, (char *) ptr, second, (ulong *) third); -+ } -+ case SHMDT: -+ return sys_shmdt ((char *)ptr); -+ case SHMGET: -+ return sys_shmget (first, second, third); -+ case SHMCTL: -+ return sys_shmctl (first, second, -+ (struct shmid_ds *) ptr); -+ default: -+ return -EINVAL; -+ } -+} -+ -+int sys_uname(struct old_utsname * name) -+{ -+ int err; -+ if (!name) -+ return -EFAULT; -+ down_read(&uts_sem); -+ err=copy_to_user(name, &system_utsname, sizeof (*name)); -+ up_read(&uts_sem); -+ return err?-EFAULT:0; -+} -+ -+int sys_olduname(struct oldold_utsname * name) -+{ -+ int error; -+ -+ if (!name) -+ return -EFAULT; -+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) -+ return -EFAULT; -+ -+ down_read(&uts_sem); -+ -+ error = __copy_to_user(&name->sysname,&system_utsname.sysname, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->release,&system_utsname.release, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->release+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->version,&system_utsname.version, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->version+__OLD_UTS_LEN); -+ error |= __copy_to_user(&name->machine,&system_utsname.machine, -+ __OLD_UTS_LEN); -+ error |= __put_user(0,name->machine+__OLD_UTS_LEN); -+ -+ up_read(&uts_sem); -+ -+ error = error ? -EFAULT : 0; -+ -+ return error; -+} -+ -+int sys_sigaltstack(const stack_t *uss, stack_t *uoss) -+{ -+ return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); -+} -+ -+long execute_syscall(void *r) -+{ -+ return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r)); -+} -+ -+spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED; -+ -+static int syscall_index = 0; -+ -+int next_syscall_index(int limit) -+{ -+ int ret; -+ -+ spin_lock(&syscall_lock); -+ ret = syscall_index; -+ if(++syscall_index == limit) -+ syscall_index = 0; -+ spin_unlock(&syscall_lock); -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/sys_call_table.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/sys_call_table.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/sys_call_table.c 2005-05-03 22:28:14.480408856 +0300 -@@ -0,0 +1,496 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/unistd.h" -+#include "linux/version.h" -+#include "linux/sys.h" -+#include "asm/signal.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_exit; -+extern syscall_handler_t sys_fork; -+extern syscall_handler_t sys_creat; -+extern syscall_handler_t sys_link; -+extern syscall_handler_t sys_unlink; -+extern syscall_handler_t sys_chdir; -+extern syscall_handler_t sys_mknod; -+extern syscall_handler_t sys_chmod; -+extern syscall_handler_t sys_lchown16; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_stat; -+extern syscall_handler_t sys_getpid; -+extern syscall_handler_t sys_oldumount; -+extern syscall_handler_t sys_setuid16; -+extern syscall_handler_t sys_getuid16; -+extern syscall_handler_t sys_ptrace; -+extern syscall_handler_t sys_alarm; -+extern syscall_handler_t sys_fstat; -+extern syscall_handler_t sys_pause; -+extern syscall_handler_t sys_utime; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_access; -+extern syscall_handler_t sys_nice; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_sync; -+extern syscall_handler_t sys_kill; -+extern syscall_handler_t sys_rename; -+extern syscall_handler_t sys_mkdir; -+extern syscall_handler_t sys_rmdir; -+extern syscall_handler_t sys_pipe; -+extern syscall_handler_t sys_times; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_brk; -+extern syscall_handler_t sys_setgid16; -+extern syscall_handler_t sys_getgid16; -+extern syscall_handler_t sys_signal; -+extern syscall_handler_t sys_geteuid16; -+extern syscall_handler_t sys_getegid16; -+extern syscall_handler_t sys_acct; -+extern syscall_handler_t sys_umount; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ioctl; -+extern syscall_handler_t sys_fcntl; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_setpgid; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_olduname; -+extern syscall_handler_t sys_umask; -+extern syscall_handler_t sys_chroot; -+extern syscall_handler_t sys_ustat; -+extern syscall_handler_t sys_dup2; -+extern syscall_handler_t sys_getppid; -+extern syscall_handler_t sys_getpgrp; -+extern syscall_handler_t sys_sigaction; -+extern syscall_handler_t sys_sgetmask; -+extern syscall_handler_t sys_ssetmask; -+extern syscall_handler_t sys_setreuid16; -+extern syscall_handler_t sys_setregid16; -+extern syscall_handler_t sys_sigsuspend; -+extern syscall_handler_t sys_sigpending; -+extern syscall_handler_t sys_sethostname; -+extern syscall_handler_t sys_setrlimit; -+extern syscall_handler_t sys_old_getrlimit; -+extern syscall_handler_t sys_getrusage; -+extern syscall_handler_t sys_gettimeofday; -+extern syscall_handler_t sys_settimeofday; -+extern syscall_handler_t sys_getgroups16; -+extern syscall_handler_t sys_setgroups16; -+extern syscall_handler_t sys_symlink; -+extern syscall_handler_t sys_lstat; -+extern syscall_handler_t sys_readlink; -+extern syscall_handler_t sys_uselib; -+extern syscall_handler_t sys_swapon; -+extern syscall_handler_t sys_reboot; -+extern syscall_handler_t old_readdir; -+extern syscall_handler_t sys_munmap; -+extern syscall_handler_t sys_truncate; -+extern syscall_handler_t sys_ftruncate; -+extern syscall_handler_t sys_fchmod; -+extern syscall_handler_t sys_fchown16; -+extern syscall_handler_t sys_getpriority; -+extern syscall_handler_t sys_setpriority; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_statfs; -+extern syscall_handler_t sys_fstatfs; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_socketcall; -+extern syscall_handler_t sys_syslog; -+extern syscall_handler_t sys_setitimer; -+extern syscall_handler_t sys_getitimer; -+extern syscall_handler_t sys_newstat; -+extern syscall_handler_t sys_newlstat; -+extern syscall_handler_t sys_newfstat; -+extern syscall_handler_t sys_uname; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_vhangup; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_swapoff; -+extern syscall_handler_t sys_sysinfo; -+extern syscall_handler_t sys_ipc; -+extern syscall_handler_t sys_fsync; -+extern syscall_handler_t sys_sigreturn; -+extern syscall_handler_t sys_rt_sigreturn; -+extern syscall_handler_t sys_clone; -+extern syscall_handler_t sys_setdomainname; -+extern syscall_handler_t sys_newuname; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_adjtimex; -+extern syscall_handler_t sys_mprotect; -+extern syscall_handler_t sys_sigprocmask; -+extern syscall_handler_t sys_create_module; -+extern syscall_handler_t sys_init_module; -+extern syscall_handler_t sys_delete_module; -+extern syscall_handler_t sys_get_kernel_syms; -+extern syscall_handler_t sys_quotactl; -+extern syscall_handler_t sys_getpgid; -+extern syscall_handler_t sys_fchdir; -+extern syscall_handler_t sys_bdflush; -+extern syscall_handler_t sys_sysfs; -+extern syscall_handler_t sys_personality; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_setfsuid16; -+extern syscall_handler_t sys_setfsgid16; -+extern syscall_handler_t sys_llseek; -+extern syscall_handler_t sys_getdents; -+extern syscall_handler_t sys_flock; -+extern syscall_handler_t sys_msync; -+extern syscall_handler_t sys_readv; -+extern syscall_handler_t sys_writev; -+extern syscall_handler_t sys_getsid; -+extern syscall_handler_t sys_fdatasync; -+extern syscall_handler_t sys_sysctl; -+extern syscall_handler_t sys_mlock; -+extern syscall_handler_t sys_munlock; -+extern syscall_handler_t sys_mlockall; -+extern syscall_handler_t sys_munlockall; -+extern syscall_handler_t sys_sched_setparam; -+extern syscall_handler_t sys_sched_getparam; -+extern syscall_handler_t sys_sched_setscheduler; -+extern syscall_handler_t sys_sched_getscheduler; -+extern syscall_handler_t sys_sched_get_priority_max; -+extern syscall_handler_t sys_sched_get_priority_min; -+extern syscall_handler_t sys_sched_rr_get_interval; -+extern syscall_handler_t sys_nanosleep; -+extern syscall_handler_t sys_mremap; -+extern syscall_handler_t sys_setresuid16; -+extern syscall_handler_t sys_getresuid16; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_query_module; -+extern syscall_handler_t sys_poll; -+extern syscall_handler_t sys_nfsservctl; -+extern syscall_handler_t sys_setresgid16; -+extern syscall_handler_t sys_getresgid16; -+extern syscall_handler_t sys_prctl; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_rt_sigaction; -+extern syscall_handler_t sys_rt_sigprocmask; -+extern syscall_handler_t sys_rt_sigpending; -+extern syscall_handler_t sys_rt_sigtimedwait; -+extern syscall_handler_t sys_rt_sigqueueinfo; -+extern syscall_handler_t sys_rt_sigsuspend; -+extern syscall_handler_t sys_pread; -+extern syscall_handler_t sys_pwrite; -+extern syscall_handler_t sys_chown16; -+extern syscall_handler_t sys_getcwd; -+extern syscall_handler_t sys_capget; -+extern syscall_handler_t sys_capset; -+extern syscall_handler_t sys_sigaltstack; -+extern syscall_handler_t sys_sendfile; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_ni_syscall; -+extern syscall_handler_t sys_vfork; -+extern syscall_handler_t sys_getrlimit; -+extern syscall_handler_t sys_mmap2; -+extern syscall_handler_t sys_truncate64; -+extern syscall_handler_t sys_ftruncate64; -+extern syscall_handler_t sys_stat64; -+extern syscall_handler_t sys_lstat64; -+extern syscall_handler_t sys_fstat64; -+extern syscall_handler_t sys_lchown; -+extern syscall_handler_t sys_getuid; -+extern syscall_handler_t sys_getgid; -+extern syscall_handler_t sys_geteuid; -+extern syscall_handler_t sys_getegid; -+extern syscall_handler_t sys_setreuid; -+extern syscall_handler_t sys_setregid; -+extern syscall_handler_t sys_getgroups; -+extern syscall_handler_t sys_setgroups; -+extern syscall_handler_t sys_fchown; -+extern syscall_handler_t sys_setresuid; -+extern syscall_handler_t sys_getresuid; -+extern syscall_handler_t sys_setresgid; -+extern syscall_handler_t sys_getresgid; -+extern syscall_handler_t sys_chown; -+extern syscall_handler_t sys_setuid; -+extern syscall_handler_t sys_setgid; -+extern syscall_handler_t sys_setfsuid; -+extern syscall_handler_t sys_setfsgid; -+extern syscall_handler_t sys_pivot_root; -+extern syscall_handler_t sys_mincore; -+extern syscall_handler_t sys_madvise; -+extern syscall_handler_t sys_fcntl64; -+extern syscall_handler_t sys_getdents64; -+extern syscall_handler_t sys_gettid; -+extern syscall_handler_t sys_readahead; -+extern syscall_handler_t sys_tkill; -+extern syscall_handler_t sys_setxattr; -+extern syscall_handler_t sys_lsetxattr; -+extern syscall_handler_t sys_fsetxattr; -+extern syscall_handler_t sys_getxattr; -+extern syscall_handler_t sys_lgetxattr; -+extern syscall_handler_t sys_fgetxattr; -+extern syscall_handler_t sys_listxattr; -+extern syscall_handler_t sys_llistxattr; -+extern syscall_handler_t sys_flistxattr; -+extern syscall_handler_t sys_removexattr; -+extern syscall_handler_t sys_lremovexattr; -+extern syscall_handler_t sys_fremovexattr; -+extern syscall_handler_t sys_sendfile64; -+ -+extern syscall_handler_t um_mount; -+extern syscall_handler_t um_time; -+extern syscall_handler_t um_stime; -+ -+#define LAST_GENERIC_SYSCALL __NR_exit_group -+ -+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL -+#define LAST_SYSCALL LAST_GENERIC_SYSCALL -+#else -+#define LAST_SYSCALL LAST_ARCH_SYSCALL -+#endif -+ -+syscall_handler_t *sys_call_table[] = { -+ [ 0 ] = sys_ni_syscall, -+ [ __NR_exit ] = sys_exit, -+ [ __NR_fork ] = sys_fork, -+ [ __NR_read ] = (syscall_handler_t *) sys_read, -+ [ __NR_write ] = (syscall_handler_t *) sys_write, -+ -+ /* These three are declared differently in asm/unistd.h */ -+ [ __NR_open ] = (syscall_handler_t *) sys_open, -+ [ __NR_close ] = (syscall_handler_t *) sys_close, -+ [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, -+ [ __NR_creat ] = sys_creat, -+ [ __NR_link ] = sys_link, -+ [ __NR_unlink ] = sys_unlink, -+ -+ /* declared differently in kern_util.h */ -+ [ __NR_execve ] = (syscall_handler_t *) sys_execve, -+ [ __NR_chdir ] = sys_chdir, -+ [ __NR_time ] = um_time, -+ [ __NR_mknod ] = sys_mknod, -+ [ __NR_chmod ] = sys_chmod, -+ [ __NR_lchown ] = sys_lchown16, -+ [ __NR_break ] = sys_ni_syscall, -+ [ __NR_oldstat ] = sys_stat, -+ [ __NR_lseek ] = (syscall_handler_t *) sys_lseek, -+ [ __NR_getpid ] = sys_getpid, -+ [ __NR_mount ] = um_mount, -+ [ __NR_umount ] = sys_oldumount, -+ [ __NR_setuid ] = sys_setuid16, -+ [ __NR_getuid ] = sys_getuid16, -+ [ __NR_stime ] = um_stime, -+ [ __NR_ptrace ] = sys_ptrace, -+ [ __NR_alarm ] = sys_alarm, -+ [ __NR_oldfstat ] = sys_fstat, -+ [ __NR_pause ] = sys_pause, -+ [ __NR_utime ] = sys_utime, -+ [ __NR_stty ] = sys_ni_syscall, -+ [ __NR_gtty ] = sys_ni_syscall, -+ [ __NR_access ] = sys_access, -+ [ __NR_nice ] = sys_nice, -+ [ __NR_ftime ] = sys_ni_syscall, -+ [ __NR_sync ] = sys_sync, -+ [ __NR_kill ] = sys_kill, -+ [ __NR_rename ] = sys_rename, -+ [ __NR_mkdir ] = sys_mkdir, -+ [ __NR_rmdir ] = sys_rmdir, -+ -+ /* Declared differently in asm/unistd.h */ -+ [ __NR_dup ] = (syscall_handler_t *) sys_dup, -+ [ __NR_pipe ] = sys_pipe, -+ [ __NR_times ] = sys_times, -+ [ __NR_prof ] = sys_ni_syscall, -+ [ __NR_brk ] = sys_brk, -+ [ __NR_setgid ] = sys_setgid16, -+ [ __NR_getgid ] = sys_getgid16, -+ [ __NR_signal ] = sys_signal, -+ [ __NR_geteuid ] = sys_geteuid16, -+ [ __NR_getegid ] = sys_getegid16, -+ [ __NR_acct ] = sys_acct, -+ [ __NR_umount2 ] = sys_umount, -+ [ __NR_lock ] = sys_ni_syscall, -+ [ __NR_ioctl ] = sys_ioctl, -+ [ __NR_fcntl ] = sys_fcntl, -+ [ __NR_mpx ] = sys_ni_syscall, -+ [ __NR_setpgid ] = sys_setpgid, -+ [ __NR_ulimit ] = sys_ni_syscall, -+ [ __NR_oldolduname ] = sys_olduname, -+ [ __NR_umask ] = sys_umask, -+ [ __NR_chroot ] = sys_chroot, -+ [ __NR_ustat ] = sys_ustat, -+ [ __NR_dup2 ] = sys_dup2, -+ [ __NR_getppid ] = sys_getppid, -+ [ __NR_getpgrp ] = sys_getpgrp, -+ [ __NR_setsid ] = (syscall_handler_t *) sys_setsid, -+ [ __NR_sigaction ] = sys_sigaction, -+ [ __NR_sgetmask ] = sys_sgetmask, -+ [ __NR_ssetmask ] = sys_ssetmask, -+ [ __NR_setreuid ] = sys_setreuid16, -+ [ __NR_setregid ] = sys_setregid16, -+ [ __NR_sigsuspend ] = sys_sigsuspend, -+ [ __NR_sigpending ] = sys_sigpending, -+ [ __NR_sethostname ] = sys_sethostname, -+ [ __NR_setrlimit ] = sys_setrlimit, -+ [ __NR_getrlimit ] = sys_old_getrlimit, -+ [ __NR_getrusage ] = sys_getrusage, -+ [ __NR_gettimeofday ] = sys_gettimeofday, -+ [ __NR_settimeofday ] = sys_settimeofday, -+ [ __NR_getgroups ] = sys_getgroups16, -+ [ __NR_setgroups ] = sys_setgroups16, -+ [ __NR_symlink ] = sys_symlink, -+ [ __NR_oldlstat ] = sys_lstat, -+ [ __NR_readlink ] = sys_readlink, -+ [ __NR_uselib ] = sys_uselib, -+ [ __NR_swapon ] = sys_swapon, -+ [ __NR_reboot ] = sys_reboot, -+ [ __NR_readdir ] = old_readdir, -+ [ __NR_munmap ] = sys_munmap, -+ [ __NR_truncate ] = sys_truncate, -+ [ __NR_ftruncate ] = sys_ftruncate, -+ [ __NR_fchmod ] = sys_fchmod, -+ [ __NR_fchown ] = sys_fchown16, -+ [ __NR_getpriority ] = sys_getpriority, -+ [ __NR_setpriority ] = sys_setpriority, -+ [ __NR_profil ] = sys_ni_syscall, -+ [ __NR_statfs ] = sys_statfs, -+ [ __NR_fstatfs ] = sys_fstatfs, -+ [ __NR_ioperm ] = sys_ni_syscall, -+ [ __NR_socketcall ] = sys_socketcall, -+ [ __NR_syslog ] = sys_syslog, -+ [ __NR_setitimer ] = sys_setitimer, -+ [ __NR_getitimer ] = sys_getitimer, -+ [ __NR_stat ] = sys_newstat, -+ [ __NR_lstat ] = sys_newlstat, -+ [ __NR_fstat ] = sys_newfstat, -+ [ __NR_olduname ] = sys_uname, -+ [ __NR_iopl ] = sys_ni_syscall, -+ [ __NR_vhangup ] = sys_vhangup, -+ [ __NR_idle ] = sys_ni_syscall, -+ [ __NR_wait4 ] = (syscall_handler_t *) sys_wait4, -+ [ __NR_swapoff ] = sys_swapoff, -+ [ __NR_sysinfo ] = sys_sysinfo, -+ [ __NR_ipc ] = sys_ipc, -+ [ __NR_fsync ] = sys_fsync, -+ [ __NR_sigreturn ] = sys_sigreturn, -+ [ __NR_clone ] = sys_clone, -+ [ __NR_setdomainname ] = sys_setdomainname, -+ [ __NR_uname ] = sys_newuname, -+ [ __NR_adjtimex ] = sys_adjtimex, -+ [ __NR_mprotect ] = sys_mprotect, -+ [ __NR_sigprocmask ] = sys_sigprocmask, -+ [ __NR_create_module ] = sys_create_module, -+ [ __NR_init_module ] = sys_init_module, -+ [ __NR_delete_module ] = sys_delete_module, -+ [ __NR_get_kernel_syms ] = sys_get_kernel_syms, -+ [ __NR_quotactl ] = sys_quotactl, -+ [ __NR_getpgid ] = sys_getpgid, -+ [ __NR_fchdir ] = sys_fchdir, -+ [ __NR_bdflush ] = sys_bdflush, -+ [ __NR_sysfs ] = sys_sysfs, -+ [ __NR_personality ] = sys_personality, -+ [ __NR_afs_syscall ] = sys_ni_syscall, -+ [ __NR_setfsuid ] = sys_setfsuid16, -+ [ __NR_setfsgid ] = sys_setfsgid16, -+ [ __NR__llseek ] = sys_llseek, -+ [ __NR_getdents ] = sys_getdents, -+ [ __NR__newselect ] = (syscall_handler_t *) sys_select, -+ [ __NR_flock ] = sys_flock, -+ [ __NR_msync ] = sys_msync, -+ [ __NR_readv ] = sys_readv, -+ [ __NR_writev ] = sys_writev, -+ [ __NR_getsid ] = sys_getsid, -+ [ __NR_fdatasync ] = sys_fdatasync, -+ [ __NR__sysctl ] = sys_sysctl, -+ [ __NR_mlock ] = sys_mlock, -+ [ __NR_munlock ] = sys_munlock, -+ [ __NR_mlockall ] = sys_mlockall, -+ [ __NR_munlockall ] = sys_munlockall, -+ [ __NR_sched_setparam ] = sys_sched_setparam, -+ [ __NR_sched_getparam ] = sys_sched_getparam, -+ [ __NR_sched_setscheduler ] = sys_sched_setscheduler, -+ [ __NR_sched_getscheduler ] = sys_sched_getscheduler, -+ [ __NR_sched_yield ] = (syscall_handler_t *) yield, -+ [ __NR_sched_get_priority_max ] = sys_sched_get_priority_max, -+ [ __NR_sched_get_priority_min ] = sys_sched_get_priority_min, -+ [ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval, -+ [ __NR_nanosleep ] = sys_nanosleep, -+ [ __NR_mremap ] = sys_mremap, -+ [ __NR_setresuid ] = sys_setresuid16, -+ [ __NR_getresuid ] = sys_getresuid16, -+ [ __NR_vm86 ] = sys_ni_syscall, -+ [ __NR_query_module ] = sys_query_module, -+ [ __NR_poll ] = sys_poll, -+ [ __NR_nfsservctl ] = sys_nfsservctl, -+ [ __NR_setresgid ] = sys_setresgid16, -+ [ __NR_getresgid ] = sys_getresgid16, -+ [ __NR_prctl ] = sys_prctl, -+ [ __NR_rt_sigreturn ] = sys_rt_sigreturn, -+ [ __NR_rt_sigaction ] = sys_rt_sigaction, -+ [ __NR_rt_sigprocmask ] = sys_rt_sigprocmask, -+ [ __NR_rt_sigpending ] = sys_rt_sigpending, -+ [ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait, -+ [ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo, -+ [ __NR_rt_sigsuspend ] = sys_rt_sigsuspend, -+ [ __NR_pread ] = sys_pread, -+ [ __NR_pwrite ] = sys_pwrite, -+ [ __NR_chown ] = sys_chown16, -+ [ __NR_getcwd ] = sys_getcwd, -+ [ __NR_capget ] = sys_capget, -+ [ __NR_capset ] = sys_capset, -+ [ __NR_sigaltstack ] = sys_sigaltstack, -+ [ __NR_sendfile ] = sys_sendfile, -+ [ __NR_getpmsg ] = sys_ni_syscall, -+ [ __NR_putpmsg ] = sys_ni_syscall, -+ [ __NR_vfork ] = sys_vfork, -+ [ __NR_ugetrlimit ] = sys_getrlimit, -+ [ __NR_mmap2 ] = sys_mmap2, -+ [ __NR_truncate64 ] = sys_truncate64, -+ [ __NR_ftruncate64 ] = sys_ftruncate64, -+ [ __NR_stat64 ] = sys_stat64, -+ [ __NR_lstat64 ] = sys_lstat64, -+ [ __NR_fstat64 ] = sys_fstat64, -+ [ __NR_fcntl64 ] = sys_fcntl64, -+ [ __NR_getdents64 ] = sys_getdents64, -+ [ __NR_security ] = sys_ni_syscall, -+ [ __NR_gettid ] = sys_gettid, -+ [ __NR_readahead ] = sys_readahead, -+ [ __NR_setxattr ] = sys_setxattr, -+ [ __NR_lsetxattr ] = sys_lsetxattr, -+ [ __NR_fsetxattr ] = sys_fsetxattr, -+ [ __NR_getxattr ] = sys_getxattr, -+ [ __NR_lgetxattr ] = sys_lgetxattr, -+ [ __NR_fgetxattr ] = sys_fgetxattr, -+ [ __NR_listxattr ] = sys_listxattr, -+ [ __NR_llistxattr ] = sys_llistxattr, -+ [ __NR_flistxattr ] = sys_flistxattr, -+ [ __NR_removexattr ] = sys_removexattr, -+ [ __NR_lremovexattr ] = sys_lremovexattr, -+ [ __NR_fremovexattr ] = sys_fremovexattr, -+ [ __NR_tkill ] = sys_tkill, -+ [ __NR_sendfile64 ] = sys_sendfile64, -+ [ __NR_futex ] = sys_ni_syscall, -+ [ __NR_sched_setaffinity ] = sys_ni_syscall, -+ [ __NR_sched_getaffinity ] = sys_ni_syscall, -+ [ __NR_set_thread_area ] = sys_ni_syscall, -+ [ __NR_get_thread_area ] = sys_ni_syscall, -+ [ __NR_io_setup ] = sys_ni_syscall, -+ [ __NR_io_destroy ] = sys_ni_syscall, -+ [ __NR_io_getevents ] = sys_ni_syscall, -+ [ __NR_io_submit ] = sys_ni_syscall, -+ [ __NR_io_cancel ] = sys_ni_syscall, -+ [ __NR_alloc_hugepages ] = sys_ni_syscall, -+ [ __NR_free_hugepages ] = sys_ni_syscall, -+ [ __NR_exit_group ] = sys_ni_syscall, -+ -+ ARCH_SYSCALLS -+ [ LAST_SYSCALL + 1 ... NR_syscalls ] = -+ (syscall_handler_t *) sys_ni_syscall -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/syscall_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/syscall_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/syscall_user.c 2005-05-03 22:28:14.481408704 +0300 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <sys/time.h> -+#include "kern_util.h" -+#include "syscall_user.h" -+ -+struct { -+ int syscall; -+ int pid; -+ int result; -+ struct timeval start; -+ struct timeval end; -+} syscall_record[1024]; -+ -+int record_syscall_start(int syscall) -+{ -+ int max, index; -+ -+ max = sizeof(syscall_record)/sizeof(syscall_record[0]); -+ index = next_syscall_index(max); -+ -+ syscall_record[index].syscall = syscall; -+ syscall_record[index].pid = current_pid(); -+ syscall_record[index].result = 0xdeadbeef; -+ gettimeofday(&syscall_record[index].start, NULL); -+ return(index); -+} -+ -+void record_syscall_end(int index, int result) -+{ -+ syscall_record[index].result = result; -+ gettimeofday(&syscall_record[index].end, NULL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/sysrq.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/sysrq.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/sysrq.c 2005-05-03 22:28:14.482408552 +0300 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/kernel.h" -+#include "linux/module.h" -+#include "asm/page.h" -+#include "asm/processor.h" -+#include "sysrq.h" -+#include "user_util.h" -+ -+ /* -+ * If the address is either in the .text section of the -+ * kernel, or in the vmalloc'ed module regions, it *may* -+ * be the address of a calling routine -+ */ -+ -+#ifdef CONFIG_MODULES -+ -+extern struct module *module_list; -+extern struct module kernel_module; -+ -+static inline int kernel_text_address(unsigned long addr) -+{ -+ int retval = 0; -+ struct module *mod; -+ -+ if (addr >= (unsigned long) &_stext && -+ addr <= (unsigned long) &_etext) -+ return 1; -+ -+ for (mod = module_list; mod != &kernel_module; mod = mod->next) { -+ /* mod_bound tests for addr being inside the vmalloc'ed -+ * module area. Of course it'd be better to test only -+ * for the .text subset... */ -+ if (mod_bound(addr, 0, mod)) { -+ retval = 1; -+ break; -+ } -+ } -+ -+ return retval; -+} -+ -+#else -+ -+static inline int kernel_text_address(unsigned long addr) -+{ -+ return (addr >= (unsigned long) &_stext && -+ addr <= (unsigned long) &_etext); -+} -+ -+#endif -+ -+void show_trace(unsigned long * stack) -+{ -+ int i; -+ unsigned long addr; -+ -+ if (!stack) -+ stack = (unsigned long*) &stack; -+ -+ printk("Call Trace: "); -+ i = 1; -+ while (((long) stack & (THREAD_SIZE-1)) != 0) { -+ addr = *stack++; -+ if (kernel_text_address(addr)) { -+ if (i && ((i % 6) == 0)) -+ printk("\n "); -+ printk("[<%08lx>] ", addr); -+ i++; -+ } -+ } -+ printk("\n"); -+} -+ -+void show_trace_task(struct task_struct *tsk) -+{ -+ unsigned long esp = PT_REGS_SP(&tsk->thread.regs); -+ -+ /* User space on another CPU? */ -+ if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1)) -+ return; -+ show_trace((unsigned long *)esp); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tempfile.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tempfile.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tempfile.c 2005-05-03 22:28:14.483408400 +0300 -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/param.h> -+#include "init.h" -+ -+/* Modified from create_mem_file and start_debugger */ -+static char *tempdir = NULL; -+ -+static void __init find_tempdir(void) -+{ -+ char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; -+ int i; -+ char *dir = NULL; -+ -+ if(tempdir != NULL) return; /* We've already been called */ -+ for(i = 0; dirs[i]; i++){ -+ dir = getenv(dirs[i]); -+ if((dir != NULL) && (*dir != '\0')) -+ break; -+ } -+ if((dir == NULL) || (*dir == '\0')) -+ dir = "/tmp"; -+ -+ tempdir = malloc(strlen(dir) + 2); -+ if(tempdir == NULL){ -+ fprintf(stderr, "Failed to malloc tempdir, " -+ "errno = %d\n", errno); -+ return; -+ } -+ strcpy(tempdir, dir); -+ strcat(tempdir, "/"); -+} -+ -+int make_tempfile(const char *template, char **out_tempname, int do_unlink) -+{ -+ char tempname[MAXPATHLEN]; -+ int fd; -+ -+ find_tempdir(); -+ if (*template != '/') -+ strcpy(tempname, tempdir); -+ else -+ *tempname = 0; -+ strcat(tempname, template); -+ fd = mkstemp(tempname); -+ if(fd < 0){ -+ fprintf(stderr, "open - cannot create %s: %s\n", tempname, -+ strerror(errno)); -+ return -1; -+ } -+ if(do_unlink && (unlink(tempname) < 0)){ -+ perror("unlink"); -+ return -1; -+ } -+ if(out_tempname){ -+ *out_tempname = strdup(tempname); -+ if(*out_tempname == NULL){ -+ perror("strdup"); -+ return -1; -+ } -+ } -+ return(fd); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/time.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/time.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/time.c 2005-05-03 22:28:14.484408248 +0300 -@@ -0,0 +1,144 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <time.h> -+#include <sys/time.h> -+#include <signal.h> -+#include <errno.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "process.h" -+#include "signal_user.h" -+#include "time_user.h" -+ -+extern struct timeval xtime; -+ -+struct timeval local_offset = { 0, 0 }; -+ -+void timer(void) -+{ -+ gettimeofday(&xtime, NULL); -+ timeradd(&xtime, &local_offset, &xtime); -+} -+ -+void set_interval(int timer_type) -+{ -+ int usec = 1000000/hz(); -+ struct itimerval interval = ((struct itimerval) { { 0, usec }, -+ { 0, usec } }); -+ -+ if(setitimer(timer_type, &interval, NULL) == -1) -+ panic("setitimer failed - errno = %d\n", errno); -+} -+ -+void enable_timer(void) -+{ -+ int usec = 1000000/hz(); -+ struct itimerval enable = ((struct itimerval) { { 0, usec }, -+ { 0, usec }}); -+ if(setitimer(ITIMER_VIRTUAL, &enable, NULL)) -+ printk("enable_timer - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void disable_timer(void) -+{ -+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); -+ if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || -+ (setitimer(ITIMER_REAL, &disable, NULL) < 0)) -+ printk("disnable_timer - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void switch_timers(int to_real) -+{ -+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); -+ struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, -+ { 0, 1000000/hz() }}); -+ int old, new; -+ -+ if(to_real){ -+ old = ITIMER_VIRTUAL; -+ new = ITIMER_REAL; -+ } -+ else { -+ old = ITIMER_REAL; -+ new = ITIMER_VIRTUAL; -+ } -+ -+ if((setitimer(old, &disable, NULL) < 0) || -+ (setitimer(new, &enable, NULL))) -+ printk("switch_timers - setitimer failed, errno = %d\n", -+ errno); -+} -+ -+void idle_timer(void) -+{ -+ if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) -+ panic("Couldn't unset SIGVTALRM handler"); -+ -+ set_handler(SIGALRM, (__sighandler_t) alarm_handler, -+ SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); -+ set_interval(ITIMER_REAL); -+} -+ -+void time_init(void) -+{ -+ /* XXX This is to fill xtime with something real - otherwise by the -+ * time /proc is mounted, no timers have fired, and xtime is still 0, -+ * meaning it shows times of Jan 1 1970. The real fix is to figure -+ * out why no timers have happened by then. -+ */ -+ timer(); -+ -+ if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+void do_gettimeofday(struct timeval *tv) -+{ -+ unsigned long flags; -+ -+ flags = time_lock(); -+ gettimeofday(tv, NULL); -+ timeradd(tv, &local_offset, tv); -+ time_unlock(flags); -+} -+ -+void do_settimeofday(struct timeval *tv) -+{ -+ struct timeval now; -+ unsigned long flags; -+ -+ flags = time_lock(); -+ gettimeofday(&now, NULL); -+ timersub(tv, &now, &local_offset); -+ time_unlock(flags); -+} -+ -+void idle_sleep(int secs) -+{ -+ struct timespec ts; -+ -+ ts.tv_sec = secs; -+ ts.tv_nsec = 0; -+ nanosleep(&ts, NULL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/time_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/time_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/time_kern.c 2005-05-03 22:28:14.485408096 +0300 -@@ -0,0 +1,209 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/unistd.h" -+#include "linux/stddef.h" -+#include "linux/spinlock.h" -+#include "linux/sched.h" -+#include "linux/interrupt.h" -+#include "linux/init.h" -+#include "linux/delay.h" -+#include "asm/irq.h" -+#include "asm/param.h" -+#include "asm/current.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "time_user.h" -+#include "mode.h" -+#include "os.h" -+ -+extern rwlock_t xtime_lock; -+ -+int hz(void) -+{ -+ return(HZ); -+} -+ -+/* Changed at early boot */ -+int timer_irq_inited = 0; -+ -+/* missed_ticks will be modified after kernel memory has been -+ * write-protected, so this puts it in a section which will be left -+ * write-enabled. -+ */ -+int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS]; -+ -+static int first_tick; -+static unsigned long long prev_usecs; -+static long long delta; /* Deviation per interval */ -+ -+#define MILLION 1000000 -+ -+void timer_irq(union uml_pt_regs *regs) -+{ -+ unsigned long long ticks = 0; -+ -+ if(!timer_irq_inited){ -+ /* This is to ensure that ticks don't pile up when -+ * the timer handler is suspended */ -+ first_tick = 0; -+ return; -+ } -+ -+ if(first_tick){ -+#if defined(CONFIG_UML_REAL_TIME_CLOCK) -+ /* We've had 1 tick */ -+ unsigned long long usecs = os_usecs(); -+ -+ delta += usecs - prev_usecs; -+ prev_usecs = usecs; -+ -+ /* Protect against the host clock being set backwards */ -+ if(delta < 0) -+ delta = 0; -+ -+ ticks += (delta * HZ) / MILLION; -+ delta -= (ticks * MILLION) / HZ; -+#else -+ ticks = 1; -+#endif -+ } -+ else { -+ prev_usecs = os_usecs(); -+ first_tick = 1; -+ } -+ -+ while(ticks > 0){ -+ do_IRQ(TIMER_IRQ, regs); -+ ticks--; -+ } -+} -+ -+void boot_timer_handler(int sig) -+{ -+ struct pt_regs regs; -+ -+ CHOOSE_MODE((void) -+ (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), -+ (void) (regs.regs.skas.is_user = 0)); -+ do_timer(®s); -+} -+ -+void um_timer(int irq, void *dev, struct pt_regs *regs) -+{ -+ do_timer(regs); -+ write_lock(&xtime_lock); -+ vxtime_lock(); -+ timer(); -+ vxtime_unlock(); -+ write_unlock(&xtime_lock); -+} -+ -+long um_time(int * tloc) -+{ -+ struct timeval now; -+ -+ do_gettimeofday(&now); -+ if (tloc) { -+ if (put_user(now.tv_sec,tloc)) -+ now.tv_sec = -EFAULT; -+ } -+ return now.tv_sec; -+} -+ -+long um_stime(int * tptr) -+{ -+ int value; -+ struct timeval new; -+ -+ if (get_user(value, tptr)) -+ return -EFAULT; -+ new.tv_sec = value; -+ new.tv_usec = 0; -+ do_settimeofday(&new); -+ return 0; -+} -+ -+/* XXX Needs to be moved under sys-i386 */ -+void __delay(um_udelay_t time) -+{ -+ /* Stolen from the i386 __loop_delay */ -+ int d0; -+ __asm__ __volatile__( -+ "\tjmp 1f\n" -+ ".align 16\n" -+ "1:\tjmp 2f\n" -+ ".align 16\n" -+ "2:\tdecl %0\n\tjns 2b" -+ :"=&a" (d0) -+ :"0" (time)); -+} -+ -+void __udelay(um_udelay_t usecs) -+{ -+ int i, n; -+ -+ n = (loops_per_jiffy * HZ * usecs) / MILLION; -+ for(i=0;i<n;i++) ; -+} -+ -+void __const_udelay(um_udelay_t usecs) -+{ -+ int i, n; -+ -+ n = (loops_per_jiffy * HZ * usecs) / MILLION; -+ for(i=0;i<n;i++) ; -+} -+ -+void timer_handler(int sig, union uml_pt_regs *regs) -+{ -+#ifdef CONFIG_SMP -+ update_process_times(user_context(UPT_SP(regs))); -+#endif -+ if(current->processor == 0) -+ timer_irq(regs); -+} -+ -+static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED; -+ -+unsigned long time_lock(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&timer_spinlock, flags); -+ return(flags); -+} -+ -+void time_unlock(unsigned long flags) -+{ -+ spin_unlock_irqrestore(&timer_spinlock, flags); -+} -+ -+int __init timer_init(void) -+{ -+ int err; -+ -+ CHOOSE_MODE(user_time_init_tt(), user_time_init_skas()); -+ err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL); -+ if(err != 0) -+ printk(KERN_ERR "timer_init : request_irq failed - " -+ "errno = %d\n", -err); -+ timer_irq_inited = 1; -+ return(0); -+} -+ -+__initcall(timer_init); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tlb.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tlb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tlb.c 2005-05-03 22:28:14.486407944 +0300 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/mm.h" -+#include "asm/page.h" -+#include "asm/pgalloc.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+ -+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address) -+{ -+ address &= PAGE_MASK; -+ flush_tlb_range(vma->vm_mm, address, address + PAGE_SIZE); -+} -+ -+void flush_tlb_all(void) -+{ -+ flush_tlb_mm(current->mm); -+} -+ -+void flush_tlb_kernel_vm(void) -+{ -+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas()); -+} -+ -+void __flush_tlb_one(unsigned long addr) -+{ -+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr); -+} -+ -+void flush_tlb_range(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, mm, start, -+ end); -+} -+ -+void flush_tlb_mm(struct mm_struct *mm) -+{ -+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm); -+} -+ -+void force_flush_all(void) -+{ -+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas()); -+} -+ -+ -+pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) -+{ -+ return(pgd_offset(mm, address)); -+} -+ -+pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) -+{ -+ return(pmd_offset(pgd, address)); -+} -+ -+pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) -+{ -+ return(pte_offset(pmd, address)); -+} -+ -+pte_t *addr_pte(struct task_struct *task, unsigned long addr) -+{ -+ return(pte_offset(pmd_offset(pgd_offset(task->mm, addr), addr), addr)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/trap_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/trap_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/trap_kern.c 2005-05-03 22:28:14.487407792 +0300 -@@ -0,0 +1,220 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/mm.h" -+#include "linux/spinlock.h" -+#include "linux/config.h" -+#include "linux/init.h" -+#include "asm/semaphore.h" -+#include "asm/pgtable.h" -+#include "asm/pgalloc.h" -+#include "asm/a.out.h" -+#include "asm/current.h" -+#include "asm/irq.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "chan_kern.h" -+#include "mconsole_kern.h" -+#include "2_5compat.h" -+#include "mem.h" -+#include "mem_kern.h" -+ -+unsigned long handle_page_fault(unsigned long address, unsigned long ip, -+ int is_write, int is_user, int *code_out) -+{ -+ struct mm_struct *mm = current->mm; -+ struct vm_area_struct *vma; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long page; -+ int handled = 0; -+ -+ *code_out = SEGV_MAPERR; -+ down_read(&mm->mmap_sem); -+ vma = find_vma(mm, address); -+ if(!vma) -+ goto out; -+ else if(vma->vm_start <= address) -+ goto good_area; -+ else if(!(vma->vm_flags & VM_GROWSDOWN)) -+ goto out; -+ else if(expand_stack(vma, address)) -+ goto out; -+ -+ good_area: -+ *code_out = SEGV_ACCERR; -+ if(is_write && !(vma->vm_flags & VM_WRITE)) -+ goto out; -+ page = address & PAGE_MASK; -+ if(page == (unsigned long) current + PAGE_SIZE) -+ panic("Kernel stack overflow"); -+ pgd = pgd_offset(mm, page); -+ pmd = pmd_offset(pgd, page); -+ do { -+ survive: -+ switch (handle_mm_fault(mm, vma, address, is_write)) { -+ case 1: -+ current->min_flt++; -+ break; -+ case 2: -+ current->maj_flt++; -+ break; -+ default: -+ if (current->pid == 1) { -+ up_read(&mm->mmap_sem); -+ yield(); -+ down_read(&mm->mmap_sem); -+ goto survive; -+ } -+ /* Fall through to bad area case */ -+ case 0: -+ goto out; -+ } -+ pte = pte_offset(pmd, page); -+ } while(!pte_present(*pte)); -+ handled = 1; -+ *pte = pte_mkyoung(*pte); -+ if(pte_write(*pte)) *pte = pte_mkdirty(*pte); -+ flush_tlb_page(vma, page); -+ out: -+ up_read(&mm->mmap_sem); -+ return(handled); -+} -+ -+LIST_HEAD(physmem_remappers); -+ -+void register_remapper(struct remapper *info) -+{ -+ list_add(&info->list, &physmem_remappers); -+} -+ -+static int check_remapped_addr(unsigned long address, int is_write, int is_user) -+{ -+ struct remapper *remapper; -+ struct list_head *ele; -+ __u64 offset; -+ int fd; -+ -+ fd = phys_mapping(__pa(address), &offset); -+ if(fd == -1) -+ return(0); -+ -+ list_for_each(ele, &physmem_remappers){ -+ remapper = list_entry(ele, struct remapper, list); -+ if((*remapper->proc)(fd, address, is_write, offset, is_user)) -+ return(1); -+ } -+ -+ return(0); -+} -+ -+unsigned long segv(unsigned long address, unsigned long ip, int is_write, -+ int is_user, void *sc) -+{ -+ struct siginfo si; -+ void *catcher; -+ int handled; -+ -+ if(!is_user && (address >= start_vm) && (address < end_vm)){ -+ flush_tlb_kernel_vm(); -+ return(0); -+ } -+ else if(check_remapped_addr(address & PAGE_MASK, is_write, is_user)) -+ return(0); -+ else if(current->mm == NULL) -+ panic("Segfault with no mm"); -+ -+ handled = handle_page_fault(address, ip, is_write, is_user, -+ &si.si_code); -+ -+ catcher = current->thread.fault_catcher; -+ if(handled) -+ return(0); -+ else if(catcher != NULL){ -+ current->thread.fault_addr = (void *) address; -+ do_longjmp(catcher, 1); -+ } -+ else if(current->thread.fault_addr != NULL) -+ panic("fault_addr set but no fault catcher"); -+ else if(arch_fixup(ip, sc)) -+ return(0); -+ -+ if(!is_user) -+ panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", -+ address, ip); -+ si.si_signo = SIGSEGV; -+ si.si_addr = (void *) address; -+ current->thread.cr2 = address; -+ current->thread.err = is_write; -+ force_sig_info(SIGSEGV, &si, current); -+ return(0); -+} -+ -+void bad_segv(unsigned long address, unsigned long ip, int is_write) -+{ -+ struct siginfo si; -+ -+ si.si_signo = SIGSEGV; -+ si.si_code = SEGV_ACCERR; -+ si.si_addr = (void *) address; -+ current->thread.cr2 = address; -+ current->thread.err = is_write; -+ force_sig_info(SIGSEGV, &si, current); -+} -+ -+void relay_signal(int sig, union uml_pt_regs *regs) -+{ -+ if(arch_handle_signal(sig, regs)) return; -+ if(!UPT_IS_USER(regs)) -+ panic("Kernel mode signal %d", sig); -+ force_sig(sig, current); -+} -+ -+void bus_handler(int sig, union uml_pt_regs *regs) -+{ -+ if(current->thread.fault_catcher != NULL) -+ do_longjmp(current->thread.fault_catcher, 1); -+ else relay_signal(sig, regs); -+} -+ -+void winch(int sig, union uml_pt_regs *regs) -+{ -+ do_IRQ(WINCH_IRQ, regs); -+} -+ -+void trap_init(void) -+{ -+} -+ -+spinlock_t trap_lock = SPIN_LOCK_UNLOCKED; -+ -+static int trap_index = 0; -+ -+int next_trap_index(int limit) -+{ -+ int ret; -+ -+ spin_lock(&trap_lock); -+ ret = trap_index; -+ if(++trap_index == limit) -+ trap_index = 0; -+ spin_unlock(&trap_lock); -+ return(ret); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/trap_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/trap_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/trap_user.c 2005-05-03 22:28:14.489407488 +0300 -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <setjmp.h> -+#include <signal.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <asm/page.h> -+#include <asm/unistd.h> -+#include <asm/ptrace.h> -+#include "init.h" -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "sysdep/sigcontext.h" -+#include "irq_user.h" -+#include "frame_user.h" -+#include "signal_user.h" -+#include "time_user.h" -+#include "task.h" -+#include "mode.h" -+#include "choose-mode.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+ -+void kill_child_dead(int pid) -+{ -+ kill(pid, SIGKILL); -+ kill(pid, SIGCONT); -+ do { -+ int n; -+ CATCH_EINTR(n = waitpid(pid, NULL, 0)); -+ if (n > 0) -+ kill(pid, SIGCONT); -+ else -+ break; -+ } while(1); -+} -+ -+/* Unlocked - don't care if this is a bit off */ -+int nsegfaults = 0; -+ -+struct { -+ unsigned long address; -+ int is_write; -+ int pid; -+ unsigned long sp; -+ int is_user; -+} segfault_record[1024]; -+ -+void segv_handler(int sig, union uml_pt_regs *regs) -+{ -+ int index, max; -+ -+ if(UPT_IS_USER(regs) && !UPT_SEGV_IS_FIXABLE(regs)){ -+ bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), -+ UPT_FAULT_WRITE(regs)); -+ return; -+ } -+ max = sizeof(segfault_record)/sizeof(segfault_record[0]); -+ index = next_trap_index(max); -+ -+ nsegfaults++; -+ segfault_record[index].address = UPT_FAULT_ADDR(regs); -+ segfault_record[index].pid = os_getpid(); -+ segfault_record[index].is_write = UPT_FAULT_WRITE(regs); -+ segfault_record[index].sp = UPT_SP(regs); -+ segfault_record[index].is_user = UPT_IS_USER(regs); -+ segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs), -+ UPT_IS_USER(regs), regs); -+} -+ -+void usr2_handler(int sig, union uml_pt_regs *regs) -+{ -+ CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -+} -+ -+struct signal_info sig_info[] = { -+ [ SIGTRAP ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGFPE ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGILL ] { .handler = relay_signal, -+ .is_irq = 0 }, -+ [ SIGWINCH ] { .handler = winch, -+ .is_irq = 1 }, -+ [ SIGBUS ] { .handler = bus_handler, -+ .is_irq = 0 }, -+ [ SIGSEGV] { .handler = segv_handler, -+ .is_irq = 0 }, -+ [ SIGIO ] { .handler = sigio_handler, -+ .is_irq = 1 }, -+ [ SIGVTALRM ] { .handler = timer_handler, -+ .is_irq = 1 }, -+ [ SIGALRM ] { .handler = timer_handler, -+ .is_irq = 1 }, -+ [ SIGUSR2 ] { .handler = usr2_handler, -+ .is_irq = 0 }, -+}; -+ -+void sig_handler(int sig, struct sigcontext sc) -+{ -+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, -+ sig, &sc); -+} -+ -+extern int timer_irq_inited, missed_ticks[]; -+ -+void alarm_handler(int sig, struct sigcontext sc) -+{ -+ if(!timer_irq_inited) return; -+ missed_ticks[cpu()]++; -+ -+ if(sig == SIGALRM) -+ switch_timers(0); -+ -+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, -+ sig, &sc); -+ -+ if(sig == SIGALRM) -+ switch_timers(1); -+} -+ -+void do_longjmp(void *b, int val) -+{ -+ sigjmp_buf *buf = b; -+ -+ siglongjmp(*buf, val); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/exec_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/exec_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/exec_kern.c 2005-05-03 22:28:14.490407336 +0300 -@@ -0,0 +1,86 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/mm.h" -+#include "asm/signal.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/pgalloc.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "irq_user.h" -+#include "time_user.h" -+#include "mem_user.h" -+#include "signal_user.h" -+#include "os.h" -+#include "tlb.h" -+#include "mode.h" -+ -+static int exec_tramp(void *sig_stack) -+{ -+ init_new_thread_stack(sig_stack, NULL); -+ init_new_thread_signals(1); -+ os_stop_process(os_getpid()); -+ return(0); -+} -+ -+void flush_thread_tt(void) -+{ -+ unsigned long stack; -+ int new_pid; -+ -+ stack = alloc_stack(0, 0); -+ if(stack == 0){ -+ printk(KERN_ERR -+ "flush_thread : failed to allocate temporary stack\n"); -+ do_exit(SIGKILL); -+ } -+ -+ new_pid = start_fork_tramp(current, stack, 0, exec_tramp); -+ if(new_pid < 0){ -+ printk(KERN_ERR -+ "flush_thread : new thread failed, errno = %d\n", -+ -new_pid); -+ do_exit(SIGKILL); -+ } -+ -+ if(current->processor == 0) -+ forward_interrupts(new_pid); -+ current->thread.request.op = OP_EXEC; -+ current->thread.request.u.exec.pid = new_pid; -+ unprotect_stack((unsigned long) current); -+ os_usr1_process(os_getpid()); -+ change_sig(SIGUSR1, 1); -+ -+ change_sig(SIGUSR1, 0); -+ enable_timer(); -+ free_page(stack); -+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); -+ task_protections((unsigned long) current); -+ force_flush_all(); -+ unblock_signals(); -+} -+ -+void start_thread_tt(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp) -+{ -+ set_fs(USER_DS); -+ flush_tlb_mm(current->mm); -+ PT_REGS_IP(regs) = eip; -+ PT_REGS_SP(regs) = esp; -+ PT_FIX_EXEC_STACK(esp); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/exec_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/exec_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/exec_user.c 2005-05-03 22:28:14.491407184 +0300 -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stdlib.h> -+#include <sched.h> -+#include <errno.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <signal.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "ptrace_user.h" -+ -+void do_exec(int old_pid, int new_pid) -+{ -+ unsigned long regs[FRAME_SIZE]; -+ int err; -+ -+ if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || -+ (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) -+ tracer_panic("do_exec failed to attach proc - errno = %d", -+ errno); -+ -+ CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); -+ if (err < 0) -+ tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", -+ errno); -+ -+ if(ptrace_getregs(old_pid, regs) < 0) -+ tracer_panic("do_exec failed to get registers - errno = %d", -+ errno); -+ -+ kill(old_pid, SIGKILL); -+ -+ if(ptrace_setregs(new_pid, regs) < 0) -+ tracer_panic("do_exec failed to start new proc - errno = %d", -+ errno); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/gdb.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/gdb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/gdb.c 2005-05-03 22:28:14.492407032 +0300 -@@ -0,0 +1,278 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <errno.h> -+#include <string.h> -+#include <signal.h> -+#include <sys/ptrace.h> -+#include <sys/types.h> -+#include "uml-config.h" -+#include "kern_constants.h" -+#include "chan_user.h" -+#include "init.h" -+#include "user.h" -+#include "debug.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "tt.h" -+#include "sysdep/thread.h" -+ -+extern int debugger_pid; -+extern int debugger_fd; -+extern int debugger_parent; -+ -+int detach(int pid, int sig) -+{ -+ return(ptrace(PTRACE_DETACH, pid, 0, sig)); -+} -+ -+int attach(int pid) -+{ -+ int err; -+ -+ err = ptrace(PTRACE_ATTACH, pid, 0, 0); -+ if(err < 0) return(-errno); -+ else return(err); -+} -+ -+int cont(int pid) -+{ -+ return(ptrace(PTRACE_CONT, pid, 0, 0)); -+} -+ -+#ifdef UML_CONFIG_PT_PROXY -+ -+int debugger_signal(int status, pid_t pid) -+{ -+ return(debugger_proxy(status, pid)); -+} -+ -+void child_signal(pid_t pid, int status) -+{ -+ child_proxy(pid, status); -+} -+ -+static void gdb_announce(char *dev_name, int dev) -+{ -+ printf("gdb assigned device '%s'\n", dev_name); -+} -+ -+static struct chan_opts opts = { -+ .announce = gdb_announce, -+ .xterm_title = "UML kernel debugger", -+ .raw = 0, -+ .tramp_stack = 0, -+ .in_kernel = 0, -+}; -+ -+/* Accessed by the tracing thread, which automatically serializes access */ -+static void *xterm_data; -+static int xterm_fd; -+ -+extern void *xterm_init(char *, int, struct chan_opts *); -+extern int xterm_open(int, int, int, void *, char **); -+extern void xterm_close(int, void *); -+ -+int open_gdb_chan(void) -+{ -+ char stack[UM_KERN_PAGE_SIZE], *dummy; -+ -+ opts.tramp_stack = (unsigned long) stack; -+ xterm_data = xterm_init("", 0, &opts); -+ xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy); -+ return(xterm_fd); -+} -+ -+static void exit_debugger_cb(void *unused) -+{ -+ if(debugger_pid != -1){ -+ if(gdb_pid != -1){ -+ fake_child_exit(); -+ gdb_pid = -1; -+ } -+ else kill_child_dead(debugger_pid); -+ debugger_pid = -1; -+ if(debugger_parent != -1) -+ detach(debugger_parent, SIGINT); -+ } -+ if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data); -+} -+ -+static void exit_debugger(void) -+{ -+ initial_thread_cb(exit_debugger_cb, NULL); -+} -+ -+__uml_exitcall(exit_debugger); -+ -+struct gdb_data { -+ char *str; -+ int err; -+}; -+ -+static void config_gdb_cb(void *arg) -+{ -+ struct gdb_data *data = arg; -+ void *task; -+ int pid; -+ -+ data->err = -1; -+ if(debugger_pid != -1) exit_debugger_cb(NULL); -+ if(!strncmp(data->str, "pid,", strlen("pid,"))){ -+ data->str += strlen("pid,"); -+ pid = strtoul(data->str, NULL, 0); -+ task = cpu_tasks[0].task; -+ debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0); -+ if(debugger_pid != -1){ -+ data->err = 0; -+ gdb_pid = pid; -+ } -+ return; -+ } -+ data->err = 0; -+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); -+ init_proxy(debugger_pid, 0, 0); -+} -+ -+int gdb_config(char *str) -+{ -+ struct gdb_data data; -+ -+ if(*str++ != '=') return(-1); -+ data.str = str; -+ initial_thread_cb(config_gdb_cb, &data); -+ return(data.err); -+} -+ -+void remove_gdb_cb(void *unused) -+{ -+ exit_debugger_cb(NULL); -+} -+ -+int gdb_remove(char *unused) -+{ -+ initial_thread_cb(remove_gdb_cb, NULL); -+ return(0); -+} -+ -+void signal_usr1(int sig) -+{ -+ if(debugger_pid != -1){ -+ printk(UM_KERN_ERR "The debugger is already running\n"); -+ return; -+ } -+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd); -+ init_proxy(debugger_pid, 0, 0); -+} -+ -+int init_ptrace_proxy(int idle_pid, int startup, int stop) -+{ -+ int pid, status; -+ -+ pid = start_debugger(linux_prog, startup, stop, &debugger_fd); -+ status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); -+ if(pid < 0){ -+ cont(idle_pid); -+ return(-1); -+ } -+ init_proxy(pid, 1, status); -+ return(pid); -+} -+ -+int attach_debugger(int idle_pid, int pid, int stop) -+{ -+ int status = 0, err; -+ -+ err = attach(pid); -+ if(err < 0){ -+ printf("Failed to attach pid %d, errno = %d\n", pid, -err); -+ return(-1); -+ } -+ if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL); -+ init_proxy(pid, 1, status); -+ return(pid); -+} -+ -+#ifdef notdef /* Put this back in when it does something useful */ -+static int __init uml_gdb_init_setup(char *line, int *add) -+{ -+ gdb_init = uml_strdup(line); -+ return 0; -+} -+ -+__uml_setup("gdb=", uml_gdb_init_setup, -+"gdb=<channel description>\n\n" -+); -+#endif -+ -+static int __init uml_gdb_pid_setup(char *line, int *add) -+{ -+ gdb_pid = strtoul(line, NULL, 0); -+ *add = 0; -+ return 0; -+} -+ -+__uml_setup("gdb-pid=", uml_gdb_pid_setup, -+"gdb-pid=<pid>\n" -+" gdb-pid is used to attach an external debugger to UML. This may be\n" -+" an already-running gdb or a debugger-like process like strace.\n\n" -+); -+ -+#else -+ -+int debugger_signal(int status, pid_t pid){ return(0); } -+void child_signal(pid_t pid, int status){ } -+int init_ptrace_proxy(int idle_pid, int startup, int stop) -+{ -+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); -+ kill_child_dead(idle_pid); -+ exit(1); -+} -+ -+void signal_usr1(int sig) -+{ -+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n"); -+} -+ -+int attach_debugger(int idle_pid, int pid, int stop) -+{ -+ printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY " -+ "is off\n"); -+ return(-1); -+} -+ -+int config_gdb(char *str) -+{ -+ return(-1); -+} -+ -+int remove_gdb(void) -+{ -+ return(-1); -+} -+ -+int init_parent_proxy(int pid) -+{ -+ return(-1); -+} -+ -+void debugger_parent_signal(int status, int pid) -+{ -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/gdb_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/gdb_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/gdb_kern.c 2005-05-03 22:28:14.493406880 +0300 -@@ -0,0 +1,40 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/config.h" -+#include "mconsole_kern.h" -+ -+#ifdef CONFIG_MCONSOLE -+ -+extern int gdb_config(char *str); -+extern int gdb_remove(char *unused); -+ -+static struct mc_device gdb_mc = { -+ .name = "gdb", -+ .config = gdb_config, -+ .remove = gdb_remove, -+}; -+ -+int gdb_mc_init(void) -+{ -+ mconsole_register_dev(&gdb_mc); -+ return(0); -+} -+ -+__initcall(gdb_mc_init); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/debug.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/debug.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/debug.h 2005-05-03 22:28:14.494406728 +0300 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and -+ * Lars Brinkhoff. -+ * Licensed under the GPL -+ */ -+ -+#ifndef __DEBUG_H -+#define __DEBUG_H -+ -+extern int debugger_proxy(int status, pid_t pid); -+extern void child_proxy(pid_t pid, int status); -+extern void init_proxy (pid_t pid, int waiting, int status); -+extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); -+extern void fake_child_exit(void); -+extern int gdb_config(char *str); -+extern int gdb_remove(char *unused); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/mmu.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/mmu.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/mmu.h 2005-05-03 22:28:14.495406576 +0300 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_MMU_H -+#define __TT_MMU_H -+ -+struct mmu_context_tt { -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/mode.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/mode.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/mode.h 2005-05-03 22:28:14.496406424 +0300 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MODE_TT_H__ -+#define __MODE_TT_H__ -+ -+#include "sysdep/ptrace.h" -+ -+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; -+ -+extern int tracing_pid; -+ -+extern int tracer(int (*init_proc)(void *), void *sp); -+extern void user_time_init_tt(void); -+extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data); -+extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, -+ void *data); -+extern void sig_handler_common_tt(int sig, void *sc); -+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); -+extern void reboot_tt(void); -+extern void halt_tt(void); -+extern int is_tracer_winch(int pid, int fd, void *data); -+extern void kill_off_processes_tt(void); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/mode_kern.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/mode_kern.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/mode_kern.h 2005-05-03 22:28:14.496406424 +0300 -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_MODE_KERN_H__ -+#define __TT_MODE_KERN_H__ -+ -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+ -+extern void *_switch_to_tt(void *prev, void *next); -+extern void flush_thread_tt(void); -+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, -+ unsigned long esp); -+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct *p, -+ struct pt_regs *regs); -+extern void release_thread_tt(struct task_struct *task); -+extern void exit_thread_tt(void); -+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg); -+extern void init_idle_tt(void); -+extern void flush_tlb_kernel_vm_tt(void); -+extern void __flush_tlb_one_tt(unsigned long addr); -+extern void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_mm_tt(struct mm_struct *mm); -+extern void force_flush_all_tt(void); -+extern long execute_syscall_tt(void *r); -+extern void before_mem_tt(unsigned long brk_start); -+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out); -+extern int start_uml_tt(void); -+extern int external_pid_tt(struct task_struct *task); -+extern int thread_pid_tt(struct thread_struct *thread); -+ -+#define kmem_end_tt (host_task_size - ABOVE_KMEM) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/ptrace-tt.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/ptrace-tt.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/ptrace-tt.h 2005-05-03 22:28:14.497406272 +0300 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PTRACE_TT_H -+#define __PTRACE_TT_H -+ -+#include "uml-config.h" -+ -+#ifdef UML_CONFIG_MODE_TT -+#include "sysdep/sc.h" -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/tt.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/tt.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/tt.h 2005-05-03 22:28:14.498406120 +0300 -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_H__ -+#define __TT_H__ -+ -+#include "sysdep/ptrace.h" -+ -+extern int gdb_pid; -+extern int debug; -+extern int debug_stop; -+extern int debug_trace; -+ -+extern int honeypot; -+ -+extern int fork_tramp(void *sig_stack); -+extern int do_proc_op(void *t, int proc_id); -+extern int tracer(int (*init_proc)(void *), void *sp); -+extern void attach_process(int pid); -+extern void tracer_panic(char *format, ...); -+extern void set_init_pid(int pid); -+extern int set_user_mode(void *task); -+extern void set_tracing(void *t, int tracing); -+extern int is_tracing(void *task); -+extern void syscall_handler(int sig, union uml_pt_regs *regs); -+extern void exit_kernel(int pid, void *task); -+extern int do_syscall(void *task, int pid); -+extern int is_valid_pid(int pid); -+extern void remap_data(void *segment_start, void *segment_end, int w); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/include/uaccess.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/include/uaccess.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/include/uaccess.h 2005-05-03 22:28:14.499405968 +0300 -@@ -0,0 +1,71 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __TT_UACCESS_H -+#define __TT_UACCESS_H -+ -+#include "linux/string.h" -+#include "linux/sched.h" -+#include "asm/processor.h" -+#include "asm/errno.h" -+#include "asm/current.h" -+#include "asm/a.out.h" -+#include "uml_uaccess.h" -+ -+#define ABOVE_KMEM (16 * 1024 * 1024) -+ -+extern unsigned long end_vm; -+extern unsigned long uml_physmem; -+ -+#define under_task_size(addr, size) \ -+ (((unsigned long) (addr) < TASK_SIZE) && \ -+ (((unsigned long) (addr) + (size)) < TASK_SIZE)) -+ -+#define is_stack(addr, size) \ -+ (((unsigned long) (addr) < STACK_TOP) && \ -+ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ -+ (((unsigned long) (addr) + (size)) <= STACK_TOP)) -+ -+#define access_ok_tt(type, addr, size) \ -+ ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ -+ (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ -+ (under_task_size(addr, size) || is_stack(addr, size)))) -+ -+static inline int verify_area_tt(int type, const void * addr, -+ unsigned long size) -+{ -+ return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); -+} -+ -+extern unsigned long get_fault_addr(void); -+ -+extern int __do_copy_from_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher); -+extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, -+ void **fault_addr, void **fault_catcher); -+extern int __do_clear_user(void *mem, size_t len, void **fault_addr, -+ void **fault_catcher); -+extern int __do_strnlen_user(const char *str, unsigned long n, -+ void **fault_addr, void **fault_catcher); -+ -+extern int copy_from_user_tt(void *to, const void *from, int n); -+extern int copy_to_user_tt(void *to, const void *from, int n); -+extern int strncpy_from_user_tt(char *dst, const char *src, int count); -+extern int __clear_user_tt(void *mem, int len); -+extern int clear_user_tt(void *mem, int len); -+extern int strnlen_user_tt(const void *str, int len); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ksyms.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ksyms.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ksyms.c 2005-05-03 22:28:14.500405816 +0300 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/module.h" -+#include "asm/uaccess.h" -+#include "mode.h" -+ -+EXPORT_SYMBOL(__do_copy_from_user); -+EXPORT_SYMBOL(__do_copy_to_user); -+EXPORT_SYMBOL(__do_strncpy_from_user); -+EXPORT_SYMBOL(__do_strnlen_user); -+EXPORT_SYMBOL(__do_clear_user); -+ -+EXPORT_SYMBOL(tracing_pid); -+EXPORT_SYMBOL(honeypot); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/Makefile 2005-05-03 22:28:14.501405664 +0300 -@@ -0,0 +1,39 @@ -+# -+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = tt.o -+ -+obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ -+ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ -+ uaccess.o uaccess_user.o -+ -+obj-$(CONFIG_PT_PROXY) += gdb_kern.o -+ -+subdir-y = sys-$(SUBARCH) -+subdir-$(CONFIG_PT_PROXY) += ptproxy -+ -+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o)) -+ -+export-objs = ksyms.o -+ -+USER_OBJS = $(filter %_user.o,$(obj-y)) gdb.o time.o tracer.o -+ -+UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS)) -+UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+$(O_TARGET) : unmap_fin.o -+ -+unmap.o: unmap.c -+ $(CC) $(UNMAP_CFLAGS) -c -o $@ $< -+ -+unmap_fin.o : unmap.o -+ ld -r -o $@ $< -lc -L/usr/lib -+ -+clean : -Index: linux-2.4.29/arch/um/kernel/tt/mem.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/mem.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/mem.c 2005-05-03 22:28:14.502405512 +0300 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "asm/uaccess.h" -+#include "mem_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "kern.h" -+#include "tt.h" -+ -+void before_mem_tt(unsigned long brk_start) -+{ -+ if(!jail || debug) -+ remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); -+ remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); -+ remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); -+} -+ -+#ifdef CONFIG_HOST_2G_2G -+#define TOP 0x80000000 -+#else -+#define TOP 0xc0000000 -+#endif -+ -+#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000) -+#define START (TOP - SIZE) -+ -+unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out, -+ unsigned long *task_size_out) -+{ -+ /* Round up to the nearest 4M */ -+ *host_size_out = ROUND_4M((unsigned long) &arg); -+ *task_size_out = START; -+ return(START); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/mem_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/mem_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/mem_user.c 2005-05-03 22:28:14.502405512 +0300 -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <stdio.h> -+#include <unistd.h> -+#include <string.h> -+#include <errno.h> -+#include <sys/mman.h> -+#include "tt.h" -+#include "mem_user.h" -+#include "user_util.h" -+ -+void remap_data(void *segment_start, void *segment_end, int w) -+{ -+ void *addr; -+ unsigned long size; -+ int data, prot; -+ -+ if(w) prot = PROT_WRITE; -+ else prot = 0; -+ prot |= PROT_READ | PROT_EXEC; -+ size = (unsigned long) segment_end - -+ (unsigned long) segment_start; -+ data = create_mem_file(size); -+ addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); -+ if(addr == MAP_FAILED){ -+ perror("mapping new data segment"); -+ exit(1); -+ } -+ memcpy(addr, segment_start, size); -+ if(switcheroo(data, prot, addr, segment_start, size) < 0){ -+ printf("switcheroo failed\n"); -+ exit(1); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/process_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/process_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/process_kern.c 2005-05-03 22:28:14.526401864 +0300 -@@ -0,0 +1,615 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "linux/signal.h" -+#include "linux/kernel.h" -+#include "linux/slab.h" -+#include "asm/system.h" -+#include "asm/pgalloc.h" -+#include "asm/ptrace.h" -+#include "irq_user.h" -+#include "signal_user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "os.h" -+#include "kern.h" -+#include "sigcontext.h" -+#include "time_user.h" -+#include "mem_user.h" -+#include "tlb.h" -+#include "mode.h" -+#include "init.h" -+#include "tt.h" -+#include "filehandle.h" -+ -+void *_switch_to_tt(void *prev, void *next) -+{ -+ struct task_struct *from, *to, *prev_sched; -+ struct file_handle *pipe; -+ unsigned long flags; -+ int err, vtalrm, alrm, prof, cpu; -+ char c; -+ /* jailing and SMP are incompatible, so this doesn't need to be -+ * made per-cpu -+ */ -+ static int reading; -+ -+ from = prev; -+ to = next; -+ -+ to->thread.prev_sched = from; -+ -+ cpu = from->processor; -+ if(cpu == 0) -+ forward_interrupts(to->thread.mode.tt.extern_pid); -+#ifdef CONFIG_SMP -+ forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid); -+#endif -+ local_irq_save(flags); -+ -+ vtalrm = change_sig(SIGVTALRM, 0); -+ alrm = change_sig(SIGALRM, 0); -+ prof = change_sig(SIGPROF, 0); -+ -+ c = 0; -+ set_current(to); -+ -+ reading = 0; -+ pipe = to->thread.mode.tt.switch_pipe; -+ err = write_file(&pipe[1], -1, &c, sizeof(c)); -+ if(err != sizeof(c)) -+ panic("write of switch_pipe failed, err = %d", -err); -+ -+ reading = 1; -+ if(from->state == TASK_ZOMBIE) -+ os_kill_process(os_getpid(), 0); -+ -+ pipe = from->thread.mode.tt.switch_pipe; -+ err = read_file(&pipe[0], -1, &c, sizeof(c)); -+ if(err != sizeof(c)) -+ panic("read of switch_pipe failed, errno = %d", -err); -+ -+ /* If the process that we have just scheduled away from has exited, -+ * then it needs to be killed here. The reason is that, even though -+ * it will kill itself when it next runs, that may be too late. Its -+ * stack will be freed, possibly before then, and if that happens, -+ * we have a use-after-free situation. So, it gets killed here -+ * in case it has not already killed itself. -+ */ -+ prev_sched = current->thread.prev_sched; -+ if(prev_sched->state == TASK_ZOMBIE) -+ os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1); -+ -+ /* This works around a nasty race with 'jail'. If we are switching -+ * between two threads of a threaded app and the incoming process -+ * runs before the outgoing process reaches the read, and it makes -+ * it all the way out to userspace, then it will have write-protected -+ * the outgoing process stack. Then, when the outgoing process -+ * returns from the write, it will segfault because it can no longer -+ * write its own stack. So, in order to avoid that, the incoming -+ * thread sits in a loop yielding until 'reading' is set. This -+ * isn't entirely safe, since there may be a reschedule from a timer -+ * happening between setting 'reading' and sleeping in read. But, -+ * it should get a whole quantum in which to reach the read and sleep, -+ * which should be enough. -+ */ -+ -+ if(jail){ -+ while(!reading) sched_yield(); -+ } -+ -+ change_sig(SIGVTALRM, vtalrm); -+ change_sig(SIGALRM, alrm); -+ change_sig(SIGPROF, prof); -+ -+ arch_switch(); -+ -+ flush_tlb_all(); -+ local_irq_restore(flags); -+ -+ return(current->thread.prev_sched); -+} -+ -+void release_thread_tt(struct task_struct *task) -+{ -+ os_kill_process(task->thread.mode.tt.extern_pid, 0); -+} -+ -+void exit_thread_tt(void) -+{ -+ struct file_handle *pipe = current->thread.mode.tt.switch_pipe; -+ -+ close_file(&pipe[0]); -+ close_file(&pipe[1]); -+ kfree(pipe); -+} -+ -+static void suspend_new_thread(struct file_handle *fh) -+{ -+ char c; -+ -+ os_stop_process(os_getpid()); -+ -+ if(read_file(fh, -1, &c, sizeof(c)) != sizeof(c)) -+ panic("read failed in suspend_new_thread"); -+} -+ -+extern void schedule_tail(struct task_struct *prev); -+ -+static void new_thread_handler(int sig) -+{ -+ struct file_handle *pipe; -+ unsigned long disable; -+ int (*fn)(void *); -+ void *arg; -+ -+ fn = current->thread.request.u.thread.proc; -+ arg = current->thread.request.u.thread.arg; -+ -+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); -+ disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | -+ (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); -+ SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; -+ -+ pipe = current->thread.mode.tt.switch_pipe; -+ suspend_new_thread(&pipe[0]); -+ -+ init_new_thread_signals(1); -+ enable_timer(); -+ free_page(current->thread.temp_stack); -+ set_cmdline("(kernel thread)"); -+ force_flush_all(); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ change_sig(SIGUSR1, 1); -+ change_sig(SIGVTALRM, 1); -+ change_sig(SIGPROF, 1); -+ sti(); -+ if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) -+ do_exit(0); -+ -+ /* XXX No set_user_mode here because a newly execed process will -+ * immediately segfault on its non-existent IP, coming straight back -+ * to the signal handler, which will call set_user_mode on its way -+ * out. This should probably change since it's confusing. -+ */ -+} -+ -+static int new_thread_proc(void *stack) -+{ -+ /* cli is needed to block out signals until this thread is properly -+ * scheduled. Otherwise, the tracing thread will get mighty upset -+ * about any signals that arrive before that. -+ * This has the complication that it sets the saved signal mask in -+ * the sigcontext to block signals. This gets restored when this -+ * thread (or a descendant, since they get a copy of this sigcontext) -+ * returns to userspace. -+ * So, this is compensated for elsewhere. -+ * XXX There is still a small window until cli() actually finishes -+ * where signals are possible - shouldn't be a problem in practice -+ * since SIGIO hasn't been forwarded here yet, and the cli should -+ * finish before a SIGVTALRM has time to be delivered. -+ */ -+ cli(); -+ init_new_thread_stack(stack, new_thread_handler); -+ os_usr1_process(os_getpid()); -+ change_sig(SIGUSR1, 1); -+ return(0); -+} -+ -+/* Signal masking - signals are blocked at the start of fork_tramp. They -+ * are re-enabled when finish_fork_handler is entered by fork_tramp hitting -+ * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, -+ * so it is blocked before it's called. They are re-enabled on sigreturn -+ * despite the fact that they were blocked when the SIGUSR1 was issued because -+ * copy_thread copies the parent's sigcontext, including the signal mask -+ * onto the signal frame. -+ */ -+ -+static void finish_fork_handler(int sig) -+{ -+ struct file_handle *pipe = current->thread.mode.tt.switch_pipe; -+ -+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); -+ suspend_new_thread(&pipe[0]); -+ -+ init_new_thread_signals(1); -+ enable_timer(); -+ sti(); -+ force_flush_all(); -+ if(current->mm != current->p_pptr->mm) -+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, -+ 1, 0, 1); -+ task_protections((unsigned long) current); -+ -+ if(current->thread.prev_sched != NULL) -+ schedule_tail(current->thread.prev_sched); -+ current->thread.prev_sched = NULL; -+ -+ free_page(current->thread.temp_stack); -+ cli(); -+ change_sig(SIGUSR1, 0); -+ set_user_mode(current); -+} -+ -+int fork_tramp(void *stack) -+{ -+ cli(); -+ arch_init_thread(); -+ init_new_thread_stack(stack, finish_fork_handler); -+ os_usr1_process(os_getpid()); -+ change_sig(SIGUSR1, 1); -+ return(0); -+} -+ -+struct file_handle *make_switch_pipe(void) -+{ -+ struct file_handle *pipe; -+ int err; -+ -+ pipe = kmalloc(sizeof(struct file_handle [2]), GFP_KERNEL); -+ if(pipe == NULL){ -+ pipe = ERR_PTR(-ENOMEM); -+ goto out; -+ } -+ -+ err = make_pipe(pipe); -+ if(err) -+ goto out_free; -+ -+ out: -+ return(pipe); -+ -+ out_free: -+ kfree(pipe); -+ pipe = ERR_PTR(err); -+ goto out; -+} -+ -+int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, -+ unsigned long stack_top, struct task_struct * p, -+ struct pt_regs *regs) -+{ -+ int (*tramp)(void *); -+ int new_pid, err; -+ unsigned long stack; -+ -+ if(current->thread.forking) -+ tramp = fork_tramp; -+ else { -+ tramp = new_thread_proc; -+ p->thread.request.u.thread = current->thread.request.u.thread; -+ } -+ -+ p->thread.mode.tt.switch_pipe = make_switch_pipe(); -+ if(IS_ERR(p->thread.mode.tt.switch_pipe)){ -+ err = PTR_ERR(p->thread.mode.tt.switch_pipe); -+ goto out; -+ } -+ -+ stack = alloc_stack(0, 0); -+ if(stack == 0){ -+ printk(KERN_ERR "copy_thread : failed to allocate " -+ "temporary stack\n"); -+ err = -ENOMEM; -+ goto out_close; -+ } -+ -+ clone_flags &= CLONE_VM; -+ p->thread.temp_stack = stack; -+ new_pid = start_fork_tramp(p, stack, clone_flags, tramp); -+ if(new_pid < 0){ -+ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -+ -new_pid); -+ err = new_pid; -+ goto out_stack; -+ } -+ -+ if(current->thread.forking){ -+ sc_to_sc(UPT_SC(&p->thread.regs.regs), -+ UPT_SC(¤t->thread.regs.regs)); -+ SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); -+ if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; -+ } -+ p->thread.mode.tt.extern_pid = new_pid; -+ -+ current->thread.request.op = OP_FORK; -+ current->thread.request.u.fork.pid = new_pid; -+ os_usr1_process(os_getpid()); -+ -+ /* Enable the signal and then disable it to ensure that it is handled -+ * here, and nowhere else. -+ */ -+ change_sig(SIGUSR1, 1); -+ -+ change_sig(SIGUSR1, 0); -+ err = 0; -+ -+ out: -+ return(err); -+ -+ out_stack: -+ free_stack(stack, 0); -+ out_close: -+ close_file(&((struct file_handle *) p->thread.mode.tt.switch_pipe)[0]); -+ close_file(&((struct file_handle *) p->thread.mode.tt.switch_pipe)[1]); -+ kfree(p->thread.mode.tt.switch_pipe); -+ goto out; -+} -+ -+void reboot_tt(void) -+{ -+ current->thread.request.op = OP_REBOOT; -+ os_usr1_process(os_getpid()); -+ change_sig(SIGUSR1, 1); -+} -+ -+void halt_tt(void) -+{ -+ current->thread.request.op = OP_HALT; -+ os_usr1_process(os_getpid()); -+ change_sig(SIGUSR1, 1); -+} -+ -+void kill_off_processes_tt(void) -+{ -+ struct task_struct *p; -+ int me; -+ -+ me = os_getpid(); -+ for_each_task(p){ -+ int pid = p->thread.mode.tt.extern_pid; -+ if((pid != me) && (pid != -1)) -+ os_kill_process(p->thread.mode.tt.extern_pid, 0); -+ } -+ if((init_task.thread.mode.tt.extern_pid != me) && -+ (init_task.thread.mode.tt.extern_pid != -1)) -+ os_kill_process(init_task.thread.mode.tt.extern_pid, 0); -+} -+ -+void initial_thread_cb_tt(void (*proc)(void *), void *arg) -+{ -+ if(os_getpid() == tracing_pid){ -+ (*proc)(arg); -+ } -+ else { -+ current->thread.request.op = OP_CB; -+ current->thread.request.u.cb.proc = proc; -+ current->thread.request.u.cb.arg = arg; -+ os_usr1_process(os_getpid()); -+ change_sig(SIGUSR1, 1); -+ -+ change_sig(SIGUSR1, 0); -+ } -+} -+ -+int do_proc_op(void *t, int proc_id) -+{ -+ struct task_struct *task; -+ struct thread_struct *thread; -+ int op, pid; -+ -+ task = t; -+ thread = &task->thread; -+ op = thread->request.op; -+ switch(op){ -+ case OP_NONE: -+ case OP_TRACE_ON: -+ break; -+ case OP_EXEC: -+ pid = thread->request.u.exec.pid; -+ do_exec(thread->mode.tt.extern_pid, pid); -+ thread->mode.tt.extern_pid = pid; -+ cpu_tasks[task->processor].pid = pid; -+ break; -+ case OP_FORK: -+ attach_process(thread->request.u.fork.pid); -+ break; -+ case OP_CB: -+ (*thread->request.u.cb.proc)(thread->request.u.cb.arg); -+ break; -+ case OP_REBOOT: -+ case OP_HALT: -+ break; -+ default: -+ tracer_panic("Bad op in do_proc_op"); -+ break; -+ } -+ thread->request.op = OP_NONE; -+ return(op); -+} -+ -+void init_idle_tt(void) -+{ -+ idle_timer(); -+} -+ -+/* Changed by jail_setup, which is a setup */ -+int jail = 0; -+ -+int __init jail_setup(char *line, int *add) -+{ -+ int ok = 1; -+ -+ if(jail) return(0); -+#ifdef CONFIG_SMP -+ printf("'jail' may not used used in a kernel with CONFIG_SMP " -+ "enabled\n"); -+ ok = 0; -+#endif -+#ifdef CONFIG_HOSTFS -+ printf("'jail' may not used used in a kernel with CONFIG_HOSTFS " -+ "enabled\n"); -+ ok = 0; -+#endif -+#ifdef CONFIG_MODULES -+ printf("'jail' may not used used in a kernel with CONFIG_MODULES " -+ "enabled\n"); -+ ok = 0; -+#endif -+ if(!ok) exit(1); -+ -+ /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem. -+ * Removing it from the bounding set eliminates the ability of anything -+ * to acquire it, and thus read or write kernel memory. -+ */ -+ cap_lower(cap_bset, CAP_SYS_RAWIO); -+ jail = 1; -+ return(0); -+} -+ -+__uml_setup("jail", jail_setup, -+"jail\n" -+" Enables the protection of kernel memory from processes.\n\n" -+); -+ -+static void mprotect_kernel_mem(int w) -+{ -+ unsigned long start, end; -+ int pages; -+ -+ if(!jail || (current == &init_task)) return; -+ -+ pages = (1 << CONFIG_KERNEL_STACK_ORDER); -+ -+ start = (unsigned long) current + PAGE_SIZE; -+ end = (unsigned long) current + PAGE_SIZE * pages; -+ protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1); -+ protect_memory(end, high_physmem - end, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&_stext); -+ end = (unsigned long) UML_ROUND_UP(&_etext); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end); -+ end = (unsigned long) UML_ROUND_UP(&_edata); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ start = (unsigned long) UML_ROUND_DOWN(&__bss_start); -+ end = (unsigned long) UML_ROUND_UP(&_end); -+ protect_memory(start, end - start, 1, w, 1, 1); -+ -+ mprotect_kernel_vm(w); -+} -+ -+void unprotect_kernel_mem(void) -+{ -+ mprotect_kernel_mem(1); -+} -+ -+void protect_kernel_mem(void) -+{ -+ mprotect_kernel_mem(0); -+} -+ -+extern void start_kernel(void); -+ -+static int start_kernel_proc(void *unused) -+{ -+ int pid; -+ -+ block_signals(); -+ pid = os_getpid(); -+ -+ cpu_tasks[0].pid = pid; -+ cpu_tasks[0].task = current; -+#ifdef CONFIG_SMP -+ cpu_online_map = 1; -+#endif -+ if(debug) os_stop_process(pid); -+ start_kernel(); -+ return(0); -+} -+ -+void set_tracing(void *task, int tracing) -+{ -+ ((struct task_struct *) task)->thread.mode.tt.tracing = tracing; -+} -+ -+int is_tracing(void *t) -+{ -+ return (((struct task_struct *) t)->thread.mode.tt.tracing); -+} -+ -+int set_user_mode(void *t) -+{ -+ struct task_struct *task; -+ -+ task = t ? t : current; -+ if(task->thread.mode.tt.tracing) -+ return(1); -+ task->thread.request.op = OP_TRACE_ON; -+ os_usr1_process(os_getpid()); -+ return(0); -+} -+ -+/* This is static rather than kmalloced because this happens before kmalloc -+ * is initialized. Also, it is always needed, so might as well be static on -+ * this ground. -+ */ -+static struct file_handle init_switch_pipe[2]; -+ -+void set_init_pid(int pid) -+{ -+ int err; -+ -+ init_task.thread.mode.tt.extern_pid = pid; -+ -+ err = make_pipe(init_switch_pipe); -+ if(err) -+ panic("set_init_pid - make_pipe failed, errno = %d", err); -+ init_task.thread.mode.tt.switch_pipe = init_switch_pipe; -+} -+ -+int start_uml_tt(void) -+{ -+ void *sp; -+ int pages; -+ -+ pages = (1 << CONFIG_KERNEL_STACK_ORDER); -+ sp = (void *) ((unsigned long) &init_task) + pages * PAGE_SIZE - -+ sizeof(unsigned long); -+ return(tracer(start_kernel_proc, sp)); -+} -+ -+int external_pid_tt(struct task_struct *task) -+{ -+ return(task->thread.mode.tt.extern_pid); -+} -+ -+int thread_pid_tt(struct thread_struct *thread) -+{ -+ return(thread->mode.tt.extern_pid); -+} -+ -+int is_valid_pid(int pid) -+{ -+ struct task_struct *task; -+ -+ read_lock(&tasklist_lock); -+ for_each_task(task){ -+ if(task->thread.mode.tt.extern_pid == pid){ -+ read_unlock(&tasklist_lock); -+ return(1); -+ } -+ } -+ read_unlock(&tasklist_lock); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/Makefile 2005-05-03 22:28:14.526401864 +0300 -@@ -0,0 +1,12 @@ -+O_TARGET = ptproxy.o -+ -+obj-y = proxy.o ptrace.o sysdep.o wait.o -+ -+USER_OBJS = $(obj-y) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean: -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/proxy.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/proxy.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/proxy.c 2005-05-03 22:28:14.529401408 +0300 -@@ -0,0 +1,371 @@ -+/********************************************************************** -+proxy.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+Jeff Dike (jdike@karaya.com) : Modified for integration into uml -+**********************************************************************/ -+ -+/* XXX This file shouldn't refer to CONFIG_* */ -+ -+#include <errno.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <signal.h> -+#include <string.h> -+#include <termios.h> -+#include <sys/wait.h> -+#include <sys/types.h> -+#include <sys/ptrace.h> -+#include <sys/ioctl.h> -+#include <asm/unistd.h> -+ -+#include "ptproxy.h" -+#include "sysdep.h" -+#include "wait.h" -+ -+#include "user_util.h" -+#include "user.h" -+#include "os.h" -+#include "tempfile.h" -+ -+static int debugger_wait(debugger_state *debugger, int *status, int options, -+ int (*syscall)(debugger_state *debugger, pid_t child), -+ int (*normal_return)(debugger_state *debugger, -+ pid_t unused), -+ int (*wait_return)(debugger_state *debugger, -+ pid_t unused)) -+{ -+ if(debugger->real_wait){ -+ debugger->handle_trace = normal_return; -+ syscall_continue(debugger->pid); -+ debugger->real_wait = 0; -+ return(1); -+ } -+ debugger->wait_status_ptr = status; -+ debugger->wait_options = options; -+ if((debugger->debugee != NULL) && debugger->debugee->event){ -+ syscall_continue(debugger->pid); -+ wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL, -+ NULL); -+ (*wait_return)(debugger, -1); -+ return(0); -+ } -+ else if(debugger->wait_options & WNOHANG){ -+ syscall_cancel(debugger->pid, 0); -+ debugger->handle_trace = syscall; -+ return(0); -+ } -+ else { -+ syscall_pause(debugger->pid); -+ debugger->handle_trace = wait_return; -+ debugger->waiting = 1; -+ } -+ return(1); -+} -+ -+/* -+ * Handle debugger trap, i.e. syscall. -+ */ -+ -+int debugger_syscall(debugger_state *debugger, pid_t child) -+{ -+ long arg1, arg2, arg3, arg4, arg5, result; -+ int syscall, ret = 0; -+ -+ syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, -+ &arg5); -+ -+ switch(syscall){ -+ case __NR_execve: -+ /* execve never returns */ -+ debugger->handle_trace = debugger_syscall; -+ break; -+ -+ case __NR_ptrace: -+ if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid; -+ if(!debugger->debugee->in_context) -+ child = debugger->debugee->pid; -+ result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child, -+ &ret); -+ syscall_cancel(debugger->pid, result); -+ debugger->handle_trace = debugger_syscall; -+ return(ret); -+ -+ case __NR_waitpid: -+ case __NR_wait4: -+ if(!debugger_wait(debugger, (int *) arg2, arg3, -+ debugger_syscall, debugger_normal_return, -+ proxy_wait_return)) -+ return(0); -+ break; -+ -+ case __NR_kill: -+ if(!debugger->debugee->in_context) -+ child = debugger->debugee->pid; -+ if(arg1 == debugger->debugee->pid){ -+ result = kill(child, arg2); -+ syscall_cancel(debugger->pid, result); -+ debugger->handle_trace = debugger_syscall; -+ return(0); -+ } -+ else debugger->handle_trace = debugger_normal_return; -+ break; -+ -+ default: -+ debugger->handle_trace = debugger_normal_return; -+ } -+ -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+/* Used by the tracing thread */ -+static debugger_state parent; -+static int parent_syscall(debugger_state *debugger, int pid); -+ -+int init_parent_proxy(int pid) -+{ -+ parent = ((debugger_state) { .pid = pid, -+ .wait_options = 0, -+ .wait_status_ptr = NULL, -+ .waiting = 0, -+ .real_wait = 0, -+ .expecting_child = 0, -+ .handle_trace = parent_syscall, -+ .debugee = NULL } ); -+ return(0); -+} -+ -+int parent_normal_return(debugger_state *debugger, pid_t unused) -+{ -+ debugger->handle_trace = parent_syscall; -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+static int parent_syscall(debugger_state *debugger, int pid) -+{ -+ long arg1, arg2, arg3, arg4, arg5; -+ int syscall; -+ -+ syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5); -+ -+ if((syscall == __NR_waitpid) || (syscall == __NR_wait4)){ -+ debugger_wait(&parent, (int *) arg2, arg3, parent_syscall, -+ parent_normal_return, parent_wait_return); -+ } -+ else ptrace(PTRACE_SYSCALL, pid, 0, 0); -+ return(0); -+} -+ -+int debugger_normal_return(debugger_state *debugger, pid_t unused) -+{ -+ debugger->handle_trace = debugger_syscall; -+ syscall_continue(debugger->pid); -+ return(0); -+} -+ -+void debugger_cancelled_return(debugger_state *debugger, int result) -+{ -+ debugger->handle_trace = debugger_syscall; -+ syscall_set_result(debugger->pid, result); -+ syscall_continue(debugger->pid); -+} -+ -+/* Used by the tracing thread */ -+static debugger_state debugger; -+static debugee_state debugee; -+ -+void init_proxy (pid_t debugger_pid, int stopped, int status) -+{ -+ debugger.pid = debugger_pid; -+ debugger.handle_trace = debugger_syscall; -+ debugger.debugee = &debugee; -+ debugger.waiting = 0; -+ debugger.real_wait = 0; -+ debugger.expecting_child = 0; -+ -+ debugee.pid = 0; -+ debugee.traced = 0; -+ debugee.stopped = stopped; -+ debugee.event = 0; -+ debugee.zombie = 0; -+ debugee.died = 0; -+ debugee.wait_status = status; -+ debugee.in_context = 1; -+} -+ -+int debugger_proxy(int status, int pid) -+{ -+ int ret = 0, sig; -+ -+ if(WIFSTOPPED(status)){ -+ sig = WSTOPSIG(status); -+ if (sig == SIGTRAP) -+ ret = (*debugger.handle_trace)(&debugger, pid); -+ -+ else if(sig == SIGCHLD){ -+ if(debugger.expecting_child){ -+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ debugger.expecting_child = 0; -+ } -+ else if(debugger.waiting) -+ real_wait_return(&debugger); -+ else { -+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ debugger.real_wait = 1; -+ } -+ } -+ else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig); -+ } -+ else if(WIFEXITED(status)){ -+ tracer_panic("debugger (pid %d) exited with status %d", -+ debugger.pid, WEXITSTATUS(status)); -+ } -+ else if(WIFSIGNALED(status)){ -+ tracer_panic("debugger (pid %d) exited with signal %d", -+ debugger.pid, WTERMSIG(status)); -+ } -+ else { -+ tracer_panic("proxy got unknown status (0x%x) on debugger " -+ "(pid %d)", status, debugger.pid); -+ } -+ return(ret); -+} -+ -+void child_proxy(pid_t pid, int status) -+{ -+ debugee.event = 1; -+ debugee.wait_status = status; -+ -+ if(WIFSTOPPED(status)){ -+ debugee.stopped = 1; -+ debugger.expecting_child = 1; -+ kill(debugger.pid, SIGCHLD); -+ } -+ else if(WIFEXITED(status) || WIFSIGNALED(status)){ -+ debugee.zombie = 1; -+ debugger.expecting_child = 1; -+ kill(debugger.pid, SIGCHLD); -+ } -+ else panic("proxy got unknown status (0x%x) on child (pid %d)", -+ status, pid); -+} -+ -+void debugger_parent_signal(int status, int pid) -+{ -+ int sig; -+ -+ if(WIFSTOPPED(status)){ -+ sig = WSTOPSIG(status); -+ if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid); -+ else ptrace(PTRACE_SYSCALL, pid, 0, sig); -+ } -+} -+ -+void fake_child_exit(void) -+{ -+ int status, pid; -+ -+ child_proxy(1, W_EXITCODE(0, 0)); -+ while(debugger.waiting == 1){ -+ CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); -+ if(pid != debugger.pid){ -+ printk("fake_child_exit - waitpid failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ debugger_proxy(status, debugger.pid); -+ } -+ CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); -+ if(pid != debugger.pid){ -+ printk("fake_child_exit - waitpid failed, " -+ "errno = %d\n", errno); -+ return; -+ } -+ if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0) -+ printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n", -+ errno); -+} -+ -+char gdb_init_string[] = -+"att 1 \n\ -+b panic \n\ -+b stop \n\ -+handle SIGWINCH nostop noprint pass \n\ -+"; -+ -+int start_debugger(char *prog, int startup, int stop, int *fd_out) -+{ -+ int slave, child; -+ -+ slave = open_gdb_chan(); -+ child = fork(); -+ if(child == 0){ -+ char *tempname = NULL; -+ int fd; -+ -+ if(setsid() < 0) perror("setsid"); -+ if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || -+ (dup2(slave, 2) < 0)){ -+ printk("start_debugger : dup2 failed, errno = %d\n", -+ errno); -+ exit(1); -+ } -+ if(ioctl(0, TIOCSCTTY, 0) < 0){ -+ printk("start_debugger : TIOCSCTTY failed, " -+ "errno = %d\n", errno); -+ exit(1); -+ } -+ if(tcsetpgrp (1, os_getpid()) < 0){ -+ printk("start_debugger : tcsetpgrp failed, " -+ "errno = %d\n", errno); -+#ifdef notdef -+ exit(1); -+#endif -+ } -+ fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); -+ if(fd < 0){ -+ printk("start_debugger : make_tempfile failed," -+ "err = %d\n", -fd); -+ exit(1); -+ } -+ os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); -+ if(startup){ -+ if(stop){ -+ os_write_file(fd, "b start_kernel\n", -+ strlen("b start_kernel\n")); -+ } -+ os_write_file(fd, "c\n", strlen("c\n")); -+ } -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ -+ printk("start_debugger : PTRACE_TRACEME failed, " -+ "errno = %d\n", errno); -+ exit(1); -+ } -+ execlp("gdb", "gdb", "--command", tempname, prog, NULL); -+ printk("start_debugger : exec of gdb failed, errno = %d\n", -+ errno); -+ } -+ if(child < 0){ -+ printk("start_debugger : fork for gdb failed, errno = %d\n", -+ errno); -+ return(-1); -+ } -+ *fd_out = slave; -+ return(child); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/ptproxy.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/ptproxy.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/ptproxy.h 2005-05-03 22:28:14.529401408 +0300 -@@ -0,0 +1,61 @@ -+/********************************************************************** -+ptproxy.h -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#ifndef __PTPROXY_H -+#define __PTPROXY_H -+ -+#include <sys/types.h> -+ -+typedef struct debugger debugger_state; -+typedef struct debugee debugee_state; -+ -+struct debugger -+{ -+ pid_t pid; -+ int wait_options; -+ int *wait_status_ptr; -+ unsigned int waiting : 1; -+ unsigned int real_wait : 1; -+ unsigned int expecting_child : 1; -+ int (*handle_trace) (debugger_state *, pid_t); -+ -+ debugee_state *debugee; -+}; -+ -+struct debugee -+{ -+ pid_t pid; -+ int wait_status; -+ unsigned int died : 1; -+ unsigned int event : 1; -+ unsigned int stopped : 1; -+ unsigned int trace_singlestep : 1; -+ unsigned int trace_syscall : 1; -+ unsigned int traced : 1; -+ unsigned int zombie : 1; -+ unsigned int in_context : 1; -+}; -+ -+extern int debugger_syscall(debugger_state *debugger, pid_t pid); -+extern int debugger_normal_return (debugger_state *debugger, pid_t unused); -+ -+extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t, -+ int *strace_out); -+extern void debugger_cancelled_return(debugger_state *debugger, int result); -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/ptrace.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/ptrace.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/ptrace.c 2005-05-03 22:28:14.531401104 +0300 -@@ -0,0 +1,239 @@ -+/********************************************************************** -+ptrace.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+Jeff Dike (jdike@karaya.com) : Modified for integration into uml -+**********************************************************************/ -+ -+#include <errno.h> -+#include <unistd.h> -+#include <signal.h> -+#include <sys/types.h> -+#include <sys/time.h> -+#include <sys/ptrace.h> -+#include <sys/wait.h> -+#include <asm/ptrace.h> -+ -+#include "ptproxy.h" -+#include "debug.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "ptrace_user.h" -+#include "tt.h" -+ -+long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, -+ long arg3, long arg4, pid_t child, int *ret) -+{ -+ sigset_t relay; -+ long result; -+ int status; -+ -+ *ret = 0; -+ if(debugger->debugee->died) return(-ESRCH); -+ -+ switch(arg1){ -+ case PTRACE_ATTACH: -+ if(debugger->debugee->traced) return(-EPERM); -+ -+ debugger->debugee->pid = arg2; -+ debugger->debugee->traced = 1; -+ -+ if(is_valid_pid(arg2) && (arg2 != child)){ -+ debugger->debugee->in_context = 0; -+ kill(arg2, SIGSTOP); -+ debugger->debugee->event = 1; -+ debugger->debugee->wait_status = W_STOPCODE(SIGSTOP); -+ } -+ else { -+ debugger->debugee->in_context = 1; -+ if(debugger->debugee->stopped) -+ child_proxy(child, W_STOPCODE(SIGSTOP)); -+ else kill(child, SIGSTOP); -+ } -+ -+ return(0); -+ -+ case PTRACE_DETACH: -+ if(!debugger->debugee->traced) return(-EPERM); -+ -+ debugger->debugee->traced = 0; -+ debugger->debugee->pid = 0; -+ if(!debugger->debugee->in_context) -+ kill(child, SIGCONT); -+ -+ return(0); -+ -+ case PTRACE_CONT: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ *ret = PTRACE_CONT; -+ return(ptrace(PTRACE_CONT, child, arg3, arg4)); -+ -+#ifdef UM_HAVE_GETFPREGS -+ case PTRACE_GETFPREGS: -+ { -+ long regs[FP_FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETFPREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, -+ regs[i]); -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_GETFPXREGS -+ case PTRACE_GETFPXREGS: -+ { -+ long regs[FPX_FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETFPXREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i, -+ regs[i]); -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_GETREGS -+ case PTRACE_GETREGS: -+ { -+ long regs[FRAME_SIZE]; -+ int i, result; -+ -+ result = ptrace(PTRACE_GETREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ ptrace (PTRACE_POKEDATA, debugger->pid, -+ arg4 + 4 * i, regs[i]); -+ return(result); -+ } -+ break; -+#endif -+ -+ case PTRACE_KILL: -+ result = ptrace(PTRACE_KILL, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ -+ case PTRACE_PEEKDATA: -+ case PTRACE_PEEKTEXT: -+ case PTRACE_PEEKUSER: -+ /* The value being read out could be -1, so we have to -+ * check errno to see if there's an error, and zero it -+ * beforehand so we're not faked out by an old error -+ */ -+ -+ errno = 0; -+ result = ptrace(arg1, child, arg3, 0); -+ if((result == -1) && (errno != 0)) return(-errno); -+ -+ result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ -+ case PTRACE_POKEDATA: -+ case PTRACE_POKETEXT: -+ case PTRACE_POKEUSER: -+ result = ptrace(arg1, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ if(arg1 == PTRACE_POKEUSER) ptrace_pokeuser(arg3, arg4); -+ return(result); -+ -+#ifdef UM_HAVE_SETFPREGS -+ case PTRACE_SETFPREGS: -+ { -+ long regs[FP_FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETFPREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_SETFPXREGS -+ case PTRACE_SETFPXREGS: -+ { -+ long regs[FPX_FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETFPXREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+#ifdef UM_HAVE_SETREGS -+ case PTRACE_SETREGS: -+ { -+ long regs[FRAME_SIZE]; -+ int i; -+ -+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) -+ regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid, -+ arg4 + 4 * i, 0); -+ result = ptrace(PTRACE_SETREGS, child, 0, regs); -+ if(result == -1) return(-errno); -+ -+ return(result); -+ } -+#endif -+ -+ case PTRACE_SINGLESTEP: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ sigemptyset(&relay); -+ sigaddset(&relay, SIGSEGV); -+ sigaddset(&relay, SIGILL); -+ sigaddset(&relay, SIGBUS); -+ result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP, -+ &relay); -+ child_proxy(child, status); -+ return(result); -+ -+ case PTRACE_SYSCALL: -+ if(!debugger->debugee->in_context) return(-EPERM); -+ result = ptrace(PTRACE_SYSCALL, child, arg3, arg4); -+ if(result == -1) return(-errno); -+ -+ *ret = PTRACE_SYSCALL; -+ return(result); -+ -+ case PTRACE_TRACEME: -+ default: -+ return(-EINVAL); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/sysdep.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/sysdep.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/sysdep.c 2005-05-03 22:28:14.532400952 +0300 -@@ -0,0 +1,72 @@ -+/********************************************************************** -+sysdep.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#include <stdio.h> -+#include <string.h> -+#include <stdlib.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/types.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+#include <linux/unistd.h> -+#include "ptrace_user.h" -+#include "user_util.h" -+#include "user.h" -+ -+int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, -+ long *arg5) -+{ -+ *arg1 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG1_OFFSET, 0); -+ *arg2 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG2_OFFSET, 0); -+ *arg3 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG3_OFFSET, 0); -+ *arg4 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG4_OFFSET, 0); -+ *arg5 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG5_OFFSET, 0); -+ return(ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0)); -+} -+ -+void syscall_cancel(pid_t pid, int result) -+{ -+ if((ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid) < 0) || -+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) || -+ (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) || -+ (ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result) < 0) || -+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)) -+ printk("ptproxy: couldn't cancel syscall: errno = %d\n", -+ errno); -+} -+ -+void syscall_set_result(pid_t pid, long result) -+{ -+ ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result); -+} -+ -+void syscall_continue(pid_t pid) -+{ -+ ptrace(PTRACE_SYSCALL, pid, 0, 0); -+} -+ -+int syscall_pause(pid_t pid) -+{ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){ -+ printk("syscall_change - ptrace failed, errno = %d\n", errno); -+ return(-1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/sysdep.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/sysdep.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/sysdep.h 2005-05-03 22:28:14.533400800 +0300 -@@ -0,0 +1,25 @@ -+/********************************************************************** -+sysdep.h -+ -+Copyright (C) 1999 Lars Brinkhoff. -+Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+See the file COPYING for licensing terms and conditions. -+**********************************************************************/ -+ -+extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, -+ long *arg4, long *arg5); -+extern void syscall_cancel (pid_t pid, long result); -+extern void syscall_set_result (pid_t pid, long result); -+extern void syscall_continue (pid_t pid); -+extern int syscall_pause(pid_t pid); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/wait.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/wait.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/wait.c 2005-05-03 22:28:14.534400648 +0300 -@@ -0,0 +1,88 @@ -+/********************************************************************** -+wait.c -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+ -+**********************************************************************/ -+ -+#include <errno.h> -+#include <signal.h> -+#include <sys/wait.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+ -+#include "ptproxy.h" -+#include "sysdep.h" -+#include "wait.h" -+#include "user_util.h" -+#include "sysdep/ptrace.h" -+#include "sysdep/ptrace_user.h" -+#include "sysdep/sigcontext.h" -+ -+int proxy_wait_return(struct debugger *debugger, pid_t unused) -+{ -+ debugger->waiting = 0; -+ -+ if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){ -+ debugger_cancelled_return(debugger, -ECHILD); -+ return(0); -+ } -+ -+ if(debugger->debugee->zombie && debugger->debugee->event) -+ debugger->debugee->died = 1; -+ -+ if(debugger->debugee->event){ -+ debugger->debugee->event = 0; -+ ptrace(PTRACE_POKEDATA, debugger->pid, -+ debugger->wait_status_ptr, -+ debugger->debugee->wait_status); -+ /* if (wait4) -+ ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */ -+ debugger_cancelled_return(debugger, debugger->debugee->pid); -+ return(0); -+ } -+ -+ /* pause will return -EINTR, which happens to be right for wait */ -+ debugger_normal_return(debugger, -1); -+ return(0); -+} -+ -+int parent_wait_return(struct debugger *debugger, pid_t unused) -+{ -+ return(debugger_normal_return(debugger, -1)); -+} -+ -+int real_wait_return(struct debugger *debugger) -+{ -+ unsigned long ip; -+ int pid; -+ -+ pid = debugger->pid; -+ -+ ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); -+ IP_RESTART_SYSCALL(ip); -+ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0) -+ tracer_panic("real_wait_return : Failed to restart system " -+ "call, errno = %d\n", errno); -+ -+ if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || -+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || -+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || -+ debugger_normal_return(debugger, -1)) -+ tracer_panic("real_wait_return : gdb failed to wait, " -+ "errno = %d\n", errno); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/ptproxy/wait.h -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/ptproxy/wait.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/ptproxy/wait.h 2005-05-03 22:28:14.534400648 +0300 -@@ -0,0 +1,15 @@ -+/********************************************************************** -+wait.h -+ -+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing -+terms and conditions. -+**********************************************************************/ -+ -+#ifndef __PTPROXY_WAIT_H -+#define __PTPROXY_WAIT_H -+ -+extern int proxy_wait_return(struct debugger *debugger, pid_t unused); -+extern int real_wait_return(struct debugger *debugger); -+extern int parent_wait_return(struct debugger *debugger, pid_t unused); -+ -+#endif -Index: linux-2.4.29/arch/um/kernel/tt/syscall_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/syscall_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/syscall_kern.c 2005-05-03 22:28:14.536400344 +0300 -@@ -0,0 +1,136 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/types.h" -+#include "linux/utime.h" -+#include "linux/sys.h" -+#include "asm/unistd.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "sysdep/syscalls.h" -+#include "kern_util.h" -+ -+static inline int check_area(void *ptr, int size) -+{ -+ return(verify_area(VERIFY_WRITE, ptr, size)); -+} -+ -+static int check_readlink(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ UPT_SYSCALL_ARG2(®s->regs))); -+} -+ -+static int check_utime(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct utimbuf))); -+} -+ -+static int check_oldstat(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct __old_kernel_stat))); -+} -+ -+static int check_stat(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct stat))); -+} -+ -+static int check_stat64(struct pt_regs *regs) -+{ -+ return(check_area((void *) UPT_SYSCALL_ARG1(®s->regs), -+ sizeof(struct stat64))); -+} -+ -+struct bogus { -+ int kernel_ds; -+ int (*check_params)(struct pt_regs *); -+}; -+ -+struct bogus this_is_bogus[256] = { -+ [ __NR_mknod ] = { 1, NULL }, -+ [ __NR_mkdir ] = { 1, NULL }, -+ [ __NR_rmdir ] = { 1, NULL }, -+ [ __NR_unlink ] = { 1, NULL }, -+ [ __NR_symlink ] = { 1, NULL }, -+ [ __NR_link ] = { 1, NULL }, -+ [ __NR_rename ] = { 1, NULL }, -+ [ __NR_umount ] = { 1, NULL }, -+ [ __NR_mount ] = { 1, NULL }, -+ [ __NR_pivot_root ] = { 1, NULL }, -+ [ __NR_chdir ] = { 1, NULL }, -+ [ __NR_chroot ] = { 1, NULL }, -+ [ __NR_open ] = { 1, NULL }, -+ [ __NR_quotactl ] = { 1, NULL }, -+ [ __NR_sysfs ] = { 1, NULL }, -+ [ __NR_readlink ] = { 1, check_readlink }, -+ [ __NR_acct ] = { 1, NULL }, -+ [ __NR_execve ] = { 1, NULL }, -+ [ __NR_uselib ] = { 1, NULL }, -+ [ __NR_statfs ] = { 1, NULL }, -+ [ __NR_truncate ] = { 1, NULL }, -+ [ __NR_access ] = { 1, NULL }, -+ [ __NR_chmod ] = { 1, NULL }, -+ [ __NR_chown ] = { 1, NULL }, -+ [ __NR_lchown ] = { 1, NULL }, -+ [ __NR_utime ] = { 1, check_utime }, -+ [ __NR_oldlstat ] = { 1, check_oldstat }, -+ [ __NR_oldstat ] = { 1, check_oldstat }, -+ [ __NR_stat ] = { 1, check_stat }, -+ [ __NR_lstat ] = { 1, check_stat }, -+ [ __NR_stat64 ] = { 1, check_stat64 }, -+ [ __NR_lstat64 ] = { 1, check_stat64 }, -+ [ __NR_chown32 ] = { 1, NULL }, -+}; -+ -+/* sys_utimes */ -+ -+static int check_bogosity(struct pt_regs *regs) -+{ -+ struct bogus *bogon = &this_is_bogus[UPT_SYSCALL_NR(®s->regs)]; -+ -+ if(!bogon->kernel_ds) return(0); -+ if(bogon->check_params && (*bogon->check_params)(regs)) -+ return(-EFAULT); -+ set_fs(KERNEL_DS); -+ return(0); -+} -+ -+extern syscall_handler_t *sys_call_table[]; -+ -+long execute_syscall_tt(void *r) -+{ -+ struct pt_regs *regs = r; -+ long res; -+ int syscall; -+ -+ current->thread.nsyscalls++; -+ nsyscalls++; -+ syscall = UPT_SYSCALL_NR(®s->regs); -+ -+ if((syscall >= NR_syscalls) || (syscall < 0)) -+ res = -ENOSYS; -+ else if(honeypot && check_bogosity(regs)) -+ res = -EFAULT; -+ else res = EXECUTE_SYSCALL(syscall, regs); -+ -+ set_fs(USER_DS); -+ -+ return(res); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/syscall_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/syscall_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/syscall_user.c 2005-05-03 22:28:14.537400192 +0300 -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sys/ptrace.h> -+#include <asm/unistd.h> -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "ptrace_user.h" -+#include "task.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "syscall_user.h" -+#include "tt.h" -+ -+/* XXX Bogus */ -+#define ERESTARTSYS 512 -+#define ERESTARTNOINTR 513 -+#define ERESTARTNOHAND 514 -+ -+void syscall_handler_tt(int sig, union uml_pt_regs *regs) -+{ -+ void *sc; -+ long result; -+ int index, syscall; -+ -+ syscall = UPT_SYSCALL_NR(regs); -+ sc = UPT_SC(regs); -+ SC_START_SYSCALL(sc); -+ -+ index = record_syscall_start(syscall); -+ syscall_trace(); -+ result = execute_syscall(regs); -+ -+ /* regs->sc may have changed while the system call ran (there may -+ * have been an interrupt or segfault), so it needs to be refreshed. -+ */ -+ UPT_SC(regs) = sc; -+ -+ SC_SET_SYSCALL_RETURN(sc, result); -+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || -+ (result == -ERESTARTNOINTR)) -+ do_signal(result); -+ -+ syscall_trace(); -+ record_syscall_end(index, result); -+} -+ -+int do_syscall(void *task, int pid) -+{ -+ unsigned long proc_regs[FRAME_SIZE]; -+ union uml_pt_regs *regs; -+ int syscall; -+ -+ if(ptrace_getregs(pid, proc_regs) < 0) -+ tracer_panic("Couldn't read registers"); -+ syscall = PT_SYSCALL_NR(proc_regs); -+ -+ regs = TASK_REGS(task); -+ UPT_SYSCALL_NR(regs) = syscall; -+ -+ if(syscall < 1) return(0); -+ -+ if((syscall != __NR_sigreturn) && -+ ((unsigned long *) PT_IP(proc_regs) >= &_stext) && -+ ((unsigned long *) PT_IP(proc_regs) <= &_etext)) -+ tracer_panic("I'm tracing myself and I can't get out"); -+ -+ if(use_sysemu) -+ return(1); -+ -+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, -+ __NR_getpid) < 0) -+ tracer_panic("do_syscall : Nullifying syscall failed, " -+ "errno = %d", errno); -+ return(1); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/sys-i386/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/sys-i386/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/sys-i386/Makefile 2005-05-03 22:28:14.538400040 +0300 -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = sys-i386.o -+ -+obj-y = sigcontext.o -+ -+USER_OBJS = sigcontext.o -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -Index: linux-2.4.29/arch/um/kernel/tt/sys-i386/sigcontext.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/sys-i386/sigcontext.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/sys-i386/sigcontext.c 2005-05-03 22:28:14.539399888 +0300 -@@ -0,0 +1,60 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <asm/sigcontext.h> -+#include "kern_util.h" -+#include "sysdep/frame.h" -+ -+int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data) -+{ -+ struct arch_frame_data *arch = data; -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ struct _fpstate *to_fp, *from_fp; -+ unsigned long sigs; -+ int err; -+ -+ to_fp = to->fpstate; -+ from_fp = from->fpstate; -+ sigs = to->oldmask; -+ err = copy_from_user_proc(to, from, sizeof(*to)); -+ to->oldmask = sigs; -+ if(to_fp != NULL){ -+ err |= copy_from_user_proc(&to->fpstate, &to_fp, -+ sizeof(to->fpstate)); -+ err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size); -+ } -+ return(err); -+} -+ -+int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data) -+{ -+ struct arch_frame_data *arch = data; -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ struct _fpstate *to_fp, *from_fp; -+ int err; -+ -+ to_fp = (struct _fpstate *) -+ (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -+ from_fp = from->fpstate; -+ err = copy_to_user_proc(to, from, sizeof(*to)); -+ if(from_fp != NULL){ -+ err |= copy_to_user_proc(&to->fpstate, &to_fp, -+ sizeof(to->fpstate)); -+ err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size); -+ } -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/time.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/time.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/time.c 2005-05-03 22:28:14.540399736 +0300 -@@ -0,0 +1,28 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include <sys/time.h> -+#include <time_user.h> -+#include "process.h" -+#include "user.h" -+ -+void user_time_init_tt(void) -+{ -+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR) -+ panic("Couldn't set SIGVTALRM handler"); -+ set_interval(ITIMER_VIRTUAL); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/tlb.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/tlb.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/tlb.c 2005-05-03 22:28:14.541399584 +0300 -@@ -0,0 +1,220 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/uaccess.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "os.h" -+ -+static void fix_range(struct mm_struct *mm, unsigned long start_addr, -+ unsigned long end_addr, int force) -+{ -+ pgd_t *npgd; -+ pmd_t *npmd; -+ pte_t *npte; -+ unsigned long addr; -+ int r, w, x, err; -+ -+ if((current->thread.mode.tt.extern_pid != -1) && -+ (current->thread.mode.tt.extern_pid != os_getpid())) -+ panic("fix_range fixing wrong address space, current = 0x%p", -+ current); -+ if(mm == NULL) return; -+ for(addr=start_addr;addr<end_addr;){ -+ if(addr == TASK_SIZE){ -+ /* Skip over kernel text, kernel data, and physical -+ * memory, which don't have ptes, plus kernel virtual -+ * memory, which is flushed separately, and remap -+ * the process stack. The only way to get here is -+ * if (end_addr == STACK_TOP) > TASK_SIZE, which is -+ * only true in the honeypot case. -+ */ -+ addr = STACK_TOP - ABOVE_KMEM; -+ continue; -+ } -+ npgd = pgd_offset(mm, addr); -+ npmd = pmd_offset(npgd, addr); -+ if(pmd_present(*npmd)){ -+ npte = pte_offset(npmd, addr); -+ r = pte_read(*npte); -+ w = pte_write(*npte); -+ x = pte_exec(*npte); -+ if(!pte_dirty(*npte)) w = 0; -+ if(!pte_young(*npte)){ -+ r = 0; -+ w = 0; -+ } -+ if(force || pte_newpage(*npte)){ -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*npte)) -+ map_memory(addr, -+ pte_val(*npte) & PAGE_MASK, -+ PAGE_SIZE, r, w, x); -+ } -+ else if(pte_newprot(*npte)){ -+ protect_memory(addr, PAGE_SIZE, r, w, x, 1); -+ } -+ *npte = pte_mkuptodate(*npte); -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(force || pmd_newpage(*npmd)){ -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ pmd_mkuptodate(*npmd); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+} -+ -+atomic_t vmchange_seq = ATOMIC_INIT(1); -+ -+static void flush_kernel_vm_range(unsigned long start, unsigned long end, -+ int update_seq) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ int updated = 0, err; -+ -+ mm = &init_mm; -+ for(addr = start; addr < end;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte) || pte_newpage(*pte)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, -+ PAGE_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ if(pte_present(*pte)) -+ map_memory(addr, -+ pte_val(*pte) & PAGE_MASK, -+ PAGE_SIZE, 1, 1, 1); -+ } -+ else if(pte_newprot(*pte)){ -+ updated = 1; -+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); -+ } -+ addr += PAGE_SIZE; -+ } -+ else { -+ if(pmd_newpage(*pmd)){ -+ updated = 1; -+ err = os_unmap_memory((void *) addr, PMD_SIZE); -+ if(err < 0) -+ panic("munmap failed, errno = %d\n", -+ -err); -+ } -+ addr += PMD_SIZE; -+ } -+ } -+ if(updated && update_seq) atomic_inc(&vmchange_seq); -+} -+ -+static void protect_vm_page(unsigned long addr, int w, int must_succeed) -+{ -+ int err; -+ -+ err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed); -+ if(err == 0) return; -+ else if((err == -EFAULT) || (err == -ENOMEM)){ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1); -+ protect_vm_page(addr, w, 1); -+ } -+ else panic("protect_vm_page : protect failed, errno = %d\n", err); -+} -+ -+void mprotect_kernel_vm(int w) -+{ -+ struct mm_struct *mm; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ unsigned long addr; -+ -+ mm = &init_mm; -+ for(addr = start_vm; addr < end_vm;){ -+ pgd = pgd_offset(mm, addr); -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_present(*pmd)){ -+ pte = pte_offset(pmd, addr); -+ if(pte_present(*pte)) protect_vm_page(addr, w, 0); -+ addr += PAGE_SIZE; -+ } -+ else addr += PMD_SIZE; -+ } -+} -+ -+void flush_tlb_kernel_vm_tt(void) -+{ -+ flush_kernel_vm_range(start_vm, end_vm, 1); -+} -+ -+void __flush_tlb_one_tt(unsigned long addr) -+{ -+ flush_kernel_vm_range(addr, addr + PAGE_SIZE, 1); -+} -+ -+void flush_tlb_range_tt(struct mm_struct *mm, unsigned long start, -+ unsigned long end) -+{ -+ if(mm != current->mm) return; -+ -+ /* Assumes that the range start ... end is entirely within -+ * either process memory or kernel vm -+ */ -+ if((start >= start_vm) && (start < end_vm)) -+ flush_kernel_vm_range(start, end, 1); -+ else fix_range(mm, start, end, 0); -+} -+ -+void flush_tlb_mm_tt(struct mm_struct *mm) -+{ -+ unsigned long seq; -+ -+ if(mm != current->mm) return; -+ -+ fix_range(mm, 0, STACK_TOP, 0); -+ -+ seq = atomic_read(&vmchange_seq); -+ if(current->thread.mode.tt.vm_seq == seq) return; -+ current->thread.mode.tt.vm_seq = seq; -+ flush_kernel_vm_range(start_vm, end_vm, 0); -+} -+ -+void force_flush_all_tt(void) -+{ -+ fix_range(current->mm, 0, STACK_TOP, 1); -+ flush_kernel_vm_range(start_vm, end_vm, 0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/tracer.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/tracer.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/tracer.c 2005-05-03 22:28:14.543399280 +0300 -@@ -0,0 +1,457 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <stdarg.h> -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sched.h> -+#include <string.h> -+#include <sys/mman.h> -+#include <sys/ptrace.h> -+#include <sys/time.h> -+#include <sys/wait.h> -+#include "user.h" -+#include "sysdep/ptrace.h" -+#include "sigcontext.h" -+#include "sysdep/sigcontext.h" -+#include "os.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "mem_user.h" -+#include "process.h" -+#include "kern_util.h" -+#include "frame.h" -+#include "chan_user.h" -+#include "ptrace_user.h" -+#include "mode.h" -+#include "tt.h" -+ -+static int tracer_winch[2]; -+ -+int is_tracer_winch(int pid, int fd, void *data) -+{ -+ if(pid != tracing_pid) -+ return(0); -+ -+ register_winch_irq(tracer_winch[0], fd, -1, data); -+ return(1); -+} -+ -+static void tracer_winch_handler(int sig) -+{ -+ int n; -+ char c = 1; -+ -+ n = os_write_file(tracer_winch[1], &c, sizeof(c)); -+ if(n != sizeof(c)) -+ printk("tracer_winch_handler - write failed, err = %d\n", -n); -+} -+ -+/* Called only by the tracing thread during initialization */ -+ -+static void setup_tracer_winch(void) -+{ -+ int err; -+ -+ err = os_pipe(tracer_winch, 1, 1); -+ if(err < 0){ -+ printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); -+ return; -+ } -+ signal(SIGWINCH, tracer_winch_handler); -+} -+ -+void attach_process(int pid) -+{ -+ if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) || -+ (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) -+ tracer_panic("OP_FORK failed to attach pid"); -+ wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); -+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) -+ tracer_panic("OP_FORK failed to continue process"); -+} -+ -+void tracer_panic(char *format, ...) -+{ -+ va_list ap; -+ -+ va_start(ap, format); -+ vprintf(format, ap); -+ printf("\n"); -+ while(1) pause(); -+} -+ -+static void tracer_segv(int sig, struct sigcontext sc) -+{ -+ printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n", -+ SC_FAULT_ADDR(&sc), SC_IP(&sc)); -+ while(1) -+ pause(); -+} -+ -+/* Changed early in boot, and then only read */ -+int debug = 0; -+int debug_stop = 1; -+int debug_parent = 0; -+int honeypot = 0; -+ -+static int signal_tramp(void *arg) -+{ -+ int (*proc)(void *); -+ -+ if(honeypot && munmap((void *) (host_task_size - 0x10000000), -+ 0x10000000)) -+ panic("Unmapping stack failed"); -+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) -+ panic("ptrace PTRACE_TRACEME failed"); -+ os_stop_process(os_getpid()); -+ change_sig(SIGWINCH, 0); -+ signal(SIGUSR1, SIG_IGN); -+ change_sig(SIGCHLD, 0); -+ signal(SIGSEGV, (__sighandler_t) sig_handler); -+ set_cmdline("(idle thread)"); -+ set_init_pid(os_getpid()); -+ proc = arg; -+ return((*proc)(NULL)); -+} -+ -+static void sleeping_process_signal(int pid, int sig) -+{ -+ switch(sig){ -+ /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is -+ * right because the process must be in the kernel already. -+ */ -+ case SIGCONT: -+ case SIGTSTP: -+ if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) -+ tracer_panic("sleeping_process_signal : Failed to " -+ "continue pid %d, signal = %d, " -+ "errno = %d\n", pid, sig, errno); -+ break; -+ -+ /* This happens when the debugger (e.g. strace) is doing system call -+ * tracing on the kernel. During a context switch, the current task -+ * will be set to the incoming process and the outgoing process will -+ * hop into write and then read. Since it's not the current process -+ * any more, the trace of those will land here. So, we need to just -+ * PTRACE_SYSCALL it. -+ */ -+ case SIGTRAP: -+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) -+ tracer_panic("sleeping_process_signal : Failed to " -+ "PTRACE_SYSCALL pid %d, errno = %d\n", -+ pid, errno); -+ break; -+ case SIGSTOP: -+ break; -+ default: -+ tracer_panic("sleeping process %d got unexpected " -+ "signal : %d\n", pid, sig); -+ break; -+ } -+} -+ -+/* Accessed only by the tracing thread */ -+int debugger_pid = -1; -+int debugger_parent = -1; -+int debugger_fd = -1; -+int gdb_pid = -1; -+ -+struct { -+ int pid; -+ int signal; -+ unsigned long addr; -+ struct timeval time; -+} signal_record[1024][32]; -+ -+int signal_index[32]; -+int nsignals = 0; -+int debug_trace = 0; -+extern int io_nsignals, io_count, intr_count; -+ -+extern void signal_usr1(int sig); -+ -+int tracing_pid = -1; -+ -+int tracer(int (*init_proc)(void *), void *sp) -+{ -+ void *task = NULL; -+ unsigned long eip = 0; -+ int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; -+ int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; -+ int cont_syscall; -+ -+ capture_signal_stack(); -+ signal(SIGPIPE, SIG_IGN); -+ setup_tracer_winch(); -+ tracing_pid = os_getpid(); -+ printf("tracing thread pid = %d\n", tracing_pid); -+ -+ pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); -+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); -+ if(n < 0){ -+ printf("waitpid on idle thread failed, errno = %d\n", errno); -+ exit(1); -+ } -+ if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ -+ printf("Failed to continue idle thread, errno = %d\n", errno); -+ exit(1); -+ } -+ -+ signal(SIGSEGV, (sighandler_t) tracer_segv); -+ signal(SIGUSR1, signal_usr1); -+ if(debug_trace){ -+ printf("Tracing thread pausing to be attached\n"); -+ stop(); -+ } -+ if(debug){ -+ if(gdb_pid != -1) -+ debugger_pid = attach_debugger(pid, gdb_pid, 1); -+ else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop); -+ if(debug_parent){ -+ debugger_parent = os_process_parent(debugger_pid); -+ init_parent_proxy(debugger_parent); -+ err = attach(debugger_parent); -+ if(err){ -+ printf("Failed to attach debugger parent %d, " -+ "errno = %d\n", debugger_parent, -err); -+ debugger_parent = -1; -+ } -+ else { -+ if(ptrace(PTRACE_SYSCALL, debugger_parent, -+ 0, 0) < 0){ -+ printf("Failed to continue debugger " -+ "parent, errno = %d\n", errno); -+ debugger_parent = -1; -+ } -+ } -+ } -+ } -+ set_cmdline("(tracing thread)"); -+ while(1){ -+ CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); -+ if(pid <= 0){ -+ if(errno != ECHILD){ -+ printf("wait failed - errno = %d\n", errno); -+ } -+ continue; -+ } -+ if(pid == debugger_pid){ -+ int cont = 0; -+ -+ if(WIFEXITED(status) || WIFSIGNALED(status)) -+ debugger_pid = -1; -+ /* XXX Figure out how to deal with gdb and SMP */ -+ else cont = debugger_signal(status, cpu_tasks[0].pid); -+ if(cont == PTRACE_SYSCALL) strace = 1; -+ continue; -+ } -+ else if(pid == debugger_parent){ -+ debugger_parent_signal(status, pid); -+ continue; -+ } -+ nsignals++; -+ if(WIFEXITED(status)) ; -+#ifdef notdef -+ { -+ printf("Child %d exited with status %d\n", pid, -+ WEXITSTATUS(status)); -+ } -+#endif -+ else if(WIFSIGNALED(status)){ -+ sig = WTERMSIG(status); -+ if(sig != 9){ -+ printf("Child %d exited with signal %d\n", pid, -+ sig); -+ } -+ } -+ else if(WIFSTOPPED(status)){ -+ proc_id = pid_to_processor_id(pid); -+ sig = WSTOPSIG(status); -+ if(signal_index[proc_id] == 1024){ -+ signal_index[proc_id] = 0; -+ last_index = 1023; -+ } -+ else last_index = signal_index[proc_id] - 1; -+ if(((sig == SIGPROF) || (sig == SIGVTALRM) || -+ (sig == SIGALRM)) && -+ (signal_record[proc_id][last_index].signal == sig)&& -+ (signal_record[proc_id][last_index].pid == pid)) -+ signal_index[proc_id] = last_index; -+ signal_record[proc_id][signal_index[proc_id]].pid = pid; -+ gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); -+ eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); -+ signal_record[proc_id][signal_index[proc_id]].addr = eip; -+ signal_record[proc_id][signal_index[proc_id]++].signal = sig; -+ -+ if(proc_id == -1){ -+ sleeping_process_signal(pid, sig); -+ continue; -+ } -+ -+ task = cpu_tasks[proc_id].task; -+ tracing = is_tracing(task); -+ old_tracing = tracing; -+ -+ cont_syscall = use_sysemu ? PTRACE_SYSEMU : -+ PTRACE_SYSCALL; -+ switch(sig){ -+ case SIGUSR1: -+ sig = 0; -+ op = do_proc_op(task, proc_id); -+ switch(op){ -+ case OP_TRACE_ON: -+ arch_leave_kernel(task, pid); -+ tracing = 1; -+ break; -+ case OP_REBOOT: -+ case OP_HALT: -+ unmap_physmem(); -+ kmalloc_ok = 0; -+ ptrace(PTRACE_KILL, pid, 0, 0); -+ return(op == OP_REBOOT); -+ case OP_NONE: -+ printf("Detaching pid %d\n", pid); -+ detach(pid, SIGSTOP); -+ continue; -+ default: -+ break; -+ } -+ /* OP_EXEC switches host processes on us, -+ * we want to continue the new one. -+ */ -+ pid = cpu_tasks[proc_id].pid; -+ break; -+ case SIGTRAP: -+ if(!tracing && (debugger_pid != -1)){ -+ child_signal(pid, status); -+ continue; -+ } -+ tracing = 0; -+ if(do_syscall(task, pid)) -+ sig = SIGUSR2; -+ break; -+ case SIGPROF: -+ if(tracing) sig = 0; -+ break; -+ case SIGCHLD: -+ case SIGHUP: -+ sig = 0; -+ break; -+ case SIGSEGV: -+ case SIGIO: -+ case SIGALRM: -+ case SIGVTALRM: -+ case SIGFPE: -+ case SIGBUS: -+ case SIGILL: -+ case SIGWINCH: -+ default: -+ tracing = 0; -+ break; -+ } -+ set_tracing(task, tracing); -+ -+ if(!tracing && old_tracing) -+ arch_enter_kernel(task, pid); -+ -+ if(!tracing && (debugger_pid != -1) && (sig != 0) && -+ (sig != SIGALRM) && (sig != SIGVTALRM) && -+ (sig != SIGSEGV) && (sig != SIGTRAP) && -+ (sig != SIGUSR2) && (sig != SIGIO) && -+ (sig != SIGFPE)){ -+ child_signal(pid, status); -+ continue; -+ } -+ -+ if(tracing){ -+ if(singlestepping(task)) -+ cont_type = PTRACE_SINGLESTEP; -+ else cont_type = cont_syscall; -+ } -+ else cont_type = PTRACE_CONT; -+ -+ if((cont_type == PTRACE_CONT) && -+ (debugger_pid != -1) && strace) -+ cont_type = PTRACE_SYSCALL; -+ -+ if(ptrace(cont_type, pid, 0, sig) != 0){ -+ tracer_panic("ptrace failed to continue " -+ "process - errno = %d\n", -+ errno); -+ } -+ } -+ } -+ return(0); -+} -+ -+static int __init uml_debug_setup(char *line, int *add) -+{ -+ char *next; -+ -+ debug = 1; -+ *add = 0; -+ if(*line != '=') return(0); -+ line++; -+ -+ while(line != NULL){ -+ next = strchr(line, ','); -+ if(next) *next++ = '\0'; -+ -+ if(!strcmp(line, "go")) debug_stop = 0; -+ else if(!strcmp(line, "parent")) debug_parent = 1; -+ else printf("Unknown debug option : '%s'\n", line); -+ -+ line = next; -+ } -+ return(0); -+} -+ -+__uml_setup("debug", uml_debug_setup, -+"debug\n" -+" Starts up the kernel under the control of gdb. See the \n" -+" kernel debugging tutorial and the debugging session pages\n" -+" at http://user-mode-linux.sourceforge.net/ for more information.\n\n" -+); -+ -+static int __init uml_debugtrace_setup(char *line, int *add) -+{ -+ debug_trace = 1; -+ return 0; -+} -+__uml_setup("debugtrace", uml_debugtrace_setup, -+"debugtrace\n" -+" Causes the tracing thread to pause until it is attached by a\n" -+" debugger and continued. This is mostly for debugging crashes\n" -+" early during boot, and should be pretty much obsoleted by\n" -+" the debug switch.\n\n" -+); -+ -+static int __init uml_honeypot_setup(char *line, int *add) -+{ -+ jail_setup("", add); -+ honeypot = 1; -+ return 0; -+} -+__uml_setup("honeypot", uml_honeypot_setup, -+"honeypot\n" -+" This makes UML put process stacks in the same location as they are\n" -+" on the host, allowing expoits such as stack smashes to work against\n" -+" UML. This implies 'jail'.\n\n" -+); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/trap_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/trap_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/trap_user.c 2005-05-03 22:28:14.544399128 +0300 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include <signal.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "signal_user.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "task.h" -+#include "tt.h" -+ -+void sig_handler_common_tt(int sig, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct tt_regs save_regs, *r; -+ struct signal_info *info; -+ int save_errno = errno, is_user; -+ -+ unprotect_kernel_mem(); -+ -+ /* This is done because to allow SIGSEGV to be delivered inside a SEGV -+ * handler. This can happen in copy_user, and if SEGV is disabled, -+ * the process will die. -+ */ -+ if(sig == SIGSEGV) -+ change_sig(SIGSEGV, 1); -+ -+ r = &TASK_REGS(get_current())->tt; -+ save_regs = *r; -+ is_user = user_context(SC_SP(sc)); -+ r->sc = sc; -+ if(sig != SIGUSR2) -+ r->syscall = -1; -+ -+ info = &sig_info[sig]; -+ if(!info->is_irq) unblock_signals(); -+ -+ (*info->handler)(sig, (union uml_pt_regs *) r); -+ -+ if(is_user){ -+ interrupt_end(); -+ block_signals(); -+ set_user_mode(NULL); -+ } -+ *r = save_regs; -+ errno = save_errno; -+ if(is_user) protect_kernel_mem(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/uaccess.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/uaccess.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/uaccess.c 2005-05-03 22:28:14.545398976 +0300 -@@ -0,0 +1,73 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "asm/uaccess.h" -+ -+int copy_from_user_tt(void *to, const void *from, int n) -+{ -+ if(!access_ok_tt(VERIFY_READ, from, n)) -+ return(n); -+ -+ return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int copy_to_user_tt(void *to, const void *from, int n) -+{ -+ if(!access_ok_tt(VERIFY_WRITE, to, n)) -+ return(n); -+ -+ return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int strncpy_from_user_tt(char *dst, const char *src, int count) -+{ -+ int n; -+ -+ if(!access_ok_tt(VERIFY_READ, src, 1)) -+ return(-EFAULT); -+ -+ n = __do_strncpy_from_user(dst, src, count, -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher); -+ if(n < 0) return(-EFAULT); -+ return(n); -+} -+ -+int __clear_user_tt(void *mem, int len) -+{ -+ return(__do_clear_user(mem, len, -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int clear_user_tt(void *mem, int len) -+{ -+ if(!access_ok_tt(VERIFY_WRITE, mem, len)) -+ return(len); -+ -+ return(__do_clear_user(mem, len, ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+int strnlen_user_tt(const void *str, int len) -+{ -+ return(__do_strnlen_user(str, len, -+ ¤t->thread.fault_addr, -+ ¤t->thread.fault_catcher)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/uaccess_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/uaccess_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/uaccess_user.c 2005-05-03 22:28:14.546398824 +0300 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <setjmp.h> -+#include <string.h> -+#include "user_util.h" -+#include "uml_uaccess.h" -+#include "task.h" -+#include "kern_util.h" -+ -+int __do_copy_from_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, -+ __do_copy, &faulted); -+ TASK_REGS(get_current())->tt = save; -+ -+ if(!faulted) return(0); -+ else return(n - (fault - (unsigned long) from)); -+} -+ -+static void __do_strncpy(void *dst, const void *src, int count) -+{ -+ strncpy(dst, src, count); -+} -+ -+int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, -+ __do_strncpy, &faulted); -+ TASK_REGS(get_current())->tt = save; -+ -+ if(!faulted) return(strlen(dst)); -+ else return(-1); -+} -+ -+static void __do_clear(void *to, const void *from, int n) -+{ -+ memset(to, 0, n); -+} -+ -+int __do_clear_user(void *mem, unsigned long len, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, -+ __do_clear, &faulted); -+ TASK_REGS(get_current())->tt = save; -+ -+ if(!faulted) return(0); -+ else return(len - (fault - (unsigned long) mem)); -+} -+ -+int __do_strnlen_user(const char *str, unsigned long n, -+ void **fault_addr, void **fault_catcher) -+{ -+ struct tt_regs save = TASK_REGS(get_current())->tt; -+ int ret; -+ unsigned long *faddrp = (unsigned long *)fault_addr; -+ sigjmp_buf jbuf; -+ -+ *fault_catcher = &jbuf; -+ if(sigsetjmp(jbuf, 1) == 0) -+ ret = strlen(str) + 1; -+ else ret = *faddrp - (unsigned long) str; -+ -+ *fault_addr = NULL; -+ *fault_catcher = NULL; -+ -+ TASK_REGS(get_current())->tt = save; -+ return ret; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tt/unmap.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tt/unmap.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tt/unmap.c 2005-05-03 22:28:14.547398672 +0300 -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <sys/mman.h> -+ -+int switcheroo(int fd, int prot, void *from, void *to, int size) -+{ -+ if(munmap(to, size) < 0){ -+ return(-1); -+ } -+ if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){ -+ return(-1); -+ } -+ if(munmap(from, size) < 0){ -+ return(-1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/tty_log.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/tty_log.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/tty_log.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,230 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and -+ * geoffrey hing <ghing@net.ohio-state.edu> -+ * Licensed under the GPL -+ */ -+ -+#include <errno.h> -+#include <string.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <sys/time.h> -+#include "init.h" -+#include "user.h" -+#include "kern_util.h" -+#include "os.h" -+ -+#define TTY_LOG_DIR "./" -+ -+/* Set early in boot and then unchanged */ -+static char *tty_log_dir = TTY_LOG_DIR; -+static int tty_log_fd = -1; -+ -+#define TTY_LOG_OPEN 1 -+#define TTY_LOG_CLOSE 2 -+#define TTY_LOG_WRITE 3 -+#define TTY_LOG_EXEC 4 -+ -+#define TTY_READ 1 -+#define TTY_WRITE 2 -+ -+struct tty_log_buf { -+ int what; -+ unsigned long tty; -+ int len; -+ int direction; -+ unsigned long sec; -+ unsigned long usec; -+}; -+ -+int open_tty_log(void *tty, void *current_tty) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")]; -+ int fd; -+ -+ gettimeofday(&tv, NULL); -+ if(tty_log_fd != -1){ -+ data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN, -+ .tty = (unsigned long) tty, -+ .len = sizeof(current_tty), -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ os_write_file(tty_log_fd, ¤t_tty, data.len); -+ return(tty_log_fd); -+ } -+ -+ sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, -+ (unsigned int) tv.tv_usec); -+ -+ fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))), -+ 0644); -+ if(fd < 0){ -+ printk("open_tty_log : couldn't open '%s', errno = %d\n", -+ buf, -fd); -+ } -+ return(fd); -+} -+ -+void close_tty_log(int fd, void *tty) -+{ -+ struct tty_log_buf data; -+ struct timeval tv; -+ -+ if(tty_log_fd != -1){ -+ gettimeofday(&tv, NULL); -+ data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE, -+ .tty = (unsigned long) tty, -+ .len = 0, -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ return; -+ } -+ os_close_file(fd); -+} -+ -+static int log_chunk(int fd, const char *buf, int len) -+{ -+ int total = 0, try, missed, n; -+ char chunk[64]; -+ -+ while(len > 0){ -+ try = (len > sizeof(chunk)) ? sizeof(chunk) : len; -+ missed = copy_from_user_proc(chunk, (char *) buf, try); -+ try -= missed; -+ n = os_write_file(fd, chunk, try); -+ if(n != try) { -+ if(n < 0) -+ return(n); -+ return(-EIO); -+ } -+ if(missed != 0) -+ return(-EFAULT); -+ -+ len -= try; -+ total += try; -+ buf += try; -+ } -+ -+ return(total); -+} -+ -+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ int direction; -+ -+ if(fd == tty_log_fd){ -+ gettimeofday(&tv, NULL); -+ direction = is_read ? TTY_READ : TTY_WRITE; -+ data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE, -+ .tty = (unsigned long) tty, -+ .len = len, -+ .direction = direction, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ } -+ -+ return(log_chunk(fd, buf, len)); -+} -+ -+void log_exec(char **argv, void *tty) -+{ -+ struct timeval tv; -+ struct tty_log_buf data; -+ char **ptr,*arg; -+ int len; -+ -+ if(tty_log_fd == -1) return; -+ -+ gettimeofday(&tv, NULL); -+ -+ len = 0; -+ for(ptr = argv; ; ptr++){ -+ if(copy_from_user_proc(&arg, ptr, sizeof(arg))) -+ return; -+ if(arg == NULL) break; -+ len += strlen_user_proc(arg); -+ } -+ -+ data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC, -+ .tty = (unsigned long) tty, -+ .len = len, -+ .direction = 0, -+ .sec = tv.tv_sec, -+ .usec = tv.tv_usec } ); -+ os_write_file(tty_log_fd, &data, sizeof(data)); -+ -+ for(ptr = argv; ; ptr++){ -+ if(copy_from_user_proc(&arg, ptr, sizeof(arg))) -+ return; -+ if(arg == NULL) break; -+ log_chunk(tty_log_fd, arg, strlen_user_proc(arg)); -+ } -+} -+ -+extern void register_tty_logger(int (*opener)(void *, void *), -+ int (*writer)(int, const char *, int, -+ void *, int), -+ void (*closer)(int, void *)); -+ -+static int register_logger(void) -+{ -+ register_tty_logger(open_tty_log, write_tty_log, close_tty_log); -+ return(0); -+} -+ -+__uml_initcall(register_logger); -+ -+static int __init set_tty_log_dir(char *name, int *add) -+{ -+ tty_log_dir = name; -+ return 0; -+} -+ -+__uml_setup("tty_log_dir=", set_tty_log_dir, -+"tty_log_dir=<directory>\n" -+" This is used to specify the directory where the logs of all pty\n" -+" data from this UML machine will be written.\n\n" -+); -+ -+static int __init set_tty_log_fd(char *name, int *add) -+{ -+ char *end; -+ -+ tty_log_fd = strtoul(name, &end, 0); -+ if((*end != '\0') || (end == name)){ -+ printf("set_tty_log_fd - strtoul failed on '%s'\n", name); -+ tty_log_fd = -1; -+ } -+ -+ *add = 0; -+ return 0; -+} -+ -+__uml_setup("tty_log_fd=", set_tty_log_fd, -+"tty_log_fd=<fd>\n" -+" This is used to specify a preconfigured file descriptor to which all\n" -+" tty data will be written. Preconfigure the descriptor with something\n" -+" like '10>tty_log tty_log_fd=10'.\n\n" -+); -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/uaccess_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/uaccess_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/uaccess_user.c 2005-05-03 22:28:14.549398368 +0300 -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <setjmp.h> -+#include <string.h> -+ -+/* These are here rather than tt/uaccess.c because skas mode needs them in -+ * order to do SIGBUS recovery when a tmpfs mount runs out of room. -+ */ -+ -+unsigned long __do_user_copy(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher, -+ void (*op)(void *to, const void *from, -+ int n), int *faulted_out) -+{ -+ unsigned long *faddrp = (unsigned long *) fault_addr, ret; -+ -+ sigjmp_buf jbuf; -+ *fault_catcher = &jbuf; -+ if(sigsetjmp(jbuf, 1) == 0){ -+ (*op)(to, from, n); -+ ret = 0; -+ *faulted_out = 0; -+ } -+ else { -+ ret = *faddrp; -+ *faulted_out = 1; -+ } -+ *fault_addr = NULL; -+ *fault_catcher = NULL; -+ return ret; -+} -+ -+void __do_copy(void *to, const void *from, int n) -+{ -+ memcpy(to, from, n); -+} -+ -+ -+int __do_copy_to_user(void *to, const void *from, int n, -+ void **fault_addr, void **fault_catcher) -+{ -+ unsigned long fault; -+ int faulted; -+ -+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, -+ __do_copy, &faulted); -+ if(!faulted) return(0); -+ else return(n - (fault - (unsigned long) to)); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/um_arch.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/um_arch.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/um_arch.c 2005-05-03 22:28:14.552397912 +0300 -@@ -0,0 +1,445 @@ -+/* -+ * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/kernel.h" -+#include "linux/sched.h" -+#include "linux/notifier.h" -+#include "linux/mm.h" -+#include "linux/types.h" -+#include "linux/tty.h" -+#include "linux/init.h" -+#include "linux/bootmem.h" -+#include "linux/spinlock.h" -+#include "linux/utsname.h" -+#include "linux/sysrq.h" -+#include "linux/seq_file.h" -+#include "linux/delay.h" -+#include "asm/page.h" -+#include "asm/pgtable.h" -+#include "asm/ptrace.h" -+#include "asm/elf.h" -+#include "asm/user.h" -+#include "ubd_user.h" -+#include "asm/current.h" -+#include "user_util.h" -+#include "kern_util.h" -+#include "kern.h" -+#include "mem_user.h" -+#include "mem.h" -+#include "umid.h" -+#include "initrd.h" -+#include "init.h" -+#include "os.h" -+#include "choose-mode.h" -+#include "mode_kern.h" -+#include "mode.h" -+ -+#define DEFAULT_COMMAND_LINE "root=/dev/ubd0" -+ -+struct cpuinfo_um boot_cpu_data = { -+ .loops_per_jiffy = 0, -+ .pgd_quick = NULL, -+ .pmd_quick = NULL, -+ .pte_quick = NULL, -+ .pgtable_cache_sz = 0, -+ .ipi_pipe = { -1, -1 } -+}; -+ -+unsigned long thread_saved_pc(struct thread_struct *thread) -+{ -+ return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, -+ thread))); -+} -+ -+static int show_cpuinfo(struct seq_file *m, void *v) -+{ -+ int index = 0; -+ -+#ifdef CONFIG_SMP -+ index = (struct cpuinfo_um *)v - cpu_data; -+ if (!(cpu_online_map & (1 << index))) -+ return 0; -+#endif -+ -+ seq_printf(m, "processor\t: %d\n", index); -+ seq_printf(m, "vendor_id\t: User Mode Linux\n"); -+ seq_printf(m, "model name\t: UML\n"); -+ seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); -+ seq_printf(m, "host\t\t: %s\n", host_info); -+ seq_printf(m, "bogomips\t: %lu.%02lu\n\n", -+ loops_per_jiffy/(500000/HZ), -+ (loops_per_jiffy/(5000/HZ)) % 100); -+ -+ return(0); -+} -+ -+static void *c_start(struct seq_file *m, loff_t *pos) -+{ -+ return *pos < NR_CPUS ? cpu_data + *pos : NULL; -+} -+ -+static void *c_next(struct seq_file *m, void *v, loff_t *pos) -+{ -+ ++*pos; -+ return c_start(m, pos); -+} -+ -+static void c_stop(struct seq_file *m, void *v) -+{ -+} -+ -+struct seq_operations cpuinfo_op = { -+ .start = c_start, -+ .next = c_next, -+ .stop = c_stop, -+ .show = show_cpuinfo, -+}; -+ -+pte_t * __bad_pagetable(void) -+{ -+ panic("Someone should implement __bad_pagetable"); -+ return(NULL); -+} -+ -+/* Set in linux_main */ -+unsigned long host_task_size; -+unsigned long task_size; -+unsigned long uml_start; -+ -+/* Set in early boot */ -+unsigned long uml_physmem; -+unsigned long uml_reserved; -+unsigned long start_vm; -+unsigned long end_vm; -+int ncpus = 1; -+ -+#ifdef CONFIG_MODE_TT -+/* Pointer set in linux_main, the array itself is private to each thread, -+ * and changed at address space creation time so this poses no concurrency -+ * problems. -+ */ -+static char *argv1_begin = NULL; -+static char *argv1_end = NULL; -+#endif -+ -+/* Set in early boot */ -+static int have_root __initdata = 0; -+long physmem_size = 32 * 1024 * 1024; -+ -+void set_cmdline(char *cmd) -+{ -+#ifdef CONFIG_MODE_TT -+ char *umid, *ptr; -+ -+ if(CHOOSE_MODE(honeypot, 0)) return; -+ -+ umid = get_umid(1); -+ if(umid != NULL){ -+ snprintf(argv1_begin, -+ (argv1_end - argv1_begin) * sizeof(*ptr), -+ "(%s) ", umid); -+ ptr = &argv1_begin[strlen(argv1_begin)]; -+ } -+ else ptr = argv1_begin; -+ -+ snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); -+ memset(argv1_begin + strlen(argv1_begin), '\0', -+ argv1_end - argv1_begin - strlen(argv1_begin)); -+#endif -+} -+ -+static char *usage_string = -+"User Mode Linux v%s\n" -+" available at http://user-mode-linux.sourceforge.net/\n\n"; -+ -+static int __init uml_version_setup(char *line, int *add) -+{ -+ printf("%s\n", system_utsname.release); -+ exit(0); -+} -+ -+__uml_setup("--version", uml_version_setup, -+"--version\n" -+" Prints the version number of the kernel.\n\n" -+); -+ -+static int __init uml_root_setup(char *line, int *add) -+{ -+ have_root = 1; -+ return 0; -+} -+ -+__uml_setup("root=", uml_root_setup, -+"root=<file containing the root fs>\n" -+" This is actually used by the generic kernel in exactly the same\n" -+" way as in any other kernel. If you configure a number of block\n" -+" devices and want to boot off something other than ubd0, you \n" -+" would use something like:\n" -+" root=/dev/ubd5\n\n" -+); -+ -+#ifdef CONFIG_SMP -+static int __init uml_ncpus_setup(char *line, int *add) -+{ -+ if (!sscanf(line, "%d", &ncpus)) { -+ printf("Couldn't parse [%s]\n", line); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+__uml_setup("ncpus=", uml_ncpus_setup, -+"ncpus=<# of desired CPUs>\n" -+" This tells an SMP kernel how many virtual processors to start.\n\n" -+); -+#endif -+ -+int force_tt = 0; -+ -+#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) -+#define DEFAULT_TT 0 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ force_tt = 1; -+ return(0); -+} -+ -+#else -+#ifdef CONFIG_MODE_SKAS -+ -+#define DEFAULT_TT 0 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); -+ return(0); -+} -+ -+#else -+#ifdef CONFIG_MODE_TT -+ -+#define DEFAULT_TT 1 -+ -+static int __init mode_tt_setup(char *line, int *add) -+{ -+ printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); -+ return(0); -+} -+ -+#else -+ -+#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled -+ -+#endif -+#endif -+#endif -+ -+__uml_setup("mode=tt", mode_tt_setup, -+"mode=tt\n" -+" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" -+" forces UML to run in tt (tracing thread) mode. It is not the default\n" -+" because it's slower and less secure than skas mode.\n\n" -+); -+ -+int mode_tt = DEFAULT_TT; -+ -+static int __init Usage(char *line, int *add) -+{ -+ const char **p; -+ -+ printf(usage_string, system_utsname.release); -+ p = &__uml_help_start; -+ while (p < &__uml_help_end) { -+ printf("%s", *p); -+ p++; -+ } -+ exit(0); -+} -+ -+__uml_setup("--help", Usage, -+"--help\n" -+" Prints this message.\n\n" -+); -+ -+static int __init uml_checksetup(char *line, int *add) -+{ -+ struct uml_param *p; -+ -+ p = &__uml_setup_start; -+ while(p < &__uml_setup_end) { -+ int n; -+ -+ n = strlen(p->str); -+ if(!strncmp(line, p->str, n)){ -+ if (p->setup_func(line + n, add)) return 1; -+ } -+ p++; -+ } -+ return 0; -+} -+ -+static void __init uml_postsetup(void) -+{ -+ initcall_t *p; -+ -+ p = &__uml_postsetup_start; -+ while(p < &__uml_postsetup_end){ -+ (*p)(); -+ p++; -+ } -+ return; -+} -+ -+/* Set during early boot */ -+unsigned long brk_start; -+unsigned long end_iomem; -+ -+#define MIN_VMALLOC (32 * 1024 * 1024) -+ -+int linux_main(int argc, char **argv) -+{ -+ unsigned long avail, diff; -+ unsigned long virtmem_size, max_physmem; -+ unsigned int i, add; -+ -+ for (i = 1; i < argc; i++){ -+ if((i == 1) && (argv[i][0] == ' ')) continue; -+ add = 1; -+ uml_checksetup(argv[i], &add); -+ if(add) add_arg(saved_command_line, argv[i]); -+ } -+ if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE); -+ -+ mode_tt = force_tt ? 1 : !can_do_skas(); -+ uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, -+ &host_task_size, &task_size); -+ -+ /* Need to check this early because mmapping happens before the -+ * kernel is running. -+ */ -+ check_tmpexec(); -+ -+ brk_start = (unsigned long) sbrk(0); -+ CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); -+ /* Increase physical memory size for exec-shield users -+ so they actually get what they asked for. This should -+ add zero for non-exec shield users */ -+ -+ diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); -+ if(diff > 1024 * 1024){ -+ printf("Adding %ld bytes to physical memory to account for " -+ "exec-shield gap\n", diff); -+ physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); -+ } -+ -+ uml_physmem = uml_start; -+ -+ /* Reserve up to 4M after the current brk */ -+ uml_reserved = ROUND_4M(brk_start) + (1 << 22); -+ -+ setup_machinename(system_utsname.machine); -+ -+#ifdef CONFIG_MODE_TT -+ argv1_begin = argv[1]; -+ argv1_end = &argv[1][strlen(argv[1])]; -+#endif -+ -+ highmem = 0; -+ iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; -+ max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; -+ -+ /* Zones have to begin on a 1 << MAX_ORDER page boundary, -+ * so this makes sure that's true for highmem -+ */ -+ max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); -+ if(physmem_size + iomem_size > max_physmem){ -+ highmem = physmem_size + iomem_size - max_physmem; -+ physmem_size -= highmem; -+#ifndef CONFIG_HIGHMEM -+ highmem = 0; -+ printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " -+ "to %ld bytes\n", physmem_size); -+#endif -+ } -+ -+ high_physmem = uml_physmem + physmem_size; -+ end_iomem = high_physmem + iomem_size; -+ high_memory = (void *) end_iomem; -+ -+ start_vm = VMALLOC_START; -+ -+ setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); -+ if(init_maps(physmem_size, iomem_size, highmem)){ -+ printf("Failed to allocate mem_map for %ld bytes of physical " -+ "memory and %ld bytes of highmem\n", physmem_size, -+ highmem); -+ exit(1); -+ } -+ -+ virtmem_size = physmem_size; -+ avail = get_kmem_end() - start_vm; -+ if(physmem_size > avail) virtmem_size = avail; -+ end_vm = start_vm + virtmem_size; -+ -+ if(virtmem_size < physmem_size) -+ printf("Kernel virtual memory size shrunk to %ld bytes\n", -+ virtmem_size); -+ -+ uml_postsetup(); -+ -+ task_protections((unsigned long) &init_task); -+ os_flush_stdout(); -+ -+ return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); -+} -+ -+extern int uml_exitcode; -+ -+static int panic_exit(struct notifier_block *self, unsigned long unused1, -+ void *unused2) -+{ -+#ifdef CONFIG_MAGIC_SYSRQ -+ handle_sysrq('p', ¤t->thread.regs, NULL, NULL); -+#endif -+ uml_exitcode = 1; -+ machine_halt(); -+ return(0); -+} -+ -+static struct notifier_block panic_exit_notifier = { -+ .notifier_call = panic_exit, -+ .next = NULL, -+ .priority = 0 -+}; -+ -+void __init setup_arch(char **cmdline_p) -+{ -+ notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); -+ paging_init(); -+ strcpy(command_line, saved_command_line); -+ *cmdline_p = command_line; -+ setup_hostinfo(); -+} -+ -+void __init check_bugs(void) -+{ -+ arch_check_bugs(); -+ check_ptrace(); -+ check_sigio(); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/umid.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/umid.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/umid.c 2005-05-03 22:28:14.554397608 +0300 -@@ -0,0 +1,328 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <errno.h> -+#include <string.h> -+#include <stdlib.h> -+#include <dirent.h> -+#include <signal.h> -+#include <sys/stat.h> -+#include <sys/param.h> -+#include "user.h" -+#include "umid.h" -+#include "init.h" -+#include "os.h" -+#include "user_util.h" -+#include "choose-mode.h" -+ -+#define UMID_LEN 64 -+#define UML_DIR "~/.uml/" -+ -+/* Changed by set_umid and make_umid, which are run early in boot */ -+static char umid[UMID_LEN] = { 0 }; -+ -+/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -+static char *uml_dir = UML_DIR; -+ -+/* Changed by set_umid */ -+static int umid_is_random = 1; -+static int umid_inited = 0; -+ -+static int make_umid(int (*printer)(const char *fmt, ...)); -+ -+static int __init set_umid(char *name, int is_random, -+ int (*printer)(const char *fmt, ...)) -+{ -+ if(umid_inited){ -+ (*printer)("Unique machine name can't be set twice\n"); -+ return(-1); -+ } -+ -+ if(strlen(name) > UMID_LEN - 1) -+ (*printer)("Unique machine name is being truncated to %d " -+ "characters\n", UMID_LEN); -+ strncpy(umid, name, UMID_LEN - 1); -+ umid[UMID_LEN - 1] = '\0'; -+ -+ umid_is_random = is_random; -+ umid_inited = 1; -+ return 0; -+} -+ -+static int __init set_umid_arg(char *name, int *add) -+{ -+ *add = 0; -+ return(set_umid(name, 0, printf)); -+} -+ -+__uml_setup("umid=", set_umid_arg, -+"umid=<name>\n" -+" This is used to assign a unique identity to this UML machine and\n" -+" is used for naming the pid file and management console socket.\n\n" -+); -+ -+int __init umid_file_name(char *name, char *buf, int len) -+{ -+ int n; -+ -+ if(!umid_inited && make_umid(printk)) return(-1); -+ -+ n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; -+ if(n > len){ -+ printk("umid_file_name : buffer too short\n"); -+ return(-1); -+ } -+ -+ sprintf(buf, "%s%s/%s", uml_dir, umid, name); -+ return(0); -+} -+ -+extern int tracing_pid; -+ -+static int __init create_pid_file(void) -+{ -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")]; -+ int fd, n; -+ -+ if(umid_file_name("pid", file, sizeof(file))) return 0; -+ -+ fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), -+ 0644); -+ if(fd < 0){ -+ printf("Open of machine pid file \"%s\" failed - " -+ "err = %d\n", file, -fd); -+ return 0; -+ } -+ -+ sprintf(pid, "%d\n", os_getpid()); -+ n = os_write_file(fd, pid, strlen(pid)); -+ if(n != strlen(pid)) -+ printf("Write of pid file failed - err = %d\n", -n); -+ os_close_file(fd); -+ return 0; -+} -+ -+static int actually_do_remove(char *dir) -+{ -+ DIR *directory; -+ struct dirent *ent; -+ int len; -+ char file[256]; -+ -+ directory = opendir(dir); -+ if(directory == NULL){ -+ printk("actually_do_remove : couldn't open directory '%s', " -+ "errno = %d\n", dir, errno); -+ return(1); -+ } -+ while((ent = readdir(directory)) != NULL){ -+ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) -+ continue; -+ len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; -+ if(len > sizeof(file)){ -+ printk("Not deleting '%s' from '%s' - name too long\n", -+ ent->d_name, dir); -+ continue; -+ } -+ sprintf(file, "%s/%s", dir, ent->d_name); -+ if(unlink(file) < 0){ -+ printk("actually_do_remove : couldn't remove '%s' " -+ "from '%s', errno = %d\n", ent->d_name, dir, -+ errno); -+ return(1); -+ } -+ } -+ if(rmdir(dir) < 0){ -+ printk("actually_do_remove : couldn't rmdir '%s', " -+ "errno = %d\n", dir, errno); -+ return(1); -+ } -+ return(0); -+} -+ -+void remove_umid_dir(void) -+{ -+ char dir[strlen(uml_dir) + UMID_LEN + 1]; -+ if(!umid_inited) return; -+ -+ sprintf(dir, "%s%s", uml_dir, umid); -+ actually_do_remove(dir); -+} -+ -+char *get_umid(int only_if_set) -+{ -+ if(only_if_set && umid_is_random) return(NULL); -+ return(umid); -+} -+ -+int not_dead_yet(char *dir) -+{ -+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; -+ char pid[sizeof("nnnnn\0")], *end; -+ int dead, fd, p, n; -+ -+ sprintf(file, "%s/pid", dir); -+ dead = 0; -+ fd = os_open_file(file, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ if(fd != -ENOENT){ -+ printk("not_dead_yet : couldn't open pid file '%s', " -+ "err = %d\n", file, -fd); -+ return(1); -+ } -+ dead = 1; -+ } -+ if(fd > 0){ -+ n = os_read_file(fd, pid, sizeof(pid)); -+ if(n < 0){ -+ printk("not_dead_yet : couldn't read pid file '%s', " -+ "err = %d\n", file, -n); -+ return(1); -+ } -+ p = strtoul(pid, &end, 0); -+ if(end == pid){ -+ printk("not_dead_yet : couldn't parse pid file '%s', " -+ "errno = %d\n", file, errno); -+ dead = 1; -+ } -+ if(((kill(p, 0) < 0) && (errno == ESRCH)) || -+ (p == CHOOSE_MODE(tracing_pid, os_getpid()))) -+ dead = 1; -+ } -+ if(!dead) return(1); -+ return(actually_do_remove(dir)); -+} -+ -+static int __init set_uml_dir(char *name, int *add) -+{ -+ if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ -+ uml_dir = malloc(strlen(name) + 2); -+ if(uml_dir == NULL){ -+ printf("Failed to malloc uml_dir - error = %d\n", -+ errno); -+ uml_dir = name; -+ /* Return 0 here because do_initcalls doesn't look at -+ * the return value. -+ */ -+ return(0); -+ } -+ sprintf(uml_dir, "%s/", name); -+ } -+ else uml_dir = name; -+ return(0); -+} -+ -+static int __init make_uml_dir(void) -+{ -+ char dir[MAXPATHLEN + 1] = { '\0' }; -+ int len; -+ -+ if(*uml_dir == '~'){ -+ char *home = getenv("HOME"); -+ -+ if(home == NULL){ -+ printf("make_uml_dir : no value in environment for " -+ "$HOME\n"); -+ exit(1); -+ } -+ strncpy(dir, home, sizeof(dir)); -+ uml_dir++; -+ } -+ len = strlen(dir); -+ strncat(dir, uml_dir, sizeof(dir) - len); -+ len = strlen(dir); -+ if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){ -+ dir[len] = '/'; -+ dir[len + 1] = '\0'; -+ } -+ -+ uml_dir = malloc(strlen(dir) + 1); -+ if(uml_dir == NULL){ -+ printf("make_uml_dir : malloc failed, errno = %d\n", errno); -+ exit(1); -+ } -+ strcpy(uml_dir, dir); -+ -+ if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ -+ printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno); -+ return(-1); -+ } -+ return 0; -+} -+ -+static int __init make_umid(int (*printer)(const char *fmt, ...)) -+{ -+ int fd, err; -+ char tmp[strlen(uml_dir) + UMID_LEN + 1]; -+ -+ strncpy(tmp, uml_dir, sizeof(tmp) - 1); -+ tmp[sizeof(tmp) - 1] = '\0'; -+ -+ if(!umid_inited){ -+ strcat(tmp, "XXXXXX"); -+ fd = mkstemp(tmp); -+ if(fd < 0){ -+ (*printer)("make_umid - mkstemp failed, errno = %d\n", -+ errno); -+ return(1); -+ } -+ -+ os_close_file(fd); -+ /* There's a nice tiny little race between this unlink and -+ * the mkdir below. It'd be nice if there were a mkstemp -+ * for directories. -+ */ -+ unlink(tmp); -+ set_umid(&tmp[strlen(uml_dir)], 1, printer); -+ } -+ -+ sprintf(tmp, "%s%s", uml_dir, umid); -+ -+ err = mkdir(tmp, 0777); -+ if(err < 0){ -+ if(errno == EEXIST){ -+ if(not_dead_yet(tmp)){ -+ (*printer)("umid '%s' is in use\n", umid); -+ return(-1); -+ } -+ err = mkdir(tmp, 0777); -+ } -+ } -+ if(err < 0){ -+ (*printer)("Failed to create %s - errno = %d\n", umid, errno); -+ return(-1); -+ } -+ -+ return(0); -+} -+ -+__uml_setup("uml_dir=", set_uml_dir, -+"uml_dir=<directory>\n" -+" The location to place the pid and umid files.\n\n" -+); -+ -+__uml_postsetup(make_uml_dir); -+ -+static int __init make_umid_setup(void) -+{ -+ return(make_umid(printf)); -+} -+ -+__uml_postsetup(make_umid_setup); -+__uml_postsetup(create_pid_file); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/kernel/user_syms.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/user_syms.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/user_syms.c 2005-05-03 23:38:38.888201256 +0300 -@@ -0,0 +1,85 @@ -+#include "linux/types.h" -+#include "linux/module.h" -+ -+/* XXX Deleted a number of symbols because they clashed strangely with headers -+ * Add them back later. -+ */ -+ -+#if 1 -+/* Some of this are builtin function (some are not but could in the future), -+ * so I *must* declare good prototypes for them and then EXPORT them. -+ * The kernel code uses the macro defined by include/linux/string.h, -+ * so I undef macros; the userspace code does not include that and I -+ * add an EXPORT for the glibc one.*/ -+ -+#undef strlen -+#undef memcpy -+#undef memset -+ -+//extern size_t strlen(const char *); -+extern void *memcpy(void *, const void *, size_t); -+extern void *memset(void *, int, size_t); -+//extern int printf(const char *, ...); -+ -+//EXPORT_SYMBOL(strlen); -+EXPORT_SYMBOL(memset); -+EXPORT_SYMBOL(memcpy); -+#undef strstr -+ -+EXPORT_SYMBOL(strstr); -+ -+#endif -+ -+/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. -+ * However, the modules will use the CRC defined *here*, no matter if it is -+ * good; so the versions of these symbols will always match -+ */ -+#define EXPORT_SYMBOL_PROTO(sym) \ -+ int sym(void); \ -+ EXPORT_SYMBOL(sym); -+ -+EXPORT_SYMBOL_PROTO(__errno_location); -+ -+EXPORT_SYMBOL_PROTO(access); -+EXPORT_SYMBOL_PROTO(open); -+EXPORT_SYMBOL_PROTO(open64); -+EXPORT_SYMBOL_PROTO(close); -+EXPORT_SYMBOL_PROTO(read); -+EXPORT_SYMBOL_PROTO(write); -+EXPORT_SYMBOL_PROTO(dup2); -+EXPORT_SYMBOL_PROTO(__xstat); -+EXPORT_SYMBOL_PROTO(__lxstat); -+EXPORT_SYMBOL_PROTO(__lxstat64); -+EXPORT_SYMBOL_PROTO(lseek); -+EXPORT_SYMBOL_PROTO(lseek64); -+EXPORT_SYMBOL_PROTO(chown); -+EXPORT_SYMBOL_PROTO(truncate); -+EXPORT_SYMBOL_PROTO(utime); -+EXPORT_SYMBOL_PROTO(chmod); -+EXPORT_SYMBOL_PROTO(rename); -+EXPORT_SYMBOL_PROTO(__xmknod); -+ -+EXPORT_SYMBOL_PROTO(symlink); -+EXPORT_SYMBOL_PROTO(link); -+EXPORT_SYMBOL_PROTO(unlink); -+EXPORT_SYMBOL_PROTO(readlink); -+ -+EXPORT_SYMBOL_PROTO(mkdir); -+EXPORT_SYMBOL_PROTO(rmdir); -+EXPORT_SYMBOL_PROTO(opendir); -+EXPORT_SYMBOL_PROTO(readdir); -+EXPORT_SYMBOL_PROTO(closedir); -+EXPORT_SYMBOL_PROTO(seekdir); -+EXPORT_SYMBOL_PROTO(telldir); -+ -+EXPORT_SYMBOL_PROTO(ioctl); -+ -+EXPORT_SYMBOL_PROTO(pread64); -+EXPORT_SYMBOL_PROTO(pwrite64); -+ -+EXPORT_SYMBOL_PROTO(statfs); -+EXPORT_SYMBOL_PROTO(statfs64); -+ -+EXPORT_SYMBOL_PROTO(getuid); -+ -+EXPORT_SYMBOL_PROTO(printf); -Index: linux-2.4.29/arch/um/kernel/user_util.c -=================================================================== ---- linux-2.4.29.orig/arch/um/kernel/user_util.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/kernel/user_util.c 2005-05-03 22:28:14.556397304 +0300 -@@ -0,0 +1,188 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <limits.h> -+#include <setjmp.h> -+#include <sys/mman.h> -+#include <sys/stat.h> -+#include <sys/ptrace.h> -+#include <sys/utsname.h> -+#include <sys/param.h> -+#include <sys/time.h> -+#include "asm/types.h" -+#include <ctype.h> -+#include <signal.h> -+#include <wait.h> -+#include <errno.h> -+#include <stdarg.h> -+#include <sched.h> -+#include <termios.h> -+#include <string.h> -+#include "user_util.h" -+#include "kern_util.h" -+#include "user.h" -+#include "mem_user.h" -+#include "init.h" -+#include "helper.h" -+#include "uml-config.h" -+ -+#define COMMAND_LINE_SIZE _POSIX_ARG_MAX -+ -+/* Changed in linux_main and setup_arch, which run before SMP is started */ -+char saved_command_line[COMMAND_LINE_SIZE] = { 0 }; -+char command_line[COMMAND_LINE_SIZE] = { 0 }; -+ -+void add_arg(char *cmd_line, char *arg) -+{ -+ if (strlen(cmd_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { -+ printf("add_arg: Too much command line!\n"); -+ exit(1); -+ } -+ if(strlen(cmd_line) > 0) strcat(cmd_line, " "); -+ strcat(cmd_line, arg); -+} -+ -+void stop(void) -+{ -+ while(1) sleep(1000000); -+} -+ -+void stack_protections(unsigned long address) -+{ -+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC; -+ -+ if(mprotect((void *) address, page_size(), prot) < 0) -+ panic("protecting stack failed, errno = %d", errno); -+} -+ -+void task_protections(unsigned long address) -+{ -+ unsigned long guard = address + page_size(); -+ unsigned long stack = guard + page_size(); -+ int prot = 0, pages; -+#ifdef notdef -+ if(mprotect((void *) guard, page_size(), prot) < 0) -+ panic("protecting guard page failed, errno = %d", errno); -+#endif -+ pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; -+ prot = PROT_READ | PROT_WRITE | PROT_EXEC; -+ if(mprotect((void *) stack, pages * page_size(), prot) < 0) -+ panic("protecting stack failed, errno = %d", errno); -+} -+ -+int wait_for_stop(int pid, int sig, int cont_type, void *relay) -+{ -+ sigset_t *relay_signals = relay; -+ int status, ret; -+ -+ while(1){ -+ CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); -+ if((ret < 0) || -+ !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ -+ if(ret < 0){ -+ printk("wait failed, errno = %d\n", -+ errno); -+ } -+ else if(WIFEXITED(status)) -+ printk("process %d exited with status %d\n", -+ pid, WEXITSTATUS(status)); -+ else if(WIFSIGNALED(status)) -+ printk("process %d exited with signal %d\n", -+ pid, WTERMSIG(status)); -+ else if((WSTOPSIG(status) == SIGVTALRM) || -+ (WSTOPSIG(status) == SIGALRM) || -+ (WSTOPSIG(status) == SIGIO) || -+ (WSTOPSIG(status) == SIGPROF) || -+ (WSTOPSIG(status) == SIGCHLD) || -+ (WSTOPSIG(status) == SIGWINCH) || -+ (WSTOPSIG(status) == SIGINT)){ -+ ptrace(cont_type, pid, 0, WSTOPSIG(status)); -+ continue; -+ } -+ else if((relay_signals != NULL) && -+ sigismember(relay_signals, WSTOPSIG(status))){ -+ ptrace(cont_type, pid, 0, WSTOPSIG(status)); -+ continue; -+ } -+ else printk("process %d stopped with signal %d\n", -+ pid, WSTOPSIG(status)); -+ panic("wait_for_stop failed to wait for %d to stop " -+ "with %d\n", pid, sig); -+ } -+ return(status); -+ } -+} -+ -+int raw(int fd) -+{ -+ struct termios tt; -+ int err; -+ -+ CATCH_EINTR(err = tcgetattr(fd, &tt)); -+ if (err < 0) { -+ printk("tcgetattr failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ cfmakeraw(&tt); -+ -+ CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); -+ if (err < 0) { -+ printk("tcsetattr failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ /* XXX tcsetattr could have applied only some changes -+ * (and cfmakeraw() is a set of changes) */ -+ return(0); -+} -+ -+void setup_machinename(char *machine_out) -+{ -+ struct utsname host; -+ -+ uname(&host); -+ strcpy(machine_out, host.machine); -+} -+ -+char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; -+ -+void setup_hostinfo(void) -+{ -+ struct utsname host; -+ -+ uname(&host); -+ sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, -+ host.release, host.version, host.machine); -+} -+ -+int setjmp_wrapper(void (*proc)(void *, void *), ...) -+{ -+ va_list args; -+ sigjmp_buf buf; -+ int n; -+ -+ n = sigsetjmp(buf, 1); -+ if(n == 0){ -+ va_start(args, proc); -+ (*proc)(&buf, &args); -+ } -+ va_end(args); -+ return(n); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,191 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+OS := $(shell uname -s) -+ -+ARCH_DIR = arch/um -+ -+core-y := kernel sys-$(SUBARCH) os-$(OS) -+drivers-y := fs drivers -+subdir-y := $(core-y) $(drivers-y) -+SUBDIRS += $(foreach dir,$(subdir-y),$(ARCH_DIR)/$(dir)) -+ -+CORE_FILES += $(foreach dir,$(core-y),$(ARCH_DIR)/$(dir)/built-in.o) -+DRIVERS += $(foreach dir,$(drivers-y),$(ARCH_DIR)/$(dir)/built-in.o) -+ -+include $(ARCH_DIR)/Makefile-$(SUBARCH) -+include $(ARCH_DIR)/Makefile-os-$(OS) -+ -+MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt -+MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas -+ -+ifneq ($(MAKEFILE-y),) -+ include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y)) -+endif -+ -+EXTRAVERSION := $(EXTRAVERSION)-1um -+ -+include/linux/version.h: arch/$(ARCH)/Makefile -+ -+# We require bash because the vmlinux link and loader script cpp use bash -+# features. -+SHELL := /bin/bash -+ -+# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE) -+# The way the toplevel Makefile is written EXTRAVERSION is not supposed -+# to be changed outside the toplevel Makefile, but recalculating MODLIB is -+# a sufficient workaround until we no longer need architecture dependent -+# EXTRAVERSION... -+MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) -+ -+ifeq ($(CONFIG_DEBUGSYM),y) -+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -+endif -+ -+CFLAGS-$(CONFIG_DEBUGSYM) += -g -+ -+ARCH_INCLUDE = -I$(TOPDIR)/$(ARCH_DIR)/include -+ -+# -Derrno=kernel_errno - This turns all kernel references to errno into -+# kernel_errno to separate them from the libc errno. This allows -fno-common -+# in CFLAGS. Otherwise, it would cause ld to complain about the two different -+# errnos. -+ -+CFLAGS += $(ARCH_CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ -+ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \ -+ $(MODE_INCLUDE) -+ -+check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) -+ -+CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) -+ -+LINKFLAGS += -r -+ -+LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc -+ -+# These are needed for clean and mrproper, since in that case .config is not -+# included; the values here are meaningless -+ -+CONFIG_NEST_LEVEL ?= 0 -+CONFIG_KERNEL_HALF_GIGS ?= 0 -+ -+SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) -+ -+# These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT + -+# CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case. -+ -+LINK_TT = -static -+LD_SCRIPT_TT := link.ld -+ -+ifeq ($(CONFIG_STATIC_LINK),y) -+ LINK-y += $(LINK_TT) -+ LD_SCRIPT-y := $(LD_SCRIPT_TT) -+else -+ifeq ($(CONFIG_MODE_TT),y) -+ LINK-y += $(LINK_TT) -+ LD_SCRIPT-y := $(LD_SCRIPT_TT) -+else -+ifeq ($(CONFIG_MODE_SKAS),y) -+ LINK-y += $(LINK_SKAS) -+ LD_SCRIPT-y := $(LD_SCRIPT_SKAS) -+endif -+endif -+endif -+ -+LD_SCRIPT-y := $(ARCH_DIR)/kernel/$(LD_SCRIPT-y) -+M4_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT) -+ -+ifndef START -+ START = $$(($(TOP_ADDR) - $(SIZE))) -+endif -+ -+$(LD_SCRIPT-y): $(LD_SCRIPT-y).in -+ pages=$$(( 1 << $(CONFIG_KERNEL_STACK_ORDER) )) ; \ -+ m4 -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \ -+ -DELF_FORMAT=$(ELF_FORMAT) $(M4_MODE_TT) \ -+ -DKERNEL_STACK_SIZE=$$(( 4096 * $$pages )) $< > $@ -+ -+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ -+ arch-signal.h -+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) -+ -+ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \ -+ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h -+ -+ifeq ($(CONFIG_MODE_SKAS), y) -+$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h -+endif -+ -+GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h -+ -+setup: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) -+ -+linux: setup vmlinux $(LD_SCRIPT-y) -+ mv vmlinux vmlinux.o -+ $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \ -+ -o linux vmlinux.o -L/usr/lib -lutil -+ -+USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) -+USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS)) -+USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ -+ $(MODE_INCLUDE) -+ -+# To get a definition of F_SETSIG -+USER_CFLAGS += -D_GNU_SOURCE -+ -+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/link.ld $(ARCH_DIR)/dyn_link.ld \ -+ $(GEN_HEADERS) -+# $(ARCH_DIR)/include/uml-config.h removed temporarily because this causes -+# make to fail after make clean -+ -+archmrproper: -+ rm -f $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \ -+ $(LD_SCRIPT) $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) -+ -+archclean: sysclean -+ find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -+ -o -name '*.gcov' \) -type f -print | xargs rm -f -+ cd $(ARCH_DIR) ; \ -+ for dir in $(subdir-y) util ; do $(MAKE) -C $$dir clean; done -+ -+archdep: -+ -+$(SYMLINK_HEADERS): -+ cd $(TOPDIR)/$(dir $@) ; \ -+ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) -+ -+include/asm-um/arch: -+ cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch -+ -+arch/um/include/sysdep: -+ cd $(TOPDIR)/arch/um/include && ln -sf sysdep-$(SUBARCH) sysdep -+ -+arch/um/os: -+ cd $(ARCH_DIR) && ln -sf os-$(OS) os -+ -+$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task -+ $< > $@ -+ -+$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants -+ $< > $@ -+ -+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h -+ sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@ -+ -+$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/util/mk_task_user.c \ -+ $(ARCH_DIR)/util/mk_task_kern.c $(SYS_HEADERS) -+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_task -+ -+$(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util/mk_constants_user.c \ -+ $(ARCH_DIR)/util/mk_constants_kern.c -+ $(MAKE) $(MFLAGS) -C $(ARCH_DIR)/util mk_constants -+ -+export SUBARCH USER_CFLAGS OS -+ -+all: linux -+ -+define archhelp -+ echo '* linux - Binary kernel image (./linux)' -+endef -Index: linux-2.4.29/arch/um/Makefile-i386 -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile-i386 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile-i386 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,46 @@ -+ifeq ($(CONFIG_HOST_2G_2G),y) -+TOP_ADDR = 0x80000000 -+else -+TOP_ADDR = 0xc0000000 -+endif -+ -+ifeq ($(CONFIG_MODE_SKAS),y) -+ ifneq ($(CONFIG_MODE_TT),y) -+ START = 0x8048000 -+ endif -+endif -+ -+ARCH_CFLAGS = -U__$(SUBARCH)__ -U$(SUBARCH) -+ -+ifneq ($(CONFIG_GPROF),y) -+ARCH_CFLAGS += -DUM_FASTCALL -+endif -+ -+ELF_ARCH = $(SUBARCH) -+ELF_FORMAT = elf32-$(SUBARCH) -+ -+I386_H = $(ARCH_DIR)/include/sysdep-i386 -+SYS = $(ARCH_DIR)/sys-i386 -+UTIL = $(SYS)/util -+SUBDIRS += $(UTIL) -+ -+SYS_HEADERS = $(I386_H)/sc.h $(I386_H)/thread.h -+ -+$(I386_H)/sc.h : $(UTIL)/mk_sc -+ $(UTIL)/mk_sc > $@ -+ -+$(I386_H)/thread.h : $(UTIL)/mk_thread -+ $(UTIL)/mk_thread > $@ -+ -+$(UTIL)/mk_sc : $(UTIL)/mk_sc.c -+ $(MAKE) -C $(UTIL) mk_sc -+ -+$(UTIL)/mk_thread : $(UTIL)/mk_thread_user.c $(UTIL)/mk_thread_kern.c \ -+ $(I386_H)/sc.h -+ $(MAKE) -C $(UTIL) mk_thread -+ -+sysclean : -+ rm -f $(SYS_HEADERS) -+ $(MAKE) -C $(UTIL) clean -+ $(MAKE) -C $(SYS) clean -+ -Index: linux-2.4.29/arch/um/Makefile-ia64 -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile-ia64 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile-ia64 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1 @@ -+START_ADDR = 0x1000000000000000 -Index: linux-2.4.29/arch/um/Makefile-os-Linux -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile-os-Linux 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile-os-Linux 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,7 @@ -+# -+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+SUBDIRS += $(ARCH_DIR)/os-$(OS)/drivers -+DRIVERS += $(ARCH_DIR)/os-$(OS)/drivers/drivers.o -Index: linux-2.4.29/arch/um/Makefile-ppc -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile-ppc 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile-ppc 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,9 @@ -+ifeq ($(CONFIG_HOST_2G_2G), y) -+START_ADDR = 0x80000000 -+else -+START_ADDR = 0xc0000000 -+endif -+ARCH_CFLAGS = -U__powerpc__ -D__UM_PPC__ -+ -+# The arch is ppc, but the elf32 name is powerpc -+ELF_SUBARCH = powerpc -Index: linux-2.4.29/arch/um/Makefile-skas -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile-skas 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile-skas 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,20 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+PROFILE += -pg -+ -+CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage -+CFLAGS-$(CONFIG_GPROF) += $(PROFILE) -+LINK-$(CONFIG_GPROF) += $(PROFILE) -+ -+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include -+ -+LINK_SKAS = -Wl,-rpath,/lib -+LD_SCRIPT_SKAS = dyn_link.ld -+ -+GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h -+ -+$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h : -+ $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h -Index: linux-2.4.29/arch/um/Makefile-tt -=================================================================== ---- linux-2.4.29.orig/arch/um/Makefile-tt 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/Makefile-tt 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,7 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include -+ -Index: linux-2.4.29/arch/um/os-Linux/aio.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/aio.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/aio.c 2005-05-03 22:28:14.563396240 +0300 -@@ -0,0 +1,404 @@ -+/* -+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <unistd.h> -+#include <signal.h> -+#include <errno.h> -+#include <sched.h> -+#include <sys/syscall.h> -+#include "os.h" -+#include "helper.h" -+#include "aio.h" -+#include "init.h" -+#include "user.h" -+#include "mode.h" -+ -+struct aio_thread_req { -+ enum aio_type type; -+ int io_fd; -+ unsigned long long offset; -+ char *buf; -+ int len; -+ int reply_fd; -+ void *data; -+}; -+ -+static int aio_req_fd_r = -1; -+static int aio_req_fd_w = -1; -+ -+#if defined(HAVE_AIO_ABI) -+#include <linux/aio_abi.h> -+ -+/* If we have the headers, we are going to build with AIO enabled. -+ * If we don't have aio in libc, we define the necessary stubs here. -+ */ -+ -+#if !defined(HAVE_AIO_LIBC) -+ -+#define __NR_io_setup 245 -+#define __NR_io_getevents 247 -+#define __NR_io_submit 248 -+ -+static long io_setup(int n, aio_context_t *ctxp) -+{ -+ return(syscall(__NR_io_setup, n, ctxp)); -+} -+ -+static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) -+{ -+ return(syscall(__NR_io_submit, ctx, nr, iocbpp)); -+} -+ -+static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, -+ struct io_event *events, struct timespec *timeout) -+{ -+ return(syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout)); -+} -+ -+#endif -+ -+/* The AIO_MMAP cases force the mmapped page into memory here -+ * rather than in whatever place first touches the data. I used -+ * to do this by touching the page, but that's delicate because -+ * gcc is prone to optimizing that away. So, what's done here -+ * is we read from the descriptor from which the page was -+ * mapped. The caller is required to pass an offset which is -+ * inside the page that was mapped. Thus, when the read -+ * returns, we know that the page is in the page cache, and -+ * that it now backs the mmapped area. -+ */ -+ -+static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, -+ int len, unsigned long long offset, void *data) -+{ -+ struct iocb iocb, *iocbp = &iocb; -+ char c; -+ int err; -+ -+ iocb = ((struct iocb) { .aio_data = (unsigned long) data, -+ .aio_reqprio = 0, -+ .aio_fildes = fd, -+ .aio_buf = (unsigned long) buf, -+ .aio_nbytes = len, -+ .aio_offset = offset, -+ .aio_reserved1 = 0, -+ .aio_reserved2 = 0, -+ .aio_reserved3 = 0 }); -+ -+ switch(type){ -+ case AIO_READ: -+ iocb.aio_lio_opcode = IOCB_CMD_PREAD; -+ err = io_submit(ctx, 1, &iocbp); -+ break; -+ case AIO_WRITE: -+ iocb.aio_lio_opcode = IOCB_CMD_PWRITE; -+ err = io_submit(ctx, 1, &iocbp); -+ break; -+ case AIO_MMAP: -+ iocb.aio_lio_opcode = IOCB_CMD_PREAD; -+ iocb.aio_buf = (unsigned long) &c; -+ iocb.aio_nbytes = sizeof(c); -+ err = io_submit(ctx, 1, &iocbp); -+ break; -+ default: -+ printk("Bogus op in do_aio - %d\n", type); -+ err = -EINVAL; -+ break; -+ } -+ if(err > 0) -+ err = 0; -+ -+ return(err); -+} -+ -+static aio_context_t ctx = 0; -+ -+static int aio_thread(void *arg) -+{ -+ struct aio_thread_reply reply; -+ struct io_event event; -+ int err, n, reply_fd; -+ -+ signal(SIGWINCH, SIG_IGN); -+ -+ while(1){ -+ n = io_getevents(ctx, 1, 1, &event, NULL); -+ if(n < 0){ -+ if(errno == EINTR) -+ continue; -+ printk("aio_thread - io_getevents failed, " -+ "errno = %d\n", errno); -+ } -+ else { -+ reply = ((struct aio_thread_reply) -+ { .data = (void *) event.data, -+ .err = event.res }); -+ reply_fd = -+ ((struct aio_context *) event.data)->reply_fd; -+ err = os_write_file(reply_fd, &reply, sizeof(reply)); -+ if(err != sizeof(reply)) -+ printk("not_aio_thread - write failed, " -+ "fd = %d, err = %d\n", -+ aio_req_fd_r, -err); -+ } -+ } -+ return(0); -+} -+ -+#endif -+ -+static int do_not_aio(struct aio_thread_req *req) -+{ -+ char c; -+ int err; -+ -+ switch(req->type){ -+ case AIO_READ: -+ err = os_seek_file(req->io_fd, req->offset); -+ if(err) -+ goto out; -+ -+ err = os_read_file(req->io_fd, req->buf, req->len); -+ break; -+ case AIO_WRITE: -+ err = os_seek_file(req->io_fd, req->offset); -+ if(err) -+ goto out; -+ -+ err = os_write_file(req->io_fd, req->buf, req->len); -+ break; -+ case AIO_MMAP: -+ err = os_seek_file(req->io_fd, req->offset); -+ if(err) -+ goto out; -+ -+ err = os_read_file(req->io_fd, &c, sizeof(c)); -+ break; -+ default: -+ printk("do_not_aio - bad request type : %d\n", req->type); -+ err = -EINVAL; -+ break; -+ } -+ -+ out: -+ return(err); -+} -+ -+static int not_aio_thread(void *arg) -+{ -+ struct aio_thread_req req; -+ struct aio_thread_reply reply; -+ int err; -+ -+ signal(SIGWINCH, SIG_IGN); -+ while(1){ -+ err = os_read_file(aio_req_fd_r, &req, sizeof(req)); -+ if(err != sizeof(req)){ -+ if(err < 0) -+ printk("not_aio_thread - read failed, fd = %d, " -+ "err = %d\n", aio_req_fd_r, -err); -+ else { -+ printk("not_aio_thread - short read, fd = %d, " -+ "length = %d\n", aio_req_fd_r, err); -+ } -+ continue; -+ } -+ err = do_not_aio(&req); -+ reply = ((struct aio_thread_reply) { .data = req.data, -+ .err = err }); -+ err = os_write_file(req.reply_fd, &reply, sizeof(reply)); -+ if(err != sizeof(reply)) -+ printk("not_aio_thread - write failed, fd = %d, " -+ "err = %d\n", aio_req_fd_r, -err); -+ } -+} -+ -+static int aio_pid = -1; -+ -+static int init_aio_24(void) -+{ -+ unsigned long stack; -+ int fds[2], err; -+ -+ err = os_pipe(fds, 1, 1); -+ if(err) -+ goto out; -+ -+ aio_req_fd_w = fds[0]; -+ aio_req_fd_r = fds[1]; -+ err = run_helper_thread(not_aio_thread, NULL, -+ CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); -+ if(err < 0) -+ goto out_close_pipe; -+ -+ aio_pid = err; -+ goto out; -+ -+ out_close_pipe: -+ os_close_file(fds[0]); -+ os_close_file(fds[1]); -+ aio_req_fd_w = -1; -+ aio_req_fd_r = -1; -+ out: -+ return(0); -+} -+ -+#ifdef HAVE_AIO_ABI -+#define DEFAULT_24_AIO 0 -+static int init_aio_26(void) -+{ -+ unsigned long stack; -+ int err; -+ -+ if(io_setup(256, &ctx)){ -+ printk("aio_thread failed to initialize context, err = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ err = run_helper_thread(aio_thread, NULL, -+ CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); -+ if(err < 0) -+ return(-errno); -+ -+ aio_pid = err; -+ err = 0; -+ out: -+ return(err); -+} -+ -+int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, -+ unsigned long long offset, int reply_fd, void *data) -+{ -+ struct aio_thread_reply reply; -+ int err; -+ -+ ((struct aio_context *) data)->reply_fd = reply_fd; -+ -+ err = do_aio(ctx, type, io_fd, buf, len, offset, data); -+ if(err){ -+ reply = ((struct aio_thread_reply) { .data = data, -+ .err = err }); -+ err = os_write_file(reply_fd, &reply, sizeof(reply)); -+ if(err != sizeof(reply)) -+ printk("submit_aio_26 - write failed, " -+ "fd = %d, err = %d\n", reply_fd, -err); -+ else err = 0; -+ } -+ -+ return(err); -+} -+ -+#else -+#define DEFAULT_24_AIO 1 -+static int init_aio_26(void) -+{ -+ return(-ENOSYS); -+} -+ -+int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, -+ unsigned long long offset, int reply_fd, void *data) -+{ -+ return(-ENOSYS); -+} -+#endif -+ -+static int aio_24 = DEFAULT_24_AIO; -+ -+static int __init set_aio_24(char *name, int *add) -+{ -+ aio_24 = 1; -+ return(0); -+} -+ -+__uml_setup("aio=2.4", set_aio_24, -+"aio=2.4\n" -+" This is used to force UML to use 2.4-style AIO even when 2.6 AIO is\n" -+" available. 2.4 AIO is a single thread that handles one request at a\n" -+" time, synchronously. 2.6 AIO is a thread which uses 2.5 AIO interface\n" -+" to handle an arbitrary number of pending requests. 2.6 AIO is not\n" -+" available in tt mode, on 2.4 hosts, or when UML is built with\n" -+" /usr/include/linux/aio_abi no available.\n\n" -+); -+ -+static int init_aio(void) -+{ -+ int err; -+ -+ CHOOSE_MODE(({ -+ if(!aio_24){ -+ printk("Disabling 2.6 AIO in tt mode\n"); -+ aio_24 = 1; -+ } }), (void) 0); -+ -+ if(!aio_24){ -+ err = init_aio_26(); -+ if(err && (errno == ENOSYS)){ -+ printk("2.6 AIO not supported on the host - " -+ "reverting to 2.4 AIO\n"); -+ aio_24 = 1; -+ } -+ else return(err); -+ } -+ -+ if(aio_24) -+ return(init_aio_24()); -+ -+ return(0); -+} -+ -+__initcall(init_aio); -+ -+static void exit_aio(void) -+{ -+ if(aio_pid != -1) -+ os_kill_process(aio_pid, 1); -+} -+ -+__uml_exitcall(exit_aio); -+ -+int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, -+ unsigned long long offset, int reply_fd, void *data) -+{ -+ struct aio_thread_req req = { .type = type, -+ .io_fd = io_fd, -+ .offset = offset, -+ .buf = buf, -+ .len = len, -+ .reply_fd = reply_fd, -+ .data = data, -+ }; -+ int err; -+ -+ err = os_write_file(aio_req_fd_w, &req, sizeof(req)); -+ if(err == sizeof(req)) -+ err = 0; -+ -+ return(err); -+} -+ -+int submit_aio(enum aio_type type, int io_fd, char *buf, int len, -+ unsigned long long offset, int reply_fd, void *data) -+{ -+ if(aio_24) -+ return(submit_aio_24(type, io_fd, buf, len, offset, reply_fd, -+ data)); -+ else { -+ return(submit_aio_26(type, io_fd, buf, len, offset, reply_fd, -+ data)); -+ } -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/drivers/etap.h -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/etap.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/etap.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "net_user.h" -+ -+struct ethertap_data { -+ char *dev_name; -+ char *gate_addr; -+ int data_fd; -+ int control_fd; -+ void *dev; -+}; -+ -+extern struct net_user_info ethertap_user_info; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/drivers/ethertap_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/ethertap_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/ethertap_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,121 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include "linux/init.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "etap.h" -+ -+struct ethertap_init { -+ char *dev_name; -+ char *gate_addr; -+}; -+ -+static void etap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct ethertap_data *epri; -+ struct ethertap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ epri = (struct ethertap_data *) pri->user; -+ *epri = ((struct ethertap_data) -+ { .dev_name = init->dev_name, -+ .gate_addr = init->gate_addr, -+ .data_fd = -1, -+ .control_fd = -1, -+ .dev = dev }); -+ -+ printk("ethertap backend - %s", epri->dev_name); -+ if(epri->gate_addr != NULL) -+ printk(", IP = %s", epri->gate_addr); -+ printk("\n"); -+} -+ -+static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ int len; -+ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); -+ if(*skb == NULL) return(-ENOMEM); -+ len = net_recvfrom(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); -+ if(len <= 0) return(len); -+ skb_pull(*skb, 2); -+ len -= 2; -+ return(len); -+} -+ -+static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) -+{ -+ if(skb_headroom(*skb) < 2){ -+ struct sk_buff *skb2; -+ -+ skb2 = skb_realloc_headroom(*skb, 2); -+ dev_kfree_skb(*skb); -+ if (skb2 == NULL) return(-ENOMEM); -+ *skb = skb2; -+ } -+ skb_push(*skb, 2); -+ return(net_send(fd, (*skb)->data, (*skb)->len)); -+} -+ -+struct net_kern_info ethertap_kern_info = { -+ .init = etap_init, -+ .protocol = eth_protocol, -+ .read = etap_read, -+ .write = etap_write, -+}; -+ -+int ethertap_setup(char *str, char **mac_out, void *data) -+{ -+ struct ethertap_init *init = data; -+ -+ *init = ((struct ethertap_init) -+ { .dev_name = NULL, -+ .gate_addr = NULL }); -+ if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, -+ &init->gate_addr)) -+ return(0); -+ if(init->dev_name == NULL){ -+ printk("ethertap_setup : Missing tap device name\n"); -+ return(0); -+ } -+ -+ return(1); -+} -+ -+static struct transport ethertap_transport = { -+ .list = LIST_HEAD_INIT(ethertap_transport.list), -+ .name = "ethertap", -+ .setup = ethertap_setup, -+ .user = ðertap_user_info, -+ .kern = ðertap_kern_info, -+ .private_size = sizeof(struct ethertap_data), -+}; -+ -+static int register_ethertap(void) -+{ -+ register_transport(ðertap_transport); -+ return(1); -+} -+ -+__initcall(register_ethertap); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/drivers/ethertap_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/ethertap_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/ethertap_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,240 @@ -+/* -+ * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and -+ * James Leu (jleu@mindspring.net). -+ * Copyright (C) 2001 by various other people who didn't put their name here. -+ * Licensed under the GPL. -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <stddef.h> -+#include <stdlib.h> -+#include <sys/errno.h> -+#include <sys/socket.h> -+#include <sys/wait.h> -+#include <sys/un.h> -+#include <net/if.h> -+#include "user.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "net_user.h" -+#include "etap.h" -+#include "helper.h" -+#include "os.h" -+ -+#define MAX_PACKET ETH_MAX_PACKET -+ -+void etap_user_init(void *data, void *dev) -+{ -+ struct ethertap_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+struct addr_change { -+ enum { ADD_ADDR, DEL_ADDR } what; -+ unsigned char addr[4]; -+ unsigned char netmask[4]; -+}; -+ -+static void etap_change(int op, unsigned char *addr, unsigned char *netmask, -+ int fd) -+{ -+ struct addr_change change; -+ void *output; -+ int n; -+ -+ change.what = op; -+ memcpy(change.addr, addr, sizeof(change.addr)); -+ memcpy(change.netmask, netmask, sizeof(change.netmask)); -+ n = os_write_file(fd, &change, sizeof(change)); -+ if(n != sizeof(change)) -+ printk("etap_change - request failed, err = %d\n", -n); -+ output = um_kmalloc(page_size()); -+ if(output == NULL) -+ printk("etap_change : Failed to allocate output buffer\n"); -+ read_output(fd, output, page_size()); -+ if(output != NULL){ -+ printk("%s", output); -+ kfree(output); -+ } -+} -+ -+static void etap_open_addr(unsigned char *addr, unsigned char *netmask, -+ void *arg) -+{ -+ etap_change(ADD_ADDR, addr, netmask, *((int *) arg)); -+} -+ -+static void etap_close_addr(unsigned char *addr, unsigned char *netmask, -+ void *arg) -+{ -+ etap_change(DEL_ADDR, addr, netmask, *((int *) arg)); -+} -+ -+struct etap_pre_exec_data { -+ int control_remote; -+ int control_me; -+ int data_me; -+}; -+ -+static void etap_pre_exec(void *arg) -+{ -+ struct etap_pre_exec_data *data = arg; -+ -+ dup2(data->control_remote, 1); -+ os_close_file(data->data_me); -+ os_close_file(data->control_me); -+} -+ -+static int etap_tramp(char *dev, char *gate, int control_me, -+ int control_remote, int data_me, int data_remote) -+{ -+ struct etap_pre_exec_data pe_data; -+ int pid, status, err, n; -+ char version_buf[sizeof("nnnnn\0")]; -+ char data_fd_buf[sizeof("nnnnnn\0")]; -+ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; -+ char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, -+ data_fd_buf, gate_buf, NULL }; -+ char *nosetup_args[] = { "uml_net", version_buf, "ethertap", -+ dev, data_fd_buf, NULL }; -+ char **args, c; -+ -+ sprintf(data_fd_buf, "%d", data_remote); -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ if(gate != NULL){ -+ strcpy(gate_buf, gate); -+ args = setup_args; -+ } -+ else args = nosetup_args; -+ -+ err = 0; -+ pe_data.control_remote = control_remote; -+ pe_data.control_me = control_me; -+ pe_data.data_me = data_me; -+ pid = run_helper(etap_pre_exec, &pe_data, args, NULL); -+ -+ if(pid < 0) err = pid; -+ os_close_file(data_remote); -+ os_close_file(control_remote); -+ n = os_read_file(control_me, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("etap_tramp : read of status failed, err = %d\n", -n); -+ return(-EINVAL); -+ } -+ if(c != 1){ -+ printk("etap_tramp : uml_net failed\n"); -+ err = -EINVAL; -+ CATCH_EINTR(n = waitpid(pid, &status, 0)); -+ if(n < 0) -+ err = -errno; -+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) -+ printk("uml_net didn't exit with status 1\n"); -+ } -+ return(err); -+} -+ -+static int etap_open(void *data) -+{ -+ struct ethertap_data *pri = data; -+ char *output; -+ int data_fds[2], control_fds[2], err, output_len; -+ -+ err = tap_open_common(pri->dev, pri->gate_addr); -+ if(err) return(err); -+ -+ err = os_pipe(data_fds, 0, 0); -+ if(err < 0){ -+ printk("data os_pipe failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ err = os_pipe(control_fds, 1, 0); -+ if(err < 0){ -+ printk("control os_pipe failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], -+ control_fds[1], data_fds[0], data_fds[1]); -+ output_len = page_size(); -+ output = um_kmalloc(output_len); -+ read_output(control_fds[0], output, output_len); -+ -+ if(output == NULL) -+ printk("etap_open : failed to allocate output buffer\n"); -+ else { -+ printk("%s", output); -+ kfree(output); -+ } -+ -+ if(err < 0){ -+ printk("etap_tramp failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ pri->data_fd = data_fds[0]; -+ pri->control_fd = control_fds[0]; -+ iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); -+ return(data_fds[0]); -+} -+ -+static void etap_close(int fd, void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); -+ os_close_file(fd); -+ os_shutdown_socket(pri->data_fd, 1, 1); -+ os_close_file(pri->data_fd); -+ pri->data_fd = -1; -+ os_close_file(pri->control_fd); -+ pri->control_fd = -1; -+} -+ -+static int etap_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+static void etap_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ tap_check_ips(pri->gate_addr, addr); -+ if(pri->control_fd == -1) return; -+ etap_open_addr(addr, netmask, &pri->control_fd); -+} -+ -+static void etap_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct ethertap_data *pri = data; -+ -+ if(pri->control_fd == -1) return; -+ etap_close_addr(addr, netmask, &pri->control_fd); -+} -+ -+struct net_user_info ethertap_user_info = { -+ .init = etap_user_init, -+ .open = etap_open, -+ .close = etap_close, -+ .remove = NULL, -+ .set_mtu = etap_set_mtu, -+ .add_address = etap_add_addr, -+ .delete_address = etap_del_addr, -+ .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/drivers/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/Makefile 2005-05-03 22:28:14.568395480 +0300 -@@ -0,0 +1,31 @@ -+# -+# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET := drivers.o -+ -+list-multi := tuntap.o ethertap.o -+ -+ethertap-objs := ethertap_kern.o ethertap_user.o -+tuntap-objs := tuntap_kern.o tuntap_user.o -+ -+obj-y = -+obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o -+obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o -+ -+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y)),$($(f)-objs)) -+ -+USER_OBJS = $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS)) -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+ethertap.o : $(ethertap-objs) -+ -+tuntap.o : $(tuntap-objs) -+ -+$(list-multi) : # This doesn't work, but should : '%.o : $(%-objs)' -+ $(LD) $(LD_RFLAG) -r -o $@ $($(patsubst %.o,%,$@)-objs) -Index: linux-2.4.29/arch/um/os-Linux/drivers/tuntap.h -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/tuntap.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/tuntap.h 2005-05-03 22:28:14.568395480 +0300 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_TUNTAP_H -+#define __UM_TUNTAP_H -+ -+#include "net_user.h" -+ -+struct tuntap_data { -+ char *dev_name; -+ int fixed_config; -+ char *gate_addr; -+ int fd; -+ void *dev; -+}; -+ -+extern struct net_user_info tuntap_user_info; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/drivers/tuntap_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/tuntap_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/tuntap_kern.c 2005-05-03 22:28:14.569395328 +0300 -@@ -0,0 +1,105 @@ -+/* -+ * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/stddef.h" -+#include "linux/netdevice.h" -+#include "linux/etherdevice.h" -+#include "linux/skbuff.h" -+#include "linux/init.h" -+#include "asm/errno.h" -+#include "net_kern.h" -+#include "net_user.h" -+#include "tuntap.h" -+ -+struct tuntap_init { -+ char *dev_name; -+ char *gate_addr; -+}; -+ -+static void tuntap_init(struct net_device *dev, void *data) -+{ -+ struct uml_net_private *pri; -+ struct tuntap_data *tpri; -+ struct tuntap_init *init = data; -+ -+ init_etherdev(dev, 0); -+ pri = dev->priv; -+ tpri = (struct tuntap_data *) pri->user; -+ *tpri = ((struct tuntap_data) -+ { .dev_name = init->dev_name, -+ .fixed_config = (init->dev_name != NULL), -+ .gate_addr = init->gate_addr, -+ .fd = -1, -+ .dev = dev }); -+ printk("TUN/TAP backend - "); -+ if(tpri->gate_addr != NULL) -+ printk("IP = %s", tpri->gate_addr); -+ printk("\n"); -+} -+ -+static int tuntap_read(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); -+ if(*skb == NULL) return(-ENOMEM); -+ return(net_read(fd, (*skb)->mac.raw, -+ (*skb)->dev->mtu + ETH_HEADER_OTHER)); -+} -+ -+static int tuntap_write(int fd, struct sk_buff **skb, -+ struct uml_net_private *lp) -+{ -+ return(net_write(fd, (*skb)->data, (*skb)->len)); -+} -+ -+struct net_kern_info tuntap_kern_info = { -+ .init = tuntap_init, -+ .protocol = eth_protocol, -+ .read = tuntap_read, -+ .write = tuntap_write, -+}; -+ -+int tuntap_setup(char *str, char **mac_out, void *data) -+{ -+ struct tuntap_init *init = data; -+ -+ *init = ((struct tuntap_init) -+ { .dev_name = NULL, -+ .gate_addr = NULL }); -+ if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, -+ &init->gate_addr)) -+ return(0); -+ -+ return(1); -+} -+ -+static struct transport tuntap_transport = { -+ .list = LIST_HEAD_INIT(tuntap_transport.list), -+ .name = "tuntap", -+ .setup = tuntap_setup, -+ .user = &tuntap_user_info, -+ .kern = &tuntap_kern_info, -+ .private_size = sizeof(struct tuntap_data), -+ .setup_size = sizeof(struct tuntap_init), -+}; -+ -+static int register_tuntap(void) -+{ -+ register_transport(&tuntap_transport); -+ return(1); -+} -+ -+__initcall(register_tuntap); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/drivers/tuntap_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/drivers/tuntap_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/drivers/tuntap_user.c 2005-05-03 22:28:14.571395024 +0300 -@@ -0,0 +1,225 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <stddef.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <errno.h> -+#include <sys/wait.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/uio.h> -+#include <sys/ioctl.h> -+#include <net/if.h> -+#include <linux/if_tun.h> -+#include "net_user.h" -+#include "tuntap.h" -+#include "kern_util.h" -+#include "user_util.h" -+#include "user.h" -+#include "helper.h" -+#include "os.h" -+ -+#define MAX_PACKET ETH_MAX_PACKET -+ -+void tuntap_user_init(void *data, void *dev) -+{ -+ struct tuntap_data *pri = data; -+ -+ pri->dev = dev; -+} -+ -+static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ tap_check_ips(pri->gate_addr, addr); -+ if((pri->fd == -1) || pri->fixed_config) return; -+ open_addr(addr, netmask, pri->dev_name); -+} -+ -+static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, -+ void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ if((pri->fd == -1) || pri->fixed_config) return; -+ close_addr(addr, netmask, pri->dev_name); -+} -+ -+struct tuntap_pre_exec_data { -+ int stdout; -+ int close_me; -+}; -+ -+static void tuntap_pre_exec(void *arg) -+{ -+ struct tuntap_pre_exec_data *data = arg; -+ -+ dup2(data->stdout, 1); -+ os_close_file(data->close_me); -+} -+ -+static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, -+ char *buffer, int buffer_len, int *used_out) -+{ -+ struct tuntap_pre_exec_data data; -+ char version_buf[sizeof("nnnnn\0")]; -+ char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, -+ NULL }; -+ char buf[CMSG_SPACE(sizeof(*fd_out))]; -+ struct msghdr msg; -+ struct cmsghdr *cmsg; -+ struct iovec iov; -+ int pid, n; -+ -+ sprintf(version_buf, "%d", UML_NET_VERSION); -+ -+ data.stdout = remote; -+ data.close_me = me; -+ -+ pid = run_helper(tuntap_pre_exec, &data, argv, NULL); -+ -+ if(pid < 0) return(-pid); -+ -+ os_close_file(remote); -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ if(buffer != NULL){ -+ iov = ((struct iovec) { buffer, buffer_len }); -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ } -+ else { -+ msg.msg_iov = NULL; -+ msg.msg_iovlen = 0; -+ } -+ msg.msg_control = buf; -+ msg.msg_controllen = sizeof(buf); -+ msg.msg_flags = 0; -+ n = recvmsg(me, &msg, 0); -+ *used_out = n; -+ if(n < 0){ -+ printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ CATCH_EINTR(waitpid(pid, NULL, 0)); -+ -+ cmsg = CMSG_FIRSTHDR(&msg); -+ if(cmsg == NULL){ -+ printk("tuntap_open_tramp : didn't receive a message\n"); -+ return(-EINVAL); -+ } -+ if((cmsg->cmsg_level != SOL_SOCKET) || -+ (cmsg->cmsg_type != SCM_RIGHTS)){ -+ printk("tuntap_open_tramp : didn't receive a descriptor\n"); -+ return(-EINVAL); -+ } -+ *fd_out = ((int *) CMSG_DATA(cmsg))[0]; -+ return(0); -+} -+ -+static int tuntap_open(void *data) -+{ -+ struct ifreq ifr; -+ struct tuntap_data *pri = data; -+ char *output, *buffer; -+ int err, fds[2], len, used; -+ -+ err = tap_open_common(pri->dev, pri->gate_addr); -+ if(err < 0) -+ return(err); -+ -+ if(pri->fixed_config){ -+ pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); -+ if(pri->fd < 0){ -+ printk("Failed to open /dev/net/tun, err = %d\n", -+ -pri->fd); -+ return(pri->fd); -+ } -+ memset(&ifr, 0, sizeof(ifr)); -+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; -+ strncpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name) - 1); -+ if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ -+ printk("TUNSETIFF failed, errno = %d\n", errno); -+ os_close_file(pri->fd); -+ return(-errno); -+ } -+ } -+ else { -+ err = os_pipe(fds, 0, 0); -+ if(err < 0){ -+ printk("tuntap_open : os_pipe failed - err = %d\n", -+ -err); -+ return(err); -+ } -+ -+ buffer = get_output_buffer(&len); -+ if(buffer != NULL) len--; -+ used = 0; -+ -+ err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], -+ fds[1], buffer, len, &used); -+ -+ output = buffer; -+ if(err < 0) { -+ printk("%s", output); -+ free_output_buffer(buffer); -+ printk("tuntap_open_tramp failed - err = %d\n", -err); -+ return(err); -+ } -+ -+ pri->dev_name = uml_strdup(buffer); -+ output += IFNAMSIZ; -+ printk("%s", output); -+ free_output_buffer(buffer); -+ -+ os_close_file(fds[0]); -+ iter_addresses(pri->dev, open_addr, pri->dev_name); -+ } -+ -+ return(pri->fd); -+} -+ -+static void tuntap_close(int fd, void *data) -+{ -+ struct tuntap_data *pri = data; -+ -+ if(!pri->fixed_config) -+ iter_addresses(pri->dev, close_addr, pri->dev_name); -+ os_close_file(fd); -+ pri->fd = -1; -+} -+ -+static int tuntap_set_mtu(int mtu, void *data) -+{ -+ return(mtu); -+} -+ -+struct net_user_info tuntap_user_info = { -+ .init = tuntap_user_init, -+ .open = tuntap_open, -+ .close = tuntap_close, -+ .remove = NULL, -+ .set_mtu = tuntap_set_mtu, -+ .add_address = tuntap_add_addr, -+ .delete_address = tuntap_del_addr, -+ .max_packet = MAX_PACKET -+}; -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/file.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/file.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/file.c 2005-05-03 22:28:14.574394568 +0300 -@@ -0,0 +1,942 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <unistd.h> -+#include <errno.h> -+#include <fcntl.h> -+#include <signal.h> -+#include <utime.h> -+#include <dirent.h> -+#include <linux/kdev_t.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+#include <sys/ioctl.h> -+#include <sys/mount.h> -+#include <sys/uio.h> -+#include <sys/utsname.h> -+#include <sys/vfs.h> -+#include "os.h" -+#include "user.h" -+#include "kern_util.h" -+ -+static void copy_stat(struct uml_stat *dst, struct stat64 *src) -+{ -+ *dst = ((struct uml_stat) { -+ .ust_major = MAJOR(src->st_dev), /* device */ -+ .ust_minor = MINOR(src->st_dev), -+ .ust_ino = src->st_ino, /* inode */ -+ .ust_mode = src->st_mode, /* protection */ -+ .ust_nlink = src->st_nlink, /* number of hard links */ -+ .ust_uid = src->st_uid, /* user ID of owner */ -+ .ust_gid = src->st_gid, /* group ID of owner */ -+ .ust_size = src->st_size, /* total size, in bytes */ -+ .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ -+ .ust_blocks = src->st_blocks, /* number of blocks allocated */ -+ .ust_atime = src->st_atime, /* time of last access */ -+ .ust_mtime = src->st_mtime, /* time of last modification */ -+ .ust_ctime = src->st_ctime, /* time of last change */ -+ .ust_rmajor = MAJOR(src->st_rdev), -+ .ust_rminor = MINOR(src->st_rdev), -+ }); -+} -+ -+int os_stat_fd(const int fd, struct uml_stat *ubuf) -+{ -+ struct stat64 sbuf; -+ int err; -+ -+ do { -+ err = fstat64(fd, &sbuf); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ if(ubuf != NULL) -+ copy_stat(ubuf, &sbuf); -+ return(err); -+} -+ -+int os_stat_file(const char *file_name, struct uml_stat *ubuf) -+{ -+ struct stat64 sbuf; -+ int err; -+ -+ do { -+ err = stat64(file_name, &sbuf); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ if(ubuf != NULL) -+ copy_stat(ubuf, &sbuf); -+ return(err); -+} -+ -+int os_lstat_file(const char *file_name, struct uml_stat *ubuf) -+{ -+ struct stat64 sbuf; -+ int err; -+ -+ do { -+ err = lstat64(file_name, &sbuf); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ if(ubuf != NULL) -+ copy_stat(ubuf, &sbuf); -+ return(err); -+} -+ -+int os_access(const char *file, int mode) -+{ -+ int amode, err; -+ -+ amode=(mode& OS_ACC_R_OK ? R_OK : 0) | (mode& OS_ACC_W_OK ? W_OK : 0) | -+ (mode& OS_ACC_X_OK ? X_OK : 0) | (mode& OS_ACC_F_OK ? F_OK : 0) ; -+ -+ err = access(file, amode); -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_set_file_time(const char *file, unsigned long access, unsigned long mod) -+{ -+ struct utimbuf buf = ((struct utimbuf){ .actime = access, -+ .modtime = mod }); -+ int err; -+ -+ err = utime(file, &buf); -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_set_file_perms(const char *file, int mode) -+{ -+ int err; -+ -+ err = chmod(file, mode); -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_set_file_owner(const char *file, int owner, int group) -+{ -+ int err; -+ -+ err = chown(file, owner, group); -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+void os_print_error(int error, const char* str) -+{ -+ errno = error < 0 ? -error : error; -+ -+ perror(str); -+} -+ -+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ -+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) -+{ -+ int err; -+ -+ err = ioctl(fd, cmd, arg); -+ if(err < 0) -+ return(-errno); -+ -+ return(err); -+} -+ -+int os_window_size(int fd, int *rows, int *cols) -+{ -+ struct winsize size; -+ -+ if(ioctl(fd, TIOCGWINSZ, &size) < 0) -+ return(-errno); -+ -+ *rows = size.ws_row; -+ *cols = size.ws_col; -+ -+ return(0); -+} -+ -+int os_new_tty_pgrp(int fd, int pid) -+{ -+ if(ioctl(fd, TIOCSCTTY, 0) < 0){ -+ printk("TIOCSCTTY failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if(tcsetpgrp(fd, pid) < 0){ -+ printk("tcsetpgrp failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+/* FIXME: ensure namebuf in os_get_if_name is big enough */ -+int os_get_ifname(int fd, char* namebuf) -+{ -+ if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_set_slip(int fd) -+{ -+ int disc, sencap; -+ -+ disc = N_SLIP; -+ if(ioctl(fd, TIOCSETD, &disc) < 0){ -+ printk("Failed to set slip line discipline - " -+ "errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ sencap = 0; -+ if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ -+ printk("Failed to set slip encapsulation - " -+ "errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_set_owner(int fd, int pid) -+{ -+ if(fcntl(fd, F_SETOWN, pid) < 0){ -+ int save_errno = errno; -+ -+ if(fcntl(fd, F_GETOWN, 0) != pid) -+ return(-save_errno); -+ } -+ -+ return(0); -+} -+ -+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ -+int os_sigio_async(int master, int slave) -+{ -+ int flags; -+ -+ flags = fcntl(master, F_GETFL); -+ if(flags < 0) { -+ printk("fcntl F_GETFL failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || -+ (fcntl(master, F_SETOWN, os_getpid()) < 0)){ -+ printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ -+ printk("fcntl F_SETFL failed, errno = %d\n", errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_mode_fd(int fd, int mode) -+{ -+ int err; -+ -+ do { -+ err = fchmod(fd, mode); -+ } while((err < 0) && (errno==EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_file_type(char *file) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_lstat_file(file, &buf); -+ if(err < 0) -+ return(err); -+ -+ if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR); -+ else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK); -+ else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV); -+ else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV); -+ else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO); -+ else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK); -+ else return(OS_TYPE_FILE); -+} -+ -+int os_file_mode(char *file, struct openflags *mode_out) -+{ -+ int err; -+ -+ *mode_out = OPENFLAGS(); -+ -+ err = os_access(file, OS_ACC_W_OK); -+ if((err < 0) && (err != -EACCES)) -+ return(err); -+ -+ *mode_out = of_write(*mode_out); -+ -+ err = os_access(file, OS_ACC_R_OK); -+ if((err < 0) && (err != -EACCES)) -+ return(err); -+ -+ *mode_out = of_read(*mode_out); -+ -+ return(0); -+} -+ -+int os_open_file(char *file, struct openflags flags, int mode) -+{ -+ int fd, f = 0; -+ -+ if(flags.r && flags.w) f = O_RDWR; -+ else if(flags.r) f = O_RDONLY; -+ else if(flags.w) f = O_WRONLY; -+ else f = 0; -+ -+ if(flags.s) f |= O_SYNC; -+ if(flags.c) f |= O_CREAT; -+ if(flags.t) f |= O_TRUNC; -+ if(flags.e) f |= O_EXCL; -+ if(flags.d) f |= O_DIRECT; -+ -+ fd = open64(file, f, mode); -+ if(fd < 0) -+ return(-errno); -+ -+ if(flags.cl && fcntl(fd, F_SETFD, 1)){ -+ os_close_file(fd); -+ return(-errno); -+ } -+ -+ return(fd); -+} -+ -+void *os_open_dir(char *path, int *err_out) -+{ -+ void *dir; -+ -+ dir = opendir(path); -+ *err_out = -errno; -+ return(dir); -+} -+ -+int os_seek_dir(void *stream, unsigned long long pos) -+{ -+ seekdir(stream, pos); -+ return(0); -+} -+ -+int os_read_dir(void *stream, unsigned long long *ino_out, char **name_out) -+{ -+ struct dirent *ent; -+ -+ errno = 0; -+ ent = readdir(stream); -+ if(ent == NULL){ -+ if(errno != 0) -+ return(-errno); -+ *name_out = NULL; -+ return(0); -+ } -+ -+ *ino_out = ent->d_ino; -+ *name_out = ent->d_name; -+ return(0); -+} -+ -+int os_tell_dir(void *stream) -+{ -+ return(telldir(stream)); -+} -+ -+int os_close_dir(void *stream) -+{ -+ int err; -+ -+ err = closedir(stream); -+ if(err < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_remove_file(const char *file) -+{ -+ int err; -+ -+ err = unlink(file); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_move_file(const char *from, const char *to) -+{ -+ int err; -+ -+ err = rename(from, to); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_truncate_fd(int fd, unsigned long long len) -+{ -+ int err; -+ -+ err = ftruncate64(fd, len); -+ if(err) -+ return(-errno); -+ return(0); -+} -+ -+int os_truncate_file(const char *file, unsigned long long len) -+{ -+ int err; -+ -+ err = truncate64(file, len); -+ if(err) -+ return(-errno); -+ return(0); -+} -+ -+int os_connect_socket(char *name) -+{ -+ struct sockaddr_un sock; -+ int fd, err; -+ -+ sock.sun_family = AF_UNIX; -+ snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); -+ -+ fd = socket(AF_UNIX, SOCK_STREAM, 0); -+ if(fd < 0) -+ return(fd); -+ -+ err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); -+ if(err) -+ return(-errno); -+ -+ return(fd); -+} -+ -+void os_close_file(int fd) -+{ -+ close(fd); -+} -+ -+int os_seek_file(int fd, __u64 offset) -+{ -+ __u64 actual; -+ -+ actual = lseek64(fd, offset, SEEK_SET); -+ if(actual != offset) -+ return(-errno); -+ return(0); -+} -+ -+static int fault_buffer(void *start, int len, -+ int (*copy_proc)(void *addr, void *buf, int len)) -+{ -+ int page = getpagesize(), i; -+ char c; -+ -+ for(i = 0; i < len; i += page){ -+ if((*copy_proc)(start + i, &c, sizeof(c))) -+ return(-EFAULT); -+ } -+ if((len % page) != 0){ -+ if((*copy_proc)(start + len - 1, &c, sizeof(c))) -+ return(-EFAULT); -+ } -+ return(0); -+} -+ -+static int file_io(int fd, void *buf, int len, -+ int (*io_proc)(int fd, void *buf, int len), -+ int (*copy_user_proc)(void *addr, void *buf, int len)) -+{ -+ int n, err; -+ -+ do { -+ n = (*io_proc)(fd, buf, len); -+ if((n < 0) && (errno == EFAULT)){ -+ err = fault_buffer(buf, len, copy_user_proc); -+ if(err) -+ return(err); -+ n = (*io_proc)(fd, buf, len); -+ } -+ } while((n < 0) && (errno == EINTR)); -+ -+ if(n < 0) -+ return(-errno); -+ return(n); -+} -+ -+int os_read_file(int fd, void *buf, int len) -+{ -+ return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, -+ copy_from_user_proc)); -+} -+ -+int os_write_file(int fd, const void *buf, int len) -+{ -+ return(file_io(fd, (void *) buf, len, -+ (int (*)(int, void *, int)) write, copy_to_user_proc)); -+} -+ -+int os_file_size(char *file, long long *size_out) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_stat_file(file, &buf); -+ if(err < 0){ -+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); -+ return(err); -+ } -+ -+ if(S_ISBLK(buf.ust_mode)){ -+ int fd, blocks; -+ -+ fd = os_open_file(file, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open \"%s\", errno = %d\n", file, -fd); -+ return(fd); -+ } -+ if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ -+ printk("Couldn't get the block size of \"%s\", " -+ "errno = %d\n", file, errno); -+ err = -errno; -+ os_close_file(fd); -+ return(err); -+ } -+ *size_out = ((long long) blocks) * 512; -+ os_close_file(fd); -+ return(0); -+ } -+ *size_out = buf.ust_size; -+ return(0); -+} -+ -+int os_fd_size(int fd, long long *size_out) -+{ -+ struct stat buf; -+ int err; -+ -+ err = fstat(fd, &buf); -+ if(err) -+ return(-errno); -+ -+ *size_out = buf.st_size; -+ return(0); -+} -+ -+int os_file_modtime(char *file, unsigned long *modtime) -+{ -+ struct uml_stat buf; -+ int err; -+ -+ err = os_stat_file(file, &buf); -+ if(err < 0){ -+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err); -+ return(err); -+ } -+ -+ *modtime = buf.ust_mtime; -+ return(0); -+} -+ -+int os_get_exec_close(int fd, int* close_on_exec) -+{ -+ int ret; -+ -+ do { -+ ret = fcntl(fd, F_GETFD); -+ } while((ret < 0) && (errno == EINTR)) ; -+ -+ if(ret < 0) -+ return(-errno); -+ -+ *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; -+ return(ret); -+} -+ -+int os_set_exec_close(int fd, int close_on_exec) -+{ -+ int flag, err; -+ -+ if(close_on_exec) flag = FD_CLOEXEC; -+ else flag = 0; -+ -+ do { -+ err = fcntl(fd, F_SETFD, flag); -+ } while((err < 0) && (errno == EINTR)) ; -+ -+ if(err < 0) -+ return(-errno); -+ return(err); -+} -+ -+int os_pipe(int *fds, int stream, int close_on_exec) -+{ -+ int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; -+ -+ err = socketpair(AF_UNIX, type, 0, fds); -+ if(err < 0) -+ return(-errno); -+ -+ if(!close_on_exec) -+ return(0); -+ -+ err = os_set_exec_close(fds[0], 1); -+ if(err < 0) -+ goto error; -+ -+ err = os_set_exec_close(fds[1], 1); -+ if(err < 0) -+ goto error; -+ -+ return(0); -+ -+ error: -+ printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); -+ os_close_file(fds[1]); -+ os_close_file(fds[0]); -+ return(err); -+} -+ -+int os_set_fd_async(int fd, int owner) -+{ -+ /* XXX This should do F_GETFL first */ -+ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ -+ printk("os_set_fd_async : failed to set O_ASYNC and " -+ "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); -+ return(-errno); -+ } -+#ifdef notdef -+ if(fcntl(fd, F_SETFD, 1) < 0){ -+ printk("os_set_fd_async : Setting FD_CLOEXEC failed, " -+ "errno = %d\n", errno); -+ } -+#endif -+ -+ if((fcntl(fd, F_SETSIG, SIGIO) < 0) || -+ (fcntl(fd, F_SETOWN, owner) < 0)){ -+ printk("os_set_fd_async : Failed to fcntl F_SETOWN " -+ "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, -+ owner, errno); -+ return(-errno); -+ } -+ -+ return(0); -+} -+ -+int os_clear_fd_async(int fd) -+{ -+ int flags = fcntl(fd, F_GETFL); -+ -+ flags &= ~(O_ASYNC | O_NONBLOCK); -+ if(fcntl(fd, F_SETFL, flags) < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_set_fd_block(int fd, int blocking) -+{ -+ int flags; -+ -+ flags = fcntl(fd, F_GETFL); -+ -+ if(blocking) flags &= ~O_NONBLOCK; -+ else flags |= O_NONBLOCK; -+ -+ if(fcntl(fd, F_SETFL, flags) < 0){ -+ printk("Failed to change blocking on fd # %d, errno = %d\n", -+ fd, errno); -+ return(-errno); -+ } -+ return(0); -+} -+ -+int os_accept_connection(int fd) -+{ -+ int new; -+ -+ new = accept(fd, NULL, 0); -+ if(new < 0) -+ return(-errno); -+ return(new); -+} -+ -+#ifndef SHUT_RD -+#define SHUT_RD 0 -+#endif -+ -+#ifndef SHUT_WR -+#define SHUT_WR 1 -+#endif -+ -+#ifndef SHUT_RDWR -+#define SHUT_RDWR 2 -+#endif -+ -+int os_shutdown_socket(int fd, int r, int w) -+{ -+ int what, err; -+ -+ if(r && w) what = SHUT_RDWR; -+ else if(r) what = SHUT_RD; -+ else if(w) what = SHUT_WR; -+ else { -+ printk("os_shutdown_socket : neither r or w was set\n"); -+ return(-EINVAL); -+ } -+ err = shutdown(fd, what); -+ if(err < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_rcv_fd(int fd, int *helper_pid_out) -+{ -+ int new, n; -+ char buf[CMSG_SPACE(sizeof(new))]; -+ struct msghdr msg; -+ struct cmsghdr *cmsg; -+ struct iovec iov; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ iov = ((struct iovec) { .iov_base = helper_pid_out, -+ .iov_len = sizeof(*helper_pid_out) }); -+ msg.msg_iov = &iov; -+ msg.msg_iovlen = 1; -+ msg.msg_control = buf; -+ msg.msg_controllen = sizeof(buf); -+ msg.msg_flags = 0; -+ -+ n = recvmsg(fd, &msg, 0); -+ if(n < 0) -+ return(-errno); -+ -+ else if(n != sizeof(iov.iov_len)) -+ *helper_pid_out = -1; -+ -+ cmsg = CMSG_FIRSTHDR(&msg); -+ if(cmsg == NULL){ -+ printk("rcv_fd didn't receive anything, error = %d\n", errno); -+ return(-1); -+ } -+ if((cmsg->cmsg_level != SOL_SOCKET) || -+ (cmsg->cmsg_type != SCM_RIGHTS)){ -+ printk("rcv_fd didn't receive a descriptor\n"); -+ return(-1); -+ } -+ -+ new = ((int *) CMSG_DATA(cmsg))[0]; -+ return(new); -+} -+ -+int os_create_unix_socket(char *file, int len, int close_on_exec) -+{ -+ struct sockaddr_un addr; -+ int sock, err; -+ -+ sock = socket(PF_UNIX, SOCK_DGRAM, 0); -+ if (sock < 0){ -+ printk("create_unix_socket - socket failed, errno = %d\n", -+ errno); -+ return(-errno); -+ } -+ -+ if(close_on_exec) { -+ err = os_set_exec_close(sock, 1); -+ if(err < 0) -+ printk("create_unix_socket : close_on_exec failed, " -+ "err = %d", -err); -+ } -+ -+ addr.sun_family = AF_UNIX; -+ -+ /* XXX Be more careful about overflow */ -+ snprintf(addr.sun_path, len, "%s", file); -+ -+ err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); -+ if (err < 0){ -+ printk("create_listening_socket at '%s' - bind failed, " -+ "errno = %d\n", file, errno); -+ return(-errno); -+ } -+ -+ return(sock); -+} -+ -+int os_make_symlink(const char *to, const char *from) -+{ -+ int err; -+ -+ err = symlink(to, from); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_read_symlink(const char *file, char *buf, int size) -+{ -+ int err; -+ -+ err = readlink(file, buf, size); -+ if(err < 0) -+ return(-errno); -+ -+ return(err); -+} -+ -+int os_link_file(const char *to, const char *from) -+{ -+ int err; -+ -+ err = link(to, from); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_make_dir(const char *dir, int mode) -+{ -+ int err; -+ -+ err = mkdir(dir, mode); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_make_dev(const char *name, int mode, int major, int minor) -+{ -+ int err; -+ -+ err = mknod(name, mode, MKDEV(major, minor)); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+int os_remove_dir(const char *dir) -+{ -+ int err; -+ -+ err = rmdir(dir); -+ if(err) -+ return(-errno); -+ -+ return(0); -+} -+ -+void os_flush_stdout(void) -+{ -+ fflush(stdout); -+} -+ -+int os_lock_file(int fd, int excl) -+{ -+ int type = excl ? F_WRLCK : F_RDLCK; -+ struct flock lock = ((struct flock) { .l_type = type, -+ .l_whence = SEEK_SET, -+ .l_start = 0, -+ .l_len = 0 } ); -+ int err, save; -+ -+ err = fcntl(fd, F_SETLK, &lock); -+ if(!err) -+ goto out; -+ -+ save = -errno; -+ err = fcntl(fd, F_GETLK, &lock); -+ if(err){ -+ err = -errno; -+ goto out; -+ } -+ -+ printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); -+ err = save; -+ out: -+ return(err); -+} -+ -+int os_stat_filesystem(char *path, long *bsize_out, long long *blocks_out, -+ long long *bfree_out, long long *bavail_out, -+ long long *files_out, long long *ffree_out, -+ void *fsid_out, int fsid_size, long *namelen_out, -+ long *spare_out) -+{ -+ struct statfs64 buf; -+ int err; -+ -+ err = statfs64(path, &buf); -+ if(err < 0) -+ return(-errno); -+ -+ *bsize_out = buf.f_bsize; -+ *blocks_out = buf.f_blocks; -+ *bfree_out = buf.f_bfree; -+ *bavail_out = buf.f_bavail; -+ *files_out = buf.f_files; -+ *ffree_out = buf.f_ffree; -+ memcpy(fsid_out, &buf.f_fsid, -+ sizeof(buf.f_fsid) > fsid_size ? fsid_size : -+ sizeof(buf.f_fsid)); -+ *namelen_out = buf.f_namelen; -+ spare_out[0] = buf.f_spare[0]; -+ spare_out[1] = buf.f_spare[1]; -+ spare_out[2] = buf.f_spare[2]; -+ spare_out[3] = buf.f_spare[3]; -+ spare_out[4] = buf.f_spare[4]; -+ spare_out[5] = buf.f_spare[5]; -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/include/file.h -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/include/file.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/include/file.h 2005-05-03 22:28:14.575394416 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __OS_FILE_H__ -+#define __OS_FILE_H__ -+ -+#define DEV_NULL "/dev/null" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/Makefile 2005-05-03 22:28:14.575394416 +0300 -@@ -0,0 +1,23 @@ -+# -+# Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = aio.o file.o process.o time.o tty.o -+ -+HAVE_AIO_ABI = $(shell [ -e /usr/include/linux/aio_abi.h ] && \ -+ echo -DHAVE_AIO_ABI) -+HAVE_AIO_LIBC = $(shell objdump -T /lib/libc-*.so | grep io_submit && \ -+ echo -DHAVE_AIO_LIBC) -+CFLAGS_aio.o = $(HAVE_AIO_ABI) $(HAVE_AIO_LIBC) -+ -+include $(TOPDIR)/Rules.make -+ -+$(obj-y) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+clean : -+ -+archmrproper: -Index: linux-2.4.29/arch/um/os-Linux/process.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/process.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/process.c 2005-05-03 22:28:14.577394112 +0300 -@@ -0,0 +1,151 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <stdio.h> -+#include <errno.h> -+#include <signal.h> -+#include <sys/mman.h> -+#include <sys/wait.h> -+#include "os.h" -+#include "user.h" -+#include "user_util.h" -+ -+#define ARBITRARY_ADDR -1 -+#define FAILURE_PID -1 -+ -+#define STAT_PATH_LEN sizeof("/proc/#######/stat\0") -+#define COMM_SCANF "%*[^)])" -+ -+unsigned long os_process_pc(int pid) -+{ -+ char proc_stat[STAT_PATH_LEN], buf[256]; -+ unsigned long pc; -+ int fd, err; -+ -+ sprintf(proc_stat, "/proc/%d/stat", pid); -+ fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("os_process_pc - couldn't open '%s', err = %d\n", -+ proc_stat, -fd); -+ return(ARBITRARY_ADDR); -+ } -+ err = os_read_file(fd, buf, sizeof(buf)); -+ if(err < 0){ -+ printk("os_process_pc - couldn't read '%s', err = %d\n", -+ proc_stat, -err); -+ os_close_file(fd); -+ return(ARBITRARY_ADDR); -+ } -+ os_close_file(fd); -+ pc = ARBITRARY_ADDR; -+ if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d " -+ "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " -+ "%*d %*d %*d %*d %*d %lu", &pc) != 1){ -+ printk("os_process_pc - couldn't find pc in '%s'\n", buf); -+ } -+ return(pc); -+} -+ -+int os_process_parent(int pid) -+{ -+ char stat[STAT_PATH_LEN]; -+ char data[256]; -+ int parent, n, fd; -+ -+ if(pid == -1) return(-1); -+ -+ snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); -+ fd = os_open_file(stat, of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open '%s', err = %d\n", stat, -fd); -+ return(FAILURE_PID); -+ } -+ -+ n = os_read_file(fd, data, sizeof(data)); -+ os_close_file(fd); -+ -+ if(n < 0){ -+ printk("Couldn't read '%s', err = %d\n", stat, -n); -+ return(FAILURE_PID); -+ } -+ -+ parent = FAILURE_PID; -+ n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); -+ if(n != 1) -+ printk("Failed to scan '%s'\n", data); -+ -+ return(parent); -+} -+ -+void os_stop_process(int pid) -+{ -+ kill(pid, SIGSTOP); -+} -+ -+void os_kill_process(int pid, int reap_child) -+{ -+ kill(pid, SIGKILL); -+ if(reap_child) -+ CATCH_EINTR(waitpid(pid, NULL, 0)); -+ -+} -+ -+void os_usr1_process(int pid) -+{ -+ kill(pid, SIGUSR1); -+} -+ -+int os_getpid(void) -+{ -+ return(getpid()); -+} -+ -+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, -+ int r, int w, int x) -+{ -+ void *loc; -+ int prot; -+ -+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0); -+ -+ loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, -+ fd, off); -+ if(loc == MAP_FAILED) -+ return(-errno); -+ return(0); -+} -+ -+int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) -+{ -+ int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | -+ (x ? PROT_EXEC : 0)); -+ -+ if(mprotect(addr, len, prot) < 0) -+ return(-errno); -+ return(0); -+} -+ -+int os_unmap_memory(void *addr, int len) -+{ -+ int err; -+ -+ err = munmap(addr, len); -+ if(err < 0) -+ return(-errno); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/time.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/time.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/time.c 2005-05-03 22:28:14.578393960 +0300 -@@ -0,0 +1,21 @@ -+#include <stdlib.h> -+#include <sys/time.h> -+ -+unsigned long long os_usecs(void) -+{ -+ struct timeval tv; -+ -+ gettimeofday(&tv, NULL); -+ return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/os-Linux/tty.c -=================================================================== ---- linux-2.4.29.orig/arch/um/os-Linux/tty.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/os-Linux/tty.c 2005-05-03 22:28:14.579393808 +0300 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdlib.h> -+#include <errno.h> -+#include "os.h" -+#include "user.h" -+#include "kern_util.h" -+ -+struct grantpt_info { -+ int fd; -+ int res; -+ int err; -+}; -+ -+static void grantpt_cb(void *arg) -+{ -+ struct grantpt_info *info = arg; -+ -+ info->res = grantpt(info->fd); -+ info->err = errno; -+} -+ -+int get_pty(void) -+{ -+ struct grantpt_info info; -+ int fd; -+ -+ fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); -+ return(fd); -+ } -+ -+ info.fd = fd; -+ initial_thread_cb(grantpt_cb, &info); -+ -+ if(info.res < 0){ -+ printk("get_pty : Couldn't grant pty - errno = %d\n", -+ -info.err); -+ return(-1); -+ } -+ if(unlockpt(fd) < 0){ -+ printk("get_pty : Couldn't unlock pty - errno = %d\n", errno); -+ return(-1); -+ } -+ return(fd); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/bugs.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/bugs.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/bugs.c 2005-05-03 22:28:14.580393656 +0300 -@@ -0,0 +1,222 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <unistd.h> -+#include <errno.h> -+#include <string.h> -+#include <sys/signal.h> -+#include <asm/ldt.h> -+#include "kern_util.h" -+#include "user.h" -+#include "sysdep/ptrace.h" -+#include "task.h" -+#include "os.h" -+ -+#define MAXTOKEN 64 -+ -+/* Set during early boot */ -+int host_has_cmov = 1; -+int host_has_xmm = 0; -+ -+static char token(int fd, char *buf, int len, char stop) -+{ -+ int n; -+ char *ptr, *end, c; -+ -+ ptr = buf; -+ end = &buf[len]; -+ do { -+ n = os_read_file(fd, ptr, sizeof(*ptr)); -+ c = *ptr++; -+ if(n != sizeof(*ptr)){ -+ if(n == 0) return(0); -+ printk("Reading /proc/cpuinfo failed, err = %d\n", -n); -+ if(n < 0) -+ return(n); -+ else -+ return(-EIO); -+ } -+ } while((c != '\n') && (c != stop) && (ptr < end)); -+ -+ if(ptr == end){ -+ printk("Failed to find '%c' in /proc/cpuinfo\n", stop); -+ return(-1); -+ } -+ *(ptr - 1) = '\0'; -+ return(c); -+} -+ -+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) -+{ -+ int n; -+ char c; -+ -+ scratch[len - 1] = '\0'; -+ while(1){ -+ c = token(fd, scratch, len - 1, ':'); -+ if(c <= 0) -+ return(0); -+ else if(c != ':'){ -+ printk("Failed to find ':' in /proc/cpuinfo\n"); -+ return(0); -+ } -+ -+ if(!strncmp(scratch, key, strlen(key))) -+ return(1); -+ -+ do { -+ n = os_read_file(fd, &c, sizeof(c)); -+ if(n != sizeof(c)){ -+ printk("Failed to find newline in " -+ "/proc/cpuinfo, err = %d\n", -n); -+ return(0); -+ } -+ } while(c != '\n'); -+ } -+ return(0); -+} -+ -+int cpu_feature(char *what, char *buf, int len) -+{ -+ int fd, ret = 0; -+ -+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); -+ return(0); -+ } -+ -+ if(!find_cpuinfo_line(fd, what, buf, len)){ -+ printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); -+ goto out_close; -+ } -+ -+ token(fd, buf, len, '\n'); -+ ret = 1; -+ -+ out_close: -+ os_close_file(fd); -+ return(ret); -+} -+ -+static int check_cpu_flag(char *feature, int *have_it) -+{ -+ char buf[MAXTOKEN], c; -+ int fd, len = sizeof(buf)/sizeof(buf[0]); -+ -+ printk("Checking for host processor %s support...", feature); -+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); -+ if(fd < 0){ -+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); -+ return(0); -+ } -+ -+ *have_it = 0; -+ if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0]))) -+ goto out; -+ -+ c = token(fd, buf, len - 1, ' '); -+ if(c < 0) goto out; -+ else if(c != ' '){ -+ printk("Failed to find ' ' in /proc/cpuinfo\n"); -+ goto out; -+ } -+ -+ while(1){ -+ c = token(fd, buf, len - 1, ' '); -+ if(c < 0) goto out; -+ else if(c == '\n') break; -+ -+ if(!strcmp(buf, feature)){ -+ *have_it = 1; -+ goto out; -+ } -+ } -+ out: -+ if(*have_it == 0) printk("No\n"); -+ else if(*have_it == 1) printk("Yes\n"); -+ os_close_file(fd); -+ return(1); -+} -+ -+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems -+ * for some people. -+ */ -+static void disable_lcall(void) -+{ -+ struct modify_ldt_ldt_s ldt; -+ int err; -+ -+ bzero(&ldt, sizeof(ldt)); -+ ldt.entry_number = 7; -+ ldt.base_addr = 0; -+ ldt.limit = 0; -+ err = modify_ldt(1, &ldt, sizeof(ldt)); -+ if(err) -+ printk("Failed to disable lcall7 - errno = %d\n", errno); -+} -+#endif -+ -+void arch_init_thread(void) -+{ -+#if 0 -+ disable_lcall(); -+#endif -+} -+ -+void arch_check_bugs(void) -+{ -+ int have_it; -+ -+ if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ -+ printk("/proc/cpuinfo not available - skipping CPU capability " -+ "checks\n"); -+ return; -+ } -+ if(check_cpu_flag("cmov", &have_it)) -+ host_has_cmov = have_it; -+ if(check_cpu_flag("xmm", &have_it)) -+ host_has_xmm = have_it; -+} -+ -+int arch_handle_signal(int sig, union uml_pt_regs *regs) -+{ -+ unsigned char tmp[2]; -+ -+ /* This is testing for a cmov (0x0f 0x4x) instruction causing a -+ * SIGILL in init. -+ */ -+ if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0); -+ -+ if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) -+ panic("SIGILL in init, could not read instructions!\n"); -+ if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) -+ return(0); -+ -+ if(host_has_cmov == 0) -+ panic("SIGILL caused by cmov, which this processor doesn't " -+ "implement, boot a filesystem compiled for older " -+ "processors"); -+ else if(host_has_cmov == 1) -+ panic("SIGILL caused by cmov, which this processor claims to " -+ "implement"); -+ else if(host_has_cmov == -1) -+ panic("SIGILL caused by cmov, couldn't tell if this processor " -+ "implements it, boot a filesystem compiled for older " -+ "processors"); -+ else panic("Bad value for host_has_cmov (%d)", host_has_cmov); -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/checksum.S -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/checksum.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/checksum.S 2005-05-03 22:28:14.582393352 +0300 -@@ -0,0 +1,460 @@ -+/* -+ * INET An implementation of the TCP/IP protocol suite for the LINUX -+ * operating system. INET is implemented using the BSD Socket -+ * interface as the means of communication with the user level. -+ * -+ * IP/TCP/UDP checksumming routines -+ * -+ * Authors: Jorge Cwik, <jorge@laser.satlink.net> -+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no> -+ * Tom May, <ftom@netcom.com> -+ * Pentium Pro/II routines: -+ * Alexander Kjeldaas <astor@guardian.no> -+ * Finn Arne Gangstad <finnag@guardian.no> -+ * Lots of code moved from tcp.c and ip.c; see those files -+ * for more names. -+ * -+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception -+ * handling. -+ * Andi Kleen, add zeroing on error -+ * converted to pure assembler -+ * -+ * 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. -+ */ -+ -+#include <linux/config.h> -+#include <asm/errno.h> -+ -+/* -+ * computes a partial checksum, e.g. for TCP/UDP fragments -+ */ -+ -+/* -+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) -+ */ -+ -+.text -+.align 4 -+.globl arch_csum_partial -+ -+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM -+ -+ /* -+ * Experiments with Ethernet and SLIP connections show that buff -+ * is aligned on either a 2-byte or 4-byte boundary. We get at -+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned. -+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte -+ * alignment for the unrolled loop. -+ */ -+arch_csum_partial: -+ pushl %esi -+ pushl %ebx -+ movl 20(%esp),%eax # Function arg: unsigned int sum -+ movl 16(%esp),%ecx # Function arg: int len -+ movl 12(%esp),%esi # Function arg: unsigned char *buff -+ testl $2, %esi # Check alignment. -+ jz 2f # Jump if alignment is ok. -+ subl $2, %ecx # Alignment uses up two bytes. -+ jae 1f # Jump if we had at least two bytes. -+ addl $2, %ecx # ecx was < 2. Deal with it. -+ jmp 4f -+1: movw (%esi), %bx -+ addl $2, %esi -+ addw %bx, %ax -+ adcl $0, %eax -+2: -+ movl %ecx, %edx -+ shrl $5, %ecx -+ jz 2f -+ testl %esi, %esi -+1: movl (%esi), %ebx -+ adcl %ebx, %eax -+ movl 4(%esi), %ebx -+ adcl %ebx, %eax -+ movl 8(%esi), %ebx -+ adcl %ebx, %eax -+ movl 12(%esi), %ebx -+ adcl %ebx, %eax -+ movl 16(%esi), %ebx -+ adcl %ebx, %eax -+ movl 20(%esi), %ebx -+ adcl %ebx, %eax -+ movl 24(%esi), %ebx -+ adcl %ebx, %eax -+ movl 28(%esi), %ebx -+ adcl %ebx, %eax -+ lea 32(%esi), %esi -+ dec %ecx -+ jne 1b -+ adcl $0, %eax -+2: movl %edx, %ecx -+ andl $0x1c, %edx -+ je 4f -+ shrl $2, %edx # This clears CF -+3: adcl (%esi), %eax -+ lea 4(%esi), %esi -+ dec %edx -+ jne 3b -+ adcl $0, %eax -+4: andl $3, %ecx -+ jz 7f -+ cmpl $2, %ecx -+ jb 5f -+ movw (%esi),%cx -+ leal 2(%esi),%esi -+ je 6f -+ shll $16,%ecx -+5: movb (%esi),%cl -+6: addl %ecx,%eax -+ adcl $0, %eax -+7: -+ popl %ebx -+ popl %esi -+ ret -+ -+#else -+ -+/* Version for PentiumII/PPro */ -+ -+arch_csum_partial: -+ pushl %esi -+ pushl %ebx -+ movl 20(%esp),%eax # Function arg: unsigned int sum -+ movl 16(%esp),%ecx # Function arg: int len -+ movl 12(%esp),%esi # Function arg: const unsigned char *buf -+ -+ testl $2, %esi -+ jnz 30f -+10: -+ movl %ecx, %edx -+ movl %ecx, %ebx -+ andl $0x7c, %ebx -+ shrl $7, %ecx -+ addl %ebx,%esi -+ shrl $2, %ebx -+ negl %ebx -+ lea 45f(%ebx,%ebx,2), %ebx -+ testl %esi, %esi -+ jmp *%ebx -+ -+ # Handle 2-byte-aligned regions -+20: addw (%esi), %ax -+ lea 2(%esi), %esi -+ adcl $0, %eax -+ jmp 10b -+ -+30: subl $2, %ecx -+ ja 20b -+ je 32f -+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned -+ addl %ebx, %eax -+ adcl $0, %eax -+ jmp 80f -+32: -+ addw (%esi), %ax # csumming 2 bytes, 2-aligned -+ adcl $0, %eax -+ jmp 80f -+ -+40: -+ addl -128(%esi), %eax -+ adcl -124(%esi), %eax -+ adcl -120(%esi), %eax -+ adcl -116(%esi), %eax -+ adcl -112(%esi), %eax -+ adcl -108(%esi), %eax -+ adcl -104(%esi), %eax -+ adcl -100(%esi), %eax -+ adcl -96(%esi), %eax -+ adcl -92(%esi), %eax -+ adcl -88(%esi), %eax -+ adcl -84(%esi), %eax -+ adcl -80(%esi), %eax -+ adcl -76(%esi), %eax -+ adcl -72(%esi), %eax -+ adcl -68(%esi), %eax -+ adcl -64(%esi), %eax -+ adcl -60(%esi), %eax -+ adcl -56(%esi), %eax -+ adcl -52(%esi), %eax -+ adcl -48(%esi), %eax -+ adcl -44(%esi), %eax -+ adcl -40(%esi), %eax -+ adcl -36(%esi), %eax -+ adcl -32(%esi), %eax -+ adcl -28(%esi), %eax -+ adcl -24(%esi), %eax -+ adcl -20(%esi), %eax -+ adcl -16(%esi), %eax -+ adcl -12(%esi), %eax -+ adcl -8(%esi), %eax -+ adcl -4(%esi), %eax -+45: -+ lea 128(%esi), %esi -+ adcl $0, %eax -+ dec %ecx -+ jge 40b -+ movl %edx, %ecx -+50: andl $3, %ecx -+ jz 80f -+ -+ # Handle the last 1-3 bytes without jumping -+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked -+ movl $0xffffff,%ebx # by the shll and shrl instructions -+ shll $3,%ecx -+ shrl %cl,%ebx -+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok -+ addl %ebx,%eax -+ adcl $0,%eax -+80: -+ popl %ebx -+ popl %esi -+ ret -+ -+#endif -+ -+/* -+unsigned int csum_partial_copy_generic (const char *src, char *dst, -+ int len, int sum, int *src_err_ptr, int *dst_err_ptr) -+ */ -+ -+/* -+ * Copy from ds while checksumming, otherwise like csum_partial -+ * -+ * The macros SRC and DST specify the type of access for the instruction. -+ * thus we can call a custom exception handler for all access types. -+ * -+ * FIXME: could someone double-check whether I haven't mixed up some SRC and -+ * DST definitions? It's damn hard to trigger all cases. I hope I got -+ * them all but there's no guarantee. -+ */ -+ -+#define SRC(y...) \ -+ 9999: y; \ -+ .section __ex_table, "a"; \ -+ .long 9999b, 6001f ; \ -+ .previous -+ -+#define DST(y...) \ -+ 9999: y; \ -+ .section __ex_table, "a"; \ -+ .long 9999b, 6002f ; \ -+ .previous -+ -+.align 4 -+.globl csum_partial_copy_generic_i386 -+ -+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM -+ -+#define ARGBASE 16 -+#define FP 12 -+ -+csum_partial_copy_generic_i386: -+ subl $4,%esp -+ pushl %edi -+ pushl %esi -+ pushl %ebx -+ movl ARGBASE+16(%esp),%eax # sum -+ movl ARGBASE+12(%esp),%ecx # len -+ movl ARGBASE+4(%esp),%esi # src -+ movl ARGBASE+8(%esp),%edi # dst -+ -+ testl $2, %edi # Check alignment. -+ jz 2f # Jump if alignment is ok. -+ subl $2, %ecx # Alignment uses up two bytes. -+ jae 1f # Jump if we had at least two bytes. -+ addl $2, %ecx # ecx was < 2. Deal with it. -+ jmp 4f -+SRC(1: movw (%esi), %bx ) -+ addl $2, %esi -+DST( movw %bx, (%edi) ) -+ addl $2, %edi -+ addw %bx, %ax -+ adcl $0, %eax -+2: -+ movl %ecx, FP(%esp) -+ shrl $5, %ecx -+ jz 2f -+ testl %esi, %esi -+SRC(1: movl (%esi), %ebx ) -+SRC( movl 4(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, (%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 4(%edi) ) -+ -+SRC( movl 8(%esi), %ebx ) -+SRC( movl 12(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 8(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 12(%edi) ) -+ -+SRC( movl 16(%esi), %ebx ) -+SRC( movl 20(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 16(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 20(%edi) ) -+ -+SRC( movl 24(%esi), %ebx ) -+SRC( movl 28(%esi), %edx ) -+ adcl %ebx, %eax -+DST( movl %ebx, 24(%edi) ) -+ adcl %edx, %eax -+DST( movl %edx, 28(%edi) ) -+ -+ lea 32(%esi), %esi -+ lea 32(%edi), %edi -+ dec %ecx -+ jne 1b -+ adcl $0, %eax -+2: movl FP(%esp), %edx -+ movl %edx, %ecx -+ andl $0x1c, %edx -+ je 4f -+ shrl $2, %edx # This clears CF -+SRC(3: movl (%esi), %ebx ) -+ adcl %ebx, %eax -+DST( movl %ebx, (%edi) ) -+ lea 4(%esi), %esi -+ lea 4(%edi), %edi -+ dec %edx -+ jne 3b -+ adcl $0, %eax -+4: andl $3, %ecx -+ jz 7f -+ cmpl $2, %ecx -+ jb 5f -+SRC( movw (%esi), %cx ) -+ leal 2(%esi), %esi -+DST( movw %cx, (%edi) ) -+ leal 2(%edi), %edi -+ je 6f -+ shll $16,%ecx -+SRC(5: movb (%esi), %cl ) -+DST( movb %cl, (%edi) ) -+6: addl %ecx, %eax -+ adcl $0, %eax -+7: -+5000: -+ -+# Exception handler: -+.section .fixup, "ax" -+ -+6001: -+ movl ARGBASE+20(%esp), %ebx # src_err_ptr -+ movl $-EFAULT, (%ebx) -+ -+ # zero the complete destination - computing the rest -+ # is too much work -+ movl ARGBASE+8(%esp), %edi # dst -+ movl ARGBASE+12(%esp), %ecx # len -+ xorl %eax,%eax -+ rep ; stosb -+ -+ jmp 5000b -+ -+6002: -+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr -+ movl $-EFAULT,(%ebx) -+ jmp 5000b -+ -+.previous -+ -+ popl %ebx -+ popl %esi -+ popl %edi -+ popl %ecx # equivalent to addl $4,%esp -+ ret -+ -+#else -+ -+/* Version for PentiumII/PPro */ -+ -+#define ROUND1(x) \ -+ SRC(movl x(%esi), %ebx ) ; \ -+ addl %ebx, %eax ; \ -+ DST(movl %ebx, x(%edi) ) ; -+ -+#define ROUND(x) \ -+ SRC(movl x(%esi), %ebx ) ; \ -+ adcl %ebx, %eax ; \ -+ DST(movl %ebx, x(%edi) ) ; -+ -+#define ARGBASE 12 -+ -+csum_partial_copy_generic_i386: -+ pushl %ebx -+ pushl %edi -+ pushl %esi -+ movl ARGBASE+4(%esp),%esi #src -+ movl ARGBASE+8(%esp),%edi #dst -+ movl ARGBASE+12(%esp),%ecx #len -+ movl ARGBASE+16(%esp),%eax #sum -+# movl %ecx, %edx -+ movl %ecx, %ebx -+ movl %esi, %edx -+ shrl $6, %ecx -+ andl $0x3c, %ebx -+ negl %ebx -+ subl %ebx, %esi -+ subl %ebx, %edi -+ lea -1(%esi),%edx -+ andl $-32,%edx -+ lea 3f(%ebx,%ebx), %ebx -+ testl %esi, %esi -+ jmp *%ebx -+1: addl $64,%esi -+ addl $64,%edi -+ SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl) -+ ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52) -+ ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36) -+ ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20) -+ ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4) -+3: adcl $0,%eax -+ addl $64, %edx -+ dec %ecx -+ jge 1b -+4: movl ARGBASE+12(%esp),%edx #len -+ andl $3, %edx -+ jz 7f -+ cmpl $2, %edx -+ jb 5f -+SRC( movw (%esi), %dx ) -+ leal 2(%esi), %esi -+DST( movw %dx, (%edi) ) -+ leal 2(%edi), %edi -+ je 6f -+ shll $16,%edx -+5: -+SRC( movb (%esi), %dl ) -+DST( movb %dl, (%edi) ) -+6: addl %edx, %eax -+ adcl $0, %eax -+7: -+.section .fixup, "ax" -+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr -+ movl $-EFAULT, (%ebx) -+ # zero the complete destination (computing the rest is too much work) -+ movl ARGBASE+8(%esp),%edi # dst -+ movl ARGBASE+12(%esp),%ecx # len -+ xorl %eax,%eax -+ rep; stosb -+ jmp 7b -+6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr -+ movl $-EFAULT, (%ebx) -+ jmp 7b -+.previous -+ -+ popl %esi -+ popl %edi -+ popl %ebx -+ ret -+ -+#undef ROUND -+#undef ROUND1 -+ -+#endif -Index: linux-2.4.29/arch/um/sys-i386/fault.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/fault.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/fault.c 2005-05-03 22:28:14.583393200 +0300 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <signal.h> -+#include "sysdep/ptrace.h" -+#include "sysdep/sigcontext.h" -+ -+extern unsigned long search_exception_table(unsigned long addr); -+ -+int arch_fixup(unsigned long address, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ unsigned long fixup; -+ -+ fixup = search_exception_table(address); -+ if(fixup != 0){ -+ sc->eip = fixup; -+ return(1); -+ } -+ return(0); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/ksyms.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/ksyms.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/ksyms.c 2005-05-03 22:28:14.584393048 +0300 -@@ -0,0 +1,17 @@ -+#include "linux/module.h" -+#include "linux/in6.h" -+#include "linux/rwsem.h" -+#include "asm/byteorder.h" -+#include "asm/semaphore.h" -+#include "asm/uaccess.h" -+#include "asm/checksum.h" -+#include "asm/errno.h" -+ -+EXPORT_SYMBOL(__down_failed); -+EXPORT_SYMBOL(__down_failed_interruptible); -+EXPORT_SYMBOL(__down_failed_trylock); -+EXPORT_SYMBOL(__up_wakeup); -+ -+/* Networking helper routines. */ -+EXPORT_SYMBOL(csum_partial_copy_from); -+EXPORT_SYMBOL(csum_partial_copy_to); -Index: linux-2.4.29/arch/um/sys-i386/ldt.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/ldt.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/ldt.c 2005-05-03 22:28:14.585392896 +0300 -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/config.h" -+#include "linux/slab.h" -+#include "asm/uaccess.h" -+#include "asm/ptrace.h" -+#include "choose-mode.h" -+#include "kern.h" -+ -+#ifdef CONFIG_MODE_TT -+extern int modify_ldt(int func, void *ptr, unsigned long bytecount); -+ -+/* XXX this needs copy_to_user and copy_from_user */ -+ -+int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount) -+{ -+ if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT); -+ return(modify_ldt(func, ptr, bytecount)); -+} -+#endif -+ -+#ifdef CONFIG_MODE_SKAS -+extern int userspace_pid; -+ -+int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount) -+{ -+ struct ptrace_ldt ldt; -+ void *buf; -+ int res, n; -+ -+ buf = kmalloc(bytecount, GFP_KERNEL); -+ if(buf == NULL) -+ return(-ENOMEM); -+ -+ res = 0; -+ -+ switch(func){ -+ case 1: -+ case 0x11: -+ res = copy_from_user(buf, ptr, bytecount); -+ break; -+ } -+ -+ if(res != 0){ -+ res = -EFAULT; -+ goto out; -+ } -+ -+ ldt = ((struct ptrace_ldt) { .func = func, -+ .ptr = buf, -+ .bytecount = bytecount }); -+ res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt); -+ if(res < 0) -+ goto out; -+ -+ switch(func){ -+ case 0: -+ case 2: -+ n = res; -+ res = copy_to_user(ptr, buf, n); -+ if(res != 0) -+ res = -EFAULT; -+ else -+ res = n; -+ break; -+ } -+ -+ out: -+ kfree(buf); -+ return(res); -+} -+#endif -+ -+int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) -+{ -+ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, -+ ptr, bytecount)); -+} -+ -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/Makefile 2005-05-03 22:28:14.586392744 +0300 -@@ -0,0 +1,46 @@ -+# -+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+# Licensed under the GPL -+# -+ -+O_TARGET = built-in.o -+ -+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o ptrace.o \ -+ ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o -+export-objs = ksyms.o -+ -+USER_OBJS = bugs.o ptrace_user.o sigcontext.o fault.o -+ -+SYMLINKS = semaphore.c extable.c -+ -+semaphore.c-dir = kernel -+extable.c-dir = mm -+ -+include $(TOPDIR)/Rules.make -+ -+$(USER_OBJS) : %.o: %.c -+ $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -+ -+define make_link -+ -rm -f $1 -+ ln -sf $(TOPDIR)/arch/i386/$($1-dir)/$1 $1 -+endef -+ -+$(SYMLINKS): -+ $(call make_link,$@) -+ -+clean: -+ $(MAKE) -C util clean -+ rm -f $(SYMLINKS) -+ -+fastdep: -+ -+dep: -+ -+archmrproper: -+ -+archclean: -+ -+archdep: -+ -+modules: -Index: linux-2.4.29/arch/um/sys-i386/ptrace.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/ptrace.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/ptrace.c 2005-05-03 22:28:14.588392440 +0300 -@@ -0,0 +1,367 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/sched.h" -+#include "asm/elf.h" -+#include "asm/ptrace.h" -+#include "asm/uaccess.h" -+#include "asm/unistd.h" -+#include "ptrace_user.h" -+#include "sysdep/sigcontext.h" -+#include "sysdep/sc.h" -+ -+void arch_switch(void) -+{ -+ update_debugregs(current->thread.arch.debugregs_seq); -+} -+ -+int is_syscall(unsigned long addr) -+{ -+ unsigned short instr; -+ int n; -+ -+ n = copy_from_user(&instr, (void *) addr, sizeof(instr)); -+ if(n){ -+ printk("is_syscall : failed to read instruction from 0x%lx\n", -+ addr); -+ return(0); -+ } -+ /* int 0x80 or sysenter */ -+ return((instr == 0x80cd) || (instr == 0x340f)); -+} -+ -+/* determines which flags the user has access to. */ -+/* 1 = access 0 = no access */ -+#define FLAG_MASK 0x00044dd5 -+ -+int putreg(struct task_struct *child, int regno, unsigned long value) -+{ -+ regno >>= 2; -+ switch (regno) { -+ case FS: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ PT_REGS_FS(&child->thread.regs) = value; -+ return 0; -+ case GS: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ PT_REGS_GS(&child->thread.regs) = value; -+ return 0; -+ case DS: -+ case ES: -+ if (value && (value & 3) != 3) -+ return -EIO; -+ value &= 0xffff; -+ break; -+ case SS: -+ case CS: -+ if ((value & 3) != 3) -+ return -EIO; -+ value &= 0xffff; -+ break; -+ case EFL: -+ value &= FLAG_MASK; -+ value |= PT_REGS_EFLAGS(&child->thread.regs); -+ break; -+ } -+ PT_REGS_SET(&child->thread.regs, regno, value); -+ return 0; -+} -+ -+unsigned long getreg(struct task_struct *child, int regno) -+{ -+ unsigned long retval = ~0UL; -+ -+ regno >>= 2; -+ switch (regno) { -+ case FS: -+ case GS: -+ case DS: -+ case ES: -+ case SS: -+ case CS: -+ retval = 0xffff; -+ /* fall through */ -+ default: -+ retval &= PT_REG(&child->thread.regs, regno); -+ } -+ return retval; -+} -+ -+struct i387_fxsave_struct { -+ unsigned short cwd; -+ unsigned short swd; -+ unsigned short twd; -+ unsigned short fop; -+ long fip; -+ long fcs; -+ long foo; -+ long fos; -+ long mxcsr; -+ long reserved; -+ long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ -+ long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ -+ long padding[56]; -+}; -+ -+/* -+ * FPU tag word conversions. -+ */ -+ -+static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) -+{ -+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */ -+ -+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */ -+ tmp = ~twd; -+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ -+ /* and move the valid bits to the lower byte. */ -+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ -+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ -+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ -+ return tmp; -+} -+ -+static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) -+{ -+ struct _fpxreg *st = NULL; -+ unsigned long twd = (unsigned long) fxsave->twd; -+ unsigned long tag; -+ unsigned long ret = 0xffff0000; -+ int i; -+ -+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); -+ -+ for ( i = 0 ; i < 8 ; i++ ) { -+ if ( twd & 0x1 ) { -+ st = (struct _fpxreg *) FPREG_ADDR( fxsave, i ); -+ -+ switch ( st->exponent & 0x7fff ) { -+ case 0x7fff: -+ tag = 2; /* Special */ -+ break; -+ case 0x0000: -+ if ( !st->significand[0] && -+ !st->significand[1] && -+ !st->significand[2] && -+ !st->significand[3] ) { -+ tag = 1; /* Zero */ -+ } else { -+ tag = 2; /* Special */ -+ } -+ break; -+ default: -+ if ( st->significand[3] & 0x8000 ) { -+ tag = 0; /* Valid */ -+ } else { -+ tag = 2; /* Special */ -+ } -+ break; -+ } -+ } else { -+ tag = 3; /* Empty */ -+ } -+ ret |= (tag << (2 * i)); -+ twd = twd >> 1; -+ } -+ return ret; -+} -+ -+/* -+ * FXSR floating point environment conversions. -+ */ -+ -+#ifdef CONFIG_MODE_TT -+static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, -+ struct pt_regs *regs) -+{ -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned long env[7]; -+ struct _fpreg *to; -+ struct _fpxreg *from; -+ int i; -+ -+ env[0] = (unsigned long)fxsave->cwd | 0xffff0000; -+ env[1] = (unsigned long)fxsave->swd | 0xffff0000; -+ env[2] = twd_fxsr_to_i387(fxsave); -+ env[3] = fxsave->fip; -+ env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); -+ env[5] = fxsave->foo; -+ env[6] = fxsave->fos; -+ -+ if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) ) -+ return 1; -+ -+ to = &buf->_st[0]; -+ from = (struct _fpxreg *) &fxsave->st_space[0]; -+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) { -+ if ( __copy_to_user( to, from, sizeof(*to) ) ) -+ return 1; -+ } -+ return 0; -+} -+#endif -+ -+static inline int convert_fxsr_to_user(struct _fpstate *buf, -+ struct pt_regs *regs) -+{ -+ return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); -+} -+ -+#ifdef CONFIG_MODE_TT -+static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, -+ struct _fpstate *buf) -+{ -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned long env[7]; -+ struct _fpxreg *to; -+ struct _fpreg *from; -+ int i; -+ -+ if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) -+ return 1; -+ -+ fxsave->cwd = (unsigned short)(env[0] & 0xffff); -+ fxsave->swd = (unsigned short)(env[1] & 0xffff); -+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); -+ fxsave->fip = env[3]; -+ fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16); -+ fxsave->fcs = (env[4] & 0xffff); -+ fxsave->foo = env[5]; -+ fxsave->fos = env[6]; -+ -+ to = (struct _fpxreg *) &fxsave->st_space[0]; -+ from = &buf->_st[0]; -+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) { -+ if ( __copy_from_user( to, from, sizeof(*from) ) ) -+ return 1; -+ } -+ return 0; -+} -+#endif -+ -+static inline int convert_fxsr_from_user(struct pt_regs *regs, -+ struct _fpstate *buf) -+{ -+ return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); -+} -+ -+int get_fpregs(unsigned long buf, struct task_struct *child) -+{ -+ int err; -+ -+ err = convert_fxsr_to_user((struct _fpstate *) buf, -+ &child->thread.regs); -+ if(err) return(-EFAULT); -+ else return(0); -+} -+ -+int set_fpregs(unsigned long buf, struct task_struct *child) -+{ -+ int err; -+ -+ err = convert_fxsr_from_user(&child->thread.regs, -+ (struct _fpstate *) buf); -+ if(err) return(-EFAULT); -+ else return(0); -+} -+ -+#ifdef CONFIG_MODE_TT -+int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -+{ -+ struct pt_regs *regs = &tsk->thread.regs; -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ int err; -+ -+ err = __copy_to_user((void *) buf, fxsave, -+ sizeof(struct user_fxsr_struct)); -+ if(err) return -EFAULT; -+ else return 0; -+} -+#endif -+ -+int get_fpxregs(unsigned long buf, struct task_struct *tsk) -+{ -+ return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0)); -+} -+ -+#ifdef CONFIG_MODE_TT -+int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) -+{ -+ struct pt_regs *regs = &tsk->thread.regs; -+ struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ int err; -+ -+ err = __copy_from_user(fxsave, (void *) buf, -+ sizeof(struct user_fxsr_struct) ); -+ if(err) return -EFAULT; -+ else return 0; -+} -+#endif -+ -+int set_fpxregs(unsigned long buf, struct task_struct *tsk) -+{ -+ return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0)); -+} -+ -+#ifdef notdef -+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -+{ -+ fpu->cwd = (((SC_FP_CW(PT_REGS_SC(regs)) & 0xffff) << 16) | -+ (SC_FP_SW(PT_REGS_SC(regs)) & 0xffff)); -+ fpu->swd = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; -+ fpu->twd = SC_FP_IPOFF(PT_REGS_SC(regs)); -+ fpu->fip = SC_FP_CSSEL(PT_REGS_SC(regs)) & 0xffff; -+ fpu->fcs = SC_FP_DATAOFF(PT_REGS_SC(regs)); -+ fpu->foo = SC_FP_DATASEL(PT_REGS_SC(regs)); -+ fpu->fos = 0; -+ memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), -+ sizeof(fpu->st_space)); -+ return(1); -+} -+#endif -+ -+#ifdef CONFIG_MODE_TT -+static inline void copy_fpu_fxsave_tt(struct pt_regs *regs, -+ struct user_i387_struct *buf) -+{ -+ struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs)); -+ unsigned short *to; -+ unsigned short *from; -+ int i; -+ -+ memcpy( buf, fpu, 7 * sizeof(long) ); -+ -+ to = (unsigned short *) &buf->st_space[0]; -+ from = (unsigned short *) &fpu->st_space[0]; -+ for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) { -+ memcpy( to, from, 5 * sizeof(unsigned short) ); -+ } -+} -+#endif -+ -+static inline void copy_fpu_fxsave(struct pt_regs *regs, -+ struct user_i387_struct *buf) -+{ -+ (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0); -+} -+ -+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) -+{ -+ copy_fpu_fxsave(regs, (struct user_i387_struct *) fpu); -+ return(1); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/ptrace_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/ptrace_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/ptrace_user.c 2005-05-03 22:28:14.589392288 +0300 -@@ -0,0 +1,118 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stdio.h> -+#include <errno.h> -+#include <unistd.h> -+#include <linux/stddef.h> -+#include <sys/ptrace.h> -+#include <asm/ptrace.h> -+#include <asm/user.h> -+#include "kern_util.h" -+#include "sysdep/thread.h" -+#include "user.h" -+#include "os.h" -+ -+int ptrace_getregs(long pid, unsigned long *regs_out) -+{ -+ return(ptrace(PTRACE_GETREGS, pid, 0, regs_out)); -+} -+ -+int ptrace_setregs(long pid, unsigned long *regs) -+{ -+ return(ptrace(PTRACE_SETREGS, pid, 0, regs)); -+} -+ -+int ptrace_getfpregs(long pid, unsigned long *regs) -+{ -+ return(ptrace(PTRACE_GETFPREGS, pid, 0, regs)); -+} -+ -+static void write_debugregs(int pid, unsigned long *regs) -+{ -+ struct user *dummy; -+ int nregs, i; -+ -+ dummy = NULL; -+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); -+ for(i = 0; i < nregs; i++){ -+ if((i == 4) || (i == 5)) continue; -+ if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i], -+ regs[i]) < 0) -+ printk("write_debugregs - ptrace failed on " -+ "register %d, value = 0x%x, errno = %d\n", i, -+ regs[i], errno); -+ } -+} -+ -+static void read_debugregs(int pid, unsigned long *regs) -+{ -+ struct user *dummy; -+ int nregs, i; -+ -+ dummy = NULL; -+ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); -+ for(i = 0; i < nregs; i++){ -+ regs[i] = ptrace(PTRACE_PEEKUSER, pid, -+ &dummy->u_debugreg[i], 0); -+ } -+} -+ -+/* Accessed only by the tracing thread */ -+static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 }; -+static int debugregs_seq = 0; -+ -+void arch_enter_kernel(void *task, int pid) -+{ -+ read_debugregs(pid, TASK_DEBUGREGS(task)); -+ write_debugregs(pid, kernel_debugregs); -+} -+ -+void arch_leave_kernel(void *task, int pid) -+{ -+ read_debugregs(pid, kernel_debugregs); -+ write_debugregs(pid, TASK_DEBUGREGS(task)); -+} -+ -+void ptrace_pokeuser(unsigned long addr, unsigned long data) -+{ -+ if((addr < offsetof(struct user, u_debugreg[0])) || -+ (addr > offsetof(struct user, u_debugreg[7]))) -+ return; -+ addr -= offsetof(struct user, u_debugreg[0]); -+ addr = addr >> 2; -+ if(kernel_debugregs[addr] == data) return; -+ -+ kernel_debugregs[addr] = data; -+ debugregs_seq++; -+} -+ -+static void update_debugregs_cb(void *arg) -+{ -+ int pid = *((int *) arg); -+ -+ write_debugregs(pid, kernel_debugregs); -+} -+ -+void update_debugregs(int seq) -+{ -+ int me; -+ -+ if(seq == debugregs_seq) return; -+ -+ me = os_getpid(); -+ initial_thread_cb(update_debugregs_cb, &me); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/sigcontext.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/sigcontext.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/sigcontext.c 2005-05-03 22:28:14.590392136 +0300 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include <stddef.h> -+#include <string.h> -+#include <asm/ptrace.h> -+#include <asm/sigcontext.h> -+#include "sysdep/ptrace.h" -+#include "kern_util.h" -+#include "frame_user.h" -+ -+int sc_size(void *data) -+{ -+ struct arch_frame_data *arch = data; -+ -+ return(sizeof(struct sigcontext) + arch->fpstate_size); -+} -+ -+void sc_to_sc(void *to_ptr, void *from_ptr) -+{ -+ struct sigcontext *to = to_ptr, *from = from_ptr; -+ int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size; -+ -+ memcpy(to, from, size); -+ if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1); -+} -+ -+unsigned long *sc_sigmask(void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ -+ return(&sc->oldmask); -+} -+ -+int sc_get_fpregs(unsigned long buf, void *sc_ptr) -+{ -+ struct sigcontext *sc = sc_ptr; -+ struct _fpstate *from = sc->fpstate, *to = (struct _fpstate *) buf; -+ int err = 0; -+ -+ if(from == NULL){ -+ err |= clear_user_proc(&to->cw, sizeof(to->cw)); -+ err |= clear_user_proc(&to->sw, sizeof(to->sw)); -+ err |= clear_user_proc(&to->tag, sizeof(to->tag)); -+ err |= clear_user_proc(&to->ipoff, sizeof(to->ipoff)); -+ err |= clear_user_proc(&to->cssel, sizeof(to->cssel)); -+ err |= clear_user_proc(&to->dataoff, sizeof(to->dataoff)); -+ err |= clear_user_proc(&to->datasel, sizeof(to->datasel)); -+ err |= clear_user_proc(&to->_st, sizeof(to->_st)); -+ } -+ else { -+ err |= copy_to_user_proc(&to->cw, &from->cw, sizeof(to->cw)); -+ err |= copy_to_user_proc(&to->sw, &from->sw, sizeof(to->sw)); -+ err |= copy_to_user_proc(&to->tag, &from->tag, -+ sizeof(to->tag)); -+ err |= copy_to_user_proc(&to->ipoff, &from->ipoff, -+ sizeof(to->ipoff)); -+ err |= copy_to_user_proc(&to->cssel,& from->cssel, -+ sizeof(to->cssel)); -+ err |= copy_to_user_proc(&to->dataoff, &from->dataoff, -+ sizeof(to->dataoff)); -+ err |= copy_to_user_proc(&to->datasel, &from->datasel, -+ sizeof(to->datasel)); -+ err |= copy_to_user_proc(to->_st, from->_st, sizeof(to->_st)); -+ } -+ return(err); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/syscalls.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/syscalls.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/syscalls.c 2005-05-03 22:28:14.590392136 +0300 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "asm/mman.h" -+#include "asm/uaccess.h" -+#include "asm/unistd.h" -+ -+/* -+ * Perform the select(nd, in, out, ex, tv) and mmap() system -+ * calls. Linux/i386 didn't use to be able to handle more than -+ * 4 system call parameters, so these system calls used a memory -+ * block for parameter passing.. -+ */ -+ -+struct mmap_arg_struct { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+extern int old_mmap(unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long fd, unsigned long offset); -+ -+int old_mmap_i386(struct mmap_arg_struct *arg) -+{ -+ struct mmap_arg_struct a; -+ int err = -EFAULT; -+ -+ if (copy_from_user(&a, arg, sizeof(a))) -+ goto out; -+ -+ err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); -+ out: -+ return err; -+} -+ -+struct sel_arg_struct { -+ unsigned long n; -+ fd_set *inp, *outp, *exp; -+ struct timeval *tvp; -+}; -+ -+int old_select(struct sel_arg_struct *arg) -+{ -+ struct sel_arg_struct a; -+ -+ if (copy_from_user(&a, arg, sizeof(a))) -+ return -EFAULT; -+ /* sys_select() does the appropriate kernel locking */ -+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-i386/sysrq.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/sysrq.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/sysrq.c 2005-05-03 22:28:14.591391984 +0300 -@@ -0,0 +1,30 @@ -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "linux/sched.h" -+#include "asm/ptrace.h" -+#include "sysrq.h" -+ -+void show_regs(struct pt_regs *regs) -+{ -+ printk("\n"); -+ printk("EIP: %04lx:[<%08lx>] CPU: %d %s", -+ 0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs), -+ smp_processor_id(), print_tainted()); -+ if (PT_REGS_CS(regs) & 3) -+ printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs), -+ PT_REGS_SP(regs)); -+ printk(" EFLAGS: %08lx\n %s\n", PT_REGS_EFLAGS(regs), -+ print_tainted()); -+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", -+ PT_REGS_EAX(regs), PT_REGS_EBX(regs), -+ PT_REGS_ECX(regs), -+ PT_REGS_EDX(regs)); -+ printk("ESI: %08lx EDI: %08lx EBP: %08lx", -+ PT_REGS_ESI(regs), PT_REGS_EDI(regs), -+ PT_REGS_EBP(regs)); -+ printk(" DS: %04lx ES: %04lx\n", -+ 0xffff & PT_REGS_DS(regs), -+ 0xffff & PT_REGS_ES(regs)); -+ -+ show_trace((unsigned long *) ®s); -+} -Index: linux-2.4.29/arch/um/sys-i386/util/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/util/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/util/Makefile 2005-05-03 22:28:14.592391832 +0300 -@@ -0,0 +1,28 @@ -+EXE = mk_sc mk_thread -+ -+include $(TOPDIR)/Rules.make -+ -+all : $(EXE) -+ -+mk_sc : mk_sc.o -+ $(HOSTCC) -o mk_sc mk_sc.o -+ -+mk_sc.o : mk_sc.c -+ $(HOSTCC) -c $< -+ -+mk_thread : mk_thread_user.o mk_thread_kern.o -+ $(HOSTCC) -o mk_thread mk_thread_user.o mk_thread_kern.o -+ -+mk_thread_user.o : mk_thread_user.c -+ $(HOSTCC) -c $< -+ -+mk_thread_kern.o : mk_thread_kern.c -+ $(HOSTCC) $(CFLAGS) -c $< -+ -+clean : -+ $(RM) $(EXE) *.o -+ -+archmrproper : clean -+ -+fastdep : -+ -Index: linux-2.4.29/arch/um/sys-i386/util/mk_sc.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/util/mk_sc.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/util/mk_sc.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,52 @@ -+#include <stdio.h> -+#include <signal.h> -+#include <linux/stddef.h> -+ -+#define SC_OFFSET(name, field) \ -+ printf("#define " name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\ -+ offsetof(struct sigcontext, field)) -+ -+#define SC_FP_OFFSET(name, field) \ -+ printf("#define " name \ -+ "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ -+ offsetof(struct _fpstate, field)) -+ -+#define SC_FP_OFFSET_PTR(name, field, type) \ -+ printf("#define " name \ -+ "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ -+ offsetof(struct _fpstate, field)) -+ -+int main(int argc, char **argv) -+{ -+ SC_OFFSET("SC_IP", eip); -+ SC_OFFSET("SC_SP", esp); -+ SC_OFFSET("SC_FS", fs); -+ SC_OFFSET("SC_GS", gs); -+ SC_OFFSET("SC_DS", ds); -+ SC_OFFSET("SC_ES", es); -+ SC_OFFSET("SC_SS", ss); -+ SC_OFFSET("SC_CS", cs); -+ SC_OFFSET("SC_EFLAGS", eflags); -+ SC_OFFSET("SC_EAX", eax); -+ SC_OFFSET("SC_EBX", ebx); -+ SC_OFFSET("SC_ECX", ecx); -+ SC_OFFSET("SC_EDX", edx); -+ SC_OFFSET("SC_EDI", edi); -+ SC_OFFSET("SC_ESI", esi); -+ SC_OFFSET("SC_EBP", ebp); -+ SC_OFFSET("SC_TRAPNO", trapno); -+ SC_OFFSET("SC_ERR", err); -+ SC_OFFSET("SC_CR2", cr2); -+ SC_OFFSET("SC_FPSTATE", fpstate); -+ SC_OFFSET("SC_SIGMASK", oldmask); -+ SC_FP_OFFSET("SC_FP_CW", cw); -+ SC_FP_OFFSET("SC_FP_SW", sw); -+ SC_FP_OFFSET("SC_FP_TAG", tag); -+ SC_FP_OFFSET("SC_FP_IPOFF", ipoff); -+ SC_FP_OFFSET("SC_FP_CSSEL", cssel); -+ SC_FP_OFFSET("SC_FP_DATAOFF", dataoff); -+ SC_FP_OFFSET("SC_FP_DATASEL", datasel); -+ SC_FP_OFFSET_PTR("SC_FP_ST", _st, "struct _fpstate"); -+ SC_FP_OFFSET_PTR("SC_FXSR_ENV", _fxsr_env, "void"); -+ return(0); -+} -Index: linux-2.4.29/arch/um/sys-i386/util/mk_thread_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/util/mk_thread_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/util/mk_thread_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,22 @@ -+#include "linux/config.h" -+#include "linux/stddef.h" -+#include "linux/sched.h" -+ -+extern void print_head(void); -+extern void print_constant_ptr(char *name, int value); -+extern void print_constant(char *name, char *type, int value); -+extern void print_tail(void); -+ -+#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field) -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs)); -+#ifdef CONFIG_MODE_TT -+ print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid)); -+#endif -+ print_tail(); -+ return(0); -+} -+ -Index: linux-2.4.29/arch/um/sys-i386/util/mk_thread_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-i386/util/mk_thread_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-i386/util/mk_thread_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,30 @@ -+#include <stdio.h> -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_thread\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __UM_THREAD_H\n"); -+ printf("#define __UM_THREAD_H\n"); -+ printf("\n"); -+} -+ -+void print_constant_ptr(char *name, int value) -+{ -+ printf("#define %s(task) ((unsigned long *) " -+ "&(((char *) (task))[%d]))\n", name, value); -+} -+ -+void print_constant(char *name, char *type, int value) -+{ -+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, -+ value); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -Index: linux-2.4.29/arch/um/sys-ia64/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ia64/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ia64/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,26 @@ -+OBJ = sys.o -+ -+OBJS = -+ -+all: $(OBJ) -+ -+$(OBJ): $(OBJS) -+ rm -f $@ -+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -+clean: -+ rm -f $(OBJS) -+ -+fastdep: -+ -+archmrproper: -+ -+archclean: -+ rm -f link.ld -+ @$(MAKEBOOT) clean -+ -+archdep: -+ @$(MAKEBOOT) dep -+ -+modules: -+ -+include $(TOPDIR)/Rules.make -Index: linux-2.4.29/arch/um/sys-ppc/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,80 @@ -+OBJ = sys.o -+ -+.S.o: -+ $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ -+OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ -+ ptrace_user.o sysrq.o -+ -+EXTRA_AFLAGS := -DCONFIG_ALL_PPC -I. -I$(TOPDIR)/arch/ppc/kernel -+ -+all: $(OBJ) -+ -+$(OBJ): $(OBJS) -+ rm -f $@ -+ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -+ -+ptrace_user.o: ptrace_user.c -+ $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+sigcontext.o: sigcontext.c -+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< -+ -+semaphore.c: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+checksum.S: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/lib/$@ $@ -+ -+mk_defs.c: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+ppc_defs.head: -+ rm -f $@ -+ ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ -+ -+ppc_defs.h: mk_defs.c ppc_defs.head \ -+ $(TOPDIR)/include/asm-ppc/mmu.h \ -+ $(TOPDIR)/include/asm-ppc/processor.h \ -+ $(TOPDIR)/include/asm-ppc/pgtable.h \ -+ $(TOPDIR)/include/asm-ppc/ptrace.h -+# $(CC) $(CFLAGS) -S mk_defs.c -+ cp ppc_defs.head ppc_defs.h -+# for bk, this way we can write to the file even if it's not checked out -+ echo '#define THREAD 608' >> ppc_defs.h -+ echo '#define PT_REGS 8' >> ppc_defs.h -+ echo '#define CLONE_VM 256' >> ppc_defs.h -+# chmod u+w ppc_defs.h -+# grep '^#define' mk_defs.s >> ppc_defs.h -+# rm mk_defs.s -+ -+# the asm link is horrible, and breaks the other targets. This is also -+# not going to work with parallel makes. -+ -+checksum.o: checksum.S -+ rm -f asm -+ ln -s $(TOPDIR)/include/asm-ppc asm -+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ rm -f asm -+ -+misc.o: misc.S ppc_defs.h -+ rm -f asm -+ ln -s $(TOPDIR)/include/asm-ppc asm -+ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o -+ rm -f asm -+ -+clean: -+ rm -f $(OBJS) -+ rm -f ppc_defs.h -+ rm -f checksum.S semaphore.c mk_defs.c -+ -+fastdep: -+ -+dep: -+ -+modules: -+ -+include $(TOPDIR)/Rules.make -Index: linux-2.4.29/arch/um/sys-ppc/misc.S -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/misc.S 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/misc.S 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,116 @@ -+/* -+ * This file contains miscellaneous low-level functions. -+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) -+ * -+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) -+ * and Paul Mackerras. -+ * -+ * A couple of functions stolen from arch/ppc/kernel/misc.S for UML -+ * by Chris Emerson. -+ * -+ * 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. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <asm/processor.h> -+#include "ppc_asm.h" -+ -+#if defined(CONFIG_4xx) || defined(CONFIG_8xx) -+#define CACHE_LINE_SIZE 16 -+#define LG_CACHE_LINE_SIZE 4 -+#define MAX_COPY_PREFETCH 1 -+#elif !defined(CONFIG_PPC64BRIDGE) -+#define CACHE_LINE_SIZE 32 -+#define LG_CACHE_LINE_SIZE 5 -+#define MAX_COPY_PREFETCH 4 -+#else -+#define CACHE_LINE_SIZE 128 -+#define LG_CACHE_LINE_SIZE 7 -+#define MAX_COPY_PREFETCH 1 -+#endif /* CONFIG_4xx || CONFIG_8xx */ -+ -+ .text -+ -+/* -+ * Clear a page using the dcbz instruction, which doesn't cause any -+ * memory traffic (except to write out any cache lines which get -+ * displaced). This only works on cacheable memory. -+ */ -+_GLOBAL(clear_page) -+ li r0,4096/CACHE_LINE_SIZE -+ mtctr r0 -+#ifdef CONFIG_8xx -+ li r4, 0 -+1: stw r4, 0(r3) -+ stw r4, 4(r3) -+ stw r4, 8(r3) -+ stw r4, 12(r3) -+#else -+1: dcbz 0,r3 -+#endif -+ addi r3,r3,CACHE_LINE_SIZE -+ bdnz 1b -+ blr -+ -+/* -+ * Copy a whole page. We use the dcbz instruction on the destination -+ * to reduce memory traffic (it eliminates the unnecessary reads of -+ * the destination into cache). This requires that the destination -+ * is cacheable. -+ */ -+#define COPY_16_BYTES \ -+ lwz r6,4(r4); \ -+ lwz r7,8(r4); \ -+ lwz r8,12(r4); \ -+ lwzu r9,16(r4); \ -+ stw r6,4(r3); \ -+ stw r7,8(r3); \ -+ stw r8,12(r3); \ -+ stwu r9,16(r3) -+ -+_GLOBAL(copy_page) -+ addi r3,r3,-4 -+ addi r4,r4,-4 -+ li r5,4 -+ -+#ifndef CONFIG_8xx -+#if MAX_COPY_PREFETCH > 1 -+ li r0,MAX_COPY_PREFETCH -+ li r11,4 -+ mtctr r0 -+11: dcbt r11,r4 -+ addi r11,r11,CACHE_LINE_SIZE -+ bdnz 11b -+#else /* MAX_COPY_PREFETCH == 1 */ -+ dcbt r5,r4 -+ li r11,CACHE_LINE_SIZE+4 -+#endif /* MAX_COPY_PREFETCH */ -+#endif /* CONFIG_8xx */ -+ -+ li r0,4096/CACHE_LINE_SIZE -+ mtctr r0 -+1: -+#ifndef CONFIG_8xx -+ dcbt r11,r4 -+ dcbz r5,r3 -+#endif -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 32 -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 64 -+ COPY_16_BYTES -+ COPY_16_BYTES -+#if CACHE_LINE_SIZE >= 128 -+ COPY_16_BYTES -+ COPY_16_BYTES -+ COPY_16_BYTES -+ COPY_16_BYTES -+#endif -+#endif -+#endif -+ bdnz 1b -+ blr -Index: linux-2.4.29/arch/um/sys-ppc/miscthings.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/miscthings.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/miscthings.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,53 @@ -+#include "linux/threads.h" -+#include "linux/stddef.h" // for NULL -+#include "linux/elf.h" // for AT_NULL -+ -+/* The following function nicked from arch/ppc/kernel/process.c and -+ * adapted slightly */ -+/* -+ * XXX ld.so expects the auxiliary table to start on -+ * a 16-byte boundary, so we have to find it and -+ * move it up. :-( -+ */ -+void shove_aux_table(unsigned long sp) -+{ -+ int argc; -+ char *p; -+ unsigned long e; -+ unsigned long aux_start, offset; -+ -+ argc = *(int *)sp; -+ sp += sizeof(int) + (argc + 1) * sizeof(char *); -+ /* skip over the environment pointers */ -+ do { -+ p = *(char **)sp; -+ sp += sizeof(char *); -+ } while (p != NULL); -+ aux_start = sp; -+ /* skip to the end of the auxiliary table */ -+ do { -+ e = *(unsigned long *)sp; -+ sp += 2 * sizeof(unsigned long); -+ } while (e != AT_NULL); -+ offset = ((aux_start + 15) & ~15) - aux_start; -+ if (offset != 0) { -+ do { -+ sp -= sizeof(unsigned long); -+ e = *(unsigned long *)sp; -+ *(unsigned long *)(sp + offset) = e; -+ } while (sp > aux_start); -+ } -+} -+/* END stuff taken from arch/ppc/kernel/process.c */ -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-ppc/ptrace.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/ptrace.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/ptrace.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,28 @@ -+#include "linux/sched.h" -+#include "asm/ptrace.h" -+ -+int putreg(struct task_struct *child, unsigned long regno, -+ unsigned long value) -+{ -+ child->thread.process_regs.regs[regno >> 2] = value; -+ return 0; -+} -+ -+unsigned long getreg(struct task_struct *child, unsigned long regno) -+{ -+ unsigned long retval = ~0UL; -+ -+ retval &= child->thread.process_regs.regs[regno >> 2]; -+ return retval; -+} -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-ppc/ptrace_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/ptrace_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/ptrace_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,40 @@ -+#include <sys/ptrace.h> -+#include <errno.h> -+#include <asm/ptrace.h> -+#include "sysdep/ptrace.h" -+ -+int ptrace_getregs(long pid, unsigned long *regs_out) -+{ -+ int i; -+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { -+ errno = 0; -+ regs_out->regs[i] = ptrace(PTRACE_PEEKUSER, pid, i*4, 0); -+ if (errno) { -+ return -errno; -+ } -+ } -+ return 0; -+} -+ -+int ptrace_setregs(long pid, unsigned long *regs_in) -+{ -+ int i; -+ for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { -+ if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) { -+ if (ptrace(PTRACE_POKEUSER, pid, i*4, regs_in->regs[i]) < 0) { -+ return -errno; -+ } -+ } -+ } -+ return 0; -+} -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-ppc/sigcontext.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/sigcontext.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/sigcontext.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,15 @@ -+#include "asm/ptrace.h" -+#include "asm/sigcontext.h" -+#include "sysdep/ptrace.h" -+#include "user_util.h" -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/sys-ppc/sysrq.c -=================================================================== ---- linux-2.4.29.orig/arch/um/sys-ppc/sysrq.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/sys-ppc/sysrq.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/kernel.h" -+#include "linux/smp.h" -+#include "asm/ptrace.h" -+#include "sysrq.h" -+ -+void show_regs(struct pt_regs_subarch *regs) -+{ -+ printk("\n"); -+ printk("show_regs(): insert regs here.\n"); -+#if 0 -+ printk("\n"); -+ printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs, regs->eip, -+ smp_processor_id()); -+ if (regs->xcs & 3) -+ printk(" ESP: %04x:%08lx",0xffff & regs->xss, regs->esp); -+ printk(" EFLAGS: %08lx\n", regs->eflags); -+ 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); -+#endif -+ -+ show_trace(®s->gpr[1]); -+} -+ -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/arch/um/util/Makefile -=================================================================== ---- linux-2.4.29.orig/arch/um/util/Makefile 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/util/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,26 @@ -+ALL = mk_task mk_constants -+ -+all : $(ALL) -+ -+mk_task : mk_task_user.o mk_task_kern.o -+ $(HOSTCC) -o mk_task mk_task_user.o mk_task_kern.o -+ -+mk_task_user.o : mk_task_user.c -+ $(HOSTCC) -c $< -+ -+mk_task_kern.o : mk_task_kern.c -+ $(HOSTCC) $(CFLAGS) -c $< -+ -+mk_constants : mk_constants_user.o mk_constants_kern.o -+ $(HOSTCC) -o mk_constants mk_constants_user.o mk_constants_kern.o -+ -+mk_constants_user.o : mk_constants_user.c -+ $(HOSTCC) -c $< -+ -+mk_constants_kern.o : mk_constants_kern.c -+ $(HOSTCC) $(CFLAGS) -c $< -+ -+clean : -+ $(RM) $(ALL) *.o *~ -+ -+archmrproper : clean -Index: linux-2.4.29/arch/um/util/mk_constants_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/util/mk_constants_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/util/mk_constants_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,25 @@ -+#include "linux/kernel.h" -+#include "linux/stringify.h" -+#include "asm/page.h" -+ -+extern void print_head(void); -+extern void print_constant_str(char *name, char *value); -+extern void print_constant_int(char *name, int value); -+extern void print_tail(void); -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE); -+ -+ print_constant_str("UM_KERN_EMERG", KERN_EMERG); -+ print_constant_str("UM_KERN_ALERT", KERN_ALERT); -+ print_constant_str("UM_KERN_CRIT", KERN_CRIT); -+ print_constant_str("UM_KERN_ERR", KERN_ERR); -+ print_constant_str("UM_KERN_WARNING", KERN_WARNING); -+ print_constant_str("UM_KERN_NOTICE", KERN_NOTICE); -+ print_constant_str("UM_KERN_INFO", KERN_INFO); -+ print_constant_str("UM_KERN_DEBUG", KERN_DEBUG); -+ print_tail(); -+ return(0); -+} -Index: linux-2.4.29/arch/um/util/mk_constants_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/util/mk_constants_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/util/mk_constants_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,28 @@ -+#include <stdio.h> -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_constants\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __UM_CONSTANTS_H\n"); -+ printf("#define __UM_CONSTANTS_H\n"); -+ printf("\n"); -+} -+ -+void print_constant_str(char *name, char *value) -+{ -+ printf("#define %s \"%s\"\n", name, value); -+} -+ -+void print_constant_int(char *name, int value) -+{ -+ printf("#define %s %d\n", name, value); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -Index: linux-2.4.29/arch/um/util/mk_task_kern.c -=================================================================== ---- linux-2.4.29.orig/arch/um/util/mk_task_kern.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/util/mk_task_kern.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,17 @@ -+#include "linux/sched.h" -+#include "linux/stddef.h" -+ -+extern void print(char *name, char *type, int offset); -+extern void print_ptr(char *name, char *type, int offset); -+extern void print_head(void); -+extern void print_tail(void); -+ -+int main(int argc, char **argv) -+{ -+ print_head(); -+ print_ptr("TASK_REGS", "union uml_pt_regs", -+ offsetof(struct task_struct, thread.regs)); -+ print("TASK_PID", "int", offsetof(struct task_struct, pid)); -+ print_tail(); -+ return(0); -+} -Index: linux-2.4.29/arch/um/util/mk_task_user.c -=================================================================== ---- linux-2.4.29.orig/arch/um/util/mk_task_user.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/arch/um/util/mk_task_user.c 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,30 @@ -+#include <stdio.h> -+ -+void print(char *name, char *type, int offset) -+{ -+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, -+ offset); -+} -+ -+void print_ptr(char *name, char *type, int offset) -+{ -+ printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type, -+ offset); -+} -+ -+void print_head(void) -+{ -+ printf("/*\n"); -+ printf(" * Generated by mk_task\n"); -+ printf(" */\n"); -+ printf("\n"); -+ printf("#ifndef __TASK_H\n"); -+ printf("#define __TASK_H\n"); -+ printf("\n"); -+} -+ -+void print_tail(void) -+{ -+ printf("\n"); -+ printf("#endif\n"); -+} -Index: linux-2.4.29/CREDITS -=================================================================== ---- linux-2.4.29.orig/CREDITS 2005-05-03 21:08:24.000000000 +0300 -+++ linux-2.4.29/CREDITS 2005-05-03 22:28:14.000000000 +0300 -@@ -434,6 +434,7 @@ - E: lars@nocrew.org - W: http://lars.nocrew.org/ - D: dsp56k device driver -+D: ptrace proxy in user mode kernel port - S: Kopmansg 2 - S: 411 13 Goteborg - S: Sweden -@@ -727,7 +728,7 @@ - E: jdike@karaya.com - W: http://user-mode-linux.sourceforge.net - D: User mode kernel port --S: RR1 Box 67C -+S: 375 Tubbs Hill Rd - S: Deering NH 03244 - S: USA - -Index: linux-2.4.29/Documentation/Configure.help -=================================================================== ---- linux-2.4.29.orig/Documentation/Configure.help 2005-05-03 21:09:27.000000000 +0300 -+++ linux-2.4.29/Documentation/Configure.help 2005-05-03 23:55:57.615290736 +0300 -@@ -16184,6 +16184,63 @@ - The module will be called speedtch.o. If you want to compile it as - a module, say M here and read <file:Documentation/modules.txt>. - -+Support for /proc/mm -+CONFIG_PROC_MM -+ Enables support for address space separation through /proc/mm. -+ A host kernel needs to have this enabled in order for UML to -+ run in skas mode. UML kernels do not need to have this option -+ unless they will host sub-UMLs. -+ -+ If you don't know what this does just say Y. -+ -+Separate Kernel Address Space support -+CONFIG_MODE_SKAS -+ This option controls whether skas (separate kernel address space) -+ support is compiled in. If you have applied the skas patch to the -+ host and enabled support for /proc/mm in the host kernel, then you -+ certainly want to say Y here (and consider saying N to -+ CONFIG_MODE_TT). Otherwise, it is safe to say Y. Disabling this -+ option will shrink the UML binary slightly. -+ -+Tracing thread support -+CONFIG_MODE_TT -+ This option controls whether tracing thread support is compiled -+ into UML. Normally, this should be set to Y. If you intend to -+ use only skas mode (and the host has the skas patch applied to it), -+ then it is OK to say N here. -+ -+Force a static link -+CONFIG_STATIC_LINK -+ If CONFIG_MODE_TT is disabled, then this option gives you the ability -+ to force a static link of UML. Normally, if only skas mode is built -+ in to UML, it will be linked as a shared binary. This is inconvenient -+ for use in a chroot jail. So, if you intend to run UML inside a -+ chroot, and you disable CONFIG_MODE_TT, you probably want to say Y -+ here. -+ -+2G/2G host address space split -+CONFIG_HOST_2G_2G -+ Most Linux machines are configured so that the kernel occupies the -+ upper 1G of the 4G address space and processes use the lower 3G. -+ However, some machine are configured with a 2G/2G split, with the -+ kernel occupying the upper 2G and processes using the lower 2G. -+ -+ To allow UML to run on a such host you have to say Y here. N should be -+ a safe choice most of the time. -+ -+Kernel stack size order -+CONFIG_KERNEL_STACK_ORDER -+ This option determines the size of UML kernel stacks. They will -+ be 1 << order pages. The default is OK unless you're running Valgrind -+ on UML, in which case, set this to 3. -+ -+UML ubd block driver -+CONFIG_BLK_DEV_UBD -+ The User-Mode Linux port includes a driver called UBD which will let -+ you access arbitrary files on the host computer as block devices. -+ Unless you know that you do not need such virtual block devices say -+ Y here. -+ - CONFIG_USB_GADGET - USB is a master/slave protocol, organized with one master - host (such as a PC) controlling up to 127 peripheral devices. -@@ -16289,17 +16346,15 @@ - - Always do synchronous disk IO for UBD - CONFIG_BLK_DEV_UBD_SYNC -- The User-Mode Linux port includes a driver called UBD which will let -- you access arbitrary files on the host computer as block devices. -- Writes to such a block device are not immediately written to the -- host's disk; this may cause problems if, for example, the User-Mode -- Linux 'Virtual Machine' uses a journalling file system and the host -- computer crashes. -+ Writes to the virtual block device are not immediately written to the host's -+ disk; this may cause problems if, for example, the User-Mode Linux -+ 'Virtual Machine' uses a journalling filesystem and the host computer -+ crashes. - - Synchronous operation (i.e. always writing data to the host's disk - immediately) is configurable on a per-UBD basis by using a special - kernel command line option. Alternatively, you can say Y here to -- turn on synchronous operation by default for all block. -+ turn on synchronous operation by default for all block devices. - - If you're running a journalling file system (like reiserfs, for - example) in your virtual machine, you will want to say Y here. If -@@ -16311,6 +16366,7 @@ - CONFIG_PT_PROXY - This option enables a debugging interface which allows gdb to debug - the kernel without needing to actually attach to kernel threads. -+ CONFIG_XTERM_CHAN must be enabled in order to enable CONFIG_PT_PROXY. - If you want to do kernel debugging, say Y here; otherwise say N. - - Management console -@@ -16357,6 +16413,9 @@ - See <http://user-mode-linux.sourceforge.net/gprof.html> for more - details. - -+ This option requires that CONFIG_MODE_TT be disabled, as UML will -+ not build with both enabled. -+ - If you're involved in UML kernel development and want to use gprof, - say Y. If you're unsure, say N. - -@@ -16380,6 +16439,19 @@ - If you'd like to be able to work with files stored on the host, - say Y or M here; otherwise say N. - -+HoneyPot ProcFS -+CONFIG_HPPFS -+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc -+ entries to be overridden, removed, or fabricated from the host. -+ Its purpose is to allow a UML to appear to be a physical machine -+ by removing or changing anything in /proc which gives away the -+ identity of a UML. -+ -+ See <http://user-mode-linux.sf.net/hppfs.html> for more information. -+ -+ You only need this if you are setting up a UML honeypot. Otherwise, -+ it is safe to say 'N' here. -+ - Example IO Memory driver - CONFIG_MMAPPER - The User-Mode Linux port can provide support for IO Memory -@@ -16395,6 +16467,21 @@ - If you'd like to be able to provide a simulated IO port space for - User-Mode Linux processes, say Y. If unsure, say N. - -+Anonymous Memory support -+CONFIG_DEV_ANON -+ Don't ask. Just say Y. -+ -+Support for software watchdog inside UML -+CONFIG_UML_WATCHDOG -+ Support for a virtual hardware watchdog. It's safe to say N here. -+ -+COW block device -+CONFIG_COW -+ This is a layered driver which sits above two other block devices. -+ One is read-only, and the other is a read-write layer which stores -+ all changes. This provides the illusion that the read-only layer -+ can be mounted read-write and changed. -+ - Virtual Serial Line - CONFIG_SSL - The User-Mode Linux environment allows you to create virtual serial -@@ -16505,26 +16592,197 @@ - - SLIP transport - CONFIG_UML_NET_SLIP -- The Slip User-Mode Linux network transport allows a running UML to -+ The slip User-Mode Linux network transport allows a running UML to - network with its host over a point-to-point link. Unlike Ethertap, - which can carry any Ethernet frame (and hence even non-IP packets), -- the Slip transport can only carry IP packets. -+ the slip transport can only carry IP packets. - -- To use this, your host must support Slip devices. -+ To use this, your host must support slip devices. - - For more information, see - <http://user-mode-linux.sourceforge.net/networking.html>. That site -- has examples of the UML command line to use to enable Slip -+ has examples of the UML command line to use to enable slip - networking, and details of a few quirks with it. - -- The Ethertap Transport is preferred over Slip because of its -- limitation. If you prefer Slip, however, say Y here. Otherwise -+ The Ethertap Transport is preferred over slip because of its -+ limitations. If you prefer slip, however, say Y here. Otherwise - choose the Multicast transport (to network multiple UMLs on - multiple hosts), Ethertap (to network with the host and the - outside world), and/or the Daemon transport (to network multiple - UMLs on a single host). You may choose more than one without - conflict. If you don't need UML networking, say N. - -+SLiRP transport -+CONFIG_UML_NET_SLIRP -+ The SLiRP User-Mode Linux network transport allows a running UML -+ to network by invoking a program that can handle SLIP encapsulated -+ packets. This is commonly (but not limited to) the application -+ known as SLiRP, a program that can re-socket IP packets back onto -+ the host on which it is run. Only IP packets are supported, -+ unlike other network transports that can handle all Ethernet -+ frames. In general, slirp allows the UML the same IP connectivity -+ to the outside world that the host user is permitted, and unlike -+ other transports, SLiRP works without the need of root level -+ privleges, setuid binaries, or SLIP devices on the host. This -+ also means not every type of connection is possible, but most -+ situations can be accomodated with carefully crafted slirp -+ commands that can be passed along as part of the network device's -+ setup string. The effect of this transport on the UML is similar -+ that of a host behind a firewall that masquerades all network -+ connections passing through it (but is less secure). -+ -+ To use this you should first have slirp compiled somewhere -+ accessible on the host, and have read its documentation. If you -+ don't need UML networking, say N. -+ -+ Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp" -+ -+pcap transport -+CONFIG_UML_NET_PCAP -+ The pcap transport makes a pcap packet stream on the host look -+ like an ethernet device inside UML. This is useful for making -+ UML act as a network monitor for the host. You must have libcap -+ installed in order to build the pcap transport into UML. -+ -+ For more information, see -+ <http://user-mode-linux.sourceforge.net/networking.html> That site -+ has examples of the UML command line to use to enable this option. -+ -+ If you intend to use UML as a network monitor for the host, say -+ Y here. Otherwise, say N. -+ -+Default main console channel initialization -+CONFIG_CON_ZERO_CHAN -+ This is the string describing the channel to which the main console -+ will be attached by default. This value can be overridden from the -+ command line. The default value is "fd:0,fd:1", which attaches the -+ main console to stdin and stdout. -+ It is safe to leave this unchanged. -+ -+Default console channel initialization -+CONFIG_CON_CHAN -+ This is the string describing the channel to which all consoles -+ except the main console will be attached by default. This value can -+ be overridden from the command line. The default value is "xterm", -+ which brings them up in xterms. -+ It is safe to leave this unchanged, although you may wish to change -+ this if you expect the UML that you build to be run in environments -+ which don't have X or xterm available. -+ -+Default serial line channel initialization -+CONFIG_SSL_CHAN -+ This is the string describing the channel to which the serial lines -+ will be attached by default. This value can be overridden from the -+ command line. The default value is "pty", which attaches them to -+ traditional pseudo-terminals. -+ It is safe to leave this unchanged, although you may wish to change -+ this if you expect the UML that you build to be run in environments -+ which don't have a set of /dev/pty* devices. -+ -+Nesting level -+CONFIG_NEST_LEVEL -+ This is set to the number of layers of UMLs that this UML will be run -+ in. Normally, this is zero, meaning that it will run directly on the -+ host. Setting it to one will build a UML that can run inside a UML -+ that is running on the host. Generally, if you intend this UML to run -+ inside another UML, set CONFIG_NEST_LEVEL to one more than the host UML. -+ Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to -+ greater than one, then the guest UML should have its CONFIG_NEST_LEVEL -+ set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS. -+ Only change this if you are running nested UMLs. -+ -+Kernel address space size (in .5G units) -+CONFIG_KERNEL_HALF_GIGS -+ This determines the amount of address space that UML will allocate for -+ its own, measured in half Gigabyte units. The default is 1. -+ Change this only if you need to boot UML with an unusually large amount -+ of physical memory. -+ -+UML sound support -+CONFIG_UML_SOUND -+ This option enables UML sound support. If enabled, it will pull in -+ soundcore and the UML hostaudio relay, which acts as a intermediary -+ between the host's dsp and mixer devices and the UML sound system. -+ It is safe to say 'Y' here. -+ -+UML SMP support -+CONFIG_UML_SMP -+ This option enables UML SMP support. UML implements virtual SMP by -+ allowing as many processes to run simultaneously on the host as -+ there are virtual processors configured. Obviously, if the host is -+ a uniprocessor, those processes will timeshare, but, inside UML, -+ will appear to be running simultaneously. If the host is a -+ multiprocessor, then UML processes may run simultaneously, depending -+ on the host scheduler. -+ CONFIG_SMP will be set to whatever this option is set to. -+ It is safe to leave this unchanged. -+ -+file descriptor channel support -+CONFIG_FD_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to already set up file descriptors. Generally, the main -+ console is attached to file descriptors 0 and 1 (stdin and stdout), -+ so it would be wise to leave this enabled unless you intend to -+ attach it to some other host device. -+ -+null device channel support -+CONFIG_NULL_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to a device similar to /dev/null. Data written to it disappears -+ and there is never any data to be read. -+ -+port channel support -+CONFIG_PORT_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host portals. They may be accessed with 'telnet <host> -+ <port number>'. Any number of consoles and serial lines may be -+ attached to a single portal, although what UML device you get when -+ you telnet to that portal will be unpredictable. -+ It is safe to say 'Y' here. -+ -+pty channel support -+CONFIG_PTY_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host pseudo-terminals. Access to both traditional -+ pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled -+ with this option. The assignment of UML devices to host devices -+ will be announced in the kernel message log. -+ It is safe to say 'Y' here. -+ -+tty channel support -+CONFIG_TTY_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to host terminals. Access to both virtual consoles -+ (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and -+ /dev/pts/*) are controlled by this option. -+ It is safe to say 'Y' here. -+ -+xterm channel support -+CONFIG_XTERM_CHAN -+ This option enables support for attaching UML consoles and serial -+ lines to xterms. Each UML device so assigned will be brought up in -+ its own xterm. -+ If you disable this option, then CONFIG_PT_PROXY will be disabled as -+ well, since UML's gdb currently requires an xterm. -+ It is safe to say 'Y' here. -+ -+tty logging -+CONFIG_TTY_LOG -+ This option enables logging of all data going through pseudo-terminals -+ to the host. This is primarily useful for honeypots, where you want -+ secure keystroke logging that can't be detected or disabled by root. -+ Say 'N' unless you are setting up a UML honeypot or otherwise know that -+ you want this option. -+ -+UML real-time clock support -+CONFIG_UML_REAL_TIME_CLOCK -+ This option ties the UML clock to the host clock, so that time passes at -+ the same rate as on the host, regardless of how much CPU time the UML is -+ getting. This should normally be enabled. The exception would be if you're -+ debugging UML. In this case, time spent staring at the debugger with UML -+ stopped will cause lots of timer ticks to be backed up, and UML will spent -+ lots of time calling the timer when it is finally continued. -+ - Microtek USB scanner support - CONFIG_USB_MICROTEK - Say Y here if you want support for the Microtek X6USB and -Index: linux-2.4.29/drivers/char/Makefile -=================================================================== ---- linux-2.4.29.orig/drivers/char/Makefile 2005-05-03 21:09:35.000000000 +0300 -+++ linux-2.4.29/drivers/char/Makefile 2005-05-03 22:28:14.000000000 +0300 -@@ -114,6 +114,12 @@ - endif - endif - -+ifeq ($(ARCH),um) -+ KEYMAP = -+ KEYBD = -+ CONSOLE = -+endif -+ - ifeq ($(ARCH),sh) - KEYMAP = - KEYBD = -Index: linux-2.4.29/drivers/char/mem.c -=================================================================== ---- linux-2.4.29.orig/drivers/char/mem.c 2005-05-03 21:07:25.000000000 +0300 -+++ linux-2.4.29/drivers/char/mem.c 2005-05-03 22:28:14.000000000 +0300 -@@ -220,7 +220,7 @@ - ssize_t read = 0; - ssize_t virtr = 0; - char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ -- -+ - if (p < (unsigned long) high_memory) { - read = count; - if (count > (unsigned long) high_memory - p) -@@ -292,6 +292,8 @@ - wrote = (unsigned long) high_memory - p; - - wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos); -+ if(wrote < 0) -+ return(wrote); - - p += wrote; - buf += wrote; -@@ -664,6 +666,8 @@ - write: write_full, - }; - -+extern struct file_operations anon_file_operations; -+ - static int memory_open(struct inode * inode, struct file * filp) - { - switch (MINOR(inode->i_rdev)) { -@@ -693,6 +697,9 @@ - case 9: - filp->f_op = &urandom_fops; - break; -+ case 10: -+ filp->f_op = &anon_file_operations; -+ break; - default: - return -ENXIO; - } -@@ -719,7 +726,8 @@ - {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, - {7, "full", S_IRUGO | S_IWUGO, &full_fops}, - {8, "random", S_IRUGO | S_IWUSR, &random_fops}, -- {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops} -+ {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, -+ {10, "anon", S_IRUGO | S_IWUSR, &anon_file_operations}, - }; - int i; - -Index: linux-2.4.29/drivers/char/n_tty.c -=================================================================== ---- linux-2.4.29.orig/drivers/char/n_tty.c 2005-05-03 21:05:08.000000000 +0300 -+++ linux-2.4.29/drivers/char/n_tty.c 2005-05-03 22:28:14.000000000 +0300 -@@ -25,9 +25,11 @@ - * who actually finally proved there really was a race. - * - * 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to -- * waiting writing processes-Sapan Bhatia <sapan@corewars.org>. -- * Also fixed a bug in BLOCKING mode where write_chan returns -- * EAGAIN -+ * waiting writing processes-Sapan Bhatia <sapan@corewars.org> -+ * -+ * 2002/03/19 Fixed write_chan to stay put if console driver returns -+ * EAGAIN and not return since it returns an EAGAIN in a -+ * non-blocking operation-Sapan Bhatia <sapan@corewars.org> - */ - - #include <linux/types.h> -@@ -1393,9 +1395,9 @@ - if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { - while (nr > 0) { - ssize_t num = opost_block(tty, b, nr); -- if (num < 0) { -- if (num == -EAGAIN) -- break; -+ if (num < 0){ -+ if(num == -EAGAIN) -+ break; - retval = num; - goto break_out; - } -Index: linux-2.4.29/drivers/char/tty_io.c -=================================================================== ---- linux-2.4.29.orig/drivers/char/tty_io.c 2005-05-03 21:07:50.000000000 +0300 -+++ linux-2.4.29/drivers/char/tty_io.c 2005-05-03 22:28:14.000000000 +0300 -@@ -967,6 +967,23 @@ - tty_wakeup(tty); - } - -+#ifdef CONFIG_TTY_LOG -+ -+int (*open_log)(void *, void *) = NULL; -+int (*write_log)(int, const char *, int, void *, int) = NULL; -+void (*close_log)(int, void *) = NULL; -+ -+void register_tty_logger(int (*opener)(void *, void *), -+ int (*writer)(int, const char *, int, void *, int), -+ void (*closer)(int, void *)) -+{ -+ open_log = opener; -+ write_log = writer; -+ close_log = closer; -+} -+ -+#endif -+ - static ssize_t tty_read(struct file * file, char * buf, size_t count, - loff_t *ppos) - { -@@ -1012,8 +1029,13 @@ - i = -EIO; - tty_ldisc_deref(ld); - unlock_kernel(); -- if (i > 0) -+ if (i > 0){ - inode->i_atime = CURRENT_TIME; -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd >= 0) && (write_log != NULL)) -+ (*write_log)(tty->log_fd, buf, i, tty, 1); -+#endif -+ } - return i; - } - -@@ -1067,6 +1089,10 @@ - if (written) { - file->f_dentry->d_inode->i_mtime = CURRENT_TIME; - ret = written; -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd >= 0) && (write_log != NULL)) -+ (*write_log)(tty->log_fd, buf - ret, ret, tty, 0); -+#endif - } - up(&tty->atomic_write); - return ret; -@@ -1662,6 +1688,11 @@ - tty_set_termios_ldisc(o_tty,N_TTY); - } - -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd >= 0) && (close_log != NULL)) -+ (*close_log)(tty->log_fd, tty); -+#endif -+ - /* - * The release_mem function takes care of the details of clearing - * the slots and preserving the termios structure. -@@ -1820,6 +1851,11 @@ - nr_warns++; - } - } -+ -+#ifdef CONFIG_TTY_LOG -+ if((tty->log_fd < 0) && (open_log != NULL)) -+ tty->log_fd = (*open_log)(tty, current->tty); -+#endif - return 0; - } - -@@ -2467,6 +2503,9 @@ - spin_lock_init(&tty->read_lock); - INIT_LIST_HEAD(&tty->tty_files); - INIT_TQUEUE(&tty->SAK_tq, 0, 0); -+#ifdef CONFIG_TTY_LOG -+ tty->log_fd = -1; -+#endif - } - - /* -Index: linux-2.4.29/drivers/net/setup.c -=================================================================== ---- linux-2.4.29.orig/drivers/net/setup.c 2005-05-03 21:09:27.000000000 +0300 -+++ linux-2.4.29/drivers/net/setup.c 2005-05-03 22:28:14.000000000 +0300 -@@ -28,7 +28,6 @@ - extern int lmc_setup(void); - - extern int madgemc_probe(void); --extern int uml_net_probe(void); - - /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ - #define __PAD6 "\0\0\0\0\0\0\0\0\0" -@@ -103,9 +102,6 @@ - #ifdef CONFIG_MADGEMC - {madgemc_probe, 0}, - #endif --#ifdef CONFIG_UML_NET -- {uml_net_probe, 0}, --#endif - - {NULL, 0}, - }; -Index: linux-2.4.29/fs/bad_inode.c -=================================================================== ---- linux-2.4.29.orig/fs/bad_inode.c 2005-05-03 21:05:44.000000000 +0300 -+++ linux-2.4.29/fs/bad_inode.c 2005-05-03 22:28:14.000000000 +0300 -@@ -83,6 +83,7 @@ - - void make_bad_inode(struct inode * inode) - { -+ inode->i_state = 0; - inode->i_mode = S_IFREG; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_op = &bad_inode_ops; -Index: linux-2.4.29/include/asm-i386/hardirq.h -=================================================================== ---- linux-2.4.29.orig/include/asm-i386/hardirq.h 2005-05-03 21:08:39.000000000 +0300 -+++ linux-2.4.29/include/asm-i386/hardirq.h 2005-05-03 23:41:09.908242720 +0300 -@@ -4,6 +4,7 @@ - #include <linux/config.h> - #include <linux/threads.h> - #include <linux/irq.h> -+#include <asm/processor.h> /* for cpu_relax */ - - /* assembly code in softirq.h is sensitive to the offsets of these fields */ - typedef struct { -Index: linux-2.4.29/include/asm-um/a.out.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/a.out.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/a.out.h 2005-05-03 22:28:14.909343648 +0300 -@@ -0,0 +1,20 @@ -+#ifndef __UM_A_OUT_H -+#define __UM_A_OUT_H -+ -+#include "linux/config.h" -+#include "asm/arch/a.out.h" -+#include "choose-mode.h" -+ -+#undef STACK_TOP -+ -+extern unsigned long stacksizelim; -+ -+extern unsigned long host_task_size; -+ -+#define STACK_ROOM (stacksizelim) -+ -+extern int honeypot; -+#define STACK_TOP \ -+ CHOOSE_MODE((honeypot ? host_task_size : task_size), task_size) -+ -+#endif -Index: linux-2.4.29/include/asm-um/archparam-i386.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/archparam-i386.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/archparam-i386.h 2005-05-03 22:28:14.911343344 +0300 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_ARCHPARAM_I386_H -+#define __UM_ARCHPARAM_I386_H -+ -+/********* Bits for asm-um/elf.h ************/ -+ -+#include "user.h" -+ -+#define ELF_PLATFORM "i586" -+ -+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) -+ -+typedef struct user_i387_struct elf_fpregset_t; -+typedef unsigned long elf_greg_t; -+ -+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+#define ELF_DATA ELFDATA2LSB -+#define ELF_ARCH EM_386 -+ -+#define ELF_PLAT_INIT(regs, load_addr) do { \ -+ PT_REGS_EBX(regs) = 0; \ -+ PT_REGS_ECX(regs) = 0; \ -+ PT_REGS_EDX(regs) = 0; \ -+ PT_REGS_ESI(regs) = 0; \ -+ PT_REGS_EDI(regs) = 0; \ -+ PT_REGS_EBP(regs) = 0; \ -+ PT_REGS_EAX(regs) = 0; \ -+} while(0) -+ -+/* Shamelessly stolen from include/asm-i386/elf.h */ -+ -+#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ -+ pr_reg[0] = PT_REGS_EBX(regs); \ -+ pr_reg[1] = PT_REGS_ECX(regs); \ -+ pr_reg[2] = PT_REGS_EDX(regs); \ -+ pr_reg[3] = PT_REGS_ESI(regs); \ -+ pr_reg[4] = PT_REGS_EDI(regs); \ -+ pr_reg[5] = PT_REGS_EBP(regs); \ -+ pr_reg[6] = PT_REGS_EAX(regs); \ -+ pr_reg[7] = PT_REGS_DS(regs); \ -+ pr_reg[8] = PT_REGS_ES(regs); \ -+ /* fake once used fs and gs selectors? */ \ -+ pr_reg[9] = PT_REGS_DS(regs); \ -+ pr_reg[10] = PT_REGS_DS(regs); \ -+ pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \ -+ pr_reg[12] = PT_REGS_IP(regs); \ -+ pr_reg[13] = PT_REGS_CS(regs); \ -+ pr_reg[14] = PT_REGS_EFLAGS(regs); \ -+ pr_reg[15] = PT_REGS_SP(regs); \ -+ pr_reg[16] = PT_REGS_SS(regs); \ -+} while(0); -+ -+/********* Bits for asm-um/delay.h **********/ -+ -+typedef unsigned long um_udelay_t; -+ -+/********* Nothing for asm-um/hardirq.h **********/ -+ -+/********* Nothing for asm-um/hw_irq.h **********/ -+ -+/********* Nothing for asm-um/string.h **********/ -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/archparam-ppc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/archparam-ppc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/archparam-ppc.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,41 @@ -+#ifndef __UM_ARCHPARAM_PPC_H -+#define __UM_ARCHPARAM_PPC_H -+ -+/********* Bits for asm-um/elf.h ************/ -+ -+#define ELF_PLATFORM (0) -+ -+#define ELF_ET_DYN_BASE (0x08000000) -+ -+/* the following stolen from asm-ppc/elf.h */ -+#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ -+#define ELF_NFPREG 33 /* includes fpscr */ -+/* General registers */ -+typedef unsigned long elf_greg_t; -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+/* Floating point registers */ -+typedef double elf_fpreg_t; -+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -+ -+#define ELF_DATA ELFDATA2MSB -+#define ELF_ARCH EM_PPC -+ -+/********* Bits for asm-um/delay.h **********/ -+ -+typedef unsigned int um_udelay_t; -+ -+/********* Bits for asm-um/hw_irq.h **********/ -+ -+struct hw_interrupt_type; -+ -+/********* Bits for asm-um/hardirq.h **********/ -+ -+#define irq_enter(cpu, irq) hardirq_enter(cpu) -+#define irq_exit(cpu, irq) hardirq_exit(cpu) -+ -+/********* Bits for asm-um/string.h **********/ -+ -+#define __HAVE_ARCH_STRRCHR -+ -+#endif -Index: linux-2.4.29/include/asm-um/arch-signal-i386.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/arch-signal-i386.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/arch-signal-i386.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_ARCH_SIGNAL_I386_H -+#define __UM_ARCH_SIGNAL_I386_H -+ -+struct arch_signal_context { -+ unsigned long extrasigs[_NSIG_WORDS]; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/atomic.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/atomic.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/atomic.h 2005-05-03 23:41:08.099517688 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_ATOMIC_H -+#define __UM_ATOMIC_H -+ -+#include "asm/arch/atomic.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/bitops.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/bitops.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/bitops.h 2005-05-03 23:41:08.093518600 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BITOPS_H -+#define __UM_BITOPS_H -+ -+#include "asm/arch/bitops.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/boot.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/boot.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/boot.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BOOT_H -+#define __UM_BOOT_H -+ -+#include "asm/arch/boot.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/bugs.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/bugs.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/bugs.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BUGS_H -+#define __UM_BUGS_H -+ -+void check_bugs(void); -+ -+#endif -Index: linux-2.4.29/include/asm-um/byteorder.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/byteorder.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/byteorder.h 2005-05-03 22:37:45.347623848 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_BYTEORDER_H -+#define __UM_BYTEORDER_H -+ -+#include "asm/arch/byteorder.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/cache.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/cache.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/cache.h 2005-05-03 22:28:14.917342432 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_CACHE_H -+#define __UM_CACHE_H -+ -+#define L1_CACHE_BYTES 32 -+ -+#endif -Index: linux-2.4.29/include/asm-um/checksum.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/checksum.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/checksum.h 2005-05-03 22:28:14.917342432 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_CHECKSUM_H -+#define __UM_CHECKSUM_H -+ -+#include "sysdep/checksum.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/cobalt.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/cobalt.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/cobalt.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_COBALT_H -+#define __UM_COBALT_H -+ -+#include "asm/arch/cobalt.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/current.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/current.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/current.h 2005-05-03 23:41:08.083520120 +0300 -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_CURRENT_H -+#define __UM_CURRENT_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include "linux/config.h" -+#include "asm/page.h" -+ -+struct task_struct; -+ -+#define CURRENT_TASK(dummy) (((unsigned long) &dummy) & \ -+ (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER)) -+ -+#define current ({ int dummy; (struct task_struct *) CURRENT_TASK(dummy); }) -+ -+#endif /* __ASSEMBLY__ */ -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/delay.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/delay.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/delay.h 2005-05-03 22:28:14.919342128 +0300 -@@ -0,0 +1,7 @@ -+#ifndef __UM_DELAY_H -+#define __UM_DELAY_H -+ -+#include "asm/arch/delay.h" -+#include "asm/archparam.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/desc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/desc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/desc.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_DESC_H -+#define __UM_DESC_H -+ -+#include "asm/arch/desc.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/div64.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/div64.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/div64.h 2005-05-03 22:28:14.941338784 +0300 -@@ -0,0 +1,6 @@ -+#ifndef _UM_DIV64_H -+#define _UM_DIV64_H -+ -+#include "asm/arch/div64.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/dma.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/dma.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/dma.h 2005-05-03 22:37:48.244183504 +0300 -@@ -0,0 +1,10 @@ -+#ifndef __UM_DMA_H -+#define __UM_DMA_H -+ -+#include "asm/io.h" -+ -+extern unsigned long uml_physmem; -+ -+#define MAX_DMA_ADDRESS (uml_physmem) -+ -+#endif -Index: linux-2.4.29/include/asm-um/elf.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/elf.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/elf.h 2005-05-03 22:28:14.943338480 +0300 -@@ -0,0 +1,18 @@ -+#ifndef __UM_ELF_H -+#define __UM_ELF_H -+ -+#include "asm/archparam.h" -+ -+#define ELF_HWCAP (0) -+ -+#define SET_PERSONALITY(ex, ibcs2) do ; while(0) -+ -+#define ELF_EXEC_PAGESIZE 4096 -+ -+#define elf_check_arch(x) (1) -+ -+#define ELF_CLASS ELFCLASS32 -+ -+#define USE_ELF_CORE_DUMP -+ -+#endif -Index: linux-2.4.29/include/asm-um/errno.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/errno.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/errno.h 2005-05-03 22:28:14.944338328 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_ERRNO_H -+#define __UM_ERRNO_H -+ -+#include "asm/arch/errno.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/fcntl.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/fcntl.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/fcntl.h 2005-05-03 22:28:14.945338176 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_FCNTL_H -+#define __UM_FCNTL_H -+ -+#include "asm/arch/fcntl.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/fixmap.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/fixmap.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/fixmap.h 2005-05-03 23:41:11.208045120 +0300 -@@ -0,0 +1,89 @@ -+#ifndef __UM_FIXMAP_H -+#define __UM_FIXMAP_H -+ -+#include <linux/config.h> -+#include <asm/kmap_types.h> -+ -+/* -+ * Here we define all the compile-time 'special' virtual -+ * addresses. The point is to have a constant address at -+ * compile time, but to set the physical address only -+ * in the boot process. We allocate these special addresses -+ * from the end of virtual memory (0xfffff000) backwards. -+ * Also this lets us do fail-safe vmalloc(), we -+ * can guarantee that these special addresses and -+ * vmalloc()-ed addresses never overlap. -+ * -+ * these 'compile-time allocated' memory buffers are -+ * fixed-size 4k pages. (or larger if used with an increment -+ * highger than 1) use fixmap_set(idx,phys) to associate -+ * physical memory with fixmap indices. -+ * -+ * TLB entries of such buffers will not be flushed across -+ * task switches. -+ */ -+ -+/* -+ * on UP currently we will have no trace of the fixmap mechanizm, -+ * no page table allocations, etc. This might change in the -+ * future, say framebuffers for the console driver(s) could be -+ * fix-mapped? -+ */ -+enum fixed_addresses { -+#ifdef CONFIG_HIGHMEM -+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ -+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, -+#endif -+ __end_of_fixed_addresses -+}; -+ -+extern void __set_fixmap (enum fixed_addresses idx, -+ unsigned long phys, pgprot_t flags); -+ -+#define set_fixmap(idx, phys) \ -+ __set_fixmap(idx, phys, PAGE_KERNEL) -+/* -+ * Some hardware wants to get fixmapped without caching. -+ */ -+#define set_fixmap_nocache(idx, phys) \ -+ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) -+/* -+ * used by vmalloc.c. -+ * -+ * Leave one empty page between vmalloc'ed areas and -+ * the start of the fixmap, and leave one page empty -+ * at the top of mem.. -+ */ -+extern unsigned long get_kmem_end(void); -+ -+#define FIXADDR_TOP (get_kmem_end() - 0x2000) -+#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) -+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) -+ -+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) -+ -+extern void __this_fixmap_does_not_exist(void); -+ -+/* -+ * 'index to address' translation. If anyone tries to use the idx -+ * directly without tranlation, we catch the bug with a NULL-deference -+ * kernel oops. Illegal ranges of incoming indices are caught too. -+ */ -+static inline unsigned long fix_to_virt(const unsigned int idx) -+{ -+ /* -+ * this branch gets completely eliminated after inlining, -+ * except when someone tries to use fixaddr indices in an -+ * illegal way. (such as mixing up address types or using -+ * out-of-range indices). -+ * -+ * If it doesn't get removed, the linker will complain -+ * loudly with a reasonably clear error message.. -+ */ -+ if (idx >= __end_of_fixed_addresses) -+ __this_fixmap_does_not_exist(); -+ -+ return __fix_to_virt(idx); -+} -+ -+#endif -Index: linux-2.4.29/include/asm-um/floppy.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/floppy.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/floppy.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_FLOPPY_H -+#define __UM_FLOPPY_H -+ -+#include "asm/arch/floppy.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/hardirq.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/hardirq.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/hardirq.h 2005-05-03 23:41:09.909242568 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_HARDIRQ_H -+#define __UM_HARDIRQ_H -+ -+#include "asm/arch/hardirq.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/hdreg.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/hdreg.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/hdreg.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_HDREG_H -+#define __UM_HDREG_H -+ -+#include "asm/arch/hdreg.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/highmem.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/highmem.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/highmem.h 2005-05-03 23:41:11.210044816 +0300 -@@ -0,0 +1,12 @@ -+#ifndef __UM_HIGHMEM_H -+#define __UM_HIGHMEM_H -+ -+#include "asm/page.h" -+#include "asm/fixmap.h" -+#include "asm/arch/highmem.h" -+ -+#undef PKMAP_BASE -+ -+#define PKMAP_BASE ((FIXADDR_START - LAST_PKMAP * PAGE_SIZE) & PMD_MASK) -+ -+#endif -Index: linux-2.4.29/include/asm-um/hw_irq.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/hw_irq.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/hw_irq.h 2005-05-03 22:37:48.105204632 +0300 -@@ -0,0 +1,10 @@ -+#ifndef _ASM_UM_HW_IRQ_H -+#define _ASM_UM_HW_IRQ_H -+ -+#include "asm/irq.h" -+#include "asm/archparam.h" -+ -+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) -+{} -+ -+#endif -Index: linux-2.4.29/include/asm-um/ide.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ide.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ide.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IDE_H -+#define __UM_IDE_H -+ -+#include "asm/arch/ide.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/init.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/init.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/init.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,11 @@ -+#ifndef _UM_INIT_H -+#define _UM_INIT_H -+ -+#ifdef notdef -+#define __init -+#define __initdata -+#define __initfunc(__arginit) __arginit -+#define __cacheline_aligned -+#endif -+ -+#endif -Index: linux-2.4.29/include/asm-um/ioctl.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ioctl.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ioctl.h 2005-05-03 22:28:14.952337112 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IOCTL_H -+#define __UM_IOCTL_H -+ -+#include "asm/arch/ioctl.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/ioctls.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ioctls.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ioctls.h 2005-05-03 22:37:45.509599224 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IOCTLS_H -+#define __UM_IOCTLS_H -+ -+#include "asm/arch/ioctls.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/io.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/io.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/io.h 2005-05-03 22:37:48.176193840 +0300 -@@ -0,0 +1,25 @@ -+#ifndef __UM_IO_H -+#define __UM_IO_H -+ -+#include "asm/page.h" -+ -+#define IO_SPACE_LIMIT 0xdeadbeef /* Sure hope nothing uses this */ -+ -+static inline int inb(unsigned long i) { return(0); } -+static inline void outb(char c, unsigned long i) { } -+ -+/* -+ * Change virtual addresses to physical addresses and vv. -+ * These are pretty trivial -+ */ -+static inline unsigned long virt_to_phys(volatile void * address) -+{ -+ return __pa((void *) address); -+} -+ -+static inline void * phys_to_virt(unsigned long address) -+{ -+ return __va(address); -+} -+ -+#endif -Index: linux-2.4.29/include/asm-um/ipcbuf.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ipcbuf.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ipcbuf.h 2005-05-03 22:28:14.954336808 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IPCBUF_H -+#define __UM_IPCBUF_H -+ -+#include "asm/arch/ipcbuf.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/ipc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ipc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ipc.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_IPC_H -+#define __UM_IPC_H -+ -+#include "asm/arch/ipc.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/irq.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/irq.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/irq.h 2005-05-03 22:28:14.956336504 +0300 -@@ -0,0 +1,23 @@ -+#ifndef __UM_IRQ_H -+#define __UM_IRQ_H -+ -+#define TIMER_IRQ 0 -+#define UMN_IRQ 1 -+#define CONSOLE_IRQ 2 -+#define CONSOLE_WRITE_IRQ 3 -+#define UBD_IRQ 4 -+#define UM_ETH_IRQ 5 -+#define SSL_IRQ 6 -+#define SSL_WRITE_IRQ 7 -+#define ACCEPT_IRQ 8 -+#define MCONSOLE_IRQ 9 -+#define WINCH_IRQ 10 -+#define SIGIO_WRITE_IRQ 11 -+#define TELNETD_IRQ 12 -+#define XTERM_IRQ 13 -+#define HUMFS_IRQ 14 -+ -+#define LAST_IRQ HUMFS_IRQ -+#define NR_IRQS (LAST_IRQ + 1) -+ -+#endif -Index: linux-2.4.29/include/asm-um/keyboard.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/keyboard.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/keyboard.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_KEYBOARD_H -+#define __UM_KEYBOARD_H -+ -+#include "asm/arch/keyboard.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/kmap_types.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/kmap_types.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/kmap_types.h 2005-05-03 22:28:14.957336352 +0300 -@@ -0,0 +1,11 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_KMAP_TYPES_H -+#define __UM_KMAP_TYPES_H -+ -+#include "asm/arch/kmap_types.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/linux_logo.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/linux_logo.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/linux_logo.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_LINUX_LOGO_H -+#define __UM_LINUX_LOGO_H -+ -+#include "asm/arch/linux_logo.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/locks.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/locks.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/locks.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_LOCKS_H -+#define __UM_LOCKS_H -+ -+#include "asm/arch/locks.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/mca_dma.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/mca_dma.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/mca_dma.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef mca___UM_DMA_H -+#define mca___UM_DMA_H -+ -+#include "asm/arch/mca_dma.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/mman.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/mman.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/mman.h 2005-05-03 22:28:14.961335744 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MMAN_H -+#define __UM_MMAN_H -+ -+#include "asm/arch/mman.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/mmu_context.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/mmu_context.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/mmu_context.h 2005-05-03 23:41:09.000000000 +0300 -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_MMU_CONTEXT_H -+#define __UM_MMU_CONTEXT_H -+ -+#include "linux/sched.h" -+#include "choose-mode.h" -+ -+#define get_mmu_context(task) do ; while(0) -+#define activate_context(tsk) do ; while(0) -+ -+static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) -+{ -+} -+ -+extern void switch_mm_skas(int mm_fd); -+ -+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, -+ struct task_struct *tsk, unsigned cpu) -+{ -+ if(prev != next){ -+ clear_bit(cpu, &prev->cpu_vm_mask); -+ set_bit(cpu, &next->cpu_vm_mask); -+ if(next != &init_mm) -+ CHOOSE_MODE((void) 0, -+ switch_mm_skas(next->context.skas.mm_fd)); -+ } -+} -+ -+static inline void enter_lazy_tlb(struct mm_struct *mm, -+ struct task_struct *tsk, unsigned cpu) -+{ -+} -+ -+extern int init_new_context_skas(struct task_struct *task, -+ struct mm_struct *mm); -+ -+static inline int init_new_context_tt(struct task_struct *task, -+ struct mm_struct *mm) -+{ -+ return(0); -+} -+ -+static inline int init_new_context(struct task_struct *task, -+ struct mm_struct *mm) -+{ -+ return(CHOOSE_MODE_PROC(init_new_context_tt, init_new_context_skas, -+ task, mm)); -+} -+ -+extern void destroy_context_skas(struct mm_struct *mm); -+ -+static inline void destroy_context(struct mm_struct *mm) -+{ -+ CHOOSE_MODE((void) 0, destroy_context_skas(mm)); -+} -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/mmu.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/mmu.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/mmu.h 2005-05-03 22:28:14.962335592 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __MMU_H -+#define __MMU_H -+ -+#include "um_mmu.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/module.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/module.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/module.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MODULE_H -+#define __UM_MODULE_H -+ -+#include "asm/arch/module.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/msgbuf.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/msgbuf.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/msgbuf.h 2005-05-03 22:28:14.964335288 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MSGBUF_H -+#define __UM_MSGBUF_H -+ -+#include "asm/arch/msgbuf.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/mtrr.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/mtrr.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/mtrr.h 2005-05-03 22:37:48.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_MTRR_H -+#define __UM_MTRR_H -+ -+#include "asm/arch/mtrr.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/namei.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/namei.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/namei.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_NAMEI_H -+#define __UM_NAMEI_H -+ -+#include "asm/arch/namei.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/page.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/page.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/page.h 2005-05-03 22:37:45.335625672 +0300 -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PAGE_H -+#define __UM_PAGE_H -+ -+struct page; -+ -+#include "asm/arch/page.h" -+ -+#undef BUG -+#undef PAGE_BUG -+#undef __pa -+#undef __va -+#undef virt_to_page -+#undef VALID_PAGE -+#undef PAGE_OFFSET -+#undef KERNELBASE -+ -+extern unsigned long uml_physmem; -+ -+#define PAGE_OFFSET (uml_physmem) -+#define KERNELBASE PAGE_OFFSET -+ -+#ifndef __ASSEMBLY__ -+ -+extern void stop(void); -+ -+#define BUG() do { \ -+ panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ -+} while (0) -+ -+#define PAGE_BUG(page) do { \ -+ BUG(); \ -+} while (0) -+ -+#endif /* __ASSEMBLY__ */ -+ -+#define __va_space (8*1024*1024) -+ -+extern unsigned long to_phys(void *virt); -+extern void *to_virt(unsigned long phys); -+ -+#define __pa(virt) to_phys((void *) virt) -+#define __va(phys) to_virt((unsigned long) phys) -+ -+#define VALID_PAGE(page) ((page - mem_map) < max_mapnr) -+ -+extern struct page *arch_validate(struct page *page, int mask, int order); -+#define HAVE_ARCH_VALIDATE -+ -+extern void arch_free_page(struct page *page, int order); -+#define HAVE_ARCH_FREE_PAGE -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/page_offset.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/page_offset.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/page_offset.h 2005-05-03 22:28:14.967334832 +0300 -@@ -0,0 +1 @@ -+#define PAGE_OFFSET_RAW (uml_physmem) -Index: linux-2.4.29/include/asm-um/param.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/param.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/param.h 2005-05-03 22:28:14.968334680 +0300 -@@ -0,0 +1,22 @@ -+#ifndef _UM_PARAM_H -+#define _UM_PARAM_H -+ -+#define HZ 100 -+ -+#define EXEC_PAGESIZE 4096 -+ -+#ifndef NGROUPS -+#define NGROUPS 32 -+#endif -+ -+#ifndef NOGROUP -+#define NOGROUP (-1) -+#endif -+ -+#define MAXHOSTNAMELEN 64 /* max length of hostname */ -+ -+#ifdef __KERNEL__ -+# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */ -+#endif -+ -+#endif -Index: linux-2.4.29/include/asm-um/pci.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/pci.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/pci.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_PCI_H -+#define __UM_PCI_H -+ -+#define PCI_DMA_BUS_IS_PHYS (1) -+ -+#endif -Index: linux-2.4.29/include/asm-um/pgalloc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/pgalloc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/pgalloc.h 2005-05-03 23:41:11.209044968 +0300 -@@ -0,0 +1,164 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PGALLOC_H -+#define __UM_PGALLOC_H -+ -+#include "linux/config.h" -+#include "linux/mm.h" -+#include "asm/fixmap.h" -+#include "choose-mode.h" -+ -+#define pgd_quicklist (current_cpu_data.pgd_quick) -+#define pmd_quicklist (current_cpu_data.pmd_quick) -+#define pte_quicklist (current_cpu_data.pte_quick) -+#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) -+ -+#define pmd_populate(mm, pmd, pte) set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) -+ -+/* -+ * Allocate and free page tables. -+ */ -+ -+static inline pgd_t *get_pgd_slow_tt(void) -+{ -+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); -+ -+ if (pgd) { -+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -+ memcpy(pgd + USER_PTRS_PER_PGD, -+ swapper_pg_dir + USER_PTRS_PER_PGD, -+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); -+ } -+ return pgd; -+} -+ -+static inline pgd_t *get_pgd_slow_skas(void) -+{ -+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL); -+ -+ if (pgd) -+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); -+ return pgd; -+} -+ -+static inline pgd_t *get_pgd_slow(void) -+{ -+ return(CHOOSE_MODE(get_pgd_slow_tt(), get_pgd_slow_skas())); -+} -+ -+static inline pgd_t *get_pgd_fast(void) -+{ -+ unsigned long *ret; -+ -+ ret = pgd_quicklist; -+ if (ret != NULL) { -+ pgd_quicklist = (unsigned long *)(*ret); -+ ret[0] = 0; -+ pgtable_cache_size--; -+ } else -+ ret = (unsigned long *)get_pgd_slow(); -+ return (pgd_t *)ret; -+} -+ -+static inline void free_pgd_fast(pgd_t *pgd) -+{ -+ *(unsigned long *)pgd = (unsigned long) pgd_quicklist; -+ pgd_quicklist = (unsigned long *) pgd; -+ pgtable_cache_size++; -+} -+ -+static inline void free_pgd_slow(pgd_t *pgd) -+{ -+ free_page((unsigned long)pgd); -+} -+ -+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) -+{ -+ pte_t *pte; -+ -+ pte = (pte_t *) __get_free_page(GFP_KERNEL); -+ if (pte) -+ clear_page(pte); -+ return pte; -+} -+ -+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address) -+{ -+ unsigned long *ret; -+ -+ ret = (unsigned long *)pte_quicklist; -+ if (ret != NULL) { -+ pte_quicklist = (unsigned long *)(*ret); -+ ret[0] = ret[1]; -+ pgtable_cache_size--; -+ } -+ return (pte_t *)ret; -+} -+ -+static inline void pte_free_fast(pte_t *pte) -+{ -+ *(unsigned long *)pte = (unsigned long) pte_quicklist; -+ pte_quicklist = (unsigned long *) pte; -+ pgtable_cache_size++; -+} -+ -+static inline void pte_free_slow(pte_t *pte) -+{ -+ free_page((unsigned long)pte); -+} -+ -+#define pte_free(pte) pte_free_fast(pte) -+#define pgd_free(pgd) free_pgd_slow(pgd) -+#define pgd_alloc(mm) get_pgd_fast() -+ -+/* -+ * allocating and freeing a pmd is trivial: the 1-entry pmd is -+ * inside the pgd, so has no extra memory associated with it. -+ */ -+ -+#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); }) -+#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) -+#define pmd_free_slow(x) do { } while (0) -+#define pmd_free_fast(x) do { } while (0) -+#define pmd_free(x) do { } while (0) -+#define pgd_populate(mm, pmd, pte) BUG() -+ -+/* -+ * TLB flushing: -+ * -+ * - flush_tlb() flushes the current mm struct TLBs -+ * - flush_tlb_all() flushes all processes TLBs -+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's -+ * - flush_tlb_page(vma, vmaddr) flushes one page -+ * - flush_tlb_kernel_vm() flushes the kernel vm area -+ * - flush_tlb_range(mm, start, end) flushes a range of pages -+ * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables -+ */ -+ -+extern void flush_tlb_all(void); -+extern void flush_tlb_mm(struct mm_struct *mm); -+extern void flush_tlb_range(struct mm_struct *mm, unsigned long start, -+ unsigned long end); -+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -+extern void flush_tlb_kernel_vm(void); -+ -+static inline void flush_tlb_pgtables(struct mm_struct *mm, -+ unsigned long start, unsigned long end) -+{ -+} -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/pgtable.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/pgtable.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/pgtable.h 2005-05-03 23:41:09.906243024 +0300 -@@ -0,0 +1,413 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Derived from include/asm-i386/pgtable.h -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PGTABLE_H -+#define __UM_PGTABLE_H -+ -+#include "linux/sched.h" -+#include "asm/processor.h" -+#include "asm/page.h" -+ -+extern pgd_t swapper_pg_dir[1024]; -+ -+#define flush_cache_all() do ; while (0) -+#define flush_cache_mm(mm) do ; while (0) -+#define flush_cache_range(vma, start, end) do ; while (0) -+#define flush_cache_page(vma, vmaddr) do ; while (0) -+#define flush_page_to_ram(page) do ; while (0) -+#define flush_dcache_page(page) do ; while (0) -+#define flush_icache_range(from, to) do ; while (0) -+#define flush_icache_page(vma,pg) do ; while (0) -+#define flush_icache_user_range(vma,pg,adr,len) do ; while (0) -+ -+extern void __flush_tlb_one(unsigned long addr); -+ -+extern void pte_free(pte_t *pte); -+ -+extern void pgd_free(pgd_t *pgd); -+ -+extern int do_check_pgt_cache(int, int); -+ -+extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt, -+ pte_t *pte_out); -+ -+/* zero page used for uninitialized stuff */ -+extern unsigned long *empty_zero_page; -+ -+#define pgtable_cache_init() do ; while (0) -+ -+/* PMD_SHIFT determines the size of the area a second-level page table can map */ -+#define PMD_SHIFT 22 -+#define PMD_SIZE (1UL << PMD_SHIFT) -+#define PMD_MASK (~(PMD_SIZE-1)) -+ -+/* PGDIR_SHIFT determines what a third-level page table entry can map */ -+#define PGDIR_SHIFT 22 -+#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -+#define PGDIR_MASK (~(PGDIR_SIZE-1)) -+ -+/* -+ * entries per page directory level: the i386 is two-level, so -+ * we don't really have any PMD directory physically. -+ */ -+#define PTRS_PER_PTE 1024 -+#define PTRS_PER_PMD 1 -+#define PTRS_PER_PGD 1024 -+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) -+#define FIRST_USER_PGD_NR 0 -+ -+#define pte_ERROR(e) \ -+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -+#define pmd_ERROR(e) \ -+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) -+#define pgd_ERROR(e) \ -+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) -+ -+/* -+ * pgd entries used up by user/kernel: -+ */ -+ -+#define USER_PGD_PTRS (TASK_SIZE >> PGDIR_SHIFT) -+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) -+ -+#ifndef __ASSEMBLY__ -+/* Just any arbitrary offset to the start of the vmalloc VM area: the -+ * current 8MB value just means that there will be a 8MB "hole" after the -+ * physical memory until the kernel virtual memory starts. That means that -+ * any out-of-bounds memory accesses will hopefully be caught. -+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced -+ * area for the same reason. ;) -+ */ -+ -+extern unsigned long end_iomem; -+ -+#define VMALLOC_OFFSET (__va_space) -+#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -+#define VMALLOC_VMADDR(x) ((unsigned long)(x)) -+ -+#if CONFIG_HIGHMEM -+# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) -+#else -+# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) -+#endif -+ -+#define _PAGE_PRESENT 0x001 -+#define _PAGE_NEWPAGE 0x002 -+#define _PAGE_PROTNONE 0x004 /* If not present */ -+#define _PAGE_RW 0x008 -+#define _PAGE_USER 0x010 -+#define _PAGE_ACCESSED 0x020 -+#define _PAGE_DIRTY 0x040 -+#define _PAGE_NEWPROT 0x080 -+ -+#define REGION_MASK 0xf0000000 -+#define REGION_SHIFT 28 -+ -+#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -+#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) -+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -+ -+#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) -+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) -+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED) -+ -+/* -+ * The i386 can't do page protection for execute, and considers that the same are read. -+ * Also, write permissions imply read permissions. This is the closest we can get.. -+ */ -+#define __P000 PAGE_NONE -+#define __P001 PAGE_READONLY -+#define __P010 PAGE_COPY -+#define __P011 PAGE_COPY -+#define __P100 PAGE_READONLY -+#define __P101 PAGE_READONLY -+#define __P110 PAGE_COPY -+#define __P111 PAGE_COPY -+ -+#define __S000 PAGE_NONE -+#define __S001 PAGE_READONLY -+#define __S010 PAGE_SHARED -+#define __S011 PAGE_SHARED -+#define __S100 PAGE_READONLY -+#define __S101 PAGE_READONLY -+#define __S110 PAGE_SHARED -+#define __S111 PAGE_SHARED -+ -+/* -+ * Define this if things work differently on an i386 and an i486: -+ * it will (on an i486) warn about kernel memory accesses that are -+ * done without a 'verify_area(VERIFY_WRITE,..)' -+ */ -+#undef TEST_VERIFY_AREA -+ -+/* page table for 0-4MB for everybody */ -+extern unsigned long pg0[1024]; -+ -+/* -+ * BAD_PAGETABLE is used when we need a bogus page-table, while -+ * BAD_PAGE is used for a bogus page. -+ * -+ * ZERO_PAGE is a global shared page that is always zero: used -+ * for zero-mapped memory areas etc.. -+ */ -+extern pte_t __bad_page(void); -+extern pte_t * __bad_pagetable(void); -+ -+#define BAD_PAGETABLE __bad_pagetable() -+#define BAD_PAGE __bad_page() -+ -+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) -+ -+/* number of bits that fit into a memory pointer */ -+#define BITS_PER_PTR (8*sizeof(unsigned long)) -+ -+/* to align the pointer to a pointer address */ -+#define PTR_MASK (~(sizeof(void*)-1)) -+ -+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ -+/* 64-bit machines, beware! SRB. */ -+#define SIZEOF_PTR_LOG2 2 -+ -+/* to find an entry in a page-table */ -+#define PAGE_PTR(address) \ -+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) -+ -+#define pte_none(x) !(pte_val(x) & ~_PAGE_NEWPAGE) -+#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) -+ -+#define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0) -+ -+#define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE)) -+#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) -+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) -+#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0) -+ -+#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) -+#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) -+ -+/* -+ * The "pgd_xxx()" functions here are trivial for a folded two-level -+ * setup: the pgd is never bad, and a pmd always exists (as it's folded -+ * into the pgd entry) -+ */ -+static inline int pgd_none(pgd_t pgd) { return 0; } -+static inline int pgd_bad(pgd_t pgd) { return 0; } -+static inline int pgd_present(pgd_t pgd) { return 1; } -+static inline void pgd_clear(pgd_t * pgdp) { } -+ -+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -+ -+#define pte_page(pte) virt_to_page(__va(pte_val(pte))) -+#define pmd_page(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) -+ -+extern struct page *phys_to_page(const unsigned long phys); -+extern struct page *__virt_to_page(const unsigned long virt); -+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr) -+ -+static inline pte_t pte_mknewprot(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_NEWPROT; -+ return(pte); -+} -+ -+static inline pte_t pte_mknewpage(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_NEWPAGE; -+ return(pte); -+} -+ -+static inline void set_pte(pte_t *pteptr, pte_t pteval) -+{ -+ /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so -+ * fix_range knows to unmap it. _PAGE_NEWPROT is specific to -+ * mapped pages. -+ */ -+ *pteptr = pte_mknewpage(pteval); -+ if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr); -+} -+ -+/* -+ * (pmds are folded into pgds so this doesnt get actually called, -+ * but the define is needed for a generic inline function.) -+ */ -+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) -+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval) -+ -+/* -+ * The following only work if pte_present() is true. -+ * Undefined behaviour if not.. -+ */ -+static inline int pte_read(pte_t pte) -+{ -+ return((pte_val(pte) & _PAGE_USER) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_exec(pte_t pte){ -+ return((pte_val(pte) & _PAGE_USER) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_write(pte_t pte) -+{ -+ return((pte_val(pte) & _PAGE_RW) && -+ !(pte_val(pte) & _PAGE_PROTNONE)); -+} -+ -+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -+static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; } -+static inline int pte_newprot(pte_t pte) -+{ -+ return(pte_present(pte) && (pte_val(pte) & _PAGE_NEWPROT)); -+} -+ -+static inline pte_t pte_rdprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_exprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkclean(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_DIRTY; -+ return(pte); -+} -+ -+static inline pte_t pte_mkold(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_ACCESSED; -+ return(pte); -+} -+ -+static inline pte_t pte_wrprotect(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_RW; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkread(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkexec(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_USER; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkdirty(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_DIRTY; -+ return(pte); -+} -+ -+static inline pte_t pte_mkyoung(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_ACCESSED; -+ return(pte); -+} -+ -+static inline pte_t pte_mkwrite(pte_t pte) -+{ -+ pte_val(pte) |= _PAGE_RW; -+ return(pte_mknewprot(pte)); -+} -+ -+static inline pte_t pte_mkuptodate(pte_t pte) -+{ -+ pte_val(pte) &= ~_PAGE_NEWPAGE; -+ if(pte_present(pte)) pte_val(pte) &= ~_PAGE_NEWPROT; -+ return(pte); -+} -+ -+extern unsigned long page_to_phys(struct page *page); -+ -+/* -+ * Conversion functions: convert a page and protection to a page entry, -+ * and a page entry and page directory to the page they refer to. -+ */ -+ -+extern pte_t mk_pte(struct page *page, pgprot_t pgprot); -+ -+/* This takes a physical page address that is used by the remapping -+ * functions -+ */ -+#define mk_pte_phys(phys, pgprot) \ -+ (pte_mknewpage(mk_pte(virt_to_page(__va(phys)), pgprot))) -+ -+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -+{ -+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); -+ if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte)); -+ return pte; -+} -+ -+/* to find an entry in a page-table-directory. */ -+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -+#define __pgd_offset(address) pgd_index(address) -+ -+/* to find an entry in a page-table-directory */ -+#define pgd_offset(mm, address) \ -+((mm)->pgd + ((address) >> PGDIR_SHIFT)) -+ -+/* to find an entry in a kernel page-table-directory */ -+#define pgd_offset_k(address) pgd_offset(&init_mm, address) -+ -+#define __pmd_offset(address) \ -+ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -+ -+/* Find an entry in the second-level page table.. */ -+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -+{ -+ return (pmd_t *) dir; -+} -+ -+/* Find an entry in the third-level page table.. */ -+#define pte_offset(pmd, address) \ -+ ((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2)))) -+ -+#define update_mmu_cache(vma,address,pte) do ; while (0) -+ -+/* Encode and de-code a swap entry */ -+#define SWP_TYPE(x) (((x).val >> 3) & 0x7f) -+#define SWP_OFFSET(x) ((x).val >> 10) -+ -+#define SWP_ENTRY(type, offset) \ -+ ((swp_entry_t) { ((type) << 3) | ((offset) << 10) }) -+#define pte_to_swp_entry(pte) \ -+ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) -+#define swp_entry_to_pte(x) ((pte_t) { (x).val }) -+ -+#define PageSkip(x) (0) -+#define kern_addr_valid(addr) (1) -+ -+#include <asm-generic/pgtable.h> -+ -+#endif -+ -+#endif -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/poll.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/poll.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/poll.h 2005-05-03 22:28:14.973333920 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_POLL_H -+#define __UM_POLL_H -+ -+#include "asm/arch/poll.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/posix_types.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/posix_types.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/posix_types.h 2005-05-03 22:28:14.974333768 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_POSIX_TYPES_H -+#define __UM_POSIX_TYPES_H -+ -+#include "asm/arch/posix_types.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/processor-generic.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/processor-generic.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/processor-generic.h 2005-05-03 23:41:08.094518448 +0300 -@@ -0,0 +1,183 @@ -+/* -+ * Copyright (C) 2000 - 2004 Jeff Dike (jdike@addtoit.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PROCESSOR_GENERIC_H -+#define __UM_PROCESSOR_GENERIC_H -+ -+struct pt_regs; -+ -+struct task_struct; -+ -+#include "linux/config.h" -+#include "linux/signal.h" -+#include "asm/ptrace.h" -+#include "asm/siginfo.h" -+#include "choose-mode.h" -+ -+struct mm_struct; -+ -+#define current_text_addr() ((void *) 0) -+ -+#define cpu_relax() do ; while (0) -+ -+struct thread_struct { -+ int forking; -+ int nsyscalls; -+ struct pt_regs regs; -+ unsigned long cr2; -+ int err; -+ unsigned long trap_no; -+ int singlestep_syscall; -+ void *fault_addr; -+ void *fault_catcher; -+ struct task_struct *prev_sched; -+ unsigned long temp_stack; -+ void *exec_buf; -+ struct arch_thread arch; -+ union { -+#ifdef CONFIG_MODE_TT -+ struct { -+ int extern_pid; -+ int tracing; -+ /* XXX This is really two filehandles, but they contain -+ * lists, and list.h includes processor.h through -+ * prefetch.h before defining struct list, so this -+ * makes the lists' sizes unknown at this point. -+ * So, this is a void *, and allocated separately. -+ * Check to see if this is fixed in 2.6. -+ */ -+ void *switch_pipe; -+ int singlestep_syscall; -+ int vm_seq; -+ } tt; -+#endif -+#ifdef CONFIG_MODE_SKAS -+ struct { -+ void *switch_buf; -+ void *fork_buf; -+ int mm_count; -+ } skas; -+#endif -+ } mode; -+ struct { -+ int op; -+ union { -+ struct { -+ int pid; -+ } fork, exec; -+ struct { -+ int (*proc)(void *); -+ void *arg; -+ } thread; -+ struct { -+ void (*proc)(void *); -+ void *arg; -+ } cb; -+ } u; -+ } request; -+}; -+ -+#define INIT_THREAD \ -+{ \ -+ .forking = 0, \ -+ .nsyscalls = 0, \ -+ .regs = EMPTY_REGS, \ -+ .cr2 = 0, \ -+ .err = 0, \ -+ .fault_addr = NULL, \ -+ .prev_sched = NULL, \ -+ .temp_stack = 0, \ -+ .exec_buf = NULL, \ -+ .arch = INIT_ARCH_THREAD, \ -+ .request = { 0 } \ -+} -+ -+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -+ -+typedef struct { -+ unsigned long seg; -+} mm_segment_t; -+ -+extern struct task_struct *alloc_task_struct(void); -+extern void free_task_struct(struct task_struct *task); -+ -+#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) -+ -+extern void release_thread(struct task_struct *); -+extern int arch_kernel_thread(int (*fn)(void *), void * arg, -+ unsigned long flags); -+extern void dump_thread(struct pt_regs *regs, struct user *u); -+ -+extern unsigned long thread_saved_pc(struct thread_struct *t); -+ -+static inline void mm_copy_segments(struct mm_struct *from_mm, -+ struct mm_struct *new_mm) -+{ -+} -+ -+static inline void copy_segments(struct task_struct *p, -+ struct mm_struct *new_mm) -+{ -+} -+ -+static inline void release_segments(struct mm_struct *mm) -+{ -+} -+ -+#define init_task (init_task_union.task) -+#define init_stack (init_task_union.stack) -+ -+/* -+ * User space process size: 3GB (default). -+ */ -+extern unsigned long task_size; -+ -+#define TASK_SIZE (task_size) -+ -+/* This decides where the kernel will search for a free chunk of vm -+ * space during mmap's. -+ */ -+#define TASK_UNMAPPED_BASE (0x40000000) -+ -+extern void start_thread(struct pt_regs *regs, unsigned long entry, -+ unsigned long stack); -+ -+struct cpuinfo_um { -+ unsigned long loops_per_jiffy; -+ unsigned long *pgd_quick; -+ unsigned long *pmd_quick; -+ unsigned long *pte_quick; -+ unsigned long pgtable_cache_sz; -+ int ipi_pipe[2]; -+}; -+ -+extern struct cpuinfo_um boot_cpu_data; -+ -+#define my_cpu_data cpu_data[smp_processor_id()] -+ -+#ifdef CONFIG_SMP -+extern struct cpuinfo_um cpu_data[]; -+#define current_cpu_data cpu_data[smp_processor_id()] -+#else -+#define cpu_data (&boot_cpu_data) -+#define current_cpu_data boot_cpu_data -+#endif -+ -+#define KSTK_EIP(tsk) (PT_REGS_IP(&tsk->thread.regs)) -+#define KSTK_ESP(tsk) (PT_REGS_SP(&tsk->thread.regs)) -+#define get_wchan(p) (0) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/processor-i386.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/processor-i386.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/processor-i386.h 2005-05-03 23:41:08.095518296 +0300 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PROCESSOR_I386_H -+#define __UM_PROCESSOR_I386_H -+ -+extern int cpu_has_xmm; -+extern int cpu_has_cmov; -+ -+struct arch_thread { -+ unsigned long debugregs[8]; -+ int debugregs_seq; -+}; -+ -+#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \ -+ .debugregs_seq = 0 } -+ -+#include "asm/arch/user.h" -+ -+#include "asm/processor-generic.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/processor-ppc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/processor-ppc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/processor-ppc.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,15 @@ -+#ifndef __UM_PROCESSOR_PPC_H -+#define __UM_PROCESSOR_PPC_H -+ -+#if defined(__ASSEMBLY__) -+ -+#define CONFIG_ALL_PPC -+#include "arch/processor.h" -+ -+#else -+ -+#include "asm/processor-generic.h" -+ -+#endif -+ -+#endif -Index: linux-2.4.29/include/asm-um/ptrace-generic.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ptrace-generic.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ptrace-generic.h 2005-05-03 23:41:08.084519968 +0300 -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PTRACE_GENERIC_H -+#define __UM_PTRACE_GENERIC_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include "linux/config.h" -+ -+#include "asm/current.h" -+ -+#define pt_regs pt_regs_subarch -+#define show_regs show_regs_subarch -+ -+#include "asm/arch/ptrace.h" -+ -+#undef pt_regs -+#undef show_regs -+#undef user_mode -+#undef instruction_pointer -+ -+#include "sysdep/ptrace.h" -+#include "skas_ptrace.h" -+ -+struct pt_regs { -+ union uml_pt_regs regs; -+}; -+ -+#define EMPTY_REGS { regs : EMPTY_UML_PT_REGS } -+ -+#define PT_REGS_IP(r) UPT_IP(&(r)->regs) -+#define PT_REGS_SP(r) UPT_SP(&(r)->regs) -+ -+#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg) -+#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val) -+ -+#define PT_REGS_SET_SYSCALL_RETURN(r, res) \ -+ UPT_SET_SYSCALL_RETURN(&(r)->regs, res) -+#define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs) -+ -+#define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs) -+ -+#define PT_REGS_SC(r) UPT_SC(&(r)->regs) -+ -+struct task_struct; -+ -+extern unsigned long getreg(struct task_struct *child, int regno); -+extern int putreg(struct task_struct *child, int regno, unsigned long value); -+extern int get_fpregs(unsigned long buf, struct task_struct *child); -+extern int set_fpregs(unsigned long buf, struct task_struct *child); -+extern int get_fpxregs(unsigned long buf, struct task_struct *child); -+extern int set_fpxregs(unsigned long buf, struct task_struct *tsk); -+ -+extern void show_regs(struct pt_regs *regs); -+ -+#define INIT_TASK_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) -+ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/ptrace-i386.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ptrace-i386.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ptrace-i386.h 2005-05-03 23:41:08.085519816 +0300 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_PTRACE_I386_H -+#define __UM_PTRACE_I386_H -+ -+#include "sysdep/ptrace.h" -+#include "asm/ptrace-generic.h" -+ -+#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs) -+#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs) -+#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs) -+#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs) -+#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs) -+#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs) -+#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs) -+ -+#define PT_REGS_CS(r) UPT_CS(&(r)->regs) -+#define PT_REGS_SS(r) UPT_SS(&(r)->regs) -+#define PT_REGS_DS(r) UPT_DS(&(r)->regs) -+#define PT_REGS_ES(r) UPT_ES(&(r)->regs) -+#define PT_REGS_FS(r) UPT_FS(&(r)->regs) -+#define PT_REGS_GS(r) UPT_GS(&(r)->regs) -+ -+#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) -+ -+#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r) -+#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r) -+#define PT_FIX_EXEC_STACK(sp) do ; while(0) -+ -+#define user_mode(r) UPT_IS_USER(&(r)->regs) -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/resource.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/resource.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/resource.h 2005-05-03 22:28:14.980332856 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_RESOURCE_H -+#define __UM_RESOURCE_H -+ -+#include "asm/arch/resource.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/rwlock.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/rwlock.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/rwlock.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_RWLOCK_H -+#define __UM_RWLOCK_H -+ -+#include "asm/arch/rwlock.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/rwsem.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/rwsem.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/rwsem.h 2005-05-03 23:41:08.109516168 +0300 -@@ -0,0 +1,10 @@ -+#ifndef __UM_RWSEM_H__ -+#define __UM_RWSEM_H__ -+ -+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) -+#define __builtin_expect(exp,c) (exp) -+#endif -+ -+#include "asm/arch/rwsem.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/scatterlist.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/scatterlist.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/scatterlist.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SCATTERLIST_H -+#define __UM_SCATTERLIST_H -+ -+#include "asm/arch/scatterlist.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/segment.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/segment.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/segment.h 2005-05-03 22:28:14.983332400 +0300 -@@ -0,0 +1,4 @@ -+#ifndef __UM_SEGMENT_H -+#define __UM_SEGMENT_H -+ -+#endif -Index: linux-2.4.29/include/asm-um/semaphore.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/semaphore.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/semaphore.h 2005-05-03 23:41:08.110516016 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SEMAPHORE_H -+#define __UM_SEMAPHORE_H -+ -+#include "asm/arch/semaphore.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/sembuf.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/sembuf.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/sembuf.h 2005-05-03 22:28:14.984332248 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SEMBUF_H -+#define __UM_SEMBUF_H -+ -+#include "asm/arch/sembuf.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/serial.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/serial.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/serial.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SERIAL_H -+#define __UM_SERIAL_H -+ -+#include "asm/arch/serial.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/shmbuf.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/shmbuf.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/shmbuf.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SHMBUF_H -+#define __UM_SHMBUF_H -+ -+#include "asm/arch/shmbuf.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/shmparam.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/shmparam.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/shmparam.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SHMPARAM_H -+#define __UM_SHMPARAM_H -+ -+#include "asm/arch/shmparam.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/sigcontext-generic.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/sigcontext-generic.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/sigcontext-generic.h 2005-05-03 22:28:14.987331792 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGCONTEXT_GENERIC_H -+#define __UM_SIGCONTEXT_GENERIC_H -+ -+#include "asm/arch/sigcontext.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/sigcontext-i386.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/sigcontext-i386.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/sigcontext-i386.h 2005-05-03 22:28:14.988331640 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGCONTEXT_I386_H -+#define __UM_SIGCONTEXT_I386_H -+ -+#include "asm/sigcontext-generic.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/sigcontext-ppc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/sigcontext-ppc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/sigcontext-ppc.h 2005-05-03 22:28:14.000000000 +0300 -@@ -0,0 +1,10 @@ -+#ifndef __UM_SIGCONTEXT_PPC_H -+#define __UM_SIGCONTEXT_PPC_H -+ -+#define pt_regs sys_pt_regs -+ -+#include "asm/sigcontext-generic.h" -+ -+#undef pt_regs -+ -+#endif -Index: linux-2.4.29/include/asm-um/siginfo.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/siginfo.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/siginfo.h 2005-05-03 23:41:08.092518752 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SIGINFO_H -+#define __UM_SIGINFO_H -+ -+#include "asm/arch/siginfo.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/signal.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/signal.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/signal.h 2005-05-03 23:41:08.090519056 +0300 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_SIGNAL_H -+#define __UM_SIGNAL_H -+ -+#include "asm/arch/signal.h" -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/smp.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/smp.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/smp.h 2005-05-03 23:41:09.801258984 +0300 -@@ -0,0 +1,19 @@ -+#ifndef __UM_SMP_H -+#define __UM_SMP_H -+ -+#ifdef CONFIG_SMP -+ -+#include "linux/config.h" -+#include "asm/current.h" -+ -+#define smp_processor_id() (current->processor) -+#define cpu_logical_map(n) (n) -+#define cpu_number_map(n) (n) -+#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ -+extern int hard_smp_processor_id(void); -+extern unsigned long cpu_online_map; -+#define NO_PROC_ID -1 -+ -+#endif -+ -+#endif -Index: linux-2.4.29/include/asm-um/smplock.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/smplock.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/smplock.h 2005-05-03 23:41:09.912242112 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SMPLOCK_H -+#define __UM_SMPLOCK_H -+ -+#include "asm/arch/smplock.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/socket.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/socket.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/socket.h 2005-05-03 22:37:45.384618224 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SOCKET_H -+#define __UM_SOCKET_H -+ -+#include "asm/arch/socket.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/sockios.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/sockios.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/sockios.h 2005-05-03 22:28:14.994330728 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_SOCKIOS_H -+#define __UM_SOCKIOS_H -+ -+#include "asm/arch/sockios.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/softirq.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/softirq.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/softirq.h 2005-05-03 23:41:09.910242416 +0300 -@@ -0,0 +1,13 @@ -+#ifndef __UM_SOFTIRQ_H -+#define __UM_SOFTIRQ_H -+ -+#include "linux/smp.h" -+#include "asm/system.h" -+#include "asm/processor.h" -+ -+/* A gratuitous name change */ -+#define i386_bh_lock um_bh_lock -+#include "asm/arch/softirq.h" -+#undef i386_bh_lock -+ -+#endif -Index: linux-2.4.29/include/asm-um/spinlock.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/spinlock.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/spinlock.h 2005-05-03 23:41:08.101517384 +0300 -@@ -0,0 +1,10 @@ -+#ifndef __UM_SPINLOCK_H -+#define __UM_SPINLOCK_H -+ -+#include "linux/config.h" -+ -+#ifdef CONFIG_SMP -+#include "asm/arch/spinlock.h" -+#endif -+ -+#endif -Index: linux-2.4.29/include/asm-um/statfs.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/statfs.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/statfs.h 2005-05-03 23:41:08.104516928 +0300 -@@ -0,0 +1,6 @@ -+#ifndef _UM_STATFS_H -+#define _UM_STATFS_H -+ -+#include "asm/arch/statfs.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/stat.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/stat.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/stat.h 2005-05-03 22:28:14.997330272 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_STAT_H -+#define __UM_STAT_H -+ -+#include "asm/arch/stat.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/string.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/string.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/string.h 2005-05-03 22:28:14.998330120 +0300 -@@ -0,0 +1,7 @@ -+#ifndef __UM_STRING_H -+#define __UM_STRING_H -+ -+#include "asm/arch/string.h" -+#include "asm/archparam.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/system-generic.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/system-generic.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/system-generic.h 2005-05-03 23:41:08.098517840 +0300 -@@ -0,0 +1,50 @@ -+#ifndef __UM_SYSTEM_GENERIC_H -+#define __UM_SYSTEM_GENERIC_H -+ -+#include "asm/arch/system.h" -+ -+#undef prepare_to_switch -+#undef switch_to -+#undef __save_flags -+#undef save_flags -+#undef __restore_flags -+#undef restore_flags -+#undef __cli -+#undef __sti -+#undef cli -+#undef sti -+#undef local_irq_save -+#undef local_irq_restore -+#undef local_irq_disable -+#undef local_irq_enable -+ -+#define prepare_to_switch() do ; while(0) -+ -+void *_switch_to(void *prev, void *next); -+ -+#define switch_to(prev, next, last) prev = _switch_to(prev, next) -+ -+extern int get_signals(void); -+extern int set_signals(int enable); -+extern void block_signals(void); -+extern void unblock_signals(void); -+ -+#define local_irq_save(flags) do { (flags) = set_signals(0); } while(0) -+ -+#define local_irq_restore(flags) do { set_signals(flags); } while(0) -+ -+#define local_irq_enable() unblock_signals() -+#define local_irq_disable() block_signals() -+ -+#define __sti() unblock_signals() -+#define sti() unblock_signals() -+#define __cli() block_signals() -+#define cli() block_signals() -+ -+#define __save_flags(x) do { (x) = get_signals(); } while(0) -+#define save_flags(x) __save_flags(x) -+ -+#define __restore_flags(x) local_irq_restore(x) -+#define restore_flags(x) __restore_flags(x) -+ -+#endif -Index: linux-2.4.29/include/asm-um/system-i386.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/system-i386.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/system-i386.h 2005-05-03 23:41:08.098517840 +0300 -@@ -0,0 +1,8 @@ -+#ifndef __UM_SYSTEM_I386_H -+#define __UM_SYSTEM_I386_H -+ -+#include "asm/system-generic.h" -+ -+#define __HAVE_ARCH_CMPXCHG 1 -+ -+#endif -Index: linux-2.4.29/include/asm-um/system-ppc.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/system-ppc.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/system-ppc.h 2005-05-03 22:28:15.000000000 +0300 -@@ -0,0 +1,12 @@ -+#ifndef __UM_SYSTEM_PPC_H -+#define __UM_SYSTEM_PPC_H -+ -+#define _switch_to _ppc_switch_to -+ -+#include "asm/arch/system.h" -+ -+#undef _switch_to -+ -+#include "asm/system-generic.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/termbits.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/termbits.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/termbits.h 2005-05-03 22:37:45.506599680 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TERMBITS_H -+#define __UM_TERMBITS_H -+ -+#include "asm/arch/termbits.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/termios.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/termios.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/termios.h 2005-05-03 22:37:45.512598768 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TERMIOS_H -+#define __UM_TERMIOS_H -+ -+#include "asm/arch/termios.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/timex.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/timex.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/timex.h 2005-05-03 23:41:09.799259288 +0300 -@@ -0,0 +1,18 @@ -+#ifndef __UM_TIMEX_H -+#define __UM_TIMEX_H -+ -+#include "linux/time.h" -+ -+typedef unsigned long cycles_t; -+ -+#define cacheflush_time (0) -+ -+static inline cycles_t get_cycles (void) -+{ -+ return 0; -+} -+ -+#define vxtime_lock() do ; while (0) -+#define vxtime_unlock() do ; while (0) -+ -+#endif -Index: linux-2.4.29/include/asm-um/tlb.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/tlb.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/tlb.h 2005-05-03 22:28:15.000000000 +0300 -@@ -0,0 +1 @@ -+#include <asm-generic/tlb.h> -Index: linux-2.4.29/include/asm-um/types.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/types.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/types.h 2005-05-03 22:28:15.006328904 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_TYPES_H -+#define __UM_TYPES_H -+ -+#include "asm/arch/types.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/uaccess.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/uaccess.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/uaccess.h 2005-05-03 23:41:09.913241960 +0300 -@@ -0,0 +1,99 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __UM_UACCESS_H -+#define __UM_UACCESS_H -+ -+#include "linux/sched.h" -+ -+#define VERIFY_READ 0 -+#define VERIFY_WRITE 1 -+ -+/* -+ * The fs value determines whether argument validity checking should be -+ * performed or not. If get_fs() == USER_DS, checking is performed, with -+ * get_fs() == KERNEL_DS, checking is bypassed. -+ * -+ * For historical reasons, these macros are grossly misnamed. -+ */ -+ -+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -+ -+#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -+#define USER_DS MAKE_MM_SEG(TASK_SIZE) -+ -+#define get_ds() (KERNEL_DS) -+#define get_fs() (current->addr_limit) -+#define set_fs(x) (current->addr_limit = (x)) -+ -+#define segment_eq(a, b) ((a).seg == (b).seg) -+ -+#include "um_uaccess.h" -+ -+#define __copy_from_user(to, from, n) copy_from_user(to, from, n) -+ -+#define __copy_to_user(to, from, n) copy_to_user(to, from, n) -+ -+#define __get_user(x, ptr) \ -+({ \ -+ const __typeof__(ptr) __private_ptr = ptr; \ -+ __typeof__(*(__private_ptr)) __private_val; \ -+ int __private_ret = -EFAULT; \ -+ (x) = 0; \ -+ if (__copy_from_user(&__private_val, (__private_ptr), \ -+ sizeof(*(__private_ptr))) == 0) {\ -+ (x) = (__typeof__(*(__private_ptr))) __private_val; \ -+ __private_ret = 0; \ -+ } \ -+ __private_ret; \ -+}) -+ -+#define get_user(x, ptr) \ -+({ \ -+ const __typeof__((*ptr)) *private_ptr = (ptr); \ -+ (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \ -+ __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \ -+}) -+ -+#define __put_user(x, ptr) \ -+({ \ -+ __typeof__(ptr) __private_ptr = ptr; \ -+ __typeof__(*(__private_ptr)) __private_val; \ -+ int __private_ret = -EFAULT; \ -+ __private_val = (__typeof__(*(__private_ptr))) (x); \ -+ if (__copy_to_user((__private_ptr), &__private_val, \ -+ sizeof(*(__private_ptr))) == 0) { \ -+ __private_ret = 0; \ -+ } \ -+ __private_ret; \ -+}) -+ -+#define put_user(x, ptr) \ -+({ \ -+ __typeof__(*(ptr)) *private_ptr = (ptr); \ -+ (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \ -+ __put_user(x, private_ptr) : -EFAULT); \ -+}) -+ -+#define strlen_user(str) strnlen_user(str, ~0UL >> 1) -+ -+struct exception_table_entry -+{ -+ unsigned long insn; -+ unsigned long fixup; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/ucontext.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/ucontext.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/ucontext.h 2005-05-03 22:28:15.008328600 +0300 -@@ -0,0 +1,6 @@ -+#ifndef _ASM_UM_UCONTEXT_H -+#define _ASM_UM_UCONTEXT_H -+ -+#include "asm/arch/ucontext.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/unaligned.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/unaligned.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/unaligned.h 2005-05-03 22:28:15.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_UNALIGNED_H -+#define __UM_UNALIGNED_H -+ -+#include "asm/arch/unaligned.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/unistd.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/unistd.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/unistd.h 2005-05-03 23:41:11.206045424 +0300 -@@ -0,0 +1,121 @@ -+/* -+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef _UM_UNISTD_H_ -+#define _UM_UNISTD_H_ -+ -+#include "linux/resource.h" -+#include "asm/uaccess.h" -+ -+extern long sys_open(const char *filename, int flags, int mode); -+extern long sys_dup(unsigned int fildes); -+extern long sys_close(unsigned int fd); -+extern int um_execve(const char *file, char *const argv[], char *const env[]); -+extern long sys_setsid(void); -+extern long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options); -+extern long sys_wait4(pid_t pid,unsigned int *stat_addr, int options, -+ struct rusage *ru); -+extern long sys_mount(char *dev_name, char *dir_name, char *type, -+ unsigned long flags, void *data); -+extern long sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, -+ struct timeval *tvp); -+extern long sys_lseek(unsigned int fildes, unsigned long offset, int whence); -+extern long sys_read(unsigned int fildes, char *buf, int len); -+extern long sys_write(unsigned int fildes, char *buf, int len); -+ -+#ifdef __KERNEL_SYSCALLS__ -+ -+#define KERNEL_CALL(ret_t, sys, args...) \ -+ mm_segment_t fs = get_fs(); \ -+ ret_t ret; \ -+ set_fs(KERNEL_DS); \ -+ ret = sys(args); \ -+ set_fs(fs); \ -+ if (ret >= 0) \ -+ return ret; \ -+ errno = -(long)ret; \ -+ return -1; -+ -+static inline long open(const char *pathname, int flags, int mode) -+{ -+ KERNEL_CALL(int, sys_open, pathname, flags, mode) -+} -+ -+static inline long dup(unsigned int fd) -+{ -+ KERNEL_CALL(int, sys_dup, fd); -+} -+ -+static inline long close(unsigned int fd) -+{ -+ KERNEL_CALL(int, sys_close, fd); -+} -+ -+static inline int execve(const char *filename, char *const argv[], -+ char *const envp[]) -+{ -+ KERNEL_CALL(int, um_execve, filename, argv, envp); -+} -+ -+static inline long waitpid(pid_t pid, unsigned int *status, int options) -+{ -+ KERNEL_CALL(pid_t, sys_wait4, pid, status, options, NULL) -+} -+ -+static inline pid_t wait(int *status) -+{ -+ KERNEL_CALL(pid_t, sys_wait4, -1, status, 0, NULL) -+} -+ -+static inline pid_t setsid(void) -+{ -+ KERNEL_CALL(pid_t, sys_setsid) -+} -+ -+static inline long lseek(unsigned int fd, off_t offset, unsigned int whence) -+{ -+ KERNEL_CALL(long, sys_lseek, fd, offset, whence) -+} -+ -+static inline int read(unsigned int fd, char * buf, int len) -+{ -+ KERNEL_CALL(int, sys_read, fd, buf, len) -+} -+ -+static inline int write(unsigned int fd, char * buf, int len) -+{ -+ KERNEL_CALL(int, sys_write, fd, buf, len) -+} -+ -+#endif -+ -+/* Save the value of __KERNEL_SYSCALLS__, undefine it, include the underlying -+ * arch's unistd.h for the system call numbers, and restore the old -+ * __KERNEL_SYSCALLS__. -+ */ -+ -+#ifdef __KERNEL_SYSCALLS__ -+#define __SAVE_KERNEL_SYSCALLS__ __KERNEL_SYSCALLS__ -+#endif -+ -+#undef __KERNEL_SYSCALLS__ -+#include "asm/arch/unistd.h" -+ -+#ifdef __KERNEL_SYSCALLS__ -+#define __KERNEL_SYSCALLS__ __SAVE_KERNEL_SYSCALLS__ -+#endif -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/asm-um/user.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/user.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/user.h 2005-05-03 23:43:26.305507184 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_USER_H -+#define __UM_USER_H -+ -+#include "asm/arch/user.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/vga.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/vga.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/vga.h 2005-05-03 22:28:15.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_VGA_H -+#define __UM_VGA_H -+ -+#include "asm/arch/vga.h" -+ -+#endif -Index: linux-2.4.29/include/asm-um/xor.h -=================================================================== ---- linux-2.4.29.orig/include/asm-um/xor.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/asm-um/xor.h 2005-05-03 22:28:15.000000000 +0300 -@@ -0,0 +1,6 @@ -+#ifndef __UM_XOR_H -+#define __UM_XOR_H -+ -+#include "asm-generic/xor.h" -+ -+#endif -Index: linux-2.4.29/include/linux/blk.h -=================================================================== ---- linux-2.4.29.orig/include/linux/blk.h 2005-05-03 21:09:03.000000000 +0300 -+++ linux-2.4.29/include/linux/blk.h 2005-05-03 23:41:26.547713136 +0300 -@@ -320,6 +320,24 @@ - #define DEVICE_REQUEST do_ida_request - #define DEVICE_NR(device) (MINOR(device) >> 4) - -+#elif (MAJOR_NR == UBD_MAJOR) -+ -+#define DEVICE_NAME "User-mode block device" -+#define DEVICE_INTR do_ubd -+#define DEVICE_REQUEST do_ubd_request -+#define DEVICE_NR(device) (MINOR(device) >> UBD_SHIFT) -+#define DEVICE_ON(device) -+#define DEVICE_OFF(device) -+ -+#elif (MAJOR_NR == COW_MAJOR) -+ -+#define DEVICE_NAME "COW device" -+#define DEVICE_INTR do_cow -+#define DEVICE_REQUEST do_cow_request -+#define DEVICE_NR(device) (MINOR(device) >> COW_SHIFT) -+#define DEVICE_ON(device) -+#define DEVICE_OFF(device) -+ - #endif /* MAJOR_NR == whatever */ - - /* provide DEVICE_xxx defaults, if not explicitly defined -Index: linux-2.4.29/include/linux/fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs.h 2005-05-03 21:06:01.000000000 +0300 -+++ linux-2.4.29/include/linux/fs.h 2005-05-03 23:56:00.359873496 +0300 -@@ -322,6 +322,8 @@ - #include <linux/ncp_fs_i.h> - #include <linux/proc_fs_i.h> - #include <linux/usbdev_fs_i.h> -+#include <linux/hostfs_fs_i.h> -+#include <linux/hppfs_fs_i.h> - #include <linux/jffs2_fs_i.h> - #include <linux/cramfs_fs_sb.h> - -@@ -518,7 +520,9 @@ - struct proc_inode_info proc_i; - struct socket socket_i; - struct usbdev_inode_info usbdev_i; -- struct jffs2_inode_info jffs2_i; -+ struct hostfs_inode_info hostfs_i; -+ struct hppfs_inode_info hppfs_i; -+ struct jffs2_inode_info jffs2_i; - void *generic_ip; - } u; - }; -@@ -866,6 +870,8 @@ - unsigned int (*poll) (struct file *, struct poll_table_struct *); - int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); - int (*mmap) (struct file *, struct vm_area_struct *); -+ void (*munmap) (struct file *, struct vm_area_struct *, -+ unsigned long start, unsigned long len); - int (*open) (struct inode *, struct file *); - int (*flush) (struct file *); - int (*release) (struct inode *, struct file *); -Index: linux-2.4.29/include/linux/ghash.h -=================================================================== ---- linux-2.4.29.orig/include/linux/ghash.h 2005-05-03 21:09:50.000000000 +0300 -+++ linux-2.4.29/include/linux/ghash.h 2005-05-03 22:28:15.000000000 +0300 -@@ -153,6 +153,26 @@ - return NULL;\ - } - -+/* LINKAGE - empty or "static", depending on whether you want the definitions to -+ * be public or not -+ * NAME - a string to stick in names to make this hash table type distinct from -+ * any others -+ * HASHSIZE - number of buckets -+ * TYPE - type of data contained in the buckets - must be a structure, one -+ * field is of type NAME_ptrs, another is the hash key -+ * PTRS - TYPE must contain a field of type NAME_ptrs, PTRS is the name of that -+ * field -+ * KEYTYPE - type of the key field within TYPE -+ * KEY - name of the key field within TYPE -+ * KEYCMP - pointer to function that compares KEYTYPEs to each other - the -+ * prototype is int KEYCMP(KEYTYPE, KEYTYPE), it returns zero for equal, -+ * non-zero for not equal -+ * HASHFN - the hash function - the prototype is int HASHFN(KEYTYPE), -+ * it returns a number in the range 0 ... HASHSIZE - 1 -+ * Call DEF_HASH_STRUCTS, define your hash table as a NAME_table, then call -+ * DEF_HASH. -+ */ -+ - #define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \ - \ - struct NAME##_table {\ -@@ -165,7 +185,7 @@ - TYPE * prev_hash;\ - }; - --#define DEF_HASH(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\ -+#define DEF_HASH(LINKAGE,NAME,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,HASHFN)\ - \ - LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\ - {\ -@@ -206,12 +226,10 @@ - \ - LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\ - {\ -- int ix = hashfn(pos);\ -+ int ix = HASHFN(pos);\ - TYPE * ptr = tbl->hashtable[ix];\ - while(ptr && KEYCMP(ptr->KEY, pos))\ - ptr = ptr->PTRS.next_hash;\ -- if(ptr && !KEYEQ(ptr->KEY, pos))\ -- ptr = NULL;\ - return ptr;\ - } - -Index: linux-2.4.29/include/linux/hostfs_fs_i.h -=================================================================== ---- linux-2.4.29.orig/include/linux/hostfs_fs_i.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/linux/hostfs_fs_i.h 2005-05-03 22:28:15.053321760 +0300 -@@ -0,0 +1,25 @@ -+#ifndef _HOSTFS_FS_I -+#define _HOSTFS_FS_I -+ -+#include "filehandle.h" -+ -+struct externfs_file_ops; -+ -+struct hostfs_inode_info { -+ struct externfs_file_ops *ops; -+ struct file_handle *fh; -+ int mode; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/linux/hppfs_fs_i.h -=================================================================== ---- linux-2.4.29.orig/include/linux/hppfs_fs_i.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/linux/hppfs_fs_i.h 2005-05-03 22:28:15.054321608 +0300 -@@ -0,0 +1,19 @@ -+#ifndef _HPPFS_FS_I -+#define _HPPFS_FS_I -+ -+struct hppfs_inode_info { -+ struct dentry *proc_dentry; -+}; -+ -+#endif -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/include/linux/kernel.h -=================================================================== ---- linux-2.4.29.orig/include/linux/kernel.h 2005-05-03 21:04:57.000000000 +0300 -+++ linux-2.4.29/include/linux/kernel.h 2005-05-03 23:41:08.088519360 +0300 -@@ -49,7 +49,7 @@ - # define ATTRIB_NORET __attribute__((noreturn)) - # define NORET_AND noreturn, - --#ifdef __i386__ -+#if defined(__i386__) || defined(UM_FASTCALL) - #define FASTCALL(x) x __attribute__((regparm(3))) - #define fastcall __attribute__((regparm(3))) - #else -Index: linux-2.4.29/include/linux/kernel_stat.h -=================================================================== ---- linux-2.4.29.orig/include/linux/kernel_stat.h 2005-05-03 21:09:36.000000000 +0300 -+++ linux-2.4.29/include/linux/kernel_stat.h 2005-05-03 23:41:09.913241960 +0300 -@@ -12,7 +12,7 @@ - * used by rstatd/perfmeter - */ - --#define DK_MAX_MAJOR 16 -+#define DK_MAX_MAJOR 99 - #define DK_MAX_DISK 16 - - struct kernel_stat { -Index: linux-2.4.29/include/linux/mm.h -=================================================================== ---- linux-2.4.29.orig/include/linux/mm.h 2005-05-03 21:05:15.000000000 +0300 -+++ linux-2.4.29/include/linux/mm.h 2005-05-03 23:55:59.724970016 +0300 -@@ -441,6 +441,18 @@ - extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)); - extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order); - -+#ifndef HAVE_ARCH_VALIDATE -+static inline struct page *arch_validate(struct page *page, -+ unsigned int gfp_mask, int order) -+{ -+ return(page); -+} -+#endif -+ -+#ifndef HAVE_ARCH_FREE_PAGE -+static inline void arch_free_page(struct page *page, int order) { } -+#endif -+ - static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order) - { - /* -@@ -448,7 +460,7 @@ - */ - if (order >= MAX_ORDER) - return NULL; -- return _alloc_pages(gfp_mask, order); -+ return arch_validate(_alloc_pages(gfp_mask, order), gfp_mask, order); - } - - #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) -@@ -508,6 +520,9 @@ - int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, - int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); - -+extern long do_mprotect(struct mm_struct *mm, unsigned long start, -+ size_t len, unsigned long prot); -+ - /* - * On a two-level page table, this ends up being trivial. Thus the - * inlining and the symmetry break with pte_alloc() that does all -@@ -555,9 +570,10 @@ - - extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - --extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, -- unsigned long len, unsigned long prot, -- unsigned long flag, unsigned long pgoff); -+extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flag, -+ unsigned long pgoff); - - static inline unsigned long do_mmap(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, -@@ -567,7 +583,8 @@ - if ((offset + PAGE_ALIGN(len)) < offset) - goto out; - if (!(offset & ~PAGE_MASK)) -- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag, -+ offset >> PAGE_SHIFT); - out: - return ret; - } -Index: linux-2.4.29/include/linux/proc_mm.h -=================================================================== ---- linux-2.4.29.orig/include/linux/proc_mm.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/include/linux/proc_mm.h 2005-05-03 23:46:00.225107848 +0300 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROC_MM_H -+#define __PROC_MM_H -+ -+#include "linux/sched.h" -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+extern struct mm_struct *proc_mm_get_mm(int fd); -+ -+#endif -Index: linux-2.4.29/include/linux/shmem_fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/shmem_fs.h 2005-05-03 21:09:04.000000000 +0300 -+++ linux-2.4.29/include/linux/shmem_fs.h 2005-05-03 22:28:15.082317352 +0300 -@@ -22,6 +22,8 @@ - unsigned long next_index; - swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */ - void **i_indirect; /* indirect blocks */ -+ unsigned long map_direct[SHMEM_NR_DIRECT]; -+ void **map_indirect; - unsigned long swapped; /* data pages assigned to swap */ - unsigned long flags; - struct list_head list; -Index: linux-2.4.29/include/linux/tty.h -=================================================================== ---- linux-2.4.29.orig/include/linux/tty.h 2005-05-03 21:07:23.000000000 +0300 -+++ linux-2.4.29/include/linux/tty.h 2005-05-03 23:41:09.901243784 +0300 -@@ -310,6 +310,9 @@ - spinlock_t read_lock; - /* If the tty has a pending do_SAK, queue it here - akpm */ - struct tq_struct SAK_tq; -+#ifdef CONFIG_TTY_LOG -+ int log_fd; -+#endif - }; - - /* tty magic number */ -@@ -368,6 +371,7 @@ - extern int specialix_init(void); - extern int espserial_init(void); - extern int macserial_init(void); -+extern int stdio_init(void); - extern int a2232board_init(void); - - extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device, -@@ -434,5 +438,7 @@ - extern int vt_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg); - -+extern void stdio_console_init(void); -+ - #endif /* __KERNEL__ */ - #endif -Index: linux-2.4.29/init/do_mounts.c -=================================================================== ---- linux-2.4.29.orig/init/do_mounts.c 2005-05-03 21:09:10.000000000 +0300 -+++ linux-2.4.29/init/do_mounts.c 2005-05-03 22:28:15.000000000 +0300 -@@ -154,6 +154,22 @@ - { "pf", 0x2f00 }, - { "apblock", APBLOCK_MAJOR << 8}, - { "ddv", DDV_MAJOR << 8}, -+ { "ubd0", UBD_MAJOR << 8 | 0 << 4}, -+ { "ubda", UBD_MAJOR << 8 | 0 << 4}, -+ { "ubd1", UBD_MAJOR << 8 | 1 << 4}, -+ { "ubdb", UBD_MAJOR << 8 | 1 << 4}, -+ { "ubd2", UBD_MAJOR << 8 | 2 << 4}, -+ { "ubdc", UBD_MAJOR << 8 | 2 << 4}, -+ { "ubd3", UBD_MAJOR << 8 | 3 << 4}, -+ { "ubdd", UBD_MAJOR << 8 | 3 << 4}, -+ { "ubd4", UBD_MAJOR << 8 | 4 << 4}, -+ { "ubde", UBD_MAJOR << 8 | 4 << 4}, -+ { "ubd5", UBD_MAJOR << 8 | 5 << 4}, -+ { "ubdf", UBD_MAJOR << 8 | 5 << 4}, -+ { "ubd6", UBD_MAJOR << 8 | 6 << 4}, -+ { "ubdg", UBD_MAJOR << 8 | 6 << 4}, -+ { "ubd7", UBD_MAJOR << 8 | 7 << 4}, -+ { "ubdh", UBD_MAJOR << 8 | 7 << 4}, - { "jsfd", JSFD_MAJOR << 8}, - #if defined(CONFIG_ARCH_S390) - { "dasda", (DASD_MAJOR << MINORBITS) }, -Index: linux-2.4.29/kernel/panic.c -=================================================================== ---- linux-2.4.29.orig/kernel/panic.c 2005-05-03 21:09:35.000000000 +0300 -+++ linux-2.4.29/kernel/panic.c 2005-05-03 22:28:15.000000000 +0300 -@@ -74,7 +74,7 @@ - smp_send_stop(); - #endif - -- notifier_call_chain(&panic_notifier_list, 0, NULL); -+ notifier_call_chain(&panic_notifier_list, 0, buf); - - if (panic_timeout > 0) - { -Index: linux-2.4.29/MAINTAINERS -=================================================================== ---- linux-2.4.29.orig/MAINTAINERS 2005-05-03 21:07:57.000000000 +0300 -+++ linux-2.4.29/MAINTAINERS 2005-05-03 22:28:15.000000000 +0300 -@@ -2120,6 +2120,14 @@ - L: linux-usb-devel@lists.sourceforge.net - W: http://usb.in.tum.de - S: Maintained -+ -+USER-MODE PORT -+P: Jeff Dike -+M: jdike@karaya.com -+L: user-mode-linux-devel@lists.sourceforge.net -+L: user-mode-linux-user@lists.sourceforge.net -+W: http://user-mode-linux.sourceforge.net -+S: Maintained - - USB "USBNET" DRIVER - P: David Brownell -Index: linux-2.4.29/Makefile -=================================================================== ---- linux-2.4.29.orig/Makefile 2005-05-03 21:08:14.000000000 +0300 -+++ linux-2.4.29/Makefile 2005-05-03 22:28:15.000000000 +0300 -@@ -5,7 +5,15 @@ - - KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) - --ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+# SUBARCH tells the usermode build what the underlying arch is. That is set -+# first, and if a usermode build is happening, the "ARCH=um" on the command -+# line overrides the setting of ARCH below. If a native build is happening, -+# then ARCH is assigned, getting whatever value it gets normally, and -+# SUBARCH is subsequently ignored. -+ -+SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) -+ARCH := $(SUBARCH) -+ - KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g") - - CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ -Index: linux-2.4.29/mm/Makefile -=================================================================== ---- linux-2.4.29.orig/mm/Makefile 2005-05-03 21:08:06.000000000 +0300 -+++ linux-2.4.29/mm/Makefile 2005-05-03 22:28:15.000000000 +0300 -@@ -17,5 +17,6 @@ - shmem.o - - obj-$(CONFIG_HIGHMEM) += highmem.o -+obj-$(CONFIG_PROC_MM) += proc_mm.o - - include $(TOPDIR)/Rules.make -Index: linux-2.4.29/mm/mmap.c -=================================================================== ---- linux-2.4.29.orig/mm/mmap.c 2005-05-03 21:07:59.000000000 +0300 -+++ linux-2.4.29/mm/mmap.c 2005-05-03 22:28:15.000000000 +0300 -@@ -391,10 +391,11 @@ - return 0; - } - --unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len, -- unsigned long prot, unsigned long flags, unsigned long pgoff) -+unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long pgoff) - { -- struct mm_struct * mm = current->mm; - struct vm_area_struct * vma, * prev; - unsigned int vm_flags; - int correct_wcount = 0; -@@ -1000,6 +1001,11 @@ - remove_shared_vm_struct(mpnt); - mm->map_count--; - -+ if((mpnt->vm_file != NULL) && (mpnt->vm_file->f_op != NULL) && -+ (mpnt->vm_file->f_op->munmap != NULL)) -+ mpnt->vm_file->f_op->munmap(mpnt->vm_file, mpnt, st, -+ size); -+ - zap_page_range(mm, st, size); - - /* -Index: linux-2.4.29/mm/mprotect.c -=================================================================== ---- linux-2.4.29.orig/mm/mprotect.c 2005-05-03 21:06:44.000000000 +0300 -+++ linux-2.4.29/mm/mprotect.c 2005-05-03 22:28:15.000000000 +0300 -@@ -264,7 +264,8 @@ - return 0; - } - --asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) -+long do_mprotect(struct mm_struct *mm, unsigned long start, size_t len, -+ unsigned long prot) - { - unsigned long nstart, end, tmp; - struct vm_area_struct * vma, * next, * prev; -@@ -281,9 +282,9 @@ - if (end == start) - return 0; - -- down_write(¤t->mm->mmap_sem); -+ down_write(&mm->mmap_sem); - -- vma = find_vma_prev(current->mm, start, &prev); -+ vma = find_vma_prev(mm, start, &prev); - error = -ENOMEM; - if (!vma || vma->vm_start > start) - goto out; -@@ -332,6 +333,11 @@ - prev->vm_mm->map_count--; - } - out: -- up_write(¤t->mm->mmap_sem); -+ up_write(&mm->mmap_sem); - return error; - } -+ -+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) -+{ -+ return(do_mprotect(current->mm, start, len, prot)); -+} -Index: linux-2.4.29/mm/page_alloc.c -=================================================================== ---- linux-2.4.29.orig/mm/page_alloc.c 2005-05-03 21:05:16.000000000 +0300 -+++ linux-2.4.29/mm/page_alloc.c 2005-05-03 22:28:15.000000000 +0300 -@@ -116,6 +116,7 @@ - struct page *base; - zone_t *zone; - -+ arch_free_page(page, order); - /* - * Yes, think what happens when other parts of the kernel take - * a reference to a page in order to pin it for io. -ben -Index: linux-2.4.29/mm/proc_mm.c -=================================================================== ---- linux-2.4.29.orig/mm/proc_mm.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-2.4.29/mm/proc_mm.c 2005-05-03 22:28:15.000000000 +0300 -@@ -0,0 +1,173 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#include "linux/init.h" -+#include "linux/proc_fs.h" -+#include "linux/proc_mm.h" -+#include "linux/file.h" -+#include "asm/uaccess.h" -+#include "asm/mmu_context.h" -+ -+static struct file_operations proc_mm_fops; -+ -+struct mm_struct *proc_mm_get_mm(int fd) -+{ -+ struct mm_struct *ret = ERR_PTR(-EBADF); -+ struct file *file; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ ret = ERR_PTR(-EINVAL); -+ if(file->f_op != &proc_mm_fops) -+ goto out_fput; -+ -+ ret = file->private_data; -+ out_fput: -+ fput(file); -+ out: -+ return(ret); -+} -+ -+extern long do_mmap2(struct mm_struct *mm, unsigned long addr, -+ unsigned long len, unsigned long prot, -+ unsigned long flags, unsigned long fd, -+ unsigned long pgoff); -+ -+static ssize_t write_proc_mm(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos) -+{ -+ struct mm_struct *mm = file->private_data; -+ struct proc_mm_op req; -+ int n, ret; -+ -+ if(count > sizeof(req)) -+ return(-EINVAL); -+ -+ n = copy_from_user(&req, buffer, count); -+ if(n != 0) -+ return(-EFAULT); -+ -+ ret = count; -+ switch(req.op){ -+ case MM_MMAP: { -+ struct mm_mmap *map = &req.u.mmap; -+ -+ ret = do_mmap2(mm, map->addr, map->len, map->prot, -+ map->flags, map->fd, map->offset >> PAGE_SHIFT); -+ if((ret & ~PAGE_MASK) == 0) -+ ret = count; -+ -+ break; -+ } -+ case MM_MUNMAP: { -+ struct mm_munmap *unmap = &req.u.munmap; -+ -+ down_write(&mm->mmap_sem); -+ ret = do_munmap(mm, unmap->addr, unmap->len); -+ up_write(&mm->mmap_sem); -+ -+ if(ret == 0) -+ ret = count; -+ break; -+ } -+ case MM_MPROTECT: { -+ struct mm_mprotect *protect = &req.u.mprotect; -+ -+ ret = do_mprotect(mm, protect->addr, protect->len, -+ protect->prot); -+ if(ret == 0) -+ ret = count; -+ break; -+ } -+ -+ case MM_COPY_SEGMENTS: { -+ struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); -+ -+ if(IS_ERR(from)){ -+ ret = PTR_ERR(from); -+ break; -+ } -+ -+ mm_copy_segments(from, mm); -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ return(ret); -+} -+ -+static int open_proc_mm(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = mm_alloc(); -+ int ret; -+ -+ ret = -ENOMEM; -+ if(mm == NULL) -+ goto out_mem; -+ -+ ret = init_new_context(current, mm); -+ if(ret) -+ goto out_free; -+ -+ spin_lock(&mmlist_lock); -+ list_add(&mm->mmlist, ¤t->mm->mmlist); -+ mmlist_nr++; -+ spin_unlock(&mmlist_lock); -+ -+ file->private_data = mm; -+ -+ return(0); -+ -+ out_free: -+ mmput(mm); -+ out_mem: -+ return(ret); -+} -+ -+static int release_proc_mm(struct inode *inode, struct file *file) -+{ -+ struct mm_struct *mm = file->private_data; -+ -+ mmput(mm); -+ return(0); -+} -+ -+static struct file_operations proc_mm_fops = { -+ .open = open_proc_mm, -+ .release = release_proc_mm, -+ .write = write_proc_mm, -+}; -+ -+static int make_proc_mm(void) -+{ -+ struct proc_dir_entry *ent; -+ -+ ent = create_proc_entry("mm", 0222, &proc_root); -+ if(ent == NULL){ -+ printk("make_proc_mm : Failed to register /proc/mm\n"); -+ return(0); -+ } -+ ent->proc_fops = &proc_mm_fops; -+ -+ return(0); -+} -+ -+__initcall(make_proc_mm); -+ -+/* -+ * Overrides for Emacs so that we follow Linus's tabbing style. -+ * Emacs will notice this stuff at the end of the file and automatically -+ * adjust the settings for this buffer only. This must remain at the end -+ * of the file. -+ * --------------------------------------------------------------------------- -+ * Local variables: -+ * c-file-style: "linux" -+ * End: -+ */ -Index: linux-2.4.29/mm/shmem.c -=================================================================== ---- linux-2.4.29.orig/mm/shmem.c 2005-05-03 21:06:51.000000000 +0300 -+++ linux-2.4.29/mm/shmem.c 2005-05-03 22:28:15.000000000 +0300 -@@ -128,16 +128,17 @@ - * +-> 48-51 - * +-> 52-55 - */ --static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, unsigned long *page) -+static void *shmem_block(unsigned long index, unsigned long *page, -+ unsigned long *direct, void ***indirect) - { - unsigned long offset; - void **dir; - - if (index < SHMEM_NR_DIRECT) -- return info->i_direct+index; -- if (!info->i_indirect) { -+ return direct+index; -+ if (!*indirect) { - if (page) { -- info->i_indirect = (void **) *page; -+ *indirect = (void **) *page; - *page = 0; - } - return NULL; /* need another page */ -@@ -146,7 +147,7 @@ - index -= SHMEM_NR_DIRECT; - offset = index % ENTRIES_PER_PAGE; - index /= ENTRIES_PER_PAGE; -- dir = info->i_indirect; -+ dir = *indirect; - - if (index >= ENTRIES_PER_PAGE/2) { - index -= ENTRIES_PER_PAGE/2; -@@ -169,7 +170,21 @@ - *dir = (void *) *page; - *page = 0; - } -- return (swp_entry_t *) *dir + offset; -+ return (unsigned long **) *dir + offset; -+} -+ -+static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, unsigned long *page) -+{ -+ return((swp_entry_t *) shmem_block(index, page, -+ (unsigned long *) info->i_direct, -+ &info->i_indirect)); -+} -+ -+static unsigned long *shmem_map_count(struct shmem_inode_info *info, -+ unsigned long index, unsigned long *page) -+{ -+ return((unsigned long *) shmem_block(index, page, info->map_direct, -+ &info->map_indirect)); - } - - /* -@@ -847,6 +862,7 @@ - ops = &shmem_vm_ops; - if (!S_ISREG(inode->i_mode)) - return -EACCES; -+ - UPDATE_ATIME(inode); - vma->vm_ops = ops; - return 0; -@@ -1750,4 +1766,125 @@ - return 0; - } - -+static int adjust_map_counts(struct shmem_inode_info *info, -+ unsigned long offset, unsigned long len, -+ int adjust) -+{ -+ unsigned long idx, i, *count, page = 0; -+ -+ spin_lock(&info->lock); -+ offset >>= PAGE_SHIFT; -+ len >>= PAGE_SHIFT; -+ for(i = 0; i < len; i++){ -+ idx = (i + offset) >> (PAGE_CACHE_SHIFT - PAGE_SHIFT); -+ -+ while((count = shmem_map_count(info, idx, &page)) == NULL){ -+ spin_unlock(&info->lock); -+ page = get_zeroed_page(GFP_KERNEL); -+ if(page == 0) -+ return(-ENOMEM); -+ spin_lock(&info->lock); -+ } -+ -+ if(page != 0) -+ free_page(page); -+ -+ *count += adjust; -+ } -+ spin_unlock(&info->lock); -+ return(0); -+} -+ - EXPORT_SYMBOL(shmem_file_setup); -+ -+struct file_operations anon_file_operations; -+ -+static int anon_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct file *new; -+ struct inode *inode; -+ loff_t size = vma->vm_end - vma->vm_start; -+ int err; -+ -+ if(file->private_data == NULL){ -+ new = shmem_file_setup("dev/anon", size); -+ if(IS_ERR(new)) -+ return(PTR_ERR(new)); -+ -+ new->f_op = &anon_file_operations; -+ file->private_data = new; -+ } -+ -+ if (vma->vm_file) -+ fput(vma->vm_file); -+ vma->vm_file = file->private_data; -+ get_file(vma->vm_file); -+ -+ inode = vma->vm_file->f_dentry->d_inode; -+ err = adjust_map_counts(SHMEM_I(inode), vma->vm_pgoff, size, 1); -+ if(err) -+ return(err); -+ -+ vma->vm_ops = &shmem_vm_ops; -+ return 0; -+} -+ -+static void anon_munmap(struct file *file, struct vm_area_struct *vma, -+ unsigned long start, unsigned long len) -+{ -+ struct inode *inode = file->f_dentry->d_inode; -+ struct shmem_inode_info *info = SHMEM_I(inode); -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ struct page *page; -+ unsigned long addr, idx, *count; -+ -+ for(addr = start; addr < start + len; addr += PAGE_SIZE){ -+ idx = (addr - vma->vm_start + vma->vm_pgoff); -+ idx >>= PAGE_CACHE_SHIFT; -+ -+ count = shmem_map_count(info, idx, NULL); -+ BUG_ON(count == NULL); -+ -+ (*count)--; -+ if(*count > 0) -+ continue; -+ -+ pgd = pgd_offset(vma->vm_mm, addr); -+ if(pgd_none(*pgd)) -+ continue; -+ -+ pmd = pmd_offset(pgd, addr); -+ if(pmd_none(*pmd)) -+ continue; -+ -+ pte = pte_offset(pmd, addr); -+ if(!pte_present(*pte)) /* XXX need to handle swapped pages */ -+ continue; -+ -+ *pte = pte_mkclean(*pte); -+ -+ page = pte_page(*pte); -+ LockPage(page); -+ lru_cache_del(page); -+ ClearPageDirty(page); -+ remove_inode_page(page); -+ UnlockPage(page); -+ -+ page_cache_release(page); -+ } -+} -+ -+int anon_release(struct inode *inode, struct file *file) -+{ -+ if(file->private_data != NULL) -+ fput(file->private_data); -+ return(0); -+} -+ -+struct file_operations anon_file_operations = { -+ .mmap = anon_mmap, -+ .munmap = anon_munmap, -+ .release = anon_release, -+}; diff --git a/lustre/kernel_patches/patches/uml-sigusr1-2.4-vanilla.patch b/lustre/kernel_patches/patches/uml-sigusr1-2.4-vanilla.patch deleted file mode 100644 index fa4ccae..0000000 --- a/lustre/kernel_patches/patches/uml-sigusr1-2.4-vanilla.patch +++ /dev/null @@ -1,22 +0,0 @@ -Index: linux-2.4.24/arch/um/os-Linux/process.c -=================================================================== ---- linux-2.4.24.orig/arch/um/os-Linux/process.c 2005-02-14 14:25:32.784128506 -0500 -+++ linux-2.4.24/arch/um/os-Linux/process.c 2005-02-14 14:26:24.990396165 -0500 -@@ -7,6 +7,7 @@ - #include <stdio.h> - #include <errno.h> - #include <signal.h> -+#include <linux/unistd.h> - #include <sys/mman.h> - #include <sys/wait.h> - #include "os.h" -@@ -92,7 +93,8 @@ - - void os_usr1_process(int pid) - { -- kill(pid, SIGUSR1); -+ syscall(__NR_tkill, pid, SIGUSR1); -+/* tkill(pid, SIGUSR1);*/ - } - - int os_getpid(void) diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch deleted file mode 100644 index 6778eec..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-hp.patch +++ /dev/null @@ -1,1948 +0,0 @@ - fs/dcache.c | 19 ++ - fs/exec.c | 17 +- - fs/namei.c | 330 +++++++++++++++++++++++++++++++++++++++------- - fs/namespace.c | 28 ++- - fs/open.c | 172 +++++++++++++++++------ - fs/proc/base.c | 3 - fs/stat.c | 52 ++++--- - include/linux/dcache.h | 60 ++++++++ - include/linux/fs.h | 32 ++++ - include/linux/fs_struct.h | 4 - kernel/exit.c | 3 - kernel/fork.c | 3 - kernel/ksyms.c | 1 - 13 files changed, 591 insertions(+), 133 deletions(-) - -Index: linux/fs/dcache.c -=================================================================== ---- linux.orig/fs/dcache.c Thu Nov 28 18:53:15 2002 -+++ linux/fs/dcache.c Wed Mar 17 13:11:25 2004 -@@ -181,6 +181,13 @@ - spin_unlock(&dcache_lock); - return 0; - } -+ -+ /* network invalidation by Lustre */ -+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { -+ spin_unlock(&dcache_lock); -+ return 0; -+ } -+ - /* - * Check whether to do a partial shrink_dcache - * to get rid of unused child entries. -@@ -830,13 +837,19 @@ - * Adds a dentry to the hash according to its name. - */ - --void d_rehash(struct dentry * entry) -+void __d_rehash(struct dentry * entry, int lock) - { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); -- spin_lock(&dcache_lock); -+ if (lock) spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); -- spin_unlock(&dcache_lock); -+ if (lock) spin_unlock(&dcache_lock); -+} -+EXPORT_SYMBOL(__d_rehash); -+ -+void d_rehash(struct dentry * entry) -+{ -+ __d_rehash(entry, 1); - } - - #define do_switch(x,y) do { \ -Index: linux/fs/exec.c -=================================================================== ---- linux.orig/fs/exec.c Wed Mar 17 13:00:38 2004 -+++ linux/fs/exec.c Wed Mar 17 13:11:25 2004 -@@ -115,8 +115,10 @@ - struct file * file; - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- error = user_path_walk(library, &nd); -+ error = user_path_walk_it(library, &nd, &it); - if (error) - goto out; - -@@ -128,7 +130,8 @@ - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -371,8 +374,10 @@ - struct inode *inode; - struct file *file; - int err = 0; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); - file = ERR_PTR(err); - if (!err) { - inode = nd.dentry->d_inode; -@@ -384,7 +389,8 @@ - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { -@@ -396,6 +402,7 @@ - return file; - } - } -+ intent_release(&it); - path_release(&nd); - } - goto out; -@@ -1120,7 +1127,7 @@ - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux/fs/namei.c -=================================================================== ---- linux.orig/fs/namei.c Wed Mar 17 13:00:37 2004 -+++ linux/fs/namei.c Wed Mar 17 13:12:31 2004 -@@ -94,6 +94,13 @@ - * XEmacs seems to be relying on it... - */ - -+void intent_release(struct lookup_intent *it) -+{ -+ if (it && it->it_op_release) -+ it->it_op_release(it); -+ -+} -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -260,10 +267,19 @@ - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * dentry = d_lookup(parent, name); - -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -281,11 +297,15 @@ - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - -+again: -+ counter++; - down(&dir->i_sem); - /* - * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup_it) -+ result = dir->i_op->lookup_it(dir, dentry, it, flags); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -321,6 +344,15 @@ - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate_it) { -+ if (!result->d_op->d_revalidate_it(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; -+ } - } - return result; - } -@@ -332,7 +364,8 @@ - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= 5) -@@ -346,10 +379,18 @@ - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - err = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (!err && it != NULL && !(it->d.lustre.it_int_flags & IT_FL_FOLLOWED)) { -+ /* vfs_follow_link was never called */ -+ intent_release(it); -+ path_release(nd); -+ err = -ENOLINK; -+ } - current->link_count--; - return err; - loop: -+ intent_release(it); - path_release(nd); - return -ELOOP; - } -@@ -379,15 +420,26 @@ - return __follow_up(mnt, dentry); - } - --static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) -+static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry, -+ struct lookup_intent *it) - { - struct vfsmount *mounted; - - spin_lock(&dcache_lock); - mounted = lookup_mnt(*mnt, *dentry); - if (mounted) { -+ int opc = 0, mode = 0; - *mnt = mntget(mounted); - spin_unlock(&dcache_lock); -+ if (it) { -+ opc = it->it_op; -+ mode = it->it_create_mode; -+ } -+ intent_release(it); -+ if (it) { -+ it->it_op = opc; -+ it->it_create_mode = mode; -+ } - dput(*dentry); - mntput(mounted->mnt_parent); - *dentry = dget(mounted->mnt_root); -@@ -399,7 +451,7 @@ - - int follow_down(struct vfsmount **mnt, struct dentry **dentry) - { -- return __follow_down(mnt,dentry); -+ return __follow_down(mnt, dentry, NULL); - } - - static inline void follow_dotdot(struct nameidata *nd) -@@ -435,7 +487,7 @@ - mntput(nd->mnt); - nd->mnt = parent; - } -- while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry)) -+ while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry, NULL)) - ; - } - -@@ -447,7 +499,8 @@ - * - * We expect 'base' to be positive and a directory. - */ --int link_path_walk(const char * name, struct nameidata *nd) -+int link_path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -520,15 +573,15 @@ - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; - } - /* Check mountpoints.. */ -- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry)) -+ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, NULL)) - ; - - err = -ENOENT; -@@ -540,7 +593,7 @@ - goto out_dput; - - if (inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, NULL); - dput(dentry); - if (err) - goto return_err; -@@ -556,7 +609,7 @@ - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup_it) - break; - continue; - /* here ends the main loop */ -@@ -583,19 +636,19 @@ - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, 0); -+ dentry = cached_lookup(nd->dentry, &this, 0, it); - if (!dentry) { -- dentry = real_lookup(nd->dentry, &this, 0); -+ dentry = real_lookup(nd->dentry, &this, 0, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; - } -- while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry)) -+ while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry, it)) - ; - inode = dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op && inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -609,7 +662,8 @@ - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || -+ (!inode->i_op->lookup && !inode->i_op->lookup_it)) - break; - } - goto return_base; -@@ -633,6 +687,34 @@ - * Check the cached dentry for staleness. - */ - dentry = nd->dentry; -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ err = -ESTALE; -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) { -+ struct dentry *new; -+ err = permission(dentry->d_parent->d_inode, -+ MAY_EXEC); -+ if (err) -+ break; -+ new = real_lookup(dentry->d_parent, -+ &dentry->d_name, 0, it); -+ if (IS_ERR(new)) { -+ err = PTR_ERR(new); -+ break; -+ } -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = new; -+ } -+ if (!nd->dentry->d_inode) -+ goto no_inode; -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if (!nd->dentry->d_inode->i_op || -+ (!nd->dentry->d_inode->i_op->lookup && -+ !nd->dentry->d_inode->i_op->lookup_it)) -+ break; -+ } -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - err = -ESTALE; - if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -646,15 +721,28 @@ - dput(dentry); - break; - } -+ if (err) -+ intent_release(it); - path_release(nd); - return_err: - return err; - } - -+int link_path_walk(const char * name, struct nameidata *nd) -+{ -+ return link_path_walk_it(name, nd, NULL); -+} -+ -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return link_path_walk_it(name, nd, it); -+} -+ - int path_walk(const char * name, struct nameidata *nd) - { - current->total_link_count = 0; -- return link_path_walk(name, nd); -+ return link_path_walk_it(name, nd, NULL); - } - - /* SMP-safe */ -@@ -739,6 +827,17 @@ - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+ -+/* SMP-safe */ - int path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -753,6 +852,7 @@ - { - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->intent = NULL; - if (*name=='/') - return walk_init_root(name,nd); - read_lock(¤t->fs->lock); -@@ -767,7 +867,8 @@ - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -790,13 +891,16 @@ - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup_it) -+ dentry = inode->i_op->lookup_it(inode, new, it, 0); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -808,6 +912,12 @@ - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -829,7 +939,7 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -860,6 +970,23 @@ - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -955,7 +1082,8 @@ - return retval; - } - --int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - int error; - -@@ -968,12 +1096,15 @@ - goto exit_lock; - - error = -EACCES; /* shouldn't it be ENOSYS? */ -- if (!dir->i_op || !dir->i_op->create) -+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it)) - goto exit_lock; - - DQUOT_INIT(dir); - lock_kernel(); -- error = dir->i_op->create(dir, dentry, mode); -+ if (dir->i_op->create_it) -+ error = dir->i_op->create_it(dir, dentry, mode, it); -+ else -+ error = dir->i_op->create(dir, dentry, mode); - unlock_kernel(); - exit_lock: - up(&dir->i_zombie); -@@ -982,6 +1113,11 @@ - return error; - } - -+int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ return vfs_create_it(dir, dentry, mode, NULL); -+} -+ - /* - * open_namei() - * -@@ -996,7 +1132,8 @@ - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1006,11 +1143,14 @@ - - acc_mode = ACC_MODE(flag); - -+ if (it) -+ it->it_flags = flag; -+ - /* - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1020,6 +1160,10 @@ - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_create_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1035,7 +1179,7 @@ - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1044,11 +1188,12 @@ - goto exit; - } - -+ it->it_create_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { - if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; -- error = vfs_create(dir->d_inode, dentry, mode); -+ error = vfs_create_it(dir->d_inode, dentry, mode, it); - up(&dir->d_inode->i_sem); - dput(nd->dentry); - nd->dentry = dentry; -@@ -1073,7 +1218,7 @@ - error = -ELOOP; - if (flag & O_NOFOLLOW) - goto exit_dput; -- while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry)); -+ while (__follow_down(&nd->mnt,&dentry,it) && d_mountpoint(dentry)); - } - error = -ENOENT; - if (!dentry->d_inode) -@@ -1152,7 +1297,7 @@ - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1164,8 +1309,10 @@ - return 0; - - exit_dput: -+ intent_release(it); - dput(dentry); - exit: -+ intent_release(it); - path_release(nd); - return error; - -@@ -1184,7 +1331,16 @@ - * are done. Procfs-like symlinks just set LAST_BIND. - */ - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) { -+ intent_release(it); -+ } else if (it != NULL && !(it->d.lustre.it_int_flags & IT_FL_FOLLOWED)) { -+ /* vfs_follow_link was never called */ -+ intent_release(it); -+ path_release(nd); -+ error = -ENOLINK; -+ } - dput(dentry); - if (error) - return error; -@@ -1206,13 +1362,20 @@ - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --static struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+static struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1220,7 +1383,7 @@ - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1276,7 +1439,20 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1298,6 +1474,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1345,7 +1522,18 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 1); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 1, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1354,6 +1542,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1454,8 +1643,16 @@ - error = -EBUSY; - goto exit1; - } -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1513,8 +1710,15 @@ - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - /* Why not before? Because we want correct error value */ -@@ -1581,15 +1785,27 @@ - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+ out2: - path_release(&nd); --out: -+ out: - putname(to); - } - putname(from); -@@ -1665,7 +1881,18 @@ - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -- new_dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out_release; -+ } -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } -+ new_dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1709,7 +1936,7 @@ - * locking]. - */ - int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - struct inode *target; -@@ -1788,7 +2015,7 @@ - } - - int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - -@@ -1876,9 +2103,18 @@ - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ lock_kernel(); -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ unlock_kernel(); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - double_lock(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd.last, old_dir); -+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); - error = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto exit3; -@@ -1894,16 +2130,16 @@ - if (newnd.last.name[newnd.last.len]) - goto exit4; - } -- new_dentry = lookup_hash(&newnd.last, new_dir); -+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; - -+ - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); - unlock_kernel(); -- - dput(new_dentry); - exit4: - dput(old_dentry); -@@ -1954,20 +2190,28 @@ - } - - static inline int --__vfs_follow_link(struct nameidata *nd, const char *link) -+__vfs_follow_link(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) - { - int res = 0; - char *name; - if (IS_ERR(link)) - goto fail; - -+ if (it == NULL) -+ it = nd->intent; -+ else if (it != nd->intent) -+ printk("it != nd->intent: tell phil@clusterfs.com\n"); -+ if (it != NULL) -+ it->d.lustre.it_int_flags |= IT_FL_FOLLOWED; -+ - if (*link == '/') { - path_release(nd); - if (!walk_init_root(link, nd)) - /* weird __emul_prefix() stuff did it */ - goto out; - } -- res = link_path_walk(link, nd); -+ res = link_path_walk_it(link, nd, it); - out: - if (current->link_count || res || nd->last_type!=LAST_NORM) - return res; -@@ -1989,7 +2233,13 @@ - - int vfs_follow_link(struct nameidata *nd, const char *link) - { -- return __vfs_follow_link(nd, link); -+ return __vfs_follow_link(nd, link, NULL); -+} -+ -+int vfs_follow_link_it(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) -+{ -+ return __vfs_follow_link(nd, link, it); - } - - /* get the link contents into pagecache */ -@@ -2031,7 +2281,7 @@ - { - struct page *page = NULL; - char *s = page_getlink(dentry, &page); -- int res = __vfs_follow_link(nd, s); -+ int res = __vfs_follow_link(nd, s, NULL); - if (page) { - kunmap(page); - page_cache_release(page); -Index: linux/fs/namespace.c -=================================================================== ---- linux.orig/fs/namespace.c Thu Nov 28 18:53:15 2002 -+++ linux/fs/namespace.c Wed Mar 17 13:11:25 2004 -@@ -99,6 +99,7 @@ - { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; -+ UNPIN(old_nd->dentry, old_nd->mnt, 1); - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); -@@ -110,6 +111,7 @@ - { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); -+ PIN(nd->dentry, nd->mnt, 1); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; -@@ -485,14 +487,17 @@ - { - struct nameidata old_nd; - struct vfsmount *mnt = NULL; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int err = mount_is_safe(nd); - if (err) - return err; - if (!old_name || !*old_name) - return -EINVAL; -- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd); -- if (err) -+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it); -+ if (err) { -+ intent_release(&it); - return err; -+ } - - down_write(¤t->namespace->sem); - err = -EINVAL; -@@ -515,6 +520,7 @@ - } - - up_write(¤t->namespace->sem); -+ intent_release(&it); - path_release(&old_nd); - return err; - } -@@ -698,6 +704,7 @@ - unsigned long flags, void *data_page) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int retval = 0; - int mnt_flags = 0; - -@@ -722,10 +729,11 @@ - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); - - /* ... and get the mountpoint */ -- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -- if (retval) -+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); -+ if (retval) { -+ intent_release(&it); - return retval; -- -+ } - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, - data_page); -@@ -736,6 +744,8 @@ - else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, - dev_name, data_page); -+ -+ intent_release(&it); - path_release(&nd); - return retval; - } -@@ -901,6 +911,8 @@ - { - struct vfsmount *tmp; - struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; -+ struct lookup_intent new_it = { .it_op = IT_GETATTR }; -+ struct lookup_intent old_it = { .it_op = IT_GETATTR }; - int error; - - if (!capable(CAP_SYS_ADMIN)) -@@ -908,14 +920,14 @@ - - lock_kernel(); - -- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it); - if (error) - goto out0; - error = -EINVAL; - if (!check_mnt(new_nd.mnt)) - goto out1; - -- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); -+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it); - if (error) - goto out1; - -@@ -970,8 +982,10 @@ - up(&old_nd.dentry->d_inode->i_zombie); - up_write(¤t->namespace->sem); - path_release(&user_nd); -+ intent_release(&old_it); - path_release(&old_nd); - out1: -+ intent_release(&new_it); - path_release(&new_nd); - out0: - unlock_kernel(); -Index: linux/fs/open.c -=================================================================== ---- linux.orig/fs/open.c Thu Nov 28 18:53:15 2002 -+++ linux/fs/open.c Wed Mar 17 13:11:25 2004 -@@ -19,6 +19,8 @@ - #include <asm/uaccess.h> - - #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) -+extern int path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it); - - int vfs_statfs(struct super_block *sb, struct statfs *buf) - { -@@ -95,9 +97,10 @@ - write_unlock(&files->file_lock); - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - struct inode *inode = dentry->d_inode; -+ struct inode_operations *op = dentry->d_inode->i_op; - int error; - struct iattr newattrs; - -@@ -108,7 +111,13 @@ - down(&inode->i_sem); - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -- error = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ } else -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); - return error; - } -@@ -118,12 +127,13 @@ - struct nameidata nd; - struct inode * inode; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd, &it); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -163,11 +173,13 @@ - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ intent_release(&it); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -215,7 +227,7 @@ - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -260,11 +272,13 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -279,11 +293,25 @@ - goto dput_and_out; - - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!times) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; - } -+ - error = notify_change(nd.dentry, &newattrs); - dput_and_out: - path_release(&nd); -@@ -304,12 +332,14 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -324,7 +354,20 @@ - newattrs.ia_atime = times[0].tv_sec; - newattrs.ia_mtime = times[1].tv_sec; - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!utimes) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; -@@ -347,6 +390,7 @@ - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -364,13 +408,14 @@ - else - current->cap_effective = current->cap_permitted; - -- res = user_path_walk(filename, &nd); -+ res = user_path_walk_it(filename, &nd, &it); - if (!res) { - res = permission(nd.dentry->d_inode, mode); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ intent_release(&it); - path_release(&nd); - } - -@@ -385,8 +430,9 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); -+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); - if (error) - goto out; - -@@ -397,6 +443,7 @@ - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -436,9 +483,10 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it); - if (error) - goto out; - -@@ -454,39 +502,56 @@ - set_fs_altroot(); - error = 0; - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode *inode = dentry->d_inode; - struct iattr newattrs; -+ int err = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -+ if (inode->i_op->setattr_raw) { -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (err != -EOPNOTSUPP) -+ goto out; -+ } - -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); - --out_putf: -+out: -+ return err; -+} -+ -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); -+ - fput(file); - out: - return err; -@@ -495,30 +560,14 @@ - asmlinkage long sys_chmod(const char * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; -- -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; - -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; -+ error = chmod_common(nd.dentry, mode); - -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -- --dput_and_out: - path_release(&nd); - out: - return error; -@@ -538,6 +587,20 @@ - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } -+ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -@@ -642,6 +705,7 @@ - { - int namei_flags, error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_OPEN }; - - namei_flags = flags; - if ((namei_flags+1) & O_ACCMODE) -@@ -649,14 +713,15 @@ - if (namei_flags & O_TRUNC) - namei_flags |= 2; - -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return dentry_open(nd.dentry, nd.mnt, flags); -+ error = open_namei_it(filename, namei_flags, mode, &nd, &it); -+ if (error) -+ return ERR_PTR(error); - -- return ERR_PTR(error); -+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); - } - --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it) - { - struct file * f; - struct inode *inode; -@@ -693,12 +758,15 @@ - } - - if (f->f_op && f->f_op->open) { -+ f->f_it = it; - error = f->f_op->open(inode,f); -+ f->f_it = NULL; - if (error) - goto cleanup_all; - } - f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - -+ intent_release(it); - return f; - - cleanup_all: -@@ -713,11 +781,17 @@ - cleanup_file: - put_filp(f); - cleanup_dentry: -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); - } - -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ return dentry_open_it(dentry, mnt, flags, NULL); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ -Index: linux/fs/proc/base.c -=================================================================== ---- linux.orig/fs/proc/base.c Wed Mar 17 13:00:35 2004 -+++ linux/fs/proc/base.c Wed Mar 17 13:11:25 2004 -@@ -481,6 +481,9 @@ - - error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt); - nd->last_type = LAST_BIND; -+ -+ if (nd->intent != NULL) -+ nd->intent->d.lustre.it_int_flags |= IT_FL_FOLLOWED; - out: - return error; - } -Index: linux/fs/stat.c -=================================================================== ---- linux.orig/fs/stat.c Thu Sep 13 19:04:43 2001 -+++ linux/fs/stat.c Wed Mar 17 13:12:31 2004 -@@ -17,10 +17,12 @@ - * Revalidate the inode. This is required for proper NFS attribute caching. - */ - static __inline__ int --do_revalidate(struct dentry *dentry) -+do_revalidate(struct dentry *dentry, struct lookup_intent *it) - { - struct inode * inode = dentry->d_inode; -- if (inode->i_op && inode->i_op->revalidate) -+ if (inode->i_op && inode->i_op->revalidate_it) -+ return inode->i_op->revalidate_it(dentry, it); -+ else if (inode->i_op && inode->i_op->revalidate) - return inode->i_op->revalidate(dentry); - return 0; - } -@@ -135,13 +137,15 @@ - asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -151,13 +155,15 @@ - asmlinkage long sys_newstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -172,13 +178,15 @@ - asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -189,13 +197,15 @@ - asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -216,7 +226,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); -@@ -235,7 +245,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); -@@ -257,7 +267,7 @@ - - error = -EINVAL; - if (inode->i_op && inode->i_op->readlink && -- !(error = do_revalidate(nd.dentry))) { -+ !(error = do_revalidate(nd.dentry, NULL))) { - UPDATE_ATIME(inode); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); - } -@@ -333,12 +343,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -348,12 +360,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -368,7 +382,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); -Index: linux/include/linux/dcache.h -=================================================================== ---- linux.orig/include/linux/dcache.h Thu Nov 28 18:53:15 2002 -+++ linux/include/linux/dcache.h Wed Mar 17 13:11:25 2004 -@@ -6,6 +6,51 @@ - #include <asm/atomic.h> - #include <linux/mount.h> - #include <linux/kernel.h> -+#include <linux/string.h> -+ -+#define IT_OPEN 0x0001 -+#define IT_CREAT 0x0002 -+#define IT_READDIR 0x0004 -+#define IT_GETATTR 0x0008 -+#define IT_LOOKUP 0x0010 -+#define IT_UNLINK 0x0020 -+#define IT_GETXATTR 0x0040 -+#define IT_EXEC 0x0080 -+#define IT_PIN 0x0100 -+ -+#define IT_FL_LOCKED 0x0001 -+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */ -+ -+#define INTENT_MAGIC 0x19620323 -+ -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; -+ int it_int_flags; -+}; -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_init(struct lookup_intent *it, int op, int flags) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+ it->it_flags = flags; -+} -+ - - /* - * linux/include/linux/dcache.h -@@ -91,8 +136,22 @@ - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *); -+ void (*d_pin)(struct dentry *, struct vfsmount * , int); -+ void (*d_unpin)(struct dentry *, struct vfsmount *, int); - }; - -+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \ -+ de->d_op->d_pin(de, mnt, flag); -+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \ -+ de->d_op->d_unpin(de, mnt, flag); -+ -+ -+/* defined in fs/namei.c */ -+extern void intent_release(struct lookup_intent *it); -+/* defined in fs/dcache.c */ -+extern void __d_rehash(struct dentry * entry, int lock); -+ - /* the dentry parameter passed to d_hash and d_compare is the parent - * directory of the entries to be compared. It is used in case these - * functions need any directory specific information for determining -@@ -124,6 +183,7 @@ - * s_nfsd_free_path semaphore will be down - */ - #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ - - extern spinlock_t dcache_lock; - -Index: linux/include/linux/fs.h -=================================================================== ---- linux.orig/include/linux/fs.h Wed Mar 17 13:11:23 2004 -+++ linux/include/linux/fs.h Wed Mar 17 13:11:31 2004 -@@ -73,6 +73,7 @@ - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - #define READ 0 - #define WRITE 1 -@@ -340,6 +341,9 @@ - #define ATTR_MTIME_SET 256 - #define ATTR_FORCE 512 /* Not a change, but a change it */ - #define ATTR_ATTR_FLAG 1024 -+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */ -+#define ATTR_CTIME_SET 0x2000 - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -474,6 +478,7 @@ - struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; - struct char_device *i_cdev; -+ void *i_filterdata; - - unsigned long i_dnotify_mask; /* Directory notify events */ - struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -576,6 +581,7 @@ - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_it; - - /* preallocated helper kiobuf to speedup O_DIRECT */ - struct kiobuf *f_iobuf; -@@ -697,6 +703,7 @@ - struct qstr last; - unsigned int flags; - int last_type; -+ struct lookup_intent *intent; - }; - - /* -@@ -817,7 +824,8 @@ - extern int vfs_link(struct dentry *, struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry); - - /* - * File types -@@ -877,21 +885,32 @@ - - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); -+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,int); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -+ int (*revalidate_it) (struct dentry *, struct lookup_intent *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); - int (*setxattr) (struct dentry *, const char *, void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1088,10 +1107,14 @@ - - asmlinkage long sys_open(const char *, int, int); - asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern int open_namei_it(const char *filename, int namei_flags, int mode, -+ struct nameidata *nd, struct lookup_intent *it); -+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1354,6 +1377,7 @@ - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1365,6 +1389,8 @@ - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void _inode_init_once(struct inode *); -@@ -1503,6 +1529,8 @@ - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; -Index: linux/include/linux/fs_struct.h -=================================================================== ---- linux.orig/include/linux/fs_struct.h Fri Jul 13 18:10:44 2001 -+++ linux/include/linux/fs_struct.h Wed Mar 17 13:11:25 2004 -@@ -34,10 +34,12 @@ - write_lock(&fs->lock); - old_root = fs->root; - old_rootmnt = fs->rootmnt; -+ PIN(dentry, mnt, 1); - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); - write_unlock(&fs->lock); - if (old_root) { -+ UNPIN(old_root, old_rootmnt, 1); - dput(old_root); - mntput(old_rootmnt); - } -@@ -57,10 +59,12 @@ - write_lock(&fs->lock); - old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; -+ PIN(dentry, mnt, 0); - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); - write_unlock(&fs->lock); - if (old_pwd) { -+ UNPIN(old_pwd, old_pwdmnt, 0); - dput(old_pwd); - mntput(old_pwdmnt); - } -Index: linux/kernel/exit.c -=================================================================== ---- linux.orig/kernel/exit.c Wed Mar 17 13:00:38 2004 -+++ linux/kernel/exit.c Wed Mar 17 13:11:25 2004 -@@ -239,11 +239,14 @@ - { - /* No need to hold fs->lock if we are killing it */ - if (atomic_dec_and_test(&fs->count)) { -+ UNPIN(fs->pwd, fs->pwdmnt, 0); -+ UNPIN(fs->root, fs->rootmnt, 1); - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { -+ UNPIN(fs->altroot, fs->altrootmnt, 1); - dput(fs->altroot); - mntput(fs->altrootmnt); - } -Index: linux/kernel/fork.c -=================================================================== ---- linux.orig/kernel/fork.c Wed Mar 17 13:00:38 2004 -+++ linux/kernel/fork.c Wed Mar 17 13:11:25 2004 -@@ -387,10 +387,13 @@ - fs->umask = old->umask; - read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); -+ PIN(old->pwd, old->pwdmnt, 0); -+ PIN(old->root, old->rootmnt, 1); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { -+ PIN(old->altroot, old->altrootmnt, 1); - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); - } else { -Index: linux/kernel/ksyms.c -=================================================================== ---- linux.orig/kernel/ksyms.c Wed Mar 17 13:11:23 2004 -+++ linux/kernel/ksyms.c Wed Mar 17 13:11:25 2004 -@@ -315,6 +315,7 @@ - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch deleted file mode 100644 index 3205465..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.20-vanilla.patch +++ /dev/null @@ -1,1854 +0,0 @@ - fs/dcache.c | 19 ++ - fs/exec.c | 17 +- - fs/namei.c | 295 +++++++++++++++++++++++++++++++++++++++------- - fs/namespace.c | 28 +++- - fs/open.c | 172 +++++++++++++++++++------- - fs/stat.c | 52 +++++--- - include/linux/dcache.h | 60 +++++++++ - include/linux/fs.h | 32 ++++ - include/linux/fs_struct.h | 4 - kernel/exit.c | 3 - kernel/fork.c | 3 - kernel/ksyms.c | 1 - 12 files changed, 558 insertions(+), 128 deletions(-) - -Index: linux-2.4.24/fs/dcache.c -=================================================================== ---- linux-2.4.24.orig/fs/dcache.c Fri Jun 13 07:51:37 2003 -+++ linux-2.4.24/fs/dcache.c Wed Mar 17 17:36:14 2004 -@@ -181,6 +181,13 @@ int d_invalidate(struct dentry * dentry) - spin_unlock(&dcache_lock); - return 0; - } -+ -+ /* network invalidation by Lustre */ -+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { -+ spin_unlock(&dcache_lock); -+ return 0; -+ } -+ - /* - * Check whether to do a partial shrink_dcache - * to get rid of unused child entries. -@@ -830,13 +837,19 @@ void d_delete(struct dentry * dentry) - * Adds a dentry to the hash according to its name. - */ - --void d_rehash(struct dentry * entry) -+void __d_rehash(struct dentry * entry, int lock) - { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); -- spin_lock(&dcache_lock); -+ if (lock) spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); -- spin_unlock(&dcache_lock); -+ if (lock) spin_unlock(&dcache_lock); -+} -+EXPORT_SYMBOL(__d_rehash); -+ -+void d_rehash(struct dentry * entry) -+{ -+ __d_rehash(entry, 1); - } - - #define do_switch(x,y) do { \ -Index: linux-2.4.24/fs/exec.c -=================================================================== ---- linux-2.4.24.orig/fs/exec.c Fri Nov 28 10:26:21 2003 -+++ linux-2.4.24/fs/exec.c Wed Mar 17 17:36:14 2004 -@@ -112,8 +112,10 @@ asmlinkage long sys_uselib(const char * - struct file * file; - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- error = user_path_walk(library, &nd); -+ error = user_path_walk_it(library, &nd, &it); - if (error) - goto out; - -@@ -125,7 +127,8 @@ asmlinkage long sys_uselib(const char * - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -374,8 +377,10 @@ struct file *open_exec(const char *name) - struct inode *inode; - struct file *file; - int err = 0; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); - file = ERR_PTR(err); - if (!err) { - inode = nd.dentry->d_inode; -@@ -387,7 +392,8 @@ struct file *open_exec(const char *name) - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { -@@ -399,6 +405,7 @@ out: - return file; - } - } -+ intent_release(&it); - path_release(&nd); - } - goto out; -@@ -1132,7 +1139,7 @@ int do_coredump(long signr, struct pt_re - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.4.24/fs/namei.c -=================================================================== ---- linux-2.4.24.orig/fs/namei.c Mon Aug 25 04:44:43 2003 -+++ linux-2.4.24/fs/namei.c Wed Mar 17 17:36:52 2004 -@@ -94,6 +94,13 @@ - * XEmacs seems to be relying on it... - */ - -+void intent_release(struct lookup_intent *it) -+{ -+ if (it && it->it_op_release) -+ it->it_op_release(it); -+ -+} -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd) - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * dentry = d_lookup(parent, name); - -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - -+again: -+ counter++; - down(&dir->i_sem); - /* - * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup_it) -+ result = dir->i_op->lookup_it(dir, dentry, it, flags); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate_it) { -+ if (!result->d_op->d_revalidate_it(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; -+ } - } - return result; - } -@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= 5) -@@ -346,10 +379,12 @@ static inline int do_follow_link(struct - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - err = dentry->d_inode->i_op->follow_link(dentry, nd); - current->link_count--; - return err; - loop: -+ intent_release(it); - path_release(nd); - return -ELOOP; - } -@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct - * - * We expect 'base' to be positive and a directory. - */ --int link_path_walk(const char * name, struct nameidata *nd) -+int link_path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -520,9 +556,9 @@ int link_path_walk(const char * name, st - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -540,7 +576,7 @@ int link_path_walk(const char * name, st - goto out_dput; - - if (inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, NULL); - dput(dentry); - if (err) - goto return_err; -@@ -556,7 +592,7 @@ int link_path_walk(const char * name, st - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup_it) - break; - continue; - /* here ends the main loop */ -@@ -583,9 +619,9 @@ last_component: - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, 0); -+ dentry = cached_lookup(nd->dentry, &this, 0, it); - if (!dentry) { -- dentry = real_lookup(nd->dentry, &this, 0); -+ dentry = real_lookup(nd->dentry, &this, 0, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -595,7 +631,7 @@ last_component: - inode = dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op && inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -609,7 +645,8 @@ last_component: - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || -+ (!inode->i_op->lookup && !inode->i_op->lookup_it)) - break; - } - goto return_base; -@@ -635,6 +672,34 @@ return_reval: - * Check the cached dentry for staleness. - */ - dentry = nd->dentry; -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ err = -ESTALE; -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) { -+ struct dentry *new; -+ err = permission(dentry->d_parent->d_inode, -+ MAY_EXEC); -+ if (err) -+ break; -+ new = real_lookup(dentry->d_parent, -+ &dentry->d_name, 0, it); -+ if (IS_ERR(new)) { -+ err = PTR_ERR(new); -+ break; -+ } -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = new; -+ } -+ if (!nd->dentry->d_inode) -+ goto no_inode; -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if (!nd->dentry->d_inode->i_op || -+ (!nd->dentry->d_inode->i_op->lookup && -+ !nd->dentry->d_inode->i_op->lookup_it)) -+ break; -+ } -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - err = -ESTALE; - if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -648,15 +706,28 @@ out_dput: - dput(dentry); - break; - } -+ if (err) -+ intent_release(it); - path_release(nd); - return_err: - return err; - } - -+int link_path_walk(const char * name, struct nameidata *nd) -+{ -+ return link_path_walk_it(name, nd, NULL); -+} -+ -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return link_path_walk_it(name, nd, it); -+} -+ - int path_walk(const char * name, struct nameidata *nd) - { - current->total_link_count = 0; -- return link_path_walk(name, nd); -+ return link_path_walk_it(name, nd, NULL); - } - - /* SMP-safe */ -@@ -741,6 +812,17 @@ walk_init_root(const char *name, struct - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+ -+/* SMP-safe */ - int path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -755,6 +837,7 @@ int path_init(const char *name, unsigned - { - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->intent = NULL; - if (*name=='/') - return walk_init_root(name,nd); - read_lock(¤t->fs->lock); -@@ -769,7 +852,8 @@ int path_init(const char *name, unsigned - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -792,13 +876,16 @@ struct dentry * lookup_hash(struct qstr - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup_it) -+ dentry = inode->i_op->lookup_it(inode, new, it, 0); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -810,6 +897,12 @@ out: - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -831,7 +924,7 @@ struct dentry * lookup_one_len(const cha - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -862,6 +955,23 @@ int __user_walk(const char *name, unsign - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -957,7 +1067,8 @@ static inline int lookup_flags(unsigned - return retval; - } - --int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - int error; - -@@ -970,12 +1081,15 @@ int vfs_create(struct inode *dir, struct - goto exit_lock; - - error = -EACCES; /* shouldn't it be ENOSYS? */ -- if (!dir->i_op || !dir->i_op->create) -+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it)) - goto exit_lock; - - DQUOT_INIT(dir); - lock_kernel(); -- error = dir->i_op->create(dir, dentry, mode); -+ if (dir->i_op->create_it) -+ error = dir->i_op->create_it(dir, dentry, mode, it); -+ else -+ error = dir->i_op->create(dir, dentry, mode); - unlock_kernel(); - exit_lock: - up(&dir->i_zombie); -@@ -984,6 +1098,11 @@ exit_lock: - return error; - } - -+int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ return vfs_create_it(dir, dentry, mode, NULL); -+} -+ - /* - * open_namei() - * -@@ -998,7 +1117,8 @@ exit_lock: - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1008,11 +1128,14 @@ int open_namei(const char * pathname, in - - acc_mode = ACC_MODE(flag); - -+ if (it) -+ it->it_flags = flag; -+ - /* - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1022,6 +1145,10 @@ int open_namei(const char * pathname, in - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_create_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1037,7 +1164,7 @@ int open_namei(const char * pathname, in - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1046,10 +1173,11 @@ do_last: - goto exit; - } - -+ it->it_create_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { -- error = vfs_create(dir->d_inode, dentry, -- mode & ~current->fs->umask); -+ error = vfs_create_it(dir->d_inode, dentry, -+ mode & ~current->fs->umask, it); - up(&dir->d_inode->i_sem); - dput(nd->dentry); - nd->dentry = dentry; -@@ -1153,7 +1281,7 @@ ok: - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1165,8 +1293,10 @@ ok: - return 0; - - exit_dput: -+ intent_release(it); - dput(dentry); - exit: -+ intent_release(it); - path_release(nd); - return error; - -@@ -1185,7 +1315,10 @@ do_link: - * are done. Procfs-like symlinks just set LAST_BIND. - */ - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) -+ intent_release(it); - dput(dentry); - if (error) - return error; -@@ -1207,13 +1340,20 @@ do_link: - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --static struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+static struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1221,7 +1361,7 @@ static struct dentry *lookup_create(stru - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1277,7 +1417,20 @@ asmlinkage long sys_mknod(const char * f - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - - mode &= ~current->fs->umask; -@@ -1298,6 +1451,7 @@ asmlinkage long sys_mknod(const char * f - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1345,7 +1499,18 @@ asmlinkage long sys_mkdir(const char * p - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 1); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 1, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_mkdir(nd.dentry->d_inode, dentry, -@@ -1353,6 +1518,7 @@ asmlinkage long sys_mkdir(const char * p - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1453,8 +1619,16 @@ asmlinkage long sys_rmdir(const char * p - error = -EBUSY; - goto exit1; - } -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1512,8 +1686,15 @@ asmlinkage long sys_unlink(const char * - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - /* Why not before? Because we want correct error value */ -@@ -1580,15 +1761,27 @@ asmlinkage long sys_symlink(const char * - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+ out2: - path_release(&nd); --out: -+ out: - putname(to); - } - putname(from); -@@ -1664,7 +1857,18 @@ asmlinkage long sys_link(const char * ol - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -- new_dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out_release; -+ } -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } -+ new_dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1708,7 +1912,7 @@ exit: - * locking]. - */ - int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - struct inode *target; -@@ -1787,7 +1991,7 @@ out_unlock: - } - - int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - -@@ -1875,9 +2079,18 @@ static inline int do_rename(const char * - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ lock_kernel(); -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ unlock_kernel(); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - double_lock(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd.last, old_dir); -+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); - error = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto exit3; -@@ -1893,16 +2106,16 @@ static inline int do_rename(const char * - if (newnd.last.name[newnd.last.len]) - goto exit4; - } -- new_dentry = lookup_hash(&newnd.last, new_dir); -+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; - -+ - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); - unlock_kernel(); -- - dput(new_dentry); - exit4: - dput(old_dentry); -@@ -1953,20 +2166,26 @@ out: - } - - static inline int --__vfs_follow_link(struct nameidata *nd, const char *link) -+__vfs_follow_link(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) - { - int res = 0; - char *name; - if (IS_ERR(link)) - goto fail; - -+ if (it == NULL) -+ it = nd->intent; -+ else if (it != nd->intent) -+ printk("it != nd->intent: tell phil@clusterfs.com\n"); -+ - if (*link == '/') { - path_release(nd); - if (!walk_init_root(link, nd)) - /* weird __emul_prefix() stuff did it */ - goto out; - } -- res = link_path_walk(link, nd); -+ res = link_path_walk_it(link, nd, it); - out: - if (current->link_count || res || nd->last_type!=LAST_NORM) - return res; -@@ -1990,7 +2209,13 @@ fail: - - int vfs_follow_link(struct nameidata *nd, const char *link) - { -- return __vfs_follow_link(nd, link); -+ return __vfs_follow_link(nd, link, NULL); -+} -+ -+int vfs_follow_link_it(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) -+{ -+ return __vfs_follow_link(nd, link, it); - } - - /* get the link contents into pagecache */ -@@ -2032,7 +2257,7 @@ int page_follow_link(struct dentry *dent - { - struct page *page = NULL; - char *s = page_getlink(dentry, &page); -- int res = __vfs_follow_link(nd, s); -+ int res = __vfs_follow_link(nd, s, NULL); - if (page) { - kunmap(page); - page_cache_release(page); -Index: linux-2.4.24/fs/namespace.c -=================================================================== ---- linux-2.4.24.orig/fs/namespace.c Fri Nov 28 10:26:21 2003 -+++ linux-2.4.24/fs/namespace.c Wed Mar 17 17:36:14 2004 -@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount * - { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; -+ UNPIN(old_nd->dentry, old_nd->mnt, 1); - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); -@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount * - { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); -+ PIN(nd->dentry, nd->mnt, 1); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; -@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata - { - struct nameidata old_nd; - struct vfsmount *mnt = NULL; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int err = mount_is_safe(nd); - if (err) - return err; - if (!old_name || !*old_name) - return -EINVAL; -- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd); -- if (err) -+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it); -+ if (err) { -+ intent_release(&it); - return err; -+ } - - down_write(¤t->namespace->sem); - err = -EINVAL; -@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata - } - - up_write(¤t->namespace->sem); -+ intent_release(&it); - path_release(&old_nd); - return err; - } -@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di - unsigned long flags, void *data_page) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int retval = 0; - int mnt_flags = 0; - -@@ -725,10 +732,11 @@ long do_mount(char * dev_name, char * di - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); - - /* ... and get the mountpoint */ -- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -- if (retval) -+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); -+ if (retval) { -+ intent_release(&it); - return retval; -- -+ } - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, - data_page); -@@ -739,6 +747,8 @@ long do_mount(char * dev_name, char * di - else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, - dev_name, data_page); -+ -+ intent_release(&it); - path_release(&nd); - return retval; - } -@@ -904,6 +914,8 @@ asmlinkage long sys_pivot_root(const cha - { - struct vfsmount *tmp; - struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; -+ struct lookup_intent new_it = { .it_op = IT_GETATTR }; -+ struct lookup_intent old_it = { .it_op = IT_GETATTR }; - int error; - - if (!capable(CAP_SYS_ADMIN)) -@@ -911,14 +923,14 @@ asmlinkage long sys_pivot_root(const cha - - lock_kernel(); - -- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it); - if (error) - goto out0; - error = -EINVAL; - if (!check_mnt(new_nd.mnt)) - goto out1; - -- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); -+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it); - if (error) - goto out1; - -@@ -973,8 +985,10 @@ out2: - up(&old_nd.dentry->d_inode->i_zombie); - up_write(¤t->namespace->sem); - path_release(&user_nd); -+ intent_release(&old_it); - path_release(&old_nd); - out1: -+ intent_release(&new_it); - path_release(&new_nd); - out0: - unlock_kernel(); -Index: linux-2.4.24/fs/open.c -=================================================================== ---- linux-2.4.24.orig/fs/open.c Mon Aug 25 04:44:43 2003 -+++ linux-2.4.24/fs/open.c Wed Mar 17 17:36:14 2004 -@@ -19,6 +19,8 @@ - #include <asm/uaccess.h> - - #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) -+extern int path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it); - - int vfs_statfs(struct super_block *sb, struct statfs *buf) - { -@@ -95,9 +97,10 @@ void fd_install(unsigned int fd, struct - write_unlock(&files->file_lock); - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - struct inode *inode = dentry->d_inode; -+ struct inode_operations *op = dentry->d_inode->i_op; - int error; - struct iattr newattrs; - -@@ -109,7 +112,13 @@ int do_truncate(struct dentry *dentry, l - down(&inode->i_sem); - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -- error = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ } else -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); - up_write(&inode->i_alloc_sem); - return error; -@@ -120,12 +129,13 @@ static inline long do_sys_truncate(const - struct nameidata nd; - struct inode * inode; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd, &it); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -165,11 +175,13 @@ static inline long do_sys_truncate(const - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ intent_release(&it); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -217,7 +229,7 @@ static inline long do_sys_ftruncate(unsi - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -262,11 +274,13 @@ asmlinkage long sys_utime(char * filenam - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -281,11 +295,25 @@ asmlinkage long sys_utime(char * filenam - goto dput_and_out; - - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!times) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; - } -+ - error = notify_change(nd.dentry, &newattrs); - dput_and_out: - path_release(&nd); -@@ -306,12 +334,14 @@ asmlinkage long sys_utimes(char * filena - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -326,7 +356,20 @@ asmlinkage long sys_utimes(char * filena - newattrs.ia_atime = times[0].tv_sec; - newattrs.ia_mtime = times[1].tv_sec; - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!utimes) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; -@@ -349,6 +392,7 @@ asmlinkage long sys_access(const char * - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -366,13 +410,14 @@ asmlinkage long sys_access(const char * - else - current->cap_effective = current->cap_permitted; - -- res = user_path_walk(filename, &nd); -+ res = user_path_walk_it(filename, &nd, &it); - if (!res) { - res = permission(nd.dentry->d_inode, mode); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ intent_release(&it); - path_release(&nd); - } - -@@ -387,8 +432,9 @@ asmlinkage long sys_chdir(const char * f - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); -+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); - if (error) - goto out; - -@@ -399,6 +445,7 @@ asmlinkage long sys_chdir(const char * f - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -438,9 +485,10 @@ asmlinkage long sys_chroot(const char * - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it); - if (error) - goto out; - -@@ -456,39 +504,56 @@ asmlinkage long sys_chroot(const char * - set_fs_altroot(); - error = 0; - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode *inode = dentry->d_inode; - struct iattr newattrs; -+ int err = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -+ if (inode->i_op->setattr_raw) { -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (err != -EOPNOTSUPP) -+ goto out; -+ } - -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); - --out_putf: -+out: -+ return err; -+} -+ -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); -+ - fput(file); - out: - return err; -@@ -497,30 +562,14 @@ out: - asmlinkage long sys_chmod(const char * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; -- -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; - -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; -+ error = chmod_common(nd.dentry, mode); - -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -- --dput_and_out: - path_release(&nd); - out: - return error; -@@ -540,6 +589,20 @@ static int chown_common(struct dentry * - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } -+ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -@@ -644,6 +707,7 @@ struct file *filp_open(const char * file - { - int namei_flags, error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_OPEN }; - - namei_flags = flags; - if ((namei_flags+1) & O_ACCMODE) -@@ -651,14 +715,15 @@ struct file *filp_open(const char * file - if (namei_flags & O_TRUNC) - namei_flags |= 2; - -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return dentry_open(nd.dentry, nd.mnt, flags); -+ error = open_namei_it(filename, namei_flags, mode, &nd, &it); -+ if (error) -+ return ERR_PTR(error); - -- return ERR_PTR(error); -+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); - } - --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it) - { - struct file * f; - struct inode *inode; -@@ -695,12 +760,15 @@ struct file *dentry_open(struct dentry * - } - - if (f->f_op && f->f_op->open) { -+ f->f_it = it; - error = f->f_op->open(inode,f); -+ f->f_it = NULL; - if (error) - goto cleanup_all; - } - f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - -+ intent_release(it); - return f; - - cleanup_all: -@@ -715,11 +783,17 @@ cleanup_all: - cleanup_file: - put_filp(f); - cleanup_dentry: -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); - } - -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ return dentry_open_it(dentry, mnt, flags, NULL); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ -Index: linux-2.4.24/fs/stat.c -=================================================================== ---- linux-2.4.24.orig/fs/stat.c Mon Aug 25 04:44:43 2003 -+++ linux-2.4.24/fs/stat.c Wed Mar 17 17:36:52 2004 -@@ -17,10 +17,12 @@ - * Revalidate the inode. This is required for proper NFS attribute caching. - */ - static __inline__ int --do_revalidate(struct dentry *dentry) -+do_revalidate(struct dentry *dentry, struct lookup_intent *it) - { - struct inode * inode = dentry->d_inode; -- if (inode->i_op && inode->i_op->revalidate) -+ if (inode->i_op && inode->i_op->revalidate_it) -+ return inode->i_op->revalidate_it(dentry, it); -+ else if (inode->i_op && inode->i_op->revalidate) - return inode->i_op->revalidate(dentry); - return 0; - } -@@ -137,13 +139,15 @@ static int cp_new_stat(struct inode * in - asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -153,13 +157,15 @@ asmlinkage long sys_stat(char * filename - asmlinkage long sys_newstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -174,13 +180,15 @@ asmlinkage long sys_newstat(char * filen - asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -191,13 +199,15 @@ asmlinkage long sys_lstat(char * filenam - asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -218,7 +228,7 @@ asmlinkage long sys_fstat(unsigned int f - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); -@@ -237,7 +247,7 @@ asmlinkage long sys_newfstat(unsigned in - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); -@@ -259,7 +269,7 @@ asmlinkage long sys_readlink(const char - - error = -EINVAL; - if (inode->i_op && inode->i_op->readlink && -- !(error = do_revalidate(nd.dentry))) { -+ !(error = do_revalidate(nd.dentry, NULL))) { - UPDATE_ATIME(inode); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); - } -@@ -335,12 +345,14 @@ asmlinkage long sys_stat64(char * filena - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -350,12 +362,14 @@ asmlinkage long sys_lstat64(char * filen - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -370,7 +384,7 @@ asmlinkage long sys_fstat64(unsigned lon - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); -Index: linux-2.4.24/include/linux/dcache.h -=================================================================== ---- linux-2.4.24.orig/include/linux/dcache.h Thu Nov 28 15:53:15 2002 -+++ linux-2.4.24/include/linux/dcache.h Wed Mar 17 17:36:14 2004 -@@ -6,6 +6,51 @@ - #include <asm/atomic.h> - #include <linux/mount.h> - #include <linux/kernel.h> -+#include <linux/string.h> -+ -+#define IT_OPEN 0x0001 -+#define IT_CREAT 0x0002 -+#define IT_READDIR 0x0004 -+#define IT_GETATTR 0x0008 -+#define IT_LOOKUP 0x0010 -+#define IT_UNLINK 0x0020 -+#define IT_GETXATTR 0x0040 -+#define IT_EXEC 0x0080 -+#define IT_PIN 0x0100 -+ -+#define IT_FL_LOCKED 0x0001 -+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */ -+ -+#define INTENT_MAGIC 0x19620323 -+ -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; -+ int it_int_flags; -+}; -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_init(struct lookup_intent *it, int op, int flags) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+ it->it_flags = flags; -+} -+ - - /* - * linux/include/linux/dcache.h -@@ -91,8 +136,22 @@ struct dentry_operations { - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *); -+ void (*d_pin)(struct dentry *, struct vfsmount * , int); -+ void (*d_unpin)(struct dentry *, struct vfsmount *, int); - }; - -+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \ -+ de->d_op->d_pin(de, mnt, flag); -+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \ -+ de->d_op->d_unpin(de, mnt, flag); -+ -+ -+/* defined in fs/namei.c */ -+extern void intent_release(struct lookup_intent *it); -+/* defined in fs/dcache.c */ -+extern void __d_rehash(struct dentry * entry, int lock); -+ - /* the dentry parameter passed to d_hash and d_compare is the parent - * directory of the entries to be compared. It is used in case these - * functions need any directory specific information for determining -@@ -124,6 +183,7 @@ d_iput: no no yes - * s_nfsd_free_path semaphore will be down - */ - #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ - - extern spinlock_t dcache_lock; - -Index: linux-2.4.24/include/linux/fs.h -=================================================================== ---- linux-2.4.24.orig/include/linux/fs.h Wed Mar 17 17:36:14 2004 -+++ linux-2.4.24/include/linux/fs.h Wed Mar 17 17:36:14 2004 -@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - #define READ 0 - #define WRITE 1 -@@ -340,6 +341,9 @@ extern void set_bh_page(struct buffer_he - #define ATTR_MTIME_SET 256 - #define ATTR_FORCE 512 /* Not a change, but a change it */ - #define ATTR_ATTR_FLAG 1024 -+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */ -+#define ATTR_CTIME_SET 0x2000 - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -478,6 +482,7 @@ struct inode { - struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; - struct char_device *i_cdev; -+ void *i_filterdata; - - unsigned long i_dnotify_mask; /* Directory notify events */ - struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -582,6 +587,7 @@ struct file { - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_it; - - /* preallocated helper kiobuf to speedup O_DIRECT */ - struct kiobuf *f_iobuf; -@@ -702,6 +708,7 @@ struct nameidata { - struct qstr last; - unsigned int flags; - int last_type; -+ struct lookup_intent *intent; - }; - - /* -@@ -822,7 +829,8 @@ extern int vfs_symlink(struct inode *, s - extern int vfs_link(struct dentry *, struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry); - - /* - * File types -@@ -884,21 +892,32 @@ struct file_operations { - - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); -+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,int); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -+ int (*revalidate_it) (struct dentry *, struct lookup_intent *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); - int (*setxattr) (struct dentry *, const char *, void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1094,10 +1113,14 @@ static inline int get_lease(struct inode - - asmlinkage long sys_open(const char *, int, int); - asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern int open_namei_it(const char *filename, int namei_flags, int mode, -+ struct nameidata *nd, struct lookup_intent *it); -+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1386,6 +1409,7 @@ typedef int (*read_actor_t)(read_descrip - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1397,6 +1421,8 @@ extern struct dentry * lookup_one_len(co - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void iput(struct inode *); -@@ -1500,6 +1526,8 @@ extern struct file_operations generic_ro - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; -Index: linux-2.4.24/include/linux/fs_struct.h -=================================================================== ---- linux-2.4.24.orig/include/linux/fs_struct.h Fri Jul 13 15:10:44 2001 -+++ linux-2.4.24/include/linux/fs_struct.h Wed Mar 17 17:36:14 2004 -@@ -34,10 +34,12 @@ static inline void set_fs_root(struct fs - write_lock(&fs->lock); - old_root = fs->root; - old_rootmnt = fs->rootmnt; -+ PIN(dentry, mnt, 1); - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); - write_unlock(&fs->lock); - if (old_root) { -+ UNPIN(old_root, old_rootmnt, 1); - dput(old_root); - mntput(old_rootmnt); - } -@@ -57,10 +59,12 @@ static inline void set_fs_pwd(struct fs_ - write_lock(&fs->lock); - old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; -+ PIN(dentry, mnt, 0); - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); - write_unlock(&fs->lock); - if (old_pwd) { -+ UNPIN(old_pwd, old_pwdmnt, 0); - dput(old_pwd); - mntput(old_pwdmnt); - } -Index: linux-2.4.24/kernel/exit.c -=================================================================== ---- linux-2.4.24.orig/kernel/exit.c Thu Nov 28 15:53:15 2002 -+++ linux-2.4.24/kernel/exit.c Wed Mar 17 17:36:14 2004 -@@ -238,11 +238,14 @@ static inline void __put_fs_struct(struc - { - /* No need to hold fs->lock if we are killing it */ - if (atomic_dec_and_test(&fs->count)) { -+ UNPIN(fs->pwd, fs->pwdmnt, 0); -+ UNPIN(fs->root, fs->rootmnt, 1); - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { -+ UNPIN(fs->altroot, fs->altrootmnt, 1); - dput(fs->altroot); - mntput(fs->altrootmnt); - } -Index: linux-2.4.24/kernel/fork.c -=================================================================== ---- linux-2.4.24.orig/kernel/fork.c Fri Nov 28 10:26:21 2003 -+++ linux-2.4.24/kernel/fork.c Wed Mar 17 17:36:14 2004 -@@ -386,10 +386,13 @@ static inline struct fs_struct *__copy_f - fs->umask = old->umask; - read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); -+ PIN(old->pwd, old->pwdmnt, 0); -+ PIN(old->root, old->rootmnt, 1); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { -+ PIN(old->altroot, old->altrootmnt, 1); - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); - } else { -Index: linux-2.4.24/kernel/ksyms.c -=================================================================== ---- linux-2.4.24.orig/kernel/ksyms.c Wed Mar 17 17:36:14 2004 -+++ linux-2.4.24/kernel/ksyms.c Wed Mar 17 17:36:14 2004 -@@ -275,6 +275,7 @@ EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(mark_page_accessed); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-rhel.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-rhel.patch deleted file mode 100644 index 83e1f2d..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-rhel.patch +++ /dev/null @@ -1,1920 +0,0 @@ -Index: linux-2.4.21-40.EL/fs/dcache.c -=================================================================== ---- linux-2.4.21-40.EL.orig/fs/dcache.c -+++ linux-2.4.21-40.EL/fs/dcache.c -@@ -187,6 +187,13 @@ int d_invalidate(struct dentry * dentry) - spin_unlock(&dcache_lock); - return 0; - } -+ -+ /* network invalidation by Lustre */ -+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { -+ spin_unlock(&dcache_lock); -+ return 0; -+ } -+ - /* - * Check whether to do a partial shrink_dcache - * to get rid of unused child entries. -@@ -848,13 +855,19 @@ void d_delete(struct dentry * dentry) - * Adds a dentry to the hash according to its name. - */ - --void d_rehash(struct dentry * entry) -+void __d_rehash(struct dentry * entry, int lock) - { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); -- spin_lock(&dcache_lock); -+ if (lock) spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); -- spin_unlock(&dcache_lock); -+ if (lock) spin_unlock(&dcache_lock); -+} -+EXPORT_SYMBOL(__d_rehash); -+ -+void d_rehash(struct dentry * entry) -+{ -+ __d_rehash(entry, 1); - } - - #define do_switch(x,y) do { \ -Index: linux-2.4.21-40.EL/fs/exec.c -=================================================================== ---- linux-2.4.21-40.EL.orig/fs/exec.c -+++ linux-2.4.21-40.EL/fs/exec.c -@@ -116,8 +116,10 @@ asmlinkage long sys_uselib(const char * - struct file * file; - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- error = user_path_walk(library, &nd); -+ error = user_path_walk_it(library, &nd, &it); - if (error) - goto out; - -@@ -129,7 +131,8 @@ asmlinkage long sys_uselib(const char * - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -405,8 +408,10 @@ struct file *open_exec(const char *name) - struct inode *inode; - struct file *file; - int err = 0; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); - file = ERR_PTR(err); - if (!err) { - inode = nd.dentry->d_inode; -@@ -418,7 +423,8 @@ struct file *open_exec(const char *name) - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { -@@ -430,6 +436,7 @@ out: - return file; - } - } -+ intent_release(&it); - path_release(&nd); - } - goto out; -@@ -1383,7 +1390,7 @@ int do_coredump(long signr, int exit_cod - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.4.21-40.EL/fs/namei.c -=================================================================== ---- linux-2.4.21-40.EL.orig/fs/namei.c -+++ linux-2.4.21-40.EL/fs/namei.c -@@ -94,6 +94,13 @@ - * XEmacs seems to be relying on it... - */ - -+void intent_release(struct lookup_intent *it) -+{ -+ if (it && it->it_op_release) -+ it->it_op_release(it); -+ -+} -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -260,10 +267,19 @@ void path_release(struct nameidata *nd) - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * dentry = d_lookup(parent, name); - -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -281,11 +297,15 @@ static struct dentry * cached_lookup(str - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - -+again: -+ counter++; - down(&dir->i_sem); - /* - * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ static struct dentry * real_lookup(struc - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup_it) -+ result = dir->i_op->lookup_it(dir, dentry, it, flags); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -321,6 +344,15 @@ static struct dentry * real_lookup(struc - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate_it) { -+ if (!result->d_op->d_revalidate_it(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; -+ } - } - return result; - } -@@ -332,7 +364,8 @@ static struct dentry * real_lookup(struc - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= 8) -@@ -346,10 +379,12 @@ static inline int do_follow_link(struct - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - err = dentry->d_inode->i_op->follow_link(dentry, nd); - current->link_count--; - return err; - loop: -+ intent_release(it); - path_release(nd); - return -ELOOP; - } -@@ -447,7 +482,8 @@ static inline void follow_dotdot(struct - * - * We expect 'base' to be positive and a directory. - */ --int link_path_walk(const char * name, struct nameidata *nd) -+int link_path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -524,12 +560,12 @@ int link_path_walk(const char * name, st - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -548,7 +584,7 @@ int link_path_walk(const char * name, st - - if (inode->i_op->follow_link) { - struct vfsmount *mnt = mntget(nd->mnt); -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, NULL); - dput(dentry); - mntput(mnt); - if (err) -@@ -565,7 +601,7 @@ int link_path_walk(const char * name, st - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup_it) - break; - continue; - /* here ends the main loop */ -@@ -592,12 +628,12 @@ last_component: - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, nd->flags); -+ dentry = cached_lookup(nd->dentry, &this, nd->flags, it); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, nd->flags); -+ dentry = real_lookup(nd->dentry, &this, nd->flags, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -608,7 +644,7 @@ last_component: - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op && inode->i_op->follow_link) { - struct vfsmount *mnt = mntget(nd->mnt); -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - mntput(mnt); - if (err) -@@ -623,7 +659,8 @@ last_component: - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || -+ (!inode->i_op->lookup && !inode->i_op->lookup_it)) - break; - } - goto return_base; -@@ -641,12 +678,42 @@ lookup_parent: - nd->last_type = LAST_DOT; - else if (this.len == 2 && this.name[1] == '.') - nd->last_type = LAST_DOTDOT; -+ else -+ goto return_base; - return_reval: - /* - * We bypassed the ordinary revalidation routines. - * Check the cached dentry for staleness. - */ - dentry = nd->dentry; -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ err = -ESTALE; -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) { -+ struct dentry *new; -+ err = permission(dentry->d_parent->d_inode, -+ MAY_EXEC); -+ if (err) -+ break; -+ new = real_lookup(dentry->d_parent, -+ &dentry->d_name, 0, it); -+ if (IS_ERR(new)) { -+ err = PTR_ERR(new); -+ break; -+ } -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = new; -+ } -+ if (!nd->dentry->d_inode) -+ goto no_inode; -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if (!nd->dentry->d_inode->i_op || -+ (!nd->dentry->d_inode->i_op->lookup && -+ !nd->dentry->d_inode->i_op->lookup_it)) -+ break; -+ } -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - err = -ESTALE; - if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -660,15 +727,28 @@ out_dput: - dput(dentry); - break; - } -+ if (err) -+ intent_release(it); - path_release(nd); - return_err: - return err; - } - -+int link_path_walk(const char * name, struct nameidata *nd) -+{ -+ return link_path_walk_it(name, nd, NULL); -+} -+ -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return link_path_walk_it(name, nd, it); -+} -+ - int path_walk(const char * name, struct nameidata *nd) - { - current->total_link_count = 0; -- return link_path_walk(name, nd); -+ return link_path_walk_it(name, nd, NULL); - } - - /* SMP-safe */ -@@ -753,6 +833,17 @@ walk_init_root(const char *name, struct - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+ -+/* SMP-safe */ - int path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -767,6 +858,7 @@ int path_init(const char *name, unsigned - { - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->intent = NULL; - if (*name=='/') - return walk_init_root(name,nd); - read_lock(¤t->fs->lock); -@@ -781,7 +873,8 @@ int path_init(const char *name, unsigned - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -804,13 +897,16 @@ struct dentry * lookup_hash(struct qstr - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup_it) -+ dentry = inode->i_op->lookup_it(inode, new, it, 0); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -822,6 +918,12 @@ out: - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -843,7 +945,7 @@ struct dentry * lookup_one_len(const cha - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -874,6 +976,23 @@ int __user_walk(const char *name, unsign - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -971,7 +1090,8 @@ static inline int lookup_flags(unsigned - return retval; - } - --int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - int error; - -@@ -984,12 +1104,15 @@ int vfs_create(struct inode *dir, struct - goto exit_lock; - - error = -EACCES; /* shouldn't it be ENOSYS? */ -- if (!dir->i_op || !dir->i_op->create) -+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it)) - goto exit_lock; - - DQUOT_INIT(dir); - lock_kernel(); -- error = dir->i_op->create(dir, dentry, mode); -+ if (dir->i_op->create_it) -+ error = dir->i_op->create_it(dir, dentry, mode, it); -+ else -+ error = dir->i_op->create(dir, dentry, mode); - unlock_kernel(); - exit_lock: - up(&dir->i_zombie); -@@ -998,6 +1121,11 @@ exit_lock: - return error; - } - -+int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ return vfs_create_it(dir, dentry, mode, NULL); -+} -+ - /* - * open_namei() - * -@@ -1012,7 +1140,8 @@ exit_lock: - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1023,11 +1152,14 @@ int open_namei(const char * pathname, in - - acc_mode = ACC_MODE(flag); - -+ if (it) -+ it->it_flags = flag; -+ - /* - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1037,6 +1169,10 @@ int open_namei(const char * pathname, in - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_create_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1052,7 +1188,7 @@ int open_namei(const char * pathname, in - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1061,11 +1197,12 @@ do_last: - goto exit; - } - -+ it->it_create_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { - if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; -- error = vfs_create(dir->d_inode, dentry, mode); -+ error = vfs_create_it(dir->d_inode, dentry, mode, it); - up(&dir->d_inode->i_sem); - dput(nd->dentry); - nd->dentry = dentry; -@@ -1169,7 +1306,7 @@ ok: - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1181,8 +1318,10 @@ ok: - return 0; - - exit_dput: -+ intent_release(it); - dput(dentry); - exit: -+ intent_release(it); - path_release(nd); - return error; - -@@ -1202,7 +1341,10 @@ do_link: - */ - UPDATE_ATIME(dentry->d_inode); - mnt = mntget(nd->mnt); -+ nd->intent = it; - error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) -+ intent_release(it); - dput(dentry); - mntput(mnt); - if (error) -@@ -1225,13 +1367,20 @@ do_link: - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --static struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+static struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1239,7 +1388,7 @@ static struct dentry *lookup_create(stru - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1295,7 +1444,20 @@ asmlinkage long sys_mknod(const char * f - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1317,6 +1479,7 @@ asmlinkage long sys_mknod(const char * f - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1364,7 +1527,18 @@ asmlinkage long sys_mkdir(const char * p - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 1); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 1, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1373,6 +1547,7 @@ asmlinkage long sys_mkdir(const char * p - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1473,8 +1648,16 @@ asmlinkage long sys_rmdir(const char * p - error = -EBUSY; - goto exit1; - } -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1532,8 +1715,15 @@ asmlinkage long sys_unlink(const char * - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - /* Why not before? Because we want correct error value */ -@@ -1600,15 +1790,27 @@ asmlinkage long sys_symlink(const char * - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+ out2: - path_release(&nd); --out: -+ out: - putname(to); - } - putname(from); -@@ -1684,7 +1886,18 @@ asmlinkage long sys_link(const char * ol - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -- new_dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out_release; -+ } -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } -+ new_dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1728,7 +1941,7 @@ exit: - * locking]. - */ - int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - struct inode *target; -@@ -1807,7 +2020,7 @@ out_unlock: - } - - int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - -@@ -1895,9 +2108,18 @@ static inline int do_rename(const char * - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ lock_kernel(); -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ unlock_kernel(); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - double_lock(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd.last, old_dir); -+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); - error = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto exit3; -@@ -1913,16 +2135,16 @@ static inline int do_rename(const char * - if (newnd.last.name[newnd.last.len]) - goto exit4; - } -- new_dentry = lookup_hash(&newnd.last, new_dir); -+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; - -+ - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); - unlock_kernel(); -- - dput(new_dentry); - exit4: - dput(old_dentry); -@@ -1973,20 +2195,26 @@ out: - } - - static inline int --__vfs_follow_link(struct nameidata *nd, const char *link) -+__vfs_follow_link(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) - { - int res = 0; - char *name; - if (IS_ERR(link)) - goto fail; - -+ if (it == NULL) -+ it = nd->intent; -+ else if (it != nd->intent) -+ printk("it != nd->intent: tell phil@clusterfs.com\n"); -+ - if (*link == '/') { - path_release(nd); - if (!walk_init_root(link, nd)) - /* weird __emul_prefix() stuff did it */ - goto out; - } -- res = link_path_walk(link, nd); -+ res = link_path_walk_it(link, nd, it); - out: - if (current->link_count || res || nd->last_type!=LAST_NORM) - return res; -@@ -2010,7 +2238,13 @@ fail: - - int vfs_follow_link(struct nameidata *nd, const char *link) - { -- return __vfs_follow_link(nd, link); -+ return __vfs_follow_link(nd, link, NULL); -+} -+ -+int vfs_follow_link_it(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) -+{ -+ return __vfs_follow_link(nd, link, it); - } - - /* get the link contents into pagecache */ -@@ -2052,7 +2286,7 @@ int page_follow_link(struct dentry *dent - { - struct page *page = NULL; - char *s = page_getlink(dentry, &page); -- int res = __vfs_follow_link(nd, s); -+ int res = __vfs_follow_link(nd, s, NULL); - if (page) { - kunmap(page); - page_cache_release(page); -Index: linux-2.4.21-40.EL/fs/namespace.c -=================================================================== ---- linux-2.4.21-40.EL.orig/fs/namespace.c -+++ linux-2.4.21-40.EL/fs/namespace.c -@@ -98,6 +98,7 @@ static void detach_mnt(struct vfsmount * - { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; -+ UNPIN(old_nd->dentry, old_nd->mnt, 1); - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); -@@ -109,6 +110,7 @@ static void attach_mnt(struct vfsmount * - { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); -+ PIN(nd->dentry, nd->mnt, 1); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; -@@ -488,14 +490,17 @@ static int do_loopback(struct nameidata - { - struct nameidata old_nd; - struct vfsmount *mnt = NULL; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int err = mount_is_safe(nd); - if (err) - return err; - if (!old_name || !*old_name) - return -EINVAL; -- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd); -- if (err) -+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it); -+ if (err) { -+ intent_release(&it); - return err; -+ } - - down_write(¤t->namespace->sem); - err = -EINVAL; -@@ -518,6 +523,7 @@ static int do_loopback(struct nameidata - } - - up_write(¤t->namespace->sem); -+ intent_release(&it); - path_release(&old_nd); - return err; - } -@@ -701,6 +707,7 @@ long do_mount(char * dev_name, char * di - unsigned long flags, void *data_page) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int retval = 0; - int mnt_flags = 0; - -@@ -725,9 +732,11 @@ long do_mount(char * dev_name, char * di - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); - - /* ... and get the mountpoint */ -- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -- if (retval) -+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); -+ if (retval) { -+ intent_release(&it); - return retval; -+ } - - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, -@@ -739,6 +748,8 @@ long do_mount(char * dev_name, char * di - else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, - dev_name, data_page); -+ -+ intent_release(&it); - path_release(&nd); - return retval; - } -@@ -904,6 +915,8 @@ asmlinkage long sys_pivot_root(const cha - { - struct vfsmount *tmp; - struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; -+ struct lookup_intent new_it = { .it_op = IT_GETATTR }; -+ struct lookup_intent old_it = { .it_op = IT_GETATTR }; - int error; - - if (!capable(CAP_SYS_ADMIN)) -@@ -911,14 +924,14 @@ asmlinkage long sys_pivot_root(const cha - - lock_kernel(); - -- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it); - if (error) - goto out0; - error = -EINVAL; - if (!check_mnt(new_nd.mnt)) - goto out1; - -- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); -+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it); - if (error) - goto out1; - -@@ -973,8 +986,10 @@ out2: - up(&old_nd.dentry->d_inode->i_zombie); - up_write(¤t->namespace->sem); - path_release(&user_nd); -+ intent_release(&old_it); - path_release(&old_nd); - out1: -+ intent_release(&new_it); - path_release(&new_nd); - out0: - unlock_kernel(); -Index: linux-2.4.21-40.EL/fs/open.c -=================================================================== ---- linux-2.4.21-40.EL.orig/fs/open.c -+++ linux-2.4.21-40.EL/fs/open.c -@@ -20,6 +20,8 @@ - #include <asm/uaccess.h> - - #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) -+extern int path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it); - - int vfs_statfs(struct super_block *sb, struct statfs *buf) - { -@@ -170,9 +172,10 @@ void fd_install(unsigned int fd, struct - write_unlock(&files->file_lock); - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - struct inode *inode = dentry->d_inode; -+ struct inode_operations *op = dentry->d_inode->i_op; - int error; - struct iattr newattrs; - -@@ -184,7 +187,13 @@ int do_truncate(struct dentry *dentry, l - down(&inode->i_sem); - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -- error = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ } else -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); - up_write(&inode->i_alloc_sem); - return error; -@@ -195,12 +204,13 @@ static inline long do_sys_truncate(const - struct nameidata nd; - struct inode * inode; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd, &it); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -240,11 +250,13 @@ static inline long do_sys_truncate(const - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ intent_release(&it); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -292,7 +304,7 @@ static inline long do_sys_ftruncate(unsi - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -337,11 +349,13 @@ asmlinkage long sys_utime(char * filenam - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -356,11 +370,25 @@ asmlinkage long sys_utime(char * filenam - goto dput_and_out; - - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!times) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; - } -+ - error = notify_change(nd.dentry, &newattrs); - dput_and_out: - path_release(&nd); -@@ -381,12 +409,14 @@ asmlinkage long sys_utimes(char * filena - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -401,7 +431,20 @@ asmlinkage long sys_utimes(char * filena - newattrs.ia_atime = times[0].tv_sec; - newattrs.ia_mtime = times[1].tv_sec; - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!utimes) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; -@@ -424,6 +467,7 @@ asmlinkage long sys_access(const char * - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -441,13 +485,14 @@ asmlinkage long sys_access(const char * - else - current->cap_effective = current->cap_permitted; - -- res = user_path_walk(filename, &nd); -+ res = user_path_walk_it(filename, &nd, &it); - if (!res) { - res = permission(nd.dentry->d_inode, mode); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ intent_release(&it); - path_release(&nd); - } - -@@ -462,8 +507,9 @@ asmlinkage long sys_chdir(const char * f - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); -+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); - if (error) - goto out; - -@@ -474,6 +520,7 @@ asmlinkage long sys_chdir(const char * f - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -513,9 +560,10 @@ asmlinkage long sys_chroot(const char * - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it); - if (error) - goto out; - -@@ -531,39 +579,56 @@ asmlinkage long sys_chroot(const char * - set_fs_altroot(); - error = 0; - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode *inode = dentry->d_inode; - struct iattr newattrs; -+ int err = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -+ if (inode->i_op->setattr_raw) { -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (err != -EOPNOTSUPP) -+ goto out; -+ } - -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); - --out_putf: -+out: -+ return err; -+} -+ -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); -+ - fput(file); - out: - return err; -@@ -572,30 +637,14 @@ out: - asmlinkage long sys_chmod(const char * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; - -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; -+ error = chmod_common(nd.dentry, mode); - -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; -- -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -- --dput_and_out: - path_release(&nd); - out: - return error; -@@ -615,6 +664,20 @@ static int chown_common(struct dentry * - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } -+ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -@@ -701,7 +764,7 @@ asmlinkage long sys_fchown(unsigned int - return error; - } - --static struct file *__dentry_open(struct dentry *, struct vfsmount *, int, struct file *); -+static struct file *__dentry_open(struct dentry *, struct vfsmount *, int, struct file *, struct lookup_intent *); - - /* - * Note that while the flag value (low two bits) for sys_open means: -@@ -721,7 +784,7 @@ struct file *filp_open(const char * file - { - int namei_flags, error; - struct nameidata nd; -- struct file *f; -+ struct lookup_intent it = { .it_op = IT_OPEN }; - - namei_flags = flags; - if ((namei_flags+1) & O_ACCMODE) -@@ -730,19 +793,16 @@ struct file *filp_open(const char * file - namei_flags |= 2; - - error = -ENFILE; -- f = get_empty_filp(); -- if (f == NULL) -- return ERR_PTR(error); - -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return __dentry_open(nd.dentry, nd.mnt, flags, f); -+ error = open_namei_it(filename, namei_flags, mode, &nd, &it); -+ if (error) -+ return ERR_PTR(error); - -- put_filp(f); -- return ERR_PTR(error); -+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); - } - --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it) - { - struct file *f; - -@@ -753,10 +813,10 @@ struct file *dentry_open(struct dentry * - return ERR_PTR(-ENFILE); - } - -- return __dentry_open(dentry, mnt, flags, f); -+ return __dentry_open(dentry, mnt, flags, f, it); - } - --static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, struct file *f) -+static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, struct file *f, struct lookup_intent *it) - { - struct inode *inode; - static LIST_HEAD(kill_list); -@@ -788,7 +848,9 @@ static struct file *__dentry_open(struct - } - - if (f->f_op && f->f_op->open) { -+ f->f_it = it; - error = f->f_op->open(inode,f); -+ f->f_it = NULL; - if (error) - goto cleanup_all; - } -@@ -804,6 +866,7 @@ static struct file *__dentry_open(struct - } - } - -+ intent_release(it); - return f; - - cleanup_all: -@@ -817,11 +880,17 @@ cleanup_all: - f->f_vfsmnt = NULL; - cleanup_file: - put_filp(f); -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); - } - -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ return dentry_open_it(dentry, mnt, flags, NULL); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ -Index: linux-2.4.21-40.EL/fs/stat.c -=================================================================== ---- linux-2.4.21-40.EL.orig/fs/stat.c -+++ linux-2.4.21-40.EL/fs/stat.c -@@ -17,10 +17,12 @@ - * Revalidate the inode. This is required for proper NFS attribute caching. - */ - static __inline__ int --do_revalidate(struct dentry *dentry) -+do_revalidate(struct dentry *dentry, struct lookup_intent *it) - { - struct inode * inode = dentry->d_inode; -- if (inode->i_op && inode->i_op->revalidate) -+ if (inode->i_op && inode->i_op->revalidate_it) -+ return inode->i_op->revalidate_it(dentry, it); -+ else if (inode->i_op && inode->i_op->revalidate) - return inode->i_op->revalidate(dentry); - return 0; - } -@@ -143,14 +145,16 @@ static int cp_new_stat(struct inode * in - asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error, errcnt = 0; - - again: -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - if (error == -ESTALE && !errcnt) { -@@ -164,14 +168,16 @@ again: - asmlinkage long sys_newstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error, errcnt = 0; - - again: -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - if (error == -ESTALE && !errcnt) { -@@ -191,14 +197,16 @@ again: - asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error, errcnt = 0; - - again: -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - if (error == -ESTALE && !errcnt) { -@@ -214,14 +222,16 @@ again: - asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error, errcnt = 0; - - again: -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - -@@ -248,7 +258,7 @@ asmlinkage long sys_fstat(unsigned int f - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); -@@ -267,7 +277,7 @@ asmlinkage long sys_newfstat(unsigned in - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); -@@ -289,7 +299,7 @@ asmlinkage long sys_readlink(const char - - error = -EINVAL; - if (inode->i_op && inode->i_op->readlink && -- !(error = do_revalidate(nd.dentry))) { -+ !(error = do_revalidate(nd.dentry, NULL))) { - UPDATE_ATIME(inode); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); - } -@@ -364,14 +374,16 @@ static long cp_new_stat64(struct inode * - asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error, errcnt = 0; - - again: -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - if (error == -ESTALE && !errcnt) { -@@ -385,14 +397,16 @@ again: - asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error, errcnt = 0; - - again: -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - if (error == -ESTALE && !errcnt) { -@@ -412,7 +426,7 @@ asmlinkage long sys_fstat64(unsigned lon - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); -Index: linux-2.4.21-40.EL/include/linux/dcache.h -=================================================================== ---- linux-2.4.21-40.EL.orig/include/linux/dcache.h -+++ linux-2.4.21-40.EL/include/linux/dcache.h -@@ -6,6 +6,51 @@ - #include <asm/atomic.h> - #include <linux/mount.h> - #include <linux/kernel.h> -+#include <linux/string.h> -+ -+#define IT_OPEN 0x0001 -+#define IT_CREAT 0x0002 -+#define IT_READDIR 0x0004 -+#define IT_GETATTR 0x0008 -+#define IT_LOOKUP 0x0010 -+#define IT_UNLINK 0x0020 -+#define IT_GETXATTR 0x0040 -+#define IT_EXEC 0x0080 -+#define IT_PIN 0x0100 -+ -+#define IT_FL_LOCKED 0x0001 -+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */ -+ -+#define INTENT_MAGIC 0x19620323 -+ -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; -+ int it_int_flags; -+}; -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_init(struct lookup_intent *it, int op, int flags) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+ it->it_flags = flags; -+} -+ - - /* - * linux/include/linux/dcache.h -@@ -96,8 +141,22 @@ struct dentry_operations { - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *); -+ void (*d_pin)(struct dentry *, struct vfsmount * , int); -+ void (*d_unpin)(struct dentry *, struct vfsmount *, int); - }; - -+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \ -+ de->d_op->d_pin(de, mnt, flag); -+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \ -+ de->d_op->d_unpin(de, mnt, flag); -+ -+ -+/* defined in fs/namei.c */ -+extern void intent_release(struct lookup_intent *it); -+/* defined in fs/dcache.c */ -+extern void __d_rehash(struct dentry * entry, int lock); -+ - /* the dentry parameter passed to d_hash and d_compare is the parent - * directory of the entries to be compared. It is used in case these - * functions need any directory specific information for determining -@@ -129,6 +188,7 @@ d_iput: no no yes - * s_nfsd_free_path semaphore will be down - */ - #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ - - extern spinlock_t dcache_lock; - -Index: linux-2.4.21-40.EL/include/linux/fs.h -=================================================================== ---- linux-2.4.21-40.EL.orig/include/linux/fs.h -+++ linux-2.4.21-40.EL/include/linux/fs.h -@@ -73,6 +73,7 @@ extern int leases_enable, dir_notify_ena - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - #define READ 0 - #define WRITE 1 -@@ -365,6 +366,9 @@ extern void set_bh_page(struct buffer_he - #define ATTR_MTIME_SET 256 - #define ATTR_FORCE 512 /* Not a change, but a change it */ - #define ATTR_ATTR_FLAG 1024 -+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */ -+#define ATTR_CTIME_SET 0x2000 - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -502,6 +506,7 @@ struct inode { - struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; - struct char_device *i_cdev; -+ void *i_filterdata; - - unsigned long i_dnotify_mask; /* Directory notify events */ - struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -604,6 +609,7 @@ struct file { - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_it; - - /* preallocated helper kiobuf to speedup O_DIRECT */ - struct kiobuf *f_iobuf; -@@ -736,6 +742,7 @@ struct nameidata { - struct qstr last; - unsigned int flags; - int last_type; -+ struct lookup_intent *intent; - }; - - /* -@@ -856,7 +863,8 @@ extern int vfs_symlink(struct inode *, s - extern int vfs_link(struct dentry *, struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry); - - /* - * File types -@@ -935,21 +943,32 @@ struct file_operations_ext { - - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); -+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,int); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -+ int (*revalidate_it) (struct dentry *, struct lookup_intent *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); - int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1151,10 +1170,14 @@ static inline int get_lease(struct inode - - asmlinkage long sys_open(const char *, int, int); - asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern int open_namei_it(const char *filename, int namei_flags, int mode, -+ struct nameidata *nd, struct lookup_intent *it); -+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1446,6 +1469,7 @@ typedef int (*read_actor_t)(read_descrip - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1457,6 +1481,8 @@ extern struct dentry * lookup_one_len(co - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void iput(struct inode *); -@@ -1512,6 +1538,7 @@ static inline struct inode *iget_locked( - return iget4_locked(sb, ino, NULL, NULL); - } - -+extern void __iget(struct inode * inode); - extern void clear_inode(struct inode *); - extern struct inode *new_inode(struct super_block *sb); - extern void remove_suid(struct inode *inode); -@@ -1629,6 +1656,8 @@ extern struct file_operations generic_ro - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; -Index: linux-2.4.21-40.EL/include/linux/fs_struct.h -=================================================================== ---- linux-2.4.21-40.EL.orig/include/linux/fs_struct.h -+++ linux-2.4.21-40.EL/include/linux/fs_struct.h -@@ -37,10 +37,12 @@ static inline void set_fs_root(struct fs - write_lock(&fs->lock); - old_root = fs->root; - old_rootmnt = fs->rootmnt; -+ PIN(dentry, mnt, 1); - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); - write_unlock(&fs->lock); - if (old_root) { -+ UNPIN(old_root, old_rootmnt, 1); - dput(old_root); - mntput(old_rootmnt); - } -@@ -60,10 +62,12 @@ static inline void set_fs_pwd(struct fs_ - write_lock(&fs->lock); - old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; -+ PIN(dentry, mnt, 0); - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); - write_unlock(&fs->lock); - if (old_pwd) { -+ UNPIN(old_pwd, old_pwdmnt, 0); - dput(old_pwd); - mntput(old_pwdmnt); - } -Index: linux-2.4.21-40.EL/kernel/exit.c -=================================================================== ---- linux-2.4.21-40.EL.orig/kernel/exit.c -+++ linux-2.4.21-40.EL/kernel/exit.c -@@ -367,11 +367,14 @@ static inline void __put_fs_struct(struc - { - /* No need to hold fs->lock if we are killing it */ - if (atomic_dec_and_test(&fs->count)) { -+ UNPIN(fs->pwd, fs->pwdmnt, 0); -+ UNPIN(fs->root, fs->rootmnt, 1); - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { -+ UNPIN(fs->altroot, fs->altrootmnt, 1); - dput(fs->altroot); - mntput(fs->altrootmnt); - } -Index: linux-2.4.21-40.EL/kernel/fork.c -=================================================================== ---- linux-2.4.21-40.EL.orig/kernel/fork.c -+++ linux-2.4.21-40.EL/kernel/fork.c -@@ -473,10 +473,13 @@ static inline struct fs_struct *__copy_f - fs->umask = old->umask; - read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); -+ PIN(old->pwd, old->pwdmnt, 0); -+ PIN(old->root, old->rootmnt, 1); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { -+ PIN(old->altroot, old->altrootmnt, 1); - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); - } else { -Index: linux-2.4.21-40.EL/kernel/ksyms.c -=================================================================== ---- linux-2.4.21-40.EL.orig/kernel/ksyms.c -+++ linux-2.4.21-40.EL/kernel/ksyms.c -@@ -319,6 +319,7 @@ EXPORT_SYMBOL(read_cache_page); - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); -@@ -592,6 +593,7 @@ EXPORT_SYMBOL(si_meminfo); - EXPORT_SYMBOL(sys_tz); - EXPORT_SYMBOL(file_fsync); - EXPORT_SYMBOL(fsync_buffers_list); -+EXPORT_SYMBOL(__iget); - EXPORT_SYMBOL(clear_inode); - EXPORT_SYMBOL(___strtok); - EXPORT_SYMBOL(init_special_inode); -Index: linux-2.4.21-47.0.1.EL/fs/inode.c -=================================================================== ---- linux-2.4.21-47.0.1.EL.orig/fs/inode.c -+++ linux-2.4.21-47.0.1.EL/fs/inode.c -@@ -278,7 +278,7 @@ static inline void write_inode(struct in - inode->i_sb->s_op->write_inode(inode, sync); - } - --static inline void __iget(struct inode * inode) -+void __iget(struct inode * inode) - { - if (atomic_read(&inode->i_count)) { - atomic_inc(&inode->i_count); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse-171.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse-171.patch deleted file mode 100644 index c2609a0..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse-171.patch +++ /dev/null @@ -1,1877 +0,0 @@ - fs/dcache.c | 19 ++ - fs/exec.c | 17 +- - fs/namei.c | 295 +++++++++++++++++++++++++++++++++++++++------- - fs/namespace.c | 28 +++- - fs/open.c | 172 +++++++++++++++++++------- - fs/stat.c | 52 +++++--- - include/linux/dcache.h | 60 +++++++++ - include/linux/fs.h | 32 ++++ - include/linux/fs_struct.h | 4 - kernel/exit.c | 3 - kernel/fork.c | 3 - kernel/ksyms.c | 1 - 12 files changed, 558 insertions(+), 128 deletions(-) - -Index: linux-2.4.21-273/fs/dcache.c -=================================================================== ---- linux-2.4.21-273.orig/fs/dcache.c 2005-01-17 07:08:10.000000000 -0500 -+++ linux-2.4.21-273/fs/dcache.c 2005-04-05 19:59:00.687028845 -0400 -@@ -186,6 +186,13 @@ - spin_unlock(&dcache_lock); - return 0; - } -+ -+ /* network invalidation by Lustre */ -+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { -+ spin_unlock(&dcache_lock); -+ return 0; -+ } -+ - /* - * Check whether to do a partial shrink_dcache - * to get rid of unused child entries. -@@ -838,13 +845,19 @@ - * Adds a dentry to the hash according to its name. - */ - --void d_rehash(struct dentry * entry) -+void __d_rehash(struct dentry * entry, int lock) - { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); -- spin_lock(&dcache_lock); -+ if (lock) spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); -- spin_unlock(&dcache_lock); -+ if (lock) spin_unlock(&dcache_lock); -+} -+EXPORT_SYMBOL(__d_rehash); -+ -+void d_rehash(struct dentry * entry) -+{ -+ __d_rehash(entry, 1); - } - - #define do_switch(x,y) do { \ -Index: linux-2.4.21-273/fs/exec.c -=================================================================== ---- linux-2.4.21-273.orig/fs/exec.c 2005-01-17 07:08:11.000000000 -0500 -+++ linux-2.4.21-273/fs/exec.c 2005-04-05 19:59:00.688028700 -0400 -@@ -113,8 +113,10 @@ - struct file * file; - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- error = user_path_walk(library, &nd); -+ error = user_path_walk_it(library, &nd, &it); - if (error) - goto out; - -@@ -126,7 +128,8 @@ - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -390,8 +393,10 @@ - struct inode *inode; - struct file *file; - int err = 0; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); - file = ERR_PTR(err); - if (!err) { - inode = nd.dentry->d_inode; -@@ -403,7 +408,8 @@ - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { -@@ -415,6 +421,7 @@ - return file; - } - } -+ intent_release(&it); - path_release(&nd); - } - goto out; -@@ -1154,7 +1161,7 @@ - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.4.21-273/fs/namei.c -=================================================================== ---- linux-2.4.21-273.orig/fs/namei.c 2005-01-17 07:08:10.000000000 -0500 -+++ linux-2.4.21-273/fs/namei.c 2005-04-05 19:59:46.773351909 -0400 -@@ -94,6 +94,13 @@ - * XEmacs seems to be relying on it... - */ - -+void intent_release(struct lookup_intent *it) -+{ -+ if (it && it->it_op_release) -+ it->it_op_release(it); -+ -+} -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -274,10 +281,19 @@ - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * dentry = d_lookup(parent, name); - -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -295,11 +311,15 @@ - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - -+again: -+ counter++; - down(&dir->i_sem); - /* - * First re-do the cached lookup just in case it was created -@@ -314,6 +334,9 @@ - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup_it) -+ result = dir->i_op->lookup_it(dir, dentry, it, flags); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -335,6 +358,15 @@ - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate_it) { -+ if (!result->d_op->d_revalidate_it(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; -+ } - } - return result; - } -@@ -346,7 +378,8 @@ - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= 8) -@@ -360,10 +393,12 @@ - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - err = dentry->d_inode->i_op->follow_link(dentry, nd); - current->link_count--; - return err; - loop: -+ intent_release(it); - path_release(nd); - return -ELOOP; - } -@@ -462,7 +497,8 @@ - * We expect 'base' to be positive and a directory. - */ - static inline int __attribute__((always_inline)) --__link_path_walk(const char * name, struct nameidata *nd) -+__link_path_walk_it(const char * name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -539,12 +575,12 @@ - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -562,7 +598,7 @@ - goto out_dput; - - if (inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, NULL); - dput(dentry); - if (err) - goto return_err; -@@ -578,7 +614,7 @@ - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup_it) - break; - continue; - /* here ends the main loop */ -@@ -605,12 +641,12 @@ - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, 0); -+ dentry = cached_lookup(nd->dentry, &this, 0, it); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, 0); -+ dentry = real_lookup(nd->dentry, &this, 0, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -620,7 +656,7 @@ - inode = dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op && inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -634,7 +670,8 @@ - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || -+ (!inode->i_op->lookup && !inode->i_op->lookup_it)) - break; - } - goto return_base; -@@ -652,12 +689,42 @@ - nd->last_type = LAST_DOT; - else if (this.len == 2 && this.name[1] == '.') - nd->last_type = LAST_DOTDOT; -+ else -+ goto return_base; - return_reval: - /* - * We bypassed the ordinary revalidation routines. - * Check the cached dentry for staleness. - */ - dentry = nd->dentry; -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ err = -ESTALE; -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) { -+ struct dentry *new; -+ err = permission(dentry->d_parent->d_inode, -+ MAY_EXEC); -+ if (err) -+ break; -+ new = real_lookup(dentry->d_parent, -+ &dentry->d_name, 0, it); -+ if (IS_ERR(new)) { -+ err = PTR_ERR(new); -+ break; -+ } -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = new; -+ } -+ if (!nd->dentry->d_inode) -+ goto no_inode; -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if (!nd->dentry->d_inode->i_op || -+ (!nd->dentry->d_inode->i_op->lookup && -+ !nd->dentry->d_inode->i_op->lookup_it)) -+ break; -+ } -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - err = -ESTALE; - if (!dentry->d_op->d_revalidate(dentry, lookup_flags & LOOKUP_PARENT)) { -@@ -671,6 +738,8 @@ - dput(dentry); - break; - } -+ if (err) -+ intent_release(it); - path_release(nd); - return_err: - return err; -@@ -678,13 +747,13 @@ - - int link_path_walk(const char * name, struct nameidata *nd) - { -- return __link_path_walk(name,nd); -+ return __link_path_walk_it(name, nd, NULL); - } - - static inline int __path_walk(const char * name, struct nameidata *nd) - { - current->total_link_count = 0; -- return __link_path_walk(name, nd); -+ return __link_path_walk_it(name, nd, NULL); - } - - int path_walk(const char * name, struct nameidata *nd) -@@ -692,6 +761,12 @@ - return __path_walk(name, nd); - } - -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return __link_path_walk_it(name, nd, it); -+} -+ - /* SMP-safe */ - /* returns 1 if everything is done */ - static int __emul_lookup_dentry(const char *name, struct nameidata *nd) -@@ -774,6 +849,16 @@ - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+/* SMP-safe */ - int path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -788,6 +873,7 @@ - { - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->intent = NULL; - if (*name=='/') - return walk_init_root(name,nd); - read_lock(¤t->fs->lock); -@@ -802,7 +888,8 @@ - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -825,13 +912,16 @@ - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup_it) -+ dentry = inode->i_op->lookup_it(inode, new, it, 0); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -843,6 +933,12 @@ - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -864,7 +960,7 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -895,6 +991,23 @@ - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -992,7 +1105,8 @@ - return retval; - } - --int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - int error; - -@@ -1005,12 +1119,15 @@ - goto exit_lock; - - error = -EACCES; /* shouldn't it be ENOSYS? */ -- if (!dir->i_op || !dir->i_op->create) -+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it)) - goto exit_lock; - - DQUOT_INIT(dir); - lock_kernel(); -- error = dir->i_op->create(dir, dentry, mode); -+ if (dir->i_op->create_it) -+ error = dir->i_op->create_it(dir, dentry, mode, it); -+ else -+ error = dir->i_op->create(dir, dentry, mode); - unlock_kernel(); - exit_lock: - up(&dir->i_zombie); -@@ -1019,6 +1136,11 @@ - return error; - } - -+int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ return vfs_create_it(dir, dentry, mode, NULL); -+} -+ - /* - * open_namei() - * -@@ -1033,7 +1155,8 @@ - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1043,11 +1166,14 @@ - - acc_mode = ACC_MODE(flag); - -+ if (it) -+ it->it_flags = flag; -+ - /* - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1057,6 +1183,10 @@ - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_create_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1072,7 +1202,7 @@ - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1081,11 +1211,12 @@ - goto exit; - } - -+ it->it_create_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { - if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; -- error = vfs_create(dir->d_inode, dentry, mode); -+ error = vfs_create_it(dir->d_inode, dentry, mode, it); - up(&dir->d_inode->i_sem); - #ifndef DENTRY_WASTE_RAM - if (error) -@@ -1193,7 +1324,7 @@ - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1205,8 +1336,10 @@ - return 0; - - exit_dput: -+ intent_release(it); - dput(dentry); - exit: -+ intent_release(it); - path_release(nd); - return error; - -@@ -1225,7 +1358,10 @@ - * are done. Procfs-like symlinks just set LAST_BIND. - */ - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) -+ intent_release(it); - dput(dentry); - if (error) - return error; -@@ -1247,13 +1383,20 @@ - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1261,7 +1404,7 @@ - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1317,7 +1460,20 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1339,6 +1495,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1386,7 +1543,18 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 1); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 1, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1395,6 +1563,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1495,8 +1664,16 @@ - error = -EBUSY; - goto exit1; - } -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1554,8 +1731,15 @@ - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - /* Why not before? Because we want correct error value */ -@@ -1622,15 +1806,27 @@ - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+ out2: - path_release(&nd); --out: -+ out: - putname(to); - } - putname(from); -@@ -1706,7 +1902,18 @@ - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -- new_dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out_release; -+ } -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } -+ new_dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1750,7 +1957,7 @@ - * locking]. - */ - int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - struct inode *target; -@@ -1829,7 +2036,7 @@ - } - - int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - -@@ -1917,9 +2124,18 @@ - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ lock_kernel(); -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ unlock_kernel(); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - double_lock(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd.last, old_dir); -+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); - error = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto exit3; -@@ -1935,16 +2151,16 @@ - if (newnd.last.name[newnd.last.len]) - goto exit4; - } -- new_dentry = lookup_hash(&newnd.last, new_dir); -+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; - -+ - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); - unlock_kernel(); -- - dput(new_dentry); - exit4: - dput(old_dentry); -@@ -1995,20 +2211,26 @@ - } - - static inline int __attribute__((always_inline)) --__vfs_follow_link(struct nameidata *nd, const char *link) -+__vfs_follow_link(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) - { - int res = 0; - char *name; - if (IS_ERR(link)) - goto fail; - -+ if (it == NULL) -+ it = nd->intent; -+ else if (it != nd->intent) -+ printk("it != nd->intent: tell phil@clusterfs.com\n"); -+ - if (*link == '/') { - path_release(nd); - if (!walk_init_root(link, nd)) - /* weird __emul_prefix() stuff did it */ - goto out; - } -- res = __link_path_walk(link, nd); -+ res = __link_path_walk_it(link, nd, it); - out: - if (current->link_count || res || nd->last_type!=LAST_NORM) - return res; -@@ -2032,7 +2254,13 @@ - - int vfs_follow_link(struct nameidata *nd, const char *link) - { -- return __vfs_follow_link(nd, link); -+ return __vfs_follow_link(nd, link, NULL); -+} -+ -+int vfs_follow_link_it(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) -+{ -+ return __vfs_follow_link(nd, link, it); - } - - /* get the link contents into pagecache */ -@@ -2074,7 +2302,7 @@ - { - struct page *page = NULL; - char *s = page_getlink(dentry, &page); -- int res = __vfs_follow_link(nd, s); -+ int res = __vfs_follow_link(nd, s, NULL); - if (page) { - kunmap(page); - page_cache_release(page); -Index: linux-2.4.21-273/fs/namespace.c -=================================================================== ---- linux-2.4.21-273.orig/fs/namespace.c 2005-01-17 07:08:11.000000000 -0500 -+++ linux-2.4.21-273/fs/namespace.c 2005-04-05 19:59:00.692028120 -0400 -@@ -98,6 +98,7 @@ - { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; -+ UNPIN(old_nd->dentry, old_nd->mnt, 1); - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); -@@ -109,6 +110,7 @@ - { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); -+ PIN(nd->dentry, nd->mnt, 1); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; -@@ -488,14 +490,17 @@ - { - struct nameidata old_nd; - struct vfsmount *mnt = NULL; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int err = mount_is_safe(nd); - if (err) - return err; - if (!old_name || !*old_name) - return -EINVAL; -- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd); -- if (err) -+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it); -+ if (err) { -+ intent_release(&it); - return err; -+ } - - down_write(¤t->namespace->sem); - err = -EINVAL; -@@ -518,6 +523,7 @@ - } - - up_write(¤t->namespace->sem); -+ intent_release(&it); - path_release(&old_nd); - return err; - } -@@ -701,6 +707,7 @@ - unsigned long flags, void *data_page) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int retval = 0; - int mnt_flags = 0; - -@@ -725,10 +732,11 @@ - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); - - /* ... and get the mountpoint */ -- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -- if (retval) -+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); -+ if (retval) { -+ intent_release(&it); - return retval; -- -+ } - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, - data_page); -@@ -739,6 +747,8 @@ - else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, - dev_name, data_page); -+ -+ intent_release(&it); - path_release(&nd); - return retval; - } -@@ -904,6 +914,8 @@ - { - struct vfsmount *tmp; - struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; -+ struct lookup_intent new_it = { .it_op = IT_GETATTR }; -+ struct lookup_intent old_it = { .it_op = IT_GETATTR }; - int error; - - if (!capable(CAP_SYS_ADMIN)) -@@ -911,14 +923,14 @@ - - lock_kernel(); - -- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it); - if (error) - goto out0; - error = -EINVAL; - if (!check_mnt(new_nd.mnt)) - goto out1; - -- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); -+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it); - if (error) - goto out1; - -@@ -973,8 +985,10 @@ - up(&old_nd.dentry->d_inode->i_zombie); - up_write(¤t->namespace->sem); - path_release(&user_nd); -+ intent_release(&old_it); - path_release(&old_nd); - out1: -+ intent_release(&new_it); - path_release(&new_nd); - out0: - unlock_kernel(); -Index: linux-2.4.21-273/fs/open.c -=================================================================== ---- linux-2.4.21-273.orig/fs/open.c 2005-01-17 07:08:11.000000000 -0500 -+++ linux-2.4.21-273/fs/open.c 2005-04-05 19:59:00.693027975 -0400 -@@ -20,6 +20,8 @@ - #include <asm/uaccess.h> - - #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) -+extern int path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it); - - int vfs_statfs(struct super_block *sb, struct statfs *buf) - { -@@ -96,9 +98,10 @@ - write_unlock(&files->file_lock); - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - struct inode *inode = dentry->d_inode; -+ struct inode_operations *op = dentry->d_inode->i_op; - int error; - struct iattr newattrs; - -@@ -110,7 +113,13 @@ - down(&inode->i_sem); - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -- error = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ } else -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); - up_write(&inode->i_alloc_sem); - return error; -@@ -121,12 +130,13 @@ - struct nameidata nd; - struct inode * inode; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd, &it); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -166,11 +176,13 @@ - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ intent_release(&it); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -218,7 +230,7 @@ - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -263,11 +275,13 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -282,11 +296,25 @@ - goto dput_and_out; - - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!times) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; - } -+ - error = notify_change(nd.dentry, &newattrs); - dput_and_out: - path_release(&nd); -@@ -307,12 +335,14 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -327,7 +357,20 @@ - newattrs.ia_atime = times[0].tv_sec; - newattrs.ia_mtime = times[1].tv_sec; - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!utimes) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; -@@ -350,6 +393,7 @@ - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -367,13 +411,14 @@ - else - current->cap_effective = current->cap_permitted; - -- res = user_path_walk(filename, &nd); -+ res = user_path_walk_it(filename, &nd, &it); - if (!res) { - res = permission(nd.dentry->d_inode, mode); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ intent_release(&it); - path_release(&nd); - } - -@@ -388,8 +433,9 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); -+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); - if (error) - goto out; - -@@ -400,6 +446,7 @@ - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -439,9 +486,10 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it); - if (error) - goto out; - -@@ -457,39 +505,56 @@ - set_fs_altroot(); - error = 0; - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode *inode = dentry->d_inode; - struct iattr newattrs; -+ int err = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -+ if (inode->i_op->setattr_raw) { -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (err != -EOPNOTSUPP) -+ goto out; -+ } - -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); - --out_putf: -+out: -+ return err; -+} -+ -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); -+ - fput(file); - out: - return err; -@@ -498,30 +563,14 @@ - asmlinkage long sys_chmod(const char * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; -- -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; - -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; -+ error = chmod_common(nd.dentry, mode); - -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -- --dput_and_out: - path_release(&nd); - out: - return error; -@@ -541,6 +590,20 @@ - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } -+ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -@@ -645,6 +708,7 @@ - { - int namei_flags, error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_OPEN }; - - namei_flags = flags; - if ((namei_flags+1) & O_ACCMODE) -@@ -652,14 +716,15 @@ - if (namei_flags & O_TRUNC) - namei_flags |= 2; - -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return dentry_open(nd.dentry, nd.mnt, flags); -+ error = open_namei_it(filename, namei_flags, mode, &nd, &it); -+ if (error) -+ return ERR_PTR(error); - -- return ERR_PTR(error); -+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); - } - --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it) - { - struct file * f; - struct inode *inode; -@@ -687,7 +752,9 @@ - file_move(f, &inode->i_sb->s_files); - - if (f->f_op && f->f_op->open) { -+ f->f_it = it; - error = f->f_op->open(inode,f); -+ f->f_it = NULL; - if (error) - goto cleanup_all; - } -@@ -699,6 +766,7 @@ - !inode->i_mapping->a_ops->direct_IO)) - goto cleanup_all; - -+ intent_release(it); - return f; - - cleanup_all: -@@ -711,11 +779,17 @@ - cleanup_file: - put_filp(f); - cleanup_dentry: -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); - } - -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ return dentry_open_it(dentry, mnt, flags, NULL); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ -Index: linux-2.4.21-273/fs/stat.c -=================================================================== ---- linux-2.4.21-273.orig/fs/stat.c 2005-01-17 07:08:11.000000000 -0500 -+++ linux-2.4.21-273/fs/stat.c 2005-04-05 19:59:00.694027831 -0400 -@@ -17,10 +17,12 @@ - * Revalidate the inode. This is required for proper NFS attribute caching. - */ - static __inline__ int --do_revalidate(struct dentry *dentry) -+do_revalidate(struct dentry *dentry, struct lookup_intent *it) - { - struct inode * inode = dentry->d_inode; -- if (inode->i_op && inode->i_op->revalidate) -+ if (inode->i_op && inode->i_op->revalidate_it) -+ return inode->i_op->revalidate_it(dentry, it); -+ else if (inode->i_op && inode->i_op->revalidate) - return inode->i_op->revalidate(dentry); - return 0; - } -@@ -141,13 +143,15 @@ - asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -157,13 +161,15 @@ - asmlinkage long sys_newstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -178,13 +184,15 @@ - asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -195,13 +203,15 @@ - asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -222,7 +232,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); -@@ -241,7 +251,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); -@@ -263,7 +273,7 @@ - - error = -EINVAL; - if (inode->i_op && inode->i_op->readlink && -- !(error = do_revalidate(nd.dentry))) { -+ !(error = do_revalidate(nd.dentry, NULL))) { - UPDATE_ATIME(inode); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); - } -@@ -339,12 +349,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -354,12 +366,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -374,7 +388,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); -Index: linux-2.4.21-273/include/linux/dcache.h -=================================================================== ---- linux-2.4.21-273.orig/include/linux/dcache.h 2005-01-17 07:09:07.000000000 -0500 -+++ linux-2.4.21-273/include/linux/dcache.h 2005-04-05 19:59:00.695027686 -0400 -@@ -7,6 +7,51 @@ - #include <linux/gdb.h> - #include <linux/mount.h> - #include <linux/kernel.h> -+#include <linux/string.h> -+ -+#define IT_OPEN 0x0001 -+#define IT_CREAT 0x0002 -+#define IT_READDIR 0x0004 -+#define IT_GETATTR 0x0008 -+#define IT_LOOKUP 0x0010 -+#define IT_UNLINK 0x0020 -+#define IT_GETXATTR 0x0040 -+#define IT_EXEC 0x0080 -+#define IT_PIN 0x0100 -+ -+#define IT_FL_LOCKED 0x0001 -+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */ -+ -+#define INTENT_MAGIC 0x19620323 -+ -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; -+ int it_int_flags; -+}; -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_init(struct lookup_intent *it, int op, int flags) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+ it->it_flags = flags; -+} -+ - - /* - * linux/include/linux/dcache.h -@@ -94,8 +139,22 @@ - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *); -+ void (*d_pin)(struct dentry *, struct vfsmount * , int); -+ void (*d_unpin)(struct dentry *, struct vfsmount *, int); - }; - -+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \ -+ de->d_op->d_pin(de, mnt, flag); -+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \ -+ de->d_op->d_unpin(de, mnt, flag); -+ -+ -+/* defined in fs/namei.c */ -+extern void intent_release(struct lookup_intent *it); -+/* defined in fs/dcache.c */ -+extern void __d_rehash(struct dentry * entry, int lock); -+ - /* the dentry parameter passed to d_hash and d_compare is the parent - * directory of the entries to be compared. It is used in case these - * functions need any directory specific information for determining -@@ -127,6 +186,7 @@ - * s_nfsd_free_path semaphore will be down - */ - #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ - - extern spinlock_t dcache_lock; - -Index: linux-2.4.21-273/include/linux/fs.h -=================================================================== ---- linux-2.4.21-273.orig/include/linux/fs.h 2005-04-05 19:58:52.741180030 -0400 -+++ linux-2.4.21-273/include/linux/fs.h 2005-04-05 19:59:00.696027541 -0400 -@@ -74,6 +74,7 @@ - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - #define READ 0 - #define WRITE 1 -@@ -360,6 +361,9 @@ - #define ATTR_MTIME_SET 256 - #define ATTR_FORCE 512 /* Not a change, but a change it */ - #define ATTR_ATTR_FLAG 1024 -+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */ -+#define ATTR_CTIME_SET 0x2000 - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -504,6 +508,7 @@ - struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; - struct char_device *i_cdev; -+ void *i_filterdata; - - unsigned long i_dnotify_mask; /* Directory notify events */ - struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -666,6 +671,7 @@ - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_it; - struct list_head f_ep_links; - spinlock_t f_ep_lock; - }; -@@ -795,6 +801,7 @@ - struct qstr last; - unsigned int flags; - int last_type; -+ struct lookup_intent *intent; - }; - - /* -@@ -916,7 +923,8 @@ - extern int __vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry); - - /* - * File types -@@ -991,21 +999,32 @@ - - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); -+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,int); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -+ int (*revalidate_it) (struct dentry *, struct lookup_intent *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); - int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1204,10 +1223,14 @@ - - asmlinkage long sys_open(const char *, int, int); - asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern int open_namei_it(const char *filename, int namei_flags, int mode, -+ struct nameidata *nd, struct lookup_intent *it); -+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1503,6 +1526,7 @@ - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1515,6 +1539,8 @@ - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void _inode_init_once(struct inode *); -@@ -1666,6 +1692,8 @@ - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; -Index: linux-2.4.21-273/include/linux/fs_struct.h -=================================================================== ---- linux-2.4.21-273.orig/include/linux/fs_struct.h 2005-01-17 07:09:10.000000000 -0500 -+++ linux-2.4.21-273/include/linux/fs_struct.h 2005-04-05 19:59:00.697027396 -0400 -@@ -34,10 +34,12 @@ - write_lock(&fs->lock); - old_root = fs->root; - old_rootmnt = fs->rootmnt; -+ PIN(dentry, mnt, 1); - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); - write_unlock(&fs->lock); - if (old_root) { -+ UNPIN(old_root, old_rootmnt, 1); - dput(old_root); - mntput(old_rootmnt); - } -@@ -57,10 +59,12 @@ - write_lock(&fs->lock); - old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; -+ PIN(dentry, mnt, 0); - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); - write_unlock(&fs->lock); - if (old_pwd) { -+ UNPIN(old_pwd, old_pwdmnt, 0); - dput(old_pwd); - mntput(old_pwdmnt); - } -Index: linux-2.4.21-273/kernel/exit.c -=================================================================== ---- linux-2.4.21-273.orig/kernel/exit.c 2005-01-17 07:08:59.000000000 -0500 -+++ linux-2.4.21-273/kernel/exit.c 2005-04-05 19:59:00.698027251 -0400 -@@ -292,11 +292,14 @@ - { - /* No need to hold fs->lock if we are killing it */ - if (atomic_dec_and_test(&fs->count)) { -+ UNPIN(fs->pwd, fs->pwdmnt, 0); -+ UNPIN(fs->root, fs->rootmnt, 1); - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { -+ UNPIN(fs->altroot, fs->altrootmnt, 1); - dput(fs->altroot); - mntput(fs->altrootmnt); - } -Index: linux-2.4.21-273/kernel/fork.c -=================================================================== ---- linux-2.4.21-273.orig/kernel/fork.c 2005-01-17 07:09:00.000000000 -0500 -+++ linux-2.4.21-273/kernel/fork.c 2005-04-05 19:59:00.699027106 -0400 -@@ -466,10 +466,13 @@ - fs->umask = old->umask; - read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); -+ PIN(old->pwd, old->pwdmnt, 0); -+ PIN(old->root, old->rootmnt, 1); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { -+ PIN(old->altroot, old->altrootmnt, 1); - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); - } else { -Index: linux-2.4.21-273/kernel/ksyms.c -=================================================================== ---- linux-2.4.21-273.orig/kernel/ksyms.c 2005-04-05 19:58:52.779174526 -0400 -+++ linux-2.4.21-273/kernel/ksyms.c 2005-04-05 19:59:00.699027106 -0400 -@@ -330,6 +330,7 @@ - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch deleted file mode 100644 index d283bd1..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.21-suse2.patch +++ /dev/null @@ -1,1878 +0,0 @@ - fs/dcache.c | 19 ++ - fs/exec.c | 17 +- - fs/namei.c | 295 +++++++++++++++++++++++++++++++++++++++------- - fs/namespace.c | 28 +++- - fs/open.c | 172 +++++++++++++++++++------- - fs/stat.c | 52 +++++--- - include/linux/dcache.h | 60 +++++++++ - include/linux/fs.h | 32 ++++ - include/linux/fs_struct.h | 4 - kernel/exit.c | 3 - kernel/fork.c | 3 - kernel/ksyms.c | 1 - 12 files changed, 558 insertions(+), 128 deletions(-) - -Index: linux-2.4.21-x86_64/fs/dcache.c -=================================================================== ---- linux-2.4.21-x86_64.orig/fs/dcache.c 2003-10-28 10:33:59.000000000 -0800 -+++ linux-2.4.21-x86_64/fs/dcache.c 2004-04-12 19:57:36.000000000 -0700 -@@ -186,6 +186,13 @@ - spin_unlock(&dcache_lock); - return 0; - } -+ -+ /* network invalidation by Lustre */ -+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { -+ spin_unlock(&dcache_lock); -+ return 0; -+ } -+ - /* - * Check whether to do a partial shrink_dcache - * to get rid of unused child entries. -@@ -838,13 +845,19 @@ - * Adds a dentry to the hash according to its name. - */ - --void d_rehash(struct dentry * entry) -+void __d_rehash(struct dentry * entry, int lock) - { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); -- spin_lock(&dcache_lock); -+ if (lock) spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); -- spin_unlock(&dcache_lock); -+ if (lock) spin_unlock(&dcache_lock); -+} -+EXPORT_SYMBOL(__d_rehash); -+ -+void d_rehash(struct dentry * entry) -+{ -+ __d_rehash(entry, 1); - } - - #define do_switch(x,y) do { \ -Index: linux-2.4.21-x86_64/fs/exec.c -=================================================================== ---- linux-2.4.21-x86_64.orig/fs/exec.c 2003-10-28 10:34:17.000000000 -0800 -+++ linux-2.4.21-x86_64/fs/exec.c 2004-04-12 19:57:36.000000000 -0700 -@@ -112,8 +112,10 @@ - struct file * file; - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- error = user_path_walk(library, &nd); -+ error = user_path_walk_it(library, &nd, &it); - if (error) - goto out; - -@@ -125,7 +127,8 @@ - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -382,8 +385,10 @@ - struct inode *inode; - struct file *file; - int err = 0; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); - file = ERR_PTR(err); - if (!err) { - inode = nd.dentry->d_inode; -@@ -395,7 +400,8 @@ - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { -@@ -407,6 +413,7 @@ - return file; - } - } -+ intent_release(&it); - path_release(&nd); - } - goto out; -@@ -1150,7 +1157,7 @@ - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.4.21-x86_64/fs/namei.c -=================================================================== ---- linux-2.4.21-x86_64.orig/fs/namei.c 2003-10-28 10:34:18.000000000 -0800 -+++ linux-2.4.21-x86_64/fs/namei.c 2004-04-12 19:58:44.000000000 -0700 -@@ -94,6 +94,13 @@ - * XEmacs seems to be relying on it... - */ - -+void intent_release(struct lookup_intent *it) -+{ -+ if (it && it->it_op_release) -+ it->it_op_release(it); -+ -+} -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -260,10 +267,19 @@ - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * dentry = d_lookup(parent, name); - -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -281,11 +297,15 @@ - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - -+again: -+ counter++; - down(&dir->i_sem); - /* - * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup_it) -+ result = dir->i_op->lookup_it(dir, dentry, it, flags); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -321,6 +344,15 @@ - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate_it) { -+ if (!result->d_op->d_revalidate_it(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; -+ } - } - return result; - } -@@ -332,7 +364,8 @@ - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= 8) -@@ -346,10 +379,12 @@ - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - err = dentry->d_inode->i_op->follow_link(dentry, nd); - current->link_count--; - return err; - loop: -+ intent_release(it); - path_release(nd); - return -ELOOP; - } -@@ -447,7 +482,8 @@ - * - * We expect 'base' to be positive and a directory. - */ --static inline int __link_path_walk(const char * name, struct nameidata *nd) -+static inline int __link_path_walk_it(const char * name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -524,12 +560,12 @@ - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -547,7 +583,7 @@ - goto out_dput; - - if (inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, NULL); - dput(dentry); - if (err) - goto return_err; -@@ -563,7 +599,7 @@ - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup_it) - break; - continue; - /* here ends the main loop */ -@@ -590,12 +626,12 @@ - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, 0); -+ dentry = cached_lookup(nd->dentry, &this, 0, it); - if (!dentry) { - err = -EWOULDBLOCKIO; - if (atomic) - break; -- dentry = real_lookup(nd->dentry, &this, 0); -+ dentry = real_lookup(nd->dentry, &this, 0, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -605,7 +641,7 @@ - inode = dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op && inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -619,7 +655,8 @@ - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || -+ (!inode->i_op->lookup && !inode->i_op->lookup_it)) - break; - } - goto return_base; -@@ -637,12 +672,42 @@ - nd->last_type = LAST_DOT; - else if (this.len == 2 && this.name[1] == '.') - nd->last_type = LAST_DOTDOT; -+ else -+ goto return_base; - return_reval: - /* - * We bypassed the ordinary revalidation routines. - * Check the cached dentry for staleness. - */ - dentry = nd->dentry; -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ err = -ESTALE; -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) { -+ struct dentry *new; -+ err = permission(dentry->d_parent->d_inode, -+ MAY_EXEC); -+ if (err) -+ break; -+ new = real_lookup(dentry->d_parent, -+ &dentry->d_name, 0, it); -+ if (IS_ERR(new)) { -+ err = PTR_ERR(new); -+ break; -+ } -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = new; -+ } -+ if (!nd->dentry->d_inode) -+ goto no_inode; -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if (!nd->dentry->d_inode->i_op || -+ (!nd->dentry->d_inode->i_op->lookup && -+ !nd->dentry->d_inode->i_op->lookup_it)) -+ break; -+ } -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - err = -ESTALE; - if (!dentry->d_op->d_revalidate(dentry, lookup_flags & LOOKUP_PARENT)) { -@@ -656,6 +714,8 @@ - dput(dentry); - break; - } -+ if (err) -+ intent_release(it); - path_release(nd); - return_err: - return err; -@@ -663,13 +723,13 @@ - - int link_path_walk(const char * name, struct nameidata *nd) - { -- return __link_path_walk(name,nd); -+ return __link_path_walk_it(name, nd, NULL); - } - - static inline int __path_walk(const char * name, struct nameidata *nd) - { - current->total_link_count = 0; -- return __link_path_walk(name, nd); -+ return __link_path_walk_it(name, nd, NULL); - } - - int path_walk(const char * name, struct nameidata *nd) -@@ -677,6 +737,12 @@ - return __path_walk(name, nd); - } - -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return __link_path_walk_it(name, nd, it); -+} -+ - /* SMP-safe */ - /* returns 1 if everything is done */ - static int __emul_lookup_dentry(const char *name, struct nameidata *nd) -@@ -759,6 +825,17 @@ - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+ -+/* SMP-safe */ - int path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -773,6 +850,7 @@ - { - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->intent = NULL; - if (*name=='/') - return walk_init_root(name,nd); - read_lock(¤t->fs->lock); -@@ -787,7 +865,8 @@ - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -810,13 +889,16 @@ - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup_it) -+ dentry = inode->i_op->lookup_it(inode, new, it, 0); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -828,6 +910,12 @@ - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -849,7 +937,7 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -880,6 +968,23 @@ - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -977,7 +1082,8 @@ - return retval; - } - --int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - int error; - -@@ -990,12 +1096,15 @@ - goto exit_lock; - - error = -EACCES; /* shouldn't it be ENOSYS? */ -- if (!dir->i_op || !dir->i_op->create) -+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it)) - goto exit_lock; - - DQUOT_INIT(dir); - lock_kernel(); -- error = dir->i_op->create(dir, dentry, mode); -+ if (dir->i_op->create_it) -+ error = dir->i_op->create_it(dir, dentry, mode, it); -+ else -+ error = dir->i_op->create(dir, dentry, mode); - unlock_kernel(); - exit_lock: - up(&dir->i_zombie); -@@ -1004,6 +1113,11 @@ - return error; - } - -+int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ return vfs_create_it(dir, dentry, mode, NULL); -+} -+ - /* - * open_namei() - * -@@ -1018,7 +1132,8 @@ - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1028,11 +1143,14 @@ - - acc_mode = ACC_MODE(flag); - -+ if (it) -+ it->it_flags = flag; -+ - /* - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1042,6 +1160,10 @@ - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_create_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1057,7 +1179,7 @@ - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1066,11 +1188,12 @@ - goto exit; - } - -+ it->it_create_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { - if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; -- error = vfs_create(dir->d_inode, dentry, mode); -+ error = vfs_create_it(dir->d_inode, dentry, mode, it); - up(&dir->d_inode->i_sem); - #ifndef DENTRY_WASTE_RAM - if (error) -@@ -1178,7 +1301,7 @@ - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1190,8 +1313,10 @@ - return 0; - - exit_dput: -+ intent_release(it); - dput(dentry); - exit: -+ intent_release(it); - path_release(nd); - return error; - -@@ -1210,7 +1335,10 @@ - * are done. Procfs-like symlinks just set LAST_BIND. - */ - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) -+ intent_release(it); - dput(dentry); - if (error) - return error; -@@ -1232,13 +1360,20 @@ - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1246,7 +1381,7 @@ - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1302,7 +1437,20 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1324,6 +1472,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1371,7 +1520,18 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 1); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 1, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - if (!IS_POSIXACL(nd.dentry->d_inode)) -@@ -1380,6 +1540,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1480,8 +1641,16 @@ - error = -EBUSY; - goto exit1; - } -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1539,8 +1708,15 @@ - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - /* Why not before? Because we want correct error value */ -@@ -1607,15 +1783,27 @@ - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+ out2: - path_release(&nd); --out: -+ out: - putname(to); - } - putname(from); -@@ -1691,7 +1879,18 @@ - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -- new_dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out_release; -+ } -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } -+ new_dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1735,7 +1934,7 @@ - * locking]. - */ - int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - struct inode *target; -@@ -1814,7 +2013,7 @@ - } - - int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - -@@ -1902,9 +2101,18 @@ - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ lock_kernel(); -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ unlock_kernel(); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - double_lock(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd.last, old_dir); -+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); - error = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto exit3; -@@ -1920,16 +2128,16 @@ - if (newnd.last.name[newnd.last.len]) - goto exit4; - } -- new_dentry = lookup_hash(&newnd.last, new_dir); -+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; - -+ - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); - unlock_kernel(); -- - dput(new_dentry); - exit4: - dput(old_dentry); -@@ -1980,20 +2188,26 @@ - } - - static inline int --__vfs_follow_link(struct nameidata *nd, const char *link) -+__vfs_follow_link(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) - { - int res = 0; - char *name; - if (IS_ERR(link)) - goto fail; - -+ if (it == NULL) -+ it = nd->intent; -+ else if (it != nd->intent) -+ printk("it != nd->intent: tell phil@clusterfs.com\n"); -+ - if (*link == '/') { - path_release(nd); - if (!walk_init_root(link, nd)) - /* weird __emul_prefix() stuff did it */ - goto out; - } -- res = __link_path_walk(link, nd); -+ res = __link_path_walk_it(link, nd, it); - out: - if (current->link_count || res || nd->last_type!=LAST_NORM) - return res; -@@ -2017,7 +2231,13 @@ - - int vfs_follow_link(struct nameidata *nd, const char *link) - { -- return __vfs_follow_link(nd, link); -+ return __vfs_follow_link(nd, link, NULL); -+} -+ -+int vfs_follow_link_it(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) -+{ -+ return __vfs_follow_link(nd, link, it); - } - - /* get the link contents into pagecache */ -@@ -2059,7 +2279,7 @@ - { - struct page *page = NULL; - char *s = page_getlink(dentry, &page); -- int res = __vfs_follow_link(nd, s); -+ int res = __vfs_follow_link(nd, s, NULL); - if (page) { - kunmap(page); - page_cache_release(page); -Index: linux-2.4.21-x86_64/fs/namespace.c -=================================================================== ---- linux-2.4.21-x86_64.orig/fs/namespace.c 2003-10-28 10:34:12.000000000 -0800 -+++ linux-2.4.21-x86_64/fs/namespace.c 2004-04-12 19:57:36.000000000 -0700 -@@ -98,6 +98,7 @@ - { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; -+ UNPIN(old_nd->dentry, old_nd->mnt, 1); - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); -@@ -109,6 +110,7 @@ - { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); -+ PIN(nd->dentry, nd->mnt, 1); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; -@@ -488,14 +490,17 @@ - { - struct nameidata old_nd; - struct vfsmount *mnt = NULL; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int err = mount_is_safe(nd); - if (err) - return err; - if (!old_name || !*old_name) - return -EINVAL; -- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd); -- if (err) -+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it); -+ if (err) { -+ intent_release(&it); - return err; -+ } - - down_write(¤t->namespace->sem); - err = -EINVAL; -@@ -518,6 +523,7 @@ - } - - up_write(¤t->namespace->sem); -+ intent_release(&it); - path_release(&old_nd); - return err; - } -@@ -701,6 +707,7 @@ - unsigned long flags, void *data_page) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int retval = 0; - int mnt_flags = 0; - -@@ -725,10 +732,11 @@ - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); - - /* ... and get the mountpoint */ -- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -- if (retval) -+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); -+ if (retval) { -+ intent_release(&it); - return retval; -- -+ } - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, - data_page); -@@ -739,6 +747,8 @@ - else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, - dev_name, data_page); -+ -+ intent_release(&it); - path_release(&nd); - return retval; - } -@@ -904,6 +914,8 @@ - { - struct vfsmount *tmp; - struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; -+ struct lookup_intent new_it = { .it_op = IT_GETATTR }; -+ struct lookup_intent old_it = { .it_op = IT_GETATTR }; - int error; - - if (!capable(CAP_SYS_ADMIN)) -@@ -911,14 +923,14 @@ - - lock_kernel(); - -- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it); - if (error) - goto out0; - error = -EINVAL; - if (!check_mnt(new_nd.mnt)) - goto out1; - -- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); -+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it); - if (error) - goto out1; - -@@ -973,8 +985,10 @@ - up(&old_nd.dentry->d_inode->i_zombie); - up_write(¤t->namespace->sem); - path_release(&user_nd); -+ intent_release(&old_it); - path_release(&old_nd); - out1: -+ intent_release(&new_it); - path_release(&new_nd); - out0: - unlock_kernel(); -Index: linux-2.4.21-x86_64/fs/open.c -=================================================================== ---- linux-2.4.21-x86_64.orig/fs/open.c 2003-10-28 10:33:59.000000000 -0800 -+++ linux-2.4.21-x86_64/fs/open.c 2004-04-12 19:57:36.000000000 -0700 -@@ -19,6 +19,8 @@ - #include <asm/uaccess.h> - - #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) -+extern int path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it); - - int vfs_statfs(struct super_block *sb, struct statfs *buf) - { -@@ -95,9 +97,10 @@ - write_unlock(&files->file_lock); - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - struct inode *inode = dentry->d_inode; -+ struct inode_operations *op = dentry->d_inode->i_op; - int error; - struct iattr newattrs; - -@@ -109,7 +112,13 @@ - down(&inode->i_sem); - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -- error = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ } else -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); - up_write(&inode->i_alloc_sem); - return error; -@@ -120,12 +129,13 @@ - struct nameidata nd; - struct inode * inode; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd, &it); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -165,11 +175,13 @@ - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ intent_release(&it); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -217,7 +229,7 @@ - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -262,11 +274,13 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -281,11 +295,25 @@ - goto dput_and_out; - - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!times) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; - } -+ - error = notify_change(nd.dentry, &newattrs); - dput_and_out: - path_release(&nd); -@@ -306,12 +334,14 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -326,7 +356,20 @@ - newattrs.ia_atime = times[0].tv_sec; - newattrs.ia_mtime = times[1].tv_sec; - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ error = -EPERM; -+ if (!utimes) { - if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE)) != 0) - goto dput_and_out; -@@ -349,6 +392,7 @@ - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -366,13 +410,14 @@ - else - current->cap_effective = current->cap_permitted; - -- res = user_path_walk(filename, &nd); -+ res = user_path_walk_it(filename, &nd, &it); - if (!res) { - res = permission(nd.dentry->d_inode, mode); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ intent_release(&it); - path_release(&nd); - } - -@@ -387,8 +432,9 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); -+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); - if (error) - goto out; - -@@ -399,6 +445,7 @@ - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -438,9 +485,10 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it); - if (error) - goto out; - -@@ -456,39 +504,56 @@ - set_fs_altroot(); - error = 0; - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode *inode = dentry->d_inode; - struct iattr newattrs; -+ int err = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -+ if (inode->i_op->setattr_raw) { -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (err != -EOPNOTSUPP) -+ goto out; -+ } - -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); - --out_putf: -+out: -+ return err; -+} -+ -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); -+ - fput(file); - out: - return err; -@@ -497,30 +562,14 @@ - asmlinkage long sys_chmod(const char * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; -- -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; - -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; -+ error = chmod_common(nd.dentry, mode); - -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -- --dput_and_out: - path_release(&nd); - out: - return error; -@@ -540,6 +589,20 @@ - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } -+ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -@@ -644,6 +707,7 @@ - { - int namei_flags, error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_OPEN }; - - namei_flags = flags; - if ((namei_flags+1) & O_ACCMODE) -@@ -651,14 +715,15 @@ - if (namei_flags & O_TRUNC) - namei_flags |= 2; - -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return dentry_open(nd.dentry, nd.mnt, flags); -+ error = open_namei_it(filename, namei_flags, mode, &nd, &it); -+ if (error) -+ return ERR_PTR(error); - -- return ERR_PTR(error); -+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); - } - --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it) - { - struct file * f; - struct inode *inode; -@@ -686,7 +751,9 @@ - file_move(f, &inode->i_sb->s_files); - - if (f->f_op && f->f_op->open) { -+ f->f_it = it; - error = f->f_op->open(inode,f); -+ f->f_it = NULL; - if (error) - goto cleanup_all; - } -@@ -698,6 +765,7 @@ - !inode->i_mapping->a_ops->direct_IO)) - goto cleanup_all; - -+ intent_release(it); - return f; - - cleanup_all: -@@ -710,11 +778,17 @@ - cleanup_file: - put_filp(f); - cleanup_dentry: -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); - } - -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ return dentry_open_it(dentry, mnt, flags, NULL); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ -Index: linux-2.4.21-x86_64/fs/stat.c -=================================================================== ---- linux-2.4.21-x86_64.orig/fs/stat.c 2003-10-28 10:33:58.000000000 -0800 -+++ linux-2.4.21-x86_64/fs/stat.c 2004-04-12 19:58:44.000000000 -0700 -@@ -17,10 +17,12 @@ - * Revalidate the inode. This is required for proper NFS attribute caching. - */ - static __inline__ int --do_revalidate(struct dentry *dentry) -+do_revalidate(struct dentry *dentry, struct lookup_intent *it) - { - struct inode * inode = dentry->d_inode; -- if (inode->i_op && inode->i_op->revalidate) -+ if (inode->i_op && inode->i_op->revalidate_it) -+ return inode->i_op->revalidate_it(dentry, it); -+ else if (inode->i_op && inode->i_op->revalidate) - return inode->i_op->revalidate(dentry); - return 0; - } -@@ -141,13 +143,15 @@ - asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -157,13 +161,15 @@ - asmlinkage long sys_newstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -178,13 +184,15 @@ - asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -195,13 +203,15 @@ - asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -222,7 +232,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); -@@ -241,7 +251,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); -@@ -263,7 +273,7 @@ - - error = -EINVAL; - if (inode->i_op && inode->i_op->readlink && -- !(error = do_revalidate(nd.dentry))) { -+ !(error = do_revalidate(nd.dentry, NULL))) { - UPDATE_ATIME(inode); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); - } -@@ -339,12 +349,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -354,12 +366,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -374,7 +388,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); -Index: linux-2.4.21-x86_64/include/linux/dcache.h -=================================================================== ---- linux-2.4.21-x86_64.orig/include/linux/dcache.h 2003-11-10 16:44:28.000000000 -0800 -+++ linux-2.4.21-x86_64/include/linux/dcache.h 2004-04-12 19:57:36.000000000 -0700 -@@ -7,6 +7,51 @@ - #include <linux/gdb.h> - #include <linux/mount.h> - #include <linux/kernel.h> -+#include <linux/string.h> -+ -+#define IT_OPEN 0x0001 -+#define IT_CREAT 0x0002 -+#define IT_READDIR 0x0004 -+#define IT_GETATTR 0x0008 -+#define IT_LOOKUP 0x0010 -+#define IT_UNLINK 0x0020 -+#define IT_GETXATTR 0x0040 -+#define IT_EXEC 0x0080 -+#define IT_PIN 0x0100 -+ -+#define IT_FL_LOCKED 0x0001 -+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */ -+ -+#define INTENT_MAGIC 0x19620323 -+ -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; -+ int it_int_flags; -+}; -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_init(struct lookup_intent *it, int op, int flags) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+ it->it_flags = flags; -+} -+ - - /* - * linux/include/linux/dcache.h -@@ -94,8 +139,22 @@ - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *); -+ void (*d_pin)(struct dentry *, struct vfsmount * , int); -+ void (*d_unpin)(struct dentry *, struct vfsmount *, int); - }; - -+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \ -+ de->d_op->d_pin(de, mnt, flag); -+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \ -+ de->d_op->d_unpin(de, mnt, flag); -+ -+ -+/* defined in fs/namei.c */ -+extern void intent_release(struct lookup_intent *it); -+/* defined in fs/dcache.c */ -+extern void __d_rehash(struct dentry * entry, int lock); -+ - /* the dentry parameter passed to d_hash and d_compare is the parent - * directory of the entries to be compared. It is used in case these - * functions need any directory specific information for determining -@@ -127,6 +186,7 @@ - * s_nfsd_free_path semaphore will be down - */ - #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ - - extern spinlock_t dcache_lock; - -Index: linux-2.4.21-x86_64/include/linux/fs.h -=================================================================== ---- linux-2.4.21-x86_64.orig/include/linux/fs.h 2004-04-12 19:57:33.000000000 -0700 -+++ linux-2.4.21-x86_64/include/linux/fs.h 2004-04-12 19:57:36.000000000 -0700 -@@ -74,6 +74,7 @@ - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - #define READ 0 - #define WRITE 1 -@@ -361,6 +362,9 @@ - #define ATTR_MTIME_SET 256 - #define ATTR_FORCE 512 /* Not a change, but a change it */ - #define ATTR_ATTR_FLAG 1024 -+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */ -+#define ATTR_CTIME_SET 0x2000 - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -505,6 +509,7 @@ - struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; - struct char_device *i_cdev; -+ void *i_filterdata; - - unsigned long i_dnotify_mask; /* Directory notify events */ - struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -667,6 +672,7 @@ - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_it; - struct list_head f_ep_links; - spinlock_t f_ep_lock; - }; -@@ -796,6 +802,7 @@ - struct qstr last; - unsigned int flags; - int last_type; -+ struct lookup_intent *intent; - }; - - /* -@@ -917,7 +924,8 @@ - extern int __vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry); - - /* - * File types -@@ -992,21 +1000,32 @@ - - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); -+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,int); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -+ int (*revalidate_it) (struct dentry *, struct lookup_intent *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); - int (*setxattr) (struct dentry *, const char *, const void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1205,10 +1224,14 @@ - - asmlinkage long sys_open(const char *, int, int); - asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern int open_namei_it(const char *filename, int namei_flags, int mode, -+ struct nameidata *nd, struct lookup_intent *it); -+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1504,6 +1527,7 @@ - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1516,6 +1540,8 @@ - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void _inode_init_once(struct inode *); -@@ -1667,6 +1693,8 @@ - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; -Index: linux-2.4.21-x86_64/include/linux/fs_struct.h -=================================================================== ---- linux-2.4.21-x86_64.orig/include/linux/fs_struct.h 2001-07-13 15:10:44.000000000 -0700 -+++ linux-2.4.21-x86_64/include/linux/fs_struct.h 2004-04-12 19:57:36.000000000 -0700 -@@ -34,10 +34,12 @@ - write_lock(&fs->lock); - old_root = fs->root; - old_rootmnt = fs->rootmnt; -+ PIN(dentry, mnt, 1); - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); - write_unlock(&fs->lock); - if (old_root) { -+ UNPIN(old_root, old_rootmnt, 1); - dput(old_root); - mntput(old_rootmnt); - } -@@ -57,10 +59,12 @@ - write_lock(&fs->lock); - old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; -+ PIN(dentry, mnt, 0); - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); - write_unlock(&fs->lock); - if (old_pwd) { -+ UNPIN(old_pwd, old_pwdmnt, 0); - dput(old_pwd); - mntput(old_pwdmnt); - } -Index: linux-2.4.21-x86_64/kernel/exit.c -=================================================================== ---- linux-2.4.21-x86_64.orig/kernel/exit.c 2003-10-28 10:34:13.000000000 -0800 -+++ linux-2.4.21-x86_64/kernel/exit.c 2004-04-12 19:57:36.000000000 -0700 -@@ -288,11 +288,14 @@ - { - /* No need to hold fs->lock if we are killing it */ - if (atomic_dec_and_test(&fs->count)) { -+ UNPIN(fs->pwd, fs->pwdmnt, 0); -+ UNPIN(fs->root, fs->rootmnt, 1); - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { -+ UNPIN(fs->altroot, fs->altrootmnt, 1); - dput(fs->altroot); - mntput(fs->altrootmnt); - } -Index: linux-2.4.21-x86_64/kernel/fork.c -=================================================================== ---- linux-2.4.21-x86_64.orig/kernel/fork.c 2003-10-28 10:34:17.000000000 -0800 -+++ linux-2.4.21-x86_64/kernel/fork.c 2004-04-12 19:57:36.000000000 -0700 -@@ -461,10 +461,13 @@ - fs->umask = old->umask; - read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); -+ PIN(old->pwd, old->pwdmnt, 0); -+ PIN(old->root, old->rootmnt, 1); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { -+ PIN(old->altroot, old->altrootmnt, 1); - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); - } else { -Index: linux-2.4.21-x86_64/kernel/ksyms.c -=================================================================== ---- linux-2.4.21-x86_64.orig/kernel/ksyms.c 2004-04-12 19:57:33.000000000 -0700 -+++ linux-2.4.21-x86_64/kernel/ksyms.c 2004-04-12 19:57:36.000000000 -0700 -@@ -327,6 +327,7 @@ - EXPORT_SYMBOL(set_page_dirty); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.4.29-vanilla.patch b/lustre/kernel_patches/patches/vfs_intent-2.4.29-vanilla.patch deleted file mode 100644 index f19fbd4..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.4.29-vanilla.patch +++ /dev/null @@ -1,1833 +0,0 @@ -Index: linux-2.4.29/fs/dcache.c -=================================================================== ---- linux-2.4.29.orig/fs/dcache.c 2005-04-07 18:52:37.000000000 +0300 -+++ linux-2.4.29/fs/dcache.c 2005-04-07 19:14:06.000000000 +0300 -@@ -184,6 +184,13 @@ - spin_unlock(&dcache_lock); - return 0; - } -+ -+ /* network invalidation by Lustre */ -+ if (dentry->d_flags & DCACHE_LUSTRE_INVALID) { -+ spin_unlock(&dcache_lock); -+ return 0; -+ } -+ - /* - * Check whether to do a partial shrink_dcache - * to get rid of unused child entries. -@@ -836,13 +843,19 @@ - * Adds a dentry to the hash according to its name. - */ - --void d_rehash(struct dentry * entry) -+void __d_rehash(struct dentry * entry, int lock) - { - struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); - if (!list_empty(&entry->d_hash)) BUG(); -- spin_lock(&dcache_lock); -+ if (lock) spin_lock(&dcache_lock); - list_add(&entry->d_hash, list); -- spin_unlock(&dcache_lock); -+ if (lock) spin_unlock(&dcache_lock); -+} -+EXPORT_SYMBOL(__d_rehash); -+ -+void d_rehash(struct dentry * entry) -+{ -+ __d_rehash(entry, 1); - } - - #define do_switch(x,y) do { \ -Index: linux-2.4.29/fs/exec.c -=================================================================== ---- linux-2.4.29.orig/fs/exec.c 2005-04-07 18:53:19.000000000 +0300 -+++ linux-2.4.29/fs/exec.c 2005-04-07 19:14:06.000000000 +0300 -@@ -112,8 +112,10 @@ - struct file * file; - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- error = user_path_walk(library, &nd); -+ error = user_path_walk_it(library, &nd, &it); - if (error) - goto out; - -@@ -125,7 +127,8 @@ - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -378,8 +381,10 @@ - struct inode *inode; - struct file *file; - int err = 0; -+ struct lookup_intent it = { .it_op = IT_OPEN, -+ .it_flags = FMODE_READ|FMODE_EXEC }; - -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -+ err = path_lookup_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); - file = ERR_PTR(err); - if (!err) { - inode = nd.dentry->d_inode; -@@ -391,7 +396,8 @@ - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &it); -+ intent_release(&it); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { -@@ -403,6 +409,7 @@ - return file; - } - } -+ intent_release(&it); - path_release(&nd); - } - goto out; -@@ -1163,7 +1170,7 @@ - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.4.29/fs/namei.c -=================================================================== ---- linux-2.4.29.orig/fs/namei.c 2005-04-07 18:53:14.000000000 +0300 -+++ linux-2.4.29/fs/namei.c 2005-05-03 17:23:44.139922792 +0300 -@@ -94,6 +94,13 @@ - * XEmacs seems to be relying on it... - */ - -+void intent_release(struct lookup_intent *it) -+{ -+ if (it && it->it_op_release) -+ it->it_op_release(it); -+ -+} -+ - /* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. -@@ -260,10 +267,19 @@ - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * dentry = d_lookup(parent, name); - -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ if (!dentry->d_op->d_revalidate_it(dentry, flags, it) && -+ !d_invalidate(dentry)) { -+ dput(dentry); -+ dentry = NULL; -+ } -+ return dentry; -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) { - dput(dentry); -@@ -281,11 +297,15 @@ - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags) -+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name, -+ int flags, struct lookup_intent *it) - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - -+again: -+ counter++; - down(&dir->i_sem); - /* - * First re-do the cached lookup just in case it was created -@@ -300,6 +320,9 @@ - result = ERR_PTR(-ENOMEM); - if (dentry) { - lock_kernel(); -+ if (dir->i_op->lookup_it) -+ result = dir->i_op->lookup_it(dir, dentry, it, flags); -+ else - result = dir->i_op->lookup(dir, dentry); - unlock_kernel(); - if (result) -@@ -321,6 +344,15 @@ - dput(result); - result = ERR_PTR(-ENOENT); - } -+ } else if (result->d_op && result->d_op->d_revalidate_it) { -+ if (!result->d_op->d_revalidate_it(result, flags, it) && -+ !d_invalidate(result)) { -+ dput(result); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; -+ } - } - return result; - } -@@ -332,7 +364,8 @@ - * Without that kind of total limit, nasty chains of consecutive - * symlinks can cause almost arbitrarily long lookups. - */ --static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) -+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd, -+ struct lookup_intent *it) - { - int err; - if (current->link_count >= 5) -@@ -346,10 +379,12 @@ - current->link_count++; - current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - err = dentry->d_inode->i_op->follow_link(dentry, nd); - current->link_count--; - return err; - loop: -+ intent_release(it); - path_release(nd); - return -ELOOP; - } -@@ -447,7 +482,8 @@ - * - * We expect 'base' to be positive and a directory. - */ --int fastcall link_path_walk(const char * name, struct nameidata *nd) -+int fastcall link_path_walk_it(const char * name, struct nameidata *nd, -+ struct lookup_intent *it) - { - struct dentry *dentry; - struct inode *inode; -@@ -520,9 +556,9 @@ - break; - } - /* This does the actual lookups.. */ -- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - if (!dentry) { -- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE); -+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -540,7 +576,7 @@ - goto out_dput; - - if (inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, NULL); - dput(dentry); - if (err) - goto return_err; -@@ -556,7 +592,7 @@ - nd->dentry = dentry; - } - err = -ENOTDIR; -- if (!inode->i_op->lookup) -+ if (!inode->i_op->lookup && !inode->i_op->lookup_it) - break; - continue; - /* here ends the main loop */ -@@ -583,9 +619,9 @@ - if (err < 0) - break; - } -- dentry = cached_lookup(nd->dentry, &this, nd->flags); -+ dentry = cached_lookup(nd->dentry, &this, nd->flags, it); - if (!dentry) { -- dentry = real_lookup(nd->dentry, &this, nd->flags); -+ dentry = real_lookup(nd->dentry, &this, nd->flags, it); - err = PTR_ERR(dentry); - if (IS_ERR(dentry)) - break; -@@ -595,7 +631,7 @@ - inode = dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op && inode->i_op->follow_link) { -- err = do_follow_link(dentry, nd); -+ err = do_follow_link(dentry, nd, it); - dput(dentry); - if (err) - goto return_err; -@@ -609,7 +645,8 @@ - goto no_inode; - if (lookup_flags & LOOKUP_DIRECTORY) { - err = -ENOTDIR; -- if (!inode->i_op || !inode->i_op->lookup) -+ if (!inode->i_op || -+ (!inode->i_op->lookup && !inode->i_op->lookup_it)) - break; - } - goto return_base; -@@ -635,6 +672,34 @@ - * Check the cached dentry for staleness. - */ - dentry = nd->dentry; -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate_it) { -+ err = -ESTALE; -+ if (!dentry->d_op->d_revalidate_it(dentry, 0, it)) { -+ struct dentry *new; -+ err = permission(dentry->d_parent->d_inode, -+ MAY_EXEC); -+ if (err) -+ break; -+ new = real_lookup(dentry->d_parent, -+ &dentry->d_name, 0, it); -+ if (IS_ERR(new)) { -+ err = PTR_ERR(new); -+ break; -+ } -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = new; -+ } -+ if (!nd->dentry->d_inode) -+ goto no_inode; -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if (!nd->dentry->d_inode->i_op || -+ (!nd->dentry->d_inode->i_op->lookup && -+ !nd->dentry->d_inode->i_op->lookup_it)) -+ break; -+ } -+ } else - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) { - err = -ESTALE; - if (!dentry->d_op->d_revalidate(dentry, 0)) { -@@ -648,15 +713,28 @@ - dput(dentry); - break; - } -+ if (err) -+ intent_release(it); - path_release(nd); - return_err: - return err; - } - -+int link_path_walk(const char * name, struct nameidata *nd) -+{ -+ return link_path_walk_it(name, nd, NULL); -+} -+ -+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it) -+{ -+ current->total_link_count = 0; -+ return link_path_walk_it(name, nd, it); -+} -+ - int fastcall path_walk(const char * name, struct nameidata *nd) - { - current->total_link_count = 0; -- return link_path_walk(name, nd); -+ return link_path_walk_it(name, nd, NULL); - } - - /* SMP-safe */ -@@ -741,6 +819,16 @@ - } - - /* SMP-safe */ -+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ int error = 0; -+ if (path_init(path, flags, nd)) -+ error = path_walk_it(path, nd, it); -+ return error; -+} -+ -+/* SMP-safe */ - int fastcall path_lookup(const char *path, unsigned flags, struct nameidata *nd) - { - int error = 0; -@@ -755,6 +843,7 @@ - { - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->intent = NULL; - if (*name=='/') - return walk_init_root(name,nd); - read_lock(¤t->fs->lock); -@@ -769,7 +858,8 @@ - * needs parent already locked. Doesn't follow mounts. - * SMP-safe. - */ --struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base, -+ struct lookup_intent *it) - { - struct dentry * dentry; - struct inode *inode; -@@ -792,13 +882,16 @@ - goto out; - } - -- dentry = cached_lookup(base, name, 0); -+ dentry = cached_lookup(base, name, 0, it); - if (!dentry) { - struct dentry *new = d_alloc(base, name); - dentry = ERR_PTR(-ENOMEM); - if (!new) - goto out; - lock_kernel(); -+ if (inode->i_op->lookup_it) -+ dentry = inode->i_op->lookup_it(inode, new, it, 0); -+ else - dentry = inode->i_op->lookup(inode, new); - unlock_kernel(); - if (!dentry) -@@ -810,6 +903,12 @@ - return dentry; - } - -+struct dentry * lookup_hash(struct qstr *name, struct dentry * base) -+{ -+ return lookup_hash_it(name, base, NULL); -+} -+ -+ - /* SMP-safe */ - struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) - { -@@ -831,7 +930,7 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return lookup_hash_it(&this, base, NULL); - access: - return ERR_PTR(-EACCES); - } -@@ -862,6 +961,23 @@ - return err; - } - -+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd, -+ struct lookup_intent *it) -+{ -+ char *tmp; -+ int err; -+ -+ tmp = getname(name); -+ err = PTR_ERR(tmp); -+ if (!IS_ERR(tmp)) { -+ err = 0; -+ if (path_init(tmp, flags, nd)) -+ err = path_walk_it(tmp, nd, it); -+ putname(tmp); -+ } -+ return err; -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -957,7 +1073,8 @@ - return retval; - } - --int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+static int vfs_create_it(struct inode *dir, struct dentry *dentry, int mode, -+ struct lookup_intent *it) - { - int error; - -@@ -970,12 +1087,15 @@ - goto exit_lock; - - error = -EACCES; /* shouldn't it be ENOSYS? */ -- if (!dir->i_op || !dir->i_op->create) -+ if (!dir->i_op || (!dir->i_op->create && !dir->i_op->create_it)) - goto exit_lock; - - DQUOT_INIT(dir); - lock_kernel(); -- error = dir->i_op->create(dir, dentry, mode); -+ if (dir->i_op->create_it) -+ error = dir->i_op->create_it(dir, dentry, mode, it); -+ else -+ error = dir->i_op->create(dir, dentry, mode); - unlock_kernel(); - exit_lock: - up(&dir->i_zombie); -@@ -984,6 +1104,11 @@ - return error; - } - -+int vfs_create(struct inode *dir, struct dentry *dentry, int mode) -+{ -+ return vfs_create_it(dir, dentry, mode, NULL); -+} -+ - /* - * open_namei() - * -@@ -998,7 +1123,8 @@ - * for symlinks (where the permissions are checked later). - * SMP-safe - */ --int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) -+int open_namei_it(const char *pathname, int flag, int mode, -+ struct nameidata *nd, struct lookup_intent *it) - { - int acc_mode, error = 0; - struct inode *inode; -@@ -1008,11 +1134,14 @@ - - acc_mode = ACC_MODE(flag); - -+ if (it) -+ it->it_flags = flag; -+ - /* - * The simplest case - just a plain lookup. - */ - if (!(flag & O_CREAT)) { -- error = path_lookup(pathname, lookup_flags(flag), nd); -+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it); - if (error) - return error; - dentry = nd->dentry; -@@ -1022,6 +1151,10 @@ - /* - * Create - we need to know the parent. - */ -+ if (it) { -+ it->it_create_mode = mode; -+ it->it_op |= IT_CREAT; -+ } - error = path_lookup(pathname, LOOKUP_PARENT, nd); - if (error) - return error; -@@ -1037,7 +1170,7 @@ - - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - - do_last: - error = PTR_ERR(dentry); -@@ -1046,10 +1179,11 @@ - goto exit; - } - -+ it->it_create_mode = mode; - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { -- error = vfs_create(dir->d_inode, dentry, -- mode & ~current->fs->umask); -+ error = vfs_create_it(dir->d_inode, dentry, -+ mode & ~current->fs->umask, it); - up(&dir->d_inode->i_sem); - dput(nd->dentry); - nd->dentry = dentry; -@@ -1153,7 +1287,7 @@ - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1165,8 +1299,10 @@ - return 0; - - exit_dput: -+ intent_release(it); - dput(dentry); - exit: -+ intent_release(it); - path_release(nd); - return error; - -@@ -1185,7 +1321,10 @@ - * are done. Procfs-like symlinks just set LAST_BIND. - */ - UPDATE_ATIME(dentry->d_inode); -+ nd->intent = it; - error = dentry->d_inode->i_op->follow_link(dentry, nd); -+ if (error) -+ intent_release(it); - dput(dentry); - if (error) - return error; -@@ -1207,13 +1346,20 @@ - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - putname(nd->last.name); - goto do_last; - } - -+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd) -+{ -+ return open_namei_it(pathname, flag, mode, nd, NULL); -+} -+ -+ - /* SMP-safe */ --static struct dentry *lookup_create(struct nameidata *nd, int is_dir) -+static struct dentry *lookup_create(struct nameidata *nd, int is_dir, -+ struct lookup_intent *it) - { - struct dentry *dentry; - -@@ -1221,7 +1367,7 @@ - dentry = ERR_PTR(-EEXIST); - if (nd->last_type != LAST_NORM) - goto fail; -- dentry = lookup_hash(&nd->last, nd->dentry); -+ dentry = lookup_hash_it(&nd->last, nd->dentry, it); - if (IS_ERR(dentry)) - goto fail; - if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode) -@@ -1277,7 +1423,20 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - - mode &= ~current->fs->umask; -@@ -1298,6 +1457,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1345,7 +1505,18 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 1); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 1, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_mkdir(nd.dentry->d_inode, dentry, -@@ -1353,6 +1524,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1453,8 +1625,16 @@ - error = -EBUSY; - goto exit1; - } -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); -@@ -1512,8 +1692,15 @@ - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); -- dentry = lookup_hash(&nd.last, nd.dentry); -+ dentry = lookup_hash_it(&nd.last, nd.dentry, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - /* Why not before? Because we want correct error value */ -@@ -1580,15 +1767,27 @@ - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -- dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out2; -+ } -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+ out2: - path_release(&nd); --out: -+ out: - putname(to); - } - putname(from); -@@ -1664,7 +1863,18 @@ - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -- new_dentry = lookup_create(&nd, 0); -+ if (nd.last_type != LAST_NORM) { -+ error = -EEXIST; -+ goto out_release; -+ } -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } -+ new_dentry = lookup_create(&nd, 0, NULL); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -@@ -1708,7 +1918,7 @@ - * locking]. - */ - int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - struct inode *target; -@@ -1787,7 +1997,7 @@ - } - - int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, -- struct inode *new_dir, struct dentry *new_dentry) -+ struct inode *new_dir, struct dentry *new_dentry) - { - int error; - -@@ -1875,9 +2085,18 @@ - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ lock_kernel(); -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ unlock_kernel(); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - double_lock(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd.last, old_dir); -+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, NULL); - error = PTR_ERR(old_dentry); - if (IS_ERR(old_dentry)) - goto exit3; -@@ -1893,16 +2112,16 @@ - if (newnd.last.name[newnd.last.len]) - goto exit4; - } -- new_dentry = lookup_hash(&newnd.last, new_dir); -+ new_dentry = lookup_hash_it(&newnd.last, new_dir, NULL); - error = PTR_ERR(new_dentry); - if (IS_ERR(new_dentry)) - goto exit4; - -+ - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); - unlock_kernel(); -- - dput(new_dentry); - exit4: - dput(old_dentry); -@@ -1953,20 +2172,26 @@ - } - - static inline int --__vfs_follow_link(struct nameidata *nd, const char *link) -+__vfs_follow_link(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) - { - int res = 0; - char *name; - if (IS_ERR(link)) - goto fail; - -+ if (it == NULL) -+ it = nd->intent; -+ else if (it != nd->intent) -+ printk("it != nd->intent: tell phil@clusterfs.com\n"); -+ - if (*link == '/') { - path_release(nd); - if (!walk_init_root(link, nd)) - /* weird __emul_prefix() stuff did it */ - goto out; - } -- res = link_path_walk(link, nd); -+ res = link_path_walk_it(link, nd, it); - out: - if (current->link_count || res || nd->last_type!=LAST_NORM) - return res; -@@ -1990,7 +2215,13 @@ - - int vfs_follow_link(struct nameidata *nd, const char *link) - { -- return __vfs_follow_link(nd, link); -+ return __vfs_follow_link(nd, link, NULL); -+} -+ -+int vfs_follow_link_it(struct nameidata *nd, const char *link, -+ struct lookup_intent *it) -+{ -+ return __vfs_follow_link(nd, link, it); - } - - /* get the link contents into pagecache */ -@@ -2032,7 +2263,7 @@ - { - struct page *page = NULL; - char *s = page_getlink(dentry, &page); -- int res = __vfs_follow_link(nd, s); -+ int res = __vfs_follow_link(nd, s, NULL); - if (page) { - kunmap(page); - page_cache_release(page); -Index: linux-2.4.29/fs/namespace.c -=================================================================== ---- linux-2.4.29.orig/fs/namespace.c 2005-04-07 18:54:11.000000000 +0300 -+++ linux-2.4.29/fs/namespace.c 2005-04-07 19:14:06.000000000 +0300 -@@ -98,6 +98,7 @@ - { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; -+ UNPIN(old_nd->dentry, old_nd->mnt, 1); - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); -@@ -109,6 +110,7 @@ - { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); -+ PIN(nd->dentry, nd->mnt, 1); - list_add(&mnt->mnt_hash, mount_hashtable+hash(nd->mnt, nd->dentry)); - list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; -@@ -488,14 +490,17 @@ - { - struct nameidata old_nd; - struct vfsmount *mnt = NULL; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int err = mount_is_safe(nd); - if (err) - return err; - if (!old_name || !*old_name) - return -EINVAL; -- err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd); -- if (err) -+ err = path_lookup_it(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd, &it); -+ if (err) { -+ intent_release(&it); - return err; -+ } - - down_write(¤t->namespace->sem); - err = -EINVAL; -@@ -518,6 +523,7 @@ - } - - up_write(¤t->namespace->sem); -+ intent_release(&it); - path_release(&old_nd); - return err; - } -@@ -701,6 +707,7 @@ - unsigned long flags, void *data_page) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int retval = 0; - int mnt_flags = 0; - -@@ -728,10 +735,11 @@ - flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV); - - /* ... and get the mountpoint */ -- retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd); -- if (retval) -+ retval = path_lookup_it(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd, &it); -+ if (retval) { -+ intent_release(&it); - return retval; -- -+ } - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, - data_page); -@@ -742,6 +750,8 @@ - else - retval = do_add_mount(&nd, type_page, flags, mnt_flags, - dev_name, data_page); -+ -+ intent_release(&it); - path_release(&nd); - return retval; - } -@@ -907,6 +917,8 @@ - { - struct vfsmount *tmp; - struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd; -+ struct lookup_intent new_it = { .it_op = IT_GETATTR }; -+ struct lookup_intent old_it = { .it_op = IT_GETATTR }; - int error; - - if (!capable(CAP_SYS_ADMIN)) -@@ -914,14 +926,14 @@ - - lock_kernel(); - -- error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -+ error = __user_walk_it(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd, &new_it); - if (error) - goto out0; - error = -EINVAL; - if (!check_mnt(new_nd.mnt)) - goto out1; - -- error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd); -+ error = __user_walk_it(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd, &old_it); - if (error) - goto out1; - -@@ -976,8 +988,10 @@ - up(&old_nd.dentry->d_inode->i_zombie); - up_write(¤t->namespace->sem); - path_release(&user_nd); -+ intent_release(&old_it); - path_release(&old_nd); - out1: -+ intent_release(&new_it); - path_release(&new_nd); - out0: - unlock_kernel(); -Index: linux-2.4.29/fs/open.c -=================================================================== ---- linux-2.4.29.orig/fs/open.c 2005-04-07 18:52:27.000000000 +0300 -+++ linux-2.4.29/fs/open.c 2005-04-07 19:14:06.000000000 +0300 -@@ -19,6 +19,8 @@ - #include <asm/uaccess.h> - - #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) -+extern int path_walk_it(const char *name, struct nameidata *nd, -+ struct lookup_intent *it); - - int vfs_statfs(struct super_block *sb, struct statfs *buf) - { -@@ -95,9 +97,10 @@ - write_unlock(&files->file_lock); - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - struct inode *inode = dentry->d_inode; -+ struct inode_operations *op = dentry->d_inode->i_op; - int error; - struct iattr newattrs; - -@@ -109,7 +112,13 @@ - down(&inode->i_sem); - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -- error = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ } else -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); - up_write(&inode->i_alloc_sem); - return error; -@@ -120,12 +129,13 @@ - struct nameidata nd; - struct inode * inode; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd, &it); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -165,11 +175,13 @@ - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ intent_release(&it); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -217,7 +229,7 @@ - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -262,11 +274,13 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -284,7 +298,20 @@ - goto dput_and_out; - - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ if (!times) { - error = -EACCES; - if (IS_IMMUTABLE(inode)) - goto dput_and_out; -@@ -312,12 +339,14 @@ - struct inode * inode; - struct iattr newattrs; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, NULL); - - if (error) - goto out; - inode = nd.dentry->d_inode; - -+ /* this is safe without a Lustre lock because it only depends -+ on the super block */ - error = -EROFS; - if (IS_RDONLY(inode)) - goto dput_and_out; -@@ -335,7 +364,19 @@ - newattrs.ia_atime = times[0].tv_sec; - newattrs.ia_mtime = times[1].tv_sec; - newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; -- } else { -+ } -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } -+ -+ if (!utimes) { - error = -EACCES; - if (IS_IMMUTABLE(inode)) - goto dput_and_out; -@@ -362,6 +403,7 @@ - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -379,13 +421,14 @@ - else - current->cap_effective = current->cap_permitted; - -- res = user_path_walk(filename, &nd); -+ res = user_path_walk_it(filename, &nd, &it); - if (!res) { - res = permission(nd.dentry->d_inode, mode); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ intent_release(&it); - path_release(&nd); - } - -@@ -400,8 +443,9 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd); -+ error = __user_walk_it(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd, &it); - if (error) - goto out; - -@@ -412,6 +456,7 @@ - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; -@@ -451,9 +496,10 @@ - { - int error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | -+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it); - if (error) - goto out; - -@@ -469,39 +515,56 @@ - set_fs_altroot(); - error = 0; - dput_and_out: -+ intent_release(&it); - path_release(&nd); - out: - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode *inode = dentry->d_inode; - struct iattr newattrs; -+ int err = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -+ if (inode->i_op->setattr_raw) { -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ err = inode->i_op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (err != -EOPNOTSUPP) -+ goto out; -+ } - -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); - --out_putf: -+out: -+ return err; -+} -+ -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); -+ - fput(file); - out: - return err; -@@ -510,30 +573,14 @@ - asmlinkage long sys_chmod(const char * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; -- -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; -- -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; - -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -+ error = chmod_common(nd.dentry, mode); - --dput_and_out: - path_release(&nd); - out: - return error; -@@ -553,6 +600,20 @@ - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } -+ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -@@ -657,6 +718,7 @@ - { - int namei_flags, error; - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_OPEN }; - - namei_flags = flags; - if ((namei_flags+1) & O_ACCMODE) -@@ -664,14 +726,15 @@ - if (namei_flags & O_TRUNC) - namei_flags |= 2; - -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return dentry_open(nd.dentry, nd.mnt, flags); -+ error = open_namei_it(filename, namei_flags, mode, &nd, &it); -+ if (error) -+ return ERR_PTR(error); - -- return ERR_PTR(error); -+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it); - } - --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it) - { - struct file * f; - struct inode *inode; -@@ -708,12 +771,15 @@ - } - - if (f->f_op && f->f_op->open) { -+ f->f_it = it; - error = f->f_op->open(inode,f); -+ f->f_it = NULL; - if (error) - goto cleanup_all; - } - f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - -+ intent_release(it); - return f; - - cleanup_all: -@@ -728,11 +794,17 @@ - cleanup_file: - put_filp(f); - cleanup_dentry: -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); - } - -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ return dentry_open_it(dentry, mnt, flags, NULL); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ -Index: linux-2.4.29/fs/stat.c -=================================================================== ---- linux-2.4.29.orig/fs/stat.c 2005-04-07 18:52:47.000000000 +0300 -+++ linux-2.4.29/fs/stat.c 2005-04-07 19:14:06.000000000 +0300 -@@ -17,10 +17,12 @@ - * Revalidate the inode. This is required for proper NFS attribute caching. - */ - static __inline__ int --do_revalidate(struct dentry *dentry) -+do_revalidate(struct dentry *dentry, struct lookup_intent *it) - { - struct inode * inode = dentry->d_inode; -- if (inode->i_op && inode->i_op->revalidate) -+ if (inode->i_op && inode->i_op->revalidate_it) -+ return inode->i_op->revalidate_it(dentry, it); -+ else if (inode->i_op && inode->i_op->revalidate) - return inode->i_op->revalidate(dentry); - return 0; - } -@@ -141,13 +143,15 @@ - asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -157,13 +161,15 @@ - asmlinkage long sys_newstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -178,13 +184,15 @@ - asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -195,13 +203,15 @@ - asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) - { - struct nameidata nd; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - int error; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -222,7 +232,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); -@@ -241,7 +251,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); -@@ -263,7 +273,7 @@ - - error = -EINVAL; - if (inode->i_op && inode->i_op->readlink && -- !(error = do_revalidate(nd.dentry))) { -+ !(error = do_revalidate(nd.dentry, NULL))) { - UPDATE_ATIME(inode); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); - } -@@ -339,12 +349,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk(filename, &nd); -+ error = user_path_walk_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -354,12 +366,14 @@ - { - struct nameidata nd; - int error; -+ struct lookup_intent it = { .it_op = IT_GETATTR }; - -- error = user_path_walk_link(filename, &nd); -+ error = user_path_walk_link_it(filename, &nd, &it); - if (!error) { -- error = do_revalidate(nd.dentry); -+ error = do_revalidate(nd.dentry, &it); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); -+ intent_release(&it); - path_release(&nd); - } - return error; -@@ -374,7 +388,7 @@ - if (f) { - struct dentry * dentry = f->f_dentry; - -- err = do_revalidate(dentry); -+ err = do_revalidate(dentry, NULL); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); -Index: linux-2.4.29/include/linux/dcache.h -=================================================================== ---- linux-2.4.29.orig/include/linux/dcache.h 2005-04-07 18:55:17.000000000 +0300 -+++ linux-2.4.29/include/linux/dcache.h 2005-04-07 19:14:06.000000000 +0300 -@@ -6,6 +6,51 @@ - #include <asm/atomic.h> - #include <linux/mount.h> - #include <linux/kernel.h> -+#include <linux/string.h> -+ -+#define IT_OPEN 0x0001 -+#define IT_CREAT 0x0002 -+#define IT_READDIR 0x0004 -+#define IT_GETATTR 0x0008 -+#define IT_LOOKUP 0x0010 -+#define IT_UNLINK 0x0020 -+#define IT_GETXATTR 0x0040 -+#define IT_EXEC 0x0080 -+#define IT_PIN 0x0100 -+ -+#define IT_FL_LOCKED 0x0001 -+#define IT_FL_FOLLOWED 0x0002 /* set by vfs_follow_link */ -+ -+#define INTENT_MAGIC 0x19620323 -+ -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; -+ int it_int_flags; -+}; -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_init(struct lookup_intent *it, int op, int flags) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+ it->it_flags = flags; -+} -+ - - /* - * linux/include/linux/dcache.h -@@ -91,8 +136,22 @@ - int (*d_delete)(struct dentry *); - void (*d_release)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); -+ int (*d_revalidate_it)(struct dentry *, int, struct lookup_intent *); -+ void (*d_pin)(struct dentry *, struct vfsmount * , int); -+ void (*d_unpin)(struct dentry *, struct vfsmount *, int); - }; - -+#define PIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_pin) \ -+ de->d_op->d_pin(de, mnt, flag); -+#define UNPIN(de,mnt,flag) if (de && de->d_op && de->d_op->d_unpin) \ -+ de->d_op->d_unpin(de, mnt, flag); -+ -+ -+/* defined in fs/namei.c */ -+extern void intent_release(struct lookup_intent *it); -+/* defined in fs/dcache.c */ -+extern void __d_rehash(struct dentry * entry, int lock); -+ - /* the dentry parameter passed to d_hash and d_compare is the parent - * directory of the entries to be compared. It is used in case these - * functions need any directory specific information for determining -@@ -124,6 +183,7 @@ - * s_nfsd_free_path semaphore will be down - */ - #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -+#define DCACHE_LUSTRE_INVALID 0x0010 /* Lustre invalidated */ - - extern spinlock_t dcache_lock; - -Index: linux-2.4.29/include/linux/fs.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs.h 2005-04-07 18:59:19.000000000 +0300 -+++ linux-2.4.29/include/linux/fs.h 2005-05-03 17:06:23.738087912 +0300 -@@ -73,6 +73,7 @@ - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - #define READ 0 - #define WRITE 1 -@@ -340,6 +341,9 @@ - #define ATTR_MTIME_SET 256 - #define ATTR_FORCE 512 /* Not a change, but a change it */ - #define ATTR_ATTR_FLAG 1024 -+#define ATTR_RAW 0x0800 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 0x1000 /* called from open path, ie O_TRUNC */ -+#define ATTR_CTIME_SET 0x2000 - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -478,6 +482,7 @@ - struct pipe_inode_info *i_pipe; - struct block_device *i_bdev; - struct char_device *i_cdev; -+ void *i_filterdata; - - unsigned long i_dnotify_mask; /* Directory notify events */ - struct dnotify_struct *i_dnotify; /* for directory notifications */ -@@ -580,6 +585,7 @@ - - /* needed for tty driver, and maybe others */ - void *private_data; -+ struct lookup_intent *f_it; - - /* preallocated helper kiobuf to speedup O_DIRECT */ - struct kiobuf *f_iobuf; -@@ -700,6 +706,7 @@ - struct qstr last; - unsigned int flags; - int last_type; -+ struct lookup_intent *intent; - }; - - /* -@@ -820,7 +827,8 @@ - extern int vfs_link(struct dentry *, struct inode *, struct dentry *); - extern int vfs_rmdir(struct inode *, struct dentry *); - extern int vfs_unlink(struct inode *, struct dentry *); --extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry); - - /* - * File types -@@ -880,21 +888,32 @@ - - struct inode_operations { - int (*create) (struct inode *,struct dentry *,int); -+ int (*create_it) (struct inode *,struct dentry *,int, struct lookup_intent *); - struct dentry * (*lookup) (struct inode *,struct dentry *); -+ struct dentry * (*lookup_it) (struct inode *,struct dentry *, struct lookup_intent *, int flags); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,int); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int); - int (*revalidate) (struct dentry *); -+ int (*revalidate_it) (struct dentry *, struct lookup_intent *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct dentry *, struct iattr *); - int (*setxattr) (struct dentry *, const char *, void *, size_t, int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); -@@ -1091,10 +1110,14 @@ - - asmlinkage long sys_open(const char *, int, int); - asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern int open_namei_it(const char *filename, int namei_flags, int mode, -+ struct nameidata *nd, struct lookup_intent *it); -+extern struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, -+ int flags, struct lookup_intent *it); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); - -@@ -1385,6 +1408,7 @@ - extern loff_t default_llseek(struct file *file, loff_t offset, int origin); - - extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it)); - extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *)); - extern int FASTCALL(path_walk(const char *, struct nameidata *)); - extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); -@@ -1396,6 +1420,8 @@ - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); - #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd) - #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) -+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it) -+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it) - - extern void inode_init_once(struct inode *); - extern void __inode_init_once(struct inode *); -@@ -1539,6 +1565,8 @@ - - extern int vfs_readlink(struct dentry *, char *, int, const char *); - extern int vfs_follow_link(struct nameidata *, const char *); -+extern int vfs_follow_link_it(struct nameidata *, const char *, -+ struct lookup_intent *it); - extern int page_readlink(struct dentry *, char *, int); - extern int page_follow_link(struct dentry *, struct nameidata *); - extern struct inode_operations page_symlink_inode_operations; -Index: linux-2.4.29/include/linux/fs_struct.h -=================================================================== ---- linux-2.4.29.orig/include/linux/fs_struct.h 2005-04-07 18:54:22.000000000 +0300 -+++ linux-2.4.29/include/linux/fs_struct.h 2005-04-07 19:14:06.000000000 +0300 -@@ -34,10 +34,12 @@ - write_lock(&fs->lock); - old_root = fs->root; - old_rootmnt = fs->rootmnt; -+ PIN(dentry, mnt, 1); - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); - write_unlock(&fs->lock); - if (old_root) { -+ UNPIN(old_root, old_rootmnt, 1); - dput(old_root); - mntput(old_rootmnt); - } -@@ -57,10 +59,12 @@ - write_lock(&fs->lock); - old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; -+ PIN(dentry, mnt, 0); - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); - write_unlock(&fs->lock); - if (old_pwd) { -+ UNPIN(old_pwd, old_pwdmnt, 0); - dput(old_pwd); - mntput(old_pwdmnt); - } -Index: linux-2.4.29/kernel/exit.c -=================================================================== ---- linux-2.4.29.orig/kernel/exit.c 2005-04-07 18:53:09.000000000 +0300 -+++ linux-2.4.29/kernel/exit.c 2005-04-07 19:14:06.000000000 +0300 -@@ -238,11 +238,14 @@ - { - /* No need to hold fs->lock if we are killing it */ - if (atomic_dec_and_test(&fs->count)) { -+ UNPIN(fs->pwd, fs->pwdmnt, 0); -+ UNPIN(fs->root, fs->rootmnt, 1); - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { -+ UNPIN(fs->altroot, fs->altrootmnt, 1); - dput(fs->altroot); - mntput(fs->altrootmnt); - } -Index: linux-2.4.29/kernel/fork.c -=================================================================== ---- linux-2.4.29.orig/kernel/fork.c 2005-04-07 18:52:37.000000000 +0300 -+++ linux-2.4.29/kernel/fork.c 2005-04-07 19:14:06.000000000 +0300 -@@ -388,10 +388,13 @@ - fs->umask = old->umask; - read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); -+ PIN(old->pwd, old->pwdmnt, 0); -+ PIN(old->root, old->rootmnt, 1); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { -+ PIN(old->altroot, old->altrootmnt, 1); - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); - } else { -Index: linux-2.4.29/kernel/ksyms.c -=================================================================== ---- linux-2.4.29.orig/kernel/ksyms.c 2005-04-07 18:59:19.000000000 +0300 -+++ linux-2.4.29/kernel/ksyms.c 2005-04-07 19:14:06.000000000 +0300 -@@ -284,6 +284,7 @@ - EXPORT_SYMBOL(mark_page_accessed); - EXPORT_SYMBOL(vfs_readlink); - EXPORT_SYMBOL(vfs_follow_link); -+EXPORT_SYMBOL(vfs_follow_link_it); - EXPORT_SYMBOL(page_readlink); - EXPORT_SYMBOL(page_follow_link); - EXPORT_SYMBOL(page_symlink_inode_operations); diff --git a/lustre/kernel_patches/patches/vfs_intent-2.6.12.patch b/lustre/kernel_patches/patches/vfs_intent-2.6.12.patch deleted file mode 100644 index 2e700ef..0000000 --- a/lustre/kernel_patches/patches/vfs_intent-2.6.12.patch +++ /dev/null @@ -1,780 +0,0 @@ ---- linux-2.6.12.6.orig/fs/exec.c -+++ linux-2.6.12.6/fs/exec.c -@@ -122,9 +122,10 @@ - struct file * file; - struct nameidata nd; - int error; -+ intent_init(&nd.intent, IT_OPEN); - -- nd.intent.open.flags = FMODE_READ; -- error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); -+ nd.intent.it_flags = FMODE_READ|FMODE_EXEC; -+ error = __user_walk_it(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); - if (error) - goto out; - -@@ -136,7 +137,7 @@ - if (error) - goto exit; - -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &nd.intent); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; -@@ -492,8 +493,9 @@ - int err; - struct file *file; - -- nd.intent.open.flags = FMODE_READ; -- err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); -+ intent_init(&nd.intent, IT_OPEN); -+ nd.intent.it_flags = FMODE_READ|FMODE_EXEC; -+ err = path_lookup(name, LOOKUP_FOLLOW, &nd); - file = ERR_PTR(err); - - if (!err) { -@@ -506,7 +508,7 @@ - err = -EACCES; - file = ERR_PTR(err); - if (!err) { -- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); -+ file = dentry_open_it(nd.dentry, nd.mnt, O_RDONLY, &nd.intent); - if (!IS_ERR(file)) { - err = deny_write_access(file); - if (err) { ---- linux-2.6.12.6.orig/fs/namei.c -+++ linux-2.6.12.6/fs/namei.c -@@ -301,8 +301,19 @@ - return 0; - } - -+void intent_release(struct lookup_intent *it) -+{ -+ if (!it) -+ return; -+ if (it->it_magic != INTENT_MAGIC) -+ return; -+ if (it->it_op_release) -+ it->it_op_release(it); -+} -+ - void path_release(struct nameidata *nd) - { -+ intent_release(&nd->intent); - dput(nd->dentry); - mntput(nd->mnt); - } -@@ -392,8 +403,11 @@ - { - struct dentry * result; - struct inode *dir = parent->d_inode; -+ int counter = 0; - - down(&dir->i_sem); -+again: -+ counter++; - /* - * First re-do the cached lookup just in case it was created - * while we waited for the directory semaphore.. -@@ -427,13 +441,16 @@ - * Uhhuh! Nasty case: the cache was re-populated while - * we waited on the semaphore. Need to revalidate. - */ -- up(&dir->i_sem); - if (result->d_op && result->d_op->d_revalidate) { - if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) { - dput(result); -- result = ERR_PTR(-ENOENT); -+ if (counter > 10) -+ result = ERR_PTR(-ESTALE); -+ if (!IS_ERR(result)) -+ goto again; - } - } -+ up(&dir->i_sem); - return result; - } - -@@ -462,6 +479,7 @@ - { - int res = 0; - char *name; -+ - if (IS_ERR(link)) - goto fail; - -@@ -471,6 +489,7 @@ - /* weird __emul_prefix() stuff did it */ - goto out; - } -+ intent_reset_fs_part(&nd->intent); - res = link_path_walk(link, nd); - out: - if (nd->depth || res || nd->last_type!=LAST_NORM) -@@ -703,6 +722,33 @@ - return PTR_ERR(dentry); - } - -+static int revalidate_special(struct nameidata *nd) -+{ -+ struct dentry *dentry = nd->dentry; -+ int err, counter = 0; -+ -+ revalidate_again: -+ if (!dentry->d_op || !dentry->d_op->d_revalidate) -+ return 0; -+ if (!dentry->d_op->d_revalidate(dentry, nd)) { -+ struct dentry *new; -+ if ((err = permission(dentry->d_parent->d_inode, MAY_EXEC, nd))) -+ return err; -+ new = real_lookup(dentry->d_parent, &dentry->d_name, nd); -+ if (IS_ERR(new)) -+ return PTR_ERR(new); -+ d_invalidate(dentry); -+ dput(dentry); -+ nd->dentry = dentry = new; -+ counter++; -+ if (counter < 10) -+ goto revalidate_again; -+ printk("excessive revalidate_it loops\n"); -+ return -ESTALE; -+ } -+ return 0; -+} -+ - /* - * Name resolution. - * This is the basic name resolution function, turning a pathname into -@@ -800,7 +846,11 @@ - goto out_dput; - - if (inode->i_op->follow_link) { -+ int save_flags = nd->flags; -+ nd->flags |= LOOKUP_LINK_NOTLAST; - err = do_follow_link(&next, nd); -+ if (!(save_flags & LOOKUP_LINK_NOTLAST)) -+ nd->flags &= ~LOOKUP_LINK_NOTLAST; - if (err) - goto return_err; - err = -ENOENT; -@@ -839,6 +889,23 @@ - inode = nd->dentry->d_inode; - /* fallthrough */ - case 1: -+ nd->flags |= LOOKUP_LAST; -+ err = revalidate_special(nd); -+ nd->flags &= ~LOOKUP_LAST; -+ if (!nd->dentry->d_inode) -+ err = -ENOENT; -+ if (err) { -+ path_release(nd); -+ goto return_err; -+ } -+ if (lookup_flags & LOOKUP_DIRECTORY) { -+ err = -ENOTDIR; -+ if(!nd->dentry->d_inode->i_op || -+ !nd->dentry->d_inode->i_op->lookup) { -+ path_release(nd); -+ goto return_err; -+ } -+ } - goto return_reval; - } - if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { -@@ -846,7 +913,9 @@ - if (err < 0) - break; - } -+ nd->flags |= LOOKUP_LAST; - err = do_lookup(nd, &this, &next); -+ nd->flags &= ~LOOKUP_LAST; - if (err) - break; - inode = next.dentry->d_inode; -@@ -1097,7 +1166,7 @@ - } - - /* SMP-safe */ --struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+struct dentry * lookup_one_len_it(const char * name, struct dentry * base, int len, struct nameidata *nd) - { - unsigned long hash; - struct qstr this; -@@ -1117,11 +1186,16 @@ - } - this.hash = end_name_hash(hash); - -- return lookup_hash(&this, base); -+ return __lookup_hash(&this, base, nd); - access: - return ERR_PTR(-EACCES); - } - -+struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) -+{ -+ return lookup_one_len_it(name, base, len, NULL); -+} -+ - /* - * namei() - * -@@ -1133,7 +1207,7 @@ - * that namei follows links, while lnamei does not. - * SMP-safe - */ --int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) -+int fastcall __user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd) - { - char *tmp = getname(name); - int err = PTR_ERR(tmp); -@@ -1145,6 +1219,12 @@ - return err; - } - -+int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) -+{ -+ intent_init(&nd->intent, IT_LOOKUP); -+ return __user_walk_it(name, flags, nd); -+} -+ - /* - * It's inline, so penalty for filesystems that don't use sticky bit is - * minimal. -@@ -1426,8 +1506,8 @@ - acc_mode |= MAY_APPEND; - - /* Fill in the open() intent data */ -- nd->intent.open.flags = flag; -- nd->intent.open.create_mode = mode; -+ nd->intent.it_flags = flag; -+ nd->intent.it_create_mode = mode; - - /* - * The simplest case - just a plain lookup. -@@ -1442,6 +1522,7 @@ - /* - * Create - we need to know the parent. - */ -+ nd->intent.it_op |= IT_CREAT; - error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd); - if (error) - return error; -@@ -1458,7 +1539,9 @@ - dir = nd->dentry; - nd->flags &= ~LOOKUP_PARENT; - down(&dir->d_inode->i_sem); -+ nd->flags |= LOOKUP_LAST; - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); -+ nd->flags &= ~LOOKUP_LAST; - path.mnt = nd->mnt; - - do_last: -@@ -1564,7 +1647,9 @@ - } - dir = nd->dentry; - down(&dir->d_inode->i_sem); -+ nd->flags |= LOOKUP_LAST; - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); -+ nd->flags &= ~LOOKUP_LAST; - path.mnt = nd->mnt; - putname(nd->last.name); - goto do_last; ---- linux-2.6.12.6.orig/fs/namespace.c -+++ linux-2.6.12.6/fs/namespace.c -@@ -62,6 +62,7 @@ - INIT_LIST_HEAD(&mnt->mnt_mounts); - INIT_LIST_HEAD(&mnt->mnt_list); - INIT_LIST_HEAD(&mnt->mnt_fslink); -+ INIT_LIST_HEAD(&mnt->mnt_lustre_list); - if (name) { - int size = strlen(name)+1; - char *newname = kmalloc(size, GFP_KERNEL); -@@ -113,6 +114,7 @@ - - static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) - { -+ memset(old_nd, 0, sizeof(*old_nd)); - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; - mnt->mnt_parent = mnt; -@@ -176,6 +178,9 @@ - { - struct super_block *sb = mnt->mnt_sb; - dput(mnt->mnt_root); -+ spin_lock(&dcache_lock); -+ list_del(&mnt->mnt_lustre_list); -+ spin_unlock(&dcache_lock); - free_vfsmnt(mnt); - deactivate_super(sb); - } -@@ -402,6 +407,8 @@ - */ - - lock_kernel(); -+ if (sb->s_op->umount_lustre) -+ sb->s_op->umount_lustre(sb); - if( (flags&MNT_FORCE) && sb->s_op->umount_begin) - sb->s_op->umount_begin(sb); - unlock_kernel(); -@@ -627,6 +634,7 @@ - return err; - if (!old_name || !*old_name) - return -EINVAL; -+ intent_init(&old_nd.intent, IT_LOOKUP); - err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd); - if (err) - return err; -@@ -701,6 +709,7 @@ - return -EPERM; - if (!old_name || !*old_name) - return -EINVAL; -+ intent_init(&old_nd.intent, IT_LOOKUP); - err = path_lookup(old_name, LOOKUP_FOLLOW, &old_nd); - if (err) - return err; -@@ -1012,6 +1021,7 @@ - int retval = 0; - int mnt_flags = 0; - -+ intent_init(&nd.intent, IT_LOOKUP); - /* Discard magic */ - if ((flags & MS_MGC_MSK) == MS_MGC_VAL) - flags &= ~MS_MGC_MSK; ---- linux-2.6.12.6.orig/fs/open.c -+++ linux-2.6.12.6/fs/open.c -@@ -215,12 +215,12 @@ - struct nameidata nd; - struct inode * inode; - int error; -- -+ intent_init(&nd.intent, IT_GETATTR); - error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ - goto out; - -- error = user_path_walk(path, &nd); -+ error = user_path_walk_it(path, &nd); - if (error) - goto out; - inode = nd.dentry->d_inode; -@@ -474,6 +474,7 @@ - int old_fsuid, old_fsgid; - kernel_cap_t old_cap; - int res; -+ intent_init(&nd.intent, IT_GETATTR); - - if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ - return -EINVAL; -@@ -498,13 +499,14 @@ - else - current->cap_effective = current->cap_permitted; - -- res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); -+ res = __user_walk_it(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); - if (!res) { - res = permission(nd.dentry->d_inode, mode, &nd); - /* SuS v2 requires we report a read only fs too */ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ - path_release(&nd); - } - -@@ -519,8 +521,9 @@ - { - struct nameidata nd; - int error; -+ intent_init(&nd.intent, IT_GETATTR); - -- error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); -+ error = __user_walk_it(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); - if (error) - goto out; - -@@ -570,8 +573,9 @@ - { - struct nameidata nd; - int error; -+ intent_init(&nd.intent, IT_GETATTR); - -- error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); -+ error = __user_walk_it(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); - if (error) - goto out; - -@@ -750,27 +754,8 @@ - * for the internal routines (ie open_namei()/follow_link() etc). 00 is - * used by symlinks. - */ --struct file *filp_open(const char * filename, int flags, int mode) --{ -- int namei_flags, error; -- struct nameidata nd; -- -- namei_flags = flags; -- if ((namei_flags+1) & O_ACCMODE) -- namei_flags++; -- if (namei_flags & O_TRUNC) -- namei_flags |= 2; -- -- error = open_namei(filename, namei_flags, mode, &nd); -- if (!error) -- return dentry_open(nd.dentry, nd.mnt, flags); -- -- return ERR_PTR(error); --} -- --EXPORT_SYMBOL(filp_open); -- --struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt, int flags, -+ struct lookup_intent *it) - { - struct file * f; - struct inode *inode; -@@ -782,6 +767,7 @@ - goto cleanup_dentry; - f->f_flags = flags; - f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; -+ f->f_it = it; - inode = dentry->d_inode; - if (f->f_mode & FMODE_WRITE) { - error = get_write_access(inode); -@@ -800,6 +786,7 @@ - error = f->f_op->open(inode,f); - if (error) - goto cleanup_all; -+ intent_release(it); - } - f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - -@@ -825,6 +812,7 @@ - cleanup_file: - put_filp(f); - cleanup_dentry: -+ intent_release(it); - dput(dentry); - mntput(mnt); - return ERR_PTR(error); -@@ -832,6 +820,36 @@ - - EXPORT_SYMBOL(dentry_open); - -+struct file *filp_open(const char * filename, int flags, int mode) -+{ -+ int namei_flags, error; -+ struct file * temp_filp; -+ struct nameidata nd; -+ intent_init(&nd.intent, IT_OPEN); -+ -+ namei_flags = flags; -+ if ((namei_flags+1) & O_ACCMODE) -+ namei_flags++; -+ if (namei_flags & O_TRUNC) -+ namei_flags |= 2; -+ -+ error = open_namei(filename, namei_flags, mode, &nd); -+ if (!error) { -+ temp_filp = dentry_open_it(nd.dentry, nd.mnt, flags, &nd.intent); -+ return temp_filp; -+ } -+ return ERR_PTR(error); -+} -+ -+ -+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) -+{ -+ struct lookup_intent it; -+ intent_init(&it, IT_LOOKUP); -+ -+ return dentry_open_it(dentry, mnt, flags, &it); -+} -+ - /* - * Find an empty file descriptor entry, and mark it busy. - */ ---- linux-2.6.12.6.orig/fs/stat.c -+++ linux-2.6.12.6/fs/stat.c -@@ -38,7 +38,7 @@ - - EXPORT_SYMBOL(generic_fillattr); - --int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -+int vfs_getattr_it(struct vfsmount *mnt, struct dentry *dentry, struct lookup_intent *it, struct kstat *stat) - { - struct inode *inode = dentry->d_inode; - int retval; -@@ -47,6 +47,8 @@ - if (retval) - return retval; - -+ if (inode->i_op->getattr_it) -+ return inode->i_op->getattr_it(mnt, dentry, it, stat); - if (inode->i_op->getattr) - return inode->i_op->getattr(mnt, dentry, stat); - -@@ -63,14 +65,20 @@ - - EXPORT_SYMBOL(vfs_getattr); - -+int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -+{ -+ return vfs_getattr_it(mnt, dentry, NULL, stat); -+} -+ - int vfs_stat(char __user *name, struct kstat *stat) - { - struct nameidata nd; - int error; -+ intent_init(&nd.intent, IT_GETATTR); - -- error = user_path_walk(name, &nd); -+ error = user_path_walk_it(name, &nd); - if (!error) { -- error = vfs_getattr(nd.mnt, nd.dentry, stat); -+ error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat); - path_release(&nd); - } - return error; -@@ -82,10 +90,11 @@ - { - struct nameidata nd; - int error; -+ intent_init(&nd.intent, IT_GETATTR); - -- error = user_path_walk_link(name, &nd); -+ error = user_path_walk_link_it(name, &nd); - if (!error) { -- error = vfs_getattr(nd.mnt, nd.dentry, stat); -+ error = vfs_getattr_it(nd.mnt, nd.dentry, &nd.intent, stat); - path_release(&nd); - } - return error; -@@ -97,9 +106,12 @@ - { - struct file *f = fget(fd); - int error = -EBADF; -+ struct nameidata nd; -+ intent_init(&nd.intent, IT_GETATTR); - - if (f) { -- error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat); -+ error = vfs_getattr_it(f->f_vfsmnt, f->f_dentry, &nd.intent, stat); -+ intent_release(&nd.intent); - fput(f); - } - return error; ---- linux-2.6.12.6.orig/fs/inode.c -+++ linux-2.6.12.6/fs/inode.c -@@ -230,6 +230,7 @@ - inodes_stat.nr_unused--; - } - -+EXPORT_SYMBOL(__iget); - /** - * clear_inode - clear an inode - * @inode: inode to clear ---- linux-2.6.12.6.orig/include/linux/dcache.h -+++ linux-2.6.12.6/include/linux/dcache.h -@@ -4,6 +4,7 @@ - #ifdef __KERNEL__ - - #include <asm/atomic.h> -+#include <linux/string.h> - #include <linux/list.h> - #include <linux/spinlock.h> - #include <linux/cache.h> -@@ -37,6 +38,8 @@ - const unsigned char *name; - }; - -+#include <linux/namei.h> -+ - struct dentry_stat_t { - int nr_dentry; - int nr_unused; ---- linux-2.6.12.6.orig/include/linux/fs.h -+++ linux-2.6.12.6/include/linux/fs.h -@@ -58,6 +58,7 @@ - - #define FMODE_READ 1 - #define FMODE_WRITE 2 -+#define FMODE_EXEC 4 - - /* Internal kernel extensions */ - #define FMODE_LSEEK 4 -@@ -260,6 +261,8 @@ - #define ATTR_ATTR_FLAG 1024 - #define ATTR_KILL_SUID 2048 - #define ATTR_KILL_SGID 4096 -+#define ATTR_RAW 8192 /* file system, not vfs will massage attrs */ -+#define ATTR_FROM_OPEN 16384 /* called from open path, ie O_TRUNC */ - - /* - * This is the Inode Attributes structure, used for notify_change(). It -@@ -463,6 +466,7 @@ - struct block_device *i_bdev; - struct cdev *i_cdev; - int i_cindex; -+ void *i_filterdata; - - __u32 i_generation; - -@@ -600,6 +604,7 @@ - spinlock_t f_ep_lock; - #endif /* #ifdef CONFIG_EPOLL */ - struct address_space *f_mapping; -+ struct lookup_intent *f_it; - }; - extern spinlock_t files_lock; - #define file_list_lock() spin_lock(&files_lock); -@@ -968,7 +973,9 @@ - void (*truncate) (struct inode *); - int (*permission) (struct inode *, int, struct nameidata *); - int (*setattr) (struct dentry *, struct iattr *); -+ int (*setattr_raw) (struct inode *, struct iattr *); - int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); -+ int (*getattr_it) (struct vfsmount *, struct dentry *, struct lookup_intent *, struct kstat *); - int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); - ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); - ssize_t (*listxattr) (struct dentry *, char *, size_t); -@@ -1008,6 +1015,7 @@ - int (*remount_fs) (struct super_block *, int *, char *); - void (*clear_inode) (struct inode *); - void (*umount_begin) (struct super_block *); -+ void (*umount_lustre) (struct super_block *); - - int (*show_options)(struct seq_file *, struct vfsmount *); - -@@ -1210,6 +1218,7 @@ - extern struct vfsmount *kern_mount(struct file_system_type *); - extern int may_umount_tree(struct vfsmount *); - extern int may_umount(struct vfsmount *); -+struct vfsmount *do_kern_mount(const char *type, int flags, const char *name, void *data); - extern long do_mount(char *, char *, char *, unsigned long, void *); - - extern int vfs_statfs(struct super_block *, struct kstatfs *); -@@ -1262,6 +1271,7 @@ - extern int do_truncate(struct dentry *, loff_t start); - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -+extern struct file * dentry_open_it(struct dentry *, struct vfsmount *, int, struct lookup_intent *); - extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char __user *); - ---- linux-2.6.12.6.orig/include/linux/namei.h -+++ linux-2.6.12.6/include/linux/namei.h -@@ -2,14 +2,55 @@ - #define _LINUX_NAMEI_H - - #include <linux/linkage.h> -+#include <linux/string.h> - - struct vfsmount; -+struct nameidata; - --struct open_intent { -- int flags; -- int create_mode; -+/* intent opcodes */ -+#define IT_OPEN (1) -+#define IT_CREAT (1<<1) -+#define IT_READDIR (1<<2) -+#define IT_GETATTR (1<<3) -+#define IT_LOOKUP (1<<4) -+#define IT_UNLINK (1<<5) -+#define IT_TRUNC (1<<6) -+#define IT_GETXATTR (1<<7) -+ -+struct lustre_intent_data { -+ int it_disposition; -+ int it_status; -+ __u64 it_lock_handle; -+ void *it_data; -+ int it_lock_mode; - }; - -+#define INTENT_MAGIC 0x19620323 -+struct lookup_intent { -+ int it_magic; -+ void (*it_op_release)(struct lookup_intent *); -+ int it_op; -+ int it_flags; -+ int it_create_mode; -+ union { -+ struct lustre_intent_data lustre; -+ } d; -+}; -+ -+static inline void intent_reset_fs_part(struct lookup_intent *it) -+{ -+ memset(&it->d, 0, sizeof(it->d)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op_release = NULL; -+} -+ -+static inline void intent_init(struct lookup_intent *it, int op) -+{ -+ memset(it, 0, sizeof(*it)); -+ it->it_magic = INTENT_MAGIC; -+ it->it_op = op; -+} -+ - enum { MAX_NESTED_LINKS = 5 }; - - struct nameidata { -@@ -21,10 +62,7 @@ - unsigned depth; - char *saved_names[MAX_NESTED_LINKS + 1]; - -- /* Intent data */ -- union { -- struct open_intent open; -- } intent; -+ struct lookup_intent intent; - }; - - /* -@@ -47,6 +85,8 @@ - #define LOOKUP_PARENT 16 - #define LOOKUP_NOALT 32 - #define LOOKUP_REVAL 64 -+#define LOOKUP_LAST (0x1000) -+#define LOOKUP_LINK_NOTLAST (0x2000) - /* - * Intent data - */ -@@ -55,6 +95,12 @@ - #define LOOKUP_ACCESS (0x0400) - - extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *)); -+extern int FASTCALL(__user_walk_it(const char __user *name, unsigned flags, struct nameidata *nd)); -+#define user_path_walk_it(name,nd) \ -+ __user_walk_it(name, LOOKUP_FOLLOW, nd) -+#define user_path_walk_link_it(name,nd) \ -+ __user_walk_it(name, 0, nd) -+extern void intent_release(struct lookup_intent *); - #define user_path_walk(name,nd) \ - __user_walk(name, LOOKUP_FOLLOW, nd) - #define user_path_walk_link(name,nd) \ -@@ -67,7 +113,6 @@ - - extern struct dentry * lookup_one_len(const char *, struct dentry *, int); - extern struct dentry * lookup_hash(struct qstr *, struct dentry *); -- - extern int follow_down(struct vfsmount **, struct dentry **); - extern int follow_up(struct vfsmount **, struct dentry **); - ---- linux-2.6.12.6.orig/include/linux/mount.h -+++ linux-2.6.12.6/include/linux/mount.h -@@ -36,6 +36,8 @@ - struct list_head mnt_list; - struct list_head mnt_fslink; /* link in fs-specific expiry list */ - struct namespace *mnt_namespace; /* containing namespace */ -+ struct list_head mnt_lustre_list; /* GNS mount list */ -+ unsigned long mnt_last_used; /* for GNS auto-umount (jiffies) */ - }; - - static inline struct vfsmount *mntget(struct vfsmount *mnt) diff --git a/lustre/kernel_patches/patches/vfs_nointent-2.6.12.patch b/lustre/kernel_patches/patches/vfs_nointent-2.6.12.patch deleted file mode 100644 index ce239c9..0000000 --- a/lustre/kernel_patches/patches/vfs_nointent-2.6.12.patch +++ /dev/null @@ -1,490 +0,0 @@ -Index: linux-2.6.12.2/fs/namei.c -=================================================================== ---- linux-2.6.12.2.orig/fs/namei.c 2005-07-23 12:25:12.241868120 +0200 -+++ linux-2.6.12.2/fs/namei.c 2005-07-23 12:25:14.440533872 +0200 -@@ -1466,7 +1466,7 @@ - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, 1); - } - put_write_access(inode); - if (error) -@@ -1719,6 +1719,7 @@ - char * tmp; - struct dentry * dentry; - struct nameidata nd; -+ intent_init(&nd.intent, IT_LOOKUP); - - if (S_ISDIR(mode)) - return -EPERM; -@@ -1729,6 +1730,15 @@ - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -+ -+ if (nd.dentry->d_inode->i_op->mknod_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mknod_raw(&nd, mode, dev); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } -+ - dentry = lookup_create(&nd, 0); - error = PTR_ERR(dentry); - -@@ -1755,6 +1765,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1796,10 +1807,18 @@ - if (!IS_ERR(tmp)) { - struct dentry *dentry; - struct nameidata nd; -+ intent_init(&nd.intent, IT_LOOKUP); - - error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) - goto out; -+ if (nd.dentry->d_inode->i_op->mkdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->mkdir_raw(&nd, mode); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } - dentry = lookup_create(&nd, 1); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { -@@ -1809,6 +1828,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(tmp); -@@ -1885,6 +1905,7 @@ - char * name; - struct dentry *dentry; - struct nameidata nd; -+ intent_init(&nd.intent, IT_LOOKUP); - - name = getname(pathname); - if(IS_ERR(name)) -@@ -1905,6 +1926,16 @@ - error = -EBUSY; - goto exit1; - } -+ -+ if (nd.dentry->d_inode->i_op->rmdir_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ error = op->rmdir_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } -+ - down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); - error = PTR_ERR(dentry); -@@ -1963,6 +1994,7 @@ - struct dentry *dentry; - struct nameidata nd; - struct inode *inode = NULL; -+ intent_init(&nd.intent, IT_LOOKUP); - - name = getname(pathname); - if(IS_ERR(name)) -@@ -1974,6 +2006,13 @@ - error = -EISDIR; - if (nd.last_type != LAST_NORM) - goto exit1; -+ if (nd.dentry->d_inode->i_op->unlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->unlink_raw(&nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit1; -+ } - down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); - error = PTR_ERR(dentry); -@@ -2040,10 +2079,18 @@ - if (!IS_ERR(to)) { - struct dentry *dentry; - struct nameidata nd; -+ intent_init(&nd.intent, IT_LOOKUP); - - error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) - goto out; -+ if (nd.dentry->d_inode->i_op->symlink_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->symlink_raw(&nd, from); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out2; -+ } - dentry = lookup_create(&nd, 0); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { -@@ -2051,6 +2098,7 @@ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -+out2: - path_release(&nd); - out: - putname(to); -@@ -2114,6 +2162,8 @@ - struct nameidata nd, old_nd; - int error; - char * to; -+ intent_init(&nd.intent, IT_LOOKUP); -+ intent_init(&old_nd.intent, IT_LOOKUP); - - to = getname(newname); - if (IS_ERR(to)) -@@ -2128,6 +2178,13 @@ - error = -EXDEV; - if (old_nd.mnt != nd.mnt) - goto out_release; -+ if (nd.dentry->d_inode->i_op->link_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ error = op->link_raw(&old_nd, &nd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out_release; -+ } - new_dentry = lookup_create(&nd, 0); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { -@@ -2300,6 +2357,8 @@ - struct dentry * old_dentry, *new_dentry; - struct dentry * trap; - struct nameidata oldnd, newnd; -+ intent_init(&oldnd.intent, IT_LOOKUP); -+ intent_init(&newnd.intent, IT_LOOKUP); - - error = path_lookup(oldname, LOOKUP_PARENT, &oldnd); - if (error) -@@ -2322,6 +2381,13 @@ - if (newnd.last_type != LAST_NORM) - goto exit2; - -+ if (old_dir->d_inode->i_op->rename_raw) { -+ error = old_dir->d_inode->i_op->rename_raw(&oldnd, &newnd); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto exit2; -+ } -+ - trap = lock_rename(new_dir, old_dir); - - old_dentry = lookup_hash(&oldnd.last, old_dir); -@@ -2353,8 +2419,7 @@ - if (new_dentry == trap) - goto exit5; - -- error = vfs_rename(old_dir->d_inode, old_dentry, -- new_dir->d_inode, new_dentry); -+ error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); - exit5: - dput(new_dentry); - exit4: -Index: linux-2.6.12.2/fs/open.c -=================================================================== ---- linux-2.6.12.2.orig/fs/open.c 2005-07-23 12:25:12.248867056 +0200 -+++ linux-2.6.12.2/fs/open.c 2005-07-23 12:28:13.221355056 +0200 -@@ -192,9 +192,10 @@ - return error; - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, int called_from_open) - { - int err; -+ struct inode_operations *op = dentry->d_inode->i_op; - struct iattr newattrs; - - /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */ -@@ -205,7 +206,16 @@ - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - - down(&dentry->d_inode->i_sem); -- err = notify_change(dentry, &newattrs); -+ if (called_from_open) -+ newattrs.ia_valid |= ATTR_FROM_OPEN; -+ if (op->setattr_raw) { -+ newattrs.ia_valid |= ATTR_RAW; -+ newattrs.ia_ctime = CURRENT_TIME; -+ down_write(&dentry->d_inode->i_alloc_sem); -+ err = op->setattr_raw(dentry->d_inode, &newattrs); -+ up_write(&dentry->d_inode->i_alloc_sem); -+ } else -+ err = notify_change(dentry, &newattrs); - up(&dentry->d_inode->i_sem); - return err; - } -@@ -260,7 +270,7 @@ - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ error = do_truncate(nd.dentry, length, 0); - } - put_write_access(inode); - -@@ -312,7 +322,7 @@ - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, 0); - out_putf: - fput(file); - out: -@@ -391,9 +401,19 @@ - (error = permission(inode,MAY_WRITE,&nd)) != 0) - goto dput_and_out; - } -- down(&inode->i_sem); -- error = notify_change(nd.dentry, &newattrs); -- up(&inode->i_sem); -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } else { -+ down(&inode->i_sem); -+ error = notify_change(nd.dentry, &newattrs); -+ up(&inode->i_sem); -+ } - dput_and_out: - path_release(&nd); - out: -@@ -444,9 +464,19 @@ - (error = permission(inode,MAY_WRITE,&nd)) != 0) - goto dput_and_out; - } -- down(&inode->i_sem); -- error = notify_change(nd.dentry, &newattrs); -- up(&inode->i_sem); -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = nd.dentry->d_inode->i_op; -+ -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto dput_and_out; -+ } else { -+ down(&inode->i_sem); -+ error = notify_change(nd.dentry, &newattrs); -+ up(&inode->i_sem); -+ } - dput_and_out: - path_release(&nd); - out: -@@ -596,36 +626,52 @@ - return error; - } - --asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+int chmod_common(struct dentry *dentry, mode_t mode) - { -- struct inode * inode; -- struct dentry * dentry; -- struct file * file; -- int err = -EBADF; -+ struct inode * inode = dentry->d_inode; - struct iattr newattrs; -+ int error = -EROFS; - -- file = fget(fd); -- if (!file) -+ if (IS_RDONLY(inode)) - goto out; -+ -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_mode = mode; -+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ goto out; -+ } - -- dentry = file->f_dentry; -- inode = dentry->d_inode; -- -- err = -EROFS; -- if (IS_RDONLY(inode)) -- goto out_putf; -- err = -EPERM; -+ error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto out_putf; -+ goto out; -+ - down(&inode->i_sem); - if (mode == (mode_t) -1) - mode = inode->i_mode; - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- err = notify_change(dentry, &newattrs); -+ error = notify_change(dentry, &newattrs); - up(&inode->i_sem); -+out: -+ return error; -+} - --out_putf: -+asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) -+{ -+ struct file * file; -+ int err = -EBADF; -+ -+ file = fget(fd); -+ if (!file) -+ goto out; -+ -+ err = chmod_common(file->f_dentry, mode); - fput(file); - out: - return err; -@@ -634,32 +680,13 @@ - asmlinkage long sys_chmod(const char __user * filename, mode_t mode) - { - struct nameidata nd; -- struct inode * inode; - int error; -- struct iattr newattrs; - - error = user_path_walk(filename, &nd); - if (error) - goto out; -- inode = nd.dentry->d_inode; -- -- error = -EROFS; -- if (IS_RDONLY(inode)) -- goto dput_and_out; -- -- error = -EPERM; -- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) -- goto dput_and_out; -- -- down(&inode->i_sem); -- if (mode == (mode_t) -1) -- mode = inode->i_mode; -- newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); -- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; -- error = notify_change(nd.dentry, &newattrs); -- up(&inode->i_sem); - --dput_and_out: -+ error = chmod_common(nd.dentry, mode); - path_release(&nd); - out: - return error; -@@ -680,6 +707,18 @@ - if (IS_RDONLY(inode)) - goto out; - error = -EPERM; -+ if (inode->i_op->setattr_raw) { -+ struct inode_operations *op = dentry->d_inode->i_op; -+ -+ newattrs.ia_uid = user; -+ newattrs.ia_gid = group; -+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; -+ newattrs.ia_valid |= ATTR_RAW; -+ error = op->setattr_raw(inode, &newattrs); -+ /* the file system wants to use normal vfs path now */ -+ if (error != -EOPNOTSUPP) -+ return error; -+ } - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; - newattrs.ia_valid = ATTR_CTIME; -@@ -693,6 +732,7 @@ - } - if (!S_ISDIR(inode->i_mode)) - newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; -+ - down(&inode->i_sem); - error = notify_change(dentry, &newattrs); - up(&inode->i_sem); -Index: linux-2.6.12.2/fs/exec.c -=================================================================== ---- linux-2.6.12.2.orig/fs/exec.c 2005-07-23 12:25:12.229869944 +0200 -+++ linux-2.6.12.2/fs/exec.c 2005-07-23 12:25:14.442533568 +0200 -@@ -1488,7 +1488,7 @@ - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, 0) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -Index: linux-2.6.12.2/include/linux/fs.h -=================================================================== ---- linux-2.6.12.2.orig/include/linux/fs.h 2005-07-23 12:25:12.279862344 +0200 -+++ linux-2.6.12.2/include/linux/fs.h 2005-07-23 12:25:14.443533416 +0200 -@@ -960,13 +960,20 @@ - int (*create) (struct inode *,struct dentry *,int, struct nameidata *); - struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); - int (*link) (struct dentry *,struct inode *,struct dentry *); -+ int (*link_raw) (struct nameidata *,struct nameidata *); - int (*unlink) (struct inode *,struct dentry *); -+ int (*unlink_raw) (struct nameidata *); - int (*symlink) (struct inode *,struct dentry *,const char *); -+ int (*symlink_raw) (struct nameidata *,const char *); - int (*mkdir) (struct inode *,struct dentry *,int); -+ int (*mkdir_raw) (struct nameidata *,int); - int (*rmdir) (struct inode *,struct dentry *); -+ int (*rmdir_raw) (struct nameidata *); - int (*mknod) (struct inode *,struct dentry *,int,dev_t); -+ int (*mknod_raw) (struct nameidata *,int,dev_t); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); -+ int (*rename_raw) (struct nameidata *, struct nameidata *); - int (*readlink) (struct dentry *, char __user *,int); - int (*follow_link) (struct dentry *, struct nameidata *); - void (*put_link) (struct dentry *, struct nameidata *); -@@ -1268,7 +1275,7 @@ - - /* fs/open.c */ - --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, int called_from_open); - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); - extern struct file * dentry_open_it(struct dentry *, struct vfsmount *, int, struct lookup_intent *); -Index: linux-2.6.12.2/net/unix/af_unix.c -=================================================================== ---- linux-2.6.12.2.orig/net/unix/af_unix.c 2005-06-30 01:00:53.000000000 +0200 -+++ linux-2.6.12.2/net/unix/af_unix.c 2005-07-23 12:25:14.445533112 +0200 -@@ -673,6 +673,7 @@ - int err = 0; - - if (sunname->sun_path[0]) { -+ intent_init(&nd.intent, IT_LOOKUP); - err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); - if (err) - goto fail; diff --git a/lustre/kernel_patches/series/2.6.12-vanilla.series b/lustre/kernel_patches/series/2.6.12-vanilla.series deleted file mode 100644 index edae2e8..0000000 --- a/lustre/kernel_patches/series/2.6.12-vanilla.series +++ /dev/null @@ -1,17 +0,0 @@ -lustre_version.patch -vfs_intent-2.6.12.patch -vfs_races-2.6.12.patch -jbd-2.6.10-jcberr.patch -iopen-misc-2.6.12.patch -export-truncate-2.6-suse.patch -export_symbols-2.6.12.patch -dev_read_only-2.6-suse.patch -export-2.6-suse.patch -lookup_bdev_init_intent.patch -8kstack-2.6.12.patch -remove-suid-2.6-suse.patch -export-show_task-2.6-vanilla.patch -sd_iostats-2.6-rhel4.patch -blkdev_tunables-2.6-suse.patch -fsprivate-2.6.patch -export_symbol_numa.patch diff --git a/lustre/kernel_patches/series/hp-pnnl-2.4.20 b/lustre/kernel_patches/series/hp-pnnl-2.4.20 deleted file mode 100644 index 11a7c93..0000000 --- a/lustre/kernel_patches/series/hp-pnnl-2.4.20 +++ /dev/null @@ -1,49 +0,0 @@ -configurable-x86-stack-2.4.20.patch -dev_read_only_2.4.20-rh.patch -exports_2.4.20-rh-hp.patch -lustre_version.patch -vfs_intent-2.4.20-hp.patch -invalidate_show-2.4.20-hp.patch -export-truncate.patch -iod-stock-24-exports_hp.patch -ext-2.4-patch-1.patch -ext-2.4-patch-2.patch -ext-2.4-patch-3.patch -ext-2.4-patch-4.patch -linux-2.4.20-xattr-0.8.54-hp.patch -ext3-2.4.20-fixes.patch -ext3-2.4-ino_t.patch -ext3-largefile.patch -ext3-truncate_blocks.patch -ext3-use-after-free.patch -ext3-orphan_lock.patch -ext3-delete_thread-2.4.20-hp.patch -ext3-noread-2.4.20.patch -extN-wantedi.patch -ext3-san-2.4.20.patch -ext3-map_inode_page.patch -ext3-error-export.patch -iopen-2.4.20.patch -jbd-dont-account-blocks-twice.patch -jbd-commit-tricks.patch -add_page_private.patch -socket-exports-vanilla.patch -removepage-2.4.20.patch -jbd-ctx_switch.patch -jbd-flushtime.patch -jbd-get_write_access.patch -nfs_export_kernel-2.4.20-hp.patch -ext3-raw-lookup.patch -ext3-ea-in-inode-2.4.20.patch -listman-2.4.20.patch -ext3-trusted_ea-2.4.20.patch -ext3-xattr-ptr-arith-fix.patch -procfs-ndynamic-2.4.patch -ext3-truncate-buffer-head.patch -inode-max-readahead-2.4.24.patch -dcache_refcount_debug.patch -ext3-extents-2.4.24.patch -ext3-extents-asyncdel-2.4.24.patch -ext3-nlinks-2.4.20-hp_pnnl.patch -export-zap-page-range.patch -ext3-sector_t-overflow-2.4.patch diff --git a/lustre/kernel_patches/series/rhel-2.4.21 b/lustre/kernel_patches/series/rhel-2.4.21 deleted file mode 100644 index 981707d..0000000 --- a/lustre/kernel_patches/series/rhel-2.4.21 +++ /dev/null @@ -1,54 +0,0 @@ -configurable-x86-stack-2.4.21-chaos.patch -dev_read_only_2.4.21-chaos.patch -exports_2.4.19-suse.patch -lustre_version.patch -vfs_intent-2.4.21-rhel.patch -invalidate_show-2.4.20-rh.patch -iod-rmap-exports-2.4.21-chaos.patch -export-truncate.patch -ext3-htree-2.4.21-rhel.patch -linux-2.4.21-xattr-0.8.54-chaos.patch -ext3-ino_sb_macro-2.4.21-chaos.patch -ext3-orphan_lock-2.4.22-rh.patch -ext3-delete_thread-2.4.21-chaos.patch -extN-misc-fixup.patch -ext3-noread-2.4.21-chaos.patch -extN-wantedi-2.4.21-chaos.patch -ext3-san-2.4.20.patch -extN-2.4.18-ino_sb_fixup.patch -ext3-map_inode_page_2.4.18.patch -ext3-error-export.patch -iopen-2.4.21-chaos.patch -jbd-dont-account-blocks-twice.patch -jbd-commit-tricks-rhel3.patch -ext3-o_direct-2.4.21-chaos.patch -ext3-no-write-super-chaos.patch -add_page_private.patch -ext3-raw-lookup.patch -nfs_export_kernel-2.4.21-chaos.patch -ext3-ea-in-inode-2.4.21-chaos.patch -listman-2.4.21-chaos.patch -pagecache-lock-2.4.21-chaos.patch -ext3-truncate-buffer-head.patch -inode-max-readahead-2.4.24.patch -dcache_refcount_debug.patch -ext3-extents-2.4.21-chaos.patch -ext3-extents-asyncdel-2.4.21-chaos.patch -blkdev_tunables-2.4.21-chaos.patch -ext3-nlinks-2.4.21-chaos.patch -sd_iostats-2.4.21-chaos.patch -llnl-frame-pointer-walk-2.4.21-rhel.patch -llnl-frame-pointer-walk-fix-2.4.21-rhel.patch -export-show_task-2.4-rhel.patch -compile-fixes-2.4.21-rhel.patch -grab_cache_page_nowait_gfp-rh-2.4.patch -remove-suid-2.4-rhel.patch -qsnet-rhel-2.4.patch -nfs_statfs-toomanyfiles-rhel-2.4.patch -statfs64-cast-unsigned-2.4-rhel.patch -fsprivate-2.4.patch -nfsd_iallocsem.patch -linux-2.4.24-jbd-handle-EIO-rhel3.patch -ext3-lookup-dotdot-2.4.20.patch -ext3-sector_t-overflow-2.4.patch -nfs_export_kernel-getattr_on_lookup-2.4.patch diff --git a/lustre/kernel_patches/series/suse-2.4.21-cray b/lustre/kernel_patches/series/suse-2.4.21-cray deleted file mode 100644 index b3b06ff..0000000 --- a/lustre/kernel_patches/series/suse-2.4.21-cray +++ /dev/null @@ -1,43 +0,0 @@ -configurable-x86-stack-2.4.21-suse2.patch -configurable-x86_64-2.4.21.patch -dev_read_only_2.4.20-rh.patch -exports_2.4.20-rh-hp.patch -lustre_version.patch -vfs_intent-2.4.21-suse2.patch -invalidate_show.patch -export-truncate.patch -iod-stock-24-exports_hp.patch -ext3-htree-2.4.21-chaos.patch -linux-2.4.21-xattr-0.8.54-suse2.patch -ext3-orphan_lock-2.4.22-rh.patch -ext3-noread-2.4.21-suse2.patch -ext3-delete_thread-2.4.21-chaos.patch -extN-wantedi-2.4.21-suse2.patch -ext3-san-2.4.20.patch -ext3-map_inode_page-2.4.21-suse2.patch -ext3-error-export.patch -iopen-2.4.21-chaos.patch -jbd-dont-account-blocks-twice.patch -jbd-commit-tricks.patch -ext3-no-write-super-chaos.patch -add_page_private.patch -nfs_export_kernel-2.4.21-suse2.patch -ext3-raw-lookup.patch -ext3-ea-in-inode-2.4.21-suse2.patch -listman-2.4.20.patch -ext3-xattr-ptr-arith-fix.patch -procfs-ndynamic-2.4.21-suse2.patch -ext3-truncate-buffer-head.patch -loop-sync-2.4.21-suse.patch -inode-max-readahead-2.4.24.patch -ext3-extents-2.4.21-suse2.patch -ext3-extents-asyncdel-2.4.24.patch -ext3-nlinks-2.4.21-chaos.patch -export-show_task-2.4-cray.patch -grab_cache_page_nowait_gfp-2.4.21-suse2.patch -remove-suid-2.4-rhel.patch -fsprivate-2.4-suse.patch -nfsd_iallocsem.patch -linux-2.4.24-jbd-handle-EIO.patch -ext3-ialloc-2.4.21-suse2.patch -ext3-sector_t-overflow-2.4.patch diff --git a/lustre/kernel_patches/series/vanilla-2.4.24 b/lustre/kernel_patches/series/vanilla-2.4.24 deleted file mode 100644 index 02b1603..0000000 --- a/lustre/kernel_patches/series/vanilla-2.4.24 +++ /dev/null @@ -1,50 +0,0 @@ -uml-patch-2.4.24-1.patch -uml-2.4.20-do_mmap_pgoff-fix.patch -uml-export-end_iomem.patch -configurable-x86-stack-2.4.20.patch -configurable-x86_64-2.4.21.patch -dev_read_only_2.4.20-rh.patch -exports_2.4.20-rh-hp.patch -lustre_version.patch -vfs_intent-2.4.20-vanilla.patch -invalidate_show.patch -export-truncate.patch -iod-stock-exports-2.4.22.patch -ext3-htree-2.4.22-rh.patch -linux-2.4.24-xattr-0.8.54.patch -ext3-orphan_lock-2.4.22-rh.patch -ext3-noread-2.4.20.patch -ext3-delete_thread-2.4.24.patch -extN-wantedi.patch -ext3-san-2.4.20.patch -ext3-map_inode_page.patch -ext3-error-export.patch -iopen-2.4.20.patch -jbd-dont-account-blocks-twice.patch -jbd-commit-tricks.patch -ext3-no-write-super-chaos.patch -add_page_private.patch -nfs_export_kernel-2.4.22.patch -ext3-raw-lookup.patch -ext3-ea-in-inode-2.4.22-rh.patch -listman-2.4.20.patch -ext3-trusted_ea-2.4.20.patch -ext3-xattr-ptr-arith-fix.patch -3.5G-address-space-2.4.22-vanilla.patch -procfs-ndynamic-2.4.patch -ext3-truncate-buffer-head.patch -inode-max-readahead-2.4.24.patch -ext3-extents-2.4.24.patch -ext3-extents-asyncdel-2.4.24.patch -export_num_siblings.patch -ext3-nlinks-2.4.24.patch -export-show_task-2.4-vanilla.patch -export-zap-page-range.patch -uml-sigusr1-2.4-vanilla.patch -remove-suid-2.4-rhel.patch -uml-exprt-clearuser.patch -fsprivate-2.4.patch -nfsd_iallocsem.patch -linux-2.4.24-jbd-handle-EIO.patch -ext3-sector_t-overflow-2.4.patch -nfs_export_kernel-getattr_on_lookup-2.4.patch diff --git a/lustre/kernel_patches/series/vanilla-2.4.29 b/lustre/kernel_patches/series/vanilla-2.4.29 deleted file mode 100644 index 88983ad..0000000 --- a/lustre/kernel_patches/series/vanilla-2.4.29 +++ /dev/null @@ -1,45 +0,0 @@ -configurable-x86-stack-2.4.20.patch -configurable-x86_64-2.4.21.patch -dev_read_only_2.4.20-rh.patch -exports_2.4.20-rh-hp.patch -lustre_version.patch -vfs_intent-2.4.29-vanilla.patch -invalidate_show-2.4.29.patch -export-truncate.patch -iod-stock-exports-2.4.22.patch -ext3-htree-2.4.29.patch -linux-2.4.29-xattr-0.8.54.patch -ext3-orphan_lock-2.4.22-rh.patch -ext3-noread-2.4.20.patch -ext3-delete_thread-2.4.29.patch -extN-wantedi.patch -ext3-san-2.4.20.patch -ext3-map_inode_page.patch -ext3-error-export.patch -iopen-2.4.20.patch -jbd-dont-account-blocks-twice.patch -jbd-commit-tricks.patch -ext3-no-write-super-chaos.patch -add_page_private.patch -nfs_export_kernel-2.4.29.patch -ext3-raw-lookup.patch -ext3-ea-in-inode-2.4.29.patch -listman-2.4.20.patch -ext3-trusted_ea-2.4.20.patch -ext3-xattr-ptr-arith-fix.patch -3.5G-address-space-2.4.22-vanilla.patch -procfs-ndynamic-2.4.patch -ext3-truncate-buffer-head.patch -inode-max-readahead-2.4.24.patch -ext3-extents-2.4.29.patch -ext3-extents-asyncdel-2.4.24.patch -ext3-nlinks-2.4.24.patch -ext3-ialloc-2.4.24.patch -export-show_task-2.4-vanilla.patch -export-zap-page-range.patch -remove-suid-2.4-rhel.patch -kallsyms-2.4.29.patch -fsprivate-2.4.patch -nfsd_iallocsem.patch -linux-2.4.24-jbd-handle-EIO.patch -ext3-sector_t-overflow-2.4.patch diff --git a/lustre/kernel_patches/series/vanilla-2.4.29-uml b/lustre/kernel_patches/series/vanilla-2.4.29-uml deleted file mode 100644 index 9740148..0000000 --- a/lustre/kernel_patches/series/vanilla-2.4.29-uml +++ /dev/null @@ -1,47 +0,0 @@ -uml-patch-2.4.29-1.patch -uml-2.4.20-do_mmap_pgoff-fix.patch -uml-export-end_iomem.patch -uml-exprt-clearuser.patch -configurable-x86-stack-2.4.20.patch -configurable-x86_64-2.4.21.patch -dev_read_only_2.4.20-rh.patch -exports_2.4.20-rh-hp.patch -lustre_version.patch -vfs_intent-2.4.29-vanilla.patch -invalidate_show-2.4.29.patch -export-truncate.patch -iod-stock-exports-2.4.22.patch -ext3-htree-2.4.29.patch -linux-2.4.29-xattr-0.8.54.patch -ext3-orphan_lock-2.4.22-rh.patch -ext3-noread-2.4.20.patch -ext3-delete_thread-2.4.29.patch -extN-wantedi.patch -ext3-san-2.4.20.patch -ext3-map_inode_page.patch -ext3-error-export.patch -iopen-2.4.20.patch -jbd-dont-account-blocks-twice.patch -jbd-commit-tricks.patch -ext3-no-write-super-chaos.patch -add_page_private.patch -nfs_export_kernel-2.4.29.patch -ext3-raw-lookup.patch -ext3-ea-in-inode-2.4.29.patch -listman-2.4.20.patch -ext3-trusted_ea-2.4.20.patch -ext3-xattr-ptr-arith-fix.patch -3.5G-address-space-2.4.22-vanilla.patch -procfs-ndynamic-2.4.patch -ext3-truncate-buffer-head.patch -inode-max-readahead-2.4.24.patch -ext3-extents-2.4.29.patch -ext3-extents-asyncdel-2.4.24.patch -ext3-nlinks-2.4.24.patch -export-show_task-2.4-vanilla.patch -export-zap-page-range.patch -remove-suid-2.4-rhel.patch -kallsyms-2.4.29.patch -fsprivate-2.4.patch -nfsd_iallocsem.patch -ext3-sector_t-overflow-2.4.patch diff --git a/lustre/kernel_patches/which_patch b/lustre/kernel_patches/which_patch index 8e21376..044d242 100644 --- a/lustre/kernel_patches/which_patch +++ b/lustre/kernel_patches/which_patch @@ -1,11 +1,9 @@ SERIES VERSION COMMENT SUPPORTED KERNELS: -rhel-2.4.21 RHEL3: 2.4.21-47.0.1.EL 2.6-suse SLES9 before SP1 already in SLES9 SP1 kernel 2.6-suse-newer SLES9: 2.6.5-7.282 extra patches for SLES9 after SP1 2.6-rhel4 RHEL4: 2.6.9-55.EL -2.6.12-vanilla kernel.org: 2.6.12.6 2.6-sles10 SLES10: 2.6.16.21-0.8 CLIENT SUPPORT FOR UNPATCHED KERNELS: -- 1.8.3.1